From 9326d0fae811f59c01e5d7e59e4d2c9280a68ff5 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 21 Aug 2024 11:56:47 +0200 Subject: [PATCH 001/157] v4.0.0 preparations --- .github/CODE_OF_CONDUCT.md | 128 ---- .github/CONTRIBUTING.md | 44 -- .github/FUNDING.yml | 1 - .github/ISSUE_TEMPLATE/bug_report.md | 37 - .github/ISSUE_TEMPLATE/plugin.md | 29 - .github/SECURITY.md | 40 -- .gitignore | 23 - LICENSE | 674 ------------------ README.md | 110 --- commands/add.js | 92 --- commands/change.js | 134 ---- commands/claim.js | 107 --- commands/close.js | 85 --- commands/delete.js | 80 --- commands/help.js | 58 -- commands/remove.js | 78 -- commands/rename.js | 88 --- commands/reopen.js | 51 -- commands/stats.js | 103 --- commands/ticket.js | 70 -- commands/unclaim.js | 125 ---- config.json | 148 ---- core/api/api.js | 18 - core/api/api.json | 61 -- core/api/modules/actions.js | 7 - core/api/modules/events.js | 454 ------------ core/api/pluginlauncher.js | 43 -- core/checker.js | 551 -------------- core/dynamicdatabase/databases/main.js | 82 --- core/dynamicdatabase/databases/stats.js | 87 --- core/dynamicdatabase/storage.js | 23 - core/errorLogSystem.js | 160 ----- core/interactionHandlers/buttons/close.js | 87 --- core/interactionHandlers/buttons/firstmsg.js | 119 ---- .../interactionHandlers/buttons/verifyBars.js | 71 -- core/interactionHandlers/embeds/commands.js | 144 ---- .../handlers/accepted/claiming.js | 60 -- .../handlers/accepted/closing.js | 76 -- .../handlers/accepted/closingReason.js | 103 --- .../handlers/accepted/deleting.js | 107 --- .../handlers/accepted/reopening.js | 41 -- core/interactionHandlers/handlers/firstmsg.js | 20 - core/interactionHandlers/handlers/handlers.js | 11 - .../handlers/verifyBars.js | 100 --- core/languageManager.js | 39 - core/logo.txt | 7 - core/reactionRoles.js | 104 --- core/slashSystem/autoSlashUpdate.js | 87 --- core/slashSystem/slashDisable.js | 23 - core/slashSystem/slashEnable.js | 305 -------- core/startscreen.js | 79 -- core/statsManager.js | 383 ---------- core/ticketActions/ticketAutoclose.js | 65 -- core/ticketActions/ticketCloser.js | 253 ------- core/ticketActions/ticketOpener.js | 265 ------- core/ticketActions/ticketReopener.js | 77 -- .../communication/compileJsonV1.js | 123 ---- .../communication/compileJsonV2.js | 395 ---------- core/transcriptSystem/communication/index.js | 29 - .../communication/mentions.js | 57 -- core/transcriptSystem/embeds.js | 80 --- core/transcriptSystem/info.json | 3 - core/transcriptSystem/manager.js | 221 ------ core/transcriptSystem/oldTranscript.js | 60 -- core/transcriptSystem/tsdb.js | 71 -- core/utils/configParser.js | 188 ----- core/utils/getButton.js | 80 --- core/utils/getDropdown.js | 70 -- core/utils/getEmbed.js | 138 ---- core/utils/hiddendata.js | 49 -- core/utils/liveStatus.js | 137 ---- core/utils/permisssionChecker.js | 176 ----- index.js | 449 ------------ language/arabic.json | 135 ---- language/bulgarian.json | 135 ---- language/custom.json | 135 ---- language/czech.json | 135 ---- language/danish.json | 135 ---- language/dutch.json | 135 ---- language/english.json | 135 ---- language/estonian.json | 135 ---- language/finnish.json | 135 ---- language/french.json | 135 ---- language/german.json | 135 ---- language/greek.json | 135 ---- language/hungarian.json | 135 ---- language/indonesian.json | 135 ---- language/italian.json | 135 ---- language/japanese.json | 135 ---- language/korean.json | 135 ---- language/kurdish.json | 135 ---- language/latvian.json | 135 ---- language/norwegian.json | 135 ---- language/persian.json | 135 ---- language/polish.json | 135 ---- language/portuguese.json | 135 ---- language/romanian.json | 135 ---- language/russian.json | 135 ---- language/simplifiedchinese.json | 135 ---- language/slashcmds/slash.json | 215 ------ language/slovenian.json | 135 ---- language/spanish.json | 135 ---- language/swedish.json | 135 ---- language/thai.json | 135 ---- language/traditionalchinese.json | 135 ---- language/turkish.json | 135 ---- language/ukrainian.json | 135 ---- language/vietnamese.json | 135 ---- package.json | 59 +- plugins/example.plugin.js | 19 - storage/hello.txt | 3 - transcriptconfig.json | 36 - 112 files changed, 32 insertions(+), 13633 deletions(-) delete mode 100644 .github/CODE_OF_CONDUCT.md delete mode 100644 .github/CONTRIBUTING.md delete mode 100644 .github/FUNDING.yml delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/plugin.md delete mode 100644 .github/SECURITY.md delete mode 100644 .gitignore delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 commands/add.js delete mode 100644 commands/change.js delete mode 100644 commands/claim.js delete mode 100644 commands/close.js delete mode 100644 commands/delete.js delete mode 100644 commands/help.js delete mode 100644 commands/remove.js delete mode 100644 commands/rename.js delete mode 100644 commands/reopen.js delete mode 100644 commands/stats.js delete mode 100644 commands/ticket.js delete mode 100644 commands/unclaim.js delete mode 100644 config.json delete mode 100644 core/api/api.js delete mode 100644 core/api/api.json delete mode 100644 core/api/modules/actions.js delete mode 100644 core/api/modules/events.js delete mode 100644 core/api/pluginlauncher.js delete mode 100644 core/checker.js delete mode 100644 core/dynamicdatabase/databases/main.js delete mode 100644 core/dynamicdatabase/databases/stats.js delete mode 100644 core/dynamicdatabase/storage.js delete mode 100644 core/errorLogSystem.js delete mode 100644 core/interactionHandlers/buttons/close.js delete mode 100644 core/interactionHandlers/buttons/firstmsg.js delete mode 100644 core/interactionHandlers/buttons/verifyBars.js delete mode 100644 core/interactionHandlers/embeds/commands.js delete mode 100644 core/interactionHandlers/handlers/accepted/claiming.js delete mode 100644 core/interactionHandlers/handlers/accepted/closing.js delete mode 100644 core/interactionHandlers/handlers/accepted/closingReason.js delete mode 100644 core/interactionHandlers/handlers/accepted/deleting.js delete mode 100644 core/interactionHandlers/handlers/accepted/reopening.js delete mode 100644 core/interactionHandlers/handlers/firstmsg.js delete mode 100644 core/interactionHandlers/handlers/handlers.js delete mode 100644 core/interactionHandlers/handlers/verifyBars.js delete mode 100644 core/languageManager.js delete mode 100644 core/logo.txt delete mode 100644 core/reactionRoles.js delete mode 100644 core/slashSystem/autoSlashUpdate.js delete mode 100644 core/slashSystem/slashDisable.js delete mode 100644 core/slashSystem/slashEnable.js delete mode 100644 core/startscreen.js delete mode 100644 core/statsManager.js delete mode 100644 core/ticketActions/ticketAutoclose.js delete mode 100755 core/ticketActions/ticketCloser.js delete mode 100755 core/ticketActions/ticketOpener.js delete mode 100755 core/ticketActions/ticketReopener.js delete mode 100644 core/transcriptSystem/communication/compileJsonV1.js delete mode 100644 core/transcriptSystem/communication/compileJsonV2.js delete mode 100644 core/transcriptSystem/communication/index.js delete mode 100644 core/transcriptSystem/communication/mentions.js delete mode 100644 core/transcriptSystem/embeds.js delete mode 100644 core/transcriptSystem/info.json delete mode 100644 core/transcriptSystem/manager.js delete mode 100755 core/transcriptSystem/oldTranscript.js delete mode 100644 core/transcriptSystem/tsdb.js delete mode 100644 core/utils/configParser.js delete mode 100644 core/utils/getButton.js delete mode 100644 core/utils/getDropdown.js delete mode 100644 core/utils/getEmbed.js delete mode 100644 core/utils/hiddendata.js delete mode 100644 core/utils/liveStatus.js delete mode 100644 core/utils/permisssionChecker.js delete mode 100644 index.js delete mode 100644 language/arabic.json delete mode 100644 language/bulgarian.json delete mode 100644 language/custom.json delete mode 100644 language/czech.json delete mode 100644 language/danish.json delete mode 100644 language/dutch.json delete mode 100644 language/english.json delete mode 100644 language/estonian.json delete mode 100644 language/finnish.json delete mode 100644 language/french.json delete mode 100644 language/german.json delete mode 100644 language/greek.json delete mode 100644 language/hungarian.json delete mode 100644 language/indonesian.json delete mode 100644 language/italian.json delete mode 100644 language/japanese.json delete mode 100644 language/korean.json delete mode 100644 language/kurdish.json delete mode 100644 language/latvian.json delete mode 100644 language/norwegian.json delete mode 100644 language/persian.json delete mode 100644 language/polish.json delete mode 100644 language/portuguese.json delete mode 100644 language/romanian.json delete mode 100644 language/russian.json delete mode 100644 language/simplifiedchinese.json delete mode 100644 language/slashcmds/slash.json delete mode 100644 language/slovenian.json delete mode 100644 language/spanish.json delete mode 100644 language/swedish.json delete mode 100644 language/thai.json delete mode 100644 language/traditionalchinese.json delete mode 100644 language/turkish.json delete mode 100644 language/ukrainian.json delete mode 100644 language/vietnamese.json delete mode 100644 plugins/example.plugin.js delete mode 100644 storage/hello.txt delete mode 100644 transcriptconfig.json diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md deleted file mode 100644 index b6c95d8..0000000 --- a/.github/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,128 +0,0 @@ -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, religion, or sexual identity -and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the - overall community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or - advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email - address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -support@dj-dj.be. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series -of actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or -permanent ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within -the community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.0, available at -https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. - -Community Impact Guidelines were inspired by [Mozilla's code of conduct -enforcement ladder](https://github.com/mozilla/diversity). - -[homepage]: https://www.contributor-covenant.org - -For answers to common questions about this code of conduct, see the FAQ at -https://www.contributor-covenant.org/faq. Translations are available at -https://www.contributor-covenant.org/translations. diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index b5680df..0000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,44 +0,0 @@ -# Contributing -## Translation -### Step 1: checking -1. [Check if the language isn't already in open ticket!](/language/) -2. Check if the current translation is up-to-date! -3. Can you edit/write JSON? -4. [Have you read the documentation?](https://otdocs.dj-dj.be) - -If there is translation missing, you go to the next step! - -### Step 2: translating -**RULES:** -- Always upload or create a pull request to the [__`dev` branch!__](https://github.com/DJj123dj/open-ticket/tree/dev) -- Don't change anything else, except the translation you are adding! -- Translations are checked before uploading, so don't write things that aren't specified in the json file -- Always start translating from `english.json` or `custom.json`! Never from another language. - -If you translate, you need to change 2 files! The first one is required, the other 2 are optional & will be added by us if you don't do it! -1. add `yourlanguage.json` to the `/language/` directory -2. add your username to the `_CREDITS` part of `yourlanguage.json`! -3. add your discord username in the translator table in `README.md` - -### Step 3: waiting -Translations will always be added in the **next version** of Open Ticket! They will never be added to the `main` branch directly without anything else! This means that it can take some time before your translation is in the official version! - -## Writing plugins -We are going to create an official repository for plugins soon! -But don't worry! You can already write some plugins! - -**RULES:** -- Always specify the versions that the plugin is compatible with! -- If extra npm dependencies are needed, then they also need to be specified! -- If there are errors while you write a plugin/edit the code in some way. Then we can't help you with fixing the bug. We only fix bugs that are part of the original unedited version of Open Ticket! - -## Other versions of contributing -If you want to contribute in another way, feel free to join [our discord server](https://discord.dj-dj.be) & talk about how you are going to do it. We will always help you further! - -
-CONTRIBUTING GUIDELINES - Last updated: 31/5/2024
-© DJdj Development

-Website: https://www.dj-dj.be
-Discord: https://discord.dj-dj.be
-Email: support@dj-dj.be
-Documentation: https://otdocs.dj-dj.be \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 1032364..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: DJj123dj diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 86254e7..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -name: Bug report -about: Report bugs to help us improve open ticket! -title: "[BUG] your bug" -labels: bug -assignees: DJj123dj - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Device:** - - Device: [e.g. Macbook pro, raspberry pi, HP Probook] - - OS: [e.g. MacOS, Ubuntu, Windows,...] - - Node.js version: - - Open Ticket Version: - -**Files:** -Please include the `openticketdebug.txt` file in your report! -This is a file that we can see what happend! - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/plugin.md b/.github/ISSUE_TEMPLATE/plugin.md deleted file mode 100644 index feb708f..0000000 --- a/.github/ISSUE_TEMPLATE/plugin.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -name: Plugin -about: Show your plugin to the developers from open ticket! -title: "[PLUGIN] your plugin" -labels: plugin -assignees: DJj123dj - ---- - -**Plugin Name:** -What's the name of your plugin? - -**Description:** -Tell a little bit about what the plugin does! -Also tell how to use the plugin, like if there is additional setup needed! - -**NPM libraries:** -List all the libraries needed for this plugin to work! -*The default open ticket libraries are not required!* - -**Author:** -- github account [e.g. DJj123dj] -- discord account [e.g. Wumpus#1234] - -**Compatible versions:** -[e.g. from v2.2.1 until v3.0.1] - -**File:** -Please attach the plugin file to this issue! diff --git a/.github/SECURITY.md b/.github/SECURITY.md deleted file mode 100644 index a19e042..0000000 --- a/.github/SECURITY.md +++ /dev/null @@ -1,40 +0,0 @@ -# Security Policy - -## Supported Versions -Below, you can find a list with the status of every open ticket version. This list will change every update! - -- ✅ Supported **(bugs, errors, discord support, documentation, html transcripts)** -- 🟧 Deprecated / Partially Supported **(discord support, documentation, html transcripts)** -- ❌ Fully Deprecated / Not Supported **(sometimes documentation)** - -| Version | Supported | Until | -|-----------|-----------|-----------------------------| -| 3.5.8 | ✅ | | -| 3.5.7 | ✅ | September 2024 | -| 3.5.6 | 🟧 | September 2024 | -| < 3.5.6 | ❌ | | - -## Reporting a Vulnerability - -You can report Vulnerabilities, Errors & Bugs using one of the methods below: -- Create an issue on github -- Create a ticket in our [discord server](https://discord.dj-dj.be) -- Report the bug in DM on discord (djj123dj) -- Email [support@dj-dj.be](mailto:support@dj-dj.be) - -While reporting your problem, please be clear about what the problem is. -We would like to know the issue in as much detail as possible. -If possible, try to provide screenshots! -The `openticketdebug.txt` file would also be handy to upload!
-**Always specify the version of open ticket that you are working with and if you have modified it or not!** - -## Contributing -Visit [Contributing.md](/.github/CONTRIBUTING.md) for rules about translating & adding features! - -
-SECURITY POLICY - Last updated: 2/8/2024
-© DJdj Development

-Website: https://www.dj-dj.be
-Discord: https://discord.dj-dj.be
-Email: support@dj-dj.be
-Open Ticket website: https://openticket.dj-dj.be diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 9f58f5b..0000000 --- a/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -node_modules/ -package-lock.json -devconfig.json -devconfig1.json -devconfig2.json -devconfig3.json -devconfig4.json -devconfig5.json -.DS_Store -openticketdebug.txt -developerChangelog.md -storage/dynamicDB/ -storage/slashcmdEnabled.txt -storage/database.json -storage/tsdatabase.json -storage/stats.json -storage/.DS_Store -.vscode/ -livestatus.json -test.js -devtsconfig.json -plugins/* -!plugins/example.plugin.js \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index e72bfdd..0000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index 839ef24..0000000 --- a/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# Coming Soon: OPEN TICKET v4.0 Beta 🎉 -Open Ticket v4 beta will be released **in a few weeks!** So stay tuned! - -What is Open Ticket v4? Well, it's a complete rewrite of Open Ticket with the main focus being "plugins". -There will be massive stability & speed improvements! Hundreds of new features! And obviously very powerful plugins! -Plugins will be 100x better and advanced than the current system! -
- -Open Ticket - -[![discord](https://img.shields.io/badge/discord-join%20our%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-3.5.8-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v3.5.8) [![discord.js](https://img.shields.io/badge/discord.js-v14-CB3837.svg?style=flat-square&logo=npm)]() [![license](https://img.shields.io/badge/license-GPL%203.0-important.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/blob/main/LICENSE) [![stars](https://img.shields.io/github/stars/djj123dj/open-ticket?color=yellow&label=stars&logo=github&style=flat-square)](https://otdocs.dj-dj.be) - -### Open Ticket -Open Ticket is the most customisable discord ticket bot that you will ever find on Github! There are more than 150+ options to configure! This includes html transcripts, claiming, unlimited tickets, custom embeds & more! Did you know that even the transcripts are highly customisable? Don't wait and check it out! If you're having trouble setting the bot up, feel free to join our support server and we will help you further! - -Take a look at all the features and discover the possibilities! -### [📚 Read The Documentation!](https://otdocs.dj-dj.be/) -### [🎥 Or Watch The YouTube Tutorial!](https://www.youtube.com/watch?v=2jK9kAf6ASU) -[![Open Ticket Full-Setup Guide](https://img.youtube.com/vi/2jK9kAf6ASU/0.jpg)](https://www.youtube.com/watch?v=2jK9kAf6ASU) - -## 📌 Features -- **🎉 html transcripts** - Make use of the most customisable, beautiful and easy-to-use HTML Transcripts! -- **✅ ticket actions** - Close, Re-Open, Delete, Rename & Move all your tickets! -- **🇬🇧 translation** - Open Ticket has been translated in more than **33 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 everywhere** - Create an infinite amount of tickets & panels! -- **📝 custom plugins** - Create the most advanced plugins that you want or use premade ones by our community! -- **👥 user management** - Add & Remove users from all tickets! -- **📊 detailed stats** - Open Ticket has ticket, user & global staticstics available for everyone! -- **📦 commands** Open Ticket supports both Slash Commands & Text Commands! -- **📥 extra types** - The bot also supports Reaction Roles & Url Buttons, because why not ¯\\_(ツ)_/¯ -- **🎛️ dependencies** - We try to use as little external dependencies as needed! - -## 📸 Preview -Message with buttons -Message with dropdown -
-Ticket start message -Ticket start message - -## ❤️ Sponsors -A big thanks to all our sponsors! Without them, it wouldn't be possible to create this project! - -|Profile Picture|Profile Picture|Profile Picture| -|----|-|-| -|**[SpyEye](https://github.com/SpyEye2)**|**[DOSEV5](https://github.com/DOSEV5)**|**[Mods HD](https://github.com/mods-hd)**| - -*Do you also want to be in this list? Don't wait & sponsor us now! 😄* - -## 🛠️ Contributors -### Official Team -|Role |User (discord name)| -|-------------------|-------------------| -|🖥️ Lead Developer |djj123dj | -|👥 Support Team |sankedev | - -### Translators -|Language |Maintainer (discord name) |Status | -|---------------------|--------------------------|---------------| -|🇬🇧 English |djj123dj |🟢 Up To Date | -|🇳🇱 Dutch |djj123dj |🟢 Up To Date | -|🇫🇷 French |sankedev & tostam |🟢 Up To Date | -|🇷🇴 Romanian |sankedev |🟢 Up To Date | -|🇪🇸 Spanish |redactado & josuens |🟢 Up To Date | -|🇩🇪 German |david.3 |🟢 Up To Date | -|🇮🇹 Italian |maurizio26 |🟢 Up To Date | -|🇨🇿 Czech |spyeye_ |🟢 Up To Date | -|🇦🇪 Arabic |deqressing |🟢 Up To Date | -|🇩🇰 Danish |.the_gamer |🟢 Up To Date | -|🇵🇹 Portuguese |quiradon |🟢 Up To Date | -|🇷🇺 Russian |apexo & ander |🟢 Up To Date | -|🇺🇦 Ukrainian |ander |🟢 Up To Date | -|🇹🇷 Turkish |0x15d3 |🟢 Up To Date | -|🇵🇱 Polish |mkevas |🟢 Up To Date | -|🇸🇮 Slovenian |n1kkec |🔴 Outdated | -|🇹🇭 Thai |modshd |🟢 Up To Date | -|🇳🇴 Norwegian |noonenook |🟢 Up To Date | -|🇬🇷 Greek |stefanos__. |🔴 Outdated | -|🇮🇩 Indonesian |erxg |🟢 Up To Date | -|❓ Kurdish |raze.hama |🟢 Up To Date | -|🇭🇺 Hungarian |kornel0706 |🟢 Up To Date | -|❓ Persian |sasanwm |🟢 Up To Date | -|🇱🇻 Latvian |ronalds1398 |🟢 Up To Date | -|🇪🇪 Estonian |iamnotmega |🟢 Up To Date | -|🇯🇵 Japanese |iamnotmega |🟢 Up To Date | -|🇰🇷 Korean |iamnotmega |🟢 Up To Date | -|🇨🇳 Simplified Chinese |iamnotmega |🟢 Up To Date | -|🇨🇳 Traditional Chinese|iamnotmega |🟢 Up To Date | -|🇫🇮 Finnish |iamnotmega |🟢 Up To Date | -|🇸🇪 Swedish |iamnotmega |🟢 Up To Date | -|🇻🇳 Vietnamese |iamnotmega |🟢 Up To Date | - -## ⭐️ Star History -Please help us grow by giving a star! It would help us a lot! - - - - - - Star History Chart - - - -## 📎 Links -current version: _v3.5.8_ -
Changelog: [click here](https://otgithub.dj-dj.be/releases) -
Documentation: [click here](https://otdocs.dj-dj.be/) - -© 2024 - DJdj Development | [website](https://www.dj-dj.be) | [discord](https://discord.dj-dj.be) | [terms of service](https://www.dj-dj.be/terms#terms) | [privacy policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file diff --git a/commands/add.js b/commands/add.js deleted file mode 100644 index 0929c9c..0000000 --- a/commands/add.js +++ /dev/null @@ -1,92 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded add.js") - - if (!DISABLE.commands.text.add) client.on("messageCreate",msg => { - if (!msg.content.startsWith(config.prefix+"add")) return - var user = msg.mentions.users.first() - if (!user) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"add `")]}) - - if (!msg.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(msg.channel.id) - if (hiddendata.length < 1) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(msg.author.id,msg.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(msg.author) - return - } - - /**@type {discord.PermissionOverwriteManager} */ - const overwrites = msg.channel.permissionOverwrites - overwrites.create(user.id,{ - ViewChannel:true, - AddReactions:true, - AttachFiles:true, - EmbedLinks:true, - SendMessages:true, - ReadMessageHistory:true - },{reason:"Added user to ticket."}) - msg.channel.send({embeds:[bot.embeds.commands.addEmbed(user,msg.author)]}) - - var loguser = msg.mentions.users.first() - log("command","someone used the 'add' command",[{key:"user",value:msg.author.username}]) - log("system","user added to ticket",[{key:"user",value:msg.author.username},{key:"ticket",value:msg.channel.name},{key:"added_user",value:loguser.username}]) - - const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - APIEvents.onTicketAdd(msg.author,loguser,msg.channel,msg.guild,new Date(),{status:"open",name:msg.channel.name,ticketOptions:ticketData}) - - APIEvents.onCommand("add",permsChecker.ticket(msg.author.id,msg.guild.id,ticketId),msg.author,msg.channel,msg.guild,new Date()) - }) - - if (!DISABLE.commands.slash.add) client.on("interactionCreate",async (interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "add") return - const user = interaction.options.getUser("user") - - if (!interaction.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(interaction.user) - return - } - - await interaction.deferReply() - - /**@type {discord.PermissionOverwriteManager} */ - const overwrites = interaction.channel.permissionOverwrites - overwrites.create(user.id,{ - ViewChannel:true, - AddReactions:true, - AttachFiles:true, - EmbedLinks:true, - SendMessages:true, - ReadMessageHistory:true - },{reason:"Added user to ticket."}) - interaction.editReply({embeds:[bot.embeds.commands.addEmbed(user,interaction.user)]}) - - var loguser = user - log("command","someone used the 'add' command",[{key:"user",value:interaction.user.username}]) - log("system","user added to ticket",[{key:"user",value:interaction.user.username},{key:"ticket",value:interaction.channel.name},{key:"added_user",value:loguser.username}]) - - const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - APIEvents.onTicketAdd(interaction.user,loguser,interaction.channel,interaction.guild,new Date(),{status:"open",name:interaction.channel.name,ticketOptions:ticketData}) - APIEvents.onCommand("add",permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId),interaction.user,interaction.channel,interaction.guild,new Date()) - - }) -} \ No newline at end of file diff --git a/commands/change.js b/commands/change.js deleted file mode 100644 index 36fedbf..0000000 --- a/commands/change.js +++ /dev/null @@ -1,134 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded change.js") - - if (!DISABLE.commands.text.change) client.on("messageCreate", async msg => { - if (!msg.content.startsWith(config.prefix+"change")) return - if (!msg.channel.isTextBased()) return - - if (!msg.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(msg.channel.id) - if (hiddendata.length < 1) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(msg.author.id,msg.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(msg.author) - return - } - - const list = [] - config.options.forEach((o) => { - if (o.type == "ticket") list.push(o.id) - }) - - var newtype = msg.content.split(config.prefix+"change")[1].substring(1) - if (!newtype) return msg.channel.send({embeds:[bot.errorLog.invalidIdChooseFromList(list,l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"change `")]}) - - const newTicket = require("../core/utils/configParser").getTicketById(newtype,true) - if (!newTicket) return msg.channel.send({embeds:[bot.errorLog.invalidIdChooseFromList(list,l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"change `")]}) - - /**@type {discord.PermissionOverwriteManager} */ - const prePermsManager = msg.channel.permissionOverwrites - const prePerms = prePermsManager.cache - - /**@type {String} */ - var chName = msg.channel.name - const splitted = chName.split("-") - const prefix = splitted.shift() - const name = (splitted.length > 0) ? splitted.join("-") : prefix - - if (newTicket.category){ - const parent = await msg.guild.channels.fetch(newTicket.category,{cache:true}) - if (parent && parent.type == discord.ChannelType.GuildCategory) msg.channel.setParent(parent) - } - - prePermsManager.set(prePerms) - msg.channel.setName(newTicket.channelprefix+name).catch(() => { - msg.channel.send({embeds:[bot.errorLog.failedRenameChannel]}) - }) - - hiddendata.find((value,index) => { - if (value.key == "type"){ - hiddendata[index] = {key:"type",value:newtype} - } - }) - - msg.channel.send({embeds:[bot.embeds.commands.changeEmbed(msg.author,newtype)]}) - - log("command","someone used the 'change' command",[{key:"user",value:msg.author.username}]) - log("system","ticket type changed",[{key:"user",value:msg.author.username},{key:"ticket",value:name},{key:"newtype",value:newtype}]) - APIEvents.onCommand("change",permsChecker.ticket(msg.author.id,msg.guild.id,ticketId),msg.author,msg.channel,msg.guild,new Date()) - }) - - if (!DISABLE.commands.slash.change) client.on("interactionCreate",async (interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "change") return - if (!interaction.channel.isTextBased()) return - - if (!interaction.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(interaction.user) - return - } - - await interaction.deferReply() - - const list = [] - config.options.forEach((o) => { - if (o.type == "ticket") list.push(o.id) - }) - - var newtype = interaction.options.getString("type",true) - const newTicket = require("../core/utils/configParser").getTicketById(newtype,true) - - if (!newTicket) return interaction.editReply({embeds:[bot.errorLog.invalidIdChooseFromList(list,l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"change `")]}) - - /**@type {discord.PermissionOverwriteManager} */ - const prePermsManager = interaction.channel.permissionOverwrites - const prePerms = prePermsManager.cache - - /**@type {String} */ - var chName = interaction.channel.name - const splitted = chName.split("-") - const prefix = splitted.shift() - const name = (splitted.length > 0) ? splitted.join("-") : prefix - - if (newTicket.category){ - const parent = await interaction.guild.channels.fetch(newTicket.category,{cache:true}) - if (parent && parent.type == discord.ChannelType.GuildCategory) interaction.channel.setParent(parent) - } - - prePermsManager.set(prePerms) - interaction.channel.setName(newTicket.channelprefix+name).catch(() => { - interaction.channel.send({embeds:[bot.errorLog.failedRenameChannel]}) - }) - - hiddendata.find((value,index) => { - if (value.key == "type"){ - hiddendata[index] = {key:"type",value:newtype} - } - }) - - interaction.editReply({embeds:[bot.embeds.commands.changeEmbed(interaction.user,newtype)]}) - - log("command","someone used the 'change' command",[{key:"user",value:interaction.user.username}]) - log("system","ticket type changed",[{key:"user",value:interaction.user.username},{key:"ticket",value:name},{key:"newtype",value:newtype}]) - APIEvents.onCommand("change",permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId),interaction.user,interaction.channel,interaction.guild,new Date()) - }) -} \ No newline at end of file diff --git a/commands/claim.js b/commands/claim.js deleted file mode 100644 index 72fad2a..0000000 --- a/commands/claim.js +++ /dev/null @@ -1,107 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") -const embed = discord.EmbedBuilder -const storage = bot.storage - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded claim.js") - - if (!DISABLE.commands.text.claim) client.on("messageCreate", async msg => { - if (!msg.content.startsWith(config.prefix+"claim")) return - var user = msg.mentions.users.first() - - const claimingUser = user ? user : msg.author - - if (!msg.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(msg.channel.id) - if (hiddendata.length < 1) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(msg.author.id,msg.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(msg.author) - return - } - - hiddendata.push({key:"claimedby",value:claimingUser.id}) - bot.hiddenData.writeHiddenData(msg.channel.id,hiddendata) - storage.set("claimData",msg.channel.id,claimingUser.id) - - await msg.channel.messages.fetchPinned().then(msglist => { - var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - - const newEmbed = new embed(firstmsg.embeds[0].data) - .setFooter({text:"claimed by: "+msg.author.username,iconURL:msg.author.displayAvatarURL()}) - - if (firstmsg.components[0].components[1] && firstmsg.components[0].components[1].disabled){ - firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabledNoClaim],embeds:[newEmbed]}) - }else{ - firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowNormalNoClaim],embeds:[newEmbed]}) - } - }) - - msg.channel.send({embeds:[bot.embeds.commands.claimEmbed(claimingUser,msg.author)]}) - - log("command","someone used the 'claim' command",[{key:"user",value:msg.author.username}]) - log("system","user claimed to ticket",[{key:"user",value:msg.author.username},{key:"ticket",value:msg.channel.name},{key:"claimed_user",value:claimingUser.username}]) - - const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - APIEvents.onTicketClaim(msg.author,loguser,msg.channel,msg.guild,new Date(),{status:"open",name:msg.channel.name,ticketOptions:ticketData}) - APIEvents.onCommand("claim",permsChecker.ticket(msg.author.id,msg.guild.id,ticketId),msg.author,msg.channel,msg.guild,new Date()) - }) - - if (!DISABLE.commands.slash.claim) client.on("interactionCreate",async (interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "claim") return - const user = interaction.options.getUser("user",false) ? interaction.options.getUser("user",true) : interaction.user - - if (!interaction.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(interaction.user) - return interaction.reply({content:":x: "+l.errors.noPermsTitle,ephemeral:true}) - } - - await interaction.deferReply() - - hiddendata.push({key:"claimedby",value:user.id}) - bot.hiddenData.writeHiddenData(interaction.channel.id,hiddendata) - storage.set("claimData",interaction.channel.id,user.id) - - await interaction.channel.messages.fetchPinned().then(msglist => { - var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - - const newEmbed = new embed(firstmsg.embeds[0].data) - .setFooter({text:"claimed by: "+user.username,iconURL:user.displayAvatarURL()}) - - if (firstmsg.components[0].components[1] && firstmsg.components[0].components[1].disabled){ - firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabledNoClaim],embeds:[newEmbed]}) - }else{ - firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowNormalNoClaim],embeds:[newEmbed]}) - } - }) - - interaction.editReply({embeds:[bot.embeds.commands.claimEmbed(user,interaction.user)]}) - - log("command","someone used the 'claim' command",[{key:"user",value:interaction.user.username}]) - log("system","user claimed to ticket",[{key:"user",value:interaction.user.username},{key:"ticket",value:interaction.channel.name},{key:"claimed_user",value:user.username}]) - - const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - APIEvents.onTicketClaim(interaction.user,user,interaction.channel,interaction.guild,new Date(),{status:"open",name:interaction.channel.name,ticketOptions:ticketData}) - APIEvents.onCommand("claim",permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId),interaction.user,interaction.channel,interaction.guild,new Date()) - }) -} \ No newline at end of file diff --git a/commands/close.js b/commands/close.js deleted file mode 100644 index f24e802..0000000 --- a/commands/close.js +++ /dev/null @@ -1,85 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded close.js") - - if (!DISABLE.commands.text.close) client.on("messageCreate",msg => { - if (!msg.content.startsWith(config.prefix+"close")) return - - const args = msg.content.substring((config.prefix+"close").length).split(" ") - args.shift() - /**@type {String|false} */ - var tempreason = args.join(" ") - if (!tempreason || tempreason == " " || tempreason == " "){ - tempreason = false - } - const reason = tempreason - - const hiddendata = bot.hiddenData.readHiddenData(msg.channel.id) - if (hiddendata.length < 1) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (hiddendata.find(h => h.key == "pendingdelete")) return msg.channel.send({embeds:[bot.errorLog.warning("Warning!","You can't close a ticket while it's being deleted!")]}) - - const descriptionReason = reason ? "**"+l.messages.reason+":** "+reason : false - msg.channel.send({embeds:[bot.embeds.commands.closeEmbed(msg.author,descriptionReason)],components:[bot.buttons.close.closeCommandRow]}) - - var name = msg.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - require("../core/ticketActions/ticketCloser").closeManager(msg.member,msg.channel,prefix,"close",reason,true) - - log("command","someone used the 'close' command",[{key:"user",value:msg.author.username}]) - APIEvents.onCommand("close",true,msg.author,msg.channel,msg.guild,new Date()) - - }) - - if (!DISABLE.commands.slash.close) client.on("interactionCreate",async(interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "close") return - - //interaction.deferReply() - - const reason = interaction.options.getString("reason") ? interaction.options.getString("reason") : false - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (hiddendata.find(h => h.key == "pendingdelete")) return interaction.reply({embeds:[bot.errorLog.warning("Warning!","You can't close a ticket while it's being deleted!")]}) - - await interaction.deferReply() - - const descriptionReason = reason ? "**"+l.messages.reason+":** "+reason : false - interaction.editReply({embeds:[bot.embeds.commands.closeEmbed(interaction.user,descriptionReason)],components:[bot.buttons.close.closeCommandRow]}) - - var name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - require("../core/ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"close",false,true) - - log("command","someone used the 'close' command",[{key:"user",value:interaction.user.username}]) - APIEvents.onCommand("close",true,interaction.user,interaction.channel,interaction.guild,new Date()) - }) -} \ No newline at end of file diff --git a/commands/delete.js b/commands/delete.js deleted file mode 100644 index 84ade6b..0000000 --- a/commands/delete.js +++ /dev/null @@ -1,80 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded delete.js") - - if (!DISABLE.commands.text.delete) client.on("messageCreate",msg => { - if (!msg.content.startsWith(config.prefix+"delete")) return - - if (!msg.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(msg.channel.id) - if (hiddendata.length < 1) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(msg.author.id,msg.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(msg.author) - return - } - - msg.channel.send({embeds:[bot.embeds.commands.deleteEmbed(msg.author)]}) - - var name = msg.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - require("../core/ticketActions/ticketCloser").closeManager(msg.member,msg.channel,prefix,"delete",false,true) - - log("command","someone used the 'delete' command",[{key:"user",value:msg.author.username}]) - APIEvents.onCommand("delete",permsChecker.ticket(msg.author.id,msg.guild.id,ticketId),msg.author,msg.channel,msg.guild,new Date()) - - }) - - if (!DISABLE.commands.slash.delete) client.on("interactionCreate",async (interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "delete") return - - if (!interaction.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(interaction.user) - return interaction.reply({embeds:[bot.errorLog.noPermsDelete(interaction.user)]}) - } - - await interaction.deferReply() - - interaction.editReply({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]}) - - var name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - require("../core/ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"delete",false,true) - - log("command","someone used the 'delete' command",[{key:"user",value:interaction.user.username}]) - APIEvents.onCommand("delete",permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId),interaction.user,interaction.channel,interaction.guild,new Date()) - }) -} \ No newline at end of file diff --git a/commands/help.js b/commands/help.js deleted file mode 100644 index 45c7c86..0000000 --- a/commands/help.js +++ /dev/null @@ -1,58 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded help.js") - - const msgName = config.system.showSlashcmdsInHelp ? "message" : "msg" - const prefix = config.system.showSlashcmdsInHelp ? "/" : config.prefix - - const helpEmbed = new discord.EmbedBuilder() - .setColor(config.color) - .setTitle("❔ "+l.helpMenu.title) - - const header = l.helpMenu.header2 - helpEmbed.setDescription(header+"`"+prefix+msgName+" ` ➜ _"+l.helpMenu.msgCmd+"_\n\n`"+prefix+"rename ` ➜ _"+l.helpMenu.renameCmd+"_\n`"+prefix+"close [reason]` ➜ _"+l.helpMenu.closeCmd+"_\n`"+prefix+"delete` ➜ _"+l.helpMenu.deleteCmd+"_\n`"+prefix+"reopen` ➜ _"+l.helpMenu.reopenCmd+"_\n\n`"+prefix+"add ` ➜ _"+l.helpMenu.addCmd+"_\n`"+prefix+"remove ` ➜ _"+l.helpMenu.removeCmd+"_\n\n`"+prefix+"change ` ➜ _"+l.helpMenu.changeCmd+"_\n`"+prefix+"claim [user]` ➜ _"+l.helpMenu.claimCmd+"_\n`"+prefix+"unclaim` ➜ _"+l.helpMenu.unclaimCmd+"_") - helpEmbed.addFields([ - {name:"Autoclose",value:l.helpMenu.autocloseCmd+"\n`"+prefix+"autoclose enable `\n`"+prefix+"autoclose disable`"}, - {name:"Stats",value:"Get statistics from the bot"+"\n`"+prefix+"stats global`\n`"+prefix+"stats ticket`\n`"+prefix+"stats user [user]`"} - ]) - - var otherprefix = prefix.endsWith(" ") ? prefix.substring(0,prefix.length-1) : prefix - - if (!DISABLE.commands.text.help) client.on("messageCreate",msg => { - if (!msg.content.startsWith(config.prefix)) return - var args = msg.content.split(config.prefix) - - if (msg.content == config.prefix || msg.content == config.prefix+" " || msg.content == otherprefix){ - msg.channel.send({embeds:[helpEmbed]}) - log("command","someone used the 'help' command",[{key:"user",value:msg.author.username}]) - APIEvents.onCommand("help",true,msg.author,msg.channel,msg.guild,new Date()) - return - } - - if (args[1]){ - if (!args[1].startsWith("close") && !args[1].startsWith("delete") && !args[1].startsWith("remove") && !args[1].startsWith("add") && !args[1].startsWith("msg") && !args[1].startsWith("remove") && !args[1].startsWith("rename") && !args[1].startsWith("reopen") && !args[1].startsWith("change") && !args[1].startsWith("claim") && !args[1].startsWith("unclaim") && !args[1].startsWith("stats")){ - msg.channel.send({embeds:[helpEmbed]}) - log("command","someone used the 'help' command",[{key:"user",value:msg.author.username}]) - APIEvents.onCommand("help",true,msg.author,msg.channel,msg.guild,new Date()) - } - } - }) - - if (!DISABLE.commands.slash.help) client.on("interactionCreate",(interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "help") return - - interaction.reply({embeds:[helpEmbed]}) - log("command","someone used the 'help' command",[{key:"user",value:interaction.user.username}]) - APIEvents.onCommand("help",true,interaction.user,interaction.channel,interaction.guild,new Date()) - }) -} \ No newline at end of file diff --git a/commands/remove.js b/commands/remove.js deleted file mode 100644 index 0a869c5..0000000 --- a/commands/remove.js +++ /dev/null @@ -1,78 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded remove.js") - - if (!DISABLE.commands.text.remove) client.on("messageCreate",msg => { - if (!msg.content.startsWith(config.prefix+"remove")) return - var user = msg.mentions.users.first() - if (!user) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"remove `")]}) - - if (!msg.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(msg.channel.id) - if (hiddendata.length < 1) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(msg.author.id,msg.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(msg.author) - return - } - - /**@type {discord.PermissionOverwriteManager} */ - const overwrites = msg.channel.permissionOverwrites - overwrites.delete(user.id,"Removed user from ticket.") - msg.channel.send({embeds:[bot.embeds.commands.removeEmbed(user,msg.author)]}) - - var loguser = msg.mentions.users.first() - - log("command","someone used the 'remove' command",[{key:"user",value:msg.author.username}]) - log("system","user removed from ticket",[{key:"user",value:msg.author.username},{key:"ticket",value:msg.channel.name},{key:"removed_user",value:loguser.username}]) - - const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - APIEvents.onTicketRemove(msg.author,loguser,msg.channel,msg.guild,new Date(),{status:"open",name:msg.channel.name,ticketOptions:ticketData}) - APIEvents.onCommand("remove",permsChecker.ticket(msg.author.id,msg.guild.id,ticketId),msg.author,msg.channel,msg.guild,new Date()) - }) - - if (!DISABLE.commands.slash.remove) client.on("interactionCreate",async (interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "remove") return - const user = interaction.options.getUser("user") - - if (!interaction.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(interaction.user) - return - } - - await interaction.deferReply() - - /**@type {discord.PermissionOverwriteManager} */ - const overwrites = interaction.channel.permissionOverwrites - overwrites.delete(user.id,"Removed user from ticket.") - interaction.editReply({embeds:[bot.embeds.commands.removeEmbed(user,interaction.user)]}) - - var loguser = user - - log("command","someone used the 'remove' command",[{key:"user",value:interaction.user.username}]) - log("system","user removed from ticket",[{key:"user",value:interaction.user.username},{key:"ticket",value:interaction.channel.name},{key:"removed_user",value:loguser.username}]) - - const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - APIEvents.onTicketRemove(interaction.user,loguser,interaction.channel,interaction.guild,new Date(),{status:"open",name:interaction.channel.name,ticketOptions:ticketData}) - APIEvents.onCommand("remove",permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId),interaction.user,interaction.channel,interaction.guild,new Date()) - }) -} \ No newline at end of file diff --git a/commands/rename.js b/commands/rename.js deleted file mode 100644 index e2a5111..0000000 --- a/commands/rename.js +++ /dev/null @@ -1,88 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded rename.js") - - if (!DISABLE.commands.text.rename) client.on("messageCreate",msg => { - if (!msg.content.startsWith(config.prefix+"rename")) return - - if (!msg.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(msg.channel.id) - if (hiddendata.length < 1) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(msg.author.id,msg.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(msg.author) - return - } - - var newname = msg.content.split(config.prefix+"rename")[1].substring(1) - - if (!newname) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"rename `")]}) - - var name = msg.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - if (!prefix) prefix = "noprefix-" - msg.channel.setName(prefix+newname) - msg.channel.send({embeds:[bot.embeds.commands.renameEmbed(msg.author,prefix+newname)]}) - - log("command","someone used the 'rename' command",[{key:"user",value:msg.author.username}]) - log("system","ticket renamed",[{key:"user",value:msg.author.username},{key:"ticket",value:name},{key:"newname",value:newname}]) - APIEvents.onCommand("rename",permsChecker.ticket(msg.author.id,msg.guild.id,ticketId),msg.author,msg.channel,msg.guild,new Date()) - }) - - if (!DISABLE.commands.slash.rename) client.on("interactionCreate",async (interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "rename") return - - if (!interaction.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(interaction.user) - return - } - - await interaction.deferReply() - - var newname = interaction.options.getString("name") - var name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - if (!prefix) prefix = "noprefix-" - - interaction.channel.setName(prefix+newname) - interaction.editReply({embeds:[bot.embeds.commands.renameEmbed(interaction.user,prefix+newname)]}) - - log("command","someone used the 'rename' command",[{key:"user",value:interaction.user.username}]) - log("system","ticket renamed",[{key:"user",value:interaction.user.username},{key:"ticket",value:name},{key:"newname",value:newname}]) - - APIEvents.onCommand("rename",permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId),interaction.user,interaction.channel,interaction.guild,new Date()) - }) -} \ No newline at end of file diff --git a/commands/reopen.js b/commands/reopen.js deleted file mode 100644 index e57a68c..0000000 --- a/commands/reopen.js +++ /dev/null @@ -1,51 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded reopen.js") - - if (!DISABLE.commands.text.reopen) client.on("messageCreate",msg => { - if (!msg.content.startsWith(config.prefix+"reopen")) return - - const hiddendata = bot.hiddenData.readHiddenData(msg.channel.id) - if (hiddendata.length < 1) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (hiddendata.find(h => h.key == "pendingdelete")) return msg.channel.send({embeds:[bot.errorLog.warning("Warning!","You can't re-open a ticket while it's being deleted!")]}) - - msg.channel.send({embeds:[bot.embeds.commands.reopenEmbed(msg.author)],components:[bot.buttons.close.openRowNormal]}) - - require("../core/ticketActions/ticketReopener").reopenTicket(msg.guild,msg.channel,msg.author,ticketId) - - log("command","someone used the 'reopen' command",[{key:"user",value:msg.author.username}]) - APIEvents.onCommand("reopen",true,msg.author,msg.channel,msg.guild,new Date()) - }) - - if (!DISABLE.commands.slash.reopen) client.on("interactionCreate",async (interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "reopen") return - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (hiddendata.find(h => h.key == "pendingdelete")) return interaction.reply({embeds:[bot.errorLog.warning("Warning!","You can't re-open a ticket while it's being deleted!")]}) - - await interaction.deferReply() - - await interaction.editReply({embeds:[bot.embeds.commands.reopenEmbed(interaction.user)],components:[bot.buttons.close.openRowNormal]}) - - require("../core/ticketActions/ticketReopener").reopenTicket(interaction.guild,interaction.channel,interaction.user,ticketId) - - log("command","someone used the 'reopen' command",[{key:"user",value:interaction.user.username}]) - APIEvents.onCommand("reopen",true,interaction.user,interaction.channel,interaction.guild,new Date()) - }) -} diff --git a/commands/stats.js b/commands/stats.js deleted file mode 100644 index e018e44..0000000 --- a/commands/stats.js +++ /dev/null @@ -1,103 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded stats.js") - - if (!DISABLE.commands.text.stats) client.on("messageCreate",async (msg) => { - if (!msg.content.startsWith(config.prefix+"stats global") && !msg.content.startsWith(config.prefix+"stats ticket") && !msg.content.startsWith(config.prefix+"stats user")) return - if (!msg.guild) return - - /**@type {"global"|"ticket"|"user"} */ - const mode = msg.content.split(config.prefix+"stats ")[1] - - if (mode == "global"){ - //send global stats - msg.channel.send({embeds:[await bot.statsManager.createGlobalStatsEmbed()]}) - - }else if (mode == "user"){ - //send user stats - const mention = msg.mentions.users.first() - if (mention){ - //get user from mention - if (!bot.statsManager.existStats("user","TICKETS_CREATED",mention.id)){ - msg.channel.send({embeds:[bot.errorLog.serverError(l.stats.errorUserNotFound)]}) - return - } - msg.channel.send({embeds:[await bot.statsManager.createUserStatsEmbed(msg.guild,mention,msg.channel.id)]}) - }else{ - //use author as user - if (!bot.statsManager.existStats("user","TICKETS_CREATED",msg.author.id)){ - msg.channel.send({embeds:[bot.errorLog.serverError(l.stats.errorUserNotFound)]}) - return - } - msg.channel.send({embeds:[await bot.statsManager.createUserStatsEmbed(msg.guild,msg.author,msg.channel.id)]}) - } - - }else if (mode == "ticket"){ - //send ticket stats - if (!bot.statsManager.existStats("ticket","STATUS",msg.channel.id)){ - msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - return - } - msg.channel.send({embeds:[await bot.statsManager.createTicketStatsEmbed(msg.guild,msg.channel.id)]}) - } - - log("command","someone used the 'stats' command",[{key:"user",value:msg.author.username},{key:"mode",value:mode}]) - APIEvents.onCommand("stats",true,msg.author,msg.channel,msg.guild,new Date()) - }) - - if (!DISABLE.commands.slash.stats) client.on("interactionCreate",async (interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "stats") return - if (!interaction.guild) return - - /**@type {"global"|"ticket"|"user"} */ - const mode = interaction.options.getSubcommand(true) - - await interaction.deferReply() - - if (mode == "global"){ - //send global stats - interaction.editReply({embeds:[await bot.statsManager.createGlobalStatsEmbed()]}) - - }else if (mode == "user"){ - //send user stats - const mention = interaction.options.getUser("user",false) - if (mention){ - //get user from mention - if (!bot.statsManager.existStats("user","TICKETS_CREATED",mention.id)){ - interaction.editReply({embeds:[bot.errorLog.serverError(l.stats.errorUserNotFound)]}) - return - } - interaction.editReply({embeds:[await bot.statsManager.createUserStatsEmbed(interaction.guild,mention,interaction.channel.id)]}) - }else{ - //use author as user - if (!bot.statsManager.existStats("user","TICKETS_CREATED",interaction.user.id)){ - interaction.editReply({embeds:[bot.errorLog.serverError(l.stats.errorUserNotFound)]}) - return - } - interaction.editReply({embeds:[await bot.statsManager.createUserStatsEmbed(interaction.guild,interaction.user,interaction.channel.id)]}) - } - - }else if (mode == "ticket"){ - //send ticket stats - if (!bot.statsManager.existStats("ticket","STATUS",interaction.channel.id)){ - interaction.editReply({embeds:[bot.errorLog.notInATicket]}) - return - } - interaction.editReply({embeds:[await bot.statsManager.createTicketStatsEmbed(interaction.guild,interaction.channel.id)]}) - } - - log("command","someone used the 'stats' command",[{key:"user",value:interaction.user.username},{key:"mode",value:mode}]) - APIEvents.onCommand("stats",true,interaction.user,interaction.channel,interaction.guild,new Date()) - }) -} \ No newline at end of file diff --git a/commands/ticket.js b/commands/ticket.js deleted file mode 100644 index 5e3eab0..0000000 --- a/commands/ticket.js +++ /dev/null @@ -1,70 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded ticket.js") - - /**@type {String[]} */ - var msgIds = [] - config.messages.forEach((msg) => { - msgIds.push(msg.id) - }) - - - if (!DISABLE.commands.text.msg) client.on("messageCreate", msg => { - if (msg.content.startsWith(config.prefix+"msg"||config.prefix+"message")){ - - if (!msg.guild) return - if (!permsChecker.global(msg.author.id,msg.guild.id)){ - permsChecker.sendUserNoPerms(msg.author) - return - } - - const id = msg.content.split(config.prefix+"msg")[1].substring(1) ? msg.content.split(config.prefix+"msg")[1].substring(1) : false - - if (!id) return msg.channel.send({embeds:[bot.errorLog.invalidIdChooseFromList(msgIds,l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"msg `")]}) - if (!msgIds.includes(id)) return msg.channel.send({embeds:[bot.errorLog.invalidIdChooseFromList(msgIds,l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"msg `")]}) - - - const {embed,componentRows} = require("../core/utils/getEmbed").createEmbed(id) - - msg.channel.send({embeds:[embed],components:componentRows}) - - log("command","someone used the 'message' command",[{key:"user",value:msg.author.username},{key:"id",value:id}]) - APIEvents.onCommand("message",permsChecker.global(msg.author.id,msg.guild.id),msg.author,msg.channel,msg.guild,new Date()) - } - }) - - if (!DISABLE.commands.slash.msg) client.on("interactionCreate", (interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "message") return - - if (!interaction.guild) return - if (!permsChecker.global(interaction.user.id,interaction.guild.id)){ - permsChecker.sendUserNoPerms(interaction.user) - return - } - - const id = interaction.options.getString("id") - - if (!msgIds.includes(id)) return interaction.reply({embeds:[bot.errorLog.invalidIdChooseFromList(msgIds)]}) - - const {embed,componentRows} = require("../core/utils/getEmbed").createEmbed(id) - - interaction.reply({content:l.commands.ticketWarning}) - interaction.channel.send({embeds:[embed],components:componentRows}) - - log("command","someone used the 'message' command",[{key:"user",value:interaction.user.username},{key:"id",value:id}]) - - APIEvents.onCommand("message",permsChecker.global(interaction.user.id,interaction.guild.id),interaction.user,interaction.channel,interaction.guild,new Date()) - - }) -} \ No newline at end of file diff --git a/commands/unclaim.js b/commands/unclaim.js deleted file mode 100644 index c37e1a6..0000000 --- a/commands/unclaim.js +++ /dev/null @@ -1,125 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permsChecker = require("../core/utils/permisssionChecker") -const embed = discord.EmbedBuilder -const storage = bot.storage - -const APIEvents = require("../core/api/modules/events") -const DISABLE = require("../core/api/api.json").disable - -module.exports = () => { - bot.errorLog.log("debug","COMMANDS: loaded unclaim.js") - - if (!DISABLE.commands.text.unclaim) client.on("messageCreate",msg => { - if (!msg.content.startsWith(config.prefix+"unclaim")) return - - if (!msg.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(msg.channel.id) - if (hiddendata.length < 1) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(msg.author.id,msg.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(msg.author) - return - } - - const unclaimuser = storage.get("claimData",msg.channel.id) - if (!unclaimuser || unclaimuser == "false") return msg.channel.send({embeds:[bot.errorLog.serverError("This ticket isn't claimed yet!")]}) - - hiddendata.push({key:"claimedby",value:"false"}) - bot.hiddenData.writeHiddenData(msg.channel.id,hiddendata) - storage.set("claimData",msg.channel.id,"false") - - msg.channel.messages.fetchPinned().then(msglist => { - /**@type {discord.Message} */ - var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - - const newEmbed = new embed(firstmsg.embeds[0].data) - - const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - if (ticketData && ticketData.autoclose.enable){ - const footerText = l.commands.autocloseTitle.replace("{0}",ticketData.autoclose.inactiveHours+"h") - newEmbed.setFooter({text:footerText}) - }else{ - newEmbed.setFooter(null) - } - - if (firstmsg.components[0].components[1] && firstmsg.components[0].components[1].disabled){ - firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabled],embeds:[newEmbed]}) - }else{ - firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowNormal],embeds:[newEmbed]}) - } - - msg.channel.send({embeds:[bot.embeds.commands.unclaimEmbed(msg.author)]}) - - log("command","someone used the 'unclaim' command",[{key:"user",value:msg.author.username}]) - log("system","user unclaimed from ticket",[{key:"user",value:msg.author.username},{key:"ticket",value:msg.channel.name},{key:"unclaimed_user",value:unclaimuser}]) - - - APIEvents.onTicketUnclaim(msg.author,msg.channel,msg.guild,new Date(),{status:"open",name:msg.channel.name,ticketOptions:ticketData}) - APIEvents.onCommand("unclaim",permsChecker.ticket(msg.author.id,msg.guild.id,ticketId),msg.author,msg.channel,msg.guild,new Date()) - }) - }) - - if (!DISABLE.commands.slash.unclaim) client.on("interactionCreate",async (interaction) => { - if (!interaction.isChatInputCommand()) return - if (interaction.commandName != "unclaim") return - - if (!interaction.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(interaction.user) - interaction.reply({content:":x: "+l.errors.noPermsTitle,ephemeral:true}) - return - } - - await interaction.deferReply() - - const unclaimuser = storage.get("claimData",interaction.channel.id) - if (!unclaimuser || unclaimuser == "false") return interaction.editReply({embeds:[bot.errorLog.serverError("This ticket isn't claimed yet!")]}) - - hiddendata.push({key:"claimedby",value:"false"}) - bot.hiddenData.writeHiddenData(interaction.channel.id,hiddendata) - storage.set("claimData",interaction.channel.id,"false") - - interaction.channel.messages.fetchPinned().then(msglist => { - /**@type {discord.Message} */ - var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) - - const newEmbed = new embed(firstmsg.embeds[0].data) - - const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - if (ticketData && ticketData.autoclose.enable){ - const footerText = l.commands.autocloseTitle.replace("{0}",ticketData.autoclose.inactiveHours+"h") - newEmbed.setFooter({text:footerText}) - }else{ - newEmbed.setFooter(null) - } - - if (firstmsg.components[0].components[1] && firstmsg.components[0].components[1].disabled){ - firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabled],embeds:[newEmbed]}) - }else{ - firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowNormal],embeds:[newEmbed]}) - } - - interaction.editReply({embeds:[bot.embeds.commands.unclaimEmbed(interaction.user)]}) - - log("command","someone used the 'unclaim' command",[{key:"user",value:interaction.user.username}]) - log("system","user unclaimed from ticket",[{key:"user",value:interaction.user.username},{key:"ticket",value:interaction.channel.name},{key:"unclaimed_user",value:unclaimuser}]) - - APIEvents.onTicketUnclaim(interaction.user,interaction.channel,interaction.guild,new Date(),{status:"open",name:interaction.channel.name,ticketOptions:ticketData}) - APIEvents.onCommand("unclaim",permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId),interaction.user,interaction.channel,interaction.guild,new Date()) - }) - }) -} \ No newline at end of file diff --git a/config.json b/config.json deleted file mode 100644 index ead5a4c..0000000 --- a/config.json +++ /dev/null @@ -1,148 +0,0 @@ -{ - "_DOCUMENTATION":"https://otdocs.dj-dj.be", - "_SUPPORT":"https://discord.dj-dj.be", - - "color":"#ffffff", - "serverId":"server id (for slash cmds)", - "token":{ - "value":"insert your bot token here", - "fromENV":false - }, - "adminRoles":["discord role id"], - "prefix":"!ticket ", - "languageFile":"english", - - "status":{ - "enabled":true, - "type":"PLAYING", - "text":"!ticket help" - }, - - "system":{ - "maxAmountOfTickets":3, - "dmMessages":false, - - "memberRole":"member role (leave empty if you have no member role)", - "closeMode":"adminonly OR normal (select one!)", - - "transcripts":"!!!! ALL SETTINGS FOR TRANSCRIPTS ARE LOCATED IN: transcriptconfig.json !!!!", - - "showSlashcmdsInHelp":false, - "answerInEphemeralOnOpen":true - }, - - "options":[ - { - "id":"example-ticket", - "name":"Question", - "description":"Create this ticket if you have a question.", - "icon":"🎫", - "label":"question", - "type":"ticket", - - "color":"gray", - "adminroles":["role id"], - "readonlyAdminroles":["role id"], - "channelprefix":"question-", - "category":"category id (or leave empty)", - "message":"You created a ticket!", - "enableDmOnOpen":true, - "ticketmessage":"The staff will help you soon!\n\n*Click on the button below to close the ticket!*", - - "thumbnail":{ - "enable":false, - "url":"https://www.example.com/catmemes/cat.png" - }, - "image":{ - "enable":false, - "url":"https://www.example.com/catmemes/cat.png" - }, - - "closedCategory":{ - "enable":false, - "id":"category id" - }, - - "autoclose":{ - "enable":false, - "inactiveHours":24 - }, - - "ping":{ - "@here":true, - "@everyone":false, - "custom":{ - "enable":false, - "roleId":"012345678910" - } - } - }, - { - "id":"example-website", - "name":"Website", - "description":"Go to our website.", - "icon":"✅", - "label":"click here", - "type":"website", - - "url":"https://www.dj-dj.be" - }, - { - "id":"example-role", - "name":"Update Ping", - "description":"Click here to get pinged for updates!", - "icon":"📢", - "label":"Update Ping", - "type":"role", - - "color":"red", - "roles":["discord role id"], - "mode":"add&remove|remove|add", - "enableDmOnOpen":true - } - ], - - "messages":[ - { - "id":"example-embed", - "name":"Choose Your Ticket", - "description":"You can click one of the buttons below!", - "dropdown":false, - - "enableFooter":false, - "footer":"Open Ticket v3.5.8 - I'm a footer!", - - "enableFooterImage":false, - "footerImage":"https://www.example.com/catmemes/cat.png", - - "enableThumbnail":false, - "thumbnail":"https://www.example.com/catmemes/cat.png", - - "enableImage":false, - "image":"https://www.example.com/catmemes/cat.png", - - "enableCustomColor":false, - "color":"#ffffff", - - "options":["example-ticket","example-website","example-role"], - - "other":{ - "enableTicketExplaination":true, - "enableMaxTicketsWarning":true, - - "customDropdownPlaceholder":{ - "enable":false, - "text":"Choose a ticket" - }, - "customCategoryText":{ - "enable":false, - "text":"choose a category:" - }, - "embedTitleURL":{ - "enable":false, - "url":"https://www.dj-dj.be/projects/open-ticket" - } - } - } - ] -} \ No newline at end of file diff --git a/core/api/api.js b/core/api/api.js deleted file mode 100644 index 888fb3e..0000000 --- a/core/api/api.js +++ /dev/null @@ -1,18 +0,0 @@ -//base -const bot = require("../../index") - -exports.client = bot.client -exports.config = bot.config -exports.utils = { - log:bot.errorLog.log, - storage:bot.storage -} - -//events -const events = require("./modules/events").events -exports.events = events - -//actions -const actions = require("./modules/actions").actions -//comming soon -//exports.actions = actions \ No newline at end of file diff --git a/core/api/api.json b/core/api/api.json deleted file mode 100644 index 96cd79d..0000000 --- a/core/api/api.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "version":"1.0.0", - "enableAPIdebug":false, - "enableAPIconsolelogs":false, - - "info":"If you turn these switches to true, then the feature will be turned OFF!", - "info2":"You can use this to disable some features you don't want!", - "disable":{ - "messages":{ - "DISCLAIMER":"the messages part doesn't work yet!", - "ticketCreated":false, - "ticketClosed":false, - "ticketDeleted":false, - "ticketReopened":false - }, - "transcripts":{ - "server":false, - "dm":false - }, - "commands":{ - "text":{ - "help":false, - "msg":false, - "close":false, - "delete":false, - "reopen":false, - "new":false, - "add":false, - "remove":false, - "rename":false, - "claim":false, - "unclaim":false, - "change":false, - "stats":false - }, - "slash":{ - "help":false, - "msg":false, - "close":false, - "delete":false, - "reopen":false, - "new":false, - "add":false, - "remove":false, - "rename":false, - "claim":false, - "unclaim":false, - "change":false, - "stats":false - } - }, - "checkerjs":{ - "token":false, - "all":false - }, - "debug":{ - "all":false, - "debuglogs":false - } - } -} \ No newline at end of file diff --git a/core/api/modules/actions.js b/core/api/modules/actions.js deleted file mode 100644 index 55fc01f..0000000 --- a/core/api/modules/actions.js +++ /dev/null @@ -1,7 +0,0 @@ -//ACTIONS: - - -//EXPORT ACTIONS: -exports.actions = { - -} \ No newline at end of file diff --git a/core/api/modules/events.js b/core/api/modules/events.js deleted file mode 100644 index 7342b0a..0000000 --- a/core/api/modules/events.js +++ /dev/null @@ -1,454 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language - -const configParser = require("../../utils/configParser") - - -//EVENT API: -const ticketOpenListeners = [] -const ticketCloseListeners = [] -const ticketDeleteListeners = [] -const ticketReopenListeners = [] - -const ticketAddListeners = [] -const ticketRemoveListeners = [] - -const ticketClaimListeners = [] -const ticketUnclaimListeners = [] -const ticketChangeListeners = [] - - -const transcriptCreationListeners = [] -const commandListeners = [] -const reactionRoleListeners = [] -const errorListeners = [] - -/** - * - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:Object|false}} ticketdata - */ -exports.onTicketOpen = (user,channel,guild,date,ticketdata) => { - //system - bot.errorLog.log("api","new ticket created",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) - - ticketOpenListeners.forEach((func) => { - try { - func(user,channel,guild,date,ticketdata) - }catch{} - }) - -} - -/** - * - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - * @param {String} reason - */ -exports.onTicketClose = (user,channel,guild,date,ticketdata,reason) => { - //system - bot.errorLog.log("api","ticket closed",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)},{key:"reason",value:reason}]) - - ticketCloseListeners.forEach((func) => { - try { - func(user,channel,guild,date,ticketdata,reason) - }catch{} - }) - -} - -/** - * - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - */ -exports.onTicketDelete = (user,channel,guild,date,ticketdata) => { - //system - bot.errorLog.log("api","ticket deleted",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) - - ticketDeleteListeners.forEach((func) => { - try { - func(user,channel,guild,date,ticketdata) - }catch{} - }) - -} - -/** - * - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - */ -exports.onTicketReopen = (user,channel,guild,date,ticketdata) => { - //system - bot.errorLog.log("api","ticket reopened",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) - - ticketReopenListeners.forEach((func) => { - try { - func(user,channel,guild,date,ticketdata) - }catch{} - }) - -} - -/** - * - * @param {discord.User} user - * @param {discord.User} editeduser - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - */ -exports.onTicketAdd = (user,editeduser,channel,guild,date,ticketdata) => { - //system - bot.errorLog.log("api","user added to ticket",[{key:"userid",value:user.id},{key:"editeduser",value:editeduser.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) - - ticketAddListeners.forEach((func) => { - try { - func(user,editeduser,channel,guild,date,ticketdata) - }catch{} - }) - -} - -/** - * - * @param {discord.User} user - * @param {discord.User} editeduser - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - */ -exports.onTicketRemove = (user,editeduser,channel,guild,date,ticketdata) => { - //system - bot.errorLog.log("api","user removed from ticket",[{key:"userid",value:user.id},{key:"editeduser",value:editeduser.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) - - ticketRemoveListeners.forEach((func) => { - try { - func(user,editeduser,channel,guild,date,ticketdata) - }catch{} - }) - -} - -/** - * - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - */ -exports.onTicketClaim = (user,channel,guild,date,ticketdata) => { - //system - bot.errorLog.log("api","user claimed a ticket",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) - - ticketClaimListeners.forEach((func) => { - try { - func(user,channel,guild,date,ticketdata) - }catch{} - }) - -} - -/** - * - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - */ -exports.onTicketUnclaim = (user,channel,guild,date,ticketdata) => { - //system - bot.errorLog.log("api","user unclaimed a ticket",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) - - ticketUnclaimListeners.forEach((func) => { - try { - func(user,channel,guild,date,ticketdata) - }catch{} - }) - -} - -/** - * @param {String} newtype - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - */ -exports.onTicketChange = (newtype,user,channel,guild,date,ticketdata) => { - //system - bot.errorLog.log("api","user changed ticket type",[{key:"newtype",value:newtype},{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) - - ticketChangeListeners.forEach((func) => { - try { - func(newtype,user,channel,guild,date,ticketdata) - }catch{} - }) - -} - -/** - * - * @param {discord.Message[]} messages - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - */ -exports.onTranscriptCreation = (messages,channel,guild,date) => { - //system - bot.errorLog.log("api","transcript created",[{key:"messages",value:JSON.stringify(messages)},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id}]) - - transcriptCreationListeners.forEach((func) => { - try { - func(messages,channel,guild,date) - }catch{} - }) - -} - -/**@typedef {"help"|"message"|"close"|"delete"|"reopen"|"rename"|"add"|"remove"|"claim"|"unclaim"|"change"|"stats"} OTCommandType */ - -/** - * - * @param {OTCommandType} type - * @param {Boolean} hasPerms - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - */ -exports.onCommand = (type,hasPerms,user,channel,guild,date) => { - - const newguild = guild ? guild : false - //system - bot.errorLog.log("api","someone used a command",[{key:"type",value:type},{key:"hasPerms",value:hasPerms},{key:"userid",value:user},{key:"channelid",value:channel.id},{key:"guildid",value:newguild.id}]) - - commandListeners.forEach((func) => { - try { - func(type,hasPerms,user,channel,newguild,date) - }catch{} - }) -} - -/**@typedef {"add"|"remove"|"add&remove"} OTReactionRoleType */ -/**@typedef {"add"|"remove"} OTReactionRoleMode */ - -/** - * @param {OTReactionRoleMode} mode - * @param {OTReactionRoleType} type - * @param {discord.Role} role - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - */ - exports.onReactionRole = (mode,type,role,user,channel,guild,date) => { - //system - bot.errorLog.log("api","someone used a reaction role",[{key:"mode",value:mode},{key:"type",value:type},{key:"roleid",value:role.id},{key:"userid",value:user},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id}]) - - reactionRoleListeners.forEach((func) => { - try { - func(mode,type,role,user,channel,guild,date) - }catch{} - }) - -} - -/** - * @param {String} err - * @param {Date} date - */ - exports.onError = (err,date) => { - //system - bot.errorLog.log("api","there is an error",[{key:"error",value:err}]) - - errorListeners.forEach((func) => { - try { - func(err,date) - }catch{} - }) - -} - - -//EVENT CALLBACKS: - -/** - * @callback TicketActionEvent - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - */ - -/** - * @callback TicketCloseEvent - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - * @param {String} reason - */ - -/** - * @callback TranscriptCreationEvent - * @param {discord.Message[]} messages - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - */ - -/** - * @callback TicketUserChangeEvent - * @param {discord.User} user - * @param {discord.User} editeduser - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - */ - -/** - * @callback TicketTypeChangeEvent - * @param {String} newtype - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata - */ - -/** - * @callback CommandEvent - * @param {OTCommandType} type - * @param {Boolean} hasPerms - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild|false} guild - * @param {Date} date - */ - -/** - * @callback ReactionRoleEvent - * @param {OTReactionRoleMode} mode - * @param {OTReactionRoleType} type - * @param {discord.Role} role - * @param {discord.User} user - * @param {discord.TextChannel} channel - * @param {discord.Guild} guild - * @param {Date} date - */ - -/** - * @callback ErrorEvent - * @param {String} error - * @param {Date} date - */ - -//EVENT EXPORT: - -/**@param {TicketActionEvent} callback */ -const onTicketOpen = (callback) => { - ticketOpenListeners.push(callback) -} - -/**@param {TicketCloseEvent} callback */ -const onTicketClose = (callback) => { - ticketCloseListeners.push(callback) -} - -/**@param {TicketActionEvent} callback */ -const onTicketDelete = (callback) => { - ticketDeleteListeners.push(callback) -} - -/**@param {TicketActionEvent} callback */ -const onTicketReopen = (callback) => { - ticketReopenListeners.push(callback) -} - -/**@param {TicketUserChangeEvent} callback */ -const onTicketAdd = (callback) => { - ticketAddListeners.push(callback) -} - -/**@param {TicketUserChangeEvent} callback */ -const onTicketRemove = (callback) => { - ticketRemoveListeners.push(callback) -} - -/**@param {TicketActionEvent} callback */ -const onTicketClaim = (callback) => { - ticketClaimListeners.push(callback) -} - -/**@param {TicketActionEvent} callback */ -const onTicketUnclaim = (callback) => { - ticketUnclaimListeners.push(callback) -} - -/**@param {TicketTypeChangeEvent} callback */ -const onTicketChange = (callback) => { - ticketChangeListeners.push(callback) -} - -/**@param {TranscriptCreationEvent} callback */ -const onTranscriptCreation = (callback) => { - transcriptCreationListeners.push(callback) -} - -/**@param {CommandEvent} callback */ -const onCommand = (callback) => { - commandListeners.push(callback) -} - -/**@param {ReactionRoleEvent} callback */ -const onReactionRole = (callback) => { - commandListeners.push(callback) -} - -/**@param {ErrorEvent} callback */ -const onError = (callback) => { - errorListeners.push(callback) -} - -exports.events = { - onTicketOpen, - onTicketClose, - onTicketDelete, - onTicketReopen, - onTicketAdd, - onTicketRemove, - onTicketClaim, - onTicketUnclaim, - onTicketChange, - onTranscriptCreation, - onCommand, - onReactionRole, - onError -} \ No newline at end of file diff --git a/core/api/pluginlauncher.js b/core/api/pluginlauncher.js deleted file mode 100644 index 3a50c4b..0000000 --- a/core/api/pluginlauncher.js +++ /dev/null @@ -1,43 +0,0 @@ -const fs = require("fs") -const bot = require("../../index") -const log = bot.errorLog.log - -module.exports = () => { - const args = process.argv - const debugMode = args.includes("--debug") - - const files = fs.readdirSync("./plugins") - const api = require("./api.json") - var totalcount = 0 - var successcount = 0 - var failcount = 0 - files.forEach((file) => { - if (file.endsWith(".plugin.js")){ - try { - require("../../plugins/" + file)() - - successcount++ - totalcount++ - }catch(err){ - /**@type {Error} */ - const theError = err - if (api.enableAPIdebug || debugMode) { - console.error(theError) - } - - try { - const data = fs.readFileSync("./openticketdebug.txt") - const newData = data ? data.toString() : "" - fs.writeFileSync("./openticketdebug.txt", newData + "\nPLUGIN "+file+" ERROR: " + theError.name + ": " + theError.message + "\n" + theError.stack + "\n\n") - } catch { - fs.writeFileSync("./openticketdebug.txt", "\nPLUGIN "+file+" ERROR: " + theError.name + ": " + theError.message + "\n" + theError.stack + "\n\n") - } - - failcount++ - totalcount++ - } - } - }) - - require("../startscreen").headerDataPlugins({ total: totalcount, success: successcount, error: failcount }) -} \ No newline at end of file diff --git a/core/checker.js b/core/checker.js deleted file mode 100644 index 543f853..0000000 --- a/core/checker.js +++ /dev/null @@ -1,551 +0,0 @@ -exports.checker = async () => { - const chalk = await (await import("chalk")).default - - if (process.argv.some((v) => v == "--nochecker")) return - if (process.argv.some((v) => v == "--devconfig")){ - //console.log(chalk.blue("=> used dev config instead of normal config")) - try{ - var tempconfig = require("../devconfig.json") - }catch(err){console.log(err);var tempconfig = require("../config.json")} - }else{ - var tempconfig = require("../config.json") - } - - const config = tempconfig - var errorList = [] - var isError = false - var warnList = [] - var isWarn = false - const createError = (message) => { - isError = true - errorList.push("open-ticket CONFIG ERROR: "+message) - } - const createWarn = (message) => { - isWarn = true - warnList.push("open-ticket CONFIG WARNING: "+message) - } - - //validators - /**@param {"userid"|"roleid"|"channelid"|"serverid"|"categoryid"} mode @param {String} value @param {String} path */ - const checkDiscord = (mode,value,path) => { - if (mode == "userid"){ - if (value.length < 16 || value.length > 40 || !/^\d+$/.test(value)){ - createError("'"+path+"' | this user id is invalid") - } - }else if (mode == "channelid"){ - if (value.length < 16 || value.length > 40 || !/^\d+$/.test(value)){ - createError("'"+path+"' | this channel id is invalid") - } - }else if (mode == "roleid"){ - if (value.length < 16 || value.length > 40 || !/^\d+$/.test(value)){ - createError("'"+path+"' | this role id is invalid") - } - }else if (mode == "serverid"){ - if (value.length < 16 || value.length > 40 || !/^\d+$/.test(value)){ - createError("'"+path+"' | this server id is invalid") - } - }else if (mode == "categoryid"){ - if (value.length < 16 || value.length > 40 || !/^\d+$/.test(value)){ - createError("'"+path+"' | this category id is invalid") - } - } - } - /**@param {String} value */ - const checkToken = (value) => { - if (value.length < 40){ - createError("'token/value' | your token is invalid") - } - if (value.includes(" ")) createError("'token/value' | your token includes spaces!") - } - - /**@param {String} value @param {String} path */ - const checkHexColor = (value,path) => { - if (!/^#[a-fA-F0-9]{3,6}$/.test(value)){ - if (value.length < 4) return createError("'"+path+"' | hex color too short! (example: #123abc)") - if (value.length > 7) return createError("'"+path+"' | hex color too long! (example: #123abc)") - createError("'"+path+"' | invalid color! (example: #123abc)") - } - } - - /**@param {String} value @param {String} path */ - const checkEmbedColor = (value,path) => { - if (!['DEFAULT','WHITE','AQUA','GREEN','BLUE','YELLOW','PURPLE','LUMINOUS_VIVID_PINK','FUCHSIA','GOLD','ORANGE','RED','GREY','DARKER_GREY','NAVY','DARK_AQUA','DARK_GREEN','DARK_BLUE','DARK_PURPLE','DARK_VIVID_PINK','DARK_GOLD','DARK_ORANGE','DARK_RED','DARK_GREY','LIGHT_GREY','DARK_NAVY','BLURPLE','GREYPLE','DARK_BUT_NOT_BLACK','NOT_QUITE_BLACK','RANDOM'].includes(value)){ - return createError("'"+path+"' | invalid color, must be a hex code or default color (more info in the wiki)") - } - } - - /**@param {String} value @param {String} path @param {Number} minLength @param {Number} maxLength @param {String} name */ - const checkString = (value,minLength,maxLength,path,name) => { - if (value.length < minLength){ - createError("'"+path+"' | "+name+" is too short!") - }else if (value.length > maxLength){ - createError("'"+path+"' | "+name+" is too long!") - } - } - - /**@param {"userid"|"roleid"|"channelid"|"serverid"} mode @param {String[]} arrayValue @param {String} path */ - const checkDiscordArray = (mode,arrayValue,path) => { - if (!Array.isArray(arrayValue)){ - return createError("'"+path+"' | this needs to be an Array!") - } - if (mode == "userid"){ - arrayValue.forEach((value,index) => { - if (value.length < 16 || value.length > 40 || !/^\d+$/.test(value)){ - createError("'"+path+":"+index+"' | this user id is invalid") - } - }) - }else if (mode == "channelid"){ - arrayValue.forEach((value,index) => { - if (value.length < 16 || value.length > 40 || !/^\d+$/.test(value)){ - createError("'"+path+":"+index+"' | this channel id is invalid") - } - }) - }else if (mode == "roleid"){ - arrayValue.forEach((value,index) => { - if (value.length < 16 || value.length > 40 || !/^\d+$/.test(value)){ - createError("'"+path+":"+index+"' | this role id is invalid") - } - }) - }else if (mode == "serverid"){ - arrayValue.forEach((value,index) => { - if (value.length < 16 || value.length > 40 || !/^\d+$/.test(value)){ - createError("'"+path+":"+index+"' | this server id is invalid") - } - }) - } - } - /**@param {String} value @param {"string"|"boolean"|"number"|"array"|"object"} type */ - const checkType = (value,type,path) => { - if (type == "boolean"){ - if (typeof value != "boolean"){ - createError("'"+path+"' | invalid type, this must be a boolean!") - return true - }else return false - }else if (type == "number"){ - if (typeof value != "number"){ - createError("'"+path+"' | invalid type, this must be a number!") - return true - }else return false - }else if (type == "string"){ - if (typeof value != "string"){ - createError("'"+path+"' | invalid type, this must be a string!") - return true - }else return false - }else if (type == "array"){ - if (!Array.isArray(value)){ - createError("'"+path+"' | invalid type, this must be an array!") - return true - }else return false - }else if (type == "object"){ - if (typeof value != "object"){ - createError("'"+path+"' | invalid type, this must be an object!") - return true - }else return false - }else return false - } - - const checkButtonColor = (value,path) => { - if (value != "none" && value != "grey" && value != "gray" && value != "black" && value != "red" && value != "green" && value != "blue" && value != "blurple"){ - createError("'"+path+"' | invalid color, it must be one of these: none, gray, red, green, blue!") - } - } - - const configParser = require("./utils/configParser") - /** - * @param {configParser.OTAllOptions} option - * @param {String} path - */ - - const checkOption = (option,path) => { - - //id - checkType(option.id,"string",path+"/id") - if (option.id.includes(" ")){ - createError("'"+path+"/id' | option id can't contain space characters!") - } - if (option.id.length > 20){ - createError("'"+path+"/id' | option id max lenght is 20!") - } - - //name - checkType(option.name,"string",path+"/name") - if (option.name.length > 100){ - createWarn("'"+path+"/name' | if your name is too long it maybe doesn't look so good!") - }else if (option.name.length < 1){ - createError("'"+path+"/name' | there is no name!") - } - - //description - checkType(option.description,"string",path+"/description") - - //icon - const emojiRegex = /(?:\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])|(?:)/gi - if (option.icon.length > 0){ - - const isEmoji = emojiRegex.test(option.icon) - - if (isEmoji == false){ - createError("'"+path+"/icon' | invalid emoji or custom discord emoji") - } - } - checkType(option.icon,"string",path+"/icon") - - //label - checkType(option.label,"string",path+"/label") - if (option.label.length < 1 && option.icon.length < 1){ - createError("'"+path+"' | you need at least one of these: label, icon!") - } - - //type - checkType(option.type,"string",path+"/type") - if (option.type != "ticket" && option.type != "website" && option.type != "role"){ - createError("'"+path+"/type' | the type must be one of these: ticket, website, role!") - } - /**@type {"ticket"|"website"|"role"} */ - const type = option.type - - if (type == "ticket"){ - //color - checkType(option.color,"string",path+"/color") - checkButtonColor(option.color,path+"/color") - - //adminroles - checkType(option.adminroles,"array",path+"/adminroles") - checkDiscordArray("roleid",option.adminroles,path+"/adminroles") - - //channelprefix - checkType(option.channelprefix,"string",path+"/channelprefix") - if (option.channelprefix.includes(" ")){ - createWarn("'"+path+"/channelprefix' | this prefix can't contain spaces!") - } - - //category - checkType(option.category,"string",path+"/category") - if (option.category.length > 0){ - checkDiscord("categoryid",option.category,path+"/category") - } - - //message - checkType(option.message,"string",path+"/message") - - //enableDmOnOpen - checkType(option.enableDmOnOpen,"boolean",path+"/enableDmOnOpen") - - //ticketmessage - checkType(option.ticketmessage,"string",path+"/ticketmessage") - - //thumbnail - if (option.thumbnail){ - checkType(option.thumbnail.enable,"boolean",path+"/thumbnail/enable") - checkType(option.thumbnail.url,"string",path+"/thumbnail/url") - }else{ - createError("'"+path+"/thumbnail' | there is no thumbnail object!") - } - - //image - if (option.image){ - checkType(option.image.enable,"boolean",path+"/image/enable") - checkType(option.image.url,"string",path+"/image/url") - }else{ - createError("'"+path+"/image' | there is no image object!") - } - - //closedCategory - if (option.closedCategory){ - checkType(option.closedCategory.enable,"boolean",path/"/closedCategory/enable") - checkType(option.closedCategory.id,"string",path/"/closedCategory/id") - if (option.closedCategory.enable){ - checkDiscord("roleid",option.closedCategory.id,path+"/closedCategory/id") - } - }else{ - createError("'"+path+"/closedCategory' | there is no closedCategory object!") - } - - //autoclose - if (option.autoclose){ - checkType(option.autoclose.enable,"boolean",path/"/autoclose/enable") - checkType(option.autoclose.inactiveHours,"number",path/"/autoclose/id") - }else{ - createError("'"+path+"/autoclose' | there is no autoclose object!") - } - - }else if (type == "website"){ - //url - checkType(option.url,"string",path+"/url") - if (option.url.includes(" ")){ - createWarn("'"+path+"/url' | a url can't contain spaces") - } - if (option.url.length < 1){ - createError("'"+path+"/url' | there is no url!") - } - if (!option.url.startsWith("https://") && !option.url.startsWith("http://") && !option.url.startsWith("discord://")){ - createWarn("'"+path+"/url' | your url doesn't start with https or http!") - } - if (option.url.startsWith("http://")){ - createWarn("'"+path+"/url' | your url is not a HTTPS link! discord can block this url!") - } - }else if (type == "role"){ - //color - checkType(option.color,"string",path+"/color") - checkButtonColor(option.color,path+"/color") - - //roles - checkDiscordArray("roleid",option.roles,path+"/roles") - - //mode - checkType(option.mode,"string",path+"/mode") - if (option.mode != "add&remove" && option.mode != "add" && option.mode != "remove"){ - createError("'"+path+"/mode' | mode must be one of these: add, remove, add&remove") - } - - //enableDmOnOpen - checkType(option.enableDmOnOpen,"boolean",path+"/enableDmOnOpen") - } - } - - /** - * - * @param {configParser.OTConfigMessage} input - * @param {String} path - */ - const checkMessage = (input,path) => { - //id - if (!input.id) createError("'"+path+"/id' | this embed doesn't have an id!") - if (input.id.length > 50) createError("'"+path+"/id' | the id can't be longer than 50") - if (input.id.includes(" ") || input.id.includes("\n")) createError("'"+path+"/id' | the id can't contain spaces!") - - //name - if (input.name.length < 1){ - createWarn("'"+path+"/name' | this embed has no name!") - }else if (input.name.length > 99) { - createError("'"+path+"/name' | the name can't be longer than 100") - } - - //description - if (input.description.length < 0){ - createWarn("'"+path+"/description' | this embed doesn't have a description!") - } - - //dropdown - checkType(input.dropdown,"boolean",path+"/dropdown") - - //footer - checkType(input.enableFooter,"boolean",path+"/enableFooter") - if (input.enableFooter){ - if (input.footer.length < 1) createError("'"+path+"/footer' | no footer!") - if (input.footer.length > 200) createError("'"+path+"/footer' | footer length can't be more than 200!") - } - - //thumbnail - checkType(input.enableThumbnail,"boolean",path+"/enableThumbnail") - if (input.enableThumbnail){ - if (input.thumbnail.length < 1) createError("'"+path+"/thumbnail' | no thumbnail url!") - } - - //customColor - checkType(input.enableCustomColor,"boolean",path+"/enableCustomColor") - if (input.enableCustomColor){ - if (input.color.length < 1) createError("'"+path+"/color' | no color!") - checkHexColor(input.color,path+"/color") - } - - //OPTIONS!!! - if (checkType(input.options,"array",path+"/options")){ - var counter = 0 - input.options.forEach((option) => {if (!configParser.optionExists(option)){counter++}}) - - if (counter == input.options.length){ - createWarn("'"+path+"/options' | insert the option ids here!") - }else{ - input.options.forEach((option,index) => { - if (!configParser.optionExists(option)){ - createWarn("'"+path+"/options:"+index+"' | this option doesnt exist!") - } - }) - } - } - - //other - //ticket explaination & max tickets warning - if (typeof input.other != "object"){ - createError("'"+path+"/other' | this object doesn't exist!") - }else{ - checkType(input.other.enableTicketExplaination,"boolean",path+"/other/enableTicketExplaination") - checkType(input.other.enableMaxTicketsWarning,"boolean",path+"/other/enableMaxTicketsWarning") - - //customDropdownPlaceholder - if (typeof input.other.customDropdownPlaceholder != "object"){ - createError("'"+path+"/other/customDropdownPlaceholder' | this object doesn't exist!") - }else{ - checkType(input.other.customDropdownPlaceholder.enable,"boolean",path+"/other/customDropdownPlaceholder/enable") - checkType(input.other.customDropdownPlaceholder.text,"string",path+"/other/customDropdownPlaceholder/text") - if (input.other.customDropdownPlaceholder.enable && input.other.customDropdownPlaceholder.text.length < 1){createError("'"+path+"/other/customDropdownPlaceholder/text' | there is no placeholder text!")} - } - - //customCategoryText - if (typeof input.other.customCategoryText != "object"){ - createError("'"+path+"/other/customCategoryText' | this object doesn't exist!") - }else{ - checkType(input.other.customCategoryText.enable,"boolean",path+"/other/customCategoryText/enable") - checkType(input.other.customCategoryText.text,"string",path+"/other/customCategoryText/text") - if (input.other.customCategoryText.enable && input.other.customCategoryText.text.length < 1){createError("'"+path+"/other/customCategoryText/text' | there is no category text!")} - } - - //embedTitleURL - if (typeof input.other.embedTitleURL != "object"){ - createError("'"+path+"/other/embedTitleURL' | this object doesn't exist!") - }else{ - checkType(input.other.embedTitleURL.enable,"boolean",path+"/other/embedTitleURL/enable") - checkType(input.other.embedTitleURL.url,"string",path+"/other/embedTitleURL/text") - if (input.other.embedTitleURL.enable && input.other.embedTitleURL.url.length < 1){createError("'"+path+"/other/embedTitleURL/url' | there is no url!")} - } - } - } - - ////////////////////////////////////////// - ////////////////////////////////////////// - /////////!!! CHECKER.JS START !!!///////// - ////////////////////////////////////////// - ////////////////////////////////////////// - - var configArray = ["color","serverId","token","adminRoles","prefix","languageFile","status","system","options","messages"] - configArray.forEach((item) => { - if (config[item] == undefined){ - throw new Error("\n\nMAIN ERROR: the item '"+item+"' doesn't exist in config.json") - } - }) - - checkHexColor(config.color,"main_color") - checkDiscord("serverid",config.serverId,"serverId") - - if (!require("./api/api.json").disable.checkerjs.token && !config.token.fromENV) checkToken(config.token.value) - - checkType(config.adminRoles,"array","/adminRoles") - checkDiscordArray("roleid",config.adminRoles,"adminRoles") - checkString(config.prefix,1,40,"prefix","prefix") - - //languagefile - checkType(config.languageFile,"string","languageFile") - const languageList = [ - "custom", - "english", - "dutch", - "romanian", - "german", - "arabic", - "spanish", - "portuguese", - "french", - "italian", - "czech", - "danish", - "russian", - "turkish", - "polish", - "slovenian", - "thai", - "norwegian", - "greek", - "ukrainian", - "hungarian", - "indonesian", - "kurdish", - "persian", - "latvian", - "estonian", - "japanese", - "korean", - "simplifiedchinese", - "traditionalchinese", - "finnish", - "swedish", - "vietnamese" - ] - if (!languageList.some((l) => config.languageFile.startsWith(l))){ - createError("'languageFile' | invalid language, more info in the wiki") - } - - //status: - checkType(config.status.enabled,"boolean","status/enabled") - if (config.status.enabled){ - if (config.status.type != "PLAYING" && config.status.type != "LISTENING" && config.status.type != "WATCHING" && config.status.type != "CUSTOM"){ - createError("'status/type' | not a valid status type! (LISTENING,WATCHING,PLAYING)") - } - if (config.status.text.length < 1){ - createError("'status/text' | there is no status text!") - } - if (config.status.text.length > 50) createError("'status/text' | text too long!") - } - - - //system: - //max tickets - checkType(config.system.maxAmountOfTickets,"number","system/maxAmountOfTickets") - - //enableDMmessages - checkType(config.system.dmMessages,"boolean","system/dmMessages") - - //memberRole - checkType(config.system.memberRole,"string","system/memberRole") - if (config.system.memberRole && ![" ","0","false","null","undefined"].includes(config.system.memberRole)){ - checkDiscord("roleid",config.system.memberRole,"system/memberRole") - }else{ - createWarn("'system/memberRole' | You don't have a member role, but it's recommended!") - } - - //closemode - checkType(config.system.closeMode,"string","system/closeMode") - if (!["normal","adminonly"].includes(config.system.closeMode)){ - createError("'system/closeMode' | the close mode must be adminonly or normal") - } - - checkType(config.system.showSlashcmdsInHelp,"boolean","system/showSlashcmdsInHelp") - checkType(config.system.answerInEphemeralOnOpen,"boolean","system/answerInEphemeralOnOpen") - - //options - - config.options.forEach((option,index) => { - checkOption(option,"options/"+index) - }) - - //messages - config.messages.forEach((message,index) => { - checkMessage(message,"messages/"+index) - }) - - - //the end - if (errorList.length > 0 || warnList.length > 0){ - console.log("REPORT:\n===========================") - warnList.forEach((w) => { - const splitw = w.split("'") - if (splitw.length > 1){ - var splitstring = chalk.yellow(splitw[0])+chalk.blue("'"+splitw[1]+"'")+chalk.yellow(splitw[2]) - if (splitw[3]){splitstring = splitstring+chalk.yellow(splitw[3])} - if (splitw[4]){splitstring = splitstring+chalk.yellow(splitw[4])} - if (splitw[5]){splitstring = splitstring+chalk.yellow(splitw[5])} - }else {var splitstring = chalk.yellow(splitw[0])} - console.log(splitstring) - }) - errorList.forEach((e) => { - const splite = e.split("'") - if (splite.length > 1){ - var splitstring = chalk.red(splite[0])+chalk.blue("'"+splite[1]+"'")+chalk.red(splite[2]) - }else {var splitstring = chalk.red(splite[0])} - console.log(splitstring) - }) - if (isError){ - console.log("===========================") - console.log("=> "+chalk.bgRed("your bot doesn't work if you don't fix the above errors!")) - if (isWarn){ - console.log("\n=> "+chalk.bgYellow("if you ignore warns, some things may work differently than expected!")) - } - console.log(chalk.bold.green("\nDOCUMENTATION => https://otdocs.dj-dj.be\nSUPPORT => https://discord.dj-dj.be\n")) - process.exit(0) - }else if (isWarn){ - console.log("===========================") - console.log("=> "+chalk.bgYellow("if you ignore warns, some things may work differently than expected!")) - console.log(chalk.bold.green("\nDOCUMENTATION => https://otdocs.dj-dj.be\nSUPPORT => https://discord.dj-dj.be\n")) - } - } -} diff --git a/core/dynamicdatabase/databases/main.js b/core/dynamicdatabase/databases/main.js deleted file mode 100644 index 866ef67..0000000 --- a/core/dynamicdatabase/databases/main.js +++ /dev/null @@ -1,82 +0,0 @@ -const fs = require("fs") -const location = "./storage/database.json" - - -/**@returns {[{category:String, key:String, value:String}]}*/ -function getData(){ - if (fs.existsSync(location)){ - return JSON.parse(fs.readFileSync(location).toString()) - }else{ - fs.writeFileSync(location,"[]") - return [] - } -} -/**@param {[{category:String, key:String, value:String}]} data*/ -function setData(data){ - fs.writeFileSync(location,JSON.stringify(data,null,"\t")) -} - -exports.set = (category,key,value) => { - const currentData = getData() - const exists = currentData.find((d) => (d.category == category) && (d.key == key)) ? true : false - var newData = [] - if (exists){ - currentData.forEach((d,i) => { - if (d.category == category && d.key == key){ - newData.push({category,key,value}) - }else{ - newData.push(d) - } - }) - }else{ - currentData.push({category,key,value}) - newData = currentData - } - - setData(newData) - return exists -} -/** - * @param {String} category - * @param {String} key - * @returns {String|false} - */ -exports.get = (category,key) => { - const currentData = getData() - const tempresult = currentData.find((d) => (d.category == category) && (d.key == key)) - const result = tempresult ? tempresult.value : false - return result -} - -/** - * @param {String} category - * @returns {[{key:String,value:String}]|false} - */ -exports.getCategory = (category) => { - const currentData = getData() - const result = currentData.filter((v) => v.category == category) - return result -} - -/** - * @param {String} category - * @param {String} key - * @param {String} value - */ -exports.delete = (category,key) => { - const currentData = getData() - const exists = currentData.find((d) => (d.category == category) && (d.key == key)) ? true : false - var newData = [] - if (exists){ - currentData.forEach((d,i) => { - if (!(d.category == category && d.key == key)){ - newData.push(d) - } - }) - }else{ - newData = currentData - } - - setData(newData) - return exists -} \ No newline at end of file diff --git a/core/dynamicdatabase/databases/stats.js b/core/dynamicdatabase/databases/stats.js deleted file mode 100644 index 2190e8a..0000000 --- a/core/dynamicdatabase/databases/stats.js +++ /dev/null @@ -1,87 +0,0 @@ -const fs = require("fs") -const location = "./storage/stats.json" - - -/**@returns {[{category:String, key:String, value:String}]}*/ -function getData(){ - if (fs.existsSync(location)){ - return JSON.parse(fs.readFileSync(location).toString()) - }else{ - fs.writeFileSync(location,"[]") - return [] - } -} -/**@param {[{category:String, key:String, value:String}]} data*/ -function setData(data){ - fs.writeFileSync(location,JSON.stringify(data,null,"\t")) -} - -/** - * @param {String} category - * @param {String} key - * @param {String|Boolean|Number} value - * @returns {Boolean} exists? - */ -exports.set = (category,key,value) => { - const currentData = getData() - const exists = currentData.find((d) => (d.category == category) && (d.key == key)) ? true : false - var newData = [] - if (exists){ - currentData.forEach((d,i) => { - if (d.category == category && d.key == key){ - newData.push({category,key,value}) - }else{ - newData.push(d) - } - }) - }else{ - currentData.push({category,key,value}) - newData = currentData - } - - setData(newData) - return exists -} -/** - * @param {String} category - * @param {String} key - * @returns {String|Boolean|Number|undefined} - */ -exports.get = (category,key) => { - const currentData = getData() - const result = currentData.find((d) => (d.category == category) && (d.key == key)) - return (result) ? result.value : undefined -} - -/** - * @param {String} category - * @returns {[{key:String,value:String|Boolean|Number}]|false} - */ -exports.getCategory = (category) => { - const currentData = getData() - const result = currentData.filter((v) => v.category == category) - return result -} - -/** - * @param {String} category - * @param {String} key - * @returns {Boolean} exists? - */ -exports.delete = (category,key) => { - const currentData = getData() - const exists = currentData.find((d) => (d.category == category) && (d.key == key)) ? true : false - var newData = [] - if (exists){ - currentData.forEach((d,i) => { - if (!(d.category == category && d.key == key)){ - newData.push(d) - } - }) - }else{ - newData = currentData - } - - setData(newData) - return exists -} \ No newline at end of file diff --git a/core/dynamicdatabase/storage.js b/core/dynamicdatabase/storage.js deleted file mode 100644 index b32f4de..0000000 --- a/core/dynamicdatabase/storage.js +++ /dev/null @@ -1,23 +0,0 @@ -/** -================================================================== -ALL DATABASE FILES NEED TO EXPORT THE FOLLOWING FUNCTIONS: -- get(category:String,key:String) => String (value) -- set(category:String,key:String,value:String) => Boolean (success) -- delete(category:String,key:String) => Boolean (success) -- getCategory(category:String) => Array[{key:String,value:String}] (key,value) -================================================================== - */ - -try { - var main = require("./databases/main") - var stats = require("./databases/stats") -}catch(err){ - console.log(err) - console.log("Unable to find the database handlers!") - process.exit(1) -} - -module.exports = { - main, - stats -} \ No newline at end of file diff --git a/core/errorLogSystem.js b/core/errorLogSystem.js deleted file mode 100644 index 3da2340..0000000 --- a/core/errorLogSystem.js +++ /dev/null @@ -1,160 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const l = bot.language - -const loadChalk = async () => { - return await (await import("chalk")).default -} -const embed = discord.EmbedBuilder -const c = discord.Colors - -/**@param {discord.User} user*/ -exports.noPermsMessage = (user) => { - return new embed() - .setColor(c.Red) - .setTitle("❌ "+l.errors.noPermsTitle) - .setDescription(l.errors.noPermsDescription) - .setFooter({iconURL:user.displayAvatarURL(),text:user.username}) -} - -/**@param {discord.User} user*/ -exports.noPermsDelete = (user) => { - return new embed() - .setColor(c.Red) - .setTitle("❌ "+l.errors.noPermsTitle) - .setDescription(l.errors.noPermsDelete) - .setFooter({iconURL:user.displayAvatarURL(),text:user.username}) -} - -/**@param {String} message */ -exports.invalidArgsMessage = (message) => { - var x = new embed() - .setColor(c.Red) - .setTitle("❌ "+l.errors.missingArgsTitle) - .setDescription(message) - - return x -} - -/**@param {String} message */ -exports.serverError = (message) => { - var x = new embed() - .setColor(c.Orange) - .setTitle("⚠️ "+l.errors.boterror) - .setDescription(message) - - return x -} - -/**@param {String[]} list @param {String|undefined} message */ -exports.invalidIdChooseFromList = (list,message) => { - const beforemsg = message ? message+"\n\n" : "" - var x = new embed() - .setColor(c.Red) - .setTitle("❌ "+l.errors.chooseFromListTitle) - .setDescription(beforemsg+l.errors.chooseFromListDescription+"\n`"+list.join("`\n`")+"`") - return x -} - -exports.failedRenameChannel = new embed() - .setColor(c.Red) - .setTitle("❌ Failed to rename channel") - .setDescription("Discord channels can only be renamed twice every 10 minutes! Open Ticket can't do anything about this error!") - -exports.notInATicket = new embed() - .setColor(c.Red) - .setTitle("❌ "+l.errors.notInTicketTitle) - .setDescription(l.errors.notInTicketDescription) - - -/**@param {String} message @param {String} title */ -exports.success = (title,message) => { - var x = new embed() - .setColor(config.color) - .setTitle("✅ "+title) - .setDescription(message) - - return x -} - -/**@param {String} message @param {String} title */ -exports.warning = (title,message) => { - var x = new embed() - .setColor(c.Orange) - .setTitle("⚠️ "+title) - .setDescription(message) - - return x -} - -/**@param {String} message the message @param {String} title the title @param {String} emoji an discord emoji @param {discord.ColorResolvable} color the embed color*/ -exports.custom = (title,message,emoji,color) => { - var x = new embed() - .setColor(color) - .setTitle(emoji+" "+title) - .setDescription(message) - - return x -} - -exports.clearDebugFile = () => { - const fs = require("fs") - if (!fs.existsSync("./openticketdebug.txt")) return - const content = fs.readFileSync("./openticketdebug.txt").toString().split("\n") - if (content.length < 5000) return - for (let i = 0; i < 4000; i++) { - content.shift() - } - - const newContent = "==========================\n\n=========================="+content.join("\n") - fs.writeFileSync("./openticketdebug.txt",newContent) -} - -const normalLog = (debugString) => { - const fs = require("fs") - const content = fs.existsSync("./openticketdebug.txt") ? fs.readFileSync("./openticketdebug.txt").toString() : "==========================\n\n==========================" - fs.writeFileSync("./openticketdebug.txt",content+"\nSYSTEM: "+debugString) - this.clearDebugFile() -} - -/** - * - * @param {"system"|"command"|"info"|"api"|"debug"} type - * @param {String} message - * @param {[{key:String,value:String}]} params - */ -exports.log = async (type,message,params) => { - var ptype = type - const chalk = await loadChalk() - var paramstring = "" - if (params){ - if (params.length > 0){ - params.forEach((p) => { - paramstring = paramstring+p.key+": "+p.value+" " - }) - } - } - const parameters = params ? "("+paramstring+")" : " " - - if (ptype == "command"){ - console.log(chalk.green("[command] ")+message+" "+chalk.yellow(parameters)) - }else if (ptype == "info"){ - console.log(chalk.blue("[info] ")+message+" "+chalk.yellow(parameters)) - }else if (ptype == "system"){ - console.log(chalk.green("[system] ")+message+" "+chalk.yellow(parameters)) - }else if (ptype == "api"){ - if (require("./api/api.json").enableAPIconsolelogs == true){ - console.log(chalk.red("[api v"+require("./api/api.json").version+"] ")+message+" "+chalk.yellow(parameters)) - } - ptype = "api v"+require("./api/api.json").version - }else if (ptype == "debug"){ - if (!process.argv.some((v) => v == "--debug")) return - console.log(chalk.redBright("[DEBUG] ")+message+" "+chalk.yellow(parameters)) - } - - const cd = new Date() - const months = ["January","February","March","April","May","June","July","August","September","October","November","December"] - normalLog("["+cd.getDate()+" "+months[cd.getMonth()-1]+" "+cd.getFullYear()+" - "+cd.getSeconds()+":"+cd.getMinutes()+":"+cd.getHours()+"] ["+ptype+"] "+message+" "+parameters) -} \ No newline at end of file diff --git a/core/interactionHandlers/buttons/close.js b/core/interactionHandlers/buttons/close.js deleted file mode 100644 index a476070..0000000 --- a/core/interactionHandlers/buttons/close.js +++ /dev/null @@ -1,87 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const hiddendata = bot.hiddenData -const embed = discord.EmbedBuilder -const mc = config.color - -const button = discord.ButtonBuilder -const arb = discord.ActionRowBuilder -const bs = discord.ButtonStyle - - -exports.closeCommandRow = new arb() - .addComponents( - new button() - .setCustomId("OTdeleteTicket1") - .setDisabled(false) - .setStyle(bs.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - .addComponents( - new button() - .setCustomId("OTreopenTicket") - .setDisabled(false) - .setStyle(bs.Success) - .setLabel(l.buttons.reopen) - .setEmoji("✔") - ) - -exports.closeCommandRowDisabled = new arb() - .addComponents( - new button() - .setCustomId("OTdeleteTicket1") - .setDisabled(true) - .setStyle(bs.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - .addComponents( - new button() - .setCustomId("OTreopenTicket") - .setDisabled(true) - .setStyle(bs.Success) - .setLabel(l.buttons.reopen) - .setEmoji("✔") - ) - -exports.openRowNormal = new arb() - .addComponents( - new button() - .setCustomId("OTcloseTicket") - .setDisabled(false) - .setStyle(bs.Secondary) - .setLabel(l.buttons.close) - .setEmoji("🔒") - ) - .addComponents( - new button() - .setCustomId("OTdeleteTicket") - .setDisabled(false) - .setStyle(bs.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - -exports.openRowDisabled = new arb() - .addComponents( - new button() - .setCustomId("OTcloseTicket") - .setDisabled(true) - .setStyle(bs.Secondary) - .setLabel(l.buttons.close) - .setEmoji("🔒") - ) - .addComponents( - new button() - .setCustomId("OTdeleteTicket") - .setDisabled(true) - .setStyle(bs.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) \ No newline at end of file diff --git a/core/interactionHandlers/buttons/firstmsg.js b/core/interactionHandlers/buttons/firstmsg.js deleted file mode 100644 index a903975..0000000 --- a/core/interactionHandlers/buttons/firstmsg.js +++ /dev/null @@ -1,119 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const hiddendata = bot.hiddenData -const embed = discord.EmbedBuilder -const mc = config.color - -const button = discord.ButtonBuilder -const arb = discord.ActionRowBuilder -const bs = discord.ButtonStyle - - -exports.firstmsgRowNormal = new arb() - .addComponents( - new button() - .setCustomId("OTclaimTicket") - .setDisabled(false) - .setStyle(bs.Success) - .setLabel("Claim Ticket") - .setEmoji("📌") - ) - .addComponents( - new button() - .setCustomId("OTcloseTicket") - .setDisabled(false) - .setStyle(bs.Secondary) - .setLabel(l.buttons.close) - .setEmoji("🔒") - ) - .addComponents( - new button() - .setCustomId("OTdeleteTicket") - .setDisabled(false) - .setStyle(bs.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - -exports.firstmsgRowDisabled = new arb() - .addComponents( - new button() - .setCustomId("OTclaimTicket") - .setDisabled(false) - .setStyle(bs.Success) - .setLabel("Claim Ticket") - .setEmoji("📌") - ) - .addComponents( - new button() - .setCustomId("OTcloseTicket") - .setDisabled(true) - .setStyle(bs.Secondary) - .setLabel(l.buttons.close) - .setEmoji("🔒") - ) - .addComponents( - new button() - .setCustomId("OTdeleteTicket") - .setDisabled(true) - .setStyle(bs.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - -exports.firstmsgRowNormalNoClaim = new arb() - .addComponents( - new button() - .setCustomId("OTclaimTicket") - .setDisabled(true) - .setStyle(bs.Secondary) - .setLabel("Claim Ticket") - .setEmoji("📌") - ) - .addComponents( - new button() - .setCustomId("OTcloseTicket") - .setDisabled(false) - .setStyle(bs.Secondary) - .setLabel(l.buttons.close) - .setEmoji("🔒") - ) - .addComponents( - new button() - .setCustomId("OTdeleteTicket") - .setDisabled(false) - .setStyle(bs.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - -exports.firstmsgRowDisabledNoClaim = new arb() - .addComponents( - new button() - .setCustomId("OTclaimTicket") - .setDisabled(true) - .setStyle(bs.Secondary) - .setLabel("Claim Ticket") - .setEmoji("📌") - ) - .addComponents( - new button() - .setCustomId("OTcloseTicket") - .setDisabled(true) - .setStyle(bs.Secondary) - .setLabel(l.buttons.close) - .setEmoji("🔒") - ) - .addComponents( - new button() - .setCustomId("OTdeleteTicket") - .setDisabled(true) - .setStyle(bs.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) \ No newline at end of file diff --git a/core/interactionHandlers/buttons/verifyBars.js b/core/interactionHandlers/buttons/verifyBars.js deleted file mode 100644 index fdd911c..0000000 --- a/core/interactionHandlers/buttons/verifyBars.js +++ /dev/null @@ -1,71 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - - -const hiddendata = bot.hiddenData -const embed = discord.EmbedBuilder -const mc = config.color - -const button = discord.ButtonBuilder -const arb = discord.ActionRowBuilder -const bs = discord.ButtonStyle - -exports.closeVerifyBar = new arb() - .addComponents( - new button() - .setCustomId("OTcloseTicketReason") - .setDisabled(false) - .setStyle(bs.Primary) - .setEmoji("💬") - .setLabel(l.buttons.closeWithReason) - ) - .addComponents( - new button() - .setCustomId("OTcloseTicketTrue") - .setDisabled(false) - .setStyle(bs.Secondary) - .setEmoji("✅") - ) - .addComponents( - new button() - .setCustomId("OTcloseTicketFalse") - .setDisabled(false) - .setStyle(bs.Secondary) - .setEmoji("❌") - ) - -exports.deleteVerifyBar = new arb() - .addComponents( - new button() - .setCustomId("OTdeleteTicketTrue") - .setDisabled(false) - .setStyle(bs.Secondary) - .setEmoji("✅") - ) - .addComponents( - new button() - .setCustomId("OTdeleteTicketFalse") - .setDisabled(false) - .setStyle(bs.Secondary) - .setEmoji("❌") - ) - -exports.delete1VerifyBar = new arb() - .addComponents( - new button() - .setCustomId("OTdeleteTicketTrue1") - .setDisabled(false) - .setStyle(bs.Secondary) - .setEmoji("✅") - ) - .addComponents( - new button() - .setCustomId("OTdeleteTicketFalse1") - .setDisabled(false) - .setStyle(bs.Secondary) - .setEmoji("❌") - ) \ No newline at end of file diff --git a/core/interactionHandlers/embeds/commands.js b/core/interactionHandlers/embeds/commands.js deleted file mode 100644 index 01985b8..0000000 --- a/core/interactionHandlers/embeds/commands.js +++ /dev/null @@ -1,144 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const hiddendata = bot.hiddenData -const embed = discord.EmbedBuilder -const mc = config.color - -/** - * - * @param {discord.User} addedUser - * @param {discord.User} adder - * @returns {discord.EmbedBuilder} - */ -exports.addEmbed = (addedUser,adder) => { - return new embed() - .setTitle("⬆️ "+l.commands.userAddedTitle.replace("{0}",addedUser.username)) - .setColor(mc) - .setFooter({text:adder.username,iconURL:adder.displayAvatarURL()}) - .setThumbnail(addedUser.displayAvatarURL({extension:"png"})) -} - -/** - * - * @param {discord.User} removedUser - * @param {discord.User} remover - * @returns {discord.EmbedBuilder} - */ -exports.removeEmbed = (removedUser,remover) => { - return new embed() - .setTitle("⬇️ "+l.commands.userRemovedTitle.replace("{0}",removedUser.username)) - .setColor(mc) - .setFooter({text:remover.username,iconURL:remover.displayAvatarURL()}) - .setThumbnail(removedUser.displayAvatarURL({extension:"png"})) -} - -/** - * - * @param {discord.User} closer - * @param {String} description - * @returns {discord.EmbedBuilder} - */ -exports.closeEmbed = (closer,description) => { - const embd = new embed() - .setTitle("🔒 "+l.commands.closeTitle) - .setColor(mc) - .setFooter({text:closer.username,iconURL:closer.displayAvatarURL()}) - - if (description) embd.setDescription(description) - return embd -} - -/** - * - * @param {discord.User} closer - * @param {Number} time - * @returns {discord.EmbedBuilder} - */ -exports.autocloseSignalEmbed = (closer,time) => { - const embd = new embed() - .setTitle("⏰ This ticket got closed by Autoclose!") - .setColor(mc) - .setFooter({text:closer.username,iconURL:closer.displayAvatarURL()}) - .setDescription("This ticket has been inactive for `"+time+"h`!") - return embd -} - -/** - * - * @param {discord.User} deleter - * @returns {discord.EmbedBuilder} - */ -exports.deleteEmbed = (deleter) => { - return new embed() - .setTitle("❌ "+l.commands.deleteTitle) - .setColor(mc) - .setFooter({text:deleter.username,iconURL:deleter.displayAvatarURL()}) -} - -/** - * - * @param {discord.User} renamer - * @param {String} newname - * @returns {discord.EmbedBuilder} - */ -exports.renameEmbed = (renamer,newname) => { - return new embed() - .setTitle("🔄 "+l.commands.renameTitle.replace("{0}",newname)) - .setColor(mc) - .setFooter({text:renamer.username,iconURL:renamer.displayAvatarURL()}) -} - -/** - * - * @param {discord.User} reopener - * @returns {discord.EmbedBuilder} - */ - exports.reopenEmbed = (reopener) => { - return new embed() - .setTitle("🔓 "+l.commands.reopenTitle) - .setColor(mc) - .setFooter({text:reopener.username,iconURL:reopener.displayAvatarURL()}) -} - -/** - * - * @param {discord.User} claimer - * @param {discord.User} user - * @returns {discord.EmbedBuilder} - */ - exports.claimEmbed = (claimer,user) => { - return new embed() - .setTitle("📌 "+l.commands.claimTitle.replace("{0}",claimer.username)) - .setColor(mc) - .setFooter({text:user.username,iconURL:user.displayAvatarURL()}) -} - -/** - * - * @param {discord.User} unclaimer - * @returns {discord.EmbedBuilder} - */ - exports.unclaimEmbed = (unclaimer) => { - return new embed() - .setTitle("🆓 "+l.commands.unclaimTitle) - .setColor(mc) - .setFooter({text:unclaimer.username,iconURL:unclaimer.displayAvatarURL()}) -} - -/** - * - * @param {discord.User} changer - * @param {String} newtype - * @returns {discord.EmbedBuilder} - */ -exports.changeEmbed = (changer,newtype) => { - return new embed() - .setTitle("🔄 "+l.commands.changeTitle.replace("{0}",newtype)) - .setColor(mc) - .setFooter({text:changer.username,iconURL:changer.displayAvatarURL()}) -} \ No newline at end of file diff --git a/core/interactionHandlers/handlers/accepted/claiming.js b/core/interactionHandlers/handlers/accepted/claiming.js deleted file mode 100644 index a9a40f9..0000000 --- a/core/interactionHandlers/handlers/accepted/claiming.js +++ /dev/null @@ -1,60 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const permissionChecker = require("../../../utils/permisssionChecker") -const storage = bot.storage -const embed = discord.EmbedBuilder -const mc = config.color -const permsChecker = require("../../../utils/permisssionChecker") - -const button = discord.ButtonBuilder -const arb = discord.ActionRowBuilder -const bs = discord.ButtonStyle - -module.exports = () => { - //CLAIM - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTclaimTicket") return - - try { - await interaction.deferUpdate() - }catch{} - - if (!interaction.guild) return - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permsChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - permsChecker.sendUserNoPerms(interaction.user) - return - } - - hiddendata.push({key:"claimedby",value:interaction.user.id}) - bot.hiddenData.writeHiddenData(interaction.channel.id,hiddendata) - storage.set("claimData",interaction.channel.id,interaction.user.id) - - interaction.channel.messages.fetchPinned().then(msglist => { - /**@type {discord.Message} */ - var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) - - const newEmbed = new embed(firstmsg.embeds[0].data) - .setFooter({text:"claimed by: "+interaction.user.username,iconURL:interaction.user.displayAvatarURL()}) - - if (firstmsg.components[0].components[1] && firstmsg.components[0].components[1].disabled){ - firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabledNoClaim],embeds:[newEmbed]}) - }else{ - firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowNormalNoClaim],embeds:[newEmbed]}) - } - - interaction.channel.send({embeds:[bot.embeds.commands.claimEmbed(interaction.user,interaction.user)]}) - }) - }) -} \ No newline at end of file diff --git a/core/interactionHandlers/handlers/accepted/closing.js b/core/interactionHandlers/handlers/accepted/closing.js deleted file mode 100644 index 6bc4cc8..0000000 --- a/core/interactionHandlers/handlers/accepted/closing.js +++ /dev/null @@ -1,76 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const permissionChecker = require("../../../utils/permisssionChecker") -const storage = bot.storage -const hiddendata = bot.hiddenData -const embed = discord.EmbedBuilder -const mc = config.color - -const button = discord.ButtonBuilder -const arb = discord.ActionRowBuilder -const bs = discord.ButtonStyle - -module.exports = () => { - //CLOSE - var closeTicketButtonChecker = false - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTcloseTicketTrue") return - - try { - await interaction.deferUpdate() - } catch{} - - if (closeTicketButtonChecker == true) return - closeTicketButtonChecker = true - - const firstcomponents = interaction.message.components - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (config.system.closeMode == "adminonly"){ - if (!permissionChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - if (!permissionChecker.sendUserNoPerms(interaction.user)){ - permissionChecker.sendChannelNoPerms(interaction.channel,interaction.user) - } - interaction.message.edit({components:firstcomponents}) - closeTicketButtonChecker = false - return - } - } - if (interaction.message.pinned && interaction.message.author.id == client.user.id){ - const claimdata = storage.get("claimData",interaction.channel.id) - if (claimdata && claimdata != "false"){ - interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabledNoClaim]}) - }else{ - interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabled]}) - } - }else{ - interaction.message.edit({components:[bot.buttons.close.openRowDisabled]}) - } - - - /** - * @type {String} - */ - const name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - interaction.channel.send({embeds:[bot.embeds.commands.closeEmbed(interaction.user)],components:[bot.buttons.close.closeCommandRow]}) - await require("../../../ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"close",false,true) - closeTicketButtonChecker = false - }) -} \ No newline at end of file diff --git a/core/interactionHandlers/handlers/accepted/closingReason.js b/core/interactionHandlers/handlers/accepted/closingReason.js deleted file mode 100644 index 5b149e3..0000000 --- a/core/interactionHandlers/handlers/accepted/closingReason.js +++ /dev/null @@ -1,103 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const permissionChecker = require("../../../utils/permisssionChecker") -const storage = bot.storage -const hiddendata = bot.hiddenData -const embed = discord.EmbedBuilder -const mc = config.color - -const button = discord.ButtonBuilder -const arb = discord.ActionRowBuilder -const bs = discord.ButtonStyle - -const modal = discord.ModalBuilder -const tis = discord.TextInputStyle -const tib = discord.TextInputBuilder - -module.exports = () => { - //theModal - const reasonModal = new modal() - .setTitle(l.buttons.closeWithReason) - .setCustomId("OTCloseReasonModal") - - const reasonInput = new arb() - .addComponents([ - new tib() - .setCustomId('OTreasonInput') - .setLabel(l.messages.modalreason) - .setStyle(tis.Short) - .setMaxLength(100) - .setRequired(true) - .setValue("") - .setPlaceholder("reason") - ]) - - reasonModal.addComponents(reasonInput) - - - - - - - //CLOSE WITH REASON - var closeTicketButtonChecker = false - - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTcloseTicketReason") return - - if (closeTicketButtonChecker == true) return interaction.deferUpdate() - closeTicketButtonChecker = true - - const firstcomponents = interaction.message.components - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (config.system.closeMode == "adminonly"){ - if (!permissionChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - if (!permissionChecker.sendUserNoPerms(interaction.user)){ - permissionChecker.sendChannelNoPerms(interaction.channel,interaction.user) - } - interaction.message.edit({components:firstcomponents}) - closeTicketButtonChecker = false - return interaction.deferUpdate() - } - } - - interaction.message.edit({components:[bot.buttons.close.openRowDisabled]}) - await interaction.showModal(reasonModal) - - }) - - client.on("interactionCreate",async (interaction) => { - if (interaction.type != discord.InteractionType.ModalSubmit) return - if (interaction.customId != "OTCloseReasonModal") return - - interaction.reply({embeds:[bot.embeds.commands.closeEmbed(interaction.user)],components:[bot.buttons.close.closeCommandRow]}) - - const reason = interaction.fields.getTextInputValue("OTreasonInput") - - /** - * @type {String} - */ - const name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - //interaction.channel.send({embeds:[bot.embeds.commands.closeEmbed(interaction.user)],components:[bot.buttons.close.closeCommandRow]}) - await require("../../../ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"close",reason,true) - closeTicketButtonChecker = false - }) -} \ No newline at end of file diff --git a/core/interactionHandlers/handlers/accepted/deleting.js b/core/interactionHandlers/handlers/accepted/deleting.js deleted file mode 100644 index 3b57f8a..0000000 --- a/core/interactionHandlers/handlers/accepted/deleting.js +++ /dev/null @@ -1,107 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const permissionChecker = require("../../../utils/permisssionChecker") -const storage = bot.storage -const hiddendata = bot.hiddenData -const embed = discord.EmbedBuilder -const mc = config.color - -const button = discord.ButtonBuilder -const arb = discord.ActionRowBuilder -const bs = discord.ButtonStyle - -module.exports = () => { - //DELETE - var deleteTicketButtonChecker = false - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTdeleteTicketTrue") return - - await interaction.deferUpdate() - - if (deleteTicketButtonChecker == true) return - deleteTicketButtonChecker = true - - const firstcomponents = bot.buttons.close.openRowNormal - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permissionChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - if (!permissionChecker.sendUserNoDelete(interaction.user)){ - permissionChecker.sendChannelNoDelete(interaction.channel,interaction.user) - } - await interaction.message.edit({components:[firstcomponents]}) - deleteTicketButtonChecker = false - return - } - - /** - * @type {String} - */ - const name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - await interaction.message.edit({components:[bot.buttons.close.openRowDisabled]}) - await interaction.channel.send({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]}) - await require("../../../ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"delete",false,true) - deleteTicketButtonChecker = false - }) - - //DELETE NO TRANSCRIPT - var deleteTicketButtonChecker1 = false - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTdeleteTicketTrue1") return - - await interaction.deferUpdate() - - if (deleteTicketButtonChecker1 == true) return - deleteTicketButtonChecker1 = true - - const firstcomponents = bot.buttons.close.closeCommandRow - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (!permissionChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - if (!permissionChecker.sendUserNoDelete(interaction.user)){ - permissionChecker.sendChannelNoDelete(interaction.channel,interaction.user) - } - await interaction.message.edit({components:[firstcomponents]}) - deleteTicketButtonChecker1 = false - return - } - - /** - * @type {String} - */ - const name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - await interaction.message.edit({components:[bot.buttons.close.closeCommandRowDisabled]}) - await interaction.channel.send({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]}) - await require("../../../ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"delete",false,true) - deleteTicketButtonChecker1 = false - - }) -} \ No newline at end of file diff --git a/core/interactionHandlers/handlers/accepted/reopening.js b/core/interactionHandlers/handlers/accepted/reopening.js deleted file mode 100644 index 45959a5..0000000 --- a/core/interactionHandlers/handlers/accepted/reopening.js +++ /dev/null @@ -1,41 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const permissionChecker = require("../../../utils/permisssionChecker") -const storage = bot.storage -const hiddendata = bot.hiddenData -const embed = discord.EmbedBuilder -const mc = config.color - -const button = discord.ButtonBuilder -const arb = discord.ActionRowBuilder -const bs = discord.ButtonStyle - -module.exports = () => { - //REOPEN - client.on("interactionCreate",async (interaction) => { - if (!interaction.isButton()) return - if (interaction.customId != "OTreopenTicket") return - - const hiddendata = bot.hiddenData.readHiddenData(interaction.channel.id) - if (hiddendata.length < 1) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - - if (config.system.closeMode == "adminonly"){ - if (!permissionChecker.ticket(interaction.user.id,interaction.guild.id,ticketId)){ - if (!permissionChecker.sendUserNoPerms(interaction.user)){ - permissionChecker.sendChannelNoPerms(interaction.channel,interaction.user) - } - return interaction.deferUpdate() - } - } - - await interaction.deferUpdate() - interaction.message.edit({embeds:[bot.embeds.commands.reopenEmbed(interaction.user)],components:[bot.buttons.close.openRowNormal]}) - require("../../../ticketActions/ticketReopener").reopenTicket(interaction.guild,interaction.channel,interaction.user,ticketId) - }) -} \ No newline at end of file diff --git a/core/interactionHandlers/handlers/firstmsg.js b/core/interactionHandlers/handlers/firstmsg.js deleted file mode 100644 index 2235f4a..0000000 --- a/core/interactionHandlers/handlers/firstmsg.js +++ /dev/null @@ -1,20 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const storage = bot.storage -const hiddendata = bot.hiddenData -const embed = discord.EmbedBuilder -const mc = config.color - -const button = discord.ButtonBuilder -const arb = discord.ActionRowBuilder -const bs = discord.ButtonStyle - - -module.exports = () => { - -} \ No newline at end of file diff --git a/core/interactionHandlers/handlers/handlers.js b/core/interactionHandlers/handlers/handlers.js deleted file mode 100644 index da7dc3c..0000000 --- a/core/interactionHandlers/handlers/handlers.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = () => { - require("./firstmsg")() - require("./verifyBars")() - - //accepted - require("./accepted/closing")() - require("./accepted/reopening")() - require("./accepted/deleting")() - require("./accepted/closingReason")() - require("./accepted/claiming")() -} \ No newline at end of file diff --git a/core/interactionHandlers/handlers/verifyBars.js b/core/interactionHandlers/handlers/verifyBars.js deleted file mode 100644 index 902c8d5..0000000 --- a/core/interactionHandlers/handlers/verifyBars.js +++ /dev/null @@ -1,100 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const storage = bot.storage -const hiddendata = bot.hiddenData -const embed = discord.EmbedBuilder -const mc = config.color - -const button = discord.ButtonBuilder -const arb = discord.ActionRowBuilder -const bs = discord.ButtonStyle - -module.exports = () => { - //CLOSE - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTcloseTicket") return - - try { - await interaction.deferUpdate() - } catch{} - interaction.message.edit({components:[bot.buttons.verifybars.closeVerifyBar]}) - - }) - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTcloseTicketFalse") return - - try { - await interaction.deferUpdate() - } catch{} - - if (interaction.message.pinned && interaction.message.author.id == client.user.id){ - const claimdata = storage.get("claimData",interaction.channel.id) - if (claimdata && claimdata != "false"){ - interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowNormalNoClaim]}) - }else{ - interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowNormal]}) - } - }else{ - interaction.message.edit({components:[bot.buttons.close.openRowNormal]}) - } - }) - - //DELETE - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTdeleteTicket") return - - try { - await interaction.deferUpdate() - } catch{} - interaction.message.edit({components:[bot.buttons.verifybars.deleteVerifyBar]}) - - }) - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTdeleteTicketFalse") return - - try { - await interaction.deferUpdate() - } catch{} - - if (interaction.message.pinned && interaction.message.author.id == client.user.id){ - const claimdata = storage.get("claimData",interaction.channel.id) - if (claimdata && claimdata != "false"){ - interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowNormalNoClaim]}) - }else{ - interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowNormal]}) - } - }else{ - interaction.message.edit({components:[bot.buttons.close.openRowNormal]}) - } - }) - - //DELETE NO TRANSCRIPT - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTdeleteTicket1") return - - try { - await interaction.deferUpdate() - } catch{} - interaction.message.edit({components:[bot.buttons.verifybars.delete1VerifyBar]}) - - }) - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "OTdeleteTicketFalse1") return - - try { - await interaction.deferUpdate() - } catch{} - interaction.message.edit({components:[bot.buttons.close.closeCommandRow]}) - }) -} \ No newline at end of file diff --git a/core/languageManager.js b/core/languageManager.js deleted file mode 100644 index 77d5e4f..0000000 --- a/core/languageManager.js +++ /dev/null @@ -1,39 +0,0 @@ -const index = require("../index") - -if (index.developerConfig){ - var config = require("../devconfig.json") -}else{var config = require("../config.json")} - -var localLanguage = require("../language/english.json") -const fs = require("fs") -const lfexists = fs.existsSync("./language/"+config.languageFile+".json") -if (lfexists) localLanguage = require("../language/"+config.languageFile+".json") - -const errorLog = async () => { - const chalk = await (await import("chalk")).default - - require("./startscreen").headerDataLanguage("Something went wrong when loading the language!",true) -} - -const successLog = async (language) => { - const chalk = await (await import("chalk")).default - - require("./startscreen").headerDataLanguage("sucessfully loaded language "+language,false) - index.actionRecorder.push({ - category:"ot.managers.language", - file:"./core/languageManager.js", - time:new Date().getTime(), - type:"language.success" - }) -} - -if (!localLanguage){ - const runError = async () => { - await errorLog() - process.exit(1) - } - runError() -}else{ - exports.language = localLanguage - successLog(config.languageFile) -} \ No newline at end of file diff --git a/core/logo.txt b/core/logo.txt deleted file mode 100644 index 2a9c369..0000000 --- a/core/logo.txt +++ /dev/null @@ -1,7 +0,0 @@ - - ██████╗ ██████╗ ███████╗███╗ ██╗ ████████╗██╗ ██████╗██╗ ██╗███████╗████████╗ -██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝ -██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ ██║██║ █████╔╝ █████╗ ██║ -██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██╔═██╗ ██╔══╝ ██║ -╚██████╔╝██║ ███████╗██║ ╚████║ ██║ ██║╚██████╗██║ ██╗███████╗ ██║ - ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ \ No newline at end of file diff --git a/core/reactionRoles.js b/core/reactionRoles.js deleted file mode 100644 index 56864bf..0000000 --- a/core/reactionRoles.js +++ /dev/null @@ -1,104 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const storage = bot.storage - -const APIEvents = require("./api/modules/events") - -module.exports = async () => { - const chalk = await (await import("chalk")).default - - client.on("interactionCreate",async (interaction) => { - if (!interaction.isButton() && !interaction.isStringSelectMenu()) return - if (interaction.isButton() && !interaction.customId.startsWith("newR")) return - if (interaction.isStringSelectMenu() && !(interaction.customId == "OTdropdownMenu")) return - - bot.actionRecorder.push({ - category:"ot.managers.reactionroles", - file:"./core/reactionRoles.js", - time:new Date().getTime(), - type:"reactionRoles.interactionCreated" - }) - - - const optionidRaw = interaction.isStringSelectMenu() ? interaction.values[0] : interaction.customId - if (!optionidRaw.includes("newR")) return - const optionid = optionidRaw.split("newR")[1] - if (!optionid){ - interaction.reply({embeds:[bot.errorLog.serverError(l.errors.roleDoesntExist)]}) - return - }else{ - try { - await interaction.deferUpdate() - } catch{} - } - - try { - - const option = require("./utils/getButton").getOption(optionid) - /**@type {"add"|"remove"|"add&remove"} */ - const mode = option.mode - const user = interaction.member - - if (mode == "add"){ - bot.actionRecorder.push({ - category:"ot.managers.reactionroles", - file:"./core/reactionRoles.js", - time:new Date().getTime(), - type:"reactionRoles.type.add" - }) - option.roles.forEach((role) => { - interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role) - - log("system","added role (reaction roles)",[{key:"user",value:interaction.user.username},{key:"role",value:role}]) - const apirole = interaction.guild.roles.cache.find(r => r.id == role) - APIEvents.onReactionRole("add","add",apirole,interaction.user,interaction.channel,interaction.guild,new Date()) - }) - - }else if (mode == "remove"){ - bot.actionRecorder.push({ - category:"ot.managers.reactionroles", - file:"./core/reactionRoles.js", - time:new Date().getTime(), - type:"reactionRoles.type.remove" - }) - option.roles.forEach((role) => { - interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role) - - log("system","removed role (reaction roles)",[{key:"user",value:interaction.user.username},{key:"role",value:role}]) - const apirole = interaction.guild.roles.cache.find(r => r.id == role) - APIEvents.onReactionRole("remove","remove",apirole,interaction.user,interaction.channel,interaction.guild,new Date()) - }) - - }else if (mode == "add&remove"){ - bot.actionRecorder.push({ - category:"ot.managers.reactionroles", - file:"./core/reactionRoles.js", - time:new Date().getTime(), - type:"reactionRoles.type.add&remove" - }) - option.roles.forEach((role) => { - if (!interaction.guild.members.cache.find(u => u.id == user.id).roles.cache.has(role)){ - interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role) - - log("system","added role (reaction roles)",[{key:"user",value:interaction.user.username},{key:"role",value:role}]) - const apirole = interaction.guild.roles.cache.find(r => r.id == role) - APIEvents.onReactionRole("add","add&remove",apirole,interaction.user,interaction.channel,interaction.guild,new Date()) - }else { - interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role) - - log("system","removed role (reaction roles)",[{key:"user",value:interaction.user.username},{key:"role",value:role}]) - const apirole = interaction.guild.roles.cache.find(r => r.id == role) - APIEvents.onReactionRole("remove","add&remove",apirole,interaction.user,interaction.channel,interaction.guild,new Date()) - } - }) - } - - }catch{ - interaction.channel.send({embeds:[bot.errorLog.serverError(l.errors.somethingWentWrong)]}) - } - }) -} \ No newline at end of file diff --git a/core/slashSystem/autoSlashUpdate.js b/core/slashSystem/autoSlashUpdate.js deleted file mode 100644 index 27614b7..0000000 --- a/core/slashSystem/autoSlashUpdate.js +++ /dev/null @@ -1,87 +0,0 @@ -const discord = require("discord.js") -const bot = require("../../index") -const client = require("../../index").client -const config = bot.config -const configParser = require("../utils/configParser") - -const act = discord.ApplicationCommandType -const acot = discord.ApplicationCommandOptionType - -module.exports = async () => { - const sid = config.serverId - - const ids = configParser.getTicketValuesArray("id") - /**@type {[{name:String,value:String}]} */ - var choices = [] - ids.forEach((id) => { - const option = configParser.getTicketById(id) - if (option){ - choices.push({name:option.name,value:option.id}) - } - }) - - /**@type {[{name:String,value:String}]} */ - var msgchoices = [] - config.messages.forEach((msg) => { - msgchoices.push({name:msg.id,value:msg.id}) - }) - - //slashtranslation - const ST = require("../../language/slashcmds/slash.json").data - - //create a ticket (/new or /ticket) - client.application.commands.create({ - name:"ticket", - description:"Create a ticket!", - descriptionLocalizations:ST.newticket, - defaultPermission:true, - type:act.ChatInput, - options:[ - { - type:acot.String, - name:"type", - description:"The type of ticket.", - required:true, - choices:choices - } - ] - },sid) - - client.application.commands.create({ - name:"new", - description:"Create a ticket!", - defaultPermission:true, - type:act.ChatInput, - descriptionLocalizations:ST.newticket, - options:[ - { - type:acot.String, - name:"type", - description:"The type of ticket.", - required:true, - choices:choices - - } - ] - },sid) - - //msg - client.application.commands.create({ - name:"message", - description:"Create a ticket message.", - defaultPermission:true, - descriptionLocalizations:ST.message, - type:act.ChatInput, - options:[ - { - type:acot.String, - name:"id", - description:"The message id.", - required:true, - choices:msgchoices, - max_length:30 - - } - ] - },sid) -} \ No newline at end of file diff --git a/core/slashSystem/slashDisable.js b/core/slashSystem/slashDisable.js deleted file mode 100644 index 82018a0..0000000 --- a/core/slashSystem/slashDisable.js +++ /dev/null @@ -1,23 +0,0 @@ -const discord = require("discord.js") -const bot = require("../../index") -const client = require("../../index").client -const config = bot.config - -module.exports = async () => { - const chalk = (await import("chalk")).default - - console.log(chalk.red("\nINSTRUCTIONS:\n\n1: Run the command you want to delete in discord.\n2: You get the message 'This command is now deleted!'\n3: There is also a message in the console that says the command is deleted.\n4: reload your discord.")) - client.on("interactionCreate",(interaction) => { - if (!interaction.isChatInputCommand()) return console.log("this isn't a command!") - - interaction.reply({content:"This command is now deleted!"}) - - try { - client.application.commands.delete(interaction.commandId,interaction.guild.id).then(() => { - console.log("deleted the command",chalk.blue(interaction.commandName),"(id:",interaction.commandId+")") - }) - }catch{ - console.log(chalk.red("something went wrong by the deleting of this command!")) - } - }) -} \ No newline at end of file diff --git a/core/slashSystem/slashEnable.js b/core/slashSystem/slashEnable.js deleted file mode 100644 index 1b3e77a..0000000 --- a/core/slashSystem/slashEnable.js +++ /dev/null @@ -1,305 +0,0 @@ -const discord = require("discord.js") -const bot = require("../../index") -const client = require("../../index").client -const config = bot.config -const configParser = require("../utils/configParser") - -const act = discord.ApplicationCommandType -const acot = discord.ApplicationCommandOptionType - -/**@param {Boolean|undefined} invisible*/ -module.exports = async (invisible) => { - const chalk = (await import("chalk")).default - const sid = config.serverId - - const ids = configParser.getTicketValuesArray("id") - /**@type {[{name:String,value:String}]} */ - var choices = [] - ids.forEach((id) => { - const option = configParser.getTicketById(id) - if (option){ - choices.push({name:option.name,value:option.id}) - } - }) - - /**@type {[{name:String,value:String}]} */ - var msgchoices = [] - config.messages.forEach((msg) => { - msgchoices.push({name:msg.id,value:msg.id}) - }) - - var readystats = 0 - - //process.stdout.write("[status] there are "+chalk.blue("0 out of 10")+" commands ready! (this can take up to 40 seconds)") - if (!invisible){ - setInterval(() => { - if (process.stdout && process.stdout.cursorTo) process.stdout.cursorTo(0) - process.stdout.write("[status] there are "+chalk.blue(readystats+" out of 14")+" commands ready! (this can take up to 40 seconds)") - if (readystats >= 14){ - console.log(chalk.green("\nready!")) - console.log(chalk.blue("you can now start the bot with "+chalk.bgBlue("'npm start'")+"!")) - process.exit(1) - } - },100) - } - - const fs = require("fs") - fs.writeFileSync("./storage/slashcmdEnabled.txt",require("../../package.json").version) - - //slashtranslation - const ST = require("../../language/slashcmds/slash.json").data - - //create a ticket (/new or /ticket) - client.application.commands.create({ - name:"ticket", - description:"Create a ticket!", - descriptionLocalizations:ST.newticket, - defaultPermission:true, - type:act.ChatInput, - options:[ - { - type:acot.String, - name:"type", - description:"The type of ticket.", - required:true, - choices:choices - } - ] - },sid).then(() => { - readystats++ - }) - - client.application.commands.create({ - name:"new", - description:"Create a ticket!", - defaultPermission:true, - type:act.ChatInput, - descriptionLocalizations:ST.newticket, - options:[ - { - type:acot.String, - name:"type", - description:"The type of ticket.", - required:true, - choices:choices - - } - ] - },sid).then(() => { - readystats++ - }) - - //help - client.application.commands.create({ - name:"help", - description:"View the available commands.", - defaultPermission:true, - descriptionLocalizations:ST.help, - type:act.ChatInput - },sid).then(() => { - readystats++ - - }) - - //close - client.application.commands.create({ - name:"close", - description:"Close the current ticket.", - defaultPermission:true, - descriptionLocalizations:ST.close, - type:act.ChatInput, - options:[{ - name:"reason", - type:discord.ApplicationCommandOptionType.String, - required:false, - description:"The reason to close this ticket.", - maxLength:100 - }] - },sid).then(() => { - readystats++ - }) - - //delete - client.application.commands.create({ - name:"delete", - description:"Delete the current ticket.", - defaultPermission:true, - descriptionLocalizations:ST.delete, - type:act.ChatInput - },sid).then(() => { - readystats++ - }) - - //msg - client.application.commands.create({ - name:"message", - description:"Create a ticket message.", - defaultPermission:true, - descriptionLocalizations:ST.message, - type:act.ChatInput, - options:[ - { - type:acot.String, - name:"id", - description:"The message id.", - required:true, - choices:msgchoices, - max_length:30 - - } - ] - },sid).then(() => { - readystats++ - }) - - //add - client.application.commands.create({ - name:"add", - description:"Add people to this ticket.", - defaultPermission:true, - descriptionLocalizations:ST.add, - type:act.ChatInput, - options:[ - { - type:acot.User, - name:"user", - description:"The user to add.", - required:true - } - ] - },sid).then(() => { - readystats++ - }) - - //remove - client.application.commands.create({ - name:"remove", - description:"Remove people from this ticket.", - defaultPermission:true, - descriptionLocalizations:ST.remove, - type:act.ChatInput, - options:[ - { - type:acot.User, - name:"user", - description:"The user to remove.", - required:true - } - ] - },sid).then(() => { - readystats++ - }) - - //rename - client.application.commands.create({ - name:"rename", - description:"Rename this ticket.", - defaultPermission:true, - descriptionLocalizations:ST.rename, - type:act.ChatInput, - options:[ - { - type:acot.String, - name:"name", - description:"The new name (without prefix).", - required:true - } - ] - },sid).then(() => { - readystats++ - }) - - //reopen - client.application.commands.create({ - name:"reopen", - description:"Reopen this ticket.", - defaultPermission:true, - descriptionLocalizations:ST.reopen, - type:act.ChatInput - },sid).then(() => { - readystats++ - }) - - //claim - client.application.commands.create({ - name:"claim", - description:"Claim this ticket / claim it for someone else.", - defaultPermission:true, - type:act.ChatInput, - options:[ - { - name:"user", - type:acot.User, - required:false, - description:"The user to claim for." - } - ] - - },sid).then(() => { - readystats++ - }) - - //unclaim - client.application.commands.create({ - name:"unclaim", - description:"Unclaim this ticket.", - defaultPermission:true, - type:act.ChatInput - },sid).then(() => { - readystats++ - }) - - //category - client.application.commands.create({ - name:"change", - description:"Change ticket type.", - defaultPermission:true, - type:act.ChatInput, - options:[ - { - type:acot.String, - name:"type", - description:"The new ticket type.", - required:true, - choices:choices - } - ] - },sid).then(() => { - readystats++ - }) - - //stats - client.application.commands.create({ - name:"stats", - description:"See bot statistics!", - defaultPermission:true, - type:act.ChatInput, - options:[ - { - type:acot.Subcommand, - name:"global", - description:"See the global bot stats!" - }, - { - type:acot.Subcommand, - name:"ticket", - description:"See the stats of a ticket (use inside of ticket)!" - }, - { - type:acot.Subcommand, - name:"user", - description:"See the stats from a user or yourself!", - options:[ - { - type:acot.User, - name:"user", - required:false, - description:"See the stats from a specific user!" - } - ] - } - ] - },sid).then(() => { - readystats++ - }) -} \ No newline at end of file diff --git a/core/startscreen.js b/core/startscreen.js deleted file mode 100644 index 710aac9..0000000 --- a/core/startscreen.js +++ /dev/null @@ -1,79 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const logo = require("fs").readFileSync("./core/logo.txt").toString() - -/**@param {import('chalk').ChalkInstance} chalk */ -const showFlags = async (chalk) => { - var isFlag = false - if (process.argv.some((v) => v == "--devconfig")) console.log(chalk.blue("[FLAGS] => used dev config instead of normal config")); isFlag = true - if (process.argv.some((v) => v == "--nochecker")) console.log(chalk.blue("[FLAGS] => disabled checker.js")); isFlag = true - if (process.argv.some((v) => v == "--tsoffline")) console.log(chalk.blue("[FLAGS] => offline check for html transcripts disabled!")); isFlag = true - if (process.argv.some((v) => v == "--debug")) console.log(chalk.blue("[FLAGS] => enabled DEBUG mode")); isFlag = true - if (process.argv.some((v) => v == "--noslash")) console.log(chalk.blue("[FLAGS] => slash commands disabled")); isFlag = true - if (process.argv.some((v) => v == "--localstatus")) console.log(chalk.blue("[FLAGS] => using local livestatus.json")); isFlag = true - if (process.argv.some((v) => v == "--noerrorupload")) console.log(chalk.blue("[FLAGS] => not uploading errors to liveStatus")); isFlag = true - - if (!isFlag) console.log(chalk.blue("no flags!")) -} - -exports.run = async () => { - const chalk = await (await import("chalk")).default - console.log(chalk.hex("f8ba00")(logo)) - const version = require("../package.json").version - var headertext = "v"+version+" - Support: https://discord.dj-dj.be - Language: "+config.languageFile - const spaceamount = (84-headertext.length)/2 - var i = 0 - while (i < spaceamount){ - headertext = " "+headertext - i++ - } - console.log(chalk.bold(headertext+"\n")) - console.log(chalk.bold(chalk.underline("FLAGS:"))) - showFlags(chalk) -} - -/** - * @param {import('chalk').ChalkInstance} chalk - * @param {{type:String,text:String,enabled:Boolean}} status - * @param {Boolean} updatingslash - * @param {Boolean} slashmode - * -*/ -exports.headerDataReady = (chalk,status,updatingslash,slashmode) => { - console.log("\n"+chalk.bold(chalk.underline("STARTUP INFO:"))) - if (status.enabled) console.log(chalk.hex("f8ba00")("status: ")+chalk.bold(status.type.toLowerCase())+" "+status.text) - if (slashmode){ - console.log("\n\n"+chalk.red(chalk.underline("STARTING IN SLASH CMD CONFIGURATION MODE!"))) - return - } - console.log(chalk.hex("f8ba00")("updating slash cmds: ")+chalk.bold(updatingslash)) -} - -var languageMSG = "" -var languageErr = false -/** - * @param {String} message - * @param {Boolean} err -*/ -exports.headerDataLanguage = async (message,err) => { - languageMSG = message - languageErr = err -} - -/**@param {{total:Number,error:Number,success:Number}} plugins*/ -exports.headerDataPlugins = async (plugins) => { - const chalk = await (await import("chalk")).default - const lmsg = languageErr ? chalk.red(languageMSG) : languageMSG - console.log(chalk.hex("f8ba00")("language: ")+lmsg) - console.log(chalk.hex("f8ba00")("plugins loaded: ")+chalk.bold(plugins.total+" total ")+"("+plugins.success+"✅ "+plugins.error+"❌)") - - console.log("\n"+chalk.bold(chalk.underline("LIVESTATUS:"))) - await require("./utils/liveStatus").run(plugins) - - console.log("\n"+chalk.bold(chalk.underline("LOGS:"))) -} \ No newline at end of file diff --git a/core/statsManager.js b/core/statsManager.js deleted file mode 100644 index 7a2acf8..0000000 --- a/core/statsManager.js +++ /dev/null @@ -1,383 +0,0 @@ -const { EmbedBuilder, Guild, TextChannel, Message, User } = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const permissionChecker = require("./utils/permisssionChecker") - -/**@typedef {"TICKETS_CREATED"|"TICKETS_CLOSED"|"TICKETS_DELETED"|"TICKETS_REOPENED"|"TICKETS_AUTOCLOSED"|"TRANSCRIPTS_CREATED"|"TIME_SINCE_UPDATE"|"LAST_VERSION"} OTGlobalStatsType */ -/**@typedef {"CREATED_AT"|"CREATED_BY"|"STATUS"} OTTicketStatsType */ -/**@typedef {"TICKETS_CREATED"|"TICKETS_CLOSED"|"TICKETS_DELETED"|"TICKETS_REOPENED"} OTUserStatsType */ -/** - * @callback OTStatsCallback - * @param {Boolean|Number|String|undefined} current - * @returns {Boolean|Number|String|undefined} - */ - - -/** - * @param {OTGlobalStatsType} type - * @param {OTStatsCallback} callback - */ -const updateGlobalStats = (type,callback) => { - const currentstat = bot.statsStorage.get("global",type) - const newstat = callback(currentstat) - if (["string","number","boolean"].includes(typeof newstat)){ - bot.statsStorage.set("global",type,newstat) - } -} - -/** - * @param {OTTicketStatsType} type - * @param {String} id - * @param {OTStatsCallback} callback - */ -const updateTicketStats = (type,id,callback) => { - const currentstat = bot.statsStorage.get("ticket"+id,type) - const newstat = callback(currentstat) - if (["string","number","boolean"].includes(typeof newstat)){ - bot.statsStorage.set("ticket"+id,type,newstat) - } -} - -/** - * @param {OTUserStatsType} type - * @param {String} id - * @param {OTStatsCallback} callback - */ -const updateUserStats = (type,id,callback) => { - const currentstat = bot.statsStorage.get("user"+id,type) - const newstat = callback(currentstat) - if (["string","number","boolean"].includes(typeof newstat)){ - bot.statsStorage.set("user"+id,type,newstat) - } -} - -/** - * - * @param {"global"|"ticket"|"user"} scope - * @param {OTGlobalStatsType|OTTicketStatsType|OTUserStatsType} type - * @param {String} [id] - */ -const removeStats = (scope,type,id) => { - const newScope = (scope == "global") ? scope : scope+id - bot.statsStorage.delete(newScope,type) -} - -/** - * - * @param {"global"|"ticket"|"user"} scope - * @param {OTGlobalStatsType|OTTicketStatsType|OTUserStatsType} type - * @param {String} [id] - */ -const existStats = (scope,type,id) => { - const newScope = (scope == "global") ? scope : scope+id - return (typeof bot.statsStorage.get(newScope,type) == "undefined") ? false : true -} - -/** - * - * @param {"global"|"ticket"|"user"} scope - * @param {OTGlobalStatsType|OTTicketStatsType|OTUserStatsType} type - * @param {String} [id] - */ -const getStats = (scope,type,id) => { - const newScope = (scope == "global") ? scope : scope+id - return bot.statsStorage.get(newScope,type) -} - -const startupStatsManager = () => { - //UPDATE LAST UPDATE DATE - if (!existStats("global","TIME_SINCE_UPDATE")){ - updateGlobalStats("TIME_SINCE_UPDATE",(current) => { - return new Date().getTime() - }) - updateGlobalStats("LAST_VERSION",(current) => { - return (require("../package.json")).version - }) - } - if ((require("../package.json")).version != getStats("global","LAST_VERSION")){ - updateGlobalStats("TIME_SINCE_UPDATE",(current) => { - return new Date().getTime() - }) - updateGlobalStats("LAST_VERSION",(current) => { - return (require("../package.json")).version - }) - } - - //UPDATE THE OTHER STATS - if (!existStats("global","TICKETS_CREATED")){ - updateGlobalStats("TICKETS_CREATED",(current) => { - return 0 - }) - } - if (!existStats("global","TICKETS_CLOSED")){ - updateGlobalStats("TICKETS_CLOSED",(current) => { - return 0 - }) - } - if (!existStats("global","TICKETS_DELETED")){ - updateGlobalStats("TICKETS_DELETED",(current) => { - return 0 - }) - } - if (!existStats("global","TICKETS_AUTOCLOSED")){ - updateGlobalStats("TICKETS_AUTOCLOSED",(current) => { - return 0 - }) - } - if (!existStats("global","TICKETS_REOPENED")){ - updateGlobalStats("TICKETS_REOPENED",(current) => { - return 0 - }) - }if (!existStats("global","TRANSCRIPTS_CREATED")){ - updateGlobalStats("TRANSCRIPTS_CREATED",(current) => { - return 0 - }) - } - - //HANDLE MEMBER LEAVE (clear the database) - client.on("guildMemberRemove",(member) => { - if (existStats("user","TICKETS_CREATED",member.id)){ - removeStats("user","TICKETS_CREATED",member.id) - } - if (existStats("user","TICKETS_CLOSED",member.id)){ - removeStats("user","TICKETS_CLOSED",member.id) - } - if (existStats("user","TICKETS_DELETED",member.id)){ - removeStats("user","TICKETS_DELETED",member.id) - } - if (existStats("user","TICKETS_REOPENED",member.id)){ - removeStats("user","TICKETS_REOPENED",member.id) - } - }) -} - -/** - * @returns {Promise<{startDate:Number, updateDate:Number, version:String, ticketsCreated:Number, ticketsClosed:Number, ticketsDeleted:Number, ticketsReopened:Number, ticketsAutoclosed:Number, transcriptsCreated:Number}>} - */ -const getGlobalStats = async () => { - //live data - const startDate = new Date().getTime() - client.uptime - const version = (require("../package.json")).version - - //saved data - const ticketsCreated = getStats("global","TICKETS_CREATED") - const ticketsClosed = getStats("global","TICKETS_CLOSED") - const ticketsDeleted = getStats("global","TICKETS_DELETED") - const ticketsReopened = getStats("global","TICKETS_REOPENED") - const ticketsAutoclosed = getStats("global","TICKETS_AUTOCLOSED") - const transcriptsCreated = getStats("global","TRANSCRIPTS_CREATED") - const timeSinceUpdate = getStats("global","TIME_SINCE_UPDATE") - - return { - startDate, - updateDate: (typeof timeSinceUpdate == "undefined") ? new Date().getTime() : timeSinceUpdate, - version, - - ticketsCreated: (typeof ticketsCreated == "undefined") ? 0 : ticketsCreated, - ticketsClosed: (typeof ticketsClosed == "undefined") ? 0 : ticketsClosed, - ticketsDeleted: (typeof ticketsDeleted == "undefined") ? 0 : ticketsDeleted, - ticketsReopened: (typeof ticketsReopened == "undefined") ? 0 : ticketsReopened, - ticketsAutoclosed: (typeof ticketsAutoclosed == "undefined") ? 0 : ticketsAutoclosed, - transcriptsCreated: (typeof transcriptsCreated == "undefined") ? 0 : transcriptsCreated, - } -} - -/** - * - * @param {discord.TextChannel} channel - * @param {Number} limit - * @returns {Promise} - */ -const getmessages = async (channel,limit) => { - const final = [] - var lastId = "" - - while (true) { - const options = {limit:100} - if (lastId) options.before = lastId - - const messages = await channel.messages.fetch(options) - messages.forEach(msg => {final.push(msg)}) - lastId = messages.last().id - - if (messages.size != 100 || final >= limit) { - break - } - } - return final -} - -/** - * @param {Guild} guild - * @param {String} channelid - * @returns {Promise<{createdAt:Number, createdBy:String, messageAmount:Number, participants:String[], ticketName:String, status:"open"|"closed"|"reopened"|"autoclosed"}>} - */ -const getTicketStats = async (guild,channelid) => { - //live data - /**@type {TextChannel|undefined} */ - const channel = guild.channels.cache.find((c) => c.id == channelid) - const messageAmount = (channel) ? (await getmessages(channel,5000)).length : 0 - const participants = (channel) ? channel.members.map((m) => "<@"+m.user.id+">") : [] - - //saved data - const createdAt = getStats("ticket","CREATED_AT",channelid) - const status = getStats("ticket","STATUS",channelid) - - const TEMPcreatedBy = getStats("ticket","CREATED_BY",channelid) - const TEMPcreatedByUser = (TEMPcreatedBy) ? guild.members.cache.find((m) => m.id == TEMPcreatedBy) : undefined - const createdBy = (TEMPcreatedByUser) ? "<@"+TEMPcreatedByUser.user.id+">" : "an unknown person 😄" - - return { - createdAt: (typeof createdAt == "undefined") ? new Date().getTime() : createdAt, - createdBy: (typeof createdBy == "undefined") ? 0 : createdBy, - messageAmount, - participants:participants.slice(0,50), - ticketName:channel.name, - status: (typeof status == "undefined") ? "open" : status - } -} - -/** - * @param {Guild} guild - * @param {User} user - * @param {String} [channelid] - * @returns {Promise<{ticketsCreated:Number, ticketsClosed:Number, ticketsDeleted:Number, ticketsReopened:Number, role:"globaladmin"|"ticketadmin"|"member", userName:String}>} - */ -const getUserStats = async (guild,user,channelid) => { - //live data - const hiddendata = bot.hiddenData.readHiddenData(channelid) - const ticketId = (hiddendata.length < 1) ? false : hiddendata.find(d => d.key == "type").value - - const isGlobalAdmin = permissionChecker.global(user.id,guild.id) - const isTicketAdmin = (ticketId) ? permissionChecker.ticket(user.id,guild.id,ticketId) : false - const role = (isGlobalAdmin) ? "globaladmin" : ((isTicketAdmin) ? "ticketadmin" : "member") - - //saved data - const ticketsCreated = getStats("user","TICKETS_CREATED",user.id) - const ticketsClosed = getStats("user","TICKETS_CLOSED",user.id) - const ticketsDeleted = getStats("user","TICKETS_DELETED",user.id) - const ticketsReopened = getStats("user","TICKETS_REOPENED",user.id) - - return { - ticketsCreated: (typeof ticketsCreated == "undefined") ? 0 : ticketsCreated, - ticketsClosed: (typeof ticketsClosed == "undefined") ? 0 : ticketsClosed, - ticketsDeleted: (typeof ticketsDeleted == "undefined") ? 0 : ticketsDeleted, - ticketsReopened: (typeof ticketsReopened == "undefined") ? 0 : ticketsReopened, - role, - userName:user.username - } -} - -const createGlobalStatsEmbed = async () => { - const stats = await getGlobalStats() - - const sentences = [ - `${l.stats.ticketsCreated}: \`${stats.ticketsCreated}\``, - `${l.stats.ticketsClosed}: \`${stats.ticketsClosed}\``, - `${l.stats.ticketsDeleted}: \`${stats.ticketsDeleted}\``, - `${l.stats.ticketsReopened}: \`${stats.ticketsReopened}\``, - `${l.stats.ticketsAutoclosed}: \`${stats.ticketsAutoclosed}\``, - - `${l.stats.startupDate}: `, - `${l.stats.latestUpdate}: ` - ] - - const embed = new EmbedBuilder() - .setColor(config.color) - .setTitle(`📊 ${l.stats.globalTitle}!`) - .setDescription(sentences.slice(0,5).join("\n")) - .addFields({ - name:`${l.stats.systemTitle}:`, - value:sentences.slice(5,7).join("\n") - }) - .setFooter({text:`${l.stats.versionTitle}: v${stats.version}`}) - return embed -} - -/** - * @param {Guild} guild - * @param {String} channelid - */ -const createTicketStatsEmbed = async (guild,channelid) => { - const stats = await getTicketStats(guild,channelid) - - if (stats.status == "open"){ - var newStatus = `🟢 \`${l.stats.switches.open}\`` - }else if (stats.status == "reopened"){ - var newStatus = `🟢 \`${l.stats.switches.reopened}\`` - }else if (stats.status == "closed"){ - var newStatus = `🔴 \`${l.stats.switches.closed}\`` - }else if (stats.status == "autoclosed"){ - var newStatus = `🔴 \`${l.stats.switches.autoclosed}\`` - } - - const sentences = [ - `${l.stats.ticketCreatedOn}: `, - `${l.stats.ticketCreatedBy}: ${stats.createdBy}`, - `${l.stats.messagesSent}: \`${stats.messageAmount}\``, - `${l.stats.status}: ${newStatus}` - ] - - const embed = new EmbedBuilder() - .setColor(config.color) - .setTitle(`📊 ${l.stats.ticketTitle}`.replace("{0}",`#${stats.ticketName}!`)) - .setDescription(sentences.join("\n")) - .addFields({ - name:`${l.stats.participants}:`, - value:stats.participants.join("\n") - }) - return embed -} - -/** - * @param {Guild} guild - * @param {User} user - * @param {String} channelid - */ -const createUserStatsEmbed = async (guild,user,channelid) => { - const stats = await getUserStats(guild,user,channelid) - - if (stats.role == "globaladmin"){ - var newRole = `🟢 \`${l.stats.switches.globalAdmin}\`` - }else if (stats.role == "ticketadmin"){ - var newRole = `🟡 \`${l.stats.switches.ticketAdmin}\`` - }else if (stats.role == "member"){ - var newRole = `🔴 \`${l.stats.switches.member}\`` - } - - const sentences = [ - `${l.stats.role}: ${newRole}`, - `${l.stats.ticketsCreated}: \`${stats.ticketsCreated}\``, - `${l.stats.ticketsClosed}: \`${stats.ticketsClosed}\``, - `${l.stats.ticketsDeleted}: \`${stats.ticketsDeleted}\``, - `${l.stats.ticketsReopened}: \`${stats.ticketsReopened}\`` - ] - - const embed = new EmbedBuilder() - .setColor(config.color) - .setTitle(`📊 ${l.stats.userTitle}`.replace("{0}",`${stats.userName}!`)) - .setDescription(sentences.join("\n")) - return embed -} - -module.exports = { - updateGlobalStats, - updateTicketStats, - updateUserStats, - - removeStats, - existStats, - getStats, - - startupStatsManager, - - getGlobalStats, - getTicketStats, - getUserStats, - createGlobalStatsEmbed, - createTicketStatsEmbed, - createUserStatsEmbed -} \ No newline at end of file diff --git a/core/ticketActions/ticketAutoclose.js b/core/ticketActions/ticketAutoclose.js deleted file mode 100644 index 55678d6..0000000 --- a/core/ticketActions/ticketAutoclose.js +++ /dev/null @@ -1,65 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const storage = bot.storage - -module.exports = () => { - setInterval(async () => { - try{ - const tickets = storage.getCategory("autocloseTickets") - if (!tickets) return - tickets.forEach(async (t) => { - if (t.value == "false" || t.value == 0 || typeof t.value != "number") return - try{ - - const channel = await client.channels.fetch(t.key,{cache:true}) - if (!channel || !channel.isTextBased()) return - - const message = (await channel.messages.fetch({limit:10})).first() - if (!message) return - - const secondsSLM = Math.round((new Date().getTime() - message.createdTimestamp)/1000) - const hoursSLM = secondsSLM/3600 - - if (hoursSLM > t.value){ - /**@type {discord.Guild|false} */ - const guild = client.guilds.cache.find((g) => g.id == channel.guild.id) - if (!guild) return - const clientMember = guild.members.cache.find((m) => m.id == client.user.id) - if (!clientMember) return - - var name = channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - require("./ticketCloser").closeManager(clientMember,channel,prefix,"close","OTautoclose",true) - storage.delete("autocloseTickets",channel.id) - - //STATS - bot.statsManager.updateGlobalStats("TICKETS_AUTOCLOSED",(current) => { - if (typeof current != "undefined") return current+1 - return 1 - }) - bot.statsManager.updateTicketStats("STATUS",channel.id,(current) => { - return "autoclosed" - }) - - channel.send({embeds:[bot.embeds.commands.autocloseSignalEmbed(client.user,t.value)],components:[bot.buttons.close.closeCommandRow]}) - } - - }catch{ - log("system","can't find autoclose channel with ID: "+t.key) - storage.delete("autocloseTickets",t.key) - } - }) - }catch{} - },120000) -} \ No newline at end of file diff --git a/core/ticketActions/ticketCloser.js b/core/ticketActions/ticketCloser.js deleted file mode 100755 index 16d06e5..0000000 --- a/core/ticketActions/ticketCloser.js +++ /dev/null @@ -1,253 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const storage = bot.storage -const permsChecker = require("../utils/permisssionChecker") - -const pendingDelete = [] - -/** - * - * @param {discord.GuildMember} member - * @param {discord.TextChannel} channel - * @param {String} prefix - * @param {"delete"|"close"|"deletenotranscript"} mode - * @param {Boolean} nomessage - * @param {String} reason only when closing, not when deleting! - */ -exports.closeManager = async (member,channel,prefix,mode,reason,nomessage) => { - const guild = channel.guild - const user = member.user - const chalk = await (await import("chalk")).default - - const newReason = reason ? reason : l.messages.none - - //start code - - //FIX CHANNEL COULD BE CLOSED AFTER DELETE: - if (pendingDelete.includes(channel.id)) return false - - /**@type {String}*/ - const channelname = channel.name - const ticketOpenerChannelName = channelname.split(prefix)[1] - - //get user that opened the ticket - var getuserID = storage.get("userFromChannel",channel.id) - try { - var ticketOpener = client.users.cache.find(u => u.id === getuserID) - var isDatabaseError = false - }catch{var isDatabaseError = true} - - if (!ticketOpener){ - console.log(chalk.red("[database error]"),"something went wrong when getting the data in the database.\nNo panic, this error fixes itself!") - var isDatabaseError = true - } - - var enableTranscript = true - var deleteRequired = false - - if (mode == "delete" || mode == "deletenotranscript"){ - //delete - const hiddendata = bot.hiddenData.readHiddenData(channel.id) - if (hiddendata.length < 1) return channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - const ticketData = require("../utils/configParser").getTicketById(ticketId,true) - - //check perms - if (!guild) return - if (!permsChecker.ticket(user.id,guild.id,ticketId)){ - permsChecker.sendUserNoPerms(user) - return - } - - //start delete proccess - deleteRequired = true - if (!nomessage){ - await channel.send({content:"**"+l.messages.gettingdeleted+"**"}) - } - log("system","deleted a ticket",[{key:"user",value:user.username},{key:"ticket",value:channel.name}]) - pendingDelete.push(channel.id) - - if (!isDatabaseError) storage.set("amountOfUserTickets",getuserID,Number(storage.get("amountOfUserTickets",getuserID)) - 1) - storage.delete("userFromChannel",channel.id) - storage.delete("claimData",channel.id) - storage.delete("autocloseTickets",channel.id) - if (Number(storage.get("amountOfUserTickets",getuserID)) < 0) storage.set("amountOfUserTickets",getuserID,0) - - require("../api/modules/events").onTicketDelete(user,channel,guild,new Date(),{name:channel.name,status:"deleted",ticketOptions:ticketData}) - - //STATS - bot.statsManager.updateGlobalStats("TICKETS_DELETED",(current) => { - if (typeof current != "undefined") return current+1 - return 1 - }) - bot.statsManager.updateUserStats("TICKETS_DELETED",user.id,(current) => { - if (typeof current != "undefined") return current+1 - return 1 - }) - bot.statsManager.removeStats("ticket","CREATED_BY",channel.id) - bot.statsManager.removeStats("ticket","CREATED_AT",channel.id) - bot.statsManager.removeStats("ticket","STATUS",channel.id) - - hiddendata.push({key:"pendingdelete",value:"true"}) - bot.hiddenData.writeHiddenData(channel.id,hiddendata) - - }else if (mode == "close"){ - //close - const hiddendata = bot.hiddenData.readHiddenData(channel.id) - if (hiddendata.length < 1) return channel.send({embeds:[bot.errorLog.notInATicket]}) - const ticketId = hiddendata.find(d => d.key == "type").value - const ticketData = require("../utils/configParser").getTicketById(ticketId,true) - - //check perms - if (config.system.closeMode == "adminonly"){ - if (!guild) return - if (!permsChecker.ticket(user.id,guild.id,ticketId)){ - permsChecker.sendUserNoPerms(user) - return - } - } - - //set new permissions - var permissionArray = [] - const pfb = discord.PermissionFlagsBits - - if (!isDatabaseError) permissionArray.push({ - id:ticketOpener, - type:"member", - allow:[pfb.ViewChannel], - deny:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages] - }) - - permissionArray.push({ - id:guild.roles.everyone, - type:"role", - deny:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel] - }) - - //add main adminroles - config.adminRoles.forEach((role,index) => { - try { - const adminrole = guild.roles.cache.find(r => r.id == role) - if (!adminrole) return - - permissionArray.push({ - id:adminrole, - type:"role", - allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel], - deny:[] - }) - }catch{ - log("system","invalid role! At 'config.json => main_adminroles:"+index) - } - }) - - if (!ticketData) return - if (ticketData.closedCategory.enable){ - /**@type {discord.CategoryChannel} */ - const category = guild.channels.cache.find(c => c.id == ticketData.closedCategory.id && c.type == discord.ChannelType.GuildCategory) - try { - channel.setParent(category) - }catch{ - bot.errorLog.log("system","failed to move channel to new category!") - } - } - - ticketData.adminroles.forEach((role,index) => { - if (!config.adminRoles.includes(role)){ - try { - const adminrole = guild.roles.cache.find(r => r.id == role) - if (!adminrole) return - - permissionArray.push({ - id:adminrole, - type:"role", - allow:[pfb.AddReactions,pfb.ViewChannel,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages], - deny:[] - }) - }catch{ - log("system","invalid role! At 'config.json => options/ticket/...:"+index) - } - } - }) - - channel.permissionOverwrites.set(permissionArray) - - if (!nomessage){ - //message - const embed = new discord.EmbedBuilder() - .setColor(config.color) - .setTitle(":lock: "+l.commands.closeTitle+" :lock:") - .setDescription(l.messages.closedDescription) - channel.send({embeds:[embed],components:[bot.buttons.close.closeCommandRow]}) - } - - log("system","closed a ticket",[{key:"user",value:user.username},{key:"ticket",value:channel.name}]) - - - //send api event - require("../api/modules/events").onTicketClose(user,channel,guild,new Date(),{name:channel.name,status:"closed",ticketOptions:ticketData},newReason) - - //STATS - bot.statsManager.updateGlobalStats("TICKETS_CLOSED",(current) => { - if (typeof current != "undefined") return current+1 - return 1 - }) - bot.statsManager.updateUserStats("TICKETS_CLOSED",user.id,(current) => { - if (typeof current != "undefined") return current+1 - return 1 - }) - bot.statsManager.updateTicketStats("STATUS",channel.id,(current) => { - return "closed" - }) - } - - /** - * - * @param {discord.TextChannel} channel - * @param {Number} limit - * @returns {Promise} - */ - const getmessages = async (channel,limit) => { - const final = [] - var lastId = "" - - while (true) { - const options = {limit:100} - if (lastId) options.before = lastId - - const messages = await channel.messages.fetch(options) - messages.forEach(msg => {final.push(msg)}) - lastId = messages.last().id - - if (messages.size != 100 || final >= limit) { - break - } - } - return final - } - - - const transcriptHandler = async () => { - if (!bot.tsconfig.sendTranscripts.enableChannel && !bot.tsconfig.sendTranscripts.enableDM) return false - - const APIEvents = require("../api/modules/events") - const messages = await getmessages(channel,5000) - await require("../transcriptSystem/manager")(messages,guild,channel,user,reason) - APIEvents.onTranscriptCreation(messages,channel,guild,new Date()) - } - const deleteHandler = async () => { - if (deleteRequired){ - pendingDelete.shift() - //delete HIDDENDATA - storage.delete("HIDDENDATA",channel.id) - - await channel.delete() - } - } - if (mode == "delete" || mode == "deletenotranscript") await transcriptHandler() - deleteHandler() -} \ No newline at end of file diff --git a/core/ticketActions/ticketOpener.js b/core/ticketActions/ticketOpener.js deleted file mode 100755 index 8762f2d..0000000 --- a/core/ticketActions/ticketOpener.js +++ /dev/null @@ -1,265 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const l = bot.language -const log = bot.errorLog.log - -const configParser = require("../utils/configParser") -const storage = bot.storage - -module.exports = () => { - //dropdown placeholder - client.on("interactionCreate",async (interaction) => { - if (!interaction.isStringSelectMenu()) return - if (interaction.customId != "OTdropdownMenu") return - if (interaction.values.includes("OTChooseTicket")){ - await interaction.deferUpdate() - } - }) - - - var closeButton = bot.buttons.firstmsg.firstmsgRowNormal - - //ticket button click / create ticket - client.on("interactionCreate",async (interaction) => { - if (interaction.isChatInputCommand() && (interaction.commandName == "new" || interaction.commandName == "ticket")){ - var customId = "OTnewT"+interaction.options.getString("type") - }else if (interaction.isButton()){ - var customId = interaction.customId - }else if (interaction.isStringSelectMenu() && (interaction.customId == "OTdropdownMenu")){ - var customId = interaction.values[0] - - }else return - - if (interaction.isButton()){ - if (interaction.customId.startsWith("OTnewT")){ - const optionid = interaction.customId.split("OTnewT")[1] - if (!optionid){ - await interaction.reply({embeds:[bot.errorLog.serverError(l.errors.ticketDoesntExist)]}) - return - } - } - } - - - if (configParser.getTicketValuesArray("id").includes(customId)){ - - //ticketoptions from config - const currentTicketOptions = configParser.getTicketById(customId) - if (currentTicketOptions == false) return interaction.reply({embeds:[bot.errorLog.serverError(l.errors.anotherOption)]}) - - if (interaction.isButton() || interaction.isStringSelectMenu() || interaction.isChatInputCommand()){ - try{ - await interaction.deferReply({ephemeral:config.system.answerInEphemeralOnOpen}) - }catch{} - } - - const currentUserTicketAmount = storage.get("amountOfUserTickets",interaction.member.id) - if (config.system.maxAmountOfTickets == 0 || !currentUserTicketAmount || currentUserTicketAmount == "false" || Number(currentUserTicketAmount) < config.system.maxAmountOfTickets){ - - //update storage - storage.set("amountOfUserTickets",interaction.member.id,Number(currentUserTicketAmount)+1) - var ticketNumber = interaction.member.user.username - - //set ticketName - var ticketName = currentTicketOptions.channelprefix+ticketNumber - var logsname = currentTicketOptions.name - - //category - if (currentTicketOptions.category.length < 16 || currentTicketOptions.category.length > 20){ - var newTicketCategory = null - }else{ - var newTicketCategory = currentTicketOptions.category - } - - var permissionsArray = [] - const pfb = discord.PermissionFlagsBits - const guild = client.guilds.cache.find(g => g.id == interaction.guild.id) - - //set @everyone no ticket access - permissionsArray.push({ - id:interaction.guild.roles.everyone, - type:"role", - allow:[], - deny:[pfb.ViewChannel] - }) - - //add the user that created the ticket - permissionsArray.push({ - id:interaction.member.user, - type:"member", - allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel,pfb.ReadMessageHistory] - }) - - //add main adminroles - config.adminRoles.forEach((role,index) => { - try { - const adminrole = guild.roles.cache.find(r => r.id == role) - if (!adminrole) return - - permissionsArray.push({ - id:adminrole, - type:"role", - allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel,pfb.ReadMessageHistory] - }) - }catch{} - }) - - //add ticket adminroles - /** - * @type {String[]} - */ - const ticketadmin = currentTicketOptions.adminroles - ticketadmin.forEach((role,index) => { - if (!config.adminRoles.includes(role)){ - try { - const adminrole = guild.roles.cache.find(r => r.id == role) - if (!adminrole) return - - permissionsArray.push({ - id:adminrole, - type:"role", - allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel,pfb.ReadMessageHistory] - }) - }catch{} - } - }) - - //add ticket adminroles - if (currentTicketOptions.readonlyAdminroles){ - currentTicketOptions.readonlyAdminroles.forEach((role,index) => { - if (!config.adminRoles.includes(role) && !currentTicketOptions.adminroles.includes(role)){ - try { - const adminrole = guild.roles.cache.find(r => r.id == role) - if (!adminrole) return - - permissionsArray.push({ - id:adminrole, - type:"role", - allow:[pfb.AddReactions,pfb.ViewChannel,pfb.ReadMessageHistory], - deny:[pfb.SendMessages,pfb.AttachFiles,pfb.EmbedLinks] - }) - }catch{} - } - }) - } - - //add member role - if (config.system.memberRole && ![" ","0","false","null","undefined"].includes(config.system.memberRole)){ - try { - const userrole = guild.roles.cache.find(r => r.id == config.system.memberRole) - if (userrole){ - permissionsArray.push({ - id:userrole, - type:"role", - deny:[pfb.ViewChannel] - }) - } - }catch{} - } - - //create the channel - interaction.guild.channels.create({ - name:ticketName, - type:discord.ChannelType.GuildText, - parent:newTicketCategory, - reason:"A new ticket is created", - permissionOverwrites:permissionsArray - - }).then((ticketChannel) => { - storage.set("userFromChannel",ticketChannel.id,interaction.member.id) - if (currentTicketOptions.autoclose.enable) storage.set("autocloseTickets",ticketChannel.id,currentTicketOptions.autoclose.inactiveHours) - - bot.hiddenData.writeHiddenData(ticketChannel.id,[{key:"type",value:currentTicketOptions.id},{key:"openerid",value:interaction.user.id},{key:"createdms",value:new Date().getTime()}]) - - var ticketEmbed = new discord.EmbedBuilder() - //.setAuthor({name:interaction.user.id}) - .setColor(config.color) - .setTitle(currentTicketOptions.name) - //.setFooter({text:"Ticket Type: "+currentTicketOptions.id}) - if (currentTicketOptions.autoclose.enable){ - const footerText = l.commands.autocloseTitle.replace("{0}",currentTicketOptions.autoclose.inactiveHours+"h") - ticketEmbed.setFooter({text:footerText}) - } - - if (currentTicketOptions.ticketmessage.length > 0){ - ticketEmbed.setDescription(currentTicketOptions.ticketmessage) - } - - if (currentTicketOptions.thumbnail.enable) ticketEmbed.setThumbnail(currentTicketOptions.thumbnail.url) - if (currentTicketOptions.image.enable) ticketEmbed.setImage(currentTicketOptions.image.url) - - const herePing = currentTicketOptions.ping['@here'] ? " @here" : "" - const everyonePing = currentTicketOptions.ping['@everyone'] ? " @everyone" : "" - const customPing = currentTicketOptions.ping.custom.enable ? " <@&"+currentTicketOptions.ping.custom.roleId+">" : "" - - - ticketChannel.send({ - content:"<@"+interaction.member.id+">"+herePing+everyonePing+customPing, - embeds:[ticketEmbed], - components:[closeButton] - - }).then(firstmsg => { - firstmsg.pin() - }) - - log("system","created new ticket",[{key:"ticket",value:ticketName},{key:"user",value:interaction.user.username}]) - require("../api/modules/events").onTicketOpen(interaction.user,ticketChannel,interaction.guild,new Date(),{name:ticketName,status:"open",ticketOptions:currentTicketOptions}) - - //STATS: - bot.statsManager.updateGlobalStats("TICKETS_CREATED",(current) => { - if (typeof current != "undefined") return current+1 - return 1 - }) - bot.statsManager.updateUserStats("TICKETS_CREATED",interaction.user.id,(current) => { - if (typeof current != "undefined") return current+1 - return 1 - }) - bot.statsManager.updateTicketStats("CREATED_BY",ticketChannel.id,(current) => { - return interaction.user.id - }) - bot.statsManager.updateTicketStats("CREATED_AT",ticketChannel.id,(current) => { - return new Date().getTime() - }) - bot.statsManager.updateTicketStats("STATUS",ticketChannel.id,(current) => { - return "open" - }) - - const channelbutton = new discord.ActionRowBuilder() - .addComponents([ - new discord.ButtonBuilder() - .setStyle(discord.ButtonStyle.Link) - .setDisabled(false) - .setEmoji("🎫") - .setLabel(l.commands.goToTicket) - .setURL(ticketChannel.url) - ]) - - try{ - if (currentTicketOptions.enableDmOnOpen) interaction.member.send({embeds:[bot.errorLog.custom(l.messages.newTicketDmTitle,currentTicketOptions.message,":ticket:",config.color)],components:[channelbutton]}) - } - catch{log("system","failed to send DM")} - - if (((interaction.isButton() || interaction.isStringSelectMenu()) && config.system.answerInEphemeralOnOpen) || interaction.isChatInputCommand()){ - if (interaction.deferred || interaction.replied){ - interaction.editReply({embeds:[bot.errorLog.success(l.messages.createdTitle,l.messages.createdDescription)],components:[channelbutton]}) - }else{ - interaction.reply({embeds:[bot.errorLog.success(l.messages.createdTitle,l.messages.createdDescription)],components:[channelbutton]}) - } - } - }) - }else{ - interaction.editReply({embeds:[bot.errorLog.warning(l.errors.maxAmountTitle,l.errors.maxAmountDescription)]}) - try { - if (config.system.dmMessages){ - interaction.member.send({embeds:[bot.errorLog.warning(l.errors.maxAmountTitle,l.errors.maxAmountDescription)]}) - } - } - catch{log("system","can't send DM to member, member doesn't allow dm's")} - - - } - } - }) -} diff --git a/core/ticketActions/ticketReopener.js b/core/ticketActions/ticketReopener.js deleted file mode 100755 index 56052ea..0000000 --- a/core/ticketActions/ticketReopener.js +++ /dev/null @@ -1,77 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const storage = bot.storage -const pfb = discord.PermissionFlagsBits -const permsChecker = require("../utils/permisssionChecker") - -/** - * - * @param {discord.Guild} guild - * @param {discord.TextBasedChannel} channel - * @param {discord.User} user - * @param {String} ticketId option id - * @returns - */ -const reopenTicket = (guild,channel,user,ticketId) => { - //check perms - if (config.system.closeMode == "adminonly"){ - if (!guild) return - if (!permsChecker.ticket(user.id,guild.id,ticketId)){ - permsChecker.sendUserNoPerms(user) - return - } - } - - log("system","re-opened a ticket",[{key:"ticket",value:channel.name},{key:"user",value:user.username}]) - - var permissionsArray = [] - - //set @everyone no ticket access - permissionsArray.push({ - id:guild.roles.everyone, - type:"role", - allow:[], - deny:[pfb.ViewChannel] - }) - - channel.permissionOverwrites.cache.forEach((p) => { - if (p.type == 1){ - permissionsArray.push({ - id:p.id, - type:"member", - allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel], - deny:[] - }) - }else{ - if (p.id != guild.roles.everyone){ - permissionsArray.push({ - id:p.id, - type:"role", - allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel], - deny:[] - }) - } - } - }) - channel.permissionOverwrites.set(permissionsArray) - - require("../api/modules/events").onTicketReopen(user,channel,guild,new Date(),{name:channel.name,status:"reopened",ticketOptions:false}) - - //STATS - bot.statsManager.updateGlobalStats("TICKETS_REOPENED",(current) => { - if (typeof current != "undefined") return current+1 - return 1 - }) - bot.statsManager.updateUserStats("TICKETS_REOPENED",user.id,(current) => { - if (typeof current != "undefined") return current+1 - return 1 - }) - bot.statsManager.updateTicketStats("STATUS",channel.id,(current) => { - return "reopened" - }) -} -exports.reopenTicket = reopenTicket \ No newline at end of file diff --git a/core/transcriptSystem/communication/compileJsonV1.js b/core/transcriptSystem/communication/compileJsonV1.js deleted file mode 100644 index 589f4c4..0000000 --- a/core/transcriptSystem/communication/compileJsonV1.js +++ /dev/null @@ -1,123 +0,0 @@ -const discord = require('discord.js') - -const bot = require("../../../index") -const tsconfig = bot.tsconfig -const tsembeds = require("../embeds") -const tsdb = require("../tsdb") - -const otversion = require("../../../package.json").version -const version = require("../info.json").version - -/**@typedef {{style:{enableCustomBackground:Boolean, backgroundModus:"color"|"image", backgroundData:String, titleColor:String}, bot:{name:String, id:Number, pfp:String}, ticket:{creatorname:String, creatorid:Number, closedtime:Number, openedtime:Number}}} OThtsDataOption */ - - -/**========================================================== -============================================================= -================THIS FILE ISN'T USED ANYMORE!!=============== - This file is for html transcripts V1! - Visit compileJsonV2.js for the current version! -============================================================= -===========================================================*/ - -/** - * - * @param {discord.Guild} guild - * @param {discord.Channel} channel - * @param {discord.User} user - * @param {discord.Message[]} messagesInv - * @param {OThtsDataOption} data - */ -exports.compile = (guild,channel,user,messagesInv,data) => { - const messages = messagesInv.reverse() - var invisibleMessages = 0 - - const rawfiles = messages.filter((m) => Array.from(m.attachments).length > 0) - var fileAmount = 0 - rawfiles.forEach((msg) => { - fileAmount = fileAmount + Array.from(msg.attachments).length - }) - - const messagesArray = [] - messages.forEach((msg) => { - if (msg.content || msg.embeds.length > 0 || msg.attachments.toJSON().length > 0){ - - const embedArray = [] - const fileArray = [] - - msg.attachments.forEach((file) => { - fileArray.push({ - name:file.name, - type:file.contentType, - size:file.size.toString()+" bytes", - url:file.url - }) - }) - - msg.embeds.forEach((embed) => { - embedArray.push({ - title:embed.title || false, - description:embed.description ? embed.description : false, - authorimg:((embed.author && embed.author.iconURL) ? embed.author.iconURL : false), - authortext:(embed.author ? embed.author.name : false), - footerimg:((embed.footer && embed.footer.iconURL) ? embed.footer.iconURL : false), - footertext:(embed.footer ? embed.footer.text : false), - color:embed.hexColor, - image:((embed.image && embed.image.url) ? embed.image.url : false), - thumbnail:((embed.thumbnail && embed.thumbnail.url) ? embed.thumbnail.url : false), - url:(embed.url ? embed.url : false) - }) - }) - - const memberColor = msg.member ? msg.member.displayHexColor : "#ffffff" - messagesArray.push({ - author:{ - name:msg.author.username, - id:Number(msg.author.id), - color:memberColor, - pfp:msg.author.displayAvatarURL() - }, - content:msg.content || "", - timestamp:msg.createdTimestamp, - embeds:embedArray, - files:fileArray - }) - }else {invisibleMessages++} - }) - - const result = { - version,otversion, - style:{ - backgroundData:data.style.backgroundData || "", - backgroundModus:data.style.backgroundModus || "", - enableCustomBackground:data.style.enableCustomBackground || false, - titleColor:data.style.titleColor || "#F8BA00" - }, - bot:{ - name:data.bot.name || "Open Ticket", - id:Number(data.bot.id) || 0, - pfp:data.bot.pfp || "transcripts.dj-dj.be/favicon.png" - }, - ticket:{ - name:channel.name, - id:Number(channel.id), - - guildname:guild.name, - guildid:Number(guild.id), - - creatorname:data.ticket.creatorname, - creatorid:Number(data.ticket.creatorid), - closedbyname:user.username, - closedbyid:Number(user.id), - - closedtime:data.ticket.closedtime, - openedtime:data.ticket.openedtime, - - messages:Array.from(messages).length-invisibleMessages, - files:fileAmount - }, - messages:messagesArray - } - - - return result -} \ No newline at end of file diff --git a/core/transcriptSystem/communication/compileJsonV2.js b/core/transcriptSystem/communication/compileJsonV2.js deleted file mode 100644 index 2b4024b..0000000 --- a/core/transcriptSystem/communication/compileJsonV2.js +++ /dev/null @@ -1,395 +0,0 @@ -const discord = require('discord.js') - -const bot = require("../../../index") -const tsconfig = bot.tsconfig -const tsembeds = require("../embeds") -const tsdb = require("../tsdb") - -const otversion = require("../../../package.json").version -const version = require("../info.json").version - -const mentions = require("./mentions").replacementions - -/**@typedef {{background:{enableCustomBackground:Boolean, backgroundModus:"color"|"image", backgroundData:String}, header:{enableCustomHeader:Boolean, decoColor:String, backgroundColor:String, textColor:String}, stats:{enableCustomStats:Boolean, backgroundColor:String, keyTextColor:String, valueTextColor:String, hideBackgroundColor:String, hideTextColor:String}, favicon:{enableCustomFavicon:Boolean, imageUrl:String}} OTTranscriptStyle} */ -/**@typedef {{name:String, id:String, pfp:String}} OTTranscriptBot */ -/**@typedef {{name:String, id:String, guildname:String, guildid:String, guildinvite:String|false, creatorname:String, creatorid:String, closedbyname:String, closedbyid:String, claimedname:String, claimedid:String, creatorpfp:String, closedbypfp:String, claimedpfp:String, closedtime:Number, openedtime:Number, components:{messages:1, files:1, embeds:1, reactions:1, interactions:{dropdowns:1, buttons:1, total:1}, attachments:{invites:1, images:1, gifs:1, stickers:1}}, roleColors:[{id:String,color:String}] }} OTTranscriptTicket */ -/**@typedef {{author:{name:String, id:String, color:String, pfp:String, bot:Boolean, verifiedBot:Boolean, system:Boolean}, content:String|false, timestamp:Number, type:"normal", important:Boolean, edited:Boolean, embeds:[{title:String|false, description:String|false, authorimg:String|false, authortext:String|false, footerimg:String|false, footertext:String|false, color:String, image:String|false, thumbnail:String|false, url:String|false, fields:[{name:String,value:String,inline:Boolean}]}], attachments:[{type:"FILE", name:String, fileType:String, size:String, url:String}, {type:"FILE:image", name:String, fileType:String, size:String, url:String}, {type:"URL:invite", guildId:String, guildName:String, guildSize:Number, guildOnline:Number, image:String, url:String}, {type:"URL:gif", url:String}, {type:"BUILDIN:sticker", name:String, url:String}], components:[{type:"buttons", buttons:[{type:"interaction"|"url", label:String|false, icon:String|false, color:"gray"|"green"|"red"|"blue", id:String|false, url:String|false, disabled:Boolean}]}, {type:"dropdown", placeholder:String|false, options:[{label:String|false, icon:String|false, description:String|false, id:String|false}]}, {type:"reactions", reactions:[{amount:1, emoji:String, type:"svg"|"image"|"gif"}]}], reply:{type:"reply"|"command"|false, user:{name:String, id:String, color:String, pfp:String, bot:Boolean, verifiedBot:Boolean, system:Boolean}, replyOptions:{content:String, messageId:String, channelId:String, guildId:String}, commandOptions:{interactionName:String, interactionId:String}}}} OTTranscriptMessage */ -/**@typedef {{enabled:Boolean,premiumToken:String, customCredits:{enable:Boolean, replaceText:String, replaceURL:String, enableReportBug:Boolean},customHeaderUrl:{enabled:Boolean, url:String, text:String}, customTranscriptUrl:{enabled:Boolean, name:String}, customFavicon:{enabled:Boolean, image:String},additionalFlags:String[]}} OTTranscriptPremium */ - -/**@typedef {{version:"2", otversion:String, language:String, style:OTTranscriptStyle, bot:OTTranscriptBot, ticket:OTTranscriptTicket, messages:OTTranscriptMessage[], premium:OTTranscriptPremium}} OTTranscriptCompileInput */ - -/**@typedef {{style:OTTranscriptStyle,bot:OTTranscriptBot,ticket:OTTranscriptTicket,premium:OTTranscriptPremium}} OTHTMLDataOption */ - - -/**@param {discord.ButtonStyle} buttonstyle */ -const buttonStyleToColor = (buttonstyle) => { - if (buttonstyle == discord.ButtonStyle.Primary){ - return "blue" - }else if (buttonstyle == discord.ButtonStyle.Secondary){ - return "gray" - }else if (buttonstyle == discord.ButtonStyle.Danger){ - return "red" - }else if (buttonstyle == discord.ButtonStyle.Success){ - return "green" - }else{ - return "gray" - } -} - -/** - * - * @param {discord.Guild} guild - * @param {discord.Channel} channel - * @param {discord.User} user - * @param {discord.Message[]} messagesInv - * @param {OTHTMLDataOption} data - */ -exports.compile = (guild,channel,user,messagesInv,data) => { - const messages = messagesInv.reverse() - var invisibleMessages = 0 - - //MESSAGE STATS COUNTS - var messageAmount = messages.length - var fileAmount = 0 - var embedAmount = 0 - var reactionsAmount = 0 - var interactionAmount = 0 - messages.forEach((msg) => { - fileAmount = fileAmount + Array.from(msg.attachments).length - embedAmount = embedAmount + msg.embeds.length - - msg.reactions.cache.forEach(reaction => { - reactionsAmount = reactionsAmount + reaction.count - }) - if (msg.components && msg.components.length > 0){ - msg.components.forEach((component) => { - if (component.components.length > 0){ - interactionAmount = interactionAmount + component.components.length - }else{ - interactionAmount = interactionAmount+1 - } - - }) - } - }) - - /**@type {OTTranscriptMessage[]} */ - const messagesArray = [] - messages.forEach((msg) => { - if (msg.content || msg.embeds.length > 0 || msg.attachments.toJSON().length > 0 || msg.components.length > 0 || msg.reactions.cache.size > 0){ - - const embedArray = [] - const attachmentArray = [] - const componentsArray = [] - - msg.attachments.forEach((file) => { - attachmentArray.push({ - type:"FILE", - name:file.name, - fileType:file.contentType, - size:Math.round(file.size/1000)+" kb", - url:file.url - }) - }) - - msg.embeds.forEach((embed) => { - embedArray.push({ - title:embed.title || false, - description:embed.description ? mentions(embed.description,guild) : false, - authorimg:((embed.author && embed.author.iconURL) ? embed.author.iconURL : false), - authortext:(embed.author ? embed.author.name : false), - footerimg:((embed.footer && embed.footer.iconURL) ? embed.footer.iconURL : false), - footertext:(embed.footer ? embed.footer.text : false), - color:embed.hexColor, - image:((embed.image && embed.image.url) ? embed.image.url : false), - thumbnail:((embed.thumbnail && embed.thumbnail.url) ? embed.thumbnail.url : false), - url:(embed.url ? embed.url : false), - fields:embed.fields - }) - }) - - const tempreactions = [] - msg.reactions.cache.forEach((reaction) => { - const count = reaction.count - const emoji = reaction.emoji - - if (emoji instanceof discord.GuildEmoji){ - //custom emoji - tempreactions.push({ - amount:count, - emoji:emoji.imageURL(), - type:(emoji.animated) ? "gif" : "image" - }) - }else if (emoji instanceof discord.ReactionEmoji){ - //build-in emoji - tempreactions.push({ - amount:count, - emoji:emoji.name, - type:"svg" - }) - } - }) - componentsArray.push({ - type: "reactions", - reactions:tempreactions - }) - - msg.components.forEach((actionrow) => { - var isdropdown = false - var actioncomponents = [] - actionrow.components.forEach((comp) => { - if (comp.type == discord.ComponentType.ActionRow || comp.type == discord.ComponentType.TextInput) return - - /** - * type: "buttons"; - buttons: [{ - type: "interaction" | "url"; - label: string | false; - icon: string | false; - color: "gray" | "green" | "red" | "blue"; - id: string | false; - url: string | false; - disabled: boolean; - }]; - }, { - type: "dropdown"; - placeholder: string | false; - options: [{ - label: string | false; - icon: string | false; - description: string | false; - id: string | false; - }]; - }, - */ - if (comp.type == discord.ComponentType.Button){ - actioncomponents.push({ - type: (comp.style == discord.ButtonStyle.Link) ? "url" : "interaction", - label: (comp.label) ? comp.label : false, - icon: (comp.emoji) ? comp.emoji.name : false, - color: buttonStyleToColor(comp.style), - id: comp.customId ? comp.customId : false, - url: (comp.url) ? comp.url : false, - disabled: false - }) - }else{ - isdropdown = true - var drpdwnoptions = [] - /**@type {discord.APISelectMenuOption[]} */ - const dropdownoptions = comp.options - dropdownoptions.forEach((opt) => { - drpdwnoptions.push({ - label: opt.label, - icon: (opt.emoji) ? opt.emoji : false, - description: (opt.description) ? opt.description : false, - id: "hello world :)" - }) - }) - - componentsArray.push({ - type:"dropdown", - placeholder:false, - options:drpdwnoptions - }) - } - }) - - if (!isdropdown){ - componentsArray.push({ - type:"buttons", - buttons:actioncomponents - }) - } - }) - - const important = msg.guild ? (msg.content.includes("<@"+msg.guild.id+">") || msg.content.includes("<@everyone") || msg.content.includes("@here")): false - - const replytype = (msg.interaction) ? "command" : ((msg.reference) ? "reply" : false) - if (replytype == "command"){ - const replycolorRAW = msg.guild.members.cache.find((m) => m.id == msg.interaction.user.id) - const replycolor = (replycolorRAW) ? replycolorRAW.displayHexColor.replace("#000000","#ffffff") : "#ffffff" - var reply = { - type:replytype, - commandOptions:{ - interactionId:msg.interaction.id, - interactionName:msg.interaction.commandName - }, - user:{ - name:msg.interaction.user.displayName, - id:msg.interaction.user.id, - color:replycolor, - pfp:msg.interaction.user.displayAvatarURL(), - bot:msg.interaction.user.bot, - system:msg.interaction.user.system, - verifiedBot:msg.interaction.user.flags.has(discord.UserFlags.VerifiedBot) - } - } - }else if (replytype == "reply"){ - - var replycontentRAW = messages.find((msg2) => msg2.id == msg.reference.messageId) - var replycontent = (replycontentRAW && replycontentRAW.content) ? replycontentRAW.content.slice(0,(60-replycontentRAW.author.displayName.length)) : "deleted this message" - const replycolorRAW = (replycontentRAW) ? msg.guild.members.cache.find((m) => m.id == replycontentRAW.author.id) : false - const replycolor = (replycolorRAW) ? replycolorRAW.displayHexColor.replace("#000000","#ffffff") : "#ffffff" - - var user = (replycontentRAW && replycontentRAW.content) ? { - name:(replycontentRAW) ? replycontentRAW.author.displayName : "undefined", - id:(replycontentRAW) ? replycontentRAW.author.id : "undefined", - color:replycolor, - pfp:(replycontentRAW) ? replycontentRAW.author.displayName : "", - bot:(replycontentRAW) ? replycontentRAW.author.bot : false, - system:(replycontentRAW) ? replycontentRAW.author.system : false, - verifiedBot:(replycontentRAW) ? replycontentRAW.author.flags.has(discord.UserFlags.VerifiedBot) : false, - } : { - name:"someone", - id:"undefined", - color:"#ffffff", - pfp:"https://raw.githubusercontent.com/twitter/twemoji/master/assets/72x72/1f5d1.png", - bot:false, - system:false, - verifiedBot:false, - } - - var reply = { - type:replytype, - replyOptions:{ - content:replycontent, - messageId: msg.reference.messageId, - channelId: msg.reference.channelId, - guildId: msg.reference.guildId - }, - user:user - } - }else{var reply = {type:replytype}} - - const authorColor = msg.member ? msg.member.displayHexColor.replace("#000000","#ffffff") : "#ffffff" - messagesArray.push({ - author:{ - name:msg.author.displayName, - id:msg.author.id, - color:authorColor, - pfp:msg.author.displayAvatarURL(), - bot:msg.author.bot, - system:msg.author.system, - verifiedBot:msg.author.flags.has(discord.UserFlags.VerifiedBot) - }, - content:mentions(msg.content,guild) || "", - timestamp:msg.createdTimestamp, - embeds:embedArray, - attachments:attachmentArray, - edited: (typeof msg.editedTimestamp == "number"), - type:"normal", - important:important, - reply:reply, - components:componentsArray - }) - }else {invisibleMessages++} - }) - - const dsb = data.style.background - const dsh = data.style.header - const dss = data.style.stats - const dsf = data.style.favicon - - /**@type {OTTranscriptCompileInput} */ - const result = { - version,otversion, - language:bot.config.languageFile, - style:{ - background:{ - backgroundData:dsb.backgroundData || "", - backgroundModus:dsb.backgroundModus || "", - enableCustomBackground:dsb.enableCustomBackground || false, - }, - header:{ - backgroundColor:dsh.backgroundColor || "#202225", - decoColor:dsh.decoColor || "#F8BA00", - textColor:dsh.textColor || "#ffffff", - enableCustomHeader:dsh.enableCustomHeader || false - }, - stats:{ - backgroundColor:dss.backgroundColor || "#202225", - keyTextColor:dss.keyTextColor || "#737373", - valueTextColor:dss.valueTextColor || "#ffffff", - hideBackgroundColor:dss.hideBackgroundColor || "#40444a", - hideTextColor:dss.hideTextColor || "#ffffff", - enableCustomStats:dss.enableCustomStats || false - } - }, - bot:{ - name:data.bot.name || "Open Ticket", - id:data.bot.id || 0, - pfp:data.bot.pfp || "transcripts.dj-dj.be/favicon.png" - }, - ticket:{ - name:channel.name, - id:channel.id, - - guildname:guild.name, - guildid:guild.id, - guildinvite:"", - - creatorname:data.ticket.creatorname, - creatorid:data.ticket.creatorid, - creatorpfp:data.ticket.creatorpfp, - - closedbyname:user.displayName, - closedbyid:user.id, - closedbypfp:user.displayAvatarURL(), - - claimedid:"", - claimedname:"", - claimedpfp:"", - - closedtime:data.ticket.closedtime, - openedtime:data.ticket.openedtime, - - roleColors:[], - components:{ - messages:messageAmount, - embeds:embedAmount, - files:fileAmount, - interactions:{ - buttons:0, - dropdowns:0, - total:interactionAmount - }, - reactions:reactionsAmount, - attachments:{ - gifs:0, - images:0, - stickers:0, - invites:0 - } - } - }, - messages:messagesArray, - premium:{ - enabled:false, - premiumToken:"", - - customCredits:{ - enable:false, - replaceText:"Powered By Open Ticket!", - replaceURL:"https://openticket.dj-dj.be", - enableReportBug:true - }, - customHeaderUrl:{ - enabled:false, - url:"https://openticket.dj-dj.be", - text:"Hello!" - }, - customTranscriptUrl:{ - enabled:false, - name:"test-server" - }, - customFavicon:{ - enabled:dsf.enableCustomFavicon, - image:(dsf.imageUrl) ? dsf.imageUrl : "https://openticket.dj-dj.be" - }, - additionalFlags:[] - } - } - - - return result -} \ No newline at end of file diff --git a/core/transcriptSystem/communication/index.js b/core/transcriptSystem/communication/index.js deleted file mode 100644 index 48b8b88..0000000 --- a/core/transcriptSystem/communication/index.js +++ /dev/null @@ -1,29 +0,0 @@ -const axios = require("axios").default -const discord = require('discord.js') - -const bot = require("../../../index") -const tsconfig = bot.tsconfig -const tsembeds = require("../embeds") -const tsdb = require("../tsdb") - -/**@typedef {{status:"success"|"error", id:String, 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}}}} OTuploadResponse */ - -/** - * @param {Object} json - * @returns {Promise} - */ -exports.upload = async (json) => { - return new Promise(async (resolve,reject) => { - const data = encodeURIComponent(JSON.stringify(json)) - - try { - const res = await axios.post("https://apis.dj-dj.be/transcripts/upload?auth=openticketTRANSCRIPT1234&version=2",JSON.stringify(json)) - if (res.status != 200) resolve(false) - - resolve(res.data) - }catch(err){ - console.log("Failed HTML transcript upload! Reached Ratelimit 429!") - resolve(false) - } - }) -} \ No newline at end of file diff --git a/core/transcriptSystem/communication/mentions.js b/core/transcriptSystem/communication/mentions.js deleted file mode 100644 index 13dd97a..0000000 --- a/core/transcriptSystem/communication/mentions.js +++ /dev/null @@ -1,57 +0,0 @@ -const discord = require('discord.js') - -const bot = require("../../../index") -const tsconfig = bot.tsconfig -const tsembeds = require("../embeds") -const tsdb = require("../tsdb") - -/** - * - * @param {String} text - * @param {discord.Guild} guild - */ -exports.replacementions = (text,guild) => { - const userregex = /<@([0-9]+)>(\s)?/g - const usertext = text.replace(userregex,(x) => { - var res = userregex.exec(x) - userregex.lastIndex = 0 - - var member = guild.members.cache.find((m) => m.id == res[1]) - var text = member ? member.user.username.replace(/\s/g," ") : res[1] - return "<@"+text+"> " - }) - - const channelregex = /<#([0-9]+)>(\s)?/g - const channeltext = usertext.replace(channelregex,(x) => { - var res = channelregex.exec(x) - channelregex.lastIndex = 0 - - var channel = guild.channels.cache.find((c) => c.id == res[1]) - var text = channel ? channel.name.replace(/\s/g," ") : res[1] - return "<#"+text+"> " - }) - - const roleregex = /<@&([0-9]+)>(\s)?/g - const roletext = channeltext.replace(roleregex,(x) => { - var res = roleregex.exec(x) - roleregex.lastIndex = 0 - - var role = guild.roles.cache.find((r) => r.id == res[1]) - var text = role ? role.name.replace(/\s/g," ") : res[1] - - var color = role ? ((role.hexColor == "#000000") ? "regular" : role.hexColor) : "regular" - - return "<@&"+text+"::"+color+"> " - }) - - const defaultroleregex = /@(everyone|here)(\s)?/g - const defaultroletext = roletext.replace(defaultroleregex,(x) => { - var res = defaultroleregex.exec(x) - defaultroleregex.lastIndex = 0 - - var text = res[1] - return "<@&"+text+"::regular> " - }) - - return defaultroletext -} \ No newline at end of file diff --git a/core/transcriptSystem/embeds.js b/core/transcriptSystem/embeds.js deleted file mode 100644 index 9a73d3b..0000000 --- a/core/transcriptSystem/embeds.js +++ /dev/null @@ -1,80 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const storage = bot.storage -const tsconfig = bot.tsconfig - -/** - * - * @param {String} name - * @param {String} id - * @param {Number} rawprocesstime milliseconds - * @param {discord.User} user - */ -exports.beingprocessed = (name,id,rawprocesstime,user) => { - - const newtime = rawprocesstime - - const processtime = "" - - const embed = new discord.EmbedBuilder() - .setTitle("🧾 "+l.transcripts.title) - .setColor(config.color) - .setAuthor({name:user.username,iconURL:user.displayAvatarURL()}) - .setFooter({text:name}) - - .setDescription("`"+l.transcripts.processed+"...`\n"+l.transcripts.wait+"\n\n"+l.transcripts.estimated+": "+processtime) - - return embed -} - - -/** - * - * @param {String} name channel name - * @param {String} url transcript url - * @param {discord.User} user transcript closer - * @param {discord.User} creator transcript creator - */ -exports.tsready = (name,url,user,creator) => { - const embed = new discord.EmbedBuilder() - .setTitle("🧾 "+l.transcripts.title) - .setColor(config.color) - .setAuthor({name:user.username,iconURL:user.displayAvatarURL()}) - .setFooter({text:name}) - - if (creator) embed.setFields([{name:"Ticket Creator", value:"<@"+creator.id+">"}]) - - if (url){ - embed.setURL(url) - embed.setDescription("\n["+l.transcripts.available+"]("+url+")\n") - }else{ - embed.setDescription("\n"+l.transcripts.available+"\n") - } - - return embed -} - -/** - * - * @param {String} name - * @param {String} id - * @param {discord.User} user - * @param {undefined|String} err - */ -exports.tserror = (name,id,user,err) => { - const embed = new discord.EmbedBuilder() - .setTitle("❌ "+l.transcripts.title) - .setColor(discord.Colors.Red) - .setAuthor({name:user.username,iconURL:user.displayAvatarURL()}) - .setFooter({text:name}) - - const errDesc = (typeof err == "string") ? "\n"+err : "" - - embed.setDescription("Something went wrong while creating the HTML transcript.\n\n[possible reasons](https://otdocs.dj-dj.be/docs/current/docs/system/transcripts)"+errDesc) - - return embed -} diff --git a/core/transcriptSystem/info.json b/core/transcriptSystem/info.json deleted file mode 100644 index 1c4b27e..0000000 --- a/core/transcriptSystem/info.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "version":"2" -} \ No newline at end of file diff --git a/core/transcriptSystem/manager.js b/core/transcriptSystem/manager.js deleted file mode 100644 index 1236da7..0000000 --- a/core/transcriptSystem/manager.js +++ /dev/null @@ -1,221 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const storage = bot.storage - -const tsconfig = bot.tsconfig -const tsembeds = require("./embeds") -const tsdb = require("./tsdb") - - -const checkAvailability = async () => { - if (process.argv.some((v) => v == "--tsoffline")) return true - const axios = require("axios").default - try{ - const res = await axios.get("https://apis.dj-dj.be/transcripts/status.json") - if (!res || !(res.status == 200) || !res.data) return false - - if (res.data && res.data["v2"] == "online") return true - else return false - }catch{ - return false - } -} - -/** - * - * @param {discord.Message[]} messages - * @param {discord.Guild} guild - * @param {discord.TextChannel} channel - * @param {discord.User} user - * @param {String|false} reason - */ -module.exports = async (messages,guild,channel,user,reason) => { - require("../api/modules/events").onTranscriptCreation(messages,channel,guild,new Date()) - bot.statsManager.updateGlobalStats("TRANSCRIPTS_CREATED",(current) => { - if (typeof current != "undefined") return current+1 - return 1 - }) - const msglist = await channel.messages.fetchPinned() - - const chName = channel.name - const chId = channel.id - - const asyncmanager = async () => { - const hiddendata = bot.hiddenData.readHiddenData(channel.id) - if (hiddendata.length < 1) return - const ticketId = hiddendata.find(d => d.key == "type").value - const ticketData = require("../utils/configParser").getTicketById(ticketId,true) - - const id = hiddendata.find(d => d.key == "openerid").value - const opentime = new Date(Number(hiddendata.find(d => d.key == "createdms").value)) - - const ticketopener = client.users.cache.find(u => u.id == id) - - if (tsconfig.sendTranscripts.useHTMLtranscripts){ - const tsb = tsconfig.style.background - const tsh = tsconfig.style.header - const tss = tsconfig.style.stats - const tsf = tsconfig.style.favicon - const JSONDATA = require("./communication/compileJsonV2").compile(guild,channel,user,messages,{ - style:{ - background:{ - enableCustomBackground:tsb.enableCustomBackground, - backgroundModus:tsb.backgroundModus, - backgroundData:tsb.backgroundData - }, - header:{ - enableCustomHeader:tsh.enableCustomHeader, - backgroundColor:tsh.backgroundColor, - decoColor:tsh.decoColor, - textColor:tsh.textColor - }, - stats:{ - enableCustomStats:tss.enableCustomStats, - backgroundColor:tss.backgroundColor, - keyTextColor:tss.keyTextColor, - valueTextColor:tss.valueTextColor, - hideBackgroundColor:tss.hideBackgroundColor, - hideTextColor:tss.hideTextColor - }, - favicon:{ - enableCustomFavicon:tsf.enableCustomFavicon, - imageUrl:tsf.imageUrl - } - - }, - bot:{ - name:client.user.displayName, - id:client.user.id, - pfp:client.user.displayAvatarURL(), - }, - ticket:{ - creatorid:ticketopener.id, - creatorname:ticketopener.displayName, - creatorpfp:ticketopener.displayAvatarURL(), - - openedtime:opentime.getTime(), - closedtime:new Date().getTime() - } - }) - - if (!await checkAvailability()){ - const attachment = await require("./oldTranscript").createTranscript(messages,channel) - const errembed = tsembeds.tserror(chName,chId,user) - - if (tsconfig.sendTranscripts.enableChannel){ - /**@type {discord.TextChannel|undefined} */ - const tc = guild.channels.cache.find((c) => c.id == tsconfig.sendTranscripts.channel) - - if (!tc) return - tc.send({embeds:[errembed],files:[attachment]}) - } - if (tsconfig.sendTranscripts.enableDM && user){ - const embed = tsembeds.tsready(chName,null,user,ticketopener) - try { - ticketopener.send({embeds:[embed],files:[attachment]}) - }catch{} - } - return - } - - const TSdata = await require("./communication/index").upload(JSONDATA) - if (!TSdata){ - const attachment = await require("./oldTranscript").createTranscript(messages,channel) - const errembed = tsembeds.tserror(chName,chId,user,"`HTML Transcript API: reached ratelimit`") - - if (tsconfig.sendTranscripts.enableChannel){ - /**@type {discord.TextChannel|undefined} */ - const tc = guild.channels.cache.find((c) => c.id == tsconfig.sendTranscripts.channel) - - if (!tc) return - tc.send({embeds:[errembed],files:[attachment]}) - } - if (tsconfig.sendTranscripts.enableDM && user){ - const embed = tsembeds.tsready(chName,null,user,ticketopener) - try { - ticketopener.send({embeds:[embed],files:[attachment]}) - }catch{} - } - return false - } - - if (TSdata.status == "success"){ - //MAKE THIS COMPATIBLE WITH PREMIUM "customTranscriptUrl" IN FUTURE VERSIONS!! - const url = "https://transcripts.dj-dj.be/v2/"+TSdata.time+"_"+TSdata.id+".html" - - //calculate estimated time - //const lastDumpTime = (new Date(TSdata.estimated.lastdump).getTime()) - //const dumpLoopTime = 15000 - //const nextDump = new Date(lastDumpTime+dumpLoopTime) - //const processtime = TSdata.estimated.processtime+6000 //6sec extra time for overflow - - const duration = TSdata.estimated.waittime - const finaltime = new Date(new Date().getTime()+duration) - - //waiting - if (tsconfig.sendTranscripts.enableChannel){ - /**@type {discord.TextChannel|undefined} */ - const tc = guild.channels.cache.find((c) => c.id == tsconfig.sendTranscripts.channel) - - if (!tc) return - const embed = tsembeds.beingprocessed(chName,chId,finaltime,user) - var msg = await tc.send({embeds:[embed]}) - }else {var msg = false} - - //ready - setTimeout(() => { - if (msg){ - msg.edit({embeds:[tsembeds.tsready(chName,url,user,ticketopener)]}) - } - - if (tsconfig.sendTranscripts.enableDM){ - if (!user) return - const embed = tsembeds.tsready(chName,url,user,ticketopener) - try { - ticketopener.send({embeds:[embed]}) - }catch{} - } - },duration) - }else{ - const attachment = await require("./oldTranscript").createTranscript(messages,channel) - const errembed = tsembeds.tserror(chName,chId,user,"`error type: transcript API error`") - - if (tsconfig.sendTranscripts.enableChannel){ - /**@type {discord.TextChannel|undefined} */ - const tc = guild.channels.cache.find((c) => c.id == tsconfig.sendTranscripts.channel) - - if (!tc) return - tc.send({embeds:[errembed],files:[attachment]}) - } - if (tsconfig.sendTranscripts.enableDM && user){ - const embed = tsembeds.tsready(chName,null,user,ticketopener) - try { - ticketopener.send({embeds:[embed],files:[attachment]}) - }catch{} - } - } - }else{ - const attachment = await require("./oldTranscript").createTranscript(messages,channel) - const embed = tsembeds.tsready(chName,null,user,ticketopener) - - if (tsconfig.sendTranscripts.enableChannel){ - /**@type {discord.TextChannel|undefined} */ - const tc = guild.channels.cache.find((c) => c.id == tsconfig.sendTranscripts.channel) - - if (!tc) return - tc.send({embeds:[embed],files:[attachment]}) - } - if (tsconfig.sendTranscripts.enableDM && user){ - const embed = tsembeds.tsready(chName,null,user,ticketopener) - try { - ticketopener.send({embeds:[embed],files:[attachment]}) - }catch{} - } - } - } - asyncmanager() -} \ No newline at end of file diff --git a/core/transcriptSystem/oldTranscript.js b/core/transcriptSystem/oldTranscript.js deleted file mode 100755 index a6b02a2..0000000 --- a/core/transcriptSystem/oldTranscript.js +++ /dev/null @@ -1,60 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const l = bot.language - -/** - * - * @param {discord.Message[]} messagecollection - * @param {discord.TextChannel} channel - * @param {Boolean} backup - * @returns new `discord.attachmentBuilder` - */ - -exports.createTranscript = async (messagecollection,channel,backup) => { - try { - const cd = new Date() - const months = ["January","February","March","April","May","June","July","August","September","October","November","December"] - const dateString = cd.getDate()+" "+months[cd.getMonth()-1]+" "+cd.getFullYear()+" - "+cd.getHours()+":"+cd.getMinutes()+":"+cd.getSeconds() - let backuptitle = backup ? "BACKUP " : "" - let backupfilename = backup ? "backup" : "" - const filearray = [backuptitle+"TRANSCRIPT:\n"] - - messagecollection.reverse() - - messagecollection.forEach((msg) => { - const timestamp = new Date(msg.createdTimestamp) - - //empty message handling - if (msg.content){ - var content = msg.content - }else if (msg.embeds.length > 0 && msg.attachments.length > 0){ - var content = "*this message only has embeds & files*" - }else if (msg.embeds.length > 0){ - var content = "*this message only has embeds*" - }else if (msg.attachments.length > 0){ - var content = "*this message only has files*" - }else{ - var content = "*empty message*" - } - - - const fileurls = [] - const rawfiles = Array.from(msg.attachments) - rawfiles.forEach((file) => { - fileurls.push("attachment: "+file[1].url) - }) - const filestring = fileurls.length > 0 ? fileurls.join("\n")+"\n" : "" - const msgstats = "files: "+msg.attachments.size+", embeds: "+msg.embeds.length - filearray.push("["+timestamp.getDate()+"/"+timestamp.getMonth()+"/"+timestamp.getFullYear()+", "+timestamp.getHours()+":"+timestamp.getMinutes()+":"+timestamp.getSeconds()+"|"+msg.author.username+"] ["+msgstats+"]\n"+content+"\n"+filestring) - }) - - if (filearray.length < 2) filearray.push("transcript is empty") - const filestring = filearray.join("\n") - const filebuff = Buffer.from(filestring,"utf-8") - return new discord.AttachmentBuilder(filebuff,{name:backupfilename+"transcript.txt",description:"Open Ticket transcript"}) - }catch{ - return false - } -} \ No newline at end of file diff --git a/core/transcriptSystem/tsdb.js b/core/transcriptSystem/tsdb.js deleted file mode 100644 index 2ad725e..0000000 --- a/core/transcriptSystem/tsdb.js +++ /dev/null @@ -1,71 +0,0 @@ -const fs = require("fs") -const location = "./storage/tsdatabase.json" - - -/**@returns {[{category:String, key:String, value:String}]}*/ -function getData(){ - if (fs.existsSync(location)){ - return JSON.parse(fs.readFileSync(location).toString()) - }else{ - fs.writeFileSync(location,"[]") - return [] - } -} -/**@param {[{category:String, key:String, value:String}]} data*/ -function setData(data){ - fs.writeFileSync(location,JSON.stringify(data,null,"\t")) -} - -exports.set = (category,key,value) => { - const currentData = getData() - const exists = currentData.find((d) => (d.category == category) && (d.key == key)) ? true : false - var newData = [] - if (exists){ - currentData.forEach((d,i) => { - if (d.category == category && d.key == key){ - newData.push({category,key,value}) - }else{ - newData.push(d) - } - }) - }else{ - currentData.push({category,key,value}) - newData = currentData - } - - setData(newData) - return exists -} -/** - * @param {String} category - * @param {String} key - * @returns {String|false} - */ -exports.get = (category,key) => { - const currentData = getData() - const tempresult = currentData.find((d) => (d.category == category) && (d.key == key)) - const result = tempresult ? tempresult.value : false - return result -} -/** - * @param {String} category - * @param {String} key - * @param {String} value - */ -exports.delete = (category,key) => { - const currentData = getData() - const exists = currentData.find((d) => (d.category == category) && (d.key == key)) ? true : false - var newData = [] - if (exists){ - currentData.forEach((d,i) => { - if (!(d.category == category && d.key == key)){ - newData.push(d) - } - }) - }else{ - newData = currentData - } - - setData(newData) - return exists -} \ No newline at end of file diff --git a/core/utils/configParser.js b/core/utils/configParser.js deleted file mode 100644 index db183df..0000000 --- a/core/utils/configParser.js +++ /dev/null @@ -1,188 +0,0 @@ -const bot = require("../../index") -const config = bot.config -const l = bot.language - -//TYPEDEFS: -//================== - -//OTTicketOptions -/**@typedef {{id: String,name: String,description: String,icon: String,label: String,type: "ticket"|"role"|"website",color: "red"|"green"|"blue"|"gray",adminroles: String[], readonlyAdminroles: String[], channelprefix: String,category: String,message: String,enableDmOnOpen: Boolean,ticketmessage: String, thumbnail:{enable:Boolean,url:String}, image:{enable:Boolean,url:String}, closedCategory:{enable:Boolean,id:String}, autoclose:{enable:Boolean,inactiveHours:Number}, ping:{"@here":Boolean, "@everyone":Boolean, custom:{enable:Boolean, roleId:String}} }} OTTicketOptions */ - -//OTRoleOptions -/**@typedef {{id: String,name: String,description: String,icon: String,label: String,type: "ticket"|"role"|"website",color:"red"|"green"|"blue"|"gray"|"none",roles:String[],mode:"add&remove"|"remove"|"add",enableDmOnOpen:Boolean}} OTRoleOptions */ - -//OTWebsiteOptions -/**@typedef {{id: String,name: String,description: String,icon: String,label: String,type: "ticket"|"role"|"website",url:String}} OTWebsiteOptions */ - - -//OTConfigMessage -/**@typedef {{id: string, name: string, description: string, dropdown: boolean, enableFooter: boolean, footer: string, enableFooterImage: boolean, footerImage: string, enableThumbnail: boolean, thumbnail: string, enableImage: boolean, image: string, enableCustomColor: boolean, color: string, options: string[], other:{enableTicketExplaination: boolean, enableMaxTicketsWarning: boolean, customDropdownPlaceholder:{enable:Boolean,text:String}, customCategoryText:{enable:Boolean,text:String}, embedTitleURL:{enable:Boolean,url:String} } }} OTConfigMessage*/ - -//OTAllOptions -/**@typedef {{id: String,name: String,description: String,icon: String,label: String,type: "ticket"|"role"|"website",color:"red"|"green"|"blue"|"gray"|"none",roles:String[],mode:"add&remove"|"remove"|"add",adminroles: String[],channelprefix: String,category: String,message: String,enableDmOnOpen: Boolean,ticketmessage: String, thumbnail:{enable:Boolean,url:String}, image:{enable:Boolean,url:String}, url:String, closedCategory:{enable:Boolean,id:String}, autoclose:{enable:Boolean,inactiveHours:Number}, readonlyAdminroles: String[]}} OTAllOptions */ - -//StringOptions -/**@typedef {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"adminroles"|"channelprefix"|"category"|"message"|"enableDmOnOpen"|"ticketmessage"|"thumbnail"|"image"|"closedCategory"|"adminroles"|"autoclose"|"ping"} OTTicketStringOptions */ -/**@typedef {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"roles"|"mode"|"enableDmOnOpen"} OTRoleStringOptions */ -/**@typedef {"id"|"name"|"description"|"icon"|"label"|"type"|"url"} OTWebsiteStringOptions */ - -//FUNCTIONS: -//================== - -/** @param {String} id the id of the embed @returns {OTConfigMessage}*/ -exports.getConfigMessage = (id) => { - var returned = config.messages.find(a => a.id == id) - if (returned){ - return returned - } - var result = config.messages[0] - if (!result){ - throw new Error("'messages' object in config.json is empty") - return - } - return result -} - -/** - * - * @param {String} id - * @param {Boolean} withoutOTnewT - * @returns {OTTicketOptions|false} - */ - exports.getTicketById = (id,withoutOTnewT) => { - var result = false - if (withoutOTnewT){ - config.options.forEach((option) => { - if (option.id == id && option.type == "ticket"){ - result = option - } - }) - }else{ - config.options.forEach((option) => { - if ("OTnewT"+option.id == id && option.type == "ticket"){ - result = option - } - }) - } - return result -} - -/** - * - * @param {String} id - * @param {Boolean} withoutOTnewR - * @returns {OTRoleOptions|false} - */ - exports.getRoleById = (id,withoutOTnewR) => { - var result = false - if (withoutOTnewR){ - config.options.forEach((option) => { - if (option.id == id && option.type == "role"){ - result = option - } - }) - }else{ - config.options.forEach((option) => { - if ("OTnewR"+option.id == id && option.type == "role"){ - result = option - } - }) - } - return result -} - -/** - * - * @param {String} id - * @returns {OTWebsiteOptions|false} - */ - exports.getWebsiteById = (id) => { - var result = false - config.options.forEach((option) => { - if (option.id == id && option.type == "website"){ - result = option - } - }) - return result -} - -/** - * @param {OTTicketStringOptions} value - * @returns {String[]} - */ -exports.getTicketValuesArray = (value,idWithoutOTnewT) => { - var result = [] - const prefix = idWithoutOTnewT ? "" : "OTnewT" - config.options.forEach((opt) => { - if (opt.type == "ticket"){ - if (value == "id"){ - result.push(prefix+opt[value]) - }else{ - result.push(opt[value]) - } - } - }) - return result -} - -/** - * @param {OTRoleStringOptions} value - * @returns {String[]} - */ - exports.getRoleValuesArray = (value,idWithoutOTnewR) => { - var result = [] - const prefix = idWithoutOTnewR ? "" : "OTnewR" - config.options.forEach((opt) => { - if (o.type == "role"){ - if (value == "id"){ - result.push(prefix+opt[value]) - }else{ - result.push(opt[value]) - } - } - }) - return result -} - -/** - * @param {OTWebsiteStringOptions} value - * @returns {String[]} - */ - exports.getWebsiteValuesArray = (value) => { - var result = [] - config.options.forEach((opt) => { - if (o.type == "website"){ - result.push(opt[value]) - } - }) - return result -} - -/**@type {OTTicketOptions} */ -this.ticketType = {} - -/**@type {OTRoleOptions} */ -this.roleType = {} - -/**@type {OTWebsiteOptions} */ -this.websiteType = {} - -/**@type {OTConfigMessage} */ -this.messageType = {} - - - -/** - * - * @param {String} id - * @returns {Boolean} - */ - exports.optionExists = (id) => { - var result = false - config.options.forEach((option) => { - if (option.id == id){ - result = true - } - }) - return result -} \ No newline at end of file diff --git a/core/utils/getButton.js b/core/utils/getButton.js deleted file mode 100644 index 06cfd08..0000000 --- a/core/utils/getButton.js +++ /dev/null @@ -1,80 +0,0 @@ -const discord = require("discord.js") -const bot = require("../../index") -const config = bot.config -const l = bot.language -const b = discord.ButtonStyle - -/** - * @param {String} color - * @returns {"DANGER"|"SUCCESS"|"PRIMARY"|"SECONDARY"} */ -const getColor = (color) => { - if (color){ - if (color.toLowerCase() == "red"){ - return b.Danger - }else if (color.toLowerCase() == "green"){ - return b.Success - }else if (color.toLowerCase() == "blue" || color.toLowerCase() == "blurple"){ - return b.Primary - }else if (color.toLowerCase() == "black" || color.toLowerCase() == "gray" || color.toLowerCase() == "grey"){ - return b.Secondary - }else if (color.toUpperCase() == "DANGER" || color.toUpperCase() == "SECONDARY" || color.toUpperCase() == "SUCCESS" || color.toUpperCase() == "PRIMARY"){ - return color - }else if (color.toLowerCase() == "none" || color.toLowerCase() == "false" || color.toLowerCase() == ""){ - return b.Secondary - }else return b.Secondary - }else return b.Secondary -} - -const getOption = (id) => { - const result = config.options.find((option) => option.id == id) - if (!result){return false}else return result -} -exports.getOption = getOption -/** - * - * @param {String} id - * @returns {discord.ButtonBuilder|false} - */ -exports.getButton = (id) => { - bot.actionRecorder.push({ - category:"ot.managers.utils", - file:"./core/utils/getButton.js", - time:new Date().getTime(), - type:"getbutton" - }) - const option = getOption(id) - if (!option) return false - if (option.type == "ticket"){ - var button = new discord.ButtonBuilder() - .setCustomId("OTnewT"+option.id) - .setDisabled(false) - .setStyle(getColor(option.color)) - - if (option.label){button.setLabel(option.label)} - if (option.icon){button.setEmoji(option.icon)} - if (!option.label && !option.icon){button.setLabel("no label or emoji")} - - }else if (option.type == "website"){ - var button = new discord.ButtonBuilder() - .setDisabled(false) - .setStyle(discord.ButtonStyle.Link) - .setURL(option.url) - - if (option.label){button.setLabel(option.label)} - if (option.icon){button.setEmoji(option.icon)} - if (!option.label && !option.icon){button.setLabel("no label or emoji")} - - }else if (option.type == "role"){ - var button = new discord.ButtonBuilder() - .setCustomId("newR"+option.id) - .setDisabled(false) - .setStyle(getColor(option.color)) - - if (option.label){button.setLabel(option.label)} - if (option.icon){button.setEmoji(option.icon)} - if (!option.label && !option.icon){button.setLabel("no label or emoji")} - - } - - return button -} \ No newline at end of file diff --git a/core/utils/getDropdown.js b/core/utils/getDropdown.js deleted file mode 100644 index 67085cc..0000000 --- a/core/utils/getDropdown.js +++ /dev/null @@ -1,70 +0,0 @@ -const discord = require("discord.js") -const bot = require("../../index") -const config = bot.config -const l = bot.language - -const configParser = require("./configParser") -/** - * - * @param {String[]} ids - * @param {String|undefined|false} placeholder - * @returns {discord.StringSelectMenuBuilder|false} - */ -exports.getDropdown = (ids,placeholder) => { - bot.actionRecorder.push({ - category:"ot.managers.utils", - file:"./core/utils/getDropdown.js", - time:new Date().getTime(), - type:"getdropdown" - }) - const dropdown = new discord.StringSelectMenuBuilder() - .setCustomId("OTdropdownMenu") - .setDisabled(false) - .setMaxValues(1) - .setMinValues(1) - .setPlaceholder(placeholder || l.messages.chooseATicket) - .addOptions( - new discord.StringSelectMenuOptionBuilder() - .setDefault(true) - .setLabel(placeholder || l.messages.chooseATicket) - .setValue("OTChooseTicket") - ) - - ids.forEach((id) => { - const option = configParser.getTicketById(id,true) - const roleoption = configParser.getRoleById(id,true) - if (option){ - const selectComponent = new discord.StringSelectMenuOptionBuilder() - .setDefault(false) - .setValue("OTnewT"+option.id) - - if (!option.label && !option.icon){ - selectComponent.setLabel("OT ERROR: no description/emoji") - }else{ - if (option.label) selectComponent.setLabel(option.label) - if (option.icon) selectComponent.setEmoji(option.icon) - if (option.description && option.description.length < 100) selectComponent.setDescription(option.description) - } - - dropdown.addOptions(selectComponent) - - }else if (roleoption){ - const selectComponent = new discord.StringSelectMenuOptionBuilder() - .setDefault(false) - .setValue("OTnewR"+roleoption.id) - - if (!roleoption.label && !roleoption.icon){ - selectComponent.setLabel("OT ERROR: no description/emoji") - }else{ - if (roleoption.label) selectComponent.setLabel(roleoption.label) - if (roleoption.icon) selectComponent.setEmoji(roleoption.icon) - } - - dropdown.addOptions(selectComponent) - } - - }) - - - return dropdown -} \ No newline at end of file diff --git a/core/utils/getEmbed.js b/core/utils/getEmbed.js deleted file mode 100644 index 2dc0f5c..0000000 --- a/core/utils/getEmbed.js +++ /dev/null @@ -1,138 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const getButton = require("./getButton") -const l = bot.language - -/** - * - * @param {String} id the id from an open-ticket embed - * @returns {{embed:discord.EmbedBuilder,componentRows:discord.MessageActionRow[]}} discord embed - */ - - - -exports.createEmbed = (id) => { - bot.actionRecorder.push({ - category:"ot.managers.utils", - file:"./core/utils/getEmbed.js", - time:new Date().getTime(), - type:"getembed" - }) - //----------------------------------- - //general importing - const data = require("./configParser").getConfigMessage(id) - /**@type {discord.ButtonBuilder[]}*/ - var buttons = [] - /**@type {import('./configParser').OTAllOptions[]} */ - var buttonData = [] - - data.options.forEach((option) => { - var button = getButton.getButton(option) - var localButtonData = getButton.getOption(option) - if (button) buttons.push(button) - if (localButtonData) buttonData.push(localButtonData) - }) - //----------------------------------- - - //----------------------------------- - //create the embed - const embed = new discord.EmbedBuilder() - .setTitle(data.name) - - try { - const footerimg = (data.enableFooter && data.enableFooterImage) ? data.footerImage : undefined - if (data.enableFooter) embed.setFooter({text:data.footer,iconURL:footerimg}) - }catch{ - bot.errorLog.log("info","FOOTER FAILED TO LOAD, probably invalid url!") - } - - try { - if (data.enableThumbnail) embed.setThumbnail(data.thumbnail) - }catch{ - bot.errorLog.log("info","THUMBNAIL FAILED TO LOAD, probably invalid url!") - } - - try { - if (data.enableImage) embed.setImage(data.image) - }catch{ - bot.errorLog.log("info","IMAGE FAILED TO LOAD, probably invalid url!") - } - - if (data.enableCustomColor){ - embed.setColor(data.color) - }else{ - embed.setColor(config.color) - } - - if (data.other.embedTitleURL.enable) embed.setURL(data.other.embedTitleURL.url) - - var description = data.description - if (data.other.enableTicketExplaination){ - const chooseCategoryMSG = data.other.customCategoryText.enable ? data.other.customCategoryText.text : l.messages.chooseATicket - description = description+"\n\n__"+chooseCategoryMSG+"__\n" - - var ticketExplainations = [] - buttonData.forEach((button) => { - var explaination = button.icon+" **"+button.name+":**\n"+button.description - ticketExplainations.push(explaination) - }) - - description = description+ticketExplainations.join("\n\n") - } - - if (data.other.enableMaxTicketsWarning){ - description = description+"\n\n"+l.commands.maxTicketWarning.replace("{0}",config.system.maxAmountOfTickets) - } - - if (description) embed.setDescription(description) - - //----------------------------------- - - - //----------------------------------- - //create the components IF DROPDOWN IS FALSE - if (!data.dropdown){ - var AmountOfRows = Math.ceil(buttons.length / 4) - var currentRow = 0 - - /** - * @type {discord.MessageActionRow[]} - */ - var componentRows = [] - - for (let i = AmountOfRows; i > 0; i--){ - - componentRows.push(new discord.ActionRowBuilder()) - } - - buttons.forEach((button,index) => { - componentRows[currentRow].addComponents([button]) - - if (index == 3 || index == 7 || index == 11 || index == 15 || index == 19 || index == 23 || index == 27 || index == 31 || index == 35 || index == 39){ - currentRow = currentRow + 1 - } - }) - - //create the component IF DROPDOWN is true - }else{ - const ids = data.options - const customPlaceholder = data.other.customDropdownPlaceholder.enable ? data.other.customDropdownPlaceholder.text : false - const dropdown = require("./getDropdown").getDropdown(ids,customPlaceholder) - var componentRows = [ - new discord.ActionRowBuilder() - .setComponents(dropdown) - ] - } - //----------------------------------- - - - - //return everything - /** - * @type {{embed:discord.EmbedBuilder,componentRows:discord.MessageActionRow[]}} - */ - const returnedData = {embed:embed,componentRows:componentRows} - return returnedData -} \ No newline at end of file diff --git a/core/utils/hiddendata.js b/core/utils/hiddendata.js deleted file mode 100644 index c3de1f4..0000000 --- a/core/utils/hiddendata.js +++ /dev/null @@ -1,49 +0,0 @@ -const storage = require("../../index").storage - -/**@typedef {[{key:String,value:String}]} hiddenData */ - -/** - * - * @param {String} channelid - * @returns {hiddenData} - */ - -exports.readHiddenData = (channelid) => { - const content = storage.get("HIDDENDATA",channelid) - if (!content) return [] - - try { - return JSON.parse(content) - } catch { - return [] - } -} - -/** - * - * @param {String} channelid - * @param {[{key:String,value:String}]} data - * @returns {Boolean} - */ -exports.writeHiddenData = (channelid,data) => { - try { - storage.set("HIDDENDATA",channelid,JSON.stringify(data)) - return true - } catch { - return false - } -} - -/** - * - * @param {String} channelid - * @returns {Boolean} - */ -exports.deleteHiddenData = (channelid) => { - try { - storage.delete("HIDDENDATA",channelid) - return true - } catch { - return false - } -} \ No newline at end of file diff --git a/core/utils/liveStatus.js b/core/utils/liveStatus.js deleted file mode 100644 index deeaa4b..0000000 --- a/core/utils/liveStatus.js +++ /dev/null @@ -1,137 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const axios = require("axios").default -const fs = require("fs") - -const loadChalk = async () => { - return await (await import("chalk")).default -} - -//OTLiveStatus -/**@typedef {[{style:[{title:String,titleColor:"normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan",description:String,descriptionColor:"normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan"}],active:{versions:String[],languages:String[],usingPlugins:["yes"|"no"|"both"],usingSlashCommands:["yes"|"no"|"both"],transcripts:["html"|"text"|"both"]}}]} OTLiveStatus */ - -//OTLiveStatusError -/**@typedef {{bot:{id:String,pfp:String,name:String}, openticket:{version:String,language:String, slashcmds:Boolean,transcripts:false|"text"|"html",config:{system:{},options:{},messages:{},transcripts:{}},plugins:String[],pluginload:{success:Number,error:Number,total:Number}}, details:{actions:[{type:String,category:String,file:String,time:Number}],errortime:Number}, error:String}} OTLiveStatusError */ - -/**@type {[{type:String, category:String, file:String, time:Number}]} */ -exports.actionRecorder = [] - -//================================================================ -//=========================FUNCTIONS============================== -//================================================================ - -const getSlashEnabled = () => { - if (!fs.existsSync("./storage/slashcmdEnabled.txt")) return false - if (fs.readFileSync("./storage/slashcmdEnabled.txt").toString() == require("../../package.json").version){ - return true - }else return false -} - -/** - * @param {Boolean} [local=false] - * @returns {Promise} -*/ -const getLivestatus = (local) => { - return new Promise((resolve,reject) => { - if (local){ - try { - const livestatus = require("../../livestatus.json") - if (!livestatus) return resolve(false) - resolve(livestatus) - }catch{ - return resolve(false) - } - }else{ - try { - axios.get("https://apis.dj-dj.be/livestatus/announcements/openticket.json").then((res) => { - const livestatus = res.data - if (!Array.isArray(livestatus)) return resolve(false) - if (!livestatus) return resolve(false) - resolve(livestatus) - }) - }catch{ - return resolve(false) - } - } - }) -} - -var globalPluginData = {total:0,error:0,success:0} - -//announcer -/**@param {{total:Number,error:Number,success:Number}} pluginData*/ -exports.run = async (pluginData) => { - const chalk = await loadChalk() - globalPluginData = pluginData - const res = await getLivestatus(process.argv.some((v) => v == "--localstatus")) - if (!res) return false - if (res.length == 0) return - - /**@type {[{title:String,titleColor:"normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan",description:String,descriptionColor:"normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan"}]} */ - const activeStyles = [] - res.forEach((announcement) => { - const a = announcement.active - - const isLanguage = a.languages.includes(config.languageFile) || a.languages.includes("all") - const isVersion = a.versions.includes(require("../../package.json").version) - - var tsenabled = (bot.tsconfig.sendTranscripts.enableChannel || bot.tsconfig.sendTranscripts.enableDM) - var tsmode = bot.tsconfig.sendTranscripts.useHTMLtranscripts ? "html" : "text" - const isTranscript = (a.transcripts.includes("html") && tsmode == "html" && tsenabled) || (a.transcripts.includes("text") && tsmode == "text" && tsenabled) || (a.transcripts.includes("both") && tsenabled) - const isPlugins = (a.usingPlugins.includes("yes") && pluginData.total > 0) || (a.usingPlugins.includes("no") && pluginData.total == 0) || (a.usingPlugins.includes("both")) - const isSlashCMD = (a.usingSlashCommands.includes("yes") && getSlashEnabled()) || (a.usingSlashCommands.includes("no") && !getSlashEnabled()) || (a.usingSlashCommands.includes("both")) - - if (!isLanguage || !isVersion || !isTranscript || !isPlugins || !isSlashCMD) return - announcement.style.forEach((s) => activeStyles.push(s)) - }) - const final = [] - activeStyles.forEach((style) => { - const dc = style.descriptionColor - const tempd = style.description.split("\n") - const tc = style.titleColor - const t = "["+style.title+"]" - const tempd2 = [] - tempd.forEach((tmpd,i) => { - if (i > 0){ - var newtext = tmpd - var i2 = 0 - while(i2 < t.length+1){ - newtext = " "+newtext - i2++ - } - tempd2.push(newtext) - }else{ - tempd2.push(tmpd) - } - }) - const d = tempd2.join("\n") - - - var fd = d - if (dc == "normal" || dc == "white") fd = chalk.white(d) - if (dc == "red") fd = chalk.red(d) - if (dc == "yellow") fd = chalk.yellow(d) - if (dc == "green") fd = chalk.green(d) - if (dc == "blue") fd = chalk.blue(d) - if (dc == "gray") fd = chalk.gray(d) - if (dc == "magenta") fd = chalk.magenta(d) - if (dc == "cyan") fd = chalk.cyan(d) - - var ft = t - if (tc == "normal" || tc == "white") ft = chalk.white(t) - if (tc == "red") ft = chalk.red(t) - if (tc == "yellow") ft = chalk.yellow(t) - if (tc == "green") ft = chalk.green(t) - if (tc == "blue") ft = chalk.blue(t) - if (tc == "gray") ft = chalk.gray(t) - if (tc == "magenta") ft = chalk.magenta(t) - if (tc == "cyan") ft = chalk.cyan(t) - - final.push(ft+" "+fd) - }) - - console.log(final.join("\n\n")) -} \ No newline at end of file diff --git a/core/utils/permisssionChecker.js b/core/utils/permisssionChecker.js deleted file mode 100644 index 9653dfc..0000000 --- a/core/utils/permisssionChecker.js +++ /dev/null @@ -1,176 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log -const l = bot.language -const storage = bot.storage - -/** - * - * @param {String} memberid - * @param {String} guildid - * @returns {Boolean} has permissions? - */ -exports.global = (memberid,guildid) => { - bot.actionRecorder.push({ - category:"ot.managers.permissionChecker", - file:"./core/permissionChecker.js", - time:new Date().getTime(), - type:"global" - }) - const permsmember = client.guilds.cache.find(g => g.id == guildid).members.cache.find(m => m.id == memberid) - if (config.adminRoles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ - return false - }else {return true} -} - -/** - * - * @param {String} memberid - * @param {String} guildid - * @param {String} optionid - * @returns {Boolean} has permissions? - */ -exports.ticket = (memberid,guildid,optionid) => { - bot.actionRecorder.push({ - category:"ot.managers.permissionChecker", - file:"./core/permissionChecker.js", - time:new Date().getTime(), - type:"ticket" - }) - - const option = config.options.find((opt) => opt.id == optionid) - const ticketadmins = option && option.adminroles ? option.adminroles : [] - const permsmember = client.guilds.cache.find(g => g.id == guildid).members.cache.find(m => m.id == memberid) - - const isGlobalAdmin = config.adminRoles.some((item)=>{return permsmember.roles.cache.has(item)}) - const isTicketAdmin = ticketadmins.some((item)=>{return permsmember.roles.cache.has(item)}) - const hasAdministrator = permsmember.permissions.has("Administrator") - const hasManageGuild = permsmember.permissions.has("ManageGuild") - - return isGlobalAdmin || isTicketAdmin || hasAdministrator || hasManageGuild -} - -/** - * - * @param {discord.User} user - * @returns {Boolean} - */ -exports.sendUserNoPerms = (user) => { - bot.actionRecorder.push({ - category:"ot.managers.permissionChecker", - file:"./core/permissionChecker.js", - time:new Date().getTime(), - type:"sendusernoperms" - }) - try { - user.send({embeds:[bot.errorLog.noPermsMessage(user)]}) - return true - }catch{ - return false - } -} - -/** - * - * @param {discord.User} user - * @returns {Boolean} - */ - exports.sendUserNoTicket = (user) => { - bot.actionRecorder.push({ - category:"ot.managers.permissionChecker", - file:"./core/permissionChecker.js", - time:new Date().getTime(), - type:"sendusernoticket" - }) - try { - user.send({embeds:[bot.errorLog.notInATicket]}) - return true - }catch{ - return false - } -} - -/** - * - * @param {discord.User} user - * @returns {Boolean} - */ - exports.sendUserNoDelete = (user) => { - bot.actionRecorder.push({ - category:"ot.managers.permissionChecker", - file:"./core/permissionChecker.js", - time:new Date().getTime(), - type:"sendusernodelete" - }) - try { - user.send({embeds:[bot.errorLog.noPermsDelete(user)]}) - return true - }catch{ - return false - } -} - -/** - * - * @param {discord.TextChannel} channel - * @param {discord.User} user - * @returns {Boolean} - */ - exports.sendChannelNoPerms = (channel,user) => { - bot.actionRecorder.push({ - category:"ot.managers.permissionChecker", - file:"./core/permissionChecker.js", - time:new Date().getTime(), - type:"sendchannelnoperms" - }) - try { - channel.send({embeds:[bot.errorLog.noPermsMessage(user)]}) - return true - }catch{ - return false - } -} - -/** - * - * @param {discord.TextChannel} channel - * @param {discord.User} user - * @returns {Boolean} - */ - exports.sendChannelNoTicket = (channel,user) => { - bot.actionRecorder.push({ - category:"ot.managers.permissionChecker", - file:"./core/permissionChecker.js", - time:new Date().getTime(), - type:"sendchannelnoticket" - }) - try { - channel.send({embeds:[bot.errorLog.notInATicket]}) - return true - }catch{ - return false - } -} - -/** - * - * @param {discord.TextChannel} channel - * @param {discord.User} user - * @returns {Boolean} - */ - exports.sendChannelNoDelete = (channel,user) => { - bot.actionRecorder.push({ - category:"ot.managers.permissionChecker", - file:"./core/permissionChecker.js", - time:new Date().getTime(), - type:"sendchannelnodelete" - }) - try { - channel.send({embeds:[bot.errorLog.noPermsDelete(user)]}) - return true - }catch{ - return false - } -} diff --git a/index.js b/index.js deleted file mode 100644 index 92bd844..0000000 --- a/index.js +++ /dev/null @@ -1,449 +0,0 @@ -/** - ____ _____ ______ _ _ _______ _____ _____ _ ________ _______ - / __ \| __ \| ____| \ | | |__ __|_ _/ ____| |/ / ____|__ __| - | | | | |__) | |__ | \| | | | | || | | ' /| |__ | | - | | | | ___/| __| | . ` | | | | || | | < | __| | | - | |__| | | | |____| |\ | | | _| || |____| . \| |____ | | - \____/|_| |______|_| \_| |_| |_____\_____|_|\_\______| |_| - - Hey! we are looking for you! - Do you speak a language that isn't yet in our /languages directory - or do you speak one that isn't up-to-date? Open Ticket needs - translators for lots of different languages! - Feel free to join our translator team and help us improve Open Ticket! - - - - - SUGGESTING NEW FEATURES: - ===================== - Open Ticket is an open-source community project! - Because of this, almost 80% of all features in OT were ideas from our community! - Feel free to add new ideas in our discord server - or via github issues! Translations are always welcome! - - - INFORMATION: - ============ - Open Ticket v3.5.8 - © DJdj Development - - discord: https://discord.dj-dj.be - website: https://www.dj-dj.be - github: https://otgithub.dj-dj.be - support e-mail: support@dj-dj.be - - Config files: - ./config.json - ./transcriptconfig.json - - Send ./openticketdebug.txt when there are errors! - */ -/** discord :)*/ -const discord = require("discord.js") -const fs = require('fs') -const {GatewayIntentBits,Partials} = discord -const client = new discord.Client({ - intents:[ - GatewayIntentBits.DirectMessages, - GatewayIntentBits.GuildInvites, - GatewayIntentBits.GuildMembers, - GatewayIntentBits.GuildMessages, - GatewayIntentBits.Guilds, - GatewayIntentBits.MessageContent - ], - partials:[Partials.Channel,Partials.Message] -}) -exports.client = client -client.setMaxListeners(120) -if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","created client") - -//LOAD CONFIG -var tempconfig = require("./config.json") -/**@type {Boolean} */ -var isDevConfig = false - -if (process.argv.some((v) => v == "--devconfig")){ - isDevConfig = true - try{ - tempconfig = require("./devconfig.json") - }catch{tempconfig = require("./config.json")} -}else{ - tempconfig = require("./config.json") -} -if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded flags") - -exports.developerConfig = isDevConfig -const config = tempconfig -exports.config = config -const tsconfig = isDevConfig ? require("./devtsconfig.json") : require("./transcriptconfig.json") -exports.tsconfig = tsconfig - -//LOAD LANGUAGE -const language = require("./core/languageManager").language -exports.language = language - -//LOAD FLAGS -if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded language") - -if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded config") -exports.storage = require('./core/dynamicdatabase/storage').main -if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded storage") - -exports.statsStorage = require('./core/dynamicdatabase/storage').stats -if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded stats storage") - -exports.errorLog = require("./core/errorLogSystem") -if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","LOADED LOGGING SYSTEM") -if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","switching to new logs") -this.errorLog.log("debug","loaded new logs") - -//LOAD SYSTEM LIBRARYS -exports.actionRecorder = require("./core/utils/liveStatus").actionRecorder -exports.hiddenData = require("./core/utils/hiddendata") -this.errorLog.log("debug","loaded hiddendataTM") -exports.embeds = { - commands:require("./core/interactionHandlers/embeds/commands") -} -exports.buttons = { - close:require("./core/interactionHandlers/buttons/close"), - firstmsg:require("./core/interactionHandlers/buttons/firstmsg"), - verifybars:require("./core/interactionHandlers/buttons/verifyBars") -} -this.errorLog.log("debug","loaded buttons & embeds") - -exports.statsManager = require("./core/statsManager") -this.statsManager.startupStatsManager() - -//START CLIENT LOGIN PROCESS -client.on('ready',async () => { - this.errorLog.log("debug","client logged in") - this.actionRecorder.push({ - category:"ot.managers.djs", - file:"index.js", - time:new Date().getTime(), - type:"client.loggedin.success" - }) - const setStatus = (type,text) => { - const getTypeEnum = (type) => { - if (type.toLowerCase() == "playing") return discord.ActivityType.Playing - else if (type.toLowerCase() == "listening") return discord.ActivityType.Listening - else if (type.toLowerCase() == "watching") return discord.ActivityType.Watching - else if (type.toLowerCase() == "custom") return discord.ActivityType.Custom - else return discord.ActivityType.Listening - } - client.user.setActivity({ - type:getTypeEnum(type), - state:(text.toLowerCase() == "custom") ? text : undefined, - name:text - }) - } - this.errorLog.log("debug","bot status loaded") - this.actionRecorder.push({ - category:"ot.managers.djs", - file:"index.js", - time:new Date().getTime(), - type:"client.setstatus.success" - }) - - const chalk = await (await import("chalk")).default - - require("./core/startscreen").run() - this.actionRecorder.push({ - category:"ot.managers.main", - file:"index.js", - time:new Date().getTime(), - type:"startscreen.success" - }) - - if (!process.argv[2] || (process.argv[2] && !process.argv[2].startsWith("slash"))){ - //normal start - this.errorLog.log("debug","loaded console interface") - - if (config.status.enabled){ - setStatus(config.status.type,config.status.text) - //refresh status every 10 minutes - setInterval(() => { - setStatus(config.status.type,config.status.text) - },(60*10*1000)) - } - - this.actionRecorder.push({ - category:"ot.managers.main", - file:"index.js", - time:new Date().getTime(), - type:"startmode.normal" - }) - - var updatingSlash = false - if (fs.existsSync("./storage/slashcmdEnabled.txt")){ - /**@type {"true"|"false"|String} */ - const data = fs.readFileSync("./storage/slashcmdEnabled.txt").toString() - if (data === require("./package.json").version){ - require("./core/slashSystem/autoSlashUpdate")() - updatingSlash = true - - }else if ((data != require("./package.json").version) && (data != "false")){ - require("./core/slashSystem/slashEnable")(true) - updatingSlash = true - } - }else{ - if (process.argv.some((v) => v == "--noslash")){ - fs.writeFileSync("./storage/slashcmdEnabled.txt","false") - }else{ - fs.writeFileSync("./storage/slashcmdEnabled.txt",require("./package.json").version) - require("./core/slashSystem/slashEnable")(true) - updatingSlash = true - } - } - this.actionRecorder.push({ - category:"ot.managers.main", - file:"index.js", - time:new Date().getTime(), - type:"slashcmd.autoupdate.success" - }) - - try { - await client.guilds.cache.find((g) => g.id == config.serverId).members.fetch() - }catch{ - this.errorLog.log("info","tried to cache user information, failed!") - } - require("./core/startscreen").headerDataReady(chalk,config.status,updatingSlash,false) - - }else{ - //slash command activation using node index.js slash (enable|disable) - require("./core/startscreen").headerDataReady(chalk,config.status,updatingSlash,true) - this.errorLog.log("debug","slashmode activated") - if (process.argv[3] == "enable"){ - console.log(chalk.green("switching to slashEnable.js")) - this.actionRecorder.push({ - category:"ot.managers.main", - file:"index.js", - time:new Date().getTime(), - type:"startmode.slash.enable" - }) - require("./core/slashSystem/slashEnable")() - }else if (process.argv[3] == "disable"){ - console.log(chalk.green("switching to slashDisable.js")) - this.actionRecorder.push({ - category:"ot.managers.main", - file:"index.js", - time:new Date().getTime(), - type:"startmode.slash.disable" - }) - require("./core/slashSystem/slashDisable")() - }else{ - console.log(chalk.bgRed("[SLASH CMD MANAGER]: unknown slash command action!")) - process.exit(1) - } - } - - //LOAD PLUGINS (after client login) - this.actionRecorder.push({ - category:"ot.managers.plugins", - file:"./core/api/pluginlauncher.js", - time:new Date().getTime(), - type:"plugins.loading" - }) - require("./core/api/pluginlauncher")() - this.actionRecorder.push({ - category:"ot.managers.plugins", - file:"./core/api/pluginlauncher.js", - time:new Date().getTime(), - type:"plugins.success" - }) - this.errorLog.log("debug","loading plugins") -}) - -//LOAD CHECKER.JS -if (!require("./core/api/api.json").disable.checkerjs.all){ - this.actionRecorder.push({ - category:"ot.managers.main", - file:"./core/checker.js", - time:new Date().getTime(), - type:"checker.loading" - }) - require("./core/checker").checker() - this.errorLog.log("debug","loading checker.js") - this.errorLog.log("debug","checking config...") - this.actionRecorder.push({ - category:"ot.managers.main", - file:"./core/checker.js", - time:new Date().getTime(), - type:"checker.success" - }) -} - -//LOAD COMMANDS & CORE -if (process.argv[2] && process.argv[2].startsWith("slash")){ - //do nothing -}else{ - - this.actionRecorder.push({ - category:"ot.managers.loader", - file:"./index.js", - time:new Date().getTime(), - type:"commands.loading" - }) - this.errorLog.log("debug","LOADING COMMANDS") - //commands - require('./commands/ticket')() - require("./commands/help")() - require("./commands/close")() - require("./commands/delete")() - require("./commands/rename")() - require("./commands/add")() - require("./commands/remove")() - require("./commands/reopen")() - require("./commands/claim")() - require("./commands/unclaim")() - require("./commands/change")() - require("./commands/stats")() - - this.actionRecorder.push({ - category:"ot.managers.loader", - file:"./index.js", - time:new Date().getTime(), - type:"commands.success" - }) - - this.actionRecorder.push({ - category:"ot.managers.loader", - file:"./index.js", - time:new Date().getTime(), - type:"core.loading" - }) - this.errorLog.log("debug","LOADING CORE") - //core - require('./core/ticketActions/ticketOpener')() - require("./core/reactionRoles")() - require("./core/ticketActions/ticketAutoclose")() - - this.errorLog.log("debug","LOADING INTERACTION HANDLERS") - //InteractionHandlers - require("./core/interactionHandlers/handlers/handlers")() - - this.actionRecorder.push({ - category:"ot.managers.loader", - file:"./index.js", - time:new Date().getTime(), - type:"core.success" - }) -} - -//LOAD API -this.actionRecorder.push({ - category:"ot.managers.loader", - file:"./index.js", - time:new Date().getTime(), - type:"api.loading" -}) -this.errorLog.log("debug","loading api") -const APIEvents = require("./core/api/modules/events") -const APIConfig = require("./core/api/api.json") - -this.actionRecorder.push({ - category:"ot.managers.loader", - file:"./index.js", - time:new Date().getTime(), - type:"api.success" -}) - -//ERROR SYSTEM -this.actionRecorder.push({ - category:"ot.managers.loader", - file:"./index.js", - time:new Date().getTime(), - type:"debugsystem.loading" -}) - -const debugLog = (debugString) => { - if (!APIConfig.disable.debug.all && !APIConfig.disable.debug.debuglogs){ - const content = fs.existsSync("./openticketdebug.txt") ? fs.readFileSync("./openticketdebug.txt").toString() : "==========================\n\n==========================" - fs.writeFileSync("./openticketdebug.txt",content+"\nDEBUG: "+debugString) - } - this.errorLog.clearDebugFile() -} -const errorLog = (errorString,stack) => { - if (!APIConfig.disable.debug.all){ - const content = fs.existsSync("./openticketdebug.txt") ? fs.readFileSync("./openticketdebug.txt").toString() : "==========================\n\n==========================" - fs.writeFileSync("./openticketdebug.txt",content+"\nERROR: "+errorString+" STACK: "+stack) - } - this.errorLog.clearDebugFile() -} -this.errorLog.log("debug","OT error system loaded successfully") - -client.on("debug", async (message) => { - if (message.startsWith("Provided token:")){ - debugLog("Provided token: ***********bot token is invisible**************...") - return - } - debugLog(message) -}); - -process.on("uncaughtException",async (error,origin) => { - const chalk = await (await import("chalk")).default - console.log(chalk.red("\nOPEN TICKET ERROR: ")+error+"\n"+chalk.green("\nCreate a ticket in our support server for more information!\nIf you do this, you might help us to avoid a future bug!\n")) - errorLog(error.name+": "+error.message+" | origin: "+origin,error.stack) - - APIEvents.onError(error.name+": "+error.message,new Date()) -}) - -this.actionRecorder.push({ - category:"ot.managers.loader", - file:"./index.js", - time:new Date().getTime(), - type:"debugsystem.success" -}) - -//PARSE .env FILE FROM DOTENV LIB -//npm i dotenv -//https://github.com/motdotla/dotenv -/**@param {Buffer} src */ -const loadFromDotEnv = (src) => { - const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg - - const obj = {} - - // Convert buffer to string - let lines = src.toString() - - // Convert line breaks to same format - lines = lines.replace(/\r\n?/mg, '\n') - - let match - while ((match = LINE.exec(lines)) != null) { - const key = match[1] - - // Default undefined or null to empty string - let value = (match[2] || '') - - // Remove whitespace - value = value.trim() - - // Check if double quoted - const maybeQuote = value[0] - - // Remove surrounding quotes - value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2') - - // Expand newlines if double quoted - if (maybeQuote === '"') { - value = value.replace(/\\n/g, '\n') - value = value.replace(/\\r/g, '\r') - } - - // Add to object - obj[key] = value - } - process.env.TOKEN = obj.TOKEN -} - -//LOGIN SYSTEM -if (config.token.fromENV){ - loadFromDotEnv(fs.readFileSync(".env")) - client.login(process.env.TOKEN) -}else{ - client.login(config.token.value) -} - -this.errorLog.log("debug","login with token") \ No newline at end of file diff --git a/language/arabic.json b/language/arabic.json deleted file mode 100644 index 082dd6e..0000000 --- a/language/arabic.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"deqressing", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors": { - "missingArgsTitle": "قيمة غير صالحة!", - "missingArgsDescription": "قيمة مفقودة", - "noPermsTitle": "ليس لديك برمشنات !", - "noPermsDescription": "أنت بحاجة الى برمشن `ADMINISTRATOR` او أن تكون في قائمة المسموح بهم!", - "noPermsDelete": "فقط الإداريين يمكنهم حذف التيكت!", - "chooseFromListTitle": "الايدي غير صحيح!", - "chooseFromListDescription": "قم بأختيار أحد من الأيديات من الأسفل:", - "boterror": "خلل في البوت !", - "notInTicketTitle": "انت لست في تكت!", - "notInTicketDescription": "هذا الأمر لا يعمل خارج التيكت!", - "ticketDoesntExist": "هذا التيكت لم يعد فعال!", - "roleDoesntExist": "خطاً ,لم تعد الرتبة موجوده!", - "anotherOption": "هذا الخيار ليس التيكت و لكنه شيء أخر!", - "maxAmountTitle": "خطأ , تم الوصول الى الحد الأقصى!", - "maxAmountDescription": "لقد وصلت الى الحد الأقصى لعدد التيكتات المسموحة بها!\nSo لا يمكنك فتح واحدة أخرى!", - "somethingWentWrong": "**هناك خطاً!**\nأعد المحاولة لاحقاً!" - }, - "commands": { - "userAddedTitle": "تم أضافة {0} من المستخدمين في التيكت!", - "userRemovedTitle": "تم أزالة {0} من المستخدمين من التيكت!", - "renameTitle": "تم تغيير أسم التيكت الى {0}!", - "closeTitle": "تم أغلاق التيكت!", - "deleteTitle": " جاري حذف التيكت...", - "reopenTitle": "إعادة فتح التيكت!", - - "claimTitle":"تم تعيين التيكت الى {0}", - "unclaimTitle":"هذا التيكت لم يتم تعيينه لاحد", - "changeTitle":"!تم تغيير نوع التيكت الى {0}", - - "statsTitle":"ها هي احصائيات {0}", - "autocloseTitle":"سيتم اغلاق التيكت تلقائيا في {0}", - "autocloseRejectTitle":"تم الغاء اغلاق التيكت تلقائيا", - "autocloseWarn":"هذا يؤثر فقط على التذاكر الغير نشطة", - - "goToTicket":"الذهاب الى التيكت", - "ticketWarning": "هذا الأمبد موجود بالفعل في الرسالة بالأسفل!", - "maxTicketWarning": "**تحذير:** _يمكنك فقط فتح {0} تكت في الوقت!_" - }, - "helpMenu": { - "title": "الأوامر المتاحة:", - "header1": "**أذهب الى {0} لإنشاء تذكرة!**\n\n", - "header2": "**قم بكتابة أمر `/new` او `/ticket` لفتح تكت!**\n\n", - - "msgCmd": "أنشاء أيمبد مع الأزرار. (الأداريين فقط)", - "renameCmd": "إعادة تسمية التيكت. (بدون مسافات)", - "closeCmd": "أغلاق التيكت.", - "deleteCmd": "حذف التيكت.", - "addCmd": "إضافة مستخدم الى التيكت.", - "removeCmd": "إزالة مستخدم من التيكت.", - "reopenCmd": "إعادة فتح تكت بعد إغلاقة.", - "changeCmd":"تغيير نوع التيكت.", - "claimCmd":"تعيينك لتيكت معين.", - "unclaimCmd":"الغاء التغيين لتيكت معين", - "statsCmd":"اضهار احصائيات التيكت", - "autocloseCmd":"قم بضبط مؤقت لاغلاق التيكت تلقائياً" - }, - "buttons": { - "close": "إغلاق التيكت", - "delete": "حذف التيكت", - "reopen": "إعادة فتح التيكت", - "closeWithReason":"اغلاق مع سبب" - }, - "messages": { - "closedDescription": "فقط الأداريين يمكنهم التحدث في هذا التيكت الأن!\n\n*أضغط على الزر بالأسفل لحذف التيكت او إعادة فتحة مجدداً!*", - "createdTitle": "تم إنشاء تكت!", - "createdDescription": "تم أنشاء تكت , قم بأنتظار الدعم في الطريق!", - - "newTicketDmTitle": "تكت جديد!", - "closedTicketDmTitle": "تم إغلاق التيكت!", - "deletedTicketDmTitle": "تم حذف التيكت!", - "closedTicketDmDescription": "تم أغلاق تذكرتك من قبل إداري", - "deletedTicketDmDescription": "تم حذف تذكرتك من قبل إداري!", - "reopenTicketDmTitle": "تم إعادة فتح تذكرتك!", - "reopenTicketDmDescription": "تم إعادة فتح التيكت!", - - "chooseCategory": "أختر الكتقاجوري:", - "gettingdeleted": "يتم حذف التيكت...", - - "none": "لا يوجد", - "reason": "سبب", - "createdat":"تم الانشاء في", - "openedby":"تم الانشاء من قبل", - "deletedby":"تم الحذف من قبل", - "closedby":"تم الاغلاق من قبل", - - "modalreason":"ماهو سببك لاغلاق التيكت؟", - "chooseATicket": "اختار تيكت معين" - }, - "transcripts":{ - "title":"سجل", - "processed":"يتم معالجة هذا السجل...", - "wait":"فضلا انتظر", - "estimated":"الوقت المتوقع", - "available":"تم انشاء السجل وهو متاح هنا" - }, - "stats":{ - "globalTitle":"احصائيات العامه", - "ticketTitle":"احصائيات التيكت ل {0}", - "userTitle":"احصائيات المستخدم {0}", - "systemTitle":"احصائيات السيستم", - "versionTitle":"نسخة البوت", - - "ticketsCreated":"التيكتس التي تمت انشاؤه", - "ticketsClosed":"التيكتس التي تمت اغلاقه", - "ticketsDeleted":"التيكتس التي تمت حذفه", - "ticketsReopened":"التيكتس التي تمت العادة فتحه", - "ticketsAutoclosed":"التيكتس التي تمت اغلاقه تلقائيا", - "transcriptsCreated":"السجلات التي تمت انشاؤه", - "startupDate":"تم تشغيل البوت في", - "latestUpdate":"اخر التحديثات", - "ticketCreatedOn":"تم انشاءالتيكت في", - "ticketCreatedBy":"تم انشاء التيكت من قبل", - "messagesSent":"جميع الرسائل", - "status":"الحالة", - "participants":"المشاركون", - "role":"الرانك", - - "switches":{ - "globalAdmin":"ادمن عام", - "ticketAdmin":"ادمن تيكت", - "member":"عضو", - "open":"مفتوح", - "reopened":"اعادة فتحه", - "closed":"مغلق", - "autoclosed":"مغلق تلقائياً" - }, - - "errorUserNotFound":"هذا المستخدم لم يتم العثور عليه في قاعدة بياناتنا!" - } -} \ No newline at end of file diff --git a/language/bulgarian.json b/language/bulgarian.json deleted file mode 100644 index 4e18255..0000000 --- a/language/bulgarian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"Stragar", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Грешни Аргументи!", - "missingArgsDescription":"Липсват Аргументи", - "noPermsTitle":"Нямате позволение!", - "noPermsDescription":"Трябва ви `ADMINISTRATOR` правомощия или да бъде в списъка с роли!", - "noPermsDelete":"Само админ може да изтрива тикети!", - "chooseFromListTitle":"Грешно ID", - "chooseFromListDescription":"Choose one of the id's below:", - "boterror":"Грешка на Бота!", - "notInTicketTitle":"Не сте в билет!", - "notInTicketDescription":"Тази команда не работи извън тикета!", - "ticketDoesntExist":"Този тикет е изтрит!", - "roleDoesntExist":"Тази роля вече не съществува!", - "anotherOption":"Тази опция не е тикет, а друг вид!", - "maxAmountTitle":"Достигнахте максимален лимит!", - "maxAmountDescription":"Вече имате прекалено много брой тикети!\nНе може да създадете нов!", - "somethingWentWrong":"**Нещо се обърка!**\nОпитай отново след малко!" - }, - "commands":{ - "userAddedTitle":"Добавен {0} в тикета!", - "userRemovedTitle":"Премахнат {0} от тикета!", - "renameTitle":"Името е сменено на {0}!", - "closeTitle":"Затворете тикета", - "deleteTitle":"Изтрийте този тикет...", - "reopenTitle":"Отоворете тикета отново!", - - "claimTitle":"Този тикет е взет от {0}", - "unclaimTitle":"Този тикет не може да бъде взет вече!", - "changeTitle":"Changed ticket type to {0}!", - - "statsTitle":"Статистика за {0}!", - "autocloseTitle":"Този тикет ще се затвори автоматично след {0}!", - "autocloseRejectTitle":"Този тикет вече няма да се затваря автоматично!", - "autocloseWarn":"Това засяга само неактивни тикети!", - - "goToTicket":"отидете на тикет", - "ticketWarning":"Текста е добавен по-долу!", - "maxTicketWarning":"**Предопреждение:** _Ти можеш да създадеш {0} тикети(s) време!_" - }, - "helpMenu":{ - "title":"Налични команди:", - "header1":"**Отидете на {0}, за да създадете тикет!**\n\n", - "header2":"**Изпълнете командата `/new` или `/ticket`, за да създадете тикет!**\n\n", - - "msgCmd":"Създаване на вградено съобщение с бутони. (само за администратори)", - "renameCmd":"Преименувайте билет. (без интервали)", - "closeCmd":"Затвори билет.", - "deleteCmd":"Изтрий билет.", - "addCmd":"Добави потребител към билета.", - "removeCmd":"Премахни потребител от билета.", - "reopenCmd":"Повторно отваряне на билет след като е затворен.", - "changeCmd":"Промени типа на билета.", - "claimCmd":"Претендирай за билет.", - "unclaimCmd":"Откажи претенцията за билет.", - "statsCmd":"Преглед на статистиката на билета.", - "autocloseCmd":"Задай таймер за автоматично затваряне на билета" - }, - "buttons":{ - "close":"Затвори билет", - "delete":"Изтрий билет", - "reopen":"Повторно отвори билет", - "closeWithReason":"затвори с причина" - }, - "messages":{ - "closedDescription":"Само администраторите могат да говорят в този билет сега!\n\n*Кликнете върху бутона по-долу, за да изтриете или повторно отворите този билет!*", - "createdTitle":"Създаден билет!", - "createdDescription":"Вашият билет е създаден, можете да го забележите по пинг!", - - "newTicketDmTitle":"Нов билет!", - "closedTicketDmTitle":"Билетът е затворен!", - "deletedTicketDmTitle":"Билетът е изтрит!", - "closedTicketDmDescription":"Вашият билет е затворен!", - "deletedTicketDmDescription":"Вашият билет е изтрит!", - "reopenTicketDmTitle":"Билетът е повторно отворен!", - "reopenTicketDmDescription":"Вашият билет е повторно отворен!", - - "chooseCategory":"изберете категория:", - "gettingdeleted":"Билетът се изтрива...", - - "none":"няма", - "reason":"причина", - "createdat":"създаден на", - "openedby":"отворен от", - "deletedby":"изтрит от", - "closedby":"затворен от", - - "modalreason":"Каква е причината за затваряне на този билет?", - "chooseATicket": "Изберете билет" - }, - "transcripts":{ - "title":"Транскрипт", - "processed":"Този транскрипт се обработва", - "wait":"Моля, изчакайте!", - "estimated":"Приблизително време", - "available":"Транскриптът е достъпен тук" - }, - "stats":{ - "globalTitle":"Глобална статистика", - "ticketTitle":"Статистика на билета за {0}", - "userTitle":"Статистика на потребителя за {0}", - "systemTitle":"Системна статистика", - "versionTitle":"Версия на бота", - - "ticketsCreated":"Създадени билети", - "ticketsClosed":"Затворени билети", - "ticketsDeleted":"Изтрити билети", - "ticketsReopened":"Повторно отворени билети", - "ticketsAutoclosed":"Автоматично затворени билети", - "transcriptsCreated":"Създадени транскрипти", - "startupDate":"Дата на стартиране", - "latestUpdate":"Последно обновление", - "ticketCreatedOn":"Билет създаден на", - "ticketCreatedBy":"Билет създаден от", - "messagesSent":"Изпратени съобщения", - "status":"Статус", - "participants":"Участници", - "role":"Роля", - - "switches":{ - "globalAdmin":"Глобален администратор", - "ticketAdmin":"Администратор на билет", - "member":"Член", - "open":"Отворен", - "reopened":"Повторно отворен", - "closed":"Затворен", - "autoclosed":"Автоматично затворен" - }, - - "errorUserNotFound":"Този потребител не може да бъде намерен в базата данни за статистика!" - } -} \ No newline at end of file diff --git a/language/custom.json b/language/custom.json deleted file mode 100644 index c7ae715..0000000 --- a/language/custom.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"DJdj Development", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Invalid Arguments!", - "missingArgsDescription":"Missing Argument", - "noPermsTitle":"No Permissions!", - "noPermsDescription":"You need the `ADMINISTRATOR` permission or be in the list of allowed roles!", - "noPermsDelete":"Only admins can delete a ticket!", - "chooseFromListTitle":"Invalid ID", - "chooseFromListDescription":"Choose one of the id's below:", - "boterror":"Bot Error!", - "notInTicketTitle":"You are not in a ticket!", - "notInTicketDescription":"This command doesn't work outside tickets!", - "ticketDoesntExist":"This ticket doesn't exist anymore!", - "roleDoesntExist":"This role doesn't exist anymore!", - "anotherOption":"This option is not a ticket but another type!", - "maxAmountTitle":"Max amount reached!", - "maxAmountDescription":"You reached the maximum number of tickets allowed!\nSo you can't create a new one!", - "somethingWentWrong":"**Something went wrong!**\nPlease try again another time!" - }, - "commands":{ - "userAddedTitle":"Added {0} to this ticket!", - "userRemovedTitle":"Removed {0} from this ticket!", - "renameTitle":"Changed the name to {0}!", - "closeTitle":"Closed this ticket!", - "deleteTitle":"Deleting this ticket...", - "reopenTitle":"Re-Opened this ticket!", - - "claimTitle":"This ticket is claimed to {0}", - "unclaimTitle":"This ticket isn't claimed anymore!", - "changeTitle":"Changed ticket type to {0}!", - - "statsTitle":"Here are the stats for {0}!", - "autocloseTitle":"This ticket will be closed automatically after {0}!", - "autocloseRejectTitle":"This ticket will no longer be closed automatically!", - "autocloseWarn":"This only affects inactive tickets!", - - "goToTicket":"go to ticket", - "ticketWarning":"The embed is in the message below!", - "maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_" - }, - "helpMenu":{ - "title":"Available Commands:", - "header1":"**Go to {0} to create a ticket!**\n\n", - "header2":"**Run the command `/new` or `/ticket` to create a ticket!**\n\n", - - "msgCmd":"Spawn an embed with buttons. (admins only)", - "renameCmd":"Rename a ticket. (no spaces)", - "closeCmd":"Close a ticket.", - "deleteCmd":"Delete a ticket.", - "addCmd":"Add a user to the ticket.", - "removeCmd":"Remove a user from the ticket.", - "reopenCmd":"Re-Open a ticket after it was closed.", - "changeCmd":"Change ticket type.", - "claimCmd":"Claim a ticket.", - "unclaimCmd":"Unclaim a ticket.", - "statsCmd":"View ticket stats.", - "autocloseCmd":"Set timer to automatically close ticket" - }, - "buttons":{ - "close":"Close Ticket", - "delete":"Delete Ticket", - "reopen":"Re-Open Ticket", - "closeWithReason":"close with reason" - }, - "messages":{ - "closedDescription":"Only admins can talk in this ticket now!\n\n*Click on the button below to delete or to re-open this ticket!*", - "createdTitle":"Ticket Created!", - "createdDescription":"Your ticket is created, you can detect it by a ping!", - - "newTicketDmTitle":"New Ticket!", - "closedTicketDmTitle":"Ticket Closed!", - "deletedTicketDmTitle":"Ticket Deleted!", - "closedTicketDmDescription":"Your ticket is closed!", - "deletedTicketDmDescription":"Your ticket is deleted!", - "reopenTicketDmTitle":"Ticket Re-opened!", - "reopenTicketDmDescription":"Your ticket is re-opened!", - - "chooseCategory":"choose a category:", - "gettingdeleted":"Ticket is getting deleted...", - - "none":"none", - "reason":"reason", - "createdat":"created at", - "openedby":"opened by", - "deletedby":"deleted by", - "closedby":"closed by", - - "modalreason":"What is the reason for closing this ticket?", - "chooseATicket": "Choose a ticket" - }, - "transcripts":{ - "title":"Transcript", - "processed":"This transcript is being processed", - "wait":"Please wait!", - "estimated":"Estimated time", - "available":"The transcript is available here" - }, - "stats":{ - "globalTitle":"Global Stats", - "ticketTitle":"Ticket Stats for {0}", - "userTitle":"User Stats for {0}", - "systemTitle":"System Stats", - "versionTitle":"Bot Version", - - "ticketsCreated":"Tickets Created", - "ticketsClosed":"Tickets Closed", - "ticketsDeleted":"Tickets Deleted", - "ticketsReopened":"Tickets Reopened", - "ticketsAutoclosed":"Tickets Autoclosed", - "transcriptsCreated":"Transcripts Created", - "startupDate":"Startup Date", - "latestUpdate":"Latest Update", - "ticketCreatedOn":"Ticket Created On", - "ticketCreatedBy":"Ticket Created By", - "messagesSent":"Messages Sent", - "status":"Status", - "participants":"Participants", - "role":"Role", - - "switches":{ - "globalAdmin":"Global Admin", - "ticketAdmin":"Ticket Admin", - "member":"Member", - "open":"Open", - "reopened":"Reopened", - "closed":"Closed", - "autoclosed":"Autoclosed" - }, - - "errorUserNotFound":"This user can't be found in the stats database!" - } -} \ No newline at end of file diff --git a/language/czech.json b/language/czech.json deleted file mode 100644 index 848cf47..0000000 --- a/language/czech.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"spyeye_", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Neplatný Argument!", - "missingArgsDescription":"Chybí Argument", - "noPermsTitle":"K tomuto nemáš práva!", - "noPermsDescription":"Potřebuješ `ADMINISTRATOR` roli nebo být na seznamu povolených rolí!", - "noPermsDelete":"Pouze Admin může vymazat ticket!", - "chooseFromListTitle":"Neplatné ID", - "chooseFromListDescription":"Vyber si jedno z ID níže:", - "boterror":"Chyba Bota!", - "notInTicketTitle":"Nejsi v ticketu!", - "notInTicketDescription":"Tento příkaz nefunguje mimo ticket!", - "ticketDoesntExist":"Tento ticket už neexistuje!", - "roleDoesntExist":"Tato role už neexistuje!", - "anotherOption":"Tato možnost není ticket, ale jiná!", - "maxAmountTitle":"Byl dosáhnut maximální počet", - "maxAmountDescription":"Dosáhl jsi maximální počet povolených ticketů!\nTakže si nemůžeš vytvořit nový.", - "somethingWentWrong":"**Něco se pokazilo!**\nProsíme zkuste to později!" - }, - "commands":{ - "userAddedTitle":"Přidat {0} do tohoto ticketu.", - "userRemovedTitle":"Odstranit {0} z tohoto ticketu.", - "renameTitle":"Změnit jméno na {0}!", - "closeTitle":"Uzavřít tento ticket!", - "deleteTitle":"Probíhá vymazání ticketu...", - "reopenTitle":"Ticket byl znovu otevřen", - - "claimTitle":"Ticket nyní převzal {0}", - "unclaimTitle":"Ticket není nadále převzaný", - "changeTitle":"Typ ticketu byl změněn {0}!", - - "statsTitle":"Zde jsou informace o ticketu {0}!", - "autocloseTitle":"Tento ticket bude automaticky uzavřen za {0}!", - "autocloseRejectTitle":"Tento ticket již nebude automaticky uzavřen!", - "autocloseWarn":"Tato možnost uzavře pouze neaktivní tickety!", - - "goToTicket":"Jít do ticketu", - "ticketWarning":"Embed se náchází pod touto zprávou.", - "maxTicketWarning":"**Warning:** _V tuto chvíli můžeš vytvořit pouze {0} ticketů_" - }, - "helpMenu":{ - "title":"Zde jsou všechny dostupné příkazy:", - "header1":"**Pro vytvoření ticketu bež do {0} **\n\n", - "header2":"**Použij příkaz `/new` nebo `/ticket` pro vytvoření nového ticketu**\n\n", - - "msgCmd":"Vytvoř embed s tlačíky. (Pouze Admin)", - "renameCmd":"Přejmenovat ticket. (Bez mezer)", - "closeCmd":"Zavřít ticket.", - "deleteCmd":"Odstranit ticket.", - "addCmd":"Přidat uživatele do ticketu.", - "removeCmd":"Odebrat uživatele z ticketu.", - "reopenCmd":"Znovu otevře ticket, který byl uzavřen.", - "changeCmd":"Změnit typ ticketu.", - "claimCmd":"Převzi ticket.", - "unclaimCmd":"Uvolnit ticket.", - "statsCmd":"Zobrazit info o ticketu.", - "autocloseCmd":"Nastavit automatické uzavření ticketu" - }, - "buttons":{ - "close":"Uzavřít ticket", - "delete":"Vymazat ticket", - "reopen":"Znovu otevřít ticket", - "closeWithReason":"Zavřít s důvodem" - }, - "messages":{ - "closedDescription":"Zde mohou psát pouze Admin uživatelé\n\n*Klikni na tlačítko níže pro smazání nebo pro znovu otevření tohoto ticketu!*", - "createdTitle":"Ticket otevřen!", - "createdDescription":"Tvůj ticket je vytvořen, můžeš si ho všimnout pomocí pingu!", - - "newTicketDmTitle":"Nový ticket!", - "closedTicketDmTitle":"Ticket byl Uzavřen!", - "deletedTicketDmTitle":"Ticket byl Odstraněn!", - "closedTicketDmDescription":"Tvůj ticket je uzavřen!", - "deletedTicketDmDescription":"Tvůj ticket byl vymazán!", - "reopenTicketDmTitle":"Ticket je znovu otevřený!", - "reopenTicketDmDescription":"Tvůj ticket byl znovu otevřený!", - - "chooseCategory":"Vyber si kategorii:", - "gettingdeleted":"Ticket bude vymazán...", - - "none":"Žádný", - "reason":"Důvod", - "createdat":"Otevřeno v", - "openedby":"Otevřel", - "deletedby":"Vymázáno uživatelem", - "closedby":"Uzavřeno uživatelem", - - "modalreason":"Zde napiš důvod uzavření tohoto ticketu.", - "chooseATicket": "Vyber si ticket" - }, - "transcripts":{ - "title":"Záznam", - "processed":"Tento záznam byl zpracován", - "wait":"Prosím počkej!", - "estimated":"Odhadovaný čas", - "available":"Záloha je uložena zde." - }, - "stats":{ - "globalTitle":"Globální statistiky", - "ticketTitle":"Ticket statistiky pro {0}", - "userTitle":"Uživatelské statistiky pro {0}", - "systemTitle":"Systémové statistiky", - "versionTitle":"Verze bota", - - "ticketsCreated":"Ticketů vytvořeno:", - "ticketsClosed":"Tickety zavřeno:", - "ticketsDeleted":"Ticketu smazáno:", - "ticketsReopened":"Ticketů znovuotevřených:", - "ticketsAutoclosed":"Ticketů automaticky zavřeno:", - "transcriptsCreated":"Záloh ticketů vytvořeno:", - "startupDate":"Datum zapnutí", - "latestUpdate":"Poslední aktualizace", - "ticketCreatedOn":"Ticket založen na", - "ticketCreatedBy":"Ticket vytvořil", - "messagesSent":"Zpráva poslána", - "status":"Status", - "participants":"Účastníci", - "role":"Role", - - "switches":{ - "globalAdmin":"Globální Admin", - "ticketAdmin":"Ticket Admin", - "member":"Člen", - "open":"Otevřený", - "reopened":"Znovuotevřený", - "closed":"Zavřený", - "autoclosed":"Automaticky zavřený" - }, - - "errorUserNotFound":"Tento uživatel nebyl nalezen v databázi statistik!" - } -} \ No newline at end of file diff --git a/language/danish.json b/language/danish.json deleted file mode 100644 index dc70bf3..0000000 --- a/language/danish.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":".the_gamer", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors": { - "missingArgsTitle": "Ugyldigt Argument!", - "missingArgsDescription": "Manglende Argument", - "noPermsTitle": "Ikke tilladelse!", - "noPermsDescription": "Du skal have tilladelsen `ADMINISTRATOR` eller være på listen over tilladte roller!", - "noPermsDelete": "Kun administratorer kan slette en ticket!", - "chooseFromListTitle": "Ugyldigt ID", - "chooseFromListDescription": "Vælg et af id'erne nedenfor:", - "boterror": "Bot Fejl!", - "notInTicketTitle": "Du er ikke i en ticket!", - "notInTicketDescription": "Denne kommando virker ikke udenfor tickets!", - "ticketDoesntExist": "Denne ticket findes ikke længere!", - "roleDoesntExist": "Denne rolle eksisterer ikke længere!", - "anotherOption": "Denne mulighed er ikke en ticket, men en anden type!", - "maxAmountTitle": "Maks. mængde opnået!", - "maxAmountDescription": "Du har nået det maksimale antal tilladte tickets!\nSå du kan ikke oprette en ny!", - "somethingWentWrong": "**Noget gik galt!**\nPrøv venligst igen en anden gang!" - }, - "commands": { - "userAddedTitle": "Føjede {0} til denne ticket!", - "userRemovedTitle": "Fjernede {0} fra denne ticket!", - "renameTitle": "Ændrede navnet til {0}!", - "closeTitle": "Lukket denne ticket!", - "deleteTitle": "Sletter denne ticket...", - "reopenTitle": "Genåbnede denne ticket!", - - "claimTitle": "Denne ticket bliver nu håndteret af {0}", - "unclaimTitle": "Denne ticket bliver ikke håndteret længere!", - "changeTitle": "Ændrede ticket-type til {0}!", - - "statsTitle": "Her er statestikerne til {0}!", - "autocloseTitle": "Denne ticket lukker automatisk om {0}!", - "autocloseRejectTitle": "Denne ticket lukker ikke længere automatisk!", - "autocloseWarn": "Dette har kun effekt på inaktive tickets!", - - "goToTicket": "gå til ticket", - "ticketWarning": "Embedet er i meddelelsen nedenfor!", - "maxTicketWarning": "**Warning:** _Du kan kun oprette {0} ticket(s) ad gangen!_" - }, - "helpMenu": { - "title": "Tilgængelige kommandoer:", - "header1": "**Gå til {0} for at oprette en ticket!**\n\n", - "header2": "**Kør kommandoen `/new` eller `/ticket` for at oprette en billet!**\n\n", - - "msgCmd": "Lav et embed med buttons. (kun administratorer)", - "renameCmd": "Omdøb en ticket. (Ingen Mellemrum!!)", - "closeCmd": "Luk en ticket.", - "deleteCmd": "Slet en ticket.", - "addCmd": "Tilføj en bruger til ticketen.", - "removeCmd": "Fjern en bruger fra ticketen.", - "reopenCmd": "Genåbn en ticket, efter at den var lukket.", - "changeCmd": "Skift ticket type.", - "claimCmd": "Håndter en ticket.", - "unclaimCmd": "Afhåndter en ticket.", - "statsCmd": "Se ticket statestiker.", - "autocloseCmd": "Angiv tiden til automatisk at lukke en ticket" - }, - "buttons": { - "close": "Luk Ticket", - "delete": "Slet Ticket", - "reopen": "Genåben Ticket", - "closeWithReason": "Luk med grundlag" - }, - "messages": { - "closedDescription": "Kun administratorer kan tale i denne billet nu!\n\n*Klik på knappen nedenfor for at slette eller genåbne denne billet!", - "createdTitle": "Ticket Oprettet!", - "createdDescription": "Din ticket er oprettet, du kan registrere den ved et ping!", - - "newTicketDmTitle": "Nt Ticket!", - "closedTicketDmTitle": "Ticket Lukket!", - "deletedTicketDmTitle": "Ticket Slettet!", - "closedTicketDmDescription": "Din ticket er lukket!", - "deletedTicketDmDescription": "Din ticket er slettet!", - "reopenTicketDmTitle": "Ticket Genåbnet!", - "reopenTicketDmDescription": "Din ticket er genåbnet!", - - "chooseCategory": "vælg en kategori:", - "gettingdeleted": "Ticketen bliver slettet...", - - "none": "intet", - "reason": "grundlag", - "createdat": "lavet af", - "openedby": "åbnet af", - "deletedby": "slettet af", - "closedby": "lukket af", - - "modalreason": "Hvad er grunden til at lukke denne ticket?", - "chooseATicket": "Vælg en ticket" - }, - "transcripts": { - "title": "Transcript", - "processed": "Dette transcript er under behandling", - "wait": "Vent venligst!", - "estimated": "Estimeret tid", - "available": "Transcriptet er tilgængelig her" - }, - "stats":{ - "globalTitle":"Globale Statestikker", - "ticketTitle":"Ticket Statestikker tilhørende: {0}", - "userTitle":"Bruger Statestikker tilhørende: {0}", - "systemTitle":"System Statestikker", - "versionTitle":"Bot Version", - - "ticketsCreated":"Tickets Oprettet", - "ticketsClosed":"Tickets Lukket", - "ticketsDeleted":"Tickets Slettet", - "ticketsReopened":"Tickets Genåbnet", - "ticketsAutoclosed":"Tickets Autolukket", - "transcriptsCreated":"Transcripts Oprettet", - "startupDate":"Startup Dato", - "latestUpdate":"Seneste Opdatering", - "ticketCreatedOn":"Ticket Oprettet Den", - "ticketCreatedBy":"Ticket Oprettet Af", - "messagesSent":"Beskeder sendt", - "status":"Status", - "participants":"Deltagere", - "role":"Rolle", - - "switches":{ - "globalAdmin":"Global Admin", - "ticketAdmin":"Ticket Admin", - "member":"Medlem", - "open":"Åben", - "reopened":"Genåbnet", - "closed":"Lukket", - "autoclosed":"Autolukket" - }, - - "errorUserNotFound":"Denne bruger kan ikke findes i statestik databasen!" -} -} \ No newline at end of file diff --git a/language/dutch.json b/language/dutch.json deleted file mode 100644 index 4ba5b58..0000000 --- a/language/dutch.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"djj123dj", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Onjuiste parameters!", - "missingArgsDescription":"Er missen parameters", - "noPermsTitle":"Geen permissies!", - "noPermsDescription":"Je hebt de `ADMINISTRATOR` permissie nodig of je moet in de lijst van toegestane users staan!", - "noPermsDelete":"Alleen admins kunnen een ticket verwijderen!", - "chooseFromListTitle":"Onjuist ID", - "chooseFromListDescription":"Kies een van de id's hier onder:", - "boterror":"Bot Error!", - "notInTicketTitle":"Je bent niet in een ticket!", - "notInTicketDescription":"Deze command werkt niet buiten tickets!", - "ticketDoesntExist":"Dit ticket bestaat niet meer!", - "roleDoesntExist":"Deze rol bestaat niet meer!", - "anotherOption":"Deze optie is niet een ticket, maar een ander type!", - "maxAmountTitle":"Maximum numer bereikt!", - "maxAmountDescription":"Je hebt het maximum aantal openstaande tickets bereikt!\nDus je kan geen nieuwe meer maken!", - "somethingWentWrong":"**Iets ging fout!**\nProbeer een andere keer opnieuw!" - }, - "commands":{ - "userAddedTitle":"{0} is toegevoegd aan dit ticket!", - "userRemovedTitle":"{0} is verwijderd van dit ticket!", - "renameTitle":"De naam is veranderd naar {0}!", - "closeTitle":"Ticket gesloten!", - "deleteTitle":"Ticket aan het verwijderen...", - "reopenTitle":"Ticket heropend!", - - "claimTitle":"Dit ticket is geclaimed door {0}", - "unclaimTitle":"Dit ticket is niet meer geclaimed!", - "changeTitle":"Ticket type veranderd naar {0}!", - - "statsTitle":"Hier zijn de stats voor {0}!", - "autocloseTitle":"Dit ticket wordt automatisch gesloten na {0}!", - "autocloseRejectTitle":"Dit ticket wordt niet langer automatisch gesloten!", - "autocloseWarn":"Dit geldt alleen voor inactieve tickets!", - - "goToTicket":"ga naar ticket", - "ticketWarning":"De embed is in het bericht hier onder!", - "maxTicketWarning":"**Waarschuwing:** _Je kan maar {0} ticket(s) tegelijkertijd maken!_" - }, - "helpMenu":{ - "title":"Beschikbare Commands:", - "header1":"**Ga naar {0} om een ticket te maken!**\n\n", - "header2":"**Run de command `/new` of `/ticket` om een ticket te maken!**\n\n", - - "msgCmd":"Spawn een embed met knoppen. (alleen admins)", - "renameCmd":"Hernoem een ticket. (geen spaties)", - "closeCmd":"Sluit een ticket.", - "deleteCmd":"Verijder een ticket.", - "addCmd":"Voeg een user aan een ticket.", - "removeCmd":"Verwijder een user van een ticket.", - "reopenCmd":"Heropen een ticket nadat het gesloten is.", - "changeCmd":"Verander ticket type.", - "claimCmd":"Claim een ticket.", - "unclaimCmd":"Unclaim een ticket.", - "statsCmd":"Bekijk ticket stats.", - "autocloseCmd":"Zet een timer om het ticket automatisch te sluiten" - }, - "buttons":{ - "close":"Sluit Ticket", - "delete":"Verwijder Ticket", - "reopen":"Heropen Ticket", - "closeWithReason":"sluit met reden" - }, - "messages":{ - "closedDescription":"Alleen admins kunnen nog praten.\n\n*Klik op de knoppen hieronder voor meer acties!*", - "createdTitle":"Ticket Aangemaakt!", - "createdDescription":"U ticket is gemaakt, je kan het detecteren bij een ping!", - - "newTicketDmTitle":"Nieuw Ticket!", - "closedTicketDmTitle":"Ticket Gesloten!", - "deletedTicketDmTitle":"Ticket Verwijderd!", - "closedTicketDmDescription":"Je ticket is gesloten!", - "deletedTicketDmDescription":"Je ticket is verwijderd!", - "reopenTicketDmTitle":"Ticket Heropend!", - "reopenTicketDmDescription":"Je ticket is heropend!", - - "chooseCategory":"kies een categorie:", - "gettingdeleted":"Ticket wordt verwijderd...", - - "none":"geen", - "reason":"reden", - "createdat":"gecreëerd op", - "openedby":"geopend door", - "deletedby":"verwijderd door", - "closedby":"gesloten door", - - "modalreason":"Wat is de reden om dit ticket te sluiten?", - "chooseATicket": "Kies een ticket" - }, - "transcripts":{ - "title":"Transcript", - "processed":"Dit transcript wordt verwerkt", - "wait":"Gelieve te wachten!", - "estimated":"Geschatte tijd", - "available":"Het transcript is hier beschikbaar" - }, - "stats":{ - "globalTitle":"Globale Stats", - "ticketTitle":"Ticket Stats voor {0}", - "userTitle":"User Stats voor {0}", - "systemTitle":"Systeem Stats", - "versionTitle":"Bot Versie", - - "ticketsCreated":"Tickets Gemaakt", - "ticketsClosed":"Tickets Gesloten", - "ticketsDeleted":"Tickets Verwijderd", - "ticketsReopened":"Tickets Heropend", - "ticketsAutoclosed":"Tickets Auto-gesloten", - "transcriptsCreated":"Transcripts Gemaakt", - "startupDate":"Opstart Datum", - "latestUpdate":"Laatste Update", - "ticketCreatedOn":"Ticket Gemaakt Op", - "ticketCreatedBy":"Ticket Gemaakt Door", - "messagesSent":"Berichten Verzonden", - "status":"Status", - "participants":"Deelnemers", - "role":"Rol", - - "switches":{ - "globalAdmin":"Globale Admin", - "ticketAdmin":"Ticket Admin", - "member":"Member", - "open":"Open", - "reopened":"Heropend", - "closed":"Gesloten", - "autoclosed":"Auto-gesloten" - }, - - "errorUserNotFound":"Deze user kan niet in de database gevonden worden!" - } -} \ No newline at end of file diff --git a/language/english.json b/language/english.json deleted file mode 100644 index 02bab43..0000000 --- a/language/english.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"DJdj Development", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Invalid Arguments!", - "missingArgsDescription":"Missing Argument", - "noPermsTitle":"No Permissions!", - "noPermsDescription":"You need the `ADMINISTRATOR` permission or be in the list of allowed roles!", - "noPermsDelete":"Only admins can delete a ticket!", - "chooseFromListTitle":"Invalid ID", - "chooseFromListDescription":"Choose one of the id's below:", - "boterror":"Bot Error!", - "notInTicketTitle":"You are not in a ticket!", - "notInTicketDescription":"This command doesn't work outside tickets!", - "ticketDoesntExist":"This ticket doesn't exist anymore!", - "roleDoesntExist":"This role doesn't exist anymore!", - "anotherOption":"This option is not a ticket but another type!", - "maxAmountTitle":"Max amount reached!", - "maxAmountDescription":"You reached the maximum number of tickets allowed!\nSo you can't create a new one!", - "somethingWentWrong":"**Something went wrong!**\nPlease try again another time!" - }, - "commands":{ - "userAddedTitle":"Added {0} to this ticket!", - "userRemovedTitle":"Removed {0} from this ticket!", - "renameTitle":"Changed the name to {0}!", - "closeTitle":"Closed this ticket!", - "deleteTitle":"Deleting this ticket...", - "reopenTitle":"Re-Opened this ticket!", - - "claimTitle":"This ticket is claimed to {0}", - "unclaimTitle":"This ticket isn't claimed anymore!", - "changeTitle":"Changed ticket type to {0}!", - - "statsTitle":"Here are the stats for {0}!", - "autocloseTitle":"This ticket will be closed automatically after {0}!", - "autocloseRejectTitle":"This ticket will no longer be closed automatically!", - "autocloseWarn":"This only affects inactive tickets!", - - "goToTicket":"go to ticket", - "ticketWarning":"The embed is in the message below!", - "maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_" - }, - "helpMenu":{ - "title":"Available Commands:", - "header1":"**Go to {0} to create a ticket!**\n\n", - "header2":"**Run the command `/new` or `/ticket` to create a ticket!**\n\n", - - "msgCmd":"Spawn an embed with buttons. (admins only)", - "renameCmd":"Rename a ticket. (no spaces)", - "closeCmd":"Close a ticket.", - "deleteCmd":"Delete a ticket.", - "addCmd":"Add a user to the ticket.", - "removeCmd":"Remove a user from the ticket.", - "reopenCmd":"Re-Open a ticket after it was closed.", - "changeCmd":"Change ticket type.", - "claimCmd":"Claim a ticket.", - "unclaimCmd":"Unclaim a ticket.", - "statsCmd":"View ticket stats.", - "autocloseCmd":"Set timer to automatically close ticket" - }, - "buttons":{ - "close":"Close Ticket", - "delete":"Delete Ticket", - "reopen":"Re-Open Ticket", - "closeWithReason":"close with reason" - }, - "messages":{ - "closedDescription":"Only admins can talk in this ticket now!\n\n*Click on the button below to delete or to re-open this ticket!*", - "createdTitle":"Ticket Created!", - "createdDescription":"Your ticket is created, you can detect it by a ping!", - - "newTicketDmTitle":"New Ticket!", - "closedTicketDmTitle":"Ticket Closed!", - "deletedTicketDmTitle":"Ticket Deleted!", - "closedTicketDmDescription":"Your ticket is closed!", - "deletedTicketDmDescription":"Your ticket is deleted!", - "reopenTicketDmTitle":"Ticket Re-opened!", - "reopenTicketDmDescription":"Your ticket is re-opened!", - - "chooseCategory":"choose a category:", - "gettingdeleted":"Ticket is getting deleted...", - - "none":"none", - "reason":"reason", - "createdat":"created at", - "openedby":"opened by", - "deletedby":"deleted by", - "closedby":"closed by", - - "modalreason":"What is the reason for closing this ticket?", - "chooseATicket": "Choose a ticket" - }, - "transcripts":{ - "title":"Transcript", - "processed":"This transcript is being processed", - "wait":"Please wait!", - "estimated":"Estimated time", - "available":"The transcript is available here" - }, - "stats":{ - "globalTitle":"Global Stats", - "ticketTitle":"Ticket Stats for {0}", - "userTitle":"User Stats for {0}", - "systemTitle":"System Stats", - "versionTitle":"Bot Version", - - "ticketsCreated":"Tickets Created", - "ticketsClosed":"Tickets Closed", - "ticketsDeleted":"Tickets Deleted", - "ticketsReopened":"Tickets Reopened", - "ticketsAutoclosed":"Tickets Autoclosed", - "transcriptsCreated":"Transcripts Created", - "startupDate":"Startup Date", - "latestUpdate":"Latest Update", - "ticketCreatedOn":"Ticket Created On", - "ticketCreatedBy":"Ticket Created By", - "messagesSent":"Messages Sent", - "status":"Status", - "participants":"Participants", - "role":"Role", - - "switches":{ - "globalAdmin":"Global Admin", - "ticketAdmin":"Ticket Admin", - "member":"Member", - "open":"Open", - "reopened":"Reopened", - "closed":"Closed", - "autoclosed":"Autoclosed" - }, - - "errorUserNotFound":"This user can't be found in the stats database!" - } -} \ No newline at end of file diff --git a/language/estonian.json b/language/estonian.json deleted file mode 100644 index 9bb695b..0000000 --- a/language/estonian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"iamnotmega", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Puuduvad argumendid!", - "missingArgsDescription":"Puuduv argument", - "noPermsTitle":"Õiguseid pole!", - "noPermsDescription":"Teil peab olema ADMINISTRAATORI luba või olema lubatud rollide loendis!", - "noPermsDelete":"Ainult administraatorid saavad piletit kustutada!", - "chooseFromListTitle":"Vigane ID", - "chooseFromListDescription":"Valige allolevast id-st:", - "boterror":"Boti viga!", - "notInTicketTitle":"Te ei ole piletil!", - "notInTicketDescription":"See käsk ei tööta pileti väliste käskudena!", - "ticketDoesntExist":"See pilet ei eksisteeri enam!", - "roleDoesntExist":"See roll ei eksisteeri enam!", - "anotherOption":"See valik pole pilet, vaid teist tüüpi!", - "maxAmountTitle":"Maksimaalne arv saavutatud!", - "maxAmountDescription":"Olete saavutanud maksimaalse lubatud piletite arvu!\nSeetõttu ei saa te uut luua!", - "somethingWentWrong":"**Midagi läks valesti!**\nPalun proovige hiljem uuesti!" - }, - "commands":{ - "userAddedTitle":"Lisatud {0} sellele piletile!", - "userRemovedTitle":"Eemaldatud {0} sellest piletist!", - "renameTitle":"Muudetud nimi {0}-ks!", - "closeTitle":"See pilet on suletud!", - "deleteTitle":"See pilet kustutatakse...", - "reopenTitle":"See pilet on taas avatud!", - - "claimTitle":"See pilet on määratud {0}-le", - "unclaimTitle":"See pilet ei ole enam määratud!", - "changeTitle":"Piletitüüp muudetud {0}-ks!", - - "statsTitle":"Siin on statistika {0} jaoks!", - "autocloseTitle":"See pilet suletakse automaatselt pärast {0}!", - "autocloseRejectTitle":"See pilet ei suletakse enam automaatselt!", - "autocloseWarn":"See mõjutab ainult mitteaktiivseid pileteid!", - - "goToTicket":"mine piletile", - "ticketWarning":"Manus on allolevas sõnumis!", - "maxTicketWarning":"**Hoiatus:** _Saate luua ainult {0} pilet(it) korraga!_" - }, - "helpMenu":{ - "title":"Saadaval olevad käsud:", - "header1":"**Mine {0} juurde, et luua pilet!**\n\n", - "header2":"**Käivitage käsk `/new` või `/ticket`, et luua pilet!**\n\n", - - "msgCmd":"Kuvab manust koos nuppudega. (ainult administraatorid)", - "renameCmd":"Piletile nime andmine. (ilma tühikuteta)", - "closeCmd":"Pilet sulgeda.", - "deleteCmd":"Pilet kustutada.", - "addCmd":"Lisage kasutaja piletile.", - "removeCmd":"Eemaldage kasutaja piletist.", - "reopenCmd":"Avage pilet pärast selle sulgemist uuesti.", - "changeCmd":"Muuta piletitüüpi.", - "claimCmd":"Pilet määrata.", - "unclaimCmd":"Pilet määramata jätta.", - "statsCmd":"Kuva pileti statistika.", - "autocloseCmd":"Määrake taimer, et pilet automaatselt sulgeda" - }, - "buttons":{ - "close":"Sulge pilet", - "delete":"Kustuta pilet", - "reopen":"Ava pilet uuesti", - "closeWithReason":"sulge põhjusega" - }, - "messages":{ - "closedDescription":"Ainult administraatorid saavad selles piletis rääkida!\n\n*Klõpsake alloleval nupul, et see pilet kustutada või uuesti avada!*", - "createdTitle":"Pilet loodud!", - "createdDescription":"Teie pilet on loodud, tuvastate selle pingi järgi!", - - "newTicketDmTitle":"Uus pilet!", - "closedTicketDmTitle":"Pilet suletud!", - "deletedTicketDmTitle":"Pilet kustutatud!", - "closedTicketDmDescription":"Teie pilet on suletud!", - "deletedTicketDmDescription":"Teie pilet on kustutatud!", - "reopenTicketDmTitle":"Pilet uuesti avatud!", - "reopenTicketDmDescription":"Teie pilet on uuesti avatud!", - - "chooseCategory":"vali kategooria:", - "gettingdeleted":"Pilet kustutatakse...", - - "none":"puudub", - "reason":"põhjus", - "createdat":"loodud", - "openedby":"avanud", - "deletedby":"kustutanud", - "closedby":"sulgenud", - - "modalreason":"Mis on selle pileti sulgemise põhjus?", - "chooseATicket":"Valige pilet" - }, - "transcripts":{ - "title":"Protokoll", - "processed":"See protokoll on töötlemisel", - "wait":"Palun oodake!", - "estimated":"Eeldatav aeg", - "available":"Protokoll on saadaval siin" - }, - "stats":{ - "globalTitle":"Üldine statistika", - "ticketTitle":"Piletistatistika {0} jaoks", - "userTitle":"Kasutajastatistika {0} jaoks", - "systemTitle":"Süsteemi statistika", - "versionTitle":"Boti versioon", - - "ticketsCreated":"Loodud piletid", - "ticketsClosed":"Suletud piletid", - "ticketsDeleted":"Kustutatud piletid", - "ticketsReopened":"Uuesti avatud piletid", - "ticketsAutoclosed":"Automaatselt suletud piletid", - "transcriptsCreated":"Loodud protokollid", - "startupDate":"Käivituskuupäev", - "latestUpdate":"Viimane värskendus", - "ticketCreatedOn":"Pilet loodud", - "ticketCreatedBy":"Pilet loodud kasutaja poolt", - "messagesSent":"Saadetud sõnumid", - "status":"Olek", - "participants":"Osalejad", - "role":"Roll", - - "switches":{ - "globalAdmin":"Globaalne administraator", - "ticketAdmin":"Pileti administraator", - "member":"Liige", - "open":"Avatud", - "reopened":"Uuesti avatud", - "closed":"Suletud", - "autoclosed":"Automaatselt suletud" - }, - - "errorUserNotFound":"Seda kasutajat ei leitud statistika andmebaasist!" - } -} diff --git a/language/finnish.json b/language/finnish.json deleted file mode 100644 index fe5931f..0000000 --- a/language/finnish.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"iamnotmega", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Virheelliset argumentit!", - "missingArgsDescription":"Puuttuva argumentti", - "noPermsTitle":"Ei oikeuksia!", - "noPermsDescription":"Tarvitset `ADMINISTRATOR`-oikeudet tai olla sallittujen roolien listalla!", - "noPermsDelete":"Vain ylläpitäjät voivat poistaa lipun!", - "chooseFromListTitle":"Virheellinen tunniste", - "chooseFromListDescription":"Valitse yksi alla olevista tunnisteista:", - "boterror":"Botti virhe!", - "notInTicketTitle":"Et ole lipussa!", - "notInTicketDescription":"Tämä komento ei toimi lipun ulkopuolella!", - "ticketDoesntExist":"Tätä lippua ei ole enää olemassa!", - "roleDoesntExist":"Tätä roolia ei ole enää olemassa!", - "anotherOption":"Tämä vaihtoehto ei ole lippu vaan toinen tyyppi!", - "maxAmountTitle":"Maksimimäärä saavutettu!", - "maxAmountDescription":"Olet saavuttanut sallittujen lippujen maksimimäärän!\nEt voi luoda uutta!", - "somethingWentWrong":"**Jotain meni pieleen!**\nYritä uudelleen myöhemmin!" - }, - "commands":{ - "userAddedTitle":"Lisätty {0} tähän lippuun!", - "userRemovedTitle":"Poistettu {0} tästä lipusta!", - "renameTitle":"Nimetty uudelleen {0}!", - "closeTitle":"Suljettu tämä lippu!", - "deleteTitle":"Poistetaan tätä lippua...", - "reopenTitle":"Avattu tämä lippu uudelleen!", - - "claimTitle":"Tämä lippu on varattu {0}:lle", - "unclaimTitle":"Tämä lippu ei ole enää varattu!", - "changeTitle":"Vaihdettu lipun tyyppi {0}:ksi!", - - "statsTitle":"Tässä ovat tilastot {0}:lle!", - "autocloseTitle":"Tämä lippu sulkeutuu automaattisesti {0} jälkeen!", - "autocloseRejectTitle":"Tämä lippu ei sulkeudu enää automaattisesti!", - "autocloseWarn":"Tämä vaikuttaa vain passiivisiin lipputilanteisiin!", - - "goToTicket":"siirry lippuun", - "ticketWarning":"Upotus on alla olevassa viestissä!", - "maxTicketWarning":"**Varoitus:** _Voit luoda kerralla vain {0} lippua!_" - }, - "helpMenu":{ - "title":"Saatavilla olevat komennot:", - "header1":"**Siirry {0}:ään luodaksesi lipun!**\n\n", - "header2":"**Aja komento `/new` tai `/ticket` luodaksesi lipun!**\n\n", - - "msgCmd":"Luo upotus painikkeilla. (vain ylläpitäjille)", - "renameCmd":"Nimeä lippu uudelleen. (ilman välilyöntejä)", - "closeCmd":"Sulje lippu.", - "deleteCmd":"Poista lippu.", - "addCmd":"Lisää käyttäjä lippuun.", - "removeCmd":"Poista käyttäjä lipusta.", - "reopenCmd":"Avaa lippu uudelleen sen sulkeutumisen jälkeen.", - "changeCmd":"Vaihda lipun tyyppi.", - "claimCmd":"Varaa lippu.", - "unclaimCmd":"Poista varaaminen lippusta.", - "statsCmd":"Näytä lipun tilastot.", - "autocloseCmd":"Aseta ajastin sulkeaksesi lipun automaattisesti" - }, - "buttons":{ - "close":"Sulje lippu", - "delete":"Poista lippu", - "reopen":"Avaa lippu uudelleen", - "closeWithReason":"sulje syyn kanssa" - }, - "messages":{ - "closedDescription":"Vain ylläpitäjät voivat puhua tässä lipussa nyt!\n\n*Napsauta alla olevaa painiketta poistaaksesi tai avataksesi tämän lipun!*", - "createdTitle":"Lippu luotu!", - "createdDescription":"Lippusi on luotu, voit tunnistaa sen pingillä!", - - "newTicketDmTitle":"Uusi lippu!", - "closedTicketDmTitle":"Lippu suljettu!", - "deletedTicketDmTitle":"Lippu poistettu!", - "closedTicketDmDescription":"Lippusi on suljettu!", - "deletedTicketDmDescription":"Lippusi on poistettu!", - "reopenTicketDmTitle":"Lippu avattu uudelleen!", - "reopenTicketDmDescription":"Lippusi on avattu uudelleen!", - - "chooseCategory":"valitse kategoria:", - "gettingdeleted":"Lippu poistetaan...", - - "none":"ei mikään", - "reason":"syy", - "createdat":"luotu", - "openedby":"avasi", - "deletedby":"poistanut", - "closedby":"sulkenut", - - "modalreason":"Mikä on syy tämän lipun sulkemiseen?", - "chooseATicket": "Valitse lippu" - }, - "transcripts":{ - "title":"Pöytäkirja", - "processed":"Tämä pöytäkirja käsitellään", - "wait":"Odota hetki!", - "estimated":"Arvioitu aika", - "available":"Pöytäkirja on saatavilla täällä" - }, - "stats":{ - "globalTitle":"Maailmanlaajuiset tilastot", - "ticketTitle":"Lipputilastot {0}:lle", - "userTitle":"Käyttäjätilastot {0}:lle", - "systemTitle":"Järjestelmätilastot", - "versionTitle":"Bottiversio", - - "ticketsCreated":"Luodut liput", - "ticketsClosed":"Suljetut liput", - "ticketsDeleted":"Poistetut liput", - "ticketsReopened":"Uudelleen avatut liput", - "ticketsAutoclosed":"Automaattisesti suljetut liput", - "transcriptsCreated":"Luodut pöytäkirjat", - "startupDate":"Käynnistyspäivämäärä", - "latestUpdate":"Viimeisin päivitys", - "ticketCreatedOn":"Lippu luotu", - "ticketCreatedBy":"Lippu luonut", - "messagesSent":"Lähetetyt viestit", - "status":"Tila", - "participants":"Osallistujat", - "role":"Rooli", - - "switches":{ - "globalAdmin":"Globaali ylläpitäjä", - "ticketAdmin":"Lippuadmin", - "member":"Jäsen", - "open":"Auki", - "reopened":"Uudelleen avattu", - "closed":"Suljettu", - "autoclosed":"Automaattisesti suljettu" - }, - - "errorUserNotFound":"Tätä käyttäjää ei löydy tilastotietokannasta!" - } -} diff --git a/language/french.json b/language/french.json deleted file mode 100644 index 3bf630a..0000000 --- a/language/french.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"tostam", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Arguments invalides !", - "missingArgsDescription":"Argument manquant !", - "noPermsTitle":"Tu n'as pas les permissions requises !", - "noPermsDescription":"Vous avez besoin de la permission `ADMINISTRATOR` ou être dans la liste des rôles autorisés !", - "noPermsDelete":"Seuls les staffs peuvent supprimer un ticket !", - "chooseFromListTitle":"ID invalide !", - "chooseFromListDescription":"Choisissez l'un des identifiants ci-dessous:", - "boterror":"Erreur du bot !", - "notInTicketTitle":"Vous n'êtes pas dans un ticket !", - "notInTicketDescription":"Cette commande ne fonctionne pas en dehors des tickets !", - "ticketDoesntExist":"Ce ticket n'existe pas !", - "roleDoesntExist":"Ce rôle n'existe pas !", - "anotherOption":"Cette option n'est pas un ticket mais un autre type !", - "maxAmountTitle":"Montant maximum de ticket atteint !", - "maxAmountDescription":"Vous avez atteint le nombre maximum de tickets autorisés !\nVous ne pouvez donc pas en créer un nouveau !", - "somethingWentWrong":"**Quelque chose s'est mal passé !**\nVeuillez réessayer une autre fois !" - }, - "commands":{ - "userAddedTitle":"{0} a été ajouté à ce ticket !", - "userRemovedTitle":"{0} a été supprimé de ce ticket !", - "renameTitle":"Changement de nom du ticket en {0} !", - "closeTitle":"Ticket fermé", - "deleteTitle":"Suppression de ce ticket...", - "reopenTitle":"Ticket réouvert", - - "claimTitle":"Ce ticket est maintenant réclamé par {0}", - "unclaimTitle":"Ce ticket n'est plus réclamé !", - "changeTitle":"Modification du type de ticket en {0} !", - - "statsTitle":"Voici les statistiques pour {0} !", - "autocloseTitle":"Ce ticket sera automatiquement clôturé après {0} !", - "autocloseRejectTitle":"Ce ticket ne sera plus clôturé automatiquement !", - "autocloseWarn":"Cela n'affecte que les tickets inactifs !", - - "goToTicket":"Aller au ticket", - "ticketWarning":"L'intégration est dans le message ci-dessous !", - "maxTicketWarning":"**Attention :** _Vous ne pouvez créer seulement {0} ticket(s) à la fois !_" - }, - "helpMenu":{ - "title":"Commandes disponibles :", - "header1":"**Allez à {0} pour créer un ticket !**\n\n", - "header2":"**Exécutez la commande `/new` ou `/ticket` pour créer un ticket !**\n\n", - - "msgCmd":"Faire apparaître une intégration avec des boutons (administrateurs uniquement)", - "renameCmd":"Renommer un ticket (sans espaces)", - "closeCmd":"Fermer un ticket", - "deleteCmd":"Supprimer un ticket", - "addCmd":"Ajouter un utilisateur au ticket", - "removeCmd":"Supprimer un utilisateur du ticket", - "reopenCmd":"Réouvrir un ticket après sa clôture", - "changeCmd":"Changer le type de ticket", - "claimCmd":"Réclamer un ticket", - "unclaimCmd":"Annuler la réclamation d'un ticket", - "statsCmd":"Afficher les statistiques des tickets", - "autocloseCmd":"Définir une minuterie pour fermer automatiquement le ticket" - }, - "buttons":{ - "close":"Fermer le ticket", - "delete":"Supprimer le ticket", - "reopen":"Réouvrir le ticket", - "closeWithReason":"Fermer avec une raison" - }, - "messages":{ - "closedDescription":"Seuls les administrateurs peuvent parler dans ce ticket maintenant !\n\n*Cliquez sur le bouton ci-dessous pour supprimer ou réouvrir ce ticket !*", - "createdTitle":"Ticket créé !", - "createdDescription":"Votre ticket est créé, vous pouvez le détecter par un ping !", - - "newTicketDmTitle":"Nouveau ticket !", - "closedTicketDmTitle":"Ticket fermé !", - "deletedTicketDmTitle":"Ticket supprimé !", - "closedTicketDmDescription":"Votre ticket est fermé !", - "deletedTicketDmDescription":"Votre ticket est supprimé !", - "reopenTicketDmTitle":"Ticket réouvert !", - "reopenTicketDmDescription":"Votre ticket est réouvert !", - - "chooseCategory":"Choisissez une catégorie:", - "gettingdeleted":"Le ticket est en cours de suppression...", - - "none":"Rien", - "reason":"Raison", - "createdat":"Créé à", - "openedby":"Ouvert par", - "deletedby":"Supprimé par", - "closedby":"Fermé par", - - "modalreason":"Qu'elle est la raison pour fermer ce ticket ?", - "chooseATicket": "Choisir un ticket" - }, - "transcripts":{ - "title":"Transcript", - "processed":"Cette transcript est en cours de traitement", - "wait":"S'il vous plait, attendez...", - "estimated":"Temps estimé:", - "available":"La transcript est disponible ici" - }, - "stats":{ - "globalTitle":"Statistiques du serveur", - "ticketTitle":"Statistiques des tickets pour {0}", - "userTitle":"Statistiques des utilisateurs pour {0}", - "systemTitle":"Statistiques du système", - "versionTitle":"Version du bot", - - "ticketsCreated":"Tickets créés", - "ticketsClosed":"Tickets fermés", - "ticketsDeleted":"Tickets supprimés", - "ticketsReopened":"Tickets réouverts", - "ticketsAutoclosed":"Tickets fermés automatiquement", - "transcriptsCreated":"Transcriptions créées", - "startupDate":"Date de démarrage du bot", - "latestUpdate":"Dernière mise à jour", - "ticketCreatedOn":"Ticket créé le", - "ticketCreatedBy":"Ticket créé par", - "messagesSent":"Messages envoyés", - "status":"Status", - "participants":"Participants", - "role":"Role", - - "switches":{ - "globalAdmin":"Administrateur global", - "ticketAdmin":"Administrateur des tickets", - "member":"Membre", - "open":"Ouvrir", - "reopened":"Réouvert", - "closed":"Fermé", - "autoclosed":"Fermé automatiquement" - }, - - "errorUserNotFound":"Cet utilisateur est introuvable dans la base de données de statistiques !" - } -} \ No newline at end of file diff --git a/language/german.json b/language/german.json deleted file mode 100644 index f8fbd6e..0000000 --- a/language/german.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"david.3", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Ungültiges Argument!", - "missingArgsDescription":"Fehlendes Argument!", - "noPermsTitle":"Du hast keine Rechte!", - "noPermsDescription":"Du benötigst die `ADMINISTRATOR` Rechte oder die erlaubte Rolle", - "noPermsDelete":"Nur Administratoren können ein Ticket löschen!", - "chooseFromListTitle":"Ungültige ID", - "chooseFromListDescription":"Wählen Sie eine der folgenden ID's:", - "boterror":"Bot Fehler!", - "notInTicketTitle":"Du bist in keinem Ticket!", - "notInTicketDescription":"Der Befehl funktioniert außerhalb eines Tickets nicht!", - "ticketDoesntExist":"Das Ticket exisitert nicht mehr!", - "roleDoesntExist":"Die Rolle exisitiert nicht mehr!", - "anotherOption":"Diese Option ist kein Ticket, sondern eine andere Art!", - "maxAmountTitle":"Das Limit wurde erreicht!", - "maxAmountDescription":"Sie haben die maximal zulässige Anzahl von Tickets erreicht!\nSie können also keine neuen erstellen.!", - "somethingWentWrong":"**Etwas ist schief gelaufen!**\nBitte versuchen Sie es ein anderes Mal!" - }, - "commands":{ - "userAddedTitle":"User geaddet!", - "userRemovedTitle":"User entfernt!", - "renameTitle":"Der Name wurde geändert!", - "closeTitle":"Dieses Ticket schließen!", - "deleteTitle":"Löschen Sie dieses Ticket!", - "reopenTitle":"Öffne dieses Ticket erneut!", - - "claimTitle":"Dieses Ticket wurde beansprucht von {0}", - "unclaimTitle":"Dieses Ticket wird nichtmehr beansprucht.", - "changeTitle":"Ticket Typ wurde geändert zu {0}!", - - "statsTitle":"Hier sind die Stats für {0}!", - "autocloseTitle":"Dieses Ticket wird automatisch geschlossen in {0}!", - "autocloseRejectTitle":"Dieses Ticket wird nichtmehr automatisch geschlossen", - "autocloseWarn":"Dies betrifft nur inaktive Tickets!", - - "goToTicket":"Geh zu deinem Ticket", - "ticketWarning":"Die Einbettung befindet sich in der Nachricht unten!", - "maxTicketWarning":"**Warnung:** _Es können maximal {0} Tickets zur gleichen Zeit geöffnet sein!_" - }, - "helpMenu":{ - "title":"Hilfe Menu:", - "header1":"**Gehe zu {0} um ein Ticket zu erstellen!**\n\n", - "header2":"**Führen Sie den Befehl `/new` oder `/ticket` um ein Ticket zu erstellen!**\n\n", - - "msgCmd":"Eine Einbettung mit Schaltflächen erzeugen. (nur admins)", - "renameCmd":"Ein Ticket umbenennen. (keine Leerzeichen)", - "closeCmd":"Schließen Sie ein Ticket.", - "deleteCmd":"Ein Ticket löschen.", - "addCmd":"Fügen Sie dem Ticket einen Benutzer hinzu.", - "removeCmd":"Entfernen eines Benutzers aus dem Ticket.", - "reopenCmd":"Öffnen Sie ein Ticket erneut, nachdem es geschlossen wurde.", - "changeCmd":"Ticket Typ ändern", - "claimCmd":"Ticket beanspruchen", - "unclaimCmd":"Ticket nicht mehr beanspruchen.", - "statsCmd":"Ticket Stats", - "autocloseCmd":"Timer wurde gesetzt auf automatisches schließen des Tickets" - }, - "buttons":{ - "close":"Ticket schließen", - "delete":"Ticket löschen", - "reopen":"Ticket wieder öffnen", - "closeWithReason":"Geschlossen mit dem Grund" - }, - "messages":{ - "closedDescription":"Nur Admins können jetzt in diesem Ticket sprechen!\n\n*Klicken Sie auf die Schaltfläche unten, um dieses Ticket zu löschen oder erneut zu öffnen!*", - "createdTitle":"Ticket erstellt!", - "createdDescription":"Ihr Ticket ist erstellt, Sie können es durch einen Ping erkennen!", - - "newTicketDmTitle":"Neues Ticket!", - "closedTicketDmTitle":"Ticket schließen!", - "deletedTicketDmTitle":"Ticket löschen!", - "closedTicketDmDescription":"Ihr Ticket ist geschlossen!", - "deletedTicketDmDescription":"Ihr Ticket ist gelöscht!", - "newTranscriptTitle":"Eine neue Transcript finden Sie hier!", - "hereIsTheTranscript":"Hier ist das Transcript:", - - "chooseCategory":"Wähle eine Kategorie:", - "gettingdeleted":"Ticket wird gelöscht...", - - "none":"none", - "reason":"Grund", - "createdat":"Erstellt um", - "openedby":"Geöffnet um", - "deletedby":"Gelöscht von", - "closedby":"Geschlossen von", - - "modalreason":"Was ist der Grund?", - "chooseATicket": "Wähle ein passendes Thema!" - }, - "transcripts":{ - "title":"Transcript", - "processed":"Das Transcript wird erstellt", - "wait":"Bitte warten!", - "estimated":"Verbleibende Zeit", - "available":"Das Transcript ist hier verfügbar" - }, - "stats":{ - "globalTitle":"Global Stats", - "ticketTitle":"Ticket Stats für {0}", - "userTitle":"NutzerStats für {0}", - "systemTitle":"System Stats", - "versionTitle":"Bot Version", - - "ticketsCreated":"Tickets erstellt", - "ticketsClosed":"Tickets geschlossen", - "ticketsDeleted":"Tickets gelöscht", - "ticketsReopened":"Tickets wiedergeöffnet", - "ticketsAutoclosed":"Tickets Autogeschlossen", - "transcriptsCreated":"Transcripts erstellt", - "startupDate":"Start Datum", - "latestUpdate":"Letztes Update", - "ticketCreatedOn":"Ticket erstellt am", - "ticketCreatedBy":"Ticket erstellt von", - "messagesSent":"Nachrichten gesendet", - "status":"Status", - "participants":"Teilnehmer", - "role":"Rolle", - - "switches":{ - "globalAdmin":"Global Admin", - "ticketAdmin":"Ticket Admin", - "member":"Nutzer", - "open":"Öffnen", - "reopened":"Wiedergeöffnet", - "closed":"Geschlossen", - "autoclosed":"Autogeschlossen" - }, - - "errorUserNotFound":"Der Nutzer wurde in der Statistik-Datenbank nicht gefunden!" - } -} \ No newline at end of file diff --git a/language/greek.json b/language/greek.json deleted file mode 100644 index c7c87e3..0000000 --- a/language/greek.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"ꙅoᴎɒᎸɘƚꙅ#3744", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Invalid Arguments!", - "missingArgsDescription":"Missing Argument", - "noPermsTitle":"Δεν έχεις άδεια για να τρέξεις αυτή την εντολή!", - "noPermsDescription":"Χρειάζεσε άδεια διαχειριστή για να τρέξεις αυτή την εντολή.", - "noPermsDelete":"Μόνο οι διαχειριστές μπορούν να διαγράψουν τα εισιτήρια!", - "chooseFromListTitle":"Μη έγκυρο id.", - "chooseFromListDescription":"Διάλεξε ενα απο τα παρακάτω id:", - "boterror":"Υπάρχει κάποιο πρόβλημα!", - "notInTicketTitle":"Δεν είσε στο κανάλι του εισιτηρίου!", - "notInTicketDescription":"Δεν μπορείς να τρέξεις αυτή την εντολή εκτός του εισιτηρίου", - "ticketDoesntExist":"Αυτο το εισιτήριο δεν υπάρχει!", - "roleDoesntExist":"Αυτός ο ρόλος δεν υπάρχει!", - "anotherOption":"Διάλεξε άλλο λόγο για εισιτήριο!", - "maxAmountTitle":"Έχεις ανοίξει πολλά εισιτήρια για την ώρα.", - "maxAmountDescription":"Έχεις υπερβεί το όριο των εισιτηρίον!\nΔεν μπορείς να ανοίξεις καινούργιο.!", - "somethingWentWrong":"**Κάτι πήγε λάθος!**\nΔοκίμασε ξανά αργότερα!" - }, - "commands":{ - "userAddedTitle":"Ο {0} προσθέθηκε στο εισιτήριο", - "userRemovedTitle":"Ο {0} αφαιρέθηκε απο το εισιτήριο!", - "renameTitle":"Το όνομα άλλαξε σε {0}!", - "closeTitle":"Το εισιτήριο έκλεισε!", - "deleteTitle":"Διαγράφω το εισιτήριο...", - "reopenTitle":"Το εισιτήριο ξανά άνοιξε!", - - "claimTitle":"Το εισιτήριο διεκδικήθεικε απο τον {0}", - "unclaimTitle":"Το εισιτήριο δεν είναι πλέον διεκδικημένο!", - "changeTitle":"Ο τύπος του εισιτηρίου άλλαξε σε {0}!", - - "statsTitle":"Εδώ είναι τα στατιστικά για το {0}!", - "autocloseTitle":"Αυτό το εισιτήριο θα κλείσε σε {0}!", - "autocloseRejectTitle":"Αυτό το εισιτήριο δεν θα κλέισε αυτόματα!", - "autocloseWarn":"Αυτό ισχύει μονο για μή ενεργά εισιτήρια!", - - "goToTicket":"Μεταφορά στο εισιτήριο.", - "ticketWarning":"Το εισιτήριο είναι στο παρακάτω μήνυμα!", - "maxTicketWarning":"**Προειδοποίηση:** _Μπορείς να φτιάξεις μόνο {0} εισιτήριο/εισιτήρια για την ώρα!_" - }, - "helpMenu":{ - "title":"Διαθέσιμες εντολές:", - "header1":"**Πηγαινε στο {0} για να φτιάξεις ενα νέο εισιτήριο!**\n\n", - "header2":"**Τρέχα την εντολή `/new` ή `/ticket` για να φτιάξεις ένα εισιτήριο!**\n\n", - - "msgCmd":"Εμφάνισε ένα embed με κουμπιά. (admins only)", - "renameCmd":"Μετονόμασε το εισιτήριο. (όχι κενά)", - "closeCmd":"Κλέισε το εισιτήριο.", - "deleteCmd":"Διέγραψε το εισιτήριο.", - "addCmd":"Πρόσθεσε κάποιον στο εισιτήριο.", - "removeCmd":"Αφαίρεσε κάποιον απο το εισιτήριο.", - "reopenCmd":"Ξανά άνοιξε το εισιτήριο.", - "changeCmd":"Άλλαξε τον τύπο του εισιτηρίου.", - "claimCmd":"Διεκδίκησε το εισιτήριο.", - "unclaimCmd":"Unclaim a ticket.", - "statsCmd":"Δές τα στατιστικά του εισιτηρίου.", - "autocloseCmd":"Βάλε χρονόμετρο για να κλείσει το εισιτήριο" - }, - "buttons":{ - "close":"κλείσε το εισιτήριο", - "delete":"Διέγραψε το εισιτήριο", - "reopen":"Ξανά άνοιξε το εισιτήριο", - "closeWithReason":"Κλείσε με αιτιολόγιση" - }, - "messages":{ - "closedDescription":"Μονο οι διαχειριστές μπορουν να διαγράψουν τα εισιτήρια!\n\n*Πάτα το παρακάτω κουμπί για να ξανά ανοίξεις το εισιτήριο!*", - "createdTitle":"Το εισιτήριο δημιουργήθηκε!", - "createdDescription":"Το εισιτήριο σου δημιουργήθηκε μπορείς να το βρείς με την αναφορά που έγινε στο κανάλι του εισιτηρίου!", - - "newTicketDmTitle":"Νέο εισιτήριο!", - "closedTicketDmTitle":"Το εισιτήριο έκλεισε!", - "deletedTicketDmTitle":"Tο εισιτήριο διεγράφη!", - "closedTicketDmDescription":"Το εισιτήριο σου είναι κλειστό!", - "deletedTicketDmDescription":"Το εισιτήριο σου διεγράφη!", - "reopenTicketDmTitle":"Tο εισιτήριο ξανά άνοιξε!", - "reopenTicketDmDescription":"Το εισιτήριο σου ξανά άνοιξε!", - - "chooseCategory":"Διάλεξε μία κατηγορία:", - "gettingdeleted":"Το εισιτήριο διαγράφεται...", - - "none":"Κανένας", - "reason":"Λόγος", - "createdat":"Δημιουργήθηκε", - "openedby":"Ανοίχτηκε από", - "deletedby":"Διεγράφη απο", - "closedby":"Έκλεισε από", - - "modalreason":"Γιατι να κλείσει το εισιτήριο?", - "chooseATicket": "Δίαλεξε ενα εισιτήριο" - }, - "transcripts":{ - "title":"Αντίγραφο", - "processed":"Το αντίγραφο ετοιμάζεται!", - "wait":"Παρακαλώ περιμένετε!", - "estimated":"Ώρα αναμονής", - "available":"Το αντίγραφο είναι ανοιχτώ εδώ!" - }, - "stats":{ - "globalTitle":"Global Stats", - "ticketTitle":"Ticket Stats for {0}", - "userTitle":"User Stats for {0}", - "systemTitle":"System Stats", - "versionTitle":"Bot Version", - - "ticketsCreated":"Tickets Created", - "ticketsClosed":"Tickets Closed", - "ticketsDeleted":"Tickets Deleted", - "ticketsReopened":"Tickets Reopened", - "ticketsAutoclosed":"Tickets Autoclosed", - "transcriptsCreated":"Transcripts Created", - "startupDate":"Startup Date", - "latestUpdate":"Latest Update", - "ticketCreatedOn":"Ticket Created On", - "ticketCreatedBy":"Ticket Created By", - "messagesSent":"Messages Sent", - "status":"Status", - "participants":"Participants", - "role":"Role", - - "switches":{ - "globalAdmin":"Global Admin", - "ticketAdmin":"Ticket Admin", - "member":"Member", - "open":"Open", - "reopened":"Reopened", - "closed":"Closed", - "autoclosed":"Autoclosed" - }, - - "errorUserNotFound":"This user can't be found in the stats database!" - } -} \ No newline at end of file diff --git a/language/hungarian.json b/language/hungarian.json deleted file mode 100644 index 143fe02..0000000 --- a/language/hungarian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"kornel0706", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Hibás paraméter!", - "missingArgsDescription":"Hiányzó paraméter", - "noPermsTitle":"Nincs jogosultságod!", - "noPermsDescription":"Rendszergazda jogosultság szükséges!", - "noPermsDelete":"Csak adminok törölhetnek hibajegyet!", - "chooseFromListTitle":"Hibás ID", - "chooseFromListDescription":"Válassz az alábbi ID_k közül:", - "boterror":"Bot hiba", - "notInTicketTitle":"Nem vagy hibajegyben!", - "notInTicketDescription":"Ez a parancs nem működik, csak hibajegyekben!", - "ticketDoesntExist":"Ez a hibajegy már nem létezik!", - "roleDoesntExist":"Ez a rang már nem létezik!", - "anotherOption":"Ez a választási lehetőség nem hibajegy!", - "maxAmountTitle":"Maximum limit elérve!", - "maxAmountDescription":"Elérted a maximum hibajegyek számát!\nEzért nem tudsz létrehozni mégegyet!", - "somethingWentWrong":"**Hiba történt!**\nKérlek próbáld újra később!" - }, - "commands":{ - "userAddedTitle":"{0} hozzáadva a hibajegyhez!", - "userRemovedTitle":"{0} eltávolítva a hibajegyből!", - "renameTitle":"Név megváltoztatva: {0}!", - "closeTitle":"Hibajegy lezárva!", - "deleteTitle":"Hibajegy törlése...", - "reopenTitle":"Hibajegy újranyitva!", - - "claimTitle":"Ezt a hibajegyet {0} birtokolja", - "unclaimTitle":"A hibajegy többé nincsen birtokolva!", - "changeTitle":"A hibajegy típusa a következővé lett módosítva: {0}!", - - "statsTitle":"Itt vannak {0} statisztikái!", - "autocloseTitle":"A hibajegy ennyi idő múlva autómatikusan törölve lesz: {0}!", - "autocloseRejectTitle":"A hibajegy többé nem lesz lezárva autómatikusan!", - "autocloseWarn":"Ez csak az inaktív hibajegyekre van hatással!", - - "goToTicket":"A hibajegyhez", - "ticketWarning":"A beágyazás az üzenet alatt található!", - "maxTicketWarning":"**Figyelem** Összesen csak {0} hibajegyed lehet egyszerre!" - }, - "helpMenu":{ - "title":"Elérhető parancsok:", - "header1":"**Go to {0} to create a ticket!**\n\n", - "header2":"**Run the command `/new` or `/ticket` to create a ticket!**\n\n", - - "msgCmd":"Embed küldése gombokkal. (csak adminok)", - "renameCmd":"Ticket átnevezése. (szóköz nélkül)", - "closeCmd":"Ticket bezárása.", - "deleteCmd":"Ticket törlése.", - "addCmd":"Felhasználó hozzáadása a tickethez.", - "removeCmd":"Felhasználó elvétele a tickettől.", - "reopenCmd":"Ticket újranyitása miután már be lett zárva.", - "changeCmd":"Ticket típusának megváltoztatása.", - "claimCmd":"Ticket igénylése.", - "unclaimCmd":"Ticket igénylésének törlése.", - "statsCmd":"Ticket statisztikák megtekintése.", - "autocloseCmd":"Ticketek automatikus bezárási idejének beállítása" - }, - "buttons":{ - "close":"Bezárás", - "delete":"Törlés", - "reopen":"Újranyitás", - "closeWithReason":"Bezárás indokkal" - }, - "messages":{ - "closedDescription":"Csak a rendszergazdák beszélhetnek ebben a jegyben!\n\n*Kattintson az alábbi gombra a jegy törléséhez vagy újbóli megnyitásához!*", - "createdTitle":"Hibajegy létrehozva!", - "createdDescription":"A hibajegyed el lett készítve, a lentebbi gombbal odatalálsz!", - - "newTicketDmTitle":"Új hibajegy!", - "closedTicketDmTitle":"Hibajegy bezárva!", - "deletedTicketDmTitle":"Hibajegy törölve!", - "closedTicketDmDescription":"A hibajegyed be van zárva!", - "deletedTicketDmDescription":"A hibajegyed törölve van!", - "reopenTicketDmTitle":"A hibajegy újranyitva!", - "reopenTicketDmDescription":"A hibajegyed újra lett nyitva!", - - "chooseCategory":"Válassz egy kategóriát::", - "gettingdeleted":"A hibajegy törlés alatt...", - - "none":"nincs megadva", - "reason":"indok", - "createdat":"létrehozva", - "openedby":"létrehozta", - "deletedby":"törölte", - "closedby":"bezárta", - - "modalreason":"Milyen indokkal zárod le a hibajegyet?", - "chooseATicket": "**Válassz egy hibajegyet**\n" - }, - "transcripts":{ - "title":"Jegyzőkönyv", - "processed":"A jegyzőkönyv feldolgozás alatt", - "wait":"Kérlek várj!", - "estimated":"Becsült idő", - "available":"A jegyzőkönyv elérhető itt" - }, - "stats":{ - "globalTitle":"Globális statisztikák", - "ticketTitle":"{0} hibajegy statisztikái", - "userTitle":"{0} felhasználó statisztikái", - "systemTitle":"Rendszer statisztikák", - "versionTitle":"Bot verzió", - - "ticketsCreated":"Hibajegyek létrehozva", - "ticketsClosed":"Hibajegyek bezárva", - "ticketsDeleted":"Hibajegyek törölve", - "ticketsReopened":"Hibajegyek újranyitva", - "ticketsAutoclosed":"Hibajegyek automata lezárása", - "transcriptsCreated":"Jegyzőkönyvek létrehozva", - "startupDate":"Üzembe helyezés ideje", - "latestUpdate":"Utolsó frissítés", - "ticketCreatedOn":"Hibajegy létrehozva", - "ticketCreatedBy":"Hibajegyet létrehozta", - "messagesSent":"Üzenetek elküldve", - "status":"Státusz", - "participants":"Résztvevők", - "role":"Rang", - - "switches":{ - "globalAdmin":"Globális rendszergazda", - "ticketAdmin":"Jegyadminisztrátor", - "member":"Tag", - "open":"Megnyitás", - "reopened":"Újra megnyitva", - "closed":"Zárva", - "autoclosed":"Autoclosed" - }, - - "errorUserNotFound":"Ez a felhasználó nem található a statisztikai adatbázisban!" - } -} \ No newline at end of file diff --git a/language/indonesian.json b/language/indonesian.json deleted file mode 100644 index 7969a85..0000000 --- a/language/indonesian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"erxg", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Argumen tidak valid!", - "missingArgsDescription":"Argumen hilang", - "noPermsTitle":"Tidak ada akses!", - "noPermsDescription":"Anda memerlukan akses `ADMINISTRATOR` atau berada di dalam peran yang diizinkan!", - "noPermsDelete":"Hanya admin yang dapat menghapus tiket!", - "chooseFromListTitle":"ID Tidak Valid", - "chooseFromListDescription":"Silahkan pilih salah satu id di bawah:", - "boterror":"Bot Error!", - "notInTicketTitle":"Anda tidak berada di dalam sebuah tiket!", - "notInTicketDescription":"Perintah ini tidak bekerja di luar tiket!", - "ticketDoesntExist":"Tiket ini sudah tidak ada lagi!", - "roleDoesntExist":"Peran ini sudah tidak ada lagi!", - "anotherOption":"Opsi ini bukan tiket, melainkan tipe lain!", - "maxAmountTitle":"Batas maksimum tercapai!", - "maxAmountDescription":"Kamu telah meraih batas maksimum tiket yang diperbolehkan!\nJadi kamu tidak bisa membuat tiket baru!", - "somethingWentWrong":"Ada yang salah! Silakan coba lagi nanti!" - }, - "commands":{ - "userAddedTitle":"Menambah {0} ke tiket ini!", - "userRemovedTitle":"Mengeluarkan {0} dari tiket ini!", - "renameTitle":"Mengganti nama menjadi {0}!", - "closeTitle":"Menutup tiket ini!", - "deleteTitle":"Menghapus tiket ini...", - "reopenTitle":"Membuka ulang tiket ini!", - - "claimTitle":"Tiket ini diklaim oleh {0}", - "unclaimTitle":"Tiket ini tidak diklaim lagi!", - "changeTitle":"Mengganti tipe tiket menjadi {0}!", - - "statsTitle":"Ini adalah status untuk {0}!", - "autocloseTitle":"Tiket ini akan tutup otomatis setelah {0}!", - "autocloseRejectTitle":"Tiket ini tidak akan tertutup secara otomatis lagi!", - "autocloseWarn":"Ini hanya mempengaruhi tiket yang tidak aktif!", - - "goToTicket":"Pergi ke tiket", - "ticketWarning":"Sematan tersebut tersedia dalam pesan di bawah ini!", - "maxTicketWarning":"**Peringatan:** _Anda hanya bisa membuat {0} tiket dalam satu waktu!_" - }, - "helpMenu":{ - "title":"Perintah yang tersedia:", - "header1":"**Pergi ke {0} untuk membuat tiket!**\n\n", - "header2":"**Jalankan perintah `/new` atau `/ticket` untuk membuat tiket!**\n\n", - - "msgCmd":"Munculkan sematan dengan tombol. (hanya admin)", - "renameCmd":"Ganti nama tiket. (tanpa spasi)", - "closeCmd":"Tutup tiket.", - "deleteCmd":"Hapus tiket.", - "addCmd":"Tambahkan pengguna ke dalam tiket.", - "removeCmd":"Keluarkan pengguna dari tiket.", - "reopenCmd":"Buka ulang tiket setelah ditutup.", - "changeCmd":"Ganti tipe tiket.", - "claimCmd":"Klaim tiket.", - "unclaimCmd":"Batalkan klaim tiket.", - "statsCmd":"Lihat status tiket.", - "autocloseCmd":"Atur timer untuk menutup tiket secara otomatis" - }, - "buttons":{ - "close":"Tutup tiket", - "delete":"Hapus tiket", - "reopen":"Buka ulang tiket", - "closeWithReason":"Tutup dengan alasan" - }, - "messages":{ - "closedDescription":"Hanya admin yang dapat berbincang di tiket ini sekarang!\n\n*Tekan tombol di bawah untuk menghapus atau membuka ulang tiket ini!*", - "createdTitle":"Tiket dibuat!", - "createdDescription":"Tiket anda dibuat, anda dapat mengetahui dengan ping!", - - "newTicketDmTitle":"Tiket baru!", - "closedTicketDmTitle":"Tiket ditutup!", - "deletedTicketDmTitle":"TIket dihapus!", - "closedTicketDmDescription":"Tiket anda ditutup!", - "deletedTicketDmDescription":"Tiket anda dihapus!", - "reopenTicketDmTitle":"Tiket dibuka kembali!", - "reopenTicketDmDescription":"Tiket anda dibuka kembali!", - - "chooseCategory":"Pilih kategori:", - "gettingdeleted":"Tiket sedang dihapus...", - - "none":"tidak ada", - "reason":"Alasan", - "createdat":"dibuat di", - "openedby":"dibuka oleh", - "deletedby":"dihapus oleh", - "closedby":"ditutup oleh", - - "modalreason":"Apa alasan penutupan tiket ini?", - "chooseATicket": "Pilih tiket" - }, - "transcripts":{ - "title":"Transcript", - "processed":"Transkrip sedang diproses", - "wait":"Mohon tunggu!", - "estimated":"Estimasi waktu", - "available":"Transkrip tersedia di sini" - }, - "stats":{ - "globalTitle":"Statistik Global", - "ticketTitle":"Status Tiket Untuk {0}", - "userTitle":"Status Pengguna Untuk {0}", - "systemTitle":"Status Sistem", - "versionTitle":"Versi Robot", - - "ticketsCreated":"Tiket Dibuat", - "ticketsClosed":"Tiket Ditutup", - "ticketsDeleted":"Tiket Dihapus", - "ticketsReopened":"Tiket Dibuka Kembali", - "ticketsAutoclosed":"Tiket Ditutup Otomatis", - "transcriptsCreated":"Transkrip Dibuat", - "startupDate":"Tanggal Mulai", - "latestUpdate":"Pembaruan Terbaru", - "ticketCreatedOn":"Tiket Dibuat Pada", - "ticketCreatedBy":"Tiket Dibuat Oleh", - "messagesSent":"Pesan Terkirim", - "status":"Status", - "participants":"Partisipan", - "role":"Peran", - - "switches":{ - "globalAdmin":"Admin Global", - "ticketAdmin":"Ticket Admin", - "member":"Anggota", - "open":"Buka", - "reopened":"Dibuka kembali", - "closed":"Ditutup", - "autoclosed":"Ditutup Otomatis" - }, - - "errorUserNotFound":"Pengguna ini tidak dapat ditemukan dalam basis data statistik!" - } -} \ No newline at end of file diff --git a/language/italian.json b/language/italian.json deleted file mode 100644 index ce12573..0000000 --- a/language/italian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"maurizio26", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Argomenti non validi!", - "missingArgsDescription":"Argomenti mancanti", - "noPermsTitle":"Non hai i permessi sufficienti!", - "noPermsDescription":"Hai bisogno del permesso `ADMINISTRATOR` o essere nella lista dei ruoli consentiti!", - "noPermsDelete":"Solo gli amministratori possono eliminare i ticket!", - "chooseFromListTitle":"ID non valido", - "chooseFromListDescription":"Scegli uno degli id sottostanti:", - "boterror":"Errore del bot!", - "notInTicketTitle":"Non sei in un ticket!", - "notInTicketDescription":"Questo comando non funziona al di fuori di un ticket!", - "ticketDoesntExist":"Questo ticket non esiste!", - "roleDoesntExist":"Questo ruolo non esiste!", - "anotherOption":"Questa opzione non è un ticket ma un'altra!", - "maxAmountTitle":"Massimo ammontare raggiunto!", - "maxAmountDescription":"Hai raggiunto il massimo di ticket aperti!\nNon puoi creare altri!", - "somethingWentWrong":"*Qualcosa è andato storto!*\nPerfavore riprova un'altra volta!" - }, - "commands":{ - "userAddedTitle":"Aggiunti {0} a questo ticket!", - "userRemovedTitle":"Rimossi {0} da questo ticket!", - "renameTitle":"Cambiato il nome a {0}!", - "closeTitle":"Ticket chiuso!", - "deleteTitle":"Eliminando questo ticket...", - "reopenTitle":"Ri-aperto questo ticket!", - - "claimTitle":"Questo ticket adesso è gestito da {0}", - "unclaimTitle":"Questo ticket non è più gestito!", - "changeTitle":"Ticket cambiato in {0}!", - - "statsTitle":"Queste sono le stats per {0}!", - "autocloseTitle":"Questo ticket sarà eliminato direttamente dopo {0}!", - "autocloseRejectTitle":"Questo ticket non sarà più chiuso automaticamente!", - "autocloseWarn":"Questo vale solo per i ticket inattivi!", - - "goToTicket":"vai al ticket", - "ticketWarning":"L'embed è nel messaggio sotto!", - "maxTicketWarning":"*Attenzione:* Tu puoi creare solo {0} ticket alla volta!" - }, - "helpMenu":{ - "title":"Comandi disponibili:", - "header1":"*Vai a {0} per creare un ticket!*\n\n", - "header2":"*Esegui il comando `/new` o `/ticket` per creare un ticket!*\n\n", - - "msgCmd":"Crea un embed con bottoni. (solo amministratori)", - "renameCmd":"Rinomina un ticket. (senza spazi)", - "closeCmd":"Chiudi un ticket.", - "deleteCmd":"Elimina un ticket.", - "addCmd":"Aggiungi un utente al ticket.", - "removeCmd":"Rimuovi un utente da un ticket.", - "reopenCmd":"Ri-apri un ticket dopo averlo chiuso.", - "changeCmd":"Cambia tipo di ticket.", - "claimCmd":"Gestisci un ticket.", - "unclaimCmd":"Lascia la gestione del ticket.", - "statsCmd":"Vedi le statistiche dei ticket.", - "autocloseCmd":"Imposta il timer dell'autochiusura dei ticket" - }, - "buttons":{ - "close":"Chiudi", - "delete":"Elimini", - "reopen":"Ri-apri un ticket", - "closeWithReason":"chiudi con motivo" - }, - "messages":{ - "closedDescription":"Solo gli amministratori possono parlare in questo ticket ora!\n\n*Clicca sul pulsante sotto per eliminare o ri-aprire questo ticket!*", - "createdTitle":"Ticket creato!", - "createdDescription":"Il tuo ticket è stato creato, puoi capirlo dal ping!", - - "newTicketDmTitle":"Nuovo ticket!", - "closedTicketDmTitle":"Ticket chiuso!", - "deletedTicketDmTitle":"Ticket eliminato!", - "closedTicketDmDescription":"Il tuo ticket è chiuso!", - "deletedTicketDmDescription":"Il tuo ticket è eliminato!", - "reopenTicketDmTitle":"Ticket ri-aperto!", - "reopenTicketDmDescription":"Il tuo ticket è stato ri-aperto!", - - "chooseCategory":"scegli una categoria:", - "gettingdeleted":"Il ticket sta per essere chiuso...", - - "none":"nessuno", - "reason":"motivo", - "createdat":"creato il", - "openedby":"aperto da", - "deletedby":"eliminato da", - "closedby":"chiuso da", - - "modalreason":"Quale è il motivo per chiudere questo ticket?", - "chooseATicket": "Scegli un ticket" - }, - "transcripts":{ - "title":"Trascrizione", - "processed":"Questo ticket sta per essere processato", - "wait":"Perfavore attendi!", - "estimated":"Tempo estimato", - "available":"La trascrizione è disponibile qui" - }, - "stats": { - "globalTitle": "Statistiche Globali", - "ticketTitle": "Statistiche Ticket per {0}", - "userTitle": "Statistiche Utenti per {0}", - "systemTitle": "Sistema Statistiche", - "versionTitle": "Versione Bot", - - "ticketsCreated": "Tickets Creato", - "ticketsClosed": "Tickets Chiuso", - "ticketsDeleted": "Tickets Eliminato", - "ticketsReopened": "Tickets Riaperto", - "ticketsAutoclosed": "Tickets Chiuso Automaticamente", - "transcriptsCreated": "Transcrizione Creata", - "startupDate": "Data Inizio", - "latestUpdate": "Ultimo Update", - "ticketCreatedOn": "Ticket Creato Su", - "ticketCreatedBy": "Ticket Creato Da", - "messagesSent": "Messaggi Inviati", - "status": "Stato", - "participants": "Partecipanti", - "role": "Ruolo", - - "switches": { - "globalAdmin": "Amministratore Globale", - "ticketAdmin": "Amministratore Ticket", - "member": "Membro", - "open": "Aperto", - "reopened": "Riaperto", - "closed": "Chiuso", - "autoclosed": "Chiuso Automaticamente" - }, - - "errorUserNotFound": "Questo utente non può essere trovato nel database delle statistiche!" - } -} \ No newline at end of file diff --git a/language/japanese.json b/language/japanese.json deleted file mode 100644 index bf7e5cb..0000000 --- a/language/japanese.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS": "iamnotmega", - "_INFO": "This file is a translation for open ticket 3.5.8", - - "errors": { - "missingArgsTitle": "매개 변수가 누락되었습니다!", - "missingArgsDescription": "필수 매개 변수가 누락되었습니다", - "noPermsTitle": "권한이 없습니다!", - "noPermsDescription": "관리자 권한이 필요하거나 허용된 역할 목록에 있어야 합니다!", - "noPermsDelete": "티켓 삭제 권한이 없습니다!", - "chooseFromListTitle": "잘못된 ID", - "chooseFromListDescription": "아래 목록에서 ID를 선택하세요:", - "boterror": "봇 오류!", - "notInTicketTitle": "티켓 내에서만 사용 가능합니다!", - "notInTicketDescription": "이 명령어는 티켓 외부에서는 작동하지 않습니다!", - "ticketDoesntExist": "이 티켓은 더 이상 존재하지 않습니다!", - "roleDoesntExist": "이 역할은 존재하지 않습니다!", - "anotherOption": "이 옵션은 티켓이 아닌 다른 유형입니다!", - "maxAmountTitle": "최대 수량 도달!", - "maxAmountDescription": "허용된 최대 티켓 수에 도달했습니다!\n새 티켓을 만들 수 없습니다!", - "somethingWentWrong": "**문제가 발생했습니다!**\n나중에 다시 시도해 주세요!" - }, - "commands": { - "userAddedTitle": "{0}님을 이 티켓에 추가했습니다!", - "userRemovedTitle": "{0}님을 이 티켓에서 제거했습니다!", - "renameTitle": "이름을 {0}(으)로 변경했습니다!", - "closeTitle": "이 티켓을 닫았습니다!", - "deleteTitle": "이 티켓을 삭제 중입니다...", - "reopenTitle": "이 티켓을 다시 열었습니다!", - - "claimTitle": "이 티켓은 {0}님에게 할당되었습니다", - "unclaimTitle": "이 티켓은 더 이상 할당되지 않았습니다!", - "changeTitle": "티켓 유형을 {0}(으)로 변경했습니다!", - - "statsTitle": "다음은 {0}의 통계입니다!", - "autocloseTitle": "이 티켓은 {0} 후에 자동으로 닫힙니다!", - "autocloseRejectTitle": "이 티켓은 더 이상 자동으로 닫히지 않습니다!", - "autocloseWarn": "이 설정은 비활성 티켓에만 영향을 미칩니다!", - - "goToTicket": "티켓으로 이동", - "ticketWarning": "임베드는 아래 메시지에 있습니다!", - "maxTicketWarning": "**경고:** _한 번에 {0}개의 티켓만 만들 수 있습니다!_" - }, - "helpMenu": { - "title": "사용 가능한 명령어:", - "header1": "**티켓을 만들려면 {0}(으)로 이동하세요!**\n\n", - "header2": "**티켓을 만들려면 `/new` 또는 `/ticket` 명령어를 실행하세요!**\n\n", - - "msgCmd": "버튼이 있는 임베드 메시지를 생성합니다. (관리자 전용)", - "renameCmd": "티켓 이름을 변경합니다. (공백 없음)", - "closeCmd": "티켓을 닫습니다.", - "deleteCmd": "티켓을 삭제합니다.", - "addCmd": "사용자를 티켓에 추가합니다.", - "removeCmd": "사용자를 티켓에서 제거합니다.", - "reopenCmd": "닫은 후 티켓을 다시 엽니다.", - "changeCmd": "티켓 유형을 변경합니다.", - "claimCmd": "티켓을 할당합니다.", - "unclaimCmd": "티켓 할당을 취소합니다.", - "statsCmd": "티켓 통계를 확인합니다.", - "autocloseCmd": "티켓을 자동으로 닫는" - }, - "buttons": { - "close": "티켓 닫기", - "delete": "티켓 삭제", - "reopen": "티켓 다시 열기", - "closeWithReason": "이유를 밝혀 닫기" - }, - "messages": { - "closedDescription": "지금은 관리자만이 이 티켓에서 말할 수 있습니다!\n\n*아래 버튼을 클릭하여 이 티켓을 삭제하거나 다시 열 수 있습니다!*", - "createdTitle": "티켓이 생성되었습니다!", - "createdDescription": "티켓이 생성되었습니다. 피드백을 통해 확인할 수 있습니다!", - - "newTicketDmTitle": "새로운 티켓!", - "closedTicketDmTitle": "티켓이 닫혔습니다!", - "deletedTicketDmTitle": "티켓이 삭제되었습니다!", - "closedTicketDmDescription": "티켓이 닫혔습니다!", - "deletedTicketDmDescription": "티켓이 삭제되었습니다!", - "reopenTicketDmTitle": "티켓이 다시 열렸습니다!", - "reopenTicketDmDescription": "티켓이 다시 열렸습니다!", - - "chooseCategory": "카테고리 선택:", - "gettingdeleted": "티켓이 삭제 중입니다...", - - "none": "없음", - "reason": "이유", - "createdat": "생성 시각", - "openedby": "생성자", - "deletedby": "삭제자", - "closedby": "닫은 사람", - - "modalreason": "이 티켓을 닫는 이유는 무엇인가요?", - "chooseATicket": "티켓을 선택하세요" - }, - "transcripts": { - "title": "전문 기록", - "processed": "이 전문은 처리 중입니다", - "wait": "잠시 기다려 주세요!", - "estimated": "예상 시간", - "available": "여기서 전문을 확인할 수 있습니다" - }, - "stats": { - "globalTitle": "전역 통계", - "ticketTitle": "{0}의 티켓 통계", - "userTitle": "{0}의 사용자 통계", - "systemTitle": "시스템 통계", - "versionTitle": "봇 버전", - - "ticketsCreated": "생성된 티켓", - "ticketsClosed": "닫힌 티켓", - "ticketsDeleted": "삭제된 티켓", - "ticketsReopened": "다시 열린 티켓", - "ticketsAutoclosed": "자동 닫힌 티켓", - "transcriptsCreated": "생성된 전문", - "startupDate": "시작 일자", - "latestUpdate": "최신 업데이트", - "ticketCreatedOn": "티켓 생성 일자", - "ticketCreatedBy": "티켓 생성자", - "messagesSent": "전송된 메시지", - "status": "상태", - "participants": "참여자", - "role": "역할", - - "switches": { - "globalAdmin": "글로벌 관리자", - "ticketAdmin": "티켓 관리자", - "member": "회원", - "open": "열림", - "reopened": "다시 열림", - "closed": "닫힘", - "autoclosed": "자동 닫힘" - }, - - "errorUserNotFound": "이 사용자는 통계 데이터베이스에서 찾을 수 없습니다!" - } -} diff --git a/language/korean.json b/language/korean.json deleted file mode 100644 index bf7e5cb..0000000 --- a/language/korean.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS": "iamnotmega", - "_INFO": "This file is a translation for open ticket 3.5.8", - - "errors": { - "missingArgsTitle": "매개 변수가 누락되었습니다!", - "missingArgsDescription": "필수 매개 변수가 누락되었습니다", - "noPermsTitle": "권한이 없습니다!", - "noPermsDescription": "관리자 권한이 필요하거나 허용된 역할 목록에 있어야 합니다!", - "noPermsDelete": "티켓 삭제 권한이 없습니다!", - "chooseFromListTitle": "잘못된 ID", - "chooseFromListDescription": "아래 목록에서 ID를 선택하세요:", - "boterror": "봇 오류!", - "notInTicketTitle": "티켓 내에서만 사용 가능합니다!", - "notInTicketDescription": "이 명령어는 티켓 외부에서는 작동하지 않습니다!", - "ticketDoesntExist": "이 티켓은 더 이상 존재하지 않습니다!", - "roleDoesntExist": "이 역할은 존재하지 않습니다!", - "anotherOption": "이 옵션은 티켓이 아닌 다른 유형입니다!", - "maxAmountTitle": "최대 수량 도달!", - "maxAmountDescription": "허용된 최대 티켓 수에 도달했습니다!\n새 티켓을 만들 수 없습니다!", - "somethingWentWrong": "**문제가 발생했습니다!**\n나중에 다시 시도해 주세요!" - }, - "commands": { - "userAddedTitle": "{0}님을 이 티켓에 추가했습니다!", - "userRemovedTitle": "{0}님을 이 티켓에서 제거했습니다!", - "renameTitle": "이름을 {0}(으)로 변경했습니다!", - "closeTitle": "이 티켓을 닫았습니다!", - "deleteTitle": "이 티켓을 삭제 중입니다...", - "reopenTitle": "이 티켓을 다시 열었습니다!", - - "claimTitle": "이 티켓은 {0}님에게 할당되었습니다", - "unclaimTitle": "이 티켓은 더 이상 할당되지 않았습니다!", - "changeTitle": "티켓 유형을 {0}(으)로 변경했습니다!", - - "statsTitle": "다음은 {0}의 통계입니다!", - "autocloseTitle": "이 티켓은 {0} 후에 자동으로 닫힙니다!", - "autocloseRejectTitle": "이 티켓은 더 이상 자동으로 닫히지 않습니다!", - "autocloseWarn": "이 설정은 비활성 티켓에만 영향을 미칩니다!", - - "goToTicket": "티켓으로 이동", - "ticketWarning": "임베드는 아래 메시지에 있습니다!", - "maxTicketWarning": "**경고:** _한 번에 {0}개의 티켓만 만들 수 있습니다!_" - }, - "helpMenu": { - "title": "사용 가능한 명령어:", - "header1": "**티켓을 만들려면 {0}(으)로 이동하세요!**\n\n", - "header2": "**티켓을 만들려면 `/new` 또는 `/ticket` 명령어를 실행하세요!**\n\n", - - "msgCmd": "버튼이 있는 임베드 메시지를 생성합니다. (관리자 전용)", - "renameCmd": "티켓 이름을 변경합니다. (공백 없음)", - "closeCmd": "티켓을 닫습니다.", - "deleteCmd": "티켓을 삭제합니다.", - "addCmd": "사용자를 티켓에 추가합니다.", - "removeCmd": "사용자를 티켓에서 제거합니다.", - "reopenCmd": "닫은 후 티켓을 다시 엽니다.", - "changeCmd": "티켓 유형을 변경합니다.", - "claimCmd": "티켓을 할당합니다.", - "unclaimCmd": "티켓 할당을 취소합니다.", - "statsCmd": "티켓 통계를 확인합니다.", - "autocloseCmd": "티켓을 자동으로 닫는" - }, - "buttons": { - "close": "티켓 닫기", - "delete": "티켓 삭제", - "reopen": "티켓 다시 열기", - "closeWithReason": "이유를 밝혀 닫기" - }, - "messages": { - "closedDescription": "지금은 관리자만이 이 티켓에서 말할 수 있습니다!\n\n*아래 버튼을 클릭하여 이 티켓을 삭제하거나 다시 열 수 있습니다!*", - "createdTitle": "티켓이 생성되었습니다!", - "createdDescription": "티켓이 생성되었습니다. 피드백을 통해 확인할 수 있습니다!", - - "newTicketDmTitle": "새로운 티켓!", - "closedTicketDmTitle": "티켓이 닫혔습니다!", - "deletedTicketDmTitle": "티켓이 삭제되었습니다!", - "closedTicketDmDescription": "티켓이 닫혔습니다!", - "deletedTicketDmDescription": "티켓이 삭제되었습니다!", - "reopenTicketDmTitle": "티켓이 다시 열렸습니다!", - "reopenTicketDmDescription": "티켓이 다시 열렸습니다!", - - "chooseCategory": "카테고리 선택:", - "gettingdeleted": "티켓이 삭제 중입니다...", - - "none": "없음", - "reason": "이유", - "createdat": "생성 시각", - "openedby": "생성자", - "deletedby": "삭제자", - "closedby": "닫은 사람", - - "modalreason": "이 티켓을 닫는 이유는 무엇인가요?", - "chooseATicket": "티켓을 선택하세요" - }, - "transcripts": { - "title": "전문 기록", - "processed": "이 전문은 처리 중입니다", - "wait": "잠시 기다려 주세요!", - "estimated": "예상 시간", - "available": "여기서 전문을 확인할 수 있습니다" - }, - "stats": { - "globalTitle": "전역 통계", - "ticketTitle": "{0}의 티켓 통계", - "userTitle": "{0}의 사용자 통계", - "systemTitle": "시스템 통계", - "versionTitle": "봇 버전", - - "ticketsCreated": "생성된 티켓", - "ticketsClosed": "닫힌 티켓", - "ticketsDeleted": "삭제된 티켓", - "ticketsReopened": "다시 열린 티켓", - "ticketsAutoclosed": "자동 닫힌 티켓", - "transcriptsCreated": "생성된 전문", - "startupDate": "시작 일자", - "latestUpdate": "최신 업데이트", - "ticketCreatedOn": "티켓 생성 일자", - "ticketCreatedBy": "티켓 생성자", - "messagesSent": "전송된 메시지", - "status": "상태", - "participants": "참여자", - "role": "역할", - - "switches": { - "globalAdmin": "글로벌 관리자", - "ticketAdmin": "티켓 관리자", - "member": "회원", - "open": "열림", - "reopened": "다시 열림", - "closed": "닫힘", - "autoclosed": "자동 닫힘" - }, - - "errorUserNotFound": "이 사용자는 통계 데이터베이스에서 찾을 수 없습니다!" - } -} diff --git a/language/kurdish.json b/language/kurdish.json deleted file mode 100644 index ec4f850..0000000 --- a/language/kurdish.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"raze.hama", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"ئه‌وه‌ی هه‌ڵتبژاردوه‌ نادروسته‌", - "missingArgsDescription":"ئه‌وه‌ی هه‌ڵتبژاردوه‌ ناردوسته‌", - "noPermsTitle":"هیچ مۆڵەتێک نییە!", - "noPermsDescription":"پێویستت بە مۆڵەتی ئه‌دمین ستره‌یته‌ر هەیە یان ده‌بێت لە لیستی ڕۆڵە ڕێگەپێدراوەکاندا بیت!", - "noPermsDelete":"تەنها ئەدمینەکان دەتوانن بلیت بسڕنەوە!", - "chooseFromListTitle":"ناسنامەی نادروست", - "chooseFromListDescription":"یەکێک لەم ناسنامانه‌ی خوارەوە هەڵبژێرە:", - "boterror":"هەڵەی بۆت!", - "notInTicketTitle":"تۆ لەناو بلیتدا نیت!", - "notInTicketDescription":"ئەم فەرمانە لە دەرەوەی بلیت کارناکات!", - "ticketDoesntExist":"ئەم بلیتە ئیتر بوونی نییە!", - "roleDoesntExist":"ئیتر ئەم ڕۆڵە بوونی نییە!", - "anotherOption":"ئەم بژاردەیە بلیت نیە بەڵکو جۆرێکی ترە !", - "maxAmountTitle":"تۆگه‌شتی به‌ زۆرترین", - "maxAmountDescription":"گەیشتووی بە زۆرترین ژمارەی بلیت کە ڕێگەپێدراوە\nبۆیە ناتوانیت نوێ دروست بکەیت", - "somethingWentWrong":"**شتێک بە هەڵەدا چووە **\n تکایە جارێکی تر هەوڵبدەرەوە" - }, - "commands":{ - "userAddedTitle":"زیادكرا {0} بۆ ئه‌م بلیته‌", - "userRemovedTitle":"لابرا{0} له‌م بلیته‌ ", - "renameTitle":"ناوەکەی گۆڕی بۆ... {0}!", - "closeTitle":"ئەم بلیتەی داخست!", - "deleteTitle":"سڕینەوەی ئەم بلیتە...", - "reopenTitle":"ئەم بلیتە دووبارە کردەوە!", - - "claimTitle":"ئەم بلیتە بانگەشەی ئەوە دەکرێت کە... {0}", - "unclaimTitle":"ئیتر ئەم بلیتە داوای ناکرێت!", - "changeTitle":"جۆری بلیت گۆڕی بۆ... {0}!", - - "statsTitle":"لێرەدا ئامارەکان بۆ... {0}!", - "autocloseTitle":"ئەم بلیتە بە شێوەیەکی ئۆتۆماتیکی دادەخرێت دوای...{0}!", - "autocloseRejectTitle":"ئەم بلیتە چیتر بە شێوەیەکی ئۆتۆماتیکی داناخرێت!", - "autocloseWarn":"ئەمەش تەنها کاریگەری لەسەر بلیتی ناچالاک هەیە!", - - "goToTicket":"بڕۆ بۆ بلیت", - "ticketWarning":"جێگیرکردنەکە لە نامەکەی خوارەوەدایە!", - "maxTicketWarning":"**ئاگاداری:** _تەنها دەتوانیت لە یەک کاتدا {0} بلیت(ەکان) دروست بکەیت!_" - }, - "helpMenu":{ - "title":"فەرمانە بەردەستەکان:", - "header1":"**Go to {0} to create a ticket!**\n\n", - "header2":"**فەرمانەکە جێبەجێ بکە `/new` or `/ticket` بۆ دروستکردنی بلیت!**\n\n", - - "msgCmd":"(تەنها ئەدمینەکان)", - "renameCmd":"ناوی بلیته‌كه‌ بگۆره‌", - "closeCmd":"بلیتێک دابخە.", - "deleteCmd":"بلیتێک بسڕەوە.", - "addCmd":"بەکارهێنەرێک زیاد بکە بۆ بلیتەکە.", - "removeCmd":"بەکارهێنەرێک لە بلیتەکە دەربهێنە.", - "reopenCmd":"دووبارە بلیتێک بکەرەوە دوای داخستنی.", - "changeCmd":"گۆڕینی جۆری بلیت.", - "claimCmd":"داوای بلیتێک بکە.", - "unclaimCmd":"داوای بلیتێک وەربگرە.", - "statsCmd":"بینینی ئاماری بلیتەکان.", - "autocloseCmd":"تایمەر دابنێ بۆ ئەوەی بلیتەکە بە شێوەیەکی ئۆتۆماتیکی دابخات" - }, - "buttons":{ - "close":"داخستنی بلیت", - "delete":"سڕینەوەی بلیت", - "reopen":"دوباره‌ بلیته‌كه‌ بكه‌ره‌وه‌", - "closeWithReason":"هۆكارێك بنوسه‌ بۆ داخستنی بلیته‌كه‌" - }, - "messages":{ - "closedDescription":"ئێستا تەنها ئەدمینەکان دەتوانن لەم بلیتەدا قسە بکەن!\n\n*بۆ سڕینەوە یان دووبارە کردنەوەی ئەم بلیتە کلیک لەسەر دوگمەی خوارەوە بکە!*", - "createdTitle":"بلیت دروستکراوە!", - "createdDescription":"بلیتەکەت دروست کراوە، دەتوانیت بە پینگێک دەستنیشان بکەیت!", - - "newTicketDmTitle":"بلیتی نوێ!", - "closedTicketDmTitle":"بلیت داخراوە!", - "deletedTicketDmTitle":"بلیت سڕاوەتەوە!", - "closedTicketDmDescription":"بلیتەکەت داخراوە!", - "deletedTicketDmDescription":"بلیتەکەت سڕاوەتەوە!", - "reopenTicketDmTitle":"بلیت دووبارە کرایەوە!", - "reopenTicketDmDescription":"بلیتەکەت دەکرێتەوە!", - - "chooseCategory":"پۆلێک هەڵبژێرە:", - "gettingdeleted":"بلیتەکە خەریکە دەسڕدرێتەوە...", - - "none":"هیچ", - "reason":"هۆكار", - "createdat":"دروستکراوە لە", - "openedby":"لەلایەن...", - "deletedby":"سڕاوەتەوە لەلایەن", - "closedby":"داخراوە لەلایەن", - - "modalreason":"هۆکاری داخستنی ئەم بلیتە چییە؟", - "chooseATicket": "بلیتێک هەڵبژێرە" - }, - "transcripts":{ - "title":"گواستنه‌وه‌", - "processed":"ئەم گواستنه‌وه‌یه‌ خەریکە پرۆسێس دەکرێت", - "wait":"تكایه‌ چاوه‌ڕێبه‌!", - "estimated":"کاتی مەزەندەکراو", - "available":" گواستنه‌وه‌كه‌ لێرەدا بەردەستە" - }, - "stats":{ - "globalTitle":"ئاماری جیهانی", - "ticketTitle":"ئاماری بلیت بۆ {0}", - "userTitle":"ئاماری بەکارهێنەر بۆ {0}", - "systemTitle":"ئاماری سیستەم", - "versionTitle":"وەشانی بۆت", - - "ticketsCreated":"بلیتەکان دروستکراون", - "ticketsClosed":"بلیتەکان داخراون", - "ticketsDeleted":"بلیتەکان سڕاونەتەوە", - "ticketsReopened":"بلیتەکان کرایەوە", - "ticketsAutoclosed":"بلیتەکان بە شێوەیەکی ئۆتۆماتیکی داخراون", - "transcriptsCreated":"گواستنه‌وه‌ دروستکراون", - "startupDate":"بەرواری دەستپێکردن", - "latestUpdate":"نوێترین نوێکردنەوە", - "ticketCreatedOn":"بلیت دروستکراوە لەسەر", - "ticketCreatedBy":"بلیت دروستکراوە لەلایەن...", - "messagesSent":"پەیامەکان نێردراوە", - "status":"دۆخ", - "participants":"بەشداربووان", - "role":"ئەرک", - - "switches":{ - "globalAdmin":"بەڕێوەبەری جیهانی", - "ticketAdmin":"ئەدمینی بلیتەکان", - "member":"ئەندام", - "open":"کردنەوە", - "reopened":"دووبارە کرایەوە", - "closed":"داخراوە", - "autoclosed":"ئۆتۆماتیکی داخراوە" - }, - - "errorUserNotFound":"ئەم بەکارهێنەرە لە بنکەدراوەی ئامارەکاندا نادۆزرێتەوە!" - } -} \ No newline at end of file diff --git a/language/latvian.json b/language/latvian.json deleted file mode 100644 index 9803efa..0000000 --- a/language/latvian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"Ronalds1398", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Nepareizi argumenti!", - "missingArgsDescription":"Trūkst argumentu!", - "noPermsTitle":"Nav atļauju!", - "noPermsDescription":"Jums ir nepieciešama `ADMINISTRATOR` atļauja vai jābūt atļautajām lomām!", - "noPermsDelete":"Tikai administratori var izdzēst biļetes!", - "chooseFromListTitle":"Nederīgs ID", - "chooseFromListDescription":"Izvēlieties vienu no zemāk esošajiem ID:", - "boterror":"Bota kļūda!", - "notInTicketTitle":"Jūs neesat biļetē!", - "notInTicketDescription":"Šī komanda nedarbojas ārpus biļetēm!", - "ticketDoesntExist":"Šāda biļete vairs nepastāv!", - "roleDoesntExist":"Šāda loma vairs nepastāv!", - "anotherOption":"Tas nav biļete, bet citas veida!", - "maxAmountTitle":"Sasniegta maksimālā summa!", - "maxAmountDescription":"Jūs esat sasniedzis maksimālo atļauto biļešu skaitu!\nTāpēc jūs nevarat izveidot jaunu!", - "somethingWentWrong":"**Kaut kas nogāja greizi!**\nLūdzu, mēģiniet vēlreiz!" - }, - "commands":{ - "userAddedTitle":"Pievienots {0} šai biļetei!", - "userRemovedTitle":"Noņemts {0} no šīs biļetes!", - "renameTitle":"Pārdēvēts uz {0}!", - "closeTitle":"Biļete aizvērta!", - "deleteTitle":"Dzēšam biļeti", - "reopenTitle":"Atkārtoti atveram biļeti!", - - "claimTitle":"Šo biļeti ņēma {0}", - "unclaimTitle":"Šī biļete nav piešķirta nevienam!", - "changeTitle":"Biļetes veids mainīts uz {0}!", - - "statsTitle":"Šeit ir statistika par {0}!", - "autocloseTitle":"Šī biļete tiks automātiski aizvērta pēc {0}!", - "autocloseRejectTitle":"Šī biļete vairs netiks automātiski aizvērta!", - "autocloseWarn":"Tas attiecas tikai uz neaktīvām biļetēm!", - - "goToTicket":"doties uz biļeti", - "ticketWarning":"Iegults ir zemāk esošajā ziņā!", - "maxTicketWarning":"**Brīdinājums:** _Jūs varat izveidot tikai tik daudz biļetes vienlaikus: {0}!_" - }, - "helpMenu":{ - "title":"Pieejamie komandu:", - "header1":"**Dodieties uz {0}, lai izveidotu biļeti!**\n\n", - "header2":"**Izpildiet komandu `/new` vai `/ticket`, lai izveidotu biļeti!**\n\n", - - "msgCmd":"Izveidojiet iegultni ar pogām. (tikai administratoriem)", - "renameCmd":"Pārdēvējiet biļeti. (bez atstarpēm)", - "closeCmd":"Aizveriet biļeti.", - "deleteCmd":"Dzēst biļeti.", - "addCmd":"Pievienojiet lietotāju biļetei.", - "removeCmd":"Noņemt lietotāju no biļetes.", - "reopenCmd":"Atveriet atkārtoti aizvērtu biļeti.", - "changeCmd":"Mainiet biļetes veidu.", - "claimCmd":"Paņemiet biļeti.", - "unclaimCmd":"Atsakieties no biļetes.", - "statsCmd":"Apskatiet biļetes statistiku.", - "autocloseCmd":"Iestatiet taimeri, lai automātiski aizvērtu biļeti" - }, - "buttons":{ - "close":"Aizveriet biļeti", - "delete":"Dzēst biļeti", - "reopen":"Atveriet biļeti", - "closeWithReason":"Aizveriet ar iemeslu" - }, - "messages":{ - "closedDescription":"Pašlaik šajā biļetē var runāt tikai administratori!\n\n*Nospiediet zemāk esošo pogu, lai dzēstu vai atkārtoti atveriet šo biļeti!*", - "createdTitle":"Biļete izveidota!", - "createdDescription":"Jūsu biļete ir izveidota, to varat atpazīt, izmantojot pingu!", - - "newTicketDmTitle":"Jauna biļete!", - "closedTicketDmTitle":"Biļete aizvērta!", - "deletedTicketDmTitle":"Biļete dzēsta!", - "closedTicketDmDescription":"Jūsu biļete ir aizvērta!", - "deletedTicketDmDescription":"Jūsu biļete ir dzēsta!", - "reopenTicketDmTitle":"Biļete atkārtoti atvērta!", - "reopenTicketDmDescription":"Jūsu biļete ir atkārtoti atvērta!", - - "chooseCategory":"izvēlieties kategoriju:", - "gettingdeleted":"Biļete tiek dzēsta...", - - "none":"nav", - "reason":"iemērs", - "createdat":"izveidots", - "openedby":"atvēris", - "deletedby":"dzēsts", - "closedby":"aizvērts", - - "modalreason":"Kāds ir šīs biļetes aizvēršanas iemesls?", - "chooseATicket": "Izvēlieties biļeti" - }, - "transcripts":{ - "title":"Transkripcija", - "processed":"Šī transkripcija tiek apstrādāta", - "wait":"Lūdzu, uzgaidiet!", - "estimated":"Apmēramais laiks", - "available":"Transkripcija pieejama šeit" - }, - "stats":{ - "globalTitle":"Globālā statistika", - "ticketTitle":"Biļetes statistika priekš {0}", - "userTitle":"Lietotāja statistika priekš {0}", - "systemTitle":"Sistēmas statistika", - "versionTitle":"Bota versija", - - "ticketsCreated":"Biļetes izveidotas", - "ticketsClosed":"Biļetes aizvērtas", - "ticketsDeleted":"Biļetes dzēstas", - "ticketsReopened":"Biļetes atkārtoti atvērtas", - "ticketsAutoclosed":"Biļetes automātiski aizvērtas", - "transcriptsCreated":"Transkripcijas izveidotas", - "startupDate":"Palaišanas datums", - "latestUpdate":"Pēdējā atjaunināšana", - "ticketCreatedOn":"Biļete izveidota", - "ticketCreatedBy":"Biļete izveidota", - "messagesSent":"Ziņojumi nosūtīti", - "status":"Statuss", - "participants":"Dalībnieki", - "role":"Loma", - - "switches":{ - "globalAdmin":"Globālais Administrātors", - "ticketAdmin":"Biļešu Administrātors", - "member":"Dalībnieks", - "open":"Atvērts", - "reopened":"Atkārtoti atvērts", - "closed":"Aizvērts", - "autoclosed":"Automātiski aizvērts" - }, - - "errorUserNotFound":"Lietotājs nav atrasts mūsu datubāzē!" - } -} \ No newline at end of file diff --git a/language/norwegian.json b/language/norwegian.json deleted file mode 100644 index 1fcf1c1..0000000 --- a/language/norwegian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"noonenook", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Ugyldige argumenter!", - "missingArgsDescription":"Manglende argument", - "noPermsTitle":"Ingen rettigheter", - "noPermsDescription":"Du trenger administrator eller moderator rettigheter", - "noPermsDelete":"Bare staff kan slette en ticket!", - "chooseFromListTitle":"Ugyldig ID", - "chooseFromListDescription":"Velg en av ID-ene nedenfor:", - "boterror":"Bot Error!", - "notInTicketTitle":"Du er ikke i en ticket!", - "notInTicketDescription":"Du kan ikke bruke denne command utenfor en ticket.", - "ticketDoesntExist":"Ticket finnes ikke lenger!", - "roleDoesntExist":"Rollen eksisterer ikke lenger!", - "anotherOption":"Dette alternativet er ikke en ticket!", - "maxAmountTitle":"Maks antall er nådd!", - "maxAmountDescription":"Du har nådd maksimalt antall tillatte ticket's\nSå du kan ikke lage en ny før de andre er lukket!", - "somethingWentWrong":"**Noe gikk galt!**\nVennligst prøv igjen senere!" - }, - "commands":{ - "userAddedTitle":"{0} har blitt lagt til i ticket!", - "userRemovedTitle":"Fjernet {0} fra ticket!", - "renameTitle":"Endret navn til {0}!", - "closeTitle":"Ticket er blitt lukket!", - "deleteTitle":"Sletter ticket...", - "reopenTitle":"Ticket er gjenåpnet", - - "claimTitle":"{0} har tatt over denne saken!", - "unclaimTitle":"Denne ticket er blitt ledig igjen!", - "changeTitle":"Endret ticket-type til {0}!", - - "statsTitle":"Her er statistikken for {0}!", - "autocloseTitle":"Denne ticket stenges automatisk etter kl {0}!", - "autocloseRejectTitle":"Denne ticket vil ikke lenger stenges automatisk!", - "autocloseWarn":"Dette påvirker kun inaktive tickets!", - - "goToTicket":"DIN TICKET", - "ticketWarning":"Embed er i meldingen nedenfor!", - "maxTicketWarning":"**Advarsel:** _Du kan bare opprette {0}ticket(s) om gangen!_" - }, - "helpMenu":{ - "title":"Tilgjengelige Commands:", - "header1":"**Gå til {0} for å opprette en ticket!**\n\n", - "header2":"**Skriv kommandoen `/new` eller `/ticket` for å lage en ticket!**\n\n", - - "msgCmd":"Lag en embed med knapper. (admins only)", - "renameCmd":"Gi nytt navn til en ticket. (ingen mellomrom)", - "closeCmd":"Lukk en ticket.", - "deleteCmd":"Slett en ticket.", - "addCmd":"Legg til en bruker i ticket.", - "removeCmd":"Fjern en bruker fra ticket.", - "reopenCmd":"Åpne en ticket på nytt etter at den ble avsluttet.", - "changeCmd":"Endre ticket kategori", - "claimCmd":"Ta over ticket.", - "unclaimCmd":"Frigjør den fra ticket.", - "statsCmd":"Se ticket stats.", - "autocloseCmd":"Still inn når ticket lukkes automatisk etter den ble åpnet" - }, - "buttons":{ - "close":"Lukk Ticket", - "delete":"Slett Ticket", - "reopen":"Gjenåpne Ticket", - "closeWithReason":"Legg til årsak" - }, - "messages":{ - "closedDescription":"Bare staff medlemmer kan snakke i denne ticket nå!\n\n*Klikk på knappen nedenfor for å slette eller åpne ticket på nytt!*", - "createdTitle":"Ticket er laget!", - "createdDescription":"__Du finner den ved å trykke på knappen under__", - - "newTicketDmTitle":"New Ticket!", - "closedTicketDmTitle":"Ticket Åpnet!", - "deletedTicketDmTitle":"Ticket Slettet!", - "closedTicketDmDescription":"Din ticket er lukket!", - "deletedTicketDmDescription":"Din ticket er slettet!", - "reopenTicketDmTitle":"Ticket gjenåpnet!", - "reopenTicketDmDescription":"Din icket er gjenåpnet!", - - "chooseCategory":"Velg en kategori:", - "gettingdeleted":"Ticket slettes....", - - "none":"Ingen", - "reason":"Grunnlag", - "createdat":"Laget", - "openedby":"Laget av", - "deletedby":"Slettet av", - "closedby":"Lukket av", - - "modalreason":"Grunnlag for lukking!", - "chooseATicket": "Velg en ticket" - }, - "transcripts":{ - "title":"Ticket logg", - "processed":"Logg fil lages, snart klar!", - "wait":"Vennligst vent!", - "estimated":"Beregnet tid", - "available":"Loggfil er tilgjengelig over denne meldingen!" - }, - "stats":{ - "globalTitle":"Globale Stats", - "ticketTitle":"Ticket Stats for {0}", - "userTitle":"Bruker Stats for {0}", - "systemTitle":"System Stats", - "versionTitle":"Bot Versjon", - - "ticketsCreated":"Tickets Laget", - "ticketsClosed":"Tickets Lukket", - "ticketsDeleted":"Tickets Slettet", - "ticketsReopened":"Tickets Gjenåpnet", - "ticketsAutoclosed":"Tickets Auto-lukket", - "transcriptsCreated":"Transcripts Opprettet", - "startupDate":"Start Dato", - "latestUpdate":"Siste Oppdatering", - "ticketCreatedOn":"Ticket Laget den", - "ticketCreatedBy":"Ticket Laget av", - "messagesSent":"Meldinger sendt", - "status":"Status", - "participants":"Deltakere", - "role":"Rolle", - - "switches":{ - "globalAdmin":"Global Admin", - "ticketAdmin":"Ticket Admin", - "member":"Medlem", - "open":"Åpen", - "reopened":"Gjenåpnet", - "closed":"Lukket", - "autoclosed":"Auto-Lukket" - }, - - "errorUserNotFound":"Denne brukeren kan ikke bli funnet i statistikkdatabasen!" - } -} \ No newline at end of file diff --git a/language/persian.json b/language/persian.json deleted file mode 100644 index f602c56..0000000 --- a/language/persian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"sasanwm", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"آرگومان‌های گم شده!", - "missingArgsDescription":"آرگومان گم شده", - "noPermsTitle":"شما دسترسی نداری!", - "noPermsDescription":"شما نیاز به دسترسی `ADMINISTRATOR` دارید یا باید در لیست رول‌های مجاز باشید!", - "noPermsDelete":"فقط ادمین ها میتونند یک تیکت رو حذف کنند!", - "chooseFromListTitle":"ایدی نامعتبر", - "chooseFromListDescription":"یکی از ایدی‌های زیر رو انتخاب کن:", - "boterror":"خطای ربات!", - "notInTicketTitle":"شما در یک تیکت نیستید!", - "notInTicketDescription":"این کامند خارج از تیکت‌ها کار نمیکند!", - "ticketDoesntExist":"این تیکت دیگه وجود نداره!", - "roleDoesntExist":"این رول دیگه وجود نداره!", - "anotherOption":"این گزینه یک تیکت نیست بلکه نوع دیگه ای هست!", - "maxAmountTitle":"حداکثر مقدار رسیده هست!", - "maxAmountDescription":"شما به حداکثر تعداد تیکت‌های مجاز رسیدید!\nبنابراین نمیتونید یکی دیگه ایجاد کنید!", - "somethingWentWrong":"**مشکلی پیش اومد!**\nدوباره تلاش کن!" - }, - "commands":{ - "userAddedTitle":"{0} به این تیکت اضافه شد!", - "userRemovedTitle":"{0} از این تیکت حذف شد!", - "renameTitle":"اسم به {0} تغییر یافت!", - "closeTitle":"این تیکت بسته شد!", - "deleteTitle":"حذف این تیکت...", - "reopenTitle":"این تیکت دوباره باز شد!", - - "claimTitle":"این تیکت به {0} اختصاص یافته است", - "unclaimTitle":"این تیکت دیگه به اختصاص یک یوزر نمیباشد!", - "changeTitle":"نوع تیکت به {0} تغییر یافت!", - - "statsTitle":"آمار اینجا {0} هست!", - "autocloseTitle":"این تیکت به طور خودکار بعد از {0} بسته خواهد شد!", - "autocloseRejectTitle":"این تیکت دیگه به طور خودکار بسته نخواهد شد!", - "autocloseWarn":"این فقط بر روی تیکت‌های غیرفعال تأثیر میزاره!", - - "goToTicket":"رفتن به تیکت", - "ticketWarning":"امبد در پیام زیر هست!", - "maxTicketWarning":"**هشدار:** _شما فقط میتوانید {0} تیکت رو در همان زمان ایجاد کنید!_" - }, - "helpMenu":{ - "title":"کامند های موجود:", - "header1":"**به {0} براید تا یک تیکت ایجاد کنید!**\n\n", - "header2":"**کامند `/new` یا `/ticket` رو اجرو کن تا یک تیکت ایجاد کنید!**\n\n", - - "msgCmd":"فرستادن یک امبد با دکمه ها (فقط ادمین ها)", - "renameCmd":"اسم یک تیکت رو تغییر دهید. (بدون فاصله)", - "closeCmd":"بستن یک تیکت.", - "deleteCmd":"حذف یک تیکت.", - "addCmd":"اضافه کردن یک یوزر به تیکت.", - "removeCmd":"حذف کردن یک یوزر از تیکت.", - "reopenCmd":"باز کردن یک تیکت پس از بسته شدن.", - "changeCmd":"تغییر دادن نوع تیکت.", - "claimCmd":"به اختیار گرفتن یک تیکت.", - "unclaimCmd":"خارج کردن یک تیکت از اختیار خود.", - "statsCmd":"مشاهده کردن امار یک تیکت.", - "autocloseCmd":"تنظیم زمان بندی برای بسته شدن خودکار تیکت. " - }, - "buttons":{ - "close":"بستن تیکت", - "delete":"حذف تیکت", - "reopen":"بازکردن مجدد تیکت", - "closeWithReason":"بستن با دلیل" - }, - "messages":{ - "closedDescription":"فقط ادمین‌ها میتواننند در این تیکت صحبت کنند!\n\n*برای حذف یا بازکردن این تیکت، روی دکمه زیر کلیک کن!*", - "createdTitle":"تیکت ایجاد شد!", - "createdDescription":"تیکت شما ایجاد شده، توی تیکت منشن شدی!", - - "newTicketDmTitle":"تیکت جدید!", - "closedTicketDmTitle":"تیکت بسته شد!", - "deletedTicketDmTitle":"تیکت حذف شد!", - "closedTicketDmDescription":"تیکت شما بسته شده هست!", - "deletedTicketDmDescription":"تیکت شما حذف شده هست!", - "reopenTicketDmTitle":"تیکت دوباره باز شد!", - "reopenTicketDmDescription":"تیکت شما دوباره باز شده هست!", - - "chooseCategory":"یک دسته بندی رو انتخاب کن:", - "gettingdeleted":"تیکت در حال حذف شدن هست...", - - "none":"هیچ", - "reason":"دلیل", - "createdat":"ایجاد شده در", - "openedby":"باز شده توسط", - "deletedby":"حذف شده توسط", - "closedby":"بسته شده توسط", - - "modalreason":"دلیل بستن این تیکت چیه؟", - "chooseATicket": "یک تیکت رو انتخاب کن" - }, - "transcripts":{ - "title":"گزارش", - "processed":"این گزارش در حال پردازش هست", - "wait":"لطفاً صبر کن!", - "estimated":"زمان تقریبی", - "available":"گزارش در دسترس هست در اینجا" - }, - "stats":{ - "globalTitle":"آمار گلوبال", - "ticketTitle":"آمار تیکت برای {0}", - "userTitle":"آمار یوزر برای {0}", - "systemTitle":"آمار سیستم", - "versionTitle":"ورژن ربات", - - "ticketsCreated":"تیکت‌های ایجاد شده", - "ticketsClosed":"تیکت‌های بسته شده", - "ticketsDeleted":"تیکت‌های حذف شده", - "ticketsReopened":"تیکت‌های دوباره باز شده", - "ticketsAutoclosed":"تیکت‌های به طور خودکار بسته شده", - "transcriptsCreated":"گزارش‌های ایجاد شده", - "startupDate":"تاریخ راه‌اندازی‌", - "latestUpdate":"آخرین بروزرسانی", - "ticketCreatedOn":"تیکت ایجاد شده در", - "ticketCreatedBy":"تیکت ایجاد شده توسط", - "messagesSent":"پیام‌های ارسال شده", - "status":"وضعیت", - "participants":"مشارکت‌کنندگان", - "role":"رول", - - "switches":{ - "globalAdmin":"ادمین گلوبال", - "ticketAdmin":"ادمین تیکت", - "member":"ممبر", - "open":"باز", - "reopened":"دوباره باز شده", - "closed":"بسته شده", - "autoclosed":"بسته شده به طور خودکار" - }, - - "errorUserNotFound":"این یوزر در دیتابیس آمار پیدا نمیشه!" - } -} \ No newline at end of file diff --git a/language/polish.json b/language/polish.json deleted file mode 100644 index ab35ebd..0000000 --- a/language/polish.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"mkevas", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Nieprawidłowe argumenty!", - "missingArgsDescription":"Brakujący argument", - "noPermsTitle":"Brak permisji!", - "noPermsDescription":"Musisz mieć uprawnienia `ADMINISTRATOR` lub być na liście dozwolonych ról!", - "noPermsDelete":"Tylko administratorzy mogą usunąć zgłoszenie!", - "chooseFromListTitle":"Błędne ID", - "chooseFromListDescription":"Wybierz jeden z poniższych identyfikatorów:", - "boterror":"Błąd bota!", - "notInTicketTitle":"Nie jesteś w tickecie!", - "notInTicketDescription":"To polecenie nie działa poza ticketami!", - "ticketDoesntExist":"Ten ticket już nie istnieje!", - "roleDoesntExist":"Ta rola już nie istnieje!", - "anotherOption":"Ta opcja nie jest ticketem, ale innym typem!", - "maxAmountTitle":"Maksymalna liczba osiągnięta!", - "maxAmountDescription":"Osiągnąłeś maksymalną dozwoloną liczbę ticketów!\nWięc nie możesz stworzyć nowego!", - "somethingWentWrong":"**Coś poszło nie tak!**\nSpróbuj ponownie innym razem!" - }, - "commands":{ - "userAddedTitle":"Dodano {0} do tego ticketa!", - "userRemovedTitle":"Usunięto {0} z tego ticketa!", - "renameTitle":"Zmieniono nazwę na {0}!", - "closeTitle":"Zamknięto ten ticket!", - "deleteTitle":"Usuwanie tego zgłoszenia..", - "reopenTitle":"Ponownie otwarto ten ticket!", - - "claimTitle":"Ten ticket został odebrany przez {0}", - "unclaimTitle":"Nie można już odebrać tego biletu!", - "changeTitle":"Changed ticket type to {0}!", - - "statsTitle":"Oto statystyki dotyczące {0}!", - "autocloseTitle":"Ten ticket zostanie automatycznie zamknięty po {0}!", - "autocloseRejectTitle":"Ten ticket nie będzie już automatycznie zamykany!", - "autocloseWarn":"Dotyczy to tylko nieaktywnych biletów!", - - "goToTicket":"Przejdź do ticketa", - "ticketWarning":"Osadzenie znajduje się w wiadomości poniżej!", - "maxTicketWarning":"**Ostrzeżenie:** _Możesz utworzyć tylko {0} bilet(ów) na raz!_" - }, - "helpMenu":{ - "title":"Dostępne polecenia:", - "header1":"**Przejdź do {0}, aby utworzyć zgłoszenie!**\n\n", - "header2":"**Uruchom polecenie `/new` lub `/ticket`, aby utworzyć zgłoszenie!**\n\n", - - "msgCmd":"Odradzaj osadzanie za pomocą przycisków. (tylko administratorzy)", - "renameCmd":"Zmień nazwę zgłoszenia. (bez spacji)", - "closeCmd":"Zamknij ticket.", - "deleteCmd":"Skasuj ticket.", - "addCmd":"Dodaj użytkownika do zgłoszenia.", - "removeCmd":"Usuń użytkownika ze zgłoszenia.", - "reopenCmd":"Otwórz ponownie ticket po jego zamknięciu.", - "changeCmd":"Zmień typ ticketa.", - "claimCmd":"Odbierz ticket.", - "unclaimCmd":"Zrezygnuj z ticketa.", - "statsCmd":"Pokaż statystyki zgłoszenia.", - "autocloseCmd":"Ustaw timer, aby automatycznie zamykał ticket." - }, - "buttons":{ - "close":"Zamknij", - "delete":"Skasuj", - "reopen":"Otworz ponownie", - "closeWithReason":"Zamknij z powodem" - }, - "messages":{ - "closedDescription":"Tylko admini mogą teraz rozmawiać w tym zgłoszeniu!\n\n*Kliknij przycisk poniżej, aby usunąć lub ponownie otworzyć ten ticket!*", - "createdTitle":"Ticket Created!", - "createdDescription":"Twój ticket został utworzony, możesz go wykryć za pomocą pingu!", - - "newTicketDmTitle":"Nowy Ticket!", - "closedTicketDmTitle":"Ticket Zamknięty!", - "deletedTicketDmTitle":"Ticket Skasowany!", - "closedTicketDmDescription":"Twój ticket jest zamknięty!", - "deletedTicketDmDescription":"Twój ticket został skasowany!", - "reopenTicketDmTitle":"Ticket otwarty!", - "reopenTicketDmDescription":"Twój ticket został ponownie otwarty!", - - "chooseCategory":"Wybierz kategorię:", - "gettingdeleted":"Ticket jest usuwany..", - - "none":"brak", - "reason":"powód", - "createdat":"utworzony", - "openedby":"otwarte przez", - "deletedby":"skasowane przez", - "closedby":"zamknięte przez", - - "modalreason":"Jaki jest powód zamknięcia tego zgłoszenia?", - "chooseATicket": "Wybierz zgłoszenie" - }, - "transcripts":{ - "title":"Transkrypcja", - "processed":"Ta transkrypcja jest przetwarzana", - "wait":"Proszę czekać!", - "estimated":"Szacowany czas", - "available":"Transkrypcja jest dostępna tutaj" - }, - "stats":{ - "globalTitle":"Globalne Statystyki", - "ticketTitle":"Statystyki biletów dla {0}", - "userTitle":"Statystyki użytkowników dla {0}", - "systemTitle":"Statystyki systemu", - "versionTitle":"Wersja bota", - - "ticketsCreated":"Bilety stworzone", - "ticketsClosed":"Bilety zamknięte", - "ticketsDeleted":"Bilety skasowane", - "ticketsReopened":"Bilety otwarte ponownie", - "ticketsAutoclosed":"Bilety automatycznie zamknięte", - "transcriptsCreated":"Utworzono transkrypcje", - "startupDate":"Data uruchomienia", - "latestUpdate":"Najnowsza aktualizacja", - "ticketCreatedOn":"Bilet został utworzony dnia", - "ticketCreatedBy":"Bilet stworzony przez", - "messagesSent":"Wiadomość wysłana", - "status":"Status", - "participants":"Uczestnicy", - "role":"Rola", - - "switches":{ - "globalAdmin":"Globalny administrator", - "ticketAdmin":"Admin biletowy", - "member":"Użytkownik", - "open":"Otwarte", - "reopened":"Otwarte ponownie", - "closed":"Zamknięte", - "autoclosed":"Automatycznie zamknięte" - }, - - "errorUserNotFound":"Tego użytkownika nie można znaleźć w bazie statystyk!" - } -} \ No newline at end of file diff --git a/language/portuguese.json b/language/portuguese.json deleted file mode 100644 index ca030ad..0000000 --- a/language/portuguese.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"quiradon", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Argumentos inválidos!", - "missingArgsDescription":"Argumento ausente", - "noPermsTitle":"Sem permissões!", - "noPermsDescription":"Você precisa da permissão `ADMINISTRATOR` ou estar na lista de funções permitidas!", - "noPermsDelete":"Somente administradores podem deletar um ticket!", - "chooseFromListTitle":"ID inválido", - "chooseFromListDescription":"Escolha um dos IDs abaixo:", - "boterror":"Erro de bot!", - "notInTicketTitle":"Você não está em um ticket!", - "notInTicketDescription":"Este comando não funciona fora dos tickets!", - "ticketDoesntExist":"Este ticket não existe mais!", - "roleDoesntExist":"Esta função não existe mais!", - "anotherOption":"Esta opção não é um ticket, mas sim outro tipo!", - "maxAmountTitle":"Quantidade máxima atingida!", - "maxAmountDescription":"Você atingiu o número máximo de tickets permitidos!\nEntão você não pode criar um novo!", - "somethingWentWrong":"**Algo deu errado!**\nPor favor, tente novamente outra vez!" - }, - "commands":{ - "userAddedTitle":"Adicionado {0} a este ticket!", - "userRemovedTitle":"Removido {0} deste ticket!", - "renameTitle":"Mudou o nome para {0}!", - "closeTitle":"Fechado este ticket!", - "deleteTitle":"Excluindo este ticket...", - "reopenTitle":"Reabriu este ticket!", - - "claimTitle":"Esse ticket foi reinvidicado {0}", - "unclaimTitle":"Esse ticket não foi reinvidicado!", - "changeTitle":"Tipo de ticket alterado para {0}!", - - "statsTitle":"Aqui estão as estatísticas para {0}!", - "autocloseTitle":"Este ticket vai fechar altomaticamente após {0}!", - "autocloseRejectTitle":"Este ticket não será mais fechado automaticamente!", - "autocloseWarn":"Isso apenas afeta tickets inativos!", - - "goToTicket":"ir para ticket", - "ticketWarning":"A incorporação está na mensagem abaixo!", - "maxTicketWarning":"**Cuidado:** _Você só pode criar {0} ticket(s) de cada vez!!_" - }, - "helpMenu":{ - "title":"Comandos Disponíveis:", - "header1":"**Vá para {0} para criar um ticket!**\n\n", - "header2":"**Execute o comando `/new` ou `/ticket` para criar um ticket!**\n\n", - - "msgCmd":"Gerar uma incorporação com botões. (somente administradores)", - "renameCmd":"Renomear um ticket. (sem espaços)", - "closeCmd":"Fechar um ticket.", - "deleteCmd":"Excluir um ticket.", - "addCmd":"Adicionar um usuário ao ticket.", - "removeCmd":"Remover um usuário do ticket.", - "reopenCmd":"Reabra um ticket depois que ele foi fechado.", - "changeCmd":"Mudar tipo de ticket", - "claimCmd":"Resgatar Ticket", - "unclaimCmd":"Desresgatar Ticket", - "statsCmd":"Olhar status do ticket", - "autocloseCmd":"Definir tempo para fechar ticket automaticamente." - }, - "buttons":{ - "close":"Fechar Ticket", - "delete":"Excluir Ticket", - "reopen":"Reabrir Ticket", - "closeWithReason":"fechado com motivo" - }, - "messages":{ - "closedDescription":"Somente administradores podem falar neste ticket agora!\n\n*Clique no botão abaixo para excluir ou reabrir este ticket!*", - "createdTitle":"Ticket criado!", - "createdDescription":"Seu ticket foi criado, você pode detectá-lo com um ping!", - - "newTicketDmTitle":"Novo Ticket!", - "closedTicketDmTitle":"Ticket fechado!", - "deletedTicketDmTitle":"Ticket excluído!", - "closedTicketDmDescription":"Seu ticket está fechado!", - "deletedTicketDmDescription":"Seu bilhete foi excluído!", - "reopenTicketDmTitle":"Ticket reaberto!", - "reopenTicketDmDescription":"Seu ticket foi reaberto!", - - "chooseCategory":"Escolha a categoria:", - "gettingdeleted":"Ticket está sendo deletado...", - - "none":"vazio", - "reason":"motivo", - "createdat":"Criado por:", - "openedby":"Aberto por:", - "deletedby":"Deletado por", - "closedby":"Fechado por", - - "modalreason":"Qual o motivo de fechar o ticket?", - "chooseATicket": "Fechar Ticket" - }, - "transcripts":{ - "title":"Transcrever", - "processed":"A Transcrição está em andamento", - "wait":"Por favor espere!", - "estimated":"Tempo estimado", - "available":"A Transcrição está disponível aqui" - }, - "stats":{ - "globalTitle":"Status Global", - "ticketTitle":"Ticket Status para {0}", - "userTitle":"Status do Membro para {0}", - "systemTitle":"Sistema de Status", - "versionTitle":"Versão do bot", - - "ticketsCreated":"Tickets Criados", - "ticketsClosed":"Tickets Fechados", - "ticketsDeleted":"Tickets Deletados", - "ticketsReopened":"Tickets Re-abertos", - "ticketsAutoclosed":"Tickets Auto-Fechados", - "transcriptsCreated":"Transcrição Criada", - "startupDate":"Data de Inicio", - "latestUpdate":"Última Atualização", - "ticketCreatedOn":"Ticket Criado em", - "ticketCreatedBy":"Ticket Criado por", - "messagesSent":"Mensagem Enviada", - "status":"Status", - "participants":"Participantes", - "role":"Cargo", - - "switches":{ - "globalAdmin":"Global Admin", - "ticketAdmin":"Ticket Admin", - "member":"Membro", - "open":"Abrir", - "reopened":"Re-aberto", - "closed":"Fechado", - "autoclosed":"Auto-Fechado" - }, - - "errorUserNotFound":"Este usuário não pode ser encontrado no banco de dados!" - } -} diff --git a/language/romanian.json b/language/romanian.json deleted file mode 100644 index 3af9f4f..0000000 --- a/language/romanian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"Sanke#6086", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Argumente Invalide", - "missingArgsDescription":"Argument Lipsa", - "noPermsTitle":"Nu ai permisiunea necesara!", - "noPermsDescription":"Ai nevoie de permisiunea de `ADMINISTRATOR`!", - "noPermsDelete":"Doar adminii pot inchide un ticket!", - "chooseFromListTitle":"Invalid ID", - "chooseFromListDescription":"Alege unul dintre id-urile urmatoare:", - "boterror":"Eroare bot!", - "notInTicketTitle":"Nu esti intr-un ticket!", - "notInTicketDescription":"Aceasta comanda nu merge inafara unui ticket!", - "ticketDoesntExist":"Acest ticket nu mai exista!", - "roleDoesntExist":"Acest rol nu mai exista!", - "anotherOption":"Aceasta optiune este altceva decat un tip de ticket!", - "maxAmountTitle":"Limita atinsa!", - "maxAmountDescription":"Ai atins limita de tickets!\nAsa ca nu mai poti creea altele noi!", - "somethingWentWrong":"**Ceva nu a mers bine!**\nTe rugam sa incerci mai tarziu!" - }, - "commands":{ - "userAddedTitle":"{0} a fost adaugat in acest ticket!", - "userRemovedTitle":"{0} a fost scos din acest ticket!", - "renameTitle":"Nume schimbat in {0}!", - "closeTitle":"Ticket inchis!", - "deleteTitle":"Se sterge ticket-ul...", - "reopenTitle":"Ticket Re-deschis!", - - "claimTitle":"Acest ticket a primit claim de la {0}", - "unclaimTitle":"Acest ticket nu mai este detinut!", - "changeTitle":"A fost schimbat tipul ticket-ului la {0}!", - - "statsTitle":"Acestea sunt informatiile pentru {0}!", - "autocloseTitle":"Acest ticket va fi inchis automat dupa {0}!", - "autocloseRejectTitle":"Acest ticket nu va mai fi inchis automat!", - "autocloseWarn":"Aceasta optiune afecteaza numai ticketele inactive!", - - "goToTicket":"Mergi la ticket", - "ticketWarning":"Embed-ul se afla in mesajul de mai jos!", - "maxTicketWarning":"**Avertizare:** _Poti creea doar {0} tickete active!_" - }, - "helpMenu":{ - "title":"Comenzi disponibile:", - "header1":"**Mergi la {0} pentru a creea un ticket!**\n\n", - "header2":"**Ruleaza comanda `/new` ori `/ticket` pentru a creea un ticket!**\n\n", - - "msgCmd":"Trimite embed-ul cu tickete. (doar admini)", - "renameCmd":"Redenumeste un ticket. (fara spatii)", - "closeCmd":"Inchide un ticket.", - "deleteCmd":"Sterge un ticket.", - "addCmd":"Adauga un utilizator in ticket.", - "removeCmd":"Sterge un utilizator din ticket.", - "reopenCmd":"Re-deschide un ticket dupa ce a fost deschis.", - "changeCmd":"Schimba categoria ticket-ului.", - "claimCmd":"Revendica un ticket", - "unclaimCmd":"Anuleaza revendicarea unui ticket.", - "statsCmd":"Afiseasa informatiile ticket-ului.", - "autocloseCmd":"Seteaza un cronometru pentru inchiderea ticket-ului." - }, - "buttons":{ - "close":"Inchide ticket-ul", - "delete":"Sterge ticket-ul", - "reopen":"Re-deschide un ticket", - "closeWithReason":"Inchide cu motiv" - }, - "messages":{ - "closedDescription":"Doar adminii pot vorbi in acest ticket acum!\n\n*Apasa pe butonul de mai jos pentru a re-deschide ori sterge ticket-ul!*", - "createdTitle":"Ticket Creat!", - "createdDescription":"Ticket-ul tau a fost creat, poti sa il vezi in canalul pe care ai fost mentionat!", - - "newTicketDmTitle":"Ticket nou!", - "closedTicketDmTitle":"Ticket Inchis!", - "deletedTicketDmTitle":"Ticket Sters!", - "closedTicketDmDescription":"Ticket-ul tau este inchis!", - "deletedTicketDmDescription":"Ticket-ul tau este sters!", - "reopenTicketDmTitle":"Ticket Re-deschis!", - "reopenTicketDmDescription":"Ticket-ul tau este re-deschis!", - - "chooseCategory":"Alege o categorie:", - "gettingdeleted":"Ticket-ul se sterge...", - - "none":"niciunul", - "reason":"Motiv", - "createdat":"Creat la", - "openedby":"Deschis de", - "deletedby":"Sters de", - "closedby":"Inchis de", - - "modalreason":"Care este motivul pentru inchiderea acestui ticket?", - "chooseATicket": "Alege un ticket" - }, - "transcripts":{ - "title":"Transcript", - "processed":"Transcript in curs de procesare...", - "wait":"Te rugam sa astepti!", - "estimated":"Timp estimat", - "available":"Transcriptul este disponibil aici" - }, - "stats":{ - "globalTitle":"Statistici Globale", - "ticketTitle":"Statistici Ticket pentru {0}", - "userTitle":"Statistici utilizator pentru {0}", - "systemTitle":"Statistici Sistem", - "versionTitle":"Versiune Bot", - - "ticketsCreated":"Tickete Create", - "ticketsClosed":"Tickets Inchise", - "ticketsDeleted":"Tickete Sterse", - "ticketsReopened":"Tickete Redeschise", - "ticketsAutoclosed":"Tickets Inchise automat", - "transcriptsCreated":"Transcript-uri create", - "startupDate":"Data startup", - "latestUpdate":"Update recent", - "ticketCreatedOn":"Ticket creat pe data", - "ticketCreatedBy":"Ticket Creat de", - "messagesSent":"Mesaje trimise", - "status":"Status", - "participants":"Participanti", - "role":"Rol", - - "switches":{ - "globalAdmin":"Admin Global", - "ticketAdmin":"Admin Ticket", - "member":"Membru", - "open":"Deschis", - "reopened":"Redeschis", - "closed":"Inchis", - "autoclosed":"Inchis automat" - }, - - "errorUserNotFound":"Acest utilizator nu poate fi gasit in database-ul nostru!" - } -} diff --git a/language/russian.json b/language/russian.json deleted file mode 100644 index 5c37bcc..0000000 --- a/language/russian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"apexo & ander", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Неверные аргументы!", - "missingArgsDescription":"Отсутствует аргумент", - "noPermsTitle":"Недостаточно прав!", - "noPermsDescription":"Вы должны иметь права `ADMINISTRATOR` или быть в списке разрешённых ролей!", - "noPermsDelete":"Только админы могут удалить тикет!", - "chooseFromListTitle":"Неверный ID", - "chooseFromListDescription":"Выберите один из id ниже:", - "boterror":"Ошибка бота!", - "notInTicketTitle":"Вы не в тикете!", - "notInTicketDescription":"Эта команда не работает вне тикетов!", - "ticketDoesntExist":"Этого тикета больше не существует!", - "roleDoesntExist":"Этой роли больше не существует!", - "anotherOption":"Эта опция не является тикетом, а представляет собой другой тип!", - "maxAmountTitle":"Максимальное количество достигнуто!", - "maxAmountDescription":"Вы достигли максимальное количество разрешённых тикетов!\nТеперь вы не можете создать ещё один!", - "somethingWentWrong":"**Что-то пошло не так!**\nПожайлуста, попробуйте в другой раз!" - }, - "commands":{ - "userAddedTitle":"Добавлено {0} в этот тикет!", - "userRemovedTitle":"Удалено {0} из этого тикета!", - "renameTitle":"Изменено имя на {0}!", - "closeTitle":"Закрыл этот тикет!", - "deleteTitle":"Удаляем этот тикет...", - "reopenTitle":"Открываем заново этот тикет!", - - "claimTitle":"Этот тикет теперь взят {0}", - "unclaimTitle":"Этот тикет никем не взят!", - "changeTitle":"Изменён тип тикета на {0}!", - - "statsTitle":"Здесь статистика для {0}!", - "autocloseTitle":"Этот тикет будет закрыт автоматически после {0}!", - "autocloseRejectTitle":"Этот тикет больше не будет закрыт автоматически!", - "autocloseWarn":"Это касается только неактивных тикетов!", - - "goToTicket":"перейти в тикет", - "ticketWarning":"embed ниже сообщения!", - "maxTicketWarning":"**Предупреждение:** _Вы можете создать только {0} тикет(а/ов) в этот раз!_" - }, - "helpMenu":{ - "title":"Доступные команды:", - "header1":"**Перейдите в {0}, чтобы создать тикет!**\n\n", - "header2":"**Выполните команду `/new` или `/ticket` для создания тикета!**\n\n", - - "msgCmd":"Создать embed с кнопками. (только админам)", - "renameCmd":"Переименовать тикет. (без пробелов)", - "closeCmd":"Закрыть тикет.", - "deleteCmd":"Удалить тикет.", - "addCmd":"Добавить пользователя в тикет.", - "removeCmd":"Удалить пользователя из тикета.", - "reopenCmd":"Открыть заново тикет после того, как он был закрыт.", - "changeCmd":"Поменять тип тикета.", - "claimCmd":"Взять тикет.", - "unclaimCmd":"Снять тикет.", - "statsCmd":"Посмотреть статистику тикета.", - "autocloseCmd":"Установить таймер, чтобы автоматически закрыть тикет" - }, - "buttons":{ - "close":"Закрыть тикет", - "delete":"Удалить тикет", - "reopen":"Открыть заново тикет", - "closeWithReason":"закрыть с причиной" - }, - "messages":{ - "closedDescription":"Только админы теперь могут писать в этом тикете!\n\n*Нажмите на кнопку ниже, чтобы удалить или заново окрыть тикет!*", - "createdTitle":"Тикет создан!", - "createdDescription":"Ваш тикет создан, вы можете обнаружить его по пингу!", - - "newTicketDmTitle":"Новый тикет!", - "closedTicketDmTitle":"Тикет закрыт!", - "deletedTicketDmTitle":"Тикет удалён!", - "closedTicketDmDescription":"Ваш тикет закрыт!", - "deletedTicketDmDescription":"Ваш тикет удалён!", - "reopenTicketDmTitle":"Тикет открыт заново!", - "reopenTicketDmDescription":"Ваш тикет открыт заново!", - - "chooseCategory":"выберите категорию:", - "gettingdeleted":"Тикет будет удалён...", - - "none":"отсутствует", - "reason":"причина", - "createdat":"создан", - "openedby":"открыт", - "deletedby":"удалён", - "closedby":"закрыт", - - "modalreason":"Какая причина закрытия этого тикета?", - "chooseATicket": "Выберите тикет" - }, - "transcripts":{ - "title":"Транскрипт", - "processed":"Этот транскрипт находится в процессе обработки", - "wait":"Пожайлуста подождите!", - "estimated":"Оценочное время", - "available":"Транскрипт здесь доступен" - }, - "stats":{ - "globalTitle":"Общая статистика", - "ticketTitle":"Статистика тикета для {0}", - "userTitle":"Статистика пользователя для {0}", - "systemTitle":"Системная статистика", - "versionTitle":"Версия бота", - - "ticketsCreated":"Тикет создан", - "ticketsClosed":"Тикет закрыт", - "ticketsDeleted":"Тикет удален", - "ticketsReopened":"Тикет переоткрыт", - "ticketsAutoclosed":"Тикет автоматически закрыт", - "transcriptsCreated":"Транскрипт создан", - "startupDate":"Дата запуска", - "latestUpdate":"Последнее обновление", - "ticketCreatedOn":"Тикет создан", - "ticketCreatedBy":"Тикет создан", - "messagesSent":"Сообщение отправлено", - "status":"Статус", - "participants":"Участники", - "role":"Роль", - - "switches":{ - "globalAdmin":"Главная", - "ticketAdmin":"Тикет", - "member":"Участник", - "open":"Открыть", - "reopened":"Переоткрытый", - "closed":"Закрыт", - "autoclosed":"Автоматически закрыт" - }, - - "errorUserNotFound":"Участник не найден в базе данных статистики!" - } -} diff --git a/language/simplifiedchinese.json b/language/simplifiedchinese.json deleted file mode 100644 index a40d474..0000000 --- a/language/simplifiedchinese.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"iamnotmega", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"缺少参数!", - "missingArgsDescription":"缺少参数", - "noPermsTitle":"没有权限!", - "noPermsDescription":"您需要管理员权限或必须在允许的角色列表中!", - "noPermsDelete":"只有管理员可以删除票据!", - "chooseFromListTitle":"无效的ID", - "chooseFromListDescription":"请选择以下ID之一:", - "boterror":"机器人错误!", - "notInTicketTitle":"你不在票据中!", - "notInTicketDescription":"此命令不适用于票据外!", - "ticketDoesntExist":"此票据已不存在!", - "roleDoesntExist":"此角色已不存在!", - "anotherOption":"此选项不是票据,而是其他类型!", - "maxAmountTitle":"达到最大数量!", - "maxAmountDescription":"您已达到允许的最大票据数量!\n因此您不能创建新的票据!", - "somethingWentWrong":"**出了点问题!**\n请稍后再试!" - }, - "commands":{ - "userAddedTitle":"已将{0}添加到此票据中!", - "userRemovedTitle":"已将{0}从此票据中移除!", - "renameTitle":"已将名称更改为{0}!", - "closeTitle":"此票据已关闭!", - "deleteTitle":"正在删除此票据...", - "reopenTitle":"此票据已重新打开!", - - "claimTitle":"此票据已分配给{0}", - "unclaimTitle":"此票据不再被分配!", - "changeTitle":"票据类型更改为{0}!", - - "statsTitle":"以下是{0}的统计信息!", - "autocloseTitle":"此票据将在{0}后自动关闭!", - "autocloseRejectTitle":"此票据将不再自动关闭!", - "autocloseWarn":"这只影响不活跃的票据!", - - "goToTicket":"前往票据", - "ticketWarning":"嵌入信息在下方消息中!", - "maxTicketWarning":"**警告:** _您一次只能创建{0}个票据!_" - }, - "helpMenu":{ - "title":"可用命令:", - "header1":"**前往{0}以创建票据!**\n\n", - "header2":"**运行命令`/new`或`/ticket`以创建票据!**\n\n", - - "msgCmd":"生成带有按钮的嵌入消息。(仅限管理员)", - "renameCmd":"重命名票据。(无空格)", - "closeCmd":"关闭票据。", - "deleteCmd":"删除票据。", - "addCmd":"将用户添加到票据。", - "removeCmd":"将用户从票据中移除。", - "reopenCmd":"关闭后重新打开票据。", - "changeCmd":"更改票据类型。", - "claimCmd":"分配票据。", - "unclaimCmd":"取消分配票据。", - "statsCmd":"查看票据统计信息。", - "autocloseCmd":"设置计时器以自动关闭票据" - }, - "buttons":{ - "close":"关闭票据", - "delete":"删除票据", - "reopen":"重新打开票据", - "closeWithReason":"有理由地关闭" - }, - "messages":{ - "closedDescription":"现在只有管理员可以在此票据中讲话!\n\n*点击下方按钮以删除或重新打开此票据!*", - "createdTitle":"票据已创建!", - "createdDescription":"您的票据已创建,您可以通过提醒来检测到它!", - - "newTicketDmTitle":"新票据!", - "closedTicketDmTitle":"票据已关闭!", - "deletedTicketDmTitle":"票据已删除!", - "closedTicketDmDescription":"您的票据已关闭!", - "deletedTicketDmDescription":"您的票据已删除!", - "reopenTicketDmTitle":"票据已重新打开!", - "reopenTicketDmDescription":"您的票据已重新打开!", - - "chooseCategory":"选择一个类别:", - "gettingdeleted":"票据正在删除...", - - "none":"无", - "reason":"原因", - "createdat":"创建于", - "openedby":"打开者", - "deletedby":"删除者", - "closedby":"关闭者", - - "modalreason":"关闭此票据的原因是什么?", - "chooseATicket":"选择一个票据" - }, - "transcripts":{ - "title":"记录", - "processed":"此记录正在处理", - "wait":"请稍候!", - "estimated":"预计时间", - "available":"记录在此处可用" - }, - "stats":{ - "globalTitle":"全局统计", - "ticketTitle":"{0}的票据统计", - "userTitle":"{0}的用户统计", - "systemTitle":"系统统计", - "versionTitle":"机器人版本", - - "ticketsCreated":"创建的票据", - "ticketsClosed":"关闭的票据", - "ticketsDeleted":"删除的票据", - "ticketsReopened":"重新打开的票据", - "ticketsAutoclosed":"自动关闭的票据", - "transcriptsCreated":"创建的记录", - "startupDate":"启动日期", - "latestUpdate":"最新更新", - "ticketCreatedOn":"票据创建于", - "ticketCreatedBy":"票据创建者", - "messagesSent":"发送的消息", - "status":"状态", - "participants":"参与者", - "role":"角色", - - "switches":{ - "globalAdmin":"全局管理员", - "ticketAdmin":"票据管理员", - "member":"成员", - "open":"打开", - "reopened":"重新打开", - "closed":"关闭", - "autoclosed":"自动关闭" - }, - - "errorUserNotFound":"在统计数据库中找不到该用户!" - } -} diff --git a/language/slashcmds/slash.json b/language/slashcmds/slash.json deleted file mode 100644 index bad4a9a..0000000 --- a/language/slashcmds/slash.json +++ /dev/null @@ -1,215 +0,0 @@ -{ - "examples":{ - "en-GB":"english", - "en-US":"english", - "no": "Norwegian", - "nl":"dutch", - "ro":"romanian", - "de":"german", - "cs":"czech", - "fr":"french", - "es-ES":"spanish", - "it":"italian", - "ru":"russian", - "tr": "Türkçe", - "ar": "Arabic", - "th": "Thailand", - - "MISSING":"portuguese", - "NOTAVAILABLE":"portuguese,czech" - }, - "data":{ - "help":{ - "en-GB":"A list of the available commands.", - "en-US":"A list of the available commands.", - "no":"En liste over commands.", - "nl":"Een lijst met de beschikbare commands.", - "ro":"O lista a comenzilor disponibile.", - "de":"Eine Liste der verfügbaren Befehle.", - "cs":"A list of the available commands", - "fr":"Une liste des commandes.", - "es-ES":"Una lista de los comandos disponibles.", - "it":"Una lista di tutti i comandi disponibili.", - "ru":"Список доступных команд", - "tr": "Kullanılabilir komutların listesi.", - "ar": "قائمة للكوماندات المتاحة", - "th": "List คำสั่งที่สามารถใช้งานได้" - }, - "message":{ - "en-GB":"Spawn an embed with buttons.", - "en-US":"Spawn an embed with buttons.", - "no":"Legg inn en melding i denne kanalen", - "nl":"Spawn een embed met knoppen.", - "ro":"Deschide un embed cu butoane.", - "de":"Sendet ein Embed mit Knöpfen.", - "cs":"Spawn an embed with buttons.", - "fr":"Créer un embed avec des boutons.", - "es-ES":"Genera un embed con botones.", - "it":"Genera un embed con un pulsante.", - "ru":"Создать embed с кнопками", - "tr": "Butonlar ile bir yerleştirme oluşturun.", - "ar": "أنشاء أيمبد مع الأزرار.", - "th": "เรียก Embed และปุ่มต่างๆ" - }, - "close":{ - "en-GB":"Close a ticket.", - "en-US":"Close a ticket.", - "no":"Lukk ticket.", - "nl":"Sluit een ticket", - "ro":"Inchide un ticket.", - "de":"Schließe ein Ticket.", - "cs":"Close a ticket.", - "fr":"Fermer un ticket.", - "es-ES":"Cierra un ticket.", - "it":"Chiudi un ticket.", - "ru":"Закрыть тикет", - "tr": "Bileti kapat.", - "ar": "اغلاق تيكت.", - "th": "ปิดห้องติดต่อ" - }, - "delete":{ - "en-GB":"Delete a ticket.", - "en-US":"Delete a ticket.", - "no":"Slett ticket.", - "nl":"Verwijder een ticket", - "ro":"Sterge un ticket.", - "de":"Lösche ein Ticket.", - "cs":"Delete a ticket.", - "fr":"Supprimer un ticket.", - "es-ES":"Elimina un ticket.", - "it":"Elimina un ticket.", - "ru":"Удалить тикет", - "tr": "Bileti sil.", - "ar": "حذف تيكت.", - "th": "ลบห้องติดต่อ" - }, - "reopen":{ - "en-GB":"Re-Open a ticket.", - "en-US":"Re-Open a ticket.", - "no":"Gjenåpne ticket.", - "nl":"Heropen een ticket.", - "ro":"Re-deschide un ticket.", - "de":"Wiedereröffnung eines Tickets.", - "cs":"Re-Open a ticket.", - "fr":"Re-ouvrir un ticket.", - "es-ES":"Re-abre un ticket.", - "it":"Ri-Apri un ticket.", - "ru":"Открыть заново тикет", - "tr": "Bileti yeniden aç.", - "ar": "اعادة فتح تيكت.", - "th": "เปิดห้องติดต่อใหม่อีกครั้ง" - }, - "add":{ - "en-GB":"Add another user to a ticket.", - "en-US":"Add another user to a ticket.", - "no":"Legg til en annen bruker til ticket.", - "nl":"Voeg een andere user toe aan een ticket.", - "ro":"Adauga un utilizator la acest ticket.", - "de":"Füge einen anderen Nutzer zum Ticket hinzu.", - "cs":"Add another user to a ticket.", - "fr":"Ajouter un utilisateur au ticket.", - "es-ES":"Agrega otro usuario al ticket.", - "it":"Aggiungi un membro al ticket", - "ru":"Добавить другого пользователя в тикет", - "tr": "Bilete başka bir kullanıcı ekle.", - "ar": "اضافة مستخدم اخر الى تيكت معين.", - "th": "เพิ่มผู้ใช้เข้ามาในห้องติดต่อ" - }, - "remove":{ - "en-GB":"Remove a user from a ticket.", - "en-US":"Remove a user from a ticket.", - "no":"Fjern en bruker fra ticket.", - "nl":"Verwijder een user van een ticket.", - "ro":"Sterge un utilizator dintr-un ticket.", - "de":"Entferne einen Nutzer von dem Ticket.", - "cs":"Remove a user from a ticket.", - "fr":"Enlever quelqu’un du ticket.", - "es-ES":"Elimina otro usuario del ticket.", - "it":"Rimuovi un membro dal ticket", - "ru":"Удалить пользователя из тикета", - "tr": "Kullanıcıyı bir biletten kaldır.", - "ar": "ازالة مستخدم من تيكت معين.", - "th": "ลบผู้ใช้ออกจากห้องติดต่อ" - }, - "newticket":{ - "en-GB":"Create a ticket", - "en-US":"Create a ticket", - "no":"Lag en ny ticket", - "nl":"Maak een ticket aan", - "ro":"Creeaza un ticket.", - "de":"Erstelle ein Ticket.", - "cs":"Create a ticket", - "fr":"Créer un ticket", - "es-ES":"Crear un ticket.", - "it":"Crea un ticket", - "ru":"Создать тикет", - "tr": "Bilet oluştur", - "ar": "انشاء تيكت.", - "th": "สร้างห้องติดต่อใหม่" - }, - "rename":{ - "en-GB":"Rename a ticket channel.", - "en-US":"Rename a ticket channel.", - "no":"Gi nytt navn til ticket kanalen.", - "nl":"Hernoem een ticket channel.", - "ro":"Redenumeste un ticket.", - "de":"Benenne einen Ticket Channel.", - "cs":"Rename a ticket channel", - "fr":"Renommer un ticket.", - "es-ES":"Renombrar un canal de ticket.", - "it":"Rinomina il canale di un ticket.", - "ru":"Переименовать канал тикета", - "tr": "Bilet kanalını yeniden adlandır.", - "ar": "اعادة تسمية التيكت.", - "th": "แก้ไชชื่อห้องติดต่อ" - }, - "claim":{ - "en-GB":"Claim a ticket.", - "en-US":"Claim a ticket.", - "no":"Overta ticket.", - "nl":"Claim een ticket.", - "ro":" ", - "de":" ", - "cs":" ", - "fr":" ", - "es-ES":" ", - "it":" ", - "ru":"Взять тикет", - "tr":"Bilet talep et.", - "ar": "تعيين التيكت", - "th": "รับเรื่อง" - }, - "unclaim":{ - "en-GB":"Un-claim a ticket.", - "en-US":"Un-claim a ticket.", - "no":"Frigjør ticket.", - "nl":"Ontclaim een ticket.", - "ro":" ", - "de":" ", - "cs":" ", - "fr":" ", - "es-ES":" ", - "it":" ", - "ru":"Снять тикет", - "tr":"Bileti iptal et.", - "ar": "ازالة التعيين من شخص الى التيكت", - "th": "ยกเลิกการรับเรื่อง" - }, - "category":{ - "en-GB":"Change ticket type.", - "en-US":"Change ticket type.", - "no":"Endre ticket type.", - "nl":"Verander ticket type.", - "ro":" ", - "de":" ", - "cs":" ", - "fr":" ", - "es-ES":" ", - "it":" ", - "ru":"Изменить тип тикета", - "tr":"Bilet türünü değiştir.", - "ar": "تغيير نوع التيكت", - "th": "เปลี่ยนประเภทห้องติดต่อ" - } - } -} diff --git a/language/slovenian.json b/language/slovenian.json deleted file mode 100644 index 3ed194b..0000000 --- a/language/slovenian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"n1kkec", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Napačen argument!", - "missingArgsDescription":"Argument manka", - "noPermsTitle":"Nimas dovoljenja!", - "noPermsDescription":"Potrebuješ dovoljenje `ADMINISTRATOR` ali pa biti v listi dovoljenih role!", - "noPermsDelete":"Samo admini lahko izbrišejo ticket!", - "chooseFromListTitle":"Napačen ID", - "chooseFromListDescription":"Izberi eden izmed ID-jev:", - "boterror":"NAPAKA Bota!", - "notInTicketTitle":"Nisi v ticketu!", - "notInTicketDescription": "Ta ukaz ne deluje zunaj ticket-ov!", - "ticketDoesntExist": "Ta ticket ne obstaja več!", - "roleDoesntExist": "Ta vloga ne obstaja več!", - "anotherOption": "Ta možnost ni ticket, ampak druga vrsta!", - "maxAmountTitle": "Najvišji doseženi znesek!", - "maxAmountDescription": "Dosegli ste največje dovoljeno število ticket-ov!\nTako da ne morete ustvariti nove!", - "somethingWentWrong": "**Nekaj je šlo narobe!**\nProsimo, poskusite znova drugič!" - }, - "commands":{ - "userAddedTitle": "Dodan {0} v ta ticket!", - "userRemovedTitle": "Odstranjeo {0} iz tega ticket-!", - "renameTitle": "Spremenjeno ime na {0}!", - "closeTitle": "Zaprl ta ticket!", - "deleteTitle": "Brisanje ticketa...", - "reopenTitle": "Ponovno odprl ta ticket!", - - "claimTitle":"Ticket je claimal {0}", - "unclaimTitle":"Ticket ni več claiman!", - "changeTitle":"Changed ticket type to {0}!", - - "statsTitle":"Statistike za {0}!", - "autocloseTitle":"Ticket so avtomatsko zapru po {0}!", - "autocloseRejectTitle":"Ticket se nebo avtomatsko zapru!", - "autocloseWarn":"To ima efekt samo na inactive ticketih!", - - "goToTicket":"pojdi v ticket", - "ticketWarning": "Opozorilo je v spodnjem sporočilu!", - "maxTicketWarning": "**Opozorilo:** _Naenkrat lahko ustvarite le {0} ticketov!_" - }, - "helpMenu":{ - "title": "Razpoložljivi ukazi:", - "header1": "**Izberite {0} in ustvarite ticket!**\n\n", - "header2": "**Zaženi ukaz `/new` ali `/ticket` za ustvarjanje ticket-a!**\n\n", - - "msgCmd": "Ustvari vstavek z gumbi. (samo za administratorje)", - "renameCmd": "Preimenujte ticket. (brez presledkov)", - "closeCmd": "Zapri ticket.", - "deleteCmd": "Izbriši ticket.", - "addCmd": "Dodaj uporabnika v ticket.", - "removeCmd": "Odstrani uporabnika z ticket-a.", - "reopenCmd": "Ponovno odprite ticket, ko je bila zaprta.", - "changeCmd":"Spremeni tip ticketa.", - "claimCmd":"Claimaj ticket.", - "unclaimCmd":"Unclaimaj ticket.", - "statCmds":"Statistike ticketa.", - "autocloseCmd":"Nastavi timer da avtomatsko zapre ticket" - }, - "buttons":{ - "close":"Zapri Ticket", - "delete":"Izbrisi Ticket", - "reopen":"Odpri Ticket", - "closeWithReason":"Zapri z razlogom" - }, - "messages":{ - "closedDescription": "V tem ticket-u lahko zdaj govorijo samo administratorji!\n\n*Kliknite na spodnji gumb za brisanje ali ponovno odprtje te ticket!*", - "createdTitle": "Ticket ustvarjen!", - "createdDescription": "Vaš ticket je ustvarjen, lahko jo odkrijete s pingom!", - - "newTicketDmTitle": "Nov ticket!", - "closedTicketDmTitle": "Ticket zaprt!", - "deletedTicketDmTitle": "Izbrisan ticket!", - "closedTicketDmDescription": "Vaš ticket je zaprta!", - "deletedTicketDmDescription": "Vaš ticket je izbrisan!", - "reopenTicketDmTitle": "Ticket je ponovno odprt!", - "reopenTicketDmDescription": "Vaš ticket je ponovno odprt!", - - "chooseCategory": "izberite kategorijo:", - "gettingdeleted": "Ticket se briše...", - - "none": "ni", - "reason": "razlog", - "createdat":"ustvarjeno ob", - "openedby":"odprto od", - "deletedby": "izbrisano s", - "closedby": "zaprl", - - "modalreason": "Kakšen je razlog za zaprtje tega ticket?", - "chooseATicket": "Izberi ticket" - }, - "transcripts":{ - "naslov": "Transkript", - "obdelano": "Ta prepis se obdeluje", - "wait": "Počakajte!", - "estimated": "Predvideni čas", - "available": "Prepis je na voljo tukaj" - }, - "stats":{ - "globalTitle":"Global Stats", - "ticketTitle":"Ticket Stats for {0}", - "userTitle":"User Stats for {0}", - "systemTitle":"System Stats", - "versionTitle":"Bot Version", - - "ticketsCreated":"Tickets Created", - "ticketsClosed":"Tickets Closed", - "ticketsDeleted":"Tickets Deleted", - "ticketsReopened":"Tickets Reopened", - "ticketsAutoclosed":"Tickets Autoclosed", - "transcriptsCreated":"Transcripts Created", - "startupDate":"Startup Date", - "latestUpdate":"Latest Update", - "ticketCreatedOn":"Ticket Created On", - "ticketCreatedBy":"Ticket Created By", - "messagesSent":"Messages Sent", - "status":"Status", - "participants":"Participants", - "role":"Role", - - "switches":{ - "globalAdmin":"Global Admin", - "ticketAdmin":"Ticket Admin", - "member":"Member", - "open":"Open", - "reopened":"Reopened", - "closed":"Closed", - "autoclosed":"Autoclosed" - }, - - "errorUserNotFound":"This user can't be found in the stats database!" - } -} \ No newline at end of file diff --git a/language/spanish.json b/language/spanish.json deleted file mode 100644 index 39f996b..0000000 --- a/language/spanish.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"redactado & josuens", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"¡Argumentos inválidos!", - "missingArgsDescription":"Argumento faltante.", - "noPermsTitle":"¡Sin permisos!", - "noPermsDescription":"Necesitas el permiso de `ADMINISTRADOR` o estar en la lista de roles permitidos!", - "noPermsDelete":"Solo los administradores pueden eliminar un ticket.!", - "chooseFromListTitle":"ID Invalida", - "chooseFromListDescription":"Elije una de las ID de abajo:", - "boterror":"¡Error del bot!", - "notInTicketTitle":"¡No te encuentras en un ticket!", - "notInTicketDescription":"¡Este comando no funciona fuera de los tickets!", - "ticketDoesntExist":"¡Este ticket no existe!", - "roleDoesntExist":"¡Este rol no existe!", - "anotherOption":"¡Esta opción no es un ticket, si no otra cosa!", - "maxAmountTitle":"¡Máxima cantidad alcanzada!", - "maxAmountDescription":"¡Has alcanzado la máxima cantidad de tickets permitida!\n¡Por lo que no puedes crear otro!", - "somethingWentWrong":"**¡Algo salió mal!**\n¡Prueba dentro de un rato!" - }, - "commands":{ - "userAddedTitle":"Se agregó {0} al ticket!", - "userRemovedTitle":"Se eliminó {0} del ticket!", - "renameTitle":"Cambió el nombre a {0}!", - "closeTitle":"Cerró este ticket!", - "deleteTitle":"Eliminando este ticket...", - "reopenTitle":"Re-abrió este boleto!", - - "claimTitle":"Este ticket fué reclamado por {0}", - "unclaimTitle":"¡Este ticket se encuentra desatendido!", - "changeTitle":"¡Cambiado el tipo de ticket a {0}!", - - "statsTitle":"¡Aquí están las estadísticas para {0}!", - "autocloseTitle":"¡Este ticket será cerrado después de {0}!", - "autocloseRejectTitle":"¡Cierre automático del ticket desactivado!", - "autocloseWarn":"¡Esto solo afecta tickets inactivos!", - - "goToTicket":"ir al ticket", - "ticketWarning":"La inserción está en el mensaje a continuación!", - "maxTicketWarning":"**Advertencia:** _Solo puedes crear {0} ticket(s) a la vez!_" - }, - "helpMenu":{ - "title":"Comandos disponibles:", - "header1":"**¡Dirígete a {0} para crear un nuevo ticket!**\n\n", - "header2":"**¡Ejecuta el comando `/new` o `/ticket` para crear un ticket!**\n\n", - - "msgCmd":"Generar un embed con botones. (Solo admins)", - "renameCmd":"Renombrar un ticket. (Sin espacios)", - "closeCmd":"Cerrar un ticket.", - "deleteCmd":"Eliminar un ticket.", - "addCmd":"Agregar un usuario al ticket.", - "removeCmd":"Eliminar un usuario del ticket.", - "reopenCmd":"Re-Abre un ticket después de que este se vea cerrado.", - "changeCmd":"Cambia el tipo de ticket.", - "claimCmd":"Reclama un ticket.", - "unclaimCmd":"Desatiende un ticket.", - "statsCmd":"Mira las estadísticas de los tickets.", - "autocloseCmd":"Establece un temporizador para cerrar el ticket." - }, - "buttons":{ - "close":"Cerrar ticket.", - "delete":"Eliminar ticket", - "reopen":"Re-Abrir ticket", - "closeWithReason":"cerrar con razón" - }, - "messages":{ - "closedDescription":"¡Solo admins pueden hablar ahora en este ticket!\n\n*¡Presiona en el botón de abajo para eliminar o re-abrir el ticket!*", - "createdTitle":"¡Ticket creado!", - "createdDescription":"¡Ticket creado, también te he mencionado en él!", - - "newTicketDmTitle":"¡Nuevo ticket!", - "closedTicketDmTitle":"¡Ticket cerrado!", - "deletedTicketDmTitle":"¡Ticket eliminado!", - "closedTicketDmDescription":"¡Tu ticket fué cerrado!", - "deletedTicketDmDescription":"¡Tu ticket fué eliminado!", - "reopenTicketDmTitle":"¡Ticket re-abierto!", - "reopenTicketDmDescription":"¡Tu ticket se vió abierto de nuevo!", - - "chooseCategory":"Elije una categoría:", - "gettingdeleted":"El ticket se está viendo eliminado...", - - "none":"Ninguna.", - "reason":"Razón", - "createdat":"creado el", - "openedby":"abierto por", - "deletedby":"eliminado por", - "closedby":"cerrado por", - - "modalreason":"Cúal es la razón para cerrar este ticket?", - "chooseATicket": "Elije un ticket" - }, - "transcripts":{ - "title":"Transcripción", - "processed":"La transcripción del ticket está siendo procesada...", - "wait":"¡Por favor, espere!", - "estimated":"Tiempo estimado", - "available":"La transcripción estará disponible aquí" - }, - "stats":{ - "globalTitle":"Estadísticas Globales", - "ticketTitle":"Estadísitcas para el ticket {0}", - "userTitle":"Estadísticas para el usuario {0}", - "systemTitle":"Estadísticas del sistema", - "versionTitle":"Versión del bot", - - "ticketsCreated":"Tickets Creados", - "ticketsClosed":"Tickets Cerrados", - "ticketsDeleted":"Tickets Eliminados", - "ticketsReopened":"Tickets Reabiertos", - "ticketsAutoclosed":"Tickets Cerrados automáticamente", - "transcriptsCreated":"Transcripciones Creadas", - "startupDate":"Fecha de Inicio", - "latestUpdate":"Última Actualización", - "ticketCreatedOn":"Ticket creado el", - "ticketCreatedBy":"Ticket creado por", - "messagesSent":"Mensajes enviados", - "status":"Estado", - "participants":"Participantes", - "role":"Rol", - - "switches":{ - "globalAdmin":"Admin Global", - "ticketAdmin":"Admin del Ticket", - "member":"Miembro", - "open":"Abierto", - "reopened":"Reabierto", - "closed":"Cerrado", - "autoclosed":"Cerrado automáticamente" - }, - - "errorUserNotFound":"¡Este usuario no pudo ser encontrado en la base de datos de estadísitcas!" - } -} \ No newline at end of file diff --git a/language/swedish.json b/language/swedish.json deleted file mode 100644 index c09ec2f..0000000 --- a/language/swedish.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"iamnotmega", - "_INFO":"Denna fil är en översättning för öppen biljett 3.5.8", - - "errors":{ - "missingArgsTitle":"Ogiltiga argument!", - "missingArgsDescription":"Saknat argument", - "noPermsTitle":"Inga behörigheter!", - "noPermsDescription":"Du behöver behörigheten `ADMINISTRATOR` eller vara i listan över tillåtna roller!", - "noPermsDelete":"Endast administratörer kan ta bort en biljett!", - "chooseFromListTitle":"Ogiltigt ID", - "chooseFromListDescription":"Välj ett av ID:n nedan:", - "boterror":"Botfel!", - "notInTicketTitle":"Du är inte i en biljett!", - "notInTicketDescription":"Detta kommando fungerar inte utanför biljetter!", - "ticketDoesntExist":"Denna biljett finns inte längre!", - "roleDoesntExist":"Denna roll finns inte längre!", - "anotherOption":"Detta alternativ är inte en biljett utan en annan typ!", - "maxAmountTitle":"Maximalt antal uppnått!", - "maxAmountDescription":"Du har nått det maximala antalet tillåtna biljetter!\nDu kan inte skapa en ny!", - "somethingWentWrong":"**Något gick fel!**\nFörsök igen senare!" - }, - "commands":{ - "userAddedTitle":"Lade till {0} i denna biljett!", - "userRemovedTitle":"Tog bort {0} från denna biljett!", - "renameTitle":"Bytte namn till {0}!", - "closeTitle":"Stängde denna biljett!", - "deleteTitle":"Tar bort denna biljett...", - "reopenTitle":"Öppnade denna biljett igen!", - - "claimTitle":"Denna biljett är anspråkad av {0}", - "unclaimTitle":"Denna biljett är inte längre anspråkad!", - "changeTitle":"Bytte biljetttyp till {0}!", - - "statsTitle":"Här är statistiken för {0}!", - "autocloseTitle":"Denna biljett kommer att stängas automatiskt efter {0}!", - "autocloseRejectTitle":"Denna biljett kommer inte längre att stängas automatiskt!", - "autocloseWarn":"Detta påverkar endast inaktiva biljetter!", - - "goToTicket":"gå till biljett", - "ticketWarning":"Inbäddningen finns i meddelandet nedan!", - "maxTicketWarning":"**Varning:** _Du kan endast skapa {0} biljett(er) åt gången!_" - }, - "helpMenu":{ - "title":"Tillgängliga kommandon:", - "header1":"**Gå till {0} för att skapa en biljett!**\n\n", - "header2":"**Kör kommandot `/new` eller `/ticket` för att skapa en biljett!**\n\n", - - "msgCmd":"Skapa en inbäddning med knappar. (endast administratörer)", - "renameCmd":"Byt namn på en biljett. (inga mellanslag)", - "closeCmd":"Stäng en biljett.", - "deleteCmd":"Ta bort en biljett.", - "addCmd":"Lägg till en användare i biljetten.", - "removeCmd":"Ta bort en användare från biljetten.", - "reopenCmd":"Öppna en biljett igen efter att den har stängts.", - "changeCmd":"Byt biljetttyp.", - "claimCmd":"Anspråka en biljett.", - "unclaimCmd":"Avslå en biljett.", - "statsCmd":"Visa biljettstatistik.", - "autocloseCmd":"Ställ in timer för att automatiskt stänga biljett" - }, - "buttons":{ - "close":"Stäng biljett", - "delete":"Ta bort biljett", - "reopen":"Öppna biljett igen", - "closeWithReason":"stäng med anledning" - }, - "messages":{ - "closedDescription":"Endast administratörer kan prata i denna biljett nu!\n\n*Klicka på knappen nedan för att ta bort eller öppna den här biljetten!*", - "createdTitle":"Biljett skapad!", - "createdDescription":"Din biljett är skapad, du kan upptäcka den genom en ping!", - - "newTicketDmTitle":"Ny biljett!", - "closedTicketDmTitle":"Biljett stängd!", - "deletedTicketDmTitle":"Biljett borttagen!", - "closedTicketDmDescription":"Din biljett är stängd!", - "deletedTicketDmDescription":"Din biljett är borttagen!", - "reopenTicketDmTitle":"Biljett öppnad igen!", - "reopenTicketDmDescription":"Din biljett är öppnad igen!", - - "chooseCategory":"välj en kategori:", - "gettingdeleted":"Biljett håller på att tas bort...", - - "none":"ingen", - "reason":"anledning", - "createdat":"skapad den", - "openedby":"öppnad av", - "deletedby":"borttagen av", - "closedby":"stängd av", - - "modalreason":"Vad är anledningen till att stänga den här biljetten?", - "chooseATicket": "Välj en biljett" - }, - "transcripts":{ - "title":"Transkript", - "processed":"Detta transkript bearbetas", - "wait":"Var god vänta!", - "estimated":"Beräknad tid", - "available":"Transkriptet är tillgängligt här" - }, - "stats":{ - "globalTitle":"Globala statistik", - "ticketTitle":"Biljettstatistik för {0}", - "userTitle":"Användarstatistik för {0}", - "systemTitle":"Systemstatistik", - "versionTitle":"Botversion", - - "ticketsCreated":"Biljetter skapade", - "ticketsClosed":"Biljetter stängda", - "ticketsDeleted":"Biljetter borttagna", - "ticketsReopened":"Biljetter öppnade igen", - "ticketsAutoclosed":"Biljetter automatiskt stängda", - "transcriptsCreated":"Transkript skapade", - "startupDate":"Uppstartsdag", - "latestUpdate":"Senaste uppdatering", - "ticketCreatedOn":"Biljett skapad den", - "ticketCreatedBy":"Biljett skapad av", - "messagesSent":"Meddelanden skickade", - "status":"Status", - "participants":"Deltagare", - "role":"Roll", - - "switches":{ - "globalAdmin":"Global admin", - "ticketAdmin":"Biljettadministratör", - "member":"Medlem", - "open":"Öppen", - "reopened":"Återöppnad", - "closed":"Stängd", - "autoclosed":"Automatiskt stängd" - }, - - "errorUserNotFound":"Den här användaren hittades inte i statistikdatabasen!" - } -} diff --git a/language/thai.json b/language/thai.json deleted file mode 100644 index 308663c..0000000 --- a/language/thai.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"modshd", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"อาร์กิวเมนต์ไม่ถูกต้อง", - "missingArgsDescription":"ขาดอาร์กิวเมนต์", - "noPermsTitle":"คุณไม่มีสิทธิ์ในการใช้งาน", - "noPermsDescription":"คุณต้องมีสิทธิ์ `ADMINISTRATOR` หรืออยู่ในรายการบทบาทที่ได้รับอนุญาตเพื่อใช้งาน", - "noPermsDelete":"เฉพาะผู้ดูแลระบบเท่านั้นที่สามารถลบห้องติดต่อได้", - "chooseFromListTitle":"ID ไม่ถูกต้อง", - "chooseFromListDescription":"เลือกหนึ่งใน ID ด้านล่าง:", - "boterror":"ข้อผิดพลาดของบอท", - "notInTicketTitle":"คุณไม่ได้อยู่ในห้องติดต่อ", - "notInTicketDescription":"คำสั่งนี้ไม่สามารถทำงานนอกห้องติดต่อ", - "ticketDoesntExist":"ห้องติดต่อนี้ไม่มีอีกต่อไป", - "roleDoesntExist":"บทบาทนี้ไม่มีอีกต่อไป", - "anotherOption":"ตัวเลือกนี้ไม่ใช่ห้องติดต่อ แต่เป็นประเภทอื่น", - "maxAmountTitle":"ถึงจำนวนสูงสุดแล้ว", - "maxAmountDescription":"คุณได้ถึงจำนวนสูงสุดของห้องติดต่อที่อนุญาต\nดังนั้นคุณไม่สามารถสร้างใหม่ได้ในขณะนี้", - "somethingWentWrong":"**มีบางอย่างผิดพลาด**\nกรุณาลองอีกครั้งในภายหลัง" - }, - "commands":{ - "userAddedTitle":"เพิ่ม {0} ในห้องติดต่อนี้", - "userRemovedTitle":"ลบ {0} ออกจากห้องติดต่อนี้", - "renameTitle":"เปลี่ยนชื่อเป็น {0}", - "closeTitle":"ปิดห้องติดต่อนี้", - "deleteTitle":"กำลังลบห้องติดต่อนี้...", - "reopenTitle":"เปิดห้องติดต่อนี้อีกครั้ง", - - "claimTitle":"ห้องติดต่อนี้ถูกรับเรื่องโดย {0}", - "unclaimTitle":"ห้องติดต่อนี้ไม่ได้ถูกรับเรื่องอีกแล้ว", - "changeTitle":"เปลี่ยนประเภทห้องติดต่อเป็น {0}", - - "statsTitle":"นี่คือสถิติสำหรับ {0}", - "autocloseTitle":"ห้องติดต่อนี้จะถูกปิดอัตโนมัติหลังจาก {0}", - "autocloseRejectTitle":"ห้องติดต่อนี้จะไม่ถูกปิดอัตโนมัติอีกต่อไป", - "autocloseWarn":"ส่วนนี้มีผลกับห้องติดต่อที่ไม่ได้ใช้งาน", - - "goToTicket":"ไปที่ห้องติดต่อ", - "ticketWarning":"Embed อยู่ในข้อความด้านล่าง", - "maxTicketWarning":"**คำเตือน:** _คุณสามารถสร้างห้องติดต่อได้แค่ {0} ห้องติดต่อคน_" - }, - "helpMenu":{ - "title":"คำสั่งที่ใช้ได้:", - "header1":"**ไปที่ {0} เพื่อสร้างห้องติดต่อ**\n\n", - "header2":"**ใช้คำสั่ง `/new` หรือ `/ticket` เพื่อสร้างห้องติดต่อ**\n\n", - - "msgCmd":"สร้าง embed พร้อมปุ่ม (เฉพาะผู้ดูแลระบบ)", - "renameCmd":"เปลี่ยนชื่อห้องติดต่อ (ไม่มีช่องว่าง)", - "closeCmd":"ปิดห้องติดต่อ", - "deleteCmd":"ลบห้องติดต่อ", - "addCmd":"เพิ่มผู้ใช้ในห้องติดต่อ", - "removeCmd":"ลบผู้ใช้ออกจากห้องติดต่อ", - "reopenCmd":"เปิดห้องติดต่ออีกครั้งหลังจากถูกปิด", - "changeCmd":"เปลี่ยนประเภทห้องติดต่อ", - "claimCmd":"รับเรื่องห้องติดต่อ", - "unclaimCmd":"ยกเลิกการรับเรื่องห้องติดต่อ", - "statsCmd":"ดูสถิติห้องติดต่อ", - "autocloseCmd":"ตั้งค่าการปิดห้องติดต่ออัตโนมัติ" - }, - "buttons":{ - "close":"ปิดห้องติดต่อ", - "delete":"ลบห้องติดต่อ", - "reopen":"เปิดห้องติดต่ออีกครั้ง", - "closeWithReason":"ปิดด้วยเหตุผล" - }, - "messages":{ - "closedDescription":"เฉพาะผู้ดูแลระบบเท่านั้นที่สามารถพูดคุยในห้องติดต่อนี้ได้\n\n*คลิกที่ปุ่มด้านล่างเพื่อลบหรือเปิดห้องติดต่อนี้อีกครั้ง*", - "createdTitle":"สร้างห้องติดต่อแล้ว", - "createdDescription":"ห้องติดต่อของคุณถูกสร้างแล้ว คุณสามารถตรวจสอบได้จากการแจ้งเตือน", - - "newTicketDmTitle":"ห้องติดต่อใหม่", - "closedTicketDmTitle":"ปิดห้องติดต่อ", - "deletedTicketDmTitle":"ลบห้องติดต่อ", - "closedTicketDmDescription":"ห้องติดต่อของคุณถูกปิด", - "deletedTicketDmDescription":"ห้องติดต่อของคุณถูกลบ", - "reopenTicketDmTitle":"เปิดห้องติดต่ออีกครั้ง", - "reopenTicketDmDescription":"ห้องติดต่อของคุณถูกเปิดอีกครั้ง", - - "chooseCategory":"เลือกหมวดหมู่:", - "gettingdeleted":"กำลังลบห้องติดต่อ...", - - "none":"ไม่มี", - "reason":"เหตุผล", - "createdat":"สร้างเมื่อ", - "openedby":"เปิดโดย", - "deletedby":"ถูกลบโดย", - "closedby":"ถูกปิดโดย", - - "modalreason":"เหตุผลในการปิดห้องติดต่อนี้คืออะไร?", - "chooseATicket": "เลือกห้องติดต่อ" - }, - "transcripts":{ - "title":"บันทึกการสนทนา", - "processed":"บันทึกการสนทนากำลังดำเนินการ", - "wait":"กรุณารอ...", - "estimated":"เวลาโดยประมาณ", - "available":"บันทึกการสนทนาสามารถใช้งานได้ที่นี่" - }, - "stats":{ - "globalTitle":"สถิติทั้งหมด", - "ticketTitle":"สถิติห้องติดต่อสำหรับ {0}", - "userTitle":"สถิติผู้ใช้สำหรับ {0}", - "systemTitle":"สถานะระบบ", - "versionTitle":"เวอร์ชั่นของบอท", - - "ticketsCreated":"ห้องติดต่อที่สร้าง", - "ticketsClosed":"ห้องติดต่อที่ปิด", - "ticketsDeleted":"ห้องติดต่อที่ลบ:", - "ticketsReopened":"ห้องติดต่อที่เปิดใหม่", - "ticketsAutoclosed":"ห้องติดต่อที่ปิดโดยอัตโนมัติ", - "transcriptsCreated":"ทรานสคริปต์ที่สร้าง", - "startupDate":"วันที่เริ่มต้น", - "latestUpdate":"การอัปเดตล่าสุด", - "ticketCreatedOn":"ห้องติดต่อที่สร้างเมื่อ", - "ticketCreatedBy":"ห้องติดต่อที่สร้างโดย", - "messagesSent":"ข้อความที่ส่ง", - "status":"สถานะ", - "participants":"ผู้มีส่วนร่วม", - "role":"บทบาท", - - "switches":{ - "globalAdmin":"ผู้ดูแลทั้งหมด", - "ticketAdmin":"ผู้ดูแลห้องติดต่อ", - "member":"ผู้ใช้", - "open":"เปิด", - "reopened":"เปิดใหม่", - "closed":"ปิด", - "autoclosed":"ปิดโดยอัตโนมัติ" - }, - - "errorUserNotFound":"ไม่พบผู้ใช้ในฐานข้อมูลสถิติ" - } -} \ No newline at end of file diff --git a/language/traditionalchinese.json b/language/traditionalchinese.json deleted file mode 100644 index ae5f2f1..0000000 --- a/language/traditionalchinese.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"iamnotmega", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"缺少參數!", - "missingArgsDescription":"缺少參數", - "noPermsTitle":"沒有權限!", - "noPermsDescription":"您需要管理員權限或必須在允許的角色列表中!", - "noPermsDelete":"只有管理員可以刪除票據!", - "chooseFromListTitle":"無效的ID", - "chooseFromListDescription":"請選擇以下ID之一:", - "boterror":"機器人錯誤!", - "notInTicketTitle":"你不在票據中!", - "notInTicketDescription":"此命令不適用於票據外!", - "ticketDoesntExist":"此票據已不存在!", - "roleDoesntExist":"此角色已不存在!", - "anotherOption":"此選項不是票據,而是其他類型!", - "maxAmountTitle":"達到最大數量!", - "maxAmountDescription":"您已達到允許的最大票據數量!\n因此您不能創建新的票據!", - "somethingWentWrong":"**出了點問題!**\n請稍後再試!" - }, - "commands":{ - "userAddedTitle":"已將{0}添加到此票據中!", - "userRemovedTitle":"已將{0}從此票據中移除!", - "renameTitle":"已將名稱更改為{0}!", - "closeTitle":"此票據已關閉!", - "deleteTitle":"正在刪除此票據...", - "reopenTitle":"此票據已重新打開!", - - "claimTitle":"此票據已分配給{0}", - "unclaimTitle":"此票據不再被分配!", - "changeTitle":"票據類型更改為{0}!", - - "statsTitle":"以下是{0}的統計信息!", - "autocloseTitle":"此票據將在{0}後自動關閉!", - "autocloseRejectTitle":"此票據將不再自動關閉!", - "autocloseWarn":"這只影響不活躍的票據!", - - "goToTicket":"前往票據", - "ticketWarning":"嵌入信息在下方消息中!", - "maxTicketWarning":"**警告:** _您一次只能創建{0}個票據!_" - }, - "helpMenu":{ - "title":"可用命令:", - "header1":"**前往{0}以創建票據!**\n\n", - "header2":"**運行命令`/new`或`/ticket`以創建票據!**\n\n", - - "msgCmd":"生成帶有按鈕的嵌入消息。(僅限管理員)", - "renameCmd":"重命名票據。(無空格)", - "closeCmd":"關閉票據。", - "deleteCmd":"刪除票據。", - "addCmd":"將用戶添加到票據。", - "removeCmd":"將用戶從票據中移除。", - "reopenCmd":"關閉後重新打開票據。", - "changeCmd":"更改票據類型。", - "claimCmd":"分配票據。", - "unclaimCmd":"取消分配票據。", - "statsCmd":"查看票據統計信息。", - "autocloseCmd":"設置計時器以自動關閉票據" - }, - "buttons":{ - "close":"關閉票據", - "delete":"刪除票據", - "reopen":"重新打開票據", - "closeWithReason":"有理由地關閉" - }, - "messages":{ - "closedDescription":"現在只有管理員可以在此票據中講話!\n\n*點擊下方按鈕以刪除或重新打開此票據!*", - "createdTitle":"票據已創建!", - "createdDescription":"您的票據已創建,您可以通過提醒來檢測到它!", - - "newTicketDmTitle":"新票據!", - "closedTicketDmTitle":"票據已關閉!", - "deletedTicketDmTitle":"票據已刪除!", - "closedTicketDmDescription":"您的票據已關閉!", - "deletedTicketDmDescription":"您的票據已刪除!", - "reopenTicketDmTitle":"票據已重新打開!", - "reopenTicketDmDescription":"您的票據已重新打開!", - - "chooseCategory":"選擇一個類別:", - "gettingdeleted":"票據正在刪除...", - - "none":"無", - "reason":"原因", - "createdat":"創建於", - "openedby":"打開者", - "deletedby":"刪除者", - "closedby":"關閉者", - - "modalreason":"關閉此票據的原因是什麼?", - "chooseATicket":"選擇一個票據" - }, - "transcripts":{ - "title":"記錄", - "processed":"此記錄正在處理", - "wait":"請稍候!", - "estimated":"預計時間", - "available":"記錄在此處可用" - }, - "stats":{ - "globalTitle":"全局統計", - "ticketTitle":"{0}的票據統計", - "userTitle":"{0}的用戶統計", - "systemTitle":"系統統計", - "versionTitle":"機器人版本", - - "ticketsCreated":"創建的票據", - "ticketsClosed":"關閉的票據", - "ticketsDeleted":"刪除的票據", - "ticketsReopened":"重新打開的票據", - "ticketsAutoclosed":"自動關閉的票據", - "transcriptsCreated":"創建的記錄", - "startupDate":"啟動日期", - "latestUpdate":"最新更新", - "ticketCreatedOn":"票據創建於", - "ticketCreatedBy":"票據創建者", - "messagesSent":"發送的消息", - "status":"狀態", - "participants":"參與者", - "role":"角色", - - "switches":{ - "globalAdmin":"全局管理員", - "ticketAdmin":"票據管理員", - "member":"成員", - "open":"打開", - "reopened":"重新打開", - "closed":"關閉", - "autoclosed":"自動關閉" - }, - - "errorUserNotFound":"在統計數據庫中找不到該用戶!" - } -} diff --git a/language/turkish.json b/language/turkish.json deleted file mode 100644 index 77318af..0000000 --- a/language/turkish.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"0x15d3", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Geçersiz argümanlar!", - "missingArgsDescription":"Eksik argüman!", - "noPermsTitle":"Bunun için yetkin yok!", - "noPermsDescription":"Bunu yapmak için 'ADMINISTRATOR' rolüne ihtiyacınız var, veya izin verilen roller listesinde olun!", - "noPermsDelete":"Sadece adminler bileti silebilir!", - "chooseFromListTitle":"Geçersiz kimlik", - "chooseFromListDescription":"Aşağıdaki kimliklerden birini seçin:", - "boterror":"Bot hatası!", - "notInTicketTitle":"Bir biletin yok!", - "notInTicketDescription":"Bu komut bilet dışında kullanılamaz!", - "ticketDoesntExist":"Bu bilet artık yok!", - "roleDoesntExist":"Bu rol artık yok!", - "anotherOption":"Bu seçenek bir bilet değil, başka bir türdür!", - "maxAmountTitle":"Ulaşabileceğin maksimum tutara ulaştın!", - "maxAmountDescription":"İzin verilen maksimum bilet sayısına ulaştınız!\nHayır yeni bir tane oluşturamazsın!", - "somethingWentWrong":"**Bir şeyler ters gitti!**\n lütfen başka bir zaman tekrar deneyin!" - }, - "commands":{ - "userAddedTitle":"{0} adlı kullanıcı bilete eklendi!", - "userRemovedTitle":"{0} adlı kullanıcı biletten çıkarıldı !", - "renameTitle":"Bilet ismi {0} olarak değştirildi!", - "closeTitle":"Bilet kapatıldı!", - "deleteTitle":"Bilet siliniyor...", - "reopenTitle":"Bilet yeniden açıldı!", - - "claimTitle":"Bu bilet {0} tarafından talep edildi.", - "unclaimTitle":"Bu bilet artık talep edilmiyor!", - "changeTitle":"Bu biletin türü {0} olarak değiştirildi!", - - "statsTitle":"{0} için istatistikler!", - "autocloseTitle":"Bu bilet {0} sonra otomatik olarak kapatılacaktır!", - "autocloseRejectTitle":"Bu bilet artık otomatik olarak kapatılmayacaktır!", - "autocloseWarn":"Bu sadece aktif olmayan biletleri etkiler!", - - "goToTicket":"Bilete git", - "ticketWarning":"Gömme aşağıdaki mesajda yer almaktadır!", - "maxTicketWarning":"**Uyarı:** _Bir seferde yalnızca {0} bilet oluşturabilirsiniz!_" - }, - "helpMenu":{ - "title":"Kullanılabilir Komutlar:", - "header1":"**Bilet oluşturmak için {0} kanalını kullan!**\n\n", - "header2":"**Bilet oluşturmak için `/new` veya `/ticket' komutunu çalıştırın!**\n\n", - - "msgCmd":"Gömülü bilet mesajı gönderir. (sadece yöneticiler)", - "renameCmd":"Bilet adını değiştirir. (boşluk olmadan)", - "closeCmd":"Bileti kapatır", - "deleteCmd":"Bileti siler", - "addCmd":"Bilete kullanıcı ekler", - "removeCmd":"Biletten kullanıcı çıkarır", - "reopenCmd":"Bilet kapandıktan sonra tekrar açar", - "changeCmd":"Bilet türünü değiştir", - "claimCmd":"Bir bileti talep et", - "unclaimCmd":"Bir bileti talep etmeyi bırak", - "statsCmd":"Bilet istatistiklerini görüntüle", - "autocloseCmd":"Bileti otomatik olarak kapatacak zamanlayıcıyı ayarla" - }, - "buttons":{ - "close":"Bileti Kapat", - "delete":"Bileti Sil", - "reopen":"Bileti Yeniden Aç", - "closeWithReason":"Bu bileti neden kapatıyorsun?" - }, - "messages":{ - "closedDescription":"Bu bilette artık sadece yöneticiler konuşabilir!\n\n* Bu bileti silmek veya yeniden açmak için aşağıdaki butona tıklayın!*", - "createdTitle":"Talep Oluşturuldu!", - "createdDescription":"Biletiniz oluşturuldu, bir bildirimle tespit edebilirsiniz!", - - "newTicketDmTitle":"Yeni Bilet!", - "closedTicketDmTitle":"Bilet Kapatıldı!", - "deletedTicketDmTitle":"Bilet Silindi!", - "closedTicketDmDescription":"Senin biletin kapatıldı!", - "deletedTicketDmDescription":"Senin biletin silindi!", - "reopenTicketDmTitle":"Bilet yeniden açıldı!", - "reopenTicketDmDescription":"Senin biletin yeniden açıldı!", - - "chooseCategory":"Bir kategori seç:", - "gettingdeleted":"Bu bilet siliniyor...", - - "none":"yok", - "reason":"sebep", - "createdat":"oluşturulma tarihi", - "openedby":"açan kişi", - "deletedby":"Silen kişi", - "closedby":"Kapatan kişi", - - "modalreason":"Bu biletin kapanmasının sebebi nedir?", - "chooseATicket": "Bir bilet seçin" - }, - "transcripts":{ - "title":"Transkript", - "processed":"Bu transkript işleniyor", - "wait":"Lütfen Bekleyiniz!", - "estimated":"Tahmini Süre", - "available":"Transkript burada mevcuttur" - }, - "stats":{ - "globalTitle":"Sunucu İstatistikleri", - "ticketTitle":"{0} için Bilet İstatistikleri", - "userTitle":"{0} için Kullanıcı İstatistikleri", - "systemTitle":"Sistem İstatistikleri", - "versionTitle":"Bot Sürümü", - - "ticketsCreated": "Oluşturulan Biletler", - "ticketsClosed": "Kapatılan Biletler", - "ticketsDeleted": "Silinen Biletler", - "ticketsReopened": "Yeniden Açılan Biletler", - "ticketsAutoclosed": "Otomatik Kapatılan Biletler", - "transcriptsCreated": "Oluşturulan Transkriptler", - "startupDate": "Başlangıç Tarihi", - "latestUpdate": "Son Güncelleme", - "ticketCreatedOn": "Bilet Oluşturulma Tarihi", - "ticketCreatedBy": "Bileti Oluşturan", - "messagesSent": "Gönderilen Mesajlar", - "status": "Durum", - "participants": "Katılımcılar", - "role": "Rol", - - "switches": { - "globalAdmin": "Küresel Yönetici", - "ticketAdmin": "Bilet Yönetici", - "member": "Üye", - "open": "Açık", - "reopened": "Yeniden Açıldı", - "closed": "Kapalı", - "autoclosed": "Otomatik Kapalı" - }, - - "errorUserNotFound": "Bu kullanıcı istatistikler veritabanında bulunamıyor!" - } -} diff --git a/language/ukrainian.json b/language/ukrainian.json deleted file mode 100644 index 805813b..0000000 --- a/language/ukrainian.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"ander", - "_INFO":"Цей файл є перекладом для open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Невірні аргументи!", - "missingArgsDescription":"Відсутні аргументи!", - "noPermsTitle":"Відсутні права!", - "noPermsDescription":"Вам потрібно право `ADMINISTRATOR` або бути в списку дозволених ролей!", - "noPermsDelete":"Тільки адміни можуть видаляти тікети!", - "chooseFromListTitle":"Недійсний ID", - "chooseFromListDescription":"Виберіть один із наведених нижче id:", - "boterror":"Помилка боту!", - "notInTicketTitle":"Вас немає в тікеті!", - "notInTicketDescription":"Ця команда не працює поза тікетами!", - "ticketDoesntExist":"Цей тікет більше не існує!", - "roleDoesntExist":"Ця роль більше не існує!", - "anotherOption":"Це не є тікетом, а є іншим типом!", - "maxAmountTitle":"Досягнуто максимальної кількості!", - "maxAmountDescription":"Ви досягли максимально дозволеної кількості тікетів!\nТож ви не можете створити новий!", - "somethingWentWrong":"**Щось пішло не так!**\nБудь ласка, спробуйте ще раз!" - }, - "commands":{ - "userAddedTitle":"Додано {0} до цього тікету!", - "userRemovedTitle":"Видалено {0} з цього тікету!", - "renameTitle":"Змінено ім'я на {0}!", - "closeTitle":"Тікет закритий!", - "deleteTitle":"Видаляємо тікет", - "reopenTitle":"Знову відкриваємо тікет!", - - "claimTitle":"Цей тікет узяв {0}", - "unclaimTitle":"Цей тікет ніким не зайнятий!", - "changeTitle":"Тип тікету змінено на {0}!", - - "statsTitle":"Ось статистика для {0}!", - "autocloseTitle":"Цей тікет буде автоматично закрито після {0}!", - "autocloseRejectTitle":"Цей тікет більше не закриватиметься автоматично!", - "autocloseWarn":"Це стосується лише неактивних тікетів!", - - "goToTicket":"перейти до тікету", - "ticketWarning":"Ембед знаходиться в повідомленні нижче!", - "maxTicketWarning":"**Попередження:** _Ви можете створити лише стільки квитків за раз: {0}!_" - }, - "helpMenu":{ - "title":"Доступні команди:", - "header1":"**Перейдіть до {0}, щоб створити тікет!**\n\n", - "header2":"**Виконайте команду `/new` або `/ticket`, щоб створити тікет!**\n\n", - - "msgCmd":"Створити ембед з кнопками. (тільки адміністратори)", - "renameCmd":"Перейменувати тікет. (без пробілів)", - "closeCmd":"Закрити тікет.", - "deleteCmd":"Видалити тікет.", - "addCmd":"Додати користувача до тікету.", - "removeCmd":"Видалити користувача з тікету.", - "reopenCmd":"Повторне відкриття тікету після його закриття.", - "changeCmd":"Змінити тіп тикету.", - "claimCmd":"Узяти тікет.", - "unclaimCmd":"Відмовитися від тікету.", - "statsCmd":"Переглянути статистику тікету.", - "autocloseCmd":"Встановіть таймер для автоматичного закриття квитка" - }, - "buttons":{ - "close":"Закрити тікет", - "delete":"Видалити тікет", - "reopen":"Відкрити тікет", - "closeWithReason":"Закрити з причиною" - }, - "messages":{ - "closedDescription":"Зараз лише адміністратори можуть говорити в цьому тікеті!\n\n*Натисніть кнопку нижче, щоб видалити або повторно відкрити цей тікет!*", - "createdTitle":"Тікет створено!", - "createdDescription":"Ваш тікет створено, ви можете визначити його за допомогою пінгу!", - - "newTicketDmTitle":"Новий тікет!", - "closedTicketDmTitle":"Тікет закрито!", - "deletedTicketDmTitle":"Тікет видалено!", - "closedTicketDmDescription":"Твій тікет закрито!", - "deletedTicketDmDescription":"Твій тікет видалено!", - "reopenTicketDmTitle":"Тікет відкритий!", - "reopenTicketDmDescription":"Твій тікет відкритий!", - - "chooseCategory":"виберіть категорію:", - "gettingdeleted":"Тікет видаляється...", - - "none":"пусто", - "reason":"причина", - "createdat":"створений", - "openedby":"відкритий", - "deletedby":"видалений", - "closedby":"закритий", - - "modalreason":"Яка причина закриття цього тікету?", - "chooseATicket": "Виберіть тікет" - }, - "transcripts":{ - "title":"Транскрипція", - "processed":"Ця транскрипція обробляється", - "wait":"Будь-ласка почекайте!", - "estimated":"Розрахунковий час", - "available":"Транскрипція доступна тут" - }, - "stats":{ - "globalTitle":"Загальна статистика", - "ticketTitle":"Статистика тікету для {0}", - "userTitle":"Статистика корстувача для {0}", - "systemTitle":"Системна статистика", - "versionTitle":"Версія бота", - - "ticketsCreated":"Тікет створен", - "ticketsClosed":"Тікет закрито", - "ticketsDeleted":"Тікет видалено", - "ticketsReopened":"Тікет перевідкритий", - "ticketsAutoclosed":"Тікет автоматично закритий", - "transcriptsCreated":"Транскрипт створено", - "startupDate":"Дата запуску", - "latestUpdate":"Останнє оновлення", - "ticketCreatedOn":"Тікет створено", - "ticketCreatedBy":"Тікет створено", - "messagesSent":"Повідомлення відправлено", - "status":"Стан", - "participants":"Учасники", - "role":"Роль", - - "switches":{ - "globalAdmin":"Головна", - "ticketAdmin":"Тікет", - "member":"Учасник", - "open":"Відкрити", - "reopened":"Перевідкритий", - "closed":"Закритий", - "autoclosed":"Автоматично закритий" - }, - - "errorUserNotFound":"Учасник не знайдений у базі даних статистики!" - } -} \ No newline at end of file diff --git a/language/vietnamese.json b/language/vietnamese.json deleted file mode 100644 index 610d6c5..0000000 --- a/language/vietnamese.json +++ /dev/null @@ -1,135 +0,0 @@ -{ - "_CREDITS":"iamnotmega", - "_INFO":"This file is a translation for open ticket 3.5.8", - - "errors":{ - "missingArgsTitle":"Đối số không hợp lệ!", - "missingArgsDescription":"Thiếu đối số", - "noPermsTitle":"Không có quyền!", - "noPermsDescription":"Bạn cần quyền `ADMINISTRATOR` hoặc nằm trong danh sách vai trò được cho phép!", - "noPermsDelete":"Chỉ có quản trị viên mới có thể xóa một phiếu hỗ trợ!", - "chooseFromListTitle":"ID không hợp lệ", - "chooseFromListDescription":"Chọn một trong các ID dưới đây:", - "boterror":"Lỗi Bot!", - "notInTicketTitle":"Bạn không ở trong một phiếu hỗ trợ!", - "notInTicketDescription":"Lệnh này không hoạt động ngoài các phiếu hỗ trợ!", - "ticketDoesntExist":"Phiếu hỗ trợ này không còn tồn tại nữa!", - "roleDoesntExist":"Vai trò này không còn tồn tại nữa!", - "anotherOption":"Lựa chọn này không phải là một phiếu hỗ trợ mà là một loại khác!", - "maxAmountTitle":"Đã đạt tối đa!", - "maxAmountDescription":"Bạn đã đạt số lượng phiếu hỗ trợ tối đa cho phép!\nBạn không thể tạo mới!", - "somethingWentWrong":"**Đã xảy ra lỗi!**\nVui lòng thử lại sau!" - }, - "commands":{ - "userAddedTitle":"Đã thêm {0} vào phiếu hỗ trợ này!", - "userRemovedTitle":"Đã xóa {0} khỏi phiếu hỗ trợ này!", - "renameTitle":"Đổi tên thành {0}!", - "closeTitle":"Đóng phiếu hỗ trợ này!", - "deleteTitle":"Đang xóa phiếu hỗ trợ này...", - "reopenTitle":"Mở lại phiếu hỗ trợ này!", - - "claimTitle":"Phiếu hỗ trợ này đã được chuyển cho {0}", - "unclaimTitle":"Phiếu hỗ trợ này không còn được chuyển nhượng!", - "changeTitle":"Đổi loại phiếu thành {0}!", - - "statsTitle":"Đây là thống kê cho {0}!", - "autocloseTitle":"Phiếu hỗ trợ này sẽ tự động đóng sau {0}!", - "autocloseRejectTitle":"Phiếu hỗ trợ này sẽ không tự động đóng nữa!", - "autocloseWarn":"Chỉ ảnh hưởng đến các phiếu hỗ trợ không hoạt động!", - - "goToTicket":"đi đến phiếu hỗ trợ", - "ticketWarning":"Thông báo nhúng ở dưới!", - "maxTicketWarning":"**Cảnh báo:** _Bạn chỉ có thể tạo {0} phiếu hỗ trợ một lúc!_" - }, - "helpMenu":{ - "title":"Các lệnh có sẵn:", - "header1":"**Đi tới {0} để tạo phiếu hỗ trợ!**\n\n", - "header2":"**Chạy lệnh `/new` hoặc `/ticket` để tạo phiếu hỗ trợ!**\n\n", - - "msgCmd":"Tạo nhúng với các nút. (chỉ dành cho quản trị viên)", - "renameCmd":"Đổi tên phiếu hỗ trợ. (không có khoảng trống)", - "closeCmd":"Đóng phiếu hỗ trợ.", - "deleteCmd":"Xóa phiếu hỗ trợ.", - "addCmd":"Thêm người dùng vào phiếu hỗ trợ.", - "removeCmd":"Xóa người dùng khỏi phiếu hỗ trợ.", - "reopenCmd":"Mở lại phiếu hỗ trợ sau khi đã đóng.", - "changeCmd":"Thay đổi loại phiếu.", - "claimCmd":"Chuyển nhượng phiếu hỗ trợ.", - "unclaimCmd":"Hủy chuyển nhượng phiếu hỗ trợ.", - "statsCmd":"Xem thống kê phiếu hỗ trợ.", - "autocloseCmd":"Đặt bộ hẹn để tự động đóng phiếu hỗ trợ" - }, - "buttons":{ - "close":"Đóng phiếu hỗ trợ", - "delete":"Xóa phiếu hỗ trợ", - "reopen":"Mở lại phiếu hỗ trợ", - "closeWithReason":"đóng với lý do" - }, - "messages":{ - "closedDescription":"Chỉ có quản trị viên mới có thể nói chuyện trong phiếu hỗ trợ này ngay bây giờ!\n\n*Nhấp vào nút bên dưới để xóa hoặc mở lại phiếu hỗ trợ này!*", - "createdTitle":"Phiếu hỗ trợ đã được tạo!", - "createdDescription":"Phiếu hỗ trợ của bạn đã được tạo, bạn có thể nhận ra nó bằng cách ping!", - - "newTicketDmTitle":"Phiếu hỗ trợ mới!", - "closedTicketDmTitle":"Phiếu hỗ trợ đã được đóng!", - "deletedTicketDmTitle":"Phiếu hỗ trợ đã được xóa!", - "closedTicketDmDescription":"Phiếu hỗ trợ của bạn đã bị đóng!", - "deletedTicketDmDescription":"Phiếu hỗ trợ của bạn đã bị xóa!", - "reopenTicketDmTitle":"Phiếu hỗ trợ đã được mở lại!", - "reopenTicketDmDescription":"Phiếu hỗ trợ của bạn đã được mở lại!", - - "chooseCategory":"chọn một danh mục:", - "gettingdeleted":"Phiếu hỗ trợ đang bị xóa...", - - "none":"không", - "reason":"lý do", - "createdat":"được tạo lúc", - "openedby":"mở bởi", - "deletedby":"xóa bởi", - "closedby":"đóng bởi", - - "modalreason":"Lý do đóng phiếu hỗ trợ này là gì?", - "chooseATicket": "Chọn một phiếu hỗ trợ" - }, - "transcripts":{ - "title":"Biên bản", - "processed":"Biên bản này đang được xử lý", - "wait":"Vui lòng đợi!", - "estimated":"Thời gian ước tính", - "available":"Biên bản này có sẵn tại đây" - }, - "stats":{ - "globalTitle":"Thống kê toàn cầu", - "ticketTitle":"Thống kê phiếu hỗ trợ cho {0}", - "userTitle":"Thống kê người dùng cho {0}", - "systemTitle":"Thống kê hệ thống", - "versionTitle":"Phiên bản Bot", - - "ticketsCreated":"Phiếu hỗ trợ đã được tạo", - "ticketsClosed":"Phiếu hỗ trợ đã được đóng", - "ticketsDeleted":"Phiếu hỗ trợ đã được xóa", - "ticketsReopened":"Phiếu hỗ trợ đã được mở lại", - "ticketsAutoclosed":"Phiếu hỗ trợ đã tự động đóng", - "transcriptsCreated":"Biên bản đã được tạo", - "startupDate":"Ngày khởi động", - "latestUpdate":"Cập nhật mới nhất", - "ticketCreatedOn":"Phiếu hỗ trợ đã được tạo vào", - "ticketCreatedBy":"Phiếu hỗ trợ đã được tạo bởi", - "messagesSent":"Tin nhắn đã được gửi", - "status":"Trạng thái", - "participants":"Người tham gia", - "role":"Vai trò", - - "switches":{ - "globalAdmin":"Quản trị viên toàn cầu", - "ticketAdmin":"Quản trị viên phiếu hỗ trợ", - "member":"Thành viên", - "open":"Mở", - "reopened":"Đã mở lại", - "closed":"Đã đóng", - "autoclosed":"Đã tự động đóng" - }, - - "errorUserNotFound":"Người dùng này không thể được tìm thấy trong cơ sở dữ liệu thống kê!" - } -} diff --git a/package.json b/package.json index 9653f3c..df895fc 100644 --- a/package.json +++ b/package.json @@ -1,28 +1,33 @@ { - "name": "open-ticket", - "author": "DJdj Development", - "version": "3.5.8", - "description": "The most advanced open-source discord ticket bot with HTML transcripts and plugins! It uses discord.js v14 & no database required!", - "main": "index.js", - "scripts": { - "start": "node index.js", - "test": "node index.js --devconfig --noerrorupload", - "slashEnable": "node index.js slash enable", - "slashDisable": "node index.js slash disable" - }, - "license": "ISC", - "dependencies": { - "axios": "^1.6.2", - "chalk": "^5.0.1", - "discord.js": "^14.15.3" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/DJj123dj/open-ticket.git" - }, - "bugs": { - "url": "https://github.com/DJj123dj/open-ticket/issues", - "email": "support@dj-dj.be" - }, - "homepage": "https://openticket.dj-dj.be" -} + "name": "open-ticket", + "author": "DJdj Development", + "version": "4.0.0", + "description": "The most advanced open-source discord ticket bot with HTML transcripts, plugins, questions, claiming, pinning & more! Using discord.js v14 & JSON database! ", + "keywords": ["ticket-bot","discord","open-ticket","plugins","discord-ticket-bot"], + "main": "./src/index.ts", + "scripts": { + "verify": "tsc -p ./tsconfig.json", + "start": "npx tsx ./src/index.ts", + "test": "npm run verify && npx tsx ./src/index.ts --dev-config --dev-database" + }, + "type": "commonjs", + "license": "GPL-3.0-only", + "dependencies": { + "ansis": "^2.3.0", + "discord.js": "^14.15.3", + "formatted-json-stringify": "^1.1.0", + "tsx": "^4.17.0" + }, + "devDependencies": { + "typescript": "^5.3.3" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/DJj123dj/open-ticket.git" + }, + "bugs": { + "url": "https://github.com/DJj123dj/open-ticket/issues", + "email": "support@dj-dj.be" + }, + "homepage": "https://openticket.dj-dj.be" +} \ No newline at end of file diff --git a/plugins/example.plugin.js b/plugins/example.plugin.js deleted file mode 100644 index a877c6c..0000000 --- a/plugins/example.plugin.js +++ /dev/null @@ -1,19 +0,0 @@ -const discord = require("discord.js") -const api = require("../core/api/api.js") - -module.exports = () => { - const {client,config,events,utils,actions} = api - - //this code will run when the bot starts! - - //in this example, we will say "hello" in the console when someone opens a ticket! - - /** - - events.onTicketOpen((user,channel,guild,date,ticketdata) => { - console.log("hello, someone opened a ticket!") - }) - - - */ -} \ No newline at end of file diff --git a/storage/hello.txt b/storage/hello.txt deleted file mode 100644 index 11385e2..0000000 --- a/storage/hello.txt +++ /dev/null @@ -1,3 +0,0 @@ -This file is only here to make sure that this directory exists! - -I don't have any other use :) \ No newline at end of file diff --git a/transcriptconfig.json b/transcriptconfig.json deleted file mode 100644 index b137a91..0000000 --- a/transcriptconfig.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "sendTranscripts":{ - "enableChannel":false, - "enableDM":false, - - "channel":"transcript channel id", - "useHTMLtranscripts":true - }, - "style":{ - "background":{ - "enableCustomBackground":false, - "backgroundModus":"image OR color", - "backgroundData":"image url OR hex color (#ffffff)" - - }, - "header":{ - "enableCustomHeader":false, - "backgroundColor":"#202225", - "decoColor":"#F8BA00", - "textColor":"#ffffff" - - }, - "stats":{ - "enableCustomStats":false, - "backgroundColor":"#202225", - "keyTextColor":"#737373", - "valueTextColor":"#ffffff", - "hideBackgroundColor":"#40444a", - "hideTextColor":"#ffffff" - }, - "favicon":{ - "enableCustomFavicon":false, - "imageUrl":"https://transcripts.dj-dj.be/favicon.png" - } - } -} \ No newline at end of file From 0c2aca703953263e570ca6d1b248704034ac38d2 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:24:56 +0200 Subject: [PATCH 002/157] Open Ticket v4 Beta --- .github/CODE_OF_CONDUCT.md | 128 ++ .github/CONTENT_CREATORS.md | 41 + .github/CONTRIBUTING.md | 69 ++ .github/FUNDING.yml | 1 + .github/ISSUE_TEMPLATE/bug_report.md | 32 + .github/SECURITY.md | 49 + .gitignore | 13 + LICENSE | 674 +++++++++++ README.md | 142 +++ config/general.json | 95 ++ config/options.json | 122 ++ config/panels.json | 39 + config/questions.json | 28 + config/transcripts.json | 57 + database/global.json | 7 + database/options.json | 1 + database/stats.json | 1 + database/tickets.json | 1 + database/users.json | 1 + languages/custom.json | 477 ++++++++ languages/czech.json | 477 ++++++++ languages/dutch.json | 477 ++++++++ languages/english.json | 477 ++++++++ languages/portuguese.json | 477 ++++++++ plugins/example-plugin/config.json | 5 + plugins/example-plugin/index.ts | 44 + plugins/example-plugin/plugin.json | 23 + src/actions/addTicketUser.ts | 87 ++ src/actions/claimTicket.ts | 276 +++++ src/actions/clearTickets.ts | 45 + src/actions/closeTicket.ts | 328 +++++ src/actions/createTicket.ts | 229 ++++ src/actions/createTicketPermissions.ts | 106 ++ src/actions/createTranscript.ts | 164 +++ src/actions/deleteTicket.ts | 463 +++++++ src/actions/handleTranscriptErrors.ts | 164 +++ src/actions/handleVerifyBar.ts | 32 + src/actions/moveTicket.ts | 220 ++++ src/actions/pinTicket.ts | 274 +++++ src/actions/reactionRole.ts | 94 ++ src/actions/removeTicketUser.ts | 81 ++ src/actions/renameTicket.ts | 78 ++ src/actions/reopenTicket.ts | 448 +++++++ src/actions/unclaimTicket.ts | 305 +++++ src/actions/unpinTicket.ts | 267 ++++ src/builders/buttons.ts | 351 ++++++ src/builders/dropdowns.ts | 37 + src/builders/embeds.ts | 1272 ++++++++++++++++++++ src/builders/files.ts | 45 + src/builders/messages.ts | 1055 ++++++++++++++++ src/builders/modals.ts | 173 +++ src/commands/add.ts | 87 ++ src/commands/autoclose.ts | 98 ++ src/commands/autodelete.ts | 93 ++ src/commands/blacklist.ts | 127 ++ src/commands/claim.ts | 138 +++ src/commands/clear.ts | 122 ++ src/commands/close.ts | 137 +++ src/commands/delete.ts | 149 +++ src/commands/help.ts | 112 ++ src/commands/move.ts | 92 ++ src/commands/panel.ts | 82 ++ src/commands/pin.ts | 137 +++ src/commands/remove.ts | 87 ++ src/commands/rename.ts | 80 ++ src/commands/reopen.ts | 142 +++ src/commands/role.ts | 41 + src/commands/stats.ts | 107 ++ src/commands/ticket.ts | 269 +++++ src/commands/unclaim.ts | 136 +++ src/commands/unpin.ts | 136 +++ src/core/api/api.ts | 60 + src/core/api/defaults/action.ts | 154 +++ src/core/api/defaults/base.ts | 45 + src/core/api/defaults/builder.ts | 532 ++++++++ src/core/api/defaults/checker.ts | 378 ++++++ src/core/api/defaults/client.ts | 147 +++ src/core/api/defaults/code.ts | 56 + src/core/api/defaults/config.ts | 470 ++++++++ src/core/api/defaults/console.ts | 42 + src/core/api/defaults/cooldown.ts | 42 + src/core/api/defaults/database.ts | 256 ++++ src/core/api/defaults/event.ts | 331 +++++ src/core/api/defaults/flag.ts | 53 + src/core/api/defaults/helpmenu.ts | 323 +++++ src/core/api/defaults/language.ts | 510 ++++++++ src/core/api/defaults/permission.ts | 30 + src/core/api/defaults/post.ts | 44 + src/core/api/defaults/responder.ts | 255 ++++ src/core/api/defaults/session.ts | 42 + src/core/api/defaults/startscreen.ts | 48 + src/core/api/defaults/stat.ts | 363 ++++++ src/core/api/defaults/verifybar.ts | 72 ++ src/core/api/defaults/worker.ts | 35 + src/core/api/main.ts | 180 +++ src/core/api/modules/action.ts | 58 + src/core/api/modules/base.ts | 749 ++++++++++++ src/core/api/modules/builder.ts | 1245 +++++++++++++++++++ src/core/api/modules/checker.ts | 1465 ++++++++++++++++++++++ src/core/api/modules/client.ts | 1470 +++++++++++++++++++++++ src/core/api/modules/code.ts | 55 + src/core/api/modules/config.ts | 96 ++ src/core/api/modules/console.ts | 663 ++++++++++ src/core/api/modules/cooldown.ts | 348 ++++++ src/core/api/modules/database.ts | 316 +++++ src/core/api/modules/defaults.ts | 319 +++++ src/core/api/modules/event.ts | 99 ++ src/core/api/modules/flag.ts | 73 ++ src/core/api/modules/helpmenu.ts | 216 ++++ src/core/api/modules/language.ts | 107 ++ src/core/api/modules/permission.ts | 211 ++++ src/core/api/modules/plugin.ts | 233 ++++ src/core/api/modules/post.ts | 90 ++ src/core/api/modules/responder.ts | 884 ++++++++++++++ src/core/api/modules/session.ts | 155 +++ src/core/api/modules/startscreen.ts | 219 ++++ src/core/api/modules/stat.ts | 212 ++++ src/core/api/modules/verifybar.ts | 43 + src/core/api/modules/worker.ts | 93 ++ src/core/api/openticket/blacklist.ts | 28 + src/core/api/openticket/option.ts | 421 +++++++ src/core/api/openticket/panel.ts | 128 ++ src/core/api/openticket/question.ts | 180 +++ src/core/api/openticket/role.ts | 122 ++ src/core/api/openticket/ticket.ts | 251 ++++ src/core/api/openticket/transcript.ts | 802 +++++++++++++ src/core/startup/init.ts | 205 ++++ src/core/startup/manageMigration.ts | 84 ++ src/core/startup/migration.ts | 8 + src/core/startup/pluginLauncher.ts | 197 +++ src/data/framework/checkerLoader.ts | 591 +++++++++ src/data/framework/codeLoader.ts | 481 ++++++++ src/data/framework/commandLoader.ts | 1076 +++++++++++++++++ src/data/framework/configLoader.ts | 12 + src/data/framework/cooldownLoader.ts | 17 + src/data/framework/databaseLoader.ts | 53 + src/data/framework/eventLoader.ts | 236 ++++ src/data/framework/flagLoader.ts | 16 + src/data/framework/helpMenuLoader.ts | 263 ++++ src/data/framework/languageLoader.ts | 15 + src/data/framework/liveStatusLoader.ts | 6 + src/data/framework/permissionLoader.ts | 82 ++ src/data/framework/postLoader.ts | 14 + src/data/framework/startScreenLoader.ts | 54 + src/data/framework/statLoader.ts | 133 ++ src/data/openticket/blacklistLoader.ts | 12 + src/data/openticket/optionLoader.ts | 107 ++ src/data/openticket/panelLoader.ts | 165 +++ src/data/openticket/questionLoader.ts | 38 + src/data/openticket/roleLoader.ts | 18 + src/data/openticket/ticketLoader.ts | 35 + src/data/openticket/transcriptLoader.ts | 456 +++++++ src/index.ts | 742 ++++++++++++ tsconfig.json | 22 + 154 files changed, 33881 insertions(+) create mode 100644 .github/CODE_OF_CONDUCT.md create mode 100644 .github/CONTENT_CREATORS.md create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/SECURITY.md create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 config/general.json create mode 100644 config/options.json create mode 100644 config/panels.json create mode 100644 config/questions.json create mode 100644 config/transcripts.json create mode 100644 database/global.json create mode 100644 database/options.json create mode 100644 database/stats.json create mode 100644 database/tickets.json create mode 100644 database/users.json create mode 100644 languages/custom.json create mode 100644 languages/czech.json create mode 100644 languages/dutch.json create mode 100644 languages/english.json create mode 100644 languages/portuguese.json create mode 100644 plugins/example-plugin/config.json create mode 100644 plugins/example-plugin/index.ts create mode 100644 plugins/example-plugin/plugin.json create mode 100644 src/actions/addTicketUser.ts create mode 100644 src/actions/claimTicket.ts create mode 100644 src/actions/clearTickets.ts create mode 100644 src/actions/closeTicket.ts create mode 100644 src/actions/createTicket.ts create mode 100644 src/actions/createTicketPermissions.ts create mode 100644 src/actions/createTranscript.ts create mode 100644 src/actions/deleteTicket.ts create mode 100644 src/actions/handleTranscriptErrors.ts create mode 100644 src/actions/handleVerifyBar.ts create mode 100644 src/actions/moveTicket.ts create mode 100644 src/actions/pinTicket.ts create mode 100644 src/actions/reactionRole.ts create mode 100644 src/actions/removeTicketUser.ts create mode 100644 src/actions/renameTicket.ts create mode 100644 src/actions/reopenTicket.ts create mode 100644 src/actions/unclaimTicket.ts create mode 100644 src/actions/unpinTicket.ts create mode 100644 src/builders/buttons.ts create mode 100644 src/builders/dropdowns.ts create mode 100644 src/builders/embeds.ts create mode 100644 src/builders/files.ts create mode 100644 src/builders/messages.ts create mode 100644 src/builders/modals.ts create mode 100644 src/commands/add.ts create mode 100644 src/commands/autoclose.ts create mode 100644 src/commands/autodelete.ts create mode 100644 src/commands/blacklist.ts create mode 100644 src/commands/claim.ts create mode 100644 src/commands/clear.ts create mode 100644 src/commands/close.ts create mode 100644 src/commands/delete.ts create mode 100644 src/commands/help.ts create mode 100644 src/commands/move.ts create mode 100644 src/commands/panel.ts create mode 100644 src/commands/pin.ts create mode 100644 src/commands/remove.ts create mode 100644 src/commands/rename.ts create mode 100644 src/commands/reopen.ts create mode 100644 src/commands/role.ts create mode 100644 src/commands/stats.ts create mode 100644 src/commands/ticket.ts create mode 100644 src/commands/unclaim.ts create mode 100644 src/commands/unpin.ts create mode 100644 src/core/api/api.ts create mode 100644 src/core/api/defaults/action.ts create mode 100644 src/core/api/defaults/base.ts create mode 100644 src/core/api/defaults/builder.ts create mode 100644 src/core/api/defaults/checker.ts create mode 100644 src/core/api/defaults/client.ts create mode 100644 src/core/api/defaults/code.ts create mode 100644 src/core/api/defaults/config.ts create mode 100644 src/core/api/defaults/console.ts create mode 100644 src/core/api/defaults/cooldown.ts create mode 100644 src/core/api/defaults/database.ts create mode 100644 src/core/api/defaults/event.ts create mode 100644 src/core/api/defaults/flag.ts create mode 100644 src/core/api/defaults/helpmenu.ts create mode 100644 src/core/api/defaults/language.ts create mode 100644 src/core/api/defaults/permission.ts create mode 100644 src/core/api/defaults/post.ts create mode 100644 src/core/api/defaults/responder.ts create mode 100644 src/core/api/defaults/session.ts create mode 100644 src/core/api/defaults/startscreen.ts create mode 100644 src/core/api/defaults/stat.ts create mode 100644 src/core/api/defaults/verifybar.ts create mode 100644 src/core/api/defaults/worker.ts create mode 100644 src/core/api/main.ts create mode 100644 src/core/api/modules/action.ts create mode 100644 src/core/api/modules/base.ts create mode 100644 src/core/api/modules/builder.ts create mode 100644 src/core/api/modules/checker.ts create mode 100644 src/core/api/modules/client.ts create mode 100644 src/core/api/modules/code.ts create mode 100644 src/core/api/modules/config.ts create mode 100644 src/core/api/modules/console.ts create mode 100644 src/core/api/modules/cooldown.ts create mode 100644 src/core/api/modules/database.ts create mode 100644 src/core/api/modules/defaults.ts create mode 100644 src/core/api/modules/event.ts create mode 100644 src/core/api/modules/flag.ts create mode 100644 src/core/api/modules/helpmenu.ts create mode 100644 src/core/api/modules/language.ts create mode 100644 src/core/api/modules/permission.ts create mode 100644 src/core/api/modules/plugin.ts create mode 100644 src/core/api/modules/post.ts create mode 100644 src/core/api/modules/responder.ts create mode 100644 src/core/api/modules/session.ts create mode 100644 src/core/api/modules/startscreen.ts create mode 100644 src/core/api/modules/stat.ts create mode 100644 src/core/api/modules/verifybar.ts create mode 100644 src/core/api/modules/worker.ts create mode 100644 src/core/api/openticket/blacklist.ts create mode 100644 src/core/api/openticket/option.ts create mode 100644 src/core/api/openticket/panel.ts create mode 100644 src/core/api/openticket/question.ts create mode 100644 src/core/api/openticket/role.ts create mode 100644 src/core/api/openticket/ticket.ts create mode 100644 src/core/api/openticket/transcript.ts create mode 100644 src/core/startup/init.ts create mode 100644 src/core/startup/manageMigration.ts create mode 100644 src/core/startup/migration.ts create mode 100644 src/core/startup/pluginLauncher.ts create mode 100644 src/data/framework/checkerLoader.ts create mode 100644 src/data/framework/codeLoader.ts create mode 100644 src/data/framework/commandLoader.ts create mode 100644 src/data/framework/configLoader.ts create mode 100644 src/data/framework/cooldownLoader.ts create mode 100644 src/data/framework/databaseLoader.ts create mode 100644 src/data/framework/eventLoader.ts create mode 100644 src/data/framework/flagLoader.ts create mode 100644 src/data/framework/helpMenuLoader.ts create mode 100644 src/data/framework/languageLoader.ts create mode 100644 src/data/framework/liveStatusLoader.ts create mode 100644 src/data/framework/permissionLoader.ts create mode 100644 src/data/framework/postLoader.ts create mode 100644 src/data/framework/startScreenLoader.ts create mode 100644 src/data/framework/statLoader.ts create mode 100644 src/data/openticket/blacklistLoader.ts create mode 100644 src/data/openticket/optionLoader.ts create mode 100644 src/data/openticket/panelLoader.ts create mode 100644 src/data/openticket/questionLoader.ts create mode 100644 src/data/openticket/roleLoader.ts create mode 100644 src/data/openticket/ticketLoader.ts create mode 100644 src/data/openticket/transcriptLoader.ts create mode 100644 src/index.ts create mode 100644 tsconfig.json diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..b6c95d8 --- /dev/null +++ b/.github/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +support@dj-dj.be. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/.github/CONTENT_CREATORS.md b/.github/CONTENT_CREATORS.md new file mode 100644 index 0000000..f72f41f --- /dev/null +++ b/.github/CONTENT_CREATORS.md @@ -0,0 +1,41 @@ +# 🎥 Content Creators +Hi there! We're searching for content creators to create tutorials & setup guides for Open Ticket. +You can get many great rewards from helpin us! + +You can choose which type of tutorial you want to make. You can create a quick setup, full setup, plugin tutorial or something else! +You are not required to talk in the video, but make sure it has some kind of subtitles instead. + +### 📄 Requirements +- 📌 At least 2k subscribers! +- 📌 A little bit of channel activity! *(minimum 2 uploads/month)* +- 📌 Video length of at least 3 minutes! +- 📌 Provide a clear link to the Open Ticket repository! +- 📌 Recommended language is English! +- 📌 Recommended platform is YouTube! +- 📌 Must be for the latest version of Open Ticket! +- 📌 **(OPTIONAL)** Speech in the video *(AI is allowed)* + + +### 🎁 Rewards +We won't give out any compensation in money, but we will give you some advantages! +- ✅ Advertisement of tutorial in the [README.md](../README.md)! +- ✅ Advertisement of channel in our [discord server](https://discord.dj-dj.be)! +- ✅ `Content Creator` role in our [discord server](https://discord.dj-dj.be)! +- ✅ Advertisement of tutorial & channel in documentation! +- ✅ Lot's of of views generated from GitHub traffic! +- ✅ A completely free 24/7 hosted Open Ticket bot! +- ✅ We will advertise the video to all our socials! + +### 💤 Outdated Content +When a tutorial or setup guide is outdated or no longer applicable, +we will remove it from the `README.md` & documentation. +Your channel will still stay in the list of contributors, so don't worry about that! + +You will be noticed at least a month before removal. +This way you can take time to create an updated tutorial if you want. + +### 💬 Contact Us +If you've read all these guidelines, requirements & rewards, +you can create a ticket in our [discord server](https://discord.dj-dj.be) to start working on it! + +We will try to help you as fast as possible! \ No newline at end of file diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 0000000..86a645a --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,69 @@ +# Contributing Guidelines +Open Ticket Logo + +[![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.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v4.0.0) + +These are the Contributing Guidelines of Open Ticket!
+Here you can find everything you need to know about contributing to Open Ticket.
+This includes new features, translations & bug fixes. + +### 💬 Translations +#### Step 1: View & Check +1. Check the [`./languages/`](./languages/) folder for existing translations. +2. When it doesn't exist yet, visit **[step 2](#step-2-translation)**. +3. When it does exist, check if it is outdated, incorrect or incomplete. +4. If you match one of these requirements, you can also visit **[step 2](#step-2-translating)**. + +#### Step 2: Translation +1. If your language doesn't exist yet, copy the [`english.json`](./../languages/english.json) file and rename it to your language. +2. You are allowed to use a little bit of `Google Translate` or `DeepL` when mentioned in the upload. (❌ Not Recommended) +3. Only translate existing values in the json file. Don't add or remove any values from the file. +4. If you are unable to translate something, leave it in `English`. + +#### Step 3: Metadata +Metadata can be found in the `_TRANSLATION` variable. +|Value |Notes | +|-------------|-------------------------------------------------------------------------------------------------| +|`otversion` |The Open Ticket version of this translation. Don't edit this! | +|`translator` |The translator discord username. When improving existing translation, add your name to the list. | +|`lastedited` |The last edited date in the `DD/MM/YYYY` format. | +|`language` |The full name of the language with capital letter. | + +> #### ✅ You are also allowed to add your username to the [`README.md`](./../README.md) translator list! + +#### Step 4: Uploading +1. When adding a new language, please mention @DJj123dj. He will add the code required for the language to work. +2. There are currently 3 ways of uploading translations: + - Create a pull request to the [__`dev` branch!__](https://github.com/DJj123dj/open-ticket/tree/dev) + - Create a ticket in our [discord server](https://discord.dj-dj.be)! + - Send a DM to @DJj123dj on discord! +3. Now you'll need to wait until the next Open Ticket version for it to be added. + +#### Step 5: Rewards +Translators get some rewards for translating Open Ticket! +- ✅ Credits in the [`README.md`](./../README.md) translator list! +- ✅ Credits in the changelog! +- ✅ Credits in the documentation! +- ✅ Credits in the translation JSON file! +- ✅ A special role in our [discord server](https://discord.dj-dj.be)! + +### 🧩 Plugins (temporary) +Currently plugins can only be added to the list via our [discord server](https://discord.dj-dj.be)! + +### 📦 Features (temporary) +Currently features can only be suggested in our [discord server](https://discord.dj-dj.be)! + +### 🕷️ Bug Fixes (temporary) +Currently bug fixes can only be reported in the following ways: +- Create an issue in the repository! +- Create a ticket in our [discord server](https://discord.dj-dj.be)! + +#### Please try to always include the `otdebug.txt` file! + +--- +Open Ticket Logo + +**Contributing Guidelines**
+[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)
+ +© 2024 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..1032364 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: DJj123dj diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..311eb2f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,32 @@ +--- +name: Bug Report +about: Report bugs to help us improve Open Ticket! +title: "[BUG] Your Bug" +labels: bug +assignees: DJj123dj +--- + +### Bug Description: +A clear and concise description of what the bug is. + +### Steps To Reproduce: +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +> Leave empty when you are unable to reproduce the bug! + +### Expected Behaviour: +A clear and concise description of what you expected to happen. + +### Screenshots: +If applicable, add screenshots to help explain your problem. + +### Files: +Please include the `otdebug.txt` file in your report! With this file, we can take a deep-dive in to the error that happend. +> This file doesn't contain any credentials or sensitive information! + +### Additional Notes: +Add any other context about the problem here. \ No newline at end of file diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000..36d5567 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,49 @@ +# Security Policy +Open Ticket Logo + +[![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.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v4.0.0) + +This is the Security Policy of Open Ticket!
+Here you can find a list of all supported & deprecated versions of the bot.
+You will also find some guidelines about how to report vulnerabilities, bugs & errors. + +### 📦 Supported Versions +Below, you can find a list with the status of every Open Ticket version.
+This list will be updated on every release. + +- 🟦 Early Access **(ideas, bugs, support, html transcripts)** +- ✅ Supported **(features, bugs, support, docs, html transcripts)** +- 🚧 Maintenance **(support, docs, html transcripts)** +- 🟧 Deprecated **(docs)** +- ❌ Fully Deprecated + +| Version | Supported | Notes | +|------------|-----------|--------------------------------| +| 4.0.0-beta | 🟦 | For v4.0.0 Full Release | +| 3.5.8 | ✅ | Supported until October 2024 | +| 3.5.7 | ✅ | Supported until September 2024 | +| 3.5.6 | 🟧 | Documentation Only | +| < 3.5.6 | 🟧 | Documentation Only | +| < 3.5.0 | ❌ | | + +### 🕷️ Reporting Vulnerabilities +You can report vulnerabilities, errors & bugs using one of the following methods: +- Create an issue on GitHub! +- Create a ticket in our [discord server](https://discord.dj-dj.be)! +- Message @DJj123dj in DM on discord! +- Send an E-mail to [support@dj-dj.be](mailto:support@dj-dj.be)! + +When you report a problem, please **give a small description** about what & how it happend.
+Try to explain the issue in as much detail as possible. + +If possible, try to provide screenshots! + +### Please upload the `otdebug.txt` file together with your bug report! + +--- +Open Ticket Logo + +**Security Policy**
+[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)
+ +© 2024 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c28ae79 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +node_modules/ +package-lock.json +devconfig/ +devdatabase/ +otdebug.txt +.DS_Store +*/.DS_Store +*/*/.DS_Store +*/*/*/.DS_Store +TEMP/ +.vscode/ +plugins/* +!plugins/example-plugin/ \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e72bfdd --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..add080b --- /dev/null +++ b/README.md @@ -0,0 +1,142 @@ +> ### 🎥 Content Creators 🎥 +> Hey there! We're searching for content creators that would want to create a tutorial or setup guide for Open Ticket!
+> [📌 More Information](.github/CONTENT_CREATORS.md) +--- + +

+Open Ticket +
Powered By
+Open Ticket
+Discord Invite Link +Open Ticket Version +Open Ticket Documentation +Open Ticket License +Open Ticket Stars +

+ +

+Open Ticket is 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! +You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 32 Languages! If you need any help, feel free to join our discord server! +

+ +

⭐️ Help us grow by giving a star! ⭐️

+ +> [!WARNING] +> Open Ticket v4 is still in beta! Please report all bugs in our [discord server](https://discord.dj-dj.be)!
+> The translation count may not be accurate! + +### 📌 Features +- **📄 html transcripts** - Make use of the most customisable, beautiful and easy-to-use HTML Transcripts! +- **✅ ticket actions** - Close, Reopen, Delete, Rename & Move all your tickets! +- **🇬🇧 translation** - Open Ticket has been translated in more than **32 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 everywhere** - Create an infinite amount of tickets & panels! +- **📝 advanced plugins** - Create the most advanced plugins that you want or use premade ones by our community! +- **👥 user management** - Add & Remove users from all tickets! +- **📊 detailed stats** - Open Ticket has ticket, user & global staticstics available for everyone! +- **🚫 blacklist** - Blacklist users to prevent them from creating a ticket! +- **❓ questions** - Let users answer questions in a modal before the ticket is created! +- **📦 commands** - Open Ticket supports both slash & text commands! +- **📥 extra types** - The bot also supports Reaction Roles & Url Buttons, because why not ¯\\_(ツ)_/¯ +- **🎛️ dependencies** - We try to use as little external dependencies as needed! + +> ### 📦 Resources +> Resources might not be accurate yet! *(because v4 is still in beta)*
+> Open Ticket Tutorial +> Open Ticket Docs +> Open Ticket Plugins + +## 📸 Preview +*Previews are not available yet in the beta release!* + +## 🧩 Plugins +View all available Open Ticket plugins in our [Official Plugin Repository](https://github.com/DJj123dj/open-discord-plugins)! + +### 📦 Official *(made by us)* +|Name |Description | +|----------------------|-------------------------| +|`nothing yet :)` |Lorem Ipsum Beta 4.0 🙃 | + +### ✅ Verified *(made by community)* +|Name |Description | +|----------------------|-------------------------| +|`nothing yet :)` |Lorem Ipsum Beta 4.0 🙃 | + +## 🛠️ Contributors +### 🖥️ Team +The team behind Open Ticket! + + + + + + + + + +
Profile PictureProfile Picture
DJj123djSanke
+ +### ❤️ Sponsors +A big thanks to all our sponsors! Without them, it wouldn't be possible to create this project! + +|Profile Picture|Profile Picture|Profile Picture| +|----|-|-| +|**[SpyEye](https://github.com/SpyEye2)**|**[DOSEV5](https://github.com/DOSEV5)**|**[Mods HD](https://github.com/mods-hd)**| + +### 💬 Translators +|Language |Maintainer (discord name) |Status | +|---------------------|--------------------------|---------------| +|🇬🇧 English |djj123dj |🟢 Up To Date | +|🇳🇱 Dutch |djj123dj |🟢 Up To Date | +|🇵🇹 Portuguese |quiradon |🟢 Up To Date | +|🇨🇿 Czech |spyeye_ |🟢 Up To Date | +|🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | +|🇷🇴 Romanian |sankedev |🟠 Temporary Outdated (beta) | +|🇪🇸 Spanish |redactado & josuens |🟠 Temporary Outdated (beta) | +|🇩🇪 German |david.3 |🟠 Temporary Outdated (beta) | +|🇮🇹 Italian |maurizio26 |🟠 Temporary Outdated (beta) | +|🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | +|🇩🇰 Danish |.the_gamer |🟠 Temporary Outdated (beta) | +|🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | +|🇺🇦 Ukrainian |ander |🟠 Temporary Outdated (beta) | +|🇹🇷 Turkish |0x15d3 |🟠 Temporary Outdated (beta) | +|🇵🇱 Polish |mkevas |🟠 Temporary Outdated (beta) | +|🇸🇮 Slovenian |n1kkec |🔴 Outdated | +|🇹🇭 Thai |modshd |🟠 Temporary Outdated (beta) | +|🇳🇴 Norwegian |noonenook |🟠 Temporary Outdated (beta) | +|🇬🇷 Greek |stefanos__. |🔴 Outdated | +|🇮🇩 Indonesian |erxg |🟠 Temporary Outdated (beta) | +|❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | +|🇭🇺 Hungarian |kornel0706 |🟠 Temporary Outdated (beta) | +|❓ Persian |sasanwm |🟠 Temporary Outdated (beta) | +|🇱🇻 Latvian |ronalds1398 |🟠 Temporary Outdated (beta) | +|🇪🇪 Estonian |iamnotmega |🟠 Temporary Outdated (beta) | +|🇯🇵 Japanese |iamnotmega |🟠 Temporary Outdated (beta) | +|🇰🇷 Korean |iamnotmega |🟠 Temporary Outdated (beta) | +|🇨🇳 Simplified Chinese |iamnotmega |🟠 Temporary Outdated (beta) | +|🇨🇳 Traditional Chinese|iamnotmega |🟠 Temporary Outdated (beta) | +|🇫🇮 Finnish |iamnotmega |🟠 Temporary Outdated (beta) | +|🇸🇪 Swedish |iamnotmega |🟠 Temporary Outdated (beta) | +|🇻🇳 Vietnamese |iamnotmega |🟠 Temporary Outdated (beta) | + + + +## ⭐️ Star History +Please help us grow by giving a star! It would help us a lot! + + + + + + Star History Chart + + + +--- +Open Ticket Logo + +**README.md**
+[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)
+ +© 2024 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file diff --git a/config/general.json b/config/general.json new file mode 100644 index 0000000..b45ca8f --- /dev/null +++ b/config/general.json @@ -0,0 +1,95 @@ +{ + "_INFO":{ + "support":"https://otdocs.dj-dj.be", + "discord":"https://discord.dj-dj.be", + "version":"open-ticket-v4.0.0" + }, + + "token":"your bot token here! Or leave empty when you use tokenFromENV", + "tokenFromENV":false, + + "mainColor":"#f8ba00", + "language":"english", + "prefix":"!ticket ", + "serverId":"discord server id", + "globalAdmins":["discord role id"], + + "slashCommands":true, + "textCommands":true, + + "status":{ + "enabled":true, + "type":"listening OR watching OR playing OR custom", + "text":"/help", + "status":"online OR invisible OR idle OR dnd" + }, + + "system":{ + "removeParticipantsOnClose":false, + "replyOnTicketCreation":true, + "replyOnReactionRole":true, + "useTranslatedConfigChecker":true, + "preferSlashOverText":true, + "sendErrorOnUnknownCommand":true, + "questionFieldsInCodeBlock":true, + "disableVerifyBars":false, + "useRedErrorEmbeds":true, + "emojiStyle":"before (OR after OR double OR disabled)", + + "enableTicketClaimButtons":true, + "enableTicketCloseButtons":true, + "enableTicketPinButtons":true, + "enableTicketDeleteButtons":true, + "enableTicketActionWithReason":true, + "enableDeleteWithoutTranscript":true, + + "logs":{ + "enabled":false, + "channel":"discord channel id" + }, + + "limits":{ + "enabled":true, + "globalMaximum":50, + "userMaximum":3 + }, + + "permissions":{ + "help":"everyone (OR admin OR none OR role id)", + "panel":"admin (OR everyone OR none OR role id)", + "ticket":"none (OR admin OR everyone OR role id)", + "close":"everyone (OR admin OR none OR role id)", + "delete":"admin (OR everyone OR none OR role id)", + "reopen":"everyone (OR admin OR none OR role id)", + "claim":"admin (OR everyone OR none OR role id)", + "unclaim":"admin (OR everyone OR none OR role id)", + "pin":"admin (OR everyone OR none OR role id)", + "unpin":"admin (OR everyone OR none OR role id)", + "move":"admin (OR everyone OR none OR role id)", + "rename":"admin (OR everyone OR none OR role id)", + "add":"admin (OR everyone OR none OR role id)", + "remove":"admin (OR everyone OR none OR role id)", + "blacklist":"admin (OR everyone OR none OR role id)", + "stats":"everyone (OR admin OR none OR role id)", + "clear":"admin (OR everyone OR none OR role id)", + "autoclose":"admin (OR everyone OR none OR role id)", + "autodelete":"admin (OR everyone OR none OR role id)" + }, + + "messages":{ + "creation":{"dm":false, "logs":true}, + "closing":{"dm":false, "logs":true}, + "deleting":{"dm":false, "logs":true}, + "reopening":{"dm":false, "logs":true}, + "claiming":{"dm":false, "logs":true}, + "pinning":{"dm":false, "logs":true}, + "adding":{"dm":false, "logs":true}, + "removing":{"dm":false, "logs":true}, + "renaming":{"dm":false, "logs":true}, + "moving":{"dm":false, "logs":true}, + "blacklisting":{"dm":false, "logs":true}, + "roleAdding":{"dm":false, "logs":true}, + "roleRemoving":{"dm":false, "logs":true} + } + } +} \ No newline at end of file diff --git a/config/options.json b/config/options.json new file mode 100644 index 0000000..6dc8604 --- /dev/null +++ b/config/options.json @@ -0,0 +1,122 @@ +[ + { + "id":"example-ticket", + "name":"Question", + "description":"Create this ticket if you have a question! (or leave empty)", + "type":"ticket", + + "button":{ + "emoji":"🎫 (or leave empty)", + "label":"question (or leave empty)", + "color":"gray OR red OR green OR blue" + }, + + "ticketAdmins":["discord role id"], + "readonlyAdmins":["discord role id"], + "allowCreationByBlacklistedUsers":false, + "questions":["example-question-1","example-question-2"], + + "channel":{ + "prefix":"question-", + "suffix":"user-name OR user-id OR random-number OR random-hex OR counter-dynamic OR counter-fixed", + "category":"category id (or leave empty)", + "closedCategory":"category id (or leave empty)", + "backupCategory":"category id (or leave empty)", + "claimedCategory":[ + {"user":"user id","category":"category id"} + ], + "description":"This is a question ticket (or leave empty)" + }, + + "dmMessage":{ + "enabled":false, + "text":"Thanks for creating a ticket in our server! (or leave empty)", + "embed":{ + "enabled":false, + "title":"Embed Title! (or leave empty)", + "description":"Description (or leave empty)", + "customColor":"#f8ab00 (or leave empty)", + + "image":"https://www.example.com/image.png (or leave empty)", + "thumbnail":"https://www.example.com/image.png (or leave empty)", + "fields":[ + {"name":"field name","value":"field value","inline":false} + ], + "timestamp":false + } + }, + "ticketMessage":{ + "enabled":true, + "text":"", + "embed":{ + "enabled":true, + "title":"Question Ticket", + "description":"Thanks for creating a 'Question' ticket in our server!\nOur support team will help you soon!", + "customColor":"#f8ab00 (or leave empty)", + + "image":"https://www.example.com/image.png (or leave empty)", + "thumbnail":"https://www.example.com/image.png (or leave empty)", + "fields":[ + {"name":"field name","value":"field value","inline":false} + ], + "timestamp":false + }, + "ping":{ + "@here":true, + "@everyone":false, + "custom":["discord role id"] + } + }, + "autoclose":{ + "enableInactiveHours":false, + "inactiveHours":24, + "enableUserLeave":true, + "disableOnClaim":false + }, + "autodelete":{ + "enableInactiveDays":false, + "inactiveDays":7, + "enableUserLeave":true, + "disableOnClaim":false + }, + "cooldown":{ + "enabled":false, + "cooldownMinutes":10 + }, + "limits":{ + "enabled":false, + "globalMaximum":20, + "userMaximum":3 + } + }, + { + "id":"example-website", + "name":"Website", + "description":"Go to our website.", + "type":"website", + + "button":{ + "emoji":"😃", + "label":"Visit our website" + }, + + "url":"https://www.dj-dj.be" + }, + { + "id":"example-role", + "name":"Update Ping", + "description":"Click here to get notified on updates!", + "type":"role", + + "button":{ + "emoji":"📢", + "label":"Update Ping", + "color":"gray OR red OR green OR blue" + }, + + "roles":["discord role id"], + "mode":"add&remove OR remove OR add", + "removeRolesOnAdd":["discord role id"], + "addOnMemberJoin":false + } +] \ No newline at end of file diff --git a/config/panels.json b/config/panels.json new file mode 100644 index 0000000..805ced5 --- /dev/null +++ b/config/panels.json @@ -0,0 +1,39 @@ +[ + { + "id":"example-embed", + "name":"Example Embed", + "dropdown":false, + "options":["example-ticket","example-website","example-role"], + + "text":"", + "embed":{ + "enabled":true, + "title":"Tickets:", + "description":"Create a ticket by clicking one of the buttons below!", + + "customColor":"#f8ab00 (or leave empty)", + "url":"https://openticket.dj-dj.be (or leave empty)", + + "image":"https://www.example.com/image.png (or leave empty)", + "thumbnail":"https://www.example.com/image.png (or leave empty)", + + "footer":"Open Ticket v4.0.0 (or leave empty)", + "fields":[ + {"name":"field name","value":"field value","inline":false} + ], + "timestamp":false + }, + "settings":{ + "dropdownPlaceholder":"Create a ticket!", + + "enableMaxTicketsWarningInText":false, + "enableMaxTicketsWarningInEmbed":true, + + "describeOptionsLayout":"simple OR normal OR detailed", + "describeOptionsCustomTitle":"", + "describeOptionsInText":false, + "describeOptionsInEmbedFields":true, + "describeOptionsInEmbedDescription":false + } + } +] \ No newline at end of file diff --git a/config/questions.json b/config/questions.json new file mode 100644 index 0000000..0d2556e --- /dev/null +++ b/config/questions.json @@ -0,0 +1,28 @@ +[ + { + "id":"example-question-1", + "name":"Example Question 1", + "type":"short", + + "required":true, + "placeholder":"Insert your short answer here!", + "length":{ + "enabled":false, + "min":0, + "max":1000 + } + }, + { + "id":"example-question-2", + "name":"Example Question 2", + "type":"paragraph", + + "required":false, + "placeholder":"Insert your long answer here!", + "length":{ + "enabled":false, + "min":0, + "max":1000 + } + } +] \ No newline at end of file diff --git a/config/transcripts.json b/config/transcripts.json new file mode 100644 index 0000000..5ce9a88 --- /dev/null +++ b/config/transcripts.json @@ -0,0 +1,57 @@ +{ + "general":{ + "enabled":false, + + "enableChannel":false, + "enableCreatorDM":false, + "enableParticipantDM":false, + "enableActiveAdminDM":false, + "enableEveryAdminDM":false, + + "channel":"transcript channel id (or leave empty)", + "mode":"html OR text" + }, + "embedSettings":{ + "customColor":"#f8ab00 (or leave empty)", + "listAllParticipants":false, + "includeTicketStats":false + }, + "textTranscriptStyle":{ + "layout":"simple OR normal OR detailed", + "includeStats":true, + "includeIds":false, + "includeEmbeds":true, + "includeFiles":true, + "includeBotMessages":true, + + "fileMode":"custom OR channel-name OR channel-id OR user-name OR user-id", + "customFileName":"this-is-a-transcript (or leave empty)" + }, + "htmlTranscriptStyle":{ + "background":{ + "enableCustomBackground":false, + "backgroundColor":"#f8ba00 (or leave empty)", + "backgroundImage":"https://www.example.com/image.png (or leave empty)" + + }, + "header":{ + "enableCustomHeader":false, + "backgroundColor":"#202225", + "decoColor":"#f8ba00", + "textColor":"#ffffff" + + }, + "stats":{ + "enableCustomStats":false, + "backgroundColor":"#202225", + "keyTextColor":"#737373", + "valueTextColor":"#ffffff", + "hideBackgroundColor":"#40444a", + "hideTextColor":"#ffffff" + }, + "favicon":{ + "enableCustomFavicon":false, + "imageUrl":"https://transcripts.dj-dj.be/favicon.png" + } + } +} \ No newline at end of file diff --git a/database/global.json b/database/global.json new file mode 100644 index 0000000..fb44b71 --- /dev/null +++ b/database/global.json @@ -0,0 +1,7 @@ +[ + {"category":"openticket:last-version","key":"openticket:version","value":"v4.0.0"}, + {"category":"openticket:last-version","key":"openticket:api","value":"v1.0.0"}, + {"category":"openticket:last-version","key":"openticket:transcripts","value":"v2.0.0"}, + {"category":"openticket:last-version","key":"openticket:livestatus","value":"v2.0.0"}, + {"category":"openticket:last-version","key":"openticket:last-version","value":"v4.0.0"} +] \ No newline at end of file diff --git a/database/options.json b/database/options.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/database/options.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/database/stats.json b/database/stats.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/database/stats.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/database/tickets.json b/database/tickets.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/database/tickets.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/database/users.json b/database/users.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/database/users.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/languages/custom.json b/languages/custom.json new file mode 100644 index 0000000..8d36a30 --- /dev/null +++ b/languages/custom.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"DJj123dj", + "lastedited":"21/08/2024", + "language":"Custom" + }, + "checker":{ + "system":{ + "typeError":"[ERROR]", + "headerOpenTicket":"OPEN TICKET", + "typeWarning":"[WARNING]", + "typeInfo":"[INFO]", + "headerConfigChecker":"CONFIG CHECKER", + "headerDescription":"check for errors in you 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":"This string can't be shorter than {0} characters!", + "stringTooLong":"This string can't be longer than {0} characters!", + "stringLengthInvalid":"This string needs to be {0} characters long!", + "stringStartsWith":"This string needs to start with {0}!", + "stringEndsWith":"This string needs to end with {0}!", + "stringContains":"This string needs to contain {0}!", + "stringChoices":"This string can only be one of the following values: {0}!", + "stringRegex":"This string is invalid!", + + "numberTooShort":"This number can't be shorter than {0} characters!", + "numberTooLong":"This number can't be longer than {0} characters!", + "numberLengthInvalid":"This number needs to be {0} characters long!", + "numberTooSmall":"This number needs to be at least {0}!", + "numberTooLarge":"This number needs to be at most {0}!", + "numberNotEqual":"This number needs to be {0}!", + "numberStep":"This number needs to be a multiple of {0}!", + "numberStepOffset":"This number needs to be a multiple of {0} starting with {1}!", + "numberStartsWith":"This number needs to start with {0}!", + "numberEndsWith":"This number needs to end with {0}!", + "numberContains":"This number needs to contain {0}!", + "numberChoices":"This number can only be one of the following values: {0}!", + "numberFloat":"This number can't be a decimal!", + "numberNegative":"This number can't be negative!", + "numberPositive":"This number can't be positive!", + "numberZero":"This number can't be zero!", + + "booleanTrue":"This boolean can't be true!", + "booleanFalse":"This boolean can't be false!", + + "arrayEmptyDisabled":"This array isn't allowed to be empty!", + "arrayEmptyRequired":"This array is required to be empty!", + "arrayTooShort":"This array needs to have a length of at least {0}!", + "arrayTooLong":"This array needs to have a length of at most {0}!", + "arrayLengthInvalid":"This array needs to have a length of {0}!", + "arrayInvalidTypes":"This array can only contain the following types: {0}!", + "arrayDouble":"This array doesn't allow the same value twice!", + + "discordInvalidId":"This is an invalid discord {0} id!", + "discordInvalidIdOptions":"This is an invalid discord {0} id! You can also use one of these: {1}!", + "discordInvalidToken":"This is an invalid discord token (syntactically)!", + "colorInvalid":"This is an invalid hex color!", + "emojiTooShort":"This string needs to have at least {0} emoji's!", + "emojiTooLong":"This string needs to have at most {0} emoji's!", + "emojiCustom":"This emoji can't be a custom discord emoji!", + "emojiInvalid":"This is an invalid emoji!", + "urlInvalid":"This url is invalid!", + "urlInvalidHttp":"This url can only use the https:// protocol!", + "urlInvalidProtocol":"This url can only use the http:// & https:// protocols!", + "urlInvalidHostname":"This url has a disallowed hostname!", + "urlInvalidExtension":"This url has an invalid extension! Choose between: {0}!", + "urlInvalidPath":"This url has an invalid path!", + "idNotUnique":"This id isn't unique, use another id instead!", + "idNonExistent":"The id {0} doesn't exist!", + + "invalidType":"This property needs to be the type: {0}!", + "propertyMissing":"The property {0} is missing from this object!", + "propertyOptional":"The property {0} is optional in this object!", + "objectDisabled":"This object is disabled, enable it using {0}!", + "nullInvalid":"This property can't be null!", + "switchInvalidType":"This needs to be one of the following types: {0}!", + "objectSwitchInvalid":"This object needs to be one of the following types: {0}!", + + "invalidLanguage":"This is an invalid language!", + "invalidButton":"This button needs to have at least an {0} or {1}!", + "unusedOption":"The option {0} isn't used anywhere!", + "unusedQuestion":"The question {0} isn't used anywhere!", + "dropdownOption":"A panel with dropdown enabled can only contain options of the 'ticket' type!" + } + }, + "actions":{ + "buttons":{ + "create":"Visit Ticket", + "close":"Close Ticket", + "delete":"Delete Ticket", + "reopen":"Reopen Ticket", + "claim":"Claim Ticket", + "unclaim":"Unclaim Ticket", + "pin":"Pin Ticket", + "unpin":"Unpin Ticket", + "clear":"Delete Tickets", + "helpSwitchSlash":"View Slash Commands", + "helpSwitchText":"View Text Commands", + "helpPage":"Page {0}", + "withReason":"With Reason", + "withoutTranscript":"Without Transcript" + }, + "titles":{ + "created":"Ticket Created", + "close":"Ticket Closed", + "delete":"Ticket Deleted", + "reopen":"Ticket Reopened", + "claim":"Ticket Claimed", + "unclaim":"Ticket Unclaimed", + "pin":"Ticket Pinned", + "unpin":"Ticket Unpinned", + "rename":"Ticket Renamed", + "move":"Ticket Moved", + "add":"Ticket User Added", + "remove":"Ticket User Removed", + + "help":"Available Commands", + "statsReset":"Reset Stats", + "blacklistAdd":"User Blacklisted", + "blacklistRemove":"User Released", + "blacklistGet":"Blacklisted User", + "blacklistView":"Current Blacklist", + "blacklistAddDm":"Added To Blacklist", + "blacklistRemoveDm":"Removed From Blacklist", + "clear":"Tickets Cleared", + "roles":"Roles Updated", + + "autoclose":"Ticket Autoclosed", + "autocloseEnabled":"Autoclose Enabled", + "autocloseDisabled":"Autoclose Disabled", + "autodelete":"Ticket Autodeleted", + "autodeleteEnabled":"Autodelete Enabled", + "autodeleteDisabled":"Autodelete Disabled" + }, + "descriptions":{ + "create":"Your ticket has been created. Click the button below to access it!", + "close":"The ticket has been closed succesfully!", + "delete":"The ticket has been deleted succesfully!", + "reopen":"The ticket has been reopened succesfully!", + "claim":"The ticket has been claimed succesfully!", + "unclaim":"The ticket has been unclaimed succesfully!", + "pin":"The ticket has been pinned succesfully!", + "unpin":"The ticket has been unpinned succesfully!", + "rename":"The ticket has been renamed to {0} succesfully!", + "move":"The ticket has been moved to {0} succesfully!", + "add":"{0} has been added to the ticket succesfully!", + "remove":"{0} has been removed from the ticket succesfully!", + + "helpExplanation":"`` => required parameter\n`[name]` => optional parameter", + "statsReset":"The bot stats have been reset successfully!", + "statsError":"Unable to view ticket stats!\n{0} is not a ticket!", + "blacklistAdd":"{0} has been blacklisted successfully!", + "blacklistRemove":"{0} has been released successfully!", + "blacklistGetSuccess":"{0} is currently blacklisted!", + "blacklistGetEmpty":"{0} is currently not blacklisted!", + "blacklistViewEmpty":"No-one has been blacklisted yet!", + "blacklistViewTip":"Use \"/blacklist add\" to blacklist a user!", + "clearVerify":"Are you sure you want to delete multiple tickets?\nThis action can't be undone!", + "clearReady":"{0} tickets have been deleted succesfully!", + "rolesEmpty":"No roles have been updated!", + + "autocloseLeave":"This ticket has been autoclosed because the creator left the server!", + "autocloseTimeout":"This ticket has been autoclosed because it has been inactive for more than `{0}h`!", + "autodeleteLeave":"This ticket has been autodeleted because the creator left the server!", + "autodeleteTimeout":"This ticket has been autodeleted because it has been inactive for more than `{0} days`!", + "autocloseEnabled":"Autoclose has been enabled in this ticket!\nIt will be closed when it is inactive for more than `{0}h`!", + "autocloseDisabled":"Autoclose has been disabled in this ticket!\nIt won't be closed automatically anymore!", + "autodeleteEnabled":"Autodelete has been enabled in this ticket!\nIt will be deleted when it is inactive for more than `{0} days`!", + "autodeleteDisabled":"Autodelete has been disabled in this ticket!\nIt won't be deleted automatically anymore!", + + "ticketMessageLimit":"You can only create {0} ticket(s) at the same time!", + "ticketMessageAutoclose":"This ticket will be autoclosed when inactive for {0}h!", + "ticketMessageAutodelete":"This ticket will be autodeleted when inactive for {0} days!", + "panelReady":"You can find the panel below!\nThis message can now be deleted!" + }, + "modal":{ + "closePlaceholder":"Why did you close this ticket?", + "deletePlaceholder":"Why did you delete this ticket?", + "reopenPlaceholder":"Why did you reopen this ticket?", + "claimPlaceholder":"Why did you claim this ticket?", + "unclaimPlaceholder":"Why did you unclaim this ticket?", + "pinPlaceholder":"Why did you pin this ticket?", + "unpinPlaceholder":"Why did you unpin this ticket?" + }, + "logs":{ + "createLog":"A new ticket got created by {0}!", + "closeLog":"This ticket has been closed by {0}!", + "closeDm":"Your ticket has been closed in our server!", + "deleteLog":"This ticket has been deleted by {0}!", + "deleteDm":"Your ticket has been deleted in our server!", + "reopenLog":"This ticket has been reopened by {0}!", + "reopenDm":"Your ticket has been reopened in our server!", + "claimLog":"This ticket has been claimed by {0}!", + "claimDm":"Your ticket has been claimed in our server!", + "unclaimLog":"This ticket has been unclaimed by {0}!", + "unclaimDm":"Your ticket has been unclaimed in our server!", + "pinLog":"This ticket has been pinned by {0}!", + "pinDm":"Your ticket has been pinned in our server!", + "unpinLog":"This ticket has been unpinned by {0}!", + "unpinDm":"Your ticket has been unpinned in our server!", + "renameLog":"This ticket has been renamed to {0} by {1}!", + "renameDm":"Your ticket has been renamed to {0} in our server!", + "moveLog":"This ticket has been moved to {0} by {1}!", + "moveDm":"Your ticket has been moved to {0} in our server!", + "addLog":"{0} has been added to this ticket by {1}!", + "addDm":"{0} has been added to your ticket in our server!", + "removeLog":"{0} has been removed from this ticket by {1}!", + "removeDm":"{0} has been removed from your ticket in our server!", + + "blacklistAddLog":"{0} was blacklisted by {1}!", + "blacklistRemoveLog":"{0} was removed from the blacklist by {1}!", + "blacklistAddDm":"You have been blacklisted in our server!\nFrom now on, you are unable to create a ticket!", + "blacklistRemoveDm":"You have been removed from the blacklist in our server!\nNow you can create tickets again!", + "clearLog":"{0} tickets have been deleted by {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Visit Transcript", + "ready":"Transcript Created", + "textFileDescription":"This is the text transcript of a deleted ticket!", + "htmlProgress":"Please wait while this html transcript is getting processed...", + + "createdChannel":"A new {0} transcript has been created in the server!", + "createdCreator":"A new {0} transcript has been created for one of your tickets!", + "createdParticipant":"A new {0} transcript has been created in one of the tickets you participated in!", + "createdActiveAdmin":"A new {0} transcript has been created in one of the tickets you participated as admin!", + "createdEveryAdmin":"A new {0} transcript has been created in one of the tickets you were admin in!", + "createdOther":"A new {0} transcript has been created!" + }, + "errors":{ + "retry":"Retry", + "continue":"Delete Without Transcript", + "backup":"Create Backup Transcript", + "error":"Something went wrong while trying to create the transcript.\nWhat would you like to do?\n\nThis ticket won't be deleted until you click one of these buttons." + } + }, + "errors":{ + "titles":{ + "internalError":"Internal Error", + "optionMissing":"Command Option Missing", + "optionInvalid":"Command Option Invalid", + "unknownCommand":"Unknown Command", + "noPermissions":"No Permissions", + "unknownTicket":"Unknown Ticket", + "deprecatedTicket":"Deprecated Ticket", + "unknownOption":"Unknown Option", + "unknownPanel":"Unknown Panel", + "notInGuild":"Not In Server", + "channelRename":"Unable To Rename Channel", + "busy":"Ticket Is Busy" + }, + "descriptions":{ + "askForInfo":"Contact the owner of this bot for more info!", + "askForInfoResolve":"Contact the bot owner of this bot if this issue doesn't resolve after a few tries.", + "internalError":"Failed to respond to this {0} due to an internal error!", + "optionMissing":"A required parameter is missing in this command!", + "optionInvalid":"A parameter in this command is invalid!", + "optionInvalidChoose":"Choose between", + "unknownCommand":"Try visiting the help menu for more info!", + "noPermissions":"You are not allowed to use this {0}!", + "noPermissionsList":"Required Permissions: (one of them)", + "noPermissionsCooldown":"You are not allowed to use this {0} because you have a cooldown!", + "noPermissionsBlacklist":"You are not allowed to use this {0} because you have been blacklisted!", + "noPermissionsLimitGlobal":"You are not allowed to create a ticket because the server reached the max tickets limit!", + "noPermissionsLimitGlobalUser":"You are not allowed to create a ticket because you reached the max tickets limit!", + "noPermissionsLimitOption":"You are not allowed to create a ticket because the server reached the max tickets limit for this option!", + "noPermissionsLimitOptionUser":"You are not allowed to create a ticket because you reached the max tickets limit for this option!", + "unknownTicket":"Try this command again in a valid ticket!", + "deprecatedTicket":"The current channel is not a valid ticket! It might have been a ticket from an old Open Ticket version!", + "notInGuild":"This {0} doesn't work in DM! Please try it again in a server!", + "channelRename":"Due to discord ratelimits, it's currently impossible for the bot to rename the channel. The channel will automatically be renamed over 10 minutes if the bot isn't rebooted.", + "channelRenameSource":"The source of this error is: {0}", + "busy":"Unable to use this {0}!\nThe ticket is currently being processed by the bot.\n\nPlease try again in a few seconds!" + }, + "optionInvalidReasons":{ + "stringRegex":"Value doesn't match pattern!", + "stringMinLength":"Value needs to be at least {0} characters!", + "stringMaxLength":"Value needs to be at most {0} characters!", + "numberInvalid":"Invalid number!", + "numberMin":"Number needs to be at least {0}!", + "numberMax":"Number needs to be at most {0}!", + "numberDecimal":"Number is not allowed to be a decimal!", + "numberNegative":"Number is not allowed to be negative!", + "numberPositive":"Number is not allowed to be positive!", + "numberZero":"Number is not allowed to be zero!", + "channelNotFound":"Unable to find channel!", + "userNotFound":"Unable to find user!", + "roleNotFound":"Unable to find role!", + "memberNotFound":"Unable to find user!", + "mentionableNotFound":"Unable to find user or role!", + "channelType":"Invalid channel type!", + "notInGuild":"This option requires you to be in a server!" + }, + "permissions":{ + "developer":"You need to be the developer of the bot.", + "owner":"You need to be the server owner.", + "admin":"You need to be a server admin.", + "moderator":"You need to be a moderator.", + "support":"You need to be in the support team.", + "member":"You need to be a member.", + "discord-administrator":"You need to have the `ADMINISTRATOR` permission." + }, + "actionInvalid":{ + "close":"Ticket is already closed!", + "reopen":"Ticket is not closed yet!", + "claim":"Ticket is already claimed!", + "unclaim":"Ticket is not claimed yet!", + "pin":"Ticket is already pinned!", + "unpin":"Ticket is not pinned yet!", + "add":"This user is already able to access the ticket!", + "remove":"Unable to remove this user from the ticket!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickets", + "reason":"Reason", + "creator":"Creator", + "remaining":"Time Remaining", + "added":"Added", + "removed":"Removed", + "filter":"Filter", + "claimedBy":"Claimed By {0}", + "method":"Method", + "type":"Type", + "blacklisted":"Blacklisted", + "panel":"Panel", + "command":"Command", + "system":"System", + "true":"True", + "false":"False", + "syntax":"Syntax", + "originalName":"Original Name", + "newName":"New Name", + "until":"Until", + "validOptions":"Valid Options", + "validPanels":"Valid Panels", + "autoclose":"Autoclose", + "autodelete":"Autodelete", + "startupDate":"Startup Date", + "version":"Version", + "name":"Name", + "role":"Role", + "status":"Status", + "claimed":"Claimed", + "pinned":"Pinned", + "creationDate":"Creation Date" + }, + "lowercase":{ + "text":"text", + "html":"html", + "command":"command", + "modal":"modal", + "button":"button", + "dropdown":"dropdown", + "method":"method" + } + }, + "commands":{ + "reason":"Specify an optional reason that will be visible in logs.", + "help":"Get a list of all the available commands.", + "panel":"Spawn a message with a dropdown or buttons (for ticket creation).", + "panelId":"The identifier of the panel that you want to spawn.", + "panelAutoUpdate":"Do you want this panel to automatically update when edited?", + "ticket":"Instantly create a ticket.", + "ticketId":"The identifier of the ticket that you want to create.", + "close":"Close a ticket.", + "delete":"Delete a ticket.", + "deleteNoTranscript":"Delete this ticket without creating a transcript.", + "reopen":"Reopen a ticket.", + "claim":"Claim a ticket.", + "claimUser":"Claim this ticket to someone else instead of yourself.", + "unclaim":"Unclaim a ticket.", + "pin":"Pin a ticket.", + "unpin":"Unpin a ticket.", + "move":"Move a ticket.", + "moveId":"The identifier of the option that you want to move to.", + "rename":"Rename a ticket.", + "renameName":"The new name for this ticket.", + "add":"Add a user to a ticket.", + "addUser":"The user to add.", + "remove":"Remove a user from a ticket.", + "removeUser":"The user to remove.", + "blacklist":"Manage the ticket blacklist.", + "blacklistView":"View a list of the current blacklist.", + "blacklistAdd":"Add a user to the blacklist.", + "blacklistRemove":"Remove a user from the blacklist.", + "blacklistGet":"Get the details from a blacklisted user.", + "blacklistGetUser":"The user to get details from.", + "stats":"View statistics from the bot, a member or a ticket.", + "statsReset":"Reset all the stats of the bot (and start counting from zero).", + "statsGlobal":"View the global stats.", + "statsUser":"View the stats from a user in the server.", + "statsUserUser":"The user to view.", + "statsTicket":"View the stats of a ticket in the server.", + "statsTicketTicket":"The ticket to view.", + "clear":"Delete multiple tickets at the same time.", + "clearFilter":"The filter for clearing tickets.", + "clearFilters":{ + "all":"All", + "open":"Open", + "close":"Closed", + "claim":"Claimed", + "unclaim":"Unclaimed", + "pin":"Pinned", + "unpin":"Unpinned", + "autoclose":"Autoclosed" + }, + "autoclose":"Manage autoclose in a ticket.", + "autocloseDisable":"Disable autoclose in this ticket.", + "autocloseEnable":"Enable autoclose in this ticket.", + "autocloseEnableTime":"The amount of hours this ticket needs to be inactive to close it.", + "autodelete":"Manage autodelete in a ticket.", + "autodeleteDisable":"Disable autodelete in this ticket.", + "autodeleteEnable":"Enable autodelete in this ticket.", + "autodeleteEnableTime":"The amount of days this ticket needs to be inactive to delete it." + }, + "helpMenu":{ + "help":"Get a list of all the available commands.", + "ticket":"Instantly create a ticket.", + "close":"Close a ticket, this disables writing in this channel.", + "delete":"Delete a ticket, this creates a transcript when enabled.", + "reopen":"Reopen a ticket, this enables writing in this channel again.", + "pin":"Pin a ticket. This will move the ticket to the top and will add a '📌' emoij to the name.", + "unpin":"Unpin a ticket. The ticket will stay on it's position but will lose the '📌' emoij.", + "move":"Move a ticket. This will change the type of this ticket.", + "rename":"Rename a ticket. This will change the channel name of this ticket.", + "claim":"Claim a ticket. With this, you can let your team know you are handling this ticket.", + "unclaim":"Unclaim a ticket. With this, you can let your team know that this ticket is free again.", + "add":"Add a user to a ticket. This will allow the user to read & write in this ticket.", + "remove":"Remove a user from a ticket. This will remove the ability to read & write for a user in this ticket.", + "panel":"Spawn a message with a dropdown or buttons (for ticket creation).", + "blacklistView":"View a list of the current blacklist.", + "blacklistAdd":"Add a user to the blacklist.", + "blacklistRemove":"Remove a user from the blacklist.", + "blacklistGet":"Get the details from a blacklisted user.", + "statsGlobal":"View the global stats.", + "statsTicket":"View the stats of a ticket in the server.", + "statsUser":"View the stats from a user in the server.", + "statsReset":"Reset all the stats of the bot (and start counting from zero).", + "autocloseDisable":"Disable autoclose in this ticket.", + "autocloseEnable":"Enable autoclose in this ticket.", + "autodeleteDisable":"Disable autodelete in this ticket.", + "autodeleteEnable":"Enable autodelete in this ticket." + }, + "stats":{ + "scopes":{ + "global":"Global Stats", + "system":"System Stats", + "user":"User Stats", + "ticket":"Ticket Stats", + "participants":"Participants" + }, + "properties":{ + "ticketsCreated":"Tickets Created", + "ticketsClosed":"Tickets Closed", + "ticketsDeleted":"Tickets Deleted", + "ticketsReopened":"Tickets Reopened", + "ticketsAutoclosed":"Tickets Autoclosed", + "ticketsClaimed":"Tickets Claimed", + "ticketsPinned":"Tickets Pinned", + "ticketsMoved":"Tickets Moved", + "usersBlacklisted":"Users Blacklisted", + "transcriptsCreated":"Transcripts Created" + } + } +} \ No newline at end of file diff --git a/languages/czech.json b/languages/czech.json new file mode 100644 index 0000000..c19fca7 --- /dev/null +++ b/languages/czech.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"spyeye_", + "lastedited":"21/08/2024", + "language":"Czech" + }, + "checker":{ + "system":{ + "typeError":"[ERROR]", + "headerOpenTicket":"OPEN TICKET", + "typeWarning":"[WARNING]", + "typeInfo":"[INFO]", + "headerConfigChecker":"CONFIG CHECKER", + "headerDescription":"kontrola chyb v konfiguračních souborech!", + "footerError":"Bot se nespustí, dokud všechny {0} nebudou opraveny!", + "footerWarning":"Doporučejeme opravit všechny {0} před spuštěním!", + "footerSupport":"PODPORA: {0} - DOKUMENTACE: {1}", + "compactInformation":"Použij {0} pro více informací!", + "dataPath":"path", + "dataDocs":"docs", + "dataMessages":"message" + }, + "messages":{ + "stringTooShort":"Tento string nesmí být kratší než {0} znaků!", + "stringTooLong":"Tento string nesmí být delší než {0} znaků!", + "stringLengthInvalid":"Tento string musí mít délku {0} znaků!", + "stringStartsWith":"Tento string musí začínat {0}!", + "stringEndsWith":"Tento string musí končit {0}!", + "stringContains":"Tento string musí obsahovat {0}!", + "stringChoices":"Tento string může být pouze jednou z následujících možností: {0}!", + "stringRegex":"Tento string je neplatný!", + + "numberTooShort":"Toto číslo nesmí být kratší než {0} znaků!", + "numberTooLong":"Toto číslo nesmí být delší než {0} znaků.!", + "numberLengthInvalid":"Toto číslo musí mít délku {0} znaků.!", + "numberTooSmall":"Toto číslo musí být alespoň {0}.!", + "numberTooLarge":"Toto číslo musí být nejvýše {0}!", + "numberNotEqual":"Toto číslo musí být {0}!", + "numberStep":"Toto číslo musí být násobkem {0}.!", + "numberStepOffset":"Toto číslo musí být násobkem {0} žačínající {1}.!", + "numberStartsWith":"Toto číslo musí začínat {0}!", + "numberEndsWith":"Toto číslo musí končit {0}!", + "numberContains":"Toto číslo musí obsahovat {0}!", + "numberChoices":"Toto číslo může být pouze jedno z následujících hodnot: {0}!", + "numberFloat":"Toto číslo nemůže být desetinné!", + "numberNegative":"Toto číslo nemůže být záporné!", + "numberPositive":"Toto číslo nemůže být kladné!", + "numberZero":"Toto číslo nemůže být nula!", + + "booleanTrue":"Tento boolean nemůže být true!", + "booleanFalse":"Tento boolean nemůže být false!", + + "arrayEmptyDisabled":"Toto pole nesmí být prázdné.!", + "arrayEmptyRequired":"Toto pole musí být prázdné!", + "arrayTooShort":"Toto pole musí mít délku alespoň {0}!", + "arrayTooLong":"Toto pole musí mít délku maximálně {0}!", + "arrayLengthInvalid":"Toto pole musí mít délku {0}!", + "arrayInvalidTypes":"Toto pole může obsahovat pouze následující typy: {0}!", + "arrayDouble":"Toto pole neumožňuje zadat stejnou hodnotu dvakrát.!", + + "discordInvalidId":"Toto je neplatné discord {0} id!", + "discordInvalidIdOptions":"Toto je neplatné Discord ID {0}! Můžete také použít jeden z těchto: {1}!", + "discordInvalidToken":"Toto je neplatný discord token (syntakticky)!", + "colorInvalid":"Toto je neplatná hex barva!", + "emojiTooShort":"Tento string musí obsahovat alespoň {0} emotikonů.!", + "emojiTooLong":"Tento string musí obsahovat nejvýše {0} emotikonů.!", + "emojiCustom":"Tento emotikon nemůže být custom emotikon!", + "emojiInvalid":"Toto je neplatný emotikon!", + "urlInvalid":"Tato url adresa je neplatná!", + "urlInvalidHttp":"Tato url může používat pouze protokol https://!", + "urlInvalidProtocol":"Tato url může používat pouze protokoly http:// a https://!", + "urlInvalidHostname":"Tato url má zakázané hostitelské jméno!", + "urlInvalidExtension":"Tato url má neplatnou příponu! Vyberte si mezi: {0}!", + "urlInvalidPath":"Tato url má neplatnou cestu!", + "idNotUnique":"Toto id není jedinečné, místo něj použijte jiné id!", + "idNonExistent":"Id {0} neexistuje!", + + "invalidType":"Toto nastavení musí být typu: {0}!", + "propertyMissing":"U tohoto objektu chybí vlastnost {0}!", + "propertyOptional":"Vlastnost {0} je v tomto objektu nepovinná!", + "objectDisabled":"Tento objekt je zakázán, povolte jej pomocí {0}!", + "nullInvalid":"Tato vlastnost nemůže být nulová!", + "switchInvalidType":"Musí se jednat o jeden z následujících typů: {0}!", + "objectSwitchInvalid":"Tento objekt musí být jednoho z následujících typů: {0}!", + + "invalidLanguage":"Jedná se o neplatný jazyk!", + "invalidButton":"Toto tlačítko musí mít alespoň {0} nebo {1}!", + "unusedOption":"Možnost {0} se nikde nepoužívá!", + "unusedQuestion":"Otázka {0} není nikde použita!", + "dropdownOption":"Panel s povoleným rozevíracím seznamem může obsahovat pouze možnosti typu „ticketu“!" + } + }, + "actions":{ + "buttons":{ + "create":"Zobrazit ticket", + "close":"Uzavřít ticket", + "delete":"Vymazat ticket", + "reopen":"Znovu otevřít ticket", + "claim":"Převzít ticket", + "unclaim":"Zrušit převzetí ticketu", + "pin":"Připnout ticket", + "unpin":"Odepnout ticket", + "clear":"Vymazat tickety", + "helpSwitchSlash":"Zobrazit slash příkazy", + "helpSwitchText":"Zobrazit textové příkazy", + "helpPage":"Strana {0}", + "withReason":"S důvodem", + "withoutTranscript":"Bez důvodu" + }, + "titles":{ + "created":"Ticket vytvořen", + "close":"Ticket uzavřen", + "delete":"Ticket vymazán", + "reopen":"Ticket znovu otevřen", + "claim":"Ticket převzat", + "unclaim":"Ticket již není převezmut", + "pin":"Ticket připnut", + "unpin":"Ticket odepnut", + "rename":"Ticket přejmenován", + "move":"Ticket přesunut", + "add":"Uživatel přidán", + "remove":"Uživatel odebrán", + + "help":"Dostupné příkazy:", + "statsReset":"Resetovat statistiky", + "blacklistAdd":"Uživatel blacklistován", + "blacklistRemove":"Uživatel odebrán z blacklistu", + "blacklistGet":"Uživatel na blacklistu", + "blacklistView":"Aktuální blacklist", + "blacklistAddDm":"Přidán na blacklistu", + "blacklistRemoveDm":"Odebrán z blacklistu", + "clear":"Tickety vyčištěny", + "roles":"Role aktualizovány", + + "autoclose":"Ticket automaticky uzavřen", + "autocloseEnabled":"Automatické uzavření povoleno", + "autocloseDisabled":"Automatické uzavření zakázáno", + "autodelete":"Ticket automaticky vymazán", + "autodeleteEnabled":"Automatické mazání povoleno", + "autodeleteDisabled":"Automatické mazání zakázáno" + }, + "descriptions":{ + "create":"Tvůj ticket byl vytvořen. Klikni na tlačítko pod zprávou pro zobrazení!", + "close":"Ticket byl úspěšně uzavřen!", + "delete":"Ticket byl úspěšně vymazán!", + "reopen":"Ticket byl úspěšně znovu otevřen!", + "claim":"Ticket byl úspěšně převzat!", + "unclaim":"Ticket již není převezmut!", + "pin":"Ticket byl úspěšně připnut!", + "unpin":"Ticket byl úspěšně odepnut!", + "rename":"Ticket byl úspěšně přejmenován na {0}!", + "move":"Ticket byl úspěšně přesunut do {0}!", + "add":"{0} byl úspěšně přidán do ticketu!", + "remove":"{0} byl úspěšně odstraněn z ticketu!", + + "helpExplanation":"`` => povinný parametr\n`[name]` => nepovinný parametr", + "statsReset":"Statistiky bota byly úspěšně resetovány!", + "statsError":"Nelze zobrazit statistiky ticketu!\n{0} není ticket!", + "blacklistAdd":"{0} byl přídán na blacklist!", + "blacklistRemove":"{0} byl odebrán z blacklistu!", + "blacklistGetSuccess":"{0} je nyní na blacklistu!", + "blacklistGetEmpty":"{0} nyní není na blacklistu!", + "blacklistViewEmpty":"Na blacklistu ještě nikdo není", + "blacklistViewTip":"Použij \"/blacklist add\" pro přidání uživatele na blacklist!", + "clearVerify":"Opravdu chcete smazat více ticketů?\nTuto akci nelze vrátit zpět!", + "clearReady":"{0} ticketů bylo úspěšně smazány!", + "rolesEmpty":"Žádné role nebyly aktualizovány!", + + "autocloseLeave":"Tento ticket byl automaticky uzavřen, protože jeho autor opustil server.!", + "autocloseTimeout":"Tento ticket byl automaticky uzavřen, protože byl neaktivní déle než `{0}h`!", + "autodeleteLeave":"Tento ticket byl automaticky smazán, protože jeho autor opustil server!", + "autodeleteTimeout":"Tento ticket byl automaticky smazán, protože je neaktivní déle než `{0} dní`!", + "autocloseEnabled":"U tohoto ticketu bylo povoleno automatické uzavření!\nTicket bude uzavřen, pokud bude neaktivní déle než `{0}h`!", + "autocloseDisabled":"U tohoto ticketu bylo vypnuto automatické zavírání!\nUž se nebude automaticky zavírat!", + "autodeleteEnabled":"U tohoto ticketu bylo povoleno automatické mazání!\nBude smazán, pokud je neaktivní déle než `{0} dní`!", + "autodeleteDisabled":"Automatické mazání bylo v tomto zakázáno!\nUž se nebude automaticky mazat!", + + "ticketMessageLimit":"Současně lze vytvořit pouze {0} ticketu!", + "ticketMessageAutoclose":"Tento ticket se automaticky uzavře, pokud je neaktivní po dobu {0}h!", + "ticketMessageAutodelete":"Tento ticket bude automaticky smazán, pokud bude neaktivní po dobu {0} dnů!", + "panelReady":"Panel najdete níže!\nTuto zprávu lze nyní smazat!" + }, + "modal":{ + "closePlaceholder":"Proč jste tento ticket uzavřel?", + "deletePlaceholder":"Proč jste tento ticket smazali?", + "reopenPlaceholder":"Proč jste tento ticket znovu otevřeli?", + "claimPlaceholder":"Proč jste si vyžádal tento ticket?", + "unclaimPlaceholder":"Proč jste zrušili převzetí tohoto ticketu?", + "pinPlaceholder":"Proč jste připnuli tento ticket?", + "unpinPlaceholder":"Proč jste odepnuli tento ticket?" + }, + "logs":{ + "createLog":"Nový ticket byl vytvořen uživatelem {0}!", + "closeLog":"Tento ticket byl uzavřen uživatelem {0}!", + "closeDm":"Tvůj ticket byl uzavřen na našem serveru!", + "deleteLog":"Tento ticket byl smazán uživatelem {0}!", + "deleteDm":"Tvůj ticket byl smazán na našem serveru!", + "reopenLog":"Tento ticket byl znovu otevřen uživatelem {0}!", + "reopenDm":"Tvůj ticket byl znovu otevřen na našem serveru!", + "claimLog":"Tento ticket byl přidělen uživatelem {0}!", + "claimDm":"Tvůj ticket byl přidělen na našem serveru!", + "unclaimLog":"Tento ticket byl odhlášen uživatelem {0}!", + "unclaimDm":"Tvůj ticket byl odhlášen na našem serveru!", + "pinLog":"Tento ticket byl připnut uživatelem {0}!", + "pinDm":"Tvůj ticket byl připnut na našem serveru!", + "unpinLog":"Tento ticket byl odepnut uživatelem {0}!", + "unpinDm":"Tvůj ticket byl odepnut na našem serveru!", + "renameLog":"Tento ticket byl přejmenován na {0} uživatelem {1}!", + "renameDm":"Tvůj ticket byl přejmenován na {0} na našem serveru!", + "moveLog":"Tento ticket byl přesunut do {0} uživatelem {1}!", + "moveDm":"Tvůj ticket byl přesunut do {0} na našem serveru!", + "addLog":"{0} byl přidán do tohoto ticketu uživatelem {1}!", + "addDm":"{0} byl přidán do tvého ticketu na našem serveru!", + "removeLog":"{0} byl odstraněn z tohoto ticketu uživatelem {1}!", + "removeDm":"{0} byl odstraněn z tvého ticketu na našem serveru!", + + "blacklistAddLog":"{0} byl přidán na blacklist uživatelem {1}!", + "blacklistRemoveLog":"{0} byl odstraněn z blacklistu uživatelem {1}!", + "blacklistAddDm":"Byl jsi přidán na blacklist na našem serveru!\nOd teď nemůžeš vytvářet tickety!", + "blacklistRemoveDm":"Byl jsi odstraněn z blacklistu na našem serveru!\nNyní můžeš opět vytvářet tickety!", + "clearLog":"{0} ticketů bylo smazáno uživatelem {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Zobrazit přepis", + "ready":"Přepis vytvořen", + "textFileDescription":"Toto je textový přepis smazaného ticketu!", + "htmlProgress":"Prosím, počkejte, zatímco se zpracovává HTML přepis...", + + "createdChannel":"Na serveru byl vytvořen nový přepis {0}!", + "createdCreator":"Byl vytvořen nový přepis {0} pro jeden z tvých ticketů!", + "createdParticipant":"Byl vytvořen nový přepis {0} v jednom z ticketů, kterých ses účastnil!", + "createdActiveAdmin":"Byl vytvořen nový přepis {0} v jednom z ticketů, kterých ses účastnil jako admin!", + "createdEveryAdmin":"Byl vytvořen nový přepis {0} v jednom z ticketů, kde jsi byl adminem!", + "createdOther":"Byl vytvořen nový přepis {0}!" + }, + "errors":{ + "retry":"Zkusit Znovu", + "continue":"Vymazat bez přepisu", + "backup":"Vytvořit záložní přepis", + "error":"Při pokusu o vytvoření přepisu se něco pokazilo.\nCo chcete udělat?\n\nTento ticket nebude smazán, dokud nekliknete na jedno z těchto tlačítek." + } + }, + "errors":{ + "titles":{ + "internalError":"Interní chyba", + "optionMissing":"Chybějící možnost příkazu", + "optionInvalid":"Neplatná možnost příkazu", + "unknownCommand":"Neznámý příkaz", + "noPermissions":"Nemáš oprávnění", + "unknownTicket":"Neznámý ticket", + "deprecatedTicket":"Zastaralý ticket", + "unknownOption":"Neznámá možnost", + "unknownPanel":"Neznámý panel", + "notInGuild":"Nejsi na serveru", + "channelRename":"Nepodařilo se přejmenovat kanál", + "busy":"Ticket je zaneprázdněn" + }, + "descriptions":{ + "askForInfo":"Pro více informací kontaktuj vlastníka tohoto bota!", + "askForInfoResolve":"Kontaktuj vlastníka tohoto bota, pokud se tento problém nevyřeší po několika pokusech.", + "internalError":"Nepodařilo se odpovědět na tento {0} kvůli interní chybě!", + "optionMissing":"V tomto příkazu chybí požadovaný parametr!", + "optionInvalid":"V tomto příkazu je neplatný parametr!", + "optionInvalidChoose":"Vyber z", + "unknownCommand":"Zkus navštívit nabídku nápovědy pro více informací!", + "noPermissions":"Nemáš oprávnění k použití tohoto {0}!", + "noPermissionsList":"Požadovaná oprávnění: (jedno z nich)", + "noPermissionsCooldown":"Nemáš oprávnění k použití tohoto {0}, protože máš cooldown!", + "noPermissionsBlacklist":"Nemáš oprávnění k použití tohoto {0}, protože jsi byl přidán na blacklist!", + "noPermissionsLimitGlobal":"Nemáš oprávnění vytvořit ticket, protože server dosáhl maximálního limitu ticketů!", + "noPermissionsLimitGlobalUser":"Nemáš oprávnění vytvořit ticket, protože jsi dosáhl maximálního limitu ticketů!", + "noPermissionsLimitOption":"Nemáš oprávnění vytvořit ticket, protože server dosáhl maximálního limitu ticketů pro tuto možnost!", + "noPermissionsLimitOptionUser":"Nemáš oprávnění vytvořit ticket, protože jsi dosáhl maximálního limitu ticketů pro tuto možnost!", + "unknownTicket":"Zkus tento příkaz znovu v platném ticketu!", + "deprecatedTicket":"Aktuální kanál není platný ticket! Může se jednat o ticket ze starší verze Open Ticketu!", + "notInGuild":"Tento {0} nefunguje v DM! Zkus to znovu na serveru!", + "channelRename":"Kvůli ratelimitům Discordu není momentálně možné, aby bot přejmenoval kanál. Kanál bude automaticky přejmenován do 10 minut, pokud nedojde k restartu bota.", + "channelRenameSource":"Zdroj této chyby je: {0}", + "busy":"Nelze použít tento {0}!\nTicket je momentálně zpracováván botem.\n\nZkus to prosím znovu za několik sekund!" + }, + "optionInvalidReasons":{ + "stringRegex":"Hodnota neodpovídá vzoru!", + "stringMinLength":"Hodnota musí mít alespoň {0} znaků!", + "stringMaxLength":"Hodnota může mít maximálně {0} znaků!", + "numberInvalid":"Neplatné číslo!", + "numberMin":"Číslo musí být alespoň {0}!", + "numberMax":"Číslo může být maximálně {0}!", + "numberDecimal":"Číslo nesmí být desetinné!", + "numberNegative":"Číslo nesmí být záporné!", + "numberPositive":"Číslo nesmí být kladné!", + "numberZero":"Číslo nesmí být nula!", + "channelNotFound":"Nelze najít kanál!", + "userNotFound":"Nelze najít uživatele!", + "roleNotFound":"Nelze najít roli!", + "memberNotFound":"Nelze najít uživatele!", + "mentionableNotFound":"Nelze najít uživatele nebo roli!", + "channelType":"Neplatný typ kanálu!", + "notInGuild":"Tato možnost vyžaduje, abys byl na serveru!" + }, + "permissions":{ + "developer":"Musíš být vývojářem tohoto bota.", + "owner":"Musíš být vlastníkem serveru.", + "admin":"Musíš být adminem serveru.", + "moderator":"Musíš být moderátorem.", + "support":"Musíš být členem týmu podpory.", + "member":"Musíš být členem.", + "discord-administrator":"Musíš mít oprávnění `ADMINISTRATOR`." + }, + "actionInvalid":{ + "close":"Ticket je již uzavřený!", + "reopen":"Ticket ještě není uzavřený!", + "claim":"Ticket je již přidělený!", + "unclaim":"Ticket ještě není přidělený!", + "pin":"Ticket je již připnutý!", + "unpin":"Ticket ještě není připnutý!", + "add":"Tento uživatel už má k ticketu přístup!", + "remove":"Tohoto uživatele nelze z ticketu odstranit!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickety", + "reason":"Důvod", + "creator":"Tvůrce", + "remaining":"Zbývající čas", + "added":"Přidáno", + "removed":"Odstraněno", + "filter":"Filtr", + "claimedBy":"Přiděleno uživatelem {0}", + "method":"Metoda", + "type":"Typ", + "blacklisted":"Na blacklistu", + "panel":"Panel", + "command":"Příkaz", + "system":"Systém", + "true":"true", + "false":"false", + "syntax":"Syntaxe", + "originalName":"Původní jméno", + "newName":"Nové jméno", + "until":"Do", + "validOptions":"Platné možnosti", + "validPanels":"Platné panely", + "autoclose":"Automatické uzavření", + "autodelete":"Automatické smazání", + "startupDate":"Datum spuštění", + "version":"Verze", + "name":"Jméno", + "role":"Role", + "status":"Stav", + "claimed":"Přiděleno", + "pinned":"Připnuto", + "creationDate":"Datum vytvoření" + }, + "lowercase":{ + "text":"text", + "html":"html", + "command":"příkaz", + "modal":"modal", + "button":"tlačítko", + "dropdown":"roletka", + "method":"metoda" + } + }, + "commands":{ + "reason":"Zadej nepovinný důvod, který bude viditelný v logu.", + "help":"Získej seznam všech dostupných příkazů.", + "panel":"Vytvoř zprávu s roletkou nebo tlačítky (pro vytvoření ticketu).", + "panelId":"Identifikátor panelu, který chceš vytvořit.", + "panelAutoUpdate":"Chceš, aby se tento panel automaticky aktualizoval při úpravách?", + "ticket":"Okamžitě vytvoř ticket.", + "ticketId":"Identifikátor ticketu, který chceš vytvořit.", + "close":"Uzavři ticket.", + "delete":"Smaž ticket.", + "deleteNoTranscript":"Smaž tento ticket bez vytvoření přepisu.", + "reopen":"Znovu otevři ticket.", + "claim":"Přiděl ticket.", + "claimUser":"Přiděl tento ticket někomu jinému místo sebe.", + "unclaim":"Odeber přidělení ticketu.", + "pin":"Připni ticket.", + "unpin":"Odepni ticket.", + "move":"Přesuň ticket.", + "moveId":"Identifikátor možnost, na který chceš přesunout.", + "rename":"Přejmenuj ticket.", + "renameName":"Nový název pro tento ticket.", + "add":"Přidej uživatele k ticketu.", + "addUser":"Uživatel k přidání.", + "remove":"Odstraň uživatele z ticketu.", + "removeUser":"Uživatel k odstranění.", + "blacklist":"Spravuj blacklist ticketů.", + "blacklistView":"Zobraz seznam aktuálního blacklistu.", + "blacklistAdd":"Přidej uživatele na blacklist.", + "blacklistRemove":"Odstraň uživatele z blacklistu.", + "blacklistGet":"Získej detaily o uživateli na blacklistu.", + "blacklistGetUser":"Uživatel, o kterém chceš získat detaily.", + "stats":"Zobraz statistiky bota, člena nebo ticketu.", + "statsReset":"Resetuj všechny statistiky bota (a začni počítat od nuly).", + "statsGlobal":"Zobraz globální statistiky.", + "statsUser":"Zobraz statistiky uživatele na serveru.", + "statsUserUser":"Uživatel, jehož statistiky chceš zobrazit.", + "statsTicket":"Zobraz statistiky ticketu na serveru.", + "statsTicketTicket":"Ticket, jehož statistiky chceš zobrazit.", + "clear":"Smaž více ticketů najednou. Lze zadat volitelný filtr.", + "clearFilter":"Filtr pro vymazání tiketů.", + "clearFilters":{ + "all":"Vše", + "open":"Otevřené", + "close":"Uzavřené", + "claim":"Přidělené", + "unclaim":"Nepřidělené", + "pin":"Připnuté", + "unpin":"Nepřipnuté", + "autoclose":"Automaticky uzavřené" + }, + "autoclose":"Spravuj automatické uzavření ticketu.", + "autocloseDisable":"Deaktivuj automatické uzavření v tomto ticketu.", + "autocloseEnable":"Aktivuj automatické uzavření v tomto ticketu.", + "autocloseEnableTime":"Počet hodin neaktivity, po kterých se ticket uzavře.", + "autodelete":"Spravuj automatické smazání ticketu.", + "autodeleteDisable":"Deaktivuj automatické smazání v tomto ticketu.", + "autodeleteEnable":"Aktivuj automatické smazání v tomto ticketu.", + "autodeleteEnableTime":"Počet dnů neaktivity, po kterých se ticket smaže." + }, + "helpMenu":{ + "help":"Získej seznam všech dostupných příkazů.", + "ticket":"Okamžitě vytvoř ticket.", + "close":"Uzavři ticket, čímž se zakáže psaní v tomto kanálu.", + "delete":"Smaž ticket, čímž se vytvoří přepis, pokud je to povoleno.", + "reopen":"Znovu otevři ticket, což opět umožní psaní v tomto kanálu.", + "pin":"Připni ticket. Tento ticket se přesune na začátek a bude mít ve jménu emoji '📌'.", + "unpin":"Odepni ticket. Ticket zůstane na svém místě, ale ztratí emoji '📌'.", + "move":"Přesuň ticket. Tím se změní typ tohoto ticketu.", + "rename":"Přejmenuj ticket. Tím se změní název kanálu tohoto ticketu.", + "claim":"Přiděl ticket. Tím dáš svému týmu najevo, že tento ticket řešíš.", + "unclaim":"Odeber přidělení ticketu. Tím dáš svému týmu najevo, že je tento ticket znovu volný.", + "add":"Přidej uživatele k ticketu. Tímto uživateli umožníš číst a psát v tomto ticketu.", + "remove":"Odstraň uživatele z ticketu. Tímto uživateli odebereš možnost číst a psát v tomto ticketu.", + "panel":"Vytvoř zprávu s roletkou nebo tlačítky (pro vytvoření ticketu).", + "blacklistView":"Zobraz seznam aktuálního blacklistu.", + "blacklistAdd":"Přidej uživatele na blacklist.", + "blacklistRemove":"Odstraň uživatele z blacklistu.", + "blacklistGet":"Získej detaily o uživateli na blacklistu.", + "statsGlobal":"Zobraz globální statistiky.", + "statsTicket":"Zobraz statistiky ticketu na serveru.", + "statsUser":"Zobraz statistiky uživatele na serveru.", + "statsReset":"Resetuj všechny statistiky bota (a začni počítat od nuly).", + "autocloseDisable":"Deaktivuj automatické uzavření v tomto ticketu.", + "autocloseEnable":"Aktivuj automatické uzavření v tomto ticketu.", + "autodeleteDisable":"Deaktivuj automatické smazání v tomto ticketu.", + "autodeleteEnable":"Aktivuj automatické smazání v tomto ticketu." + }, + "stats":{ + "scopes":{ + "global":"Globální statistiky", + "system":"Statistiky systému", + "user":"Statistiky uživatele", + "ticket":"Statistiky ticketu", + "participants":"Účastníci" + }, + "properties":{ + "ticketsCreated":"Vytvořené tickety", + "ticketsClosed":"Uzavřené tickety", + "ticketsDeleted":"Smazané tickety", + "ticketsReopened":"Znovu otevřené tickety", + "ticketsAutoclosed":"Automaticky uzavřené tickety", + "ticketsClaimed":"Přidělené tickety", + "ticketsPinned":"Připnuté tickety", + "ticketsMoved":"Přesunuté tickety", + "usersBlacklisted":"Uživatelé na blacklistu", + "transcriptsCreated":"Vytvořené přepisy" + } + } +} \ No newline at end of file diff --git a/languages/dutch.json b/languages/dutch.json new file mode 100644 index 0000000..fa3b14d --- /dev/null +++ b/languages/dutch.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"DJj123dj", + "lastedited":"21/08/2024", + "language":"Dutch" + }, + "checker":{ + "system":{ + "typeError":"[ERROR]", + "headerOpenTicket":"OPEN TICKET", + "typeWarning":"[WAARSCHUWING]", + "typeInfo":"[INFO]", + "headerConfigChecker":"CONFIG CHECKER", + "headerDescription":"check voor errors in je config bestanden!", + "footerError":"de bot start niet tot alle {0}'s opgelost zijn!", + "footerWarning":"het is aangeraden om alle {0}'en op te lossen voor het starten!", + "footerSupport":"SUPPORT: {0} - DOCS: {1}", + "compactInformation":"gebruik {0} voor meer informatie!", + "dataPath":"pad", + "dataDocs":"docs", + "dataMessages":"bericht" + }, + "messages":{ + "stringTooShort":"Deze tekst kan niet korter dan {0} karakters zijn!", + "stringTooLong":"Deze tekst kan niet langer dan {0} karakters zijn!", + "stringLengthInvalid":"Deze tekst moet {0} karakters lang zijn!", + "stringStartsWith":"Deze tekst moet starten met {0}!", + "stringEndsWith":"Deze tekst moet eindigen met {0}!", + "stringContains":"Deze tekst moet {0} bevatten!", + "stringChoices":"Deze tekst kan alleen de volgende waardes bevatten: {0}!", + "stringRegex":"Deze tekst is ongeldig!", + + "numberTooShort":"Dit nummer kan niet korter dan {0} karakters zijn!", + "numberTooLong":"Dit nummer kan niet langer dan {0} karakters zijn!", + "numberLengthInvalid":"Dit nummer moet {0} karakters lang zijn!", + "numberTooSmall":"Dit nummer moet minimum {0} zijn!", + "numberTooLarge":"Dit nummer kan maximum {0} zijn!", + "numberNotEqual":"Dit nummer moet gelijk zijn aan {0}!", + "numberStep":"Dit nummer moet een meervoud zijn van {0}!", + "numberStepOffset":"Dit nummer moet een meervoud zijn van {0} startend bij {1}!", + "numberStartsWith":"Dit nummer moet starten met {0}!", + "numberEndsWith":"Dit nummer moet eindigen met {0}!", + "numberContains":"Dit nummer moet {0} bevatten!", + "numberChoices":"Dit nummer kan alleen een van de volgende waardes bevatten: {0}!", + "numberFloat":"Dit nummer kan geen kommagetal zijn!", + "numberNegative":"Dit nummer kan niet negatief zijn!", + "numberPositive":"Dit nummer kan niet positief zijn!", + "numberZero":"Dit nummer kan niet nul zijn!", + + "booleanTrue":"Deze boolean kan niet true zijn!", + "booleanFalse":"Deze boolean kan niet false zijn!", + + "arrayEmptyDisabled":"Deze array mag niet leeg zijn!", + "arrayEmptyRequired":"Deze array moet leeg zijn!", + "arrayTooShort":"Deze array moet een minimum lengte hebben van {0}!", + "arrayTooLong":"Deze array mag niet langer zijn dan {0}!", + "arrayLengthInvalid":"Deze array moet een lengte hebben van {0}!", + "arrayInvalidTypes":"Deze array kan alleen de volgende waardes bevatten: {0}!", + "arrayDouble":"Deze array staat dubbele waardes niet toe!", + + "discordInvalidId":"Dit is een ongeldig discord {0} id!", + "discordInvalidIdOptions":"Dit is an ongeldig discord {0} id! Je kan ook een van deze gebruiken: {1}!", + "discordInvalidToken":"Dit is een ongeldig discord token (syntactisch)!", + "colorInvalid":"Dit is een ongeldig hex kleur!", + "emojiTooShort":"Deze tekst moet minimum {0} emoji's hebben!", + "emojiTooLong":"Deze tekst mag maximum {0} emoji's hebben!", + "emojiCustom":"Deze emoji kan geen custom discord emoji zijn!", + "emojiInvalid":"Dit is een ongeldige emoji!", + "urlInvalid":"Deze url is ongeldig!", + "urlInvalidHttp":"Deze url kan alleen het https:// protocol gebruiken!", + "urlInvalidProtocol":"Deze url kan alleen de http:// & https:// protocolen gebruiken!", + "urlInvalidHostname":"Deze url heeft een verboden hostnaam (domein)!", + "urlInvalidExtension":"Deze url heeft een ongeldige extensie! Kies tussen: {0}!", + "urlInvalidPath":"Deze url heeft een ongeldig pad!", + "idNotUnique":"Dit id is niet uniek, gebruik een andere in de plaats!", + "idNonExistent":"Het id {0} bestaat niet!", + + "invalidType":"Het type van deze property moet gelijk zijn aan: {0}!", + "propertyMissing":"De property {0} mist in dit object!", + "propertyOptional":"De property {0} is optioneel in dit object!", + "objectDisabled":"Dit object is uitgeschakeld, gebruik het met behulp van {0}!", + "nullInvalid":"Deze property kan niet null zijn!", + "switchInvalidType":"Dit moet een van de volgende types zijn: {0}!", + "objectSwitchInvalid":"Dit object moet een van de volgende types zijn: {0}!", + + "invalidLanguage":"Dit is een ongeldige taal!", + "invalidButton":"Deze knop moet een {0} of {1} hebben!", + "unusedOption":"De optie {0} wordt nergens gebruikt!", + "unusedQuestion":"The vraag {0} wordt nergens gebruikt!", + "dropdownOption":"Een paneel met dropdown mag alleen opties bevaten van het 'ticket' type!" + } + }, + "actions":{ + "buttons":{ + "create":"Bekijk Ticket", + "close":"Sluit Ticket", + "delete":"Verwijder Ticket", + "reopen":"Heropen Ticket", + "claim":"Claim Ticket", + "unclaim":"Ontclaim Ticket", + "pin":"Pin Ticket", + "unpin":"Maak Ticket Los", + "clear":"Verwijder Tickets", + "helpSwitchSlash":"Bekijk Slash Commands", + "helpSwitchText":"Bekijk Text Commands", + "helpPage":"Pagina {0}", + "withReason":"Met Reden", + "withoutTranscript":"Zonder Transcript" + }, + "titles":{ + "created":"Ticket Gecreëerd", + "close":"Ticket Gesloten", + "delete":"Ticket Verwijderd", + "reopen":"Ticket Heropend", + "claim":"Ticket Geclaimd", + "unclaim":"Ticket Ontclaimd", + "pin":"Ticket Gepind", + "unpin":"Ticket Losgemaakt", + "rename":"Ticket Hernoemd", + "move":"Ticket Verplaatst", + "add":"Ticket Gebruiker Toegevoegd", + "remove":"Ticket Gebruiker Verwijderd", + + "help":"Beschikbare Commands", + "statsReset":"Reset Stats", + "blacklistAdd":"Gebruiker Geblacklisted", + "blacklistRemove":"Gebruiker Vrijgelaten", + "blacklistGet":"Geblackliste Gebruiker", + "blacklistView":"Huidige Blacklist", + "blacklistAddDm":"Toegevoegd Aan Blacklist", + "blacklistRemoveDm":"Verwijderd Van Blacklist", + "clear":"Tickets Opgeruimd", + "roles":"Rollen Bijgewerkt", + + "autoclose":"Ticket Automatisch Gesloten", + "autocloseEnabled":"Autoclose Ingeschakeld", + "autocloseDisabled":"Autoclose Uitgeschakeld", + "autodelete":"Ticket Automatisch Verwijderd", + "autodeleteEnabled":"Autodelete Ingeschakeld", + "autodeleteDisabled":"Autodelete Uitgeschakeld" + }, + "descriptions":{ + "create":"Je ticket is aangemaakt. Klik op de knop hier onder om er naar toe te gaan!", + "close":"Het ticket is succesvol gesloten!", + "delete":"Het ticket is succesvol verwijderd!", + "reopen":"Het ticket is succesvol heropend!", + "claim":"Het ticket is succesvol geclaimd!", + "unclaim":"Het ticket is succesvol ontclaimd!", + "pin":"Het ticket is succesvol gepind!", + "unpin":"Het ticket is succesvol losgemaakt!", + "rename":"Het ticket is succesvol hernoemd naar {0}!", + "move":"Het ticket is succesvol verplaatst naar {0}!", + "add":"{0} is succesvol toegevoegd aan het ticket!", + "remove":"{0} is succesvol verwijderd van het ticket!", + + "helpExplanation":"`` => verplichte parameter\n`[naam]` => optionele parameter", + "statsReset":"De bot stats zijn succesvol gereset!", + "statsError":"Kan ticket stats niet bekijken!\n{0} is geen ticket!", + "blacklistAdd":"{0} is succesvol geblacklist!", + "blacklistRemove":"{0} is succesvol vrijgelaten!", + "blacklistGetSuccess":"{0} is op dit moment geblacklist!", + "blacklistGetEmpty":"{0} is op dit moment niet geblacklist!", + "blacklistViewEmpty":"Nog niemand is geblacklist!", + "blacklistViewTip":"Gebruik \"/blacklist add\" om een gebruiker te blacklisten!", + "clearVerify":"Weet je zeker dat je meerdere tickets wilt verwijderen? Deze actie kan niet teruggedraaid worden!", + "clearReady":"{0} tickets zijn succesvol verwijderd!", + "rolesEmpty":"Geen enkele rollen zijn bijgewerkt!", + + "autocloseLeave":"Dit ticket is automatisch gesloten omdat de maker de server verlaten is!", + "autocloseTimeout":"Dit ticket is automatisch gesloten omdat het inactief was voor meer dan `{0} uur`!", + "autodeleteLeave":"Dit ticket is automatisch verwijderd omdat de maker de server verlaten is!", + "autodeleteTimeout":"Dit ticket is automatisch verwijderd omdat het inactief was voor meer dan `{0} dagen`!", + "autocloseEnabled":"Autoclose is ingeschakeld in dit ticket!\nHet wordt gesloten wanneer het inactief is voor meer dan `{0} uur`!", + "autocloseDisabled":"Autoclose is uitgeschakeld in dit ticket!\nHet wordt niet meer automatisch gesloten!", + "autodeleteEnabled":"Autodelete is ingeschakeld in dit ticket!\nHet wordt verwijderd wanneer het inactief is voor meer dan `{0} dagen`!", + "autodeleteDisabled":"Autodelete is uitgeschakeld in dit ticket!\nHet wordt niet meer automatisch verwijderd!", + + "ticketMessageLimit":"Je kan maar {0} ticket(s) op het zelfde moment aanmaken!", + "ticketMessageAutoclose":"Dit ticket wordt automatisch gesloten wanneer het inactief is voor {0} uur!", + "ticketMessageAutodelete":"Dit ticket wordt automatisch verwijderd wanneer het inactief is voor {0} dagen!", + "panelReady":"Je kan het paneel hier onder vinden!\nDit bericht kan nu verwijderd worden!" + }, + "modal":{ + "closePlaceholder":"Waarom heb je dit ticket gesloten?", + "deletePlaceholder":"Waarom heb je dit ticket verwijderd?", + "reopenPlaceholder":"Waarom heb je dit ticket heropend?", + "claimPlaceholder":"Waarom heb je dit ticket geclaimd?", + "unclaimPlaceholder":"Waarom heb je dit ticket ontclaimd?", + "pinPlaceholder":"Waarom heb je dit ticket gepind?", + "unpinPlaceholder":"Waarom heb je dit ticket losgemaakt?" + }, + "logs":{ + "createLog":"Een nieuw ticket is aangemaakt door {0}!", + "closeLog":"Dit ticket is gesloten door {0}!", + "closeDm":"Jouw ticket is gesloten in onze server!", + "deleteLog":"Dit ticket is verwijderd door {0}!", + "deleteDm":"Jouw ticket is verwijderd in onze server!", + "reopenLog":"Dit ticket is heropend door {0}!", + "reopenDm":"Jouw ticket is heropend in onze server!", + "claimLog":"Dit ticket is geclaimd door {0}!", + "claimDm":"Jouw ticket is geclaimd in onze server!", + "unclaimLog":"Dit ticket is ontclaimd door {0}!", + "unclaimDm":"Jouw ticket is ontclaimd in onze server!", + "pinLog":"Dit ticket is gepind door {0}!", + "pinDm":"Jouw ticket is gepind in onze server!", + "unpinLog":"Dit ticket is losgemaakt door {0}!", + "unpinDm":"Jouw ticket is losgemaakt in onze server!", + "renameLog":"Dit ticket is hernoemd naar {0} door {1}!", + "renameDm":"Jouw ticket is hernoemd naar {0} in onze server!", + "moveLog":"Dit ticket is verplaatst naar {0} door {1}!", + "moveDm":"Jouw ticket is verplaatst naar {0} in onze server!", + "addLog":"{0} is toegevoegd aan dit ticket door {1}!", + "addDm":"{0} is toegevoegd aan jouw ticket in onze server!", + "removeLog":"{0} is verwijderd van dit ticket door {1}!", + "removeDm":"{0} is verwijderd van jouw ticket in onze server!", + + "blacklistAddLog":"{0} is geblacklist door {1}!", + "blacklistRemoveLog":"{0} is verwijderd van de blacklist door {1}!", + "blacklistAddDm":"Je bent geblacklist in onze server!\nVanaf nu kan je geen tickets meer aanmaken!", + "blacklistRemoveDm":"Je bent verwijderd van de blacklist in onze server!\nNormaal zou je nu terug tickets kunnen aanmaken!", + "clearLog":"{0} tickets zijn verwijderd door by {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Bekijk Transcript", + "ready":"Transcript Aangemaakt", + "textFileDescription":"Dit is een tekst transcript van een verwijderd ticket!", + "htmlProgress":"Gelieve te wachten terwijl dit html transcript verwerkt wordt...", + + "createdChannel":"Een nieuw {0} transcript is aangemaakt in de server!", + "createdCreator":"Een nieuw {0} transcript is aangemaakt voor een van jouw tickets!", + "createdParticipant":"Een nieuw {0} transcript is aangemaakt in een van de tickets waar jij lid van was!", + "createdActiveAdmin":"Een nieuw {0} transcript is aangemaakt in een van de tickets waar jij een actieve admin was!", + "createdEveryAdmin":"Een nieuw {0} transcript is aangemaakt in een van de tickets waar jij admin was!", + "createdOther":"Een nieuw {0} transcript is aangemaakt!" + }, + "errors":{ + "retry":"Herprobeer", + "continue":"Verwijder Zonder Transcript", + "backup":"Maak Backup Transcript", + "error":"Er is iets misgegaan bij het maken van het transcript.\nWat wil je doen?\n\nDit ticket wordt niet meer verwijderd to je een van de onderstaande knoppen gebruikt." + } + }, + "errors":{ + "titles":{ + "internalError":"Interne Error", + "optionMissing":"Missende Command Optie", + "optionInvalid":"Onjuiste Command Optie", + "unknownCommand":"Onbekende Command", + "noPermissions":"Geen Permissies", + "unknownTicket":"Onbekend Ticket", + "deprecatedTicket":"Verouderd Ticket", + "unknownOption":"Onbekende Optie", + "unknownPanel":"Onbekend Paneel", + "notInGuild":"Niet In Server", + "channelRename":"Kan Kanaal Niet Hernoemen", + "busy":"Ticket Is Bezig" + }, + "descriptions":{ + "askForInfo":"Contacteer the eigenaar van deze bot voor meer info!", + "askForInfoResolve":"Contacteer de eigenaar van deze bot als het probleem niet opgelost wordt na enkele keren.", + "internalError":"Gefaald om te reageren op deze {0} door een interne error!", + "optionMissing":"Een verplichte parameter mist in deze command!", + "optionInvalid":"Een parameter in deze command is ongeldig!", + "optionInvalidChoose":"Kies tussen", + "unknownCommand":"Probeer het help menu te bekijken voor meer info!", + "noPermissions":"Je bent niet toegestaan om deze {0} te gebruiken!", + "noPermissionsList":"Benodigde Permissies: (één van deze)", + "noPermissionsCooldown":"Je bent niet toegestaan om deze {0} te gebruiken omdat je een cooldown hebt!", + "noPermissionsBlacklist":"Je bent niet toegestaan om deze {0} te gebruiken omdat je geblacklist bent!", + "noPermissionsLimitGlobal":"Je bent niet toegestaan om een ticket aan te maken omdat de server het maximum tickets limiet heeft bereikt!", + "noPermissionsLimitGlobalUser":"Je bent niet toegestaan om een ticket aan te maken omdat je het maximum tickets limiet hebt bereikt!", + "noPermissionsLimitOption":"Je bent niet toegestaan om een ticket aan te maken omdat de server het maximum tickets limiet van deze optie heeft bereikt!", + "noPermissionsLimitOptionUser":"Je bent niet toegestaan om een ticket aan te maken omdat je het maximum tickets limiet van deze optie hebt bereikt!", + "unknownTicket":"Probeer deze command opnieuw in een geldig ticket!", + "deprecatedTicket":"Het huidige kanaal is geen geldig ticket! Het is misschien een ticket van een oudere Open Ticket versie!", + "notInGuild":"Deze {0} werkt niet in DM! Probeer het opnieuw in een server!", + "channelRename":"Door discord ratelimits is het op dit moment onmogelijk voor de bot om het kanaal te hernoemen. Het kanaal zal automatisch hernoemd worden over 10 min als de bot niet herstart wordt.", + "channelRenameSource":"De bron van deze error is: {0}", + "busy":"Kan deze {0} niet gebruiken!\nHet ticket wordt op dit moment verwerkt door de bot.\n\nProbeer het opnieuw binnen een paar seconden!" + }, + "optionInvalidReasons":{ + "stringRegex":"Waarde is niet gelijk aan het patroon!", + "stringMinLength":"Waarde moet minstens {0} karakters hebben!", + "stringMaxLength":"Waarde moet maximum {0} karakters hebben!", + "numberInvalid":"Ongeldig nummer!", + "numberMin":"Nummer moet minstens {0} zijn!", + "numberMax":"Nummer moet maximum {0} zijn!", + "numberDecimal":"Nummer kan geen kommagetal zijn!", + "numberNegative":"Nummer mag niet negatief zijn!", + "numberPositive":"Nummer mag niet positief zijn!", + "numberZero":"Nummer mag niet nul zijn!", + "channelNotFound":"Kan kanaal niet vinden!", + "userNotFound":"Kan gebruiker niet vinden!", + "roleNotFound":"Kan rol niet vinden!", + "memberNotFound":"Kan gebruiker niet vinden!", + "mentionableNotFound":"Kan gebruiker of rol niet vinden!", + "channelType":"Ongeldig kanaal type!", + "notInGuild":"Voor deze optie moet je in een server zitten!" + }, + "permissions":{ + "developer":"Je moet de ontwikkelaar van de bot zijn.", + "owner":"Je moet de server eigenaar zijn.", + "admin":"Je moet een server admin zijn.", + "moderator":"Je moet een server moderator zijn.", + "support":"Je moet in het support team zitten.", + "member":"Je moet een member van de server zijn.", + "discord-administrator":"Je hebt de `ADMINISTRATOR` permissie nodig." + }, + "actionInvalid":{ + "close":"Ticket is al gesloten!", + "reopen":"Ticket is nog niet gesloten!", + "claim":"Ticket is al geclaimd!", + "unclaim":"Ticket nog niet geclaimd!", + "pin":"Ticket is al gepind!", + "unpin":"Ticket nog niet gepind!", + "add":"Deze gebruiker heeft al toegang tot dit ticket!", + "remove":"Deze gebruiker kan niet verwijderd worden van dit ticket!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickets", + "reason":"Reden", + "creator":"Maker", + "remaining":"Resterende Tijd", + "added":"Toegevoegd", + "removed":"Verwijderd", + "filter":"Filter", + "claimedBy":"Geclaimd Door {0}", + "method":"Methode", + "type":"Type", + "blacklisted":"Geblacklist", + "panel":"Paneel", + "command":"Command", + "system":"Systeem", + "true":"Waar", + "false":"Onwaar", + "syntax":"Syntax", + "originalName":"Originele Naam", + "newName":"Nieuwe Naam", + "until":"Tot", + "validOptions":"Geldige Opties", + "validPanels":"Geldige Panelen", + "autoclose":"Autoclose", + "autodelete":"Autodelete", + "startupDate":"Opstart Datum", + "version":"Versie", + "name":"Naam", + "role":"Rol", + "status":"Status", + "claimed":"Geclaimd", + "pinned":"Gepind", + "creationDate":"Aanmaakdatum" + }, + "lowercase":{ + "text":"tekst", + "html":"html", + "command":"command", + "modal":"form", + "button":"knop", + "dropdown":"dropdown", + "method":"methode" + } + }, + "commands":{ + "reason":"Specifieer een optionele reden die zichtbaar is in de logs.", + "help":"Verkrijg een lijst met alle beschikbare commands.", + "panel":"Spawn een bericht met een dropdown of knoppen (voor ticket creatie).", + "panelId":"Het id van het paneel dat je wilt spawnen.", + "panelAutoUpdate":"Wil je dat dit paneel automatisch bijwerkt wanneer het aangepast wordt?", + "ticket":"Maak een instant ticket.", + "ticketId":"Het id van het ticket dat je wilt aanmaken.", + "close":"Sluit een ticket, dit schakelt schrijven in het kanaal uit.", + "delete":"Verwijder een ticket, dit maakt een transcript waneer ingeschakeld.", + "deleteNoTranscript":"Verwijder dit ticket zonder een transcript aan te maken.", + "reopen":"Heropen een ticket, dit schakelt schrijven in het kanaal terug aan.", + "claim":"Claim een ticket.", + "claimUser":"Claim dit ticket voor iemand anders.", + "unclaim":"Ontclaim dit ticket.", + "pin":"Pin dit ticket.", + "unpin":"Maak dit ticket los.", + "move":"Verplaats een ticket.", + "moveId":"Het id van de optie waarnaar je wilt verplaatsen.", + "rename":"Hernoem een ticket.", + "renameName":"De nieuwe naam voor dit ticket.", + "add":"Voeg een gebruiker toe aan dit ticket.", + "addUser":"De gebruiker om toe te voegen.", + "remove":"Verwijder een user van dit ticket.", + "removeUser":"De gebruiker om te verwijderen.", + "blacklist":"Beheer de ticket blacklist.", + "blacklistView":"Bekijk de huidige blacklist.", + "blacklistAdd":"Voeg een gebruiker toe aan de blacklist.", + "blacklistRemove":"Verwijder een gebruiker van de blacklist.", + "blacklistGet":"Verkrijg de details van een geblackliste gebruiker.", + "blacklistGetUser":"De gebruiker om details van te verkrijgen.", + "stats":"Bekijk statistieken van de bot, een gebruiker of ticket.", + "statsReset":"Reset alle stats van de bot (en begin terug bij nul).", + "statsGlobal":"Bekijk de globale stats.", + "statsUser":"Bekijk de stats van een gebruiker in de server.", + "statsUserUser":"De gebruiker om te bekijken.", + "statsTicket":"Bekijk de stats van een ticket in de server.", + "statsTicketTicket":"Het ticket om te bekijken.", + "clear":"Verwijder meerdere tickets tegelijkertijd.", + "clearFilter":"De filter om tickets op te ruimen.", + "clearFilters":{ + "all":"Allemaal", + "open":"Open (niet gesloten)", + "close":"Gesloten", + "claim":"Geclaimd", + "unclaim":"Ontclaimd (niet geclaimd)", + "pin":"Gepind", + "unpin":"Losgemaakt (niet gepind)", + "autoclose":"Automatisch Gesloten" + }, + "autoclose":"Beheer autoclose in een ticket.", + "autocloseDisable":"Schakel autoclose in dit ticket uit.", + "autocloseEnable":"Schakel autoclose in dit ticket in.", + "autocloseEnableTime":"De hoeveelheid uren dat dit ticket inactief moet zijn voor het te sluiten.", + "autodelete":"Beheer autodelete in een ticket.", + "autodeleteDisable":"Schakel autodelete in dit ticket aan.", + "autodeleteEnable":"Schakel autodelete in dit ticket aan.", + "autodeleteEnableTime":"De hoeveelheid dagen dat dit ticket inactief moet zijn voor het te verwijderen." + }, + "helpMenu":{ + "help":"Krijg een lijst van alle beschikbare commands.", + "ticket":"Maak een instant ticket.", + "close":"Sluit een ticket, dit schakelt schrijven in het kanaal uit.", + "delete":"Verwijder een ticket, dit maakt een transcript wanneer ingeschakeld.", + "reopen":"Heropen een ticket, dit schakeld schrijven in het kanaal terug aan.", + "pin":"Pin een ticket. Dit verplaatst het ticket naar boven & voegt een '📌' emoij toe.", + "unpin":"Maak een ticket los. Het ticket zal blijven staan, maar de '📌' emoij verliezen.", + "move":"Verplaats een ticket. Dit verandert het soort van dit ticket.", + "rename":"Hernoem een ticket. Dit zal de kanaalnaam veranderen.", + "claim":"Claim een ticket. Hiermee kan je laten weten dat je bezig bent met dit ticket.", + "unclaim":"Ontclaim een ticket. Hiermee kan je laten weten dat het ticket terug vrij is.", + "add":"Voeg een user toe aan een ticket.", + "remove":"Verwijder een user van een ticket.", + "panel":"Spawn een bericht met dropdown of knoppen.", + "blacklistView":"Bekijk een lijst van de huidige blacklist.", + "blacklistAdd":"Voeg een user toe aan de blacklist.", + "blacklistRemove":"Verwijder een user van de blacklist.", + "blacklistGet":"Verkrijg de details van een geblacklisted user.", + "statsGlobal":"Bekijk de globale stats.", + "statsTicket":"Bekijk de stats van een ticket in de server.", + "statsUser":"Bekijk de stats van een user in de server.", + "statsReset":"Reset alle stats van de bot (en begin terug vanaf 0).", + "autocloseDisable":"Zet autoclose uit in dit ticket.", + "autocloseEnable":"Zet autoclose in aan dit ticket.", + "autodeleteDisable":"Zet autodelete uit in dit ticket.", + "autodeleteEnable":"Zet autodelete aan in dit ticket." + }, + "stats":{ + "scopes":{ + "global":"Globale Stats", + "system":"Systeem Stats", + "user":"User Stats", + "ticket":"Ticket Stats", + "participants":"Deelnemers" + }, + "properties":{ + "ticketsCreated":"Tickets Aangemaakt", + "ticketsClosed":"Tickets Gesloten", + "ticketsDeleted":"Tickets Verwijderd", + "ticketsReopened":"Tickets Heropend", + "ticketsAutoclosed":"Tickets Autoclosed", + "ticketsClaimed":"Tickets Geclaimd", + "ticketsPinned":"Tickets Gepind", + "ticketsMoved":"Tickets Verplaatst", + "usersBlacklisted":"Users Geblacklist", + "transcriptsCreated":"Transcripts Aangemaakt" + } + } +} \ No newline at end of file diff --git a/languages/english.json b/languages/english.json new file mode 100644 index 0000000..d73991b --- /dev/null +++ b/languages/english.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"DJj123dj", + "lastedited":"21/08/2024", + "language":"English" + }, + "checker":{ + "system":{ + "typeError":"[ERROR]", + "headerOpenTicket":"OPEN TICKET", + "typeWarning":"[WARNING]", + "typeInfo":"[INFO]", + "headerConfigChecker":"CONFIG CHECKER", + "headerDescription":"check for errors in you 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":"This string can't be shorter than {0} characters!", + "stringTooLong":"This string can't be longer than {0} characters!", + "stringLengthInvalid":"This string needs to be {0} characters long!", + "stringStartsWith":"This string needs to start with {0}!", + "stringEndsWith":"This string needs to end with {0}!", + "stringContains":"This string needs to contain {0}!", + "stringChoices":"This string can only be one of the following values: {0}!", + "stringRegex":"This string is invalid!", + + "numberTooShort":"This number can't be shorter than {0} characters!", + "numberTooLong":"This number can't be longer than {0} characters!", + "numberLengthInvalid":"This number needs to be {0} characters long!", + "numberTooSmall":"This number needs to be at least {0}!", + "numberTooLarge":"This number needs to be at most {0}!", + "numberNotEqual":"This number needs to be {0}!", + "numberStep":"This number needs to be a multiple of {0}!", + "numberStepOffset":"This number needs to be a multiple of {0} starting with {1}!", + "numberStartsWith":"This number needs to start with {0}!", + "numberEndsWith":"This number needs to end with {0}!", + "numberContains":"This number needs to contain {0}!", + "numberChoices":"This number can only be one of the following values: {0}!", + "numberFloat":"This number can't be a decimal!", + "numberNegative":"This number can't be negative!", + "numberPositive":"This number can't be positive!", + "numberZero":"This number can't be zero!", + + "booleanTrue":"This boolean can't be true!", + "booleanFalse":"This boolean can't be false!", + + "arrayEmptyDisabled":"This array isn't allowed to be empty!", + "arrayEmptyRequired":"This array is required to be empty!", + "arrayTooShort":"This array needs to have a length of at least {0}!", + "arrayTooLong":"This array needs to have a length of at most {0}!", + "arrayLengthInvalid":"This array needs to have a length of {0}!", + "arrayInvalidTypes":"This array can only contain the following types: {0}!", + "arrayDouble":"This array doesn't allow the same value twice!", + + "discordInvalidId":"This is an invalid discord {0} id!", + "discordInvalidIdOptions":"This is an invalid discord {0} id! You can also use one of these: {1}!", + "discordInvalidToken":"This is an invalid discord token (syntactically)!", + "colorInvalid":"This is an invalid hex color!", + "emojiTooShort":"This string needs to have at least {0} emoji's!", + "emojiTooLong":"This string needs to have at most {0} emoji's!", + "emojiCustom":"This emoji can't be a custom discord emoji!", + "emojiInvalid":"This is an invalid emoji!", + "urlInvalid":"This url is invalid!", + "urlInvalidHttp":"This url can only use the https:// protocol!", + "urlInvalidProtocol":"This url can only use the http:// & https:// protocols!", + "urlInvalidHostname":"This url has a disallowed hostname!", + "urlInvalidExtension":"This url has an invalid extension! Choose between: {0}!", + "urlInvalidPath":"This url has an invalid path!", + "idNotUnique":"This id isn't unique, use another id instead!", + "idNonExistent":"The id {0} doesn't exist!", + + "invalidType":"This property needs to be the type: {0}!", + "propertyMissing":"The property {0} is missing from this object!", + "propertyOptional":"The property {0} is optional in this object!", + "objectDisabled":"This object is disabled, enable it using {0}!", + "nullInvalid":"This property can't be null!", + "switchInvalidType":"This needs to be one of the following types: {0}!", + "objectSwitchInvalid":"This object needs to be one of the following types: {0}!", + + "invalidLanguage":"This is an invalid language!", + "invalidButton":"This button needs to have at least an {0} or {1}!", + "unusedOption":"The option {0} isn't used anywhere!", + "unusedQuestion":"The question {0} isn't used anywhere!", + "dropdownOption":"A panel with dropdown enabled can only contain options of the 'ticket' type!" + } + }, + "actions":{ + "buttons":{ + "create":"Visit Ticket", + "close":"Close Ticket", + "delete":"Delete Ticket", + "reopen":"Reopen Ticket", + "claim":"Claim Ticket", + "unclaim":"Unclaim Ticket", + "pin":"Pin Ticket", + "unpin":"Unpin Ticket", + "clear":"Delete Tickets", + "helpSwitchSlash":"View Slash Commands", + "helpSwitchText":"View Text Commands", + "helpPage":"Page {0}", + "withReason":"With Reason", + "withoutTranscript":"Without Transcript" + }, + "titles":{ + "created":"Ticket Created", + "close":"Ticket Closed", + "delete":"Ticket Deleted", + "reopen":"Ticket Reopened", + "claim":"Ticket Claimed", + "unclaim":"Ticket Unclaimed", + "pin":"Ticket Pinned", + "unpin":"Ticket Unpinned", + "rename":"Ticket Renamed", + "move":"Ticket Moved", + "add":"Ticket User Added", + "remove":"Ticket User Removed", + + "help":"Available Commands", + "statsReset":"Reset Stats", + "blacklistAdd":"User Blacklisted", + "blacklistRemove":"User Released", + "blacklistGet":"Blacklisted User", + "blacklistView":"Current Blacklist", + "blacklistAddDm":"Added To Blacklist", + "blacklistRemoveDm":"Removed From Blacklist", + "clear":"Tickets Cleared", + "roles":"Roles Updated", + + "autoclose":"Ticket Autoclosed", + "autocloseEnabled":"Autoclose Enabled", + "autocloseDisabled":"Autoclose Disabled", + "autodelete":"Ticket Autodeleted", + "autodeleteEnabled":"Autodelete Enabled", + "autodeleteDisabled":"Autodelete Disabled" + }, + "descriptions":{ + "create":"Your ticket has been created. Click the button below to access it!", + "close":"The ticket has been closed succesfully!", + "delete":"The ticket has been deleted succesfully!", + "reopen":"The ticket has been reopened succesfully!", + "claim":"The ticket has been claimed succesfully!", + "unclaim":"The ticket has been unclaimed succesfully!", + "pin":"The ticket has been pinned succesfully!", + "unpin":"The ticket has been unpinned succesfully!", + "rename":"The ticket has been renamed to {0} succesfully!", + "move":"The ticket has been moved to {0} succesfully!", + "add":"{0} has been added to the ticket succesfully!", + "remove":"{0} has been removed from the ticket succesfully!", + + "helpExplanation":"`` => required parameter\n`[name]` => optional parameter", + "statsReset":"The bot stats have been reset successfully!", + "statsError":"Unable to view ticket stats!\n{0} is not a ticket!", + "blacklistAdd":"{0} has been blacklisted successfully!", + "blacklistRemove":"{0} has been released successfully!", + "blacklistGetSuccess":"{0} is currently blacklisted!", + "blacklistGetEmpty":"{0} is currently not blacklisted!", + "blacklistViewEmpty":"No-one has been blacklisted yet!", + "blacklistViewTip":"Use \"/blacklist add\" to blacklist a user!", + "clearVerify":"Are you sure you want to delete multiple tickets?\nThis action can't be undone!", + "clearReady":"{0} tickets have been deleted succesfully!", + "rolesEmpty":"No roles have been updated!", + + "autocloseLeave":"This ticket has been autoclosed because the creator left the server!", + "autocloseTimeout":"This ticket has been autoclosed because it has been inactive for more than `{0}h`!", + "autodeleteLeave":"This ticket has been autodeleted because the creator left the server!", + "autodeleteTimeout":"This ticket has been autodeleted because it has been inactive for more than `{0} days`!", + "autocloseEnabled":"Autoclose has been enabled in this ticket!\nIt will be closed when it is inactive for more than `{0}h`!", + "autocloseDisabled":"Autoclose has been disabled in this ticket!\nIt won't be closed automatically anymore!", + "autodeleteEnabled":"Autodelete has been enabled in this ticket!\nIt will be deleted when it is inactive for more than `{0} days`!", + "autodeleteDisabled":"Autodelete has been disabled in this ticket!\nIt won't be deleted automatically anymore!", + + "ticketMessageLimit":"You can only create {0} ticket(s) at the same time!", + "ticketMessageAutoclose":"This ticket will be autoclosed when inactive for {0}h!", + "ticketMessageAutodelete":"This ticket will be autodeleted when inactive for {0} days!", + "panelReady":"You can find the panel below!\nThis message can now be deleted!" + }, + "modal":{ + "closePlaceholder":"Why did you close this ticket?", + "deletePlaceholder":"Why did you delete this ticket?", + "reopenPlaceholder":"Why did you reopen this ticket?", + "claimPlaceholder":"Why did you claim this ticket?", + "unclaimPlaceholder":"Why did you unclaim this ticket?", + "pinPlaceholder":"Why did you pin this ticket?", + "unpinPlaceholder":"Why did you unpin this ticket?" + }, + "logs":{ + "createLog":"A new ticket got created by {0}!", + "closeLog":"This ticket has been closed by {0}!", + "closeDm":"Your ticket has been closed in our server!", + "deleteLog":"This ticket has been deleted by {0}!", + "deleteDm":"Your ticket has been deleted in our server!", + "reopenLog":"This ticket has been reopened by {0}!", + "reopenDm":"Your ticket has been reopened in our server!", + "claimLog":"This ticket has been claimed by {0}!", + "claimDm":"Your ticket has been claimed in our server!", + "unclaimLog":"This ticket has been unclaimed by {0}!", + "unclaimDm":"Your ticket has been unclaimed in our server!", + "pinLog":"This ticket has been pinned by {0}!", + "pinDm":"Your ticket has been pinned in our server!", + "unpinLog":"This ticket has been unpinned by {0}!", + "unpinDm":"Your ticket has been unpinned in our server!", + "renameLog":"This ticket has been renamed to {0} by {1}!", + "renameDm":"Your ticket has been renamed to {0} in our server!", + "moveLog":"This ticket has been moved to {0} by {1}!", + "moveDm":"Your ticket has been moved to {0} in our server!", + "addLog":"{0} has been added to this ticket by {1}!", + "addDm":"{0} has been added to your ticket in our server!", + "removeLog":"{0} has been removed from this ticket by {1}!", + "removeDm":"{0} has been removed from your ticket in our server!", + + "blacklistAddLog":"{0} was blacklisted by {1}!", + "blacklistRemoveLog":"{0} was removed from the blacklist by {1}!", + "blacklistAddDm":"You have been blacklisted in our server!\nFrom now on, you are unable to create a ticket!", + "blacklistRemoveDm":"You have been removed from the blacklist in our server!\nNow you can create tickets again!", + "clearLog":"{0} tickets have been deleted by {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Visit Transcript", + "ready":"Transcript Created", + "textFileDescription":"This is the text transcript of a deleted ticket!", + "htmlProgress":"Please wait while this html transcript is getting processed...", + + "createdChannel":"A new {0} transcript has been created in the server!", + "createdCreator":"A new {0} transcript has been created for one of your tickets!", + "createdParticipant":"A new {0} transcript has been created in one of the tickets you participated in!", + "createdActiveAdmin":"A new {0} transcript has been created in one of the tickets you participated as admin!", + "createdEveryAdmin":"A new {0} transcript has been created in one of the tickets you were admin in!", + "createdOther":"A new {0} transcript has been created!" + }, + "errors":{ + "retry":"Retry", + "continue":"Delete Without Transcript", + "backup":"Create Backup Transcript", + "error":"Something went wrong while trying to create the transcript.\nWhat would you like to do?\n\nThis ticket won't be deleted until you click one of these buttons." + } + }, + "errors":{ + "titles":{ + "internalError":"Internal Error", + "optionMissing":"Command Option Missing", + "optionInvalid":"Command Option Invalid", + "unknownCommand":"Unknown Command", + "noPermissions":"No Permissions", + "unknownTicket":"Unknown Ticket", + "deprecatedTicket":"Deprecated Ticket", + "unknownOption":"Unknown Option", + "unknownPanel":"Unknown Panel", + "notInGuild":"Not In Server", + "channelRename":"Unable To Rename Channel", + "busy":"Ticket Is Busy" + }, + "descriptions":{ + "askForInfo":"Contact the owner of this bot for more info!", + "askForInfoResolve":"Contact the bot owner of this bot if this issue doesn't resolve after a few tries.", + "internalError":"Failed to respond to this {0} due to an internal error!", + "optionMissing":"A required parameter is missing in this command!", + "optionInvalid":"A parameter in this command is invalid!", + "optionInvalidChoose":"Choose between", + "unknownCommand":"Try visiting the help menu for more info!", + "noPermissions":"You are not allowed to use this {0}!", + "noPermissionsList":"Required Permissions: (one of them)", + "noPermissionsCooldown":"You are not allowed to use this {0} because you have a cooldown!", + "noPermissionsBlacklist":"You are not allowed to use this {0} because you have been blacklisted!", + "noPermissionsLimitGlobal":"You are not allowed to create a ticket because the server reached the max tickets limit!", + "noPermissionsLimitGlobalUser":"You are not allowed to create a ticket because you reached the max tickets limit!", + "noPermissionsLimitOption":"You are not allowed to create a ticket because the server reached the max tickets limit for this option!", + "noPermissionsLimitOptionUser":"You are not allowed to create a ticket because you reached the max tickets limit for this option!", + "unknownTicket":"Try this command again in a valid ticket!", + "deprecatedTicket":"The current channel is not a valid ticket! It might have been a ticket from an old Open Ticket version!", + "notInGuild":"This {0} doesn't work in DM! Please try it again in a server!", + "channelRename":"Due to discord ratelimits, it's currently impossible for the bot to rename the channel. The channel will automatically be renamed over 10 minutes if the bot isn't rebooted.", + "channelRenameSource":"The source of this error is: {0}", + "busy":"Unable to use this {0}!\nThe ticket is currently being processed by the bot.\n\nPlease try again in a few seconds!" + }, + "optionInvalidReasons":{ + "stringRegex":"Value doesn't match pattern!", + "stringMinLength":"Value needs to be at least {0} characters!", + "stringMaxLength":"Value needs to be at most {0} characters!", + "numberInvalid":"Invalid number!", + "numberMin":"Number needs to be at least {0}!", + "numberMax":"Number needs to be at most {0}!", + "numberDecimal":"Number is not allowed to be a decimal!", + "numberNegative":"Number is not allowed to be negative!", + "numberPositive":"Number is not allowed to be positive!", + "numberZero":"Number is not allowed to be zero!", + "channelNotFound":"Unable to find channel!", + "userNotFound":"Unable to find user!", + "roleNotFound":"Unable to find role!", + "memberNotFound":"Unable to find user!", + "mentionableNotFound":"Unable to find user or role!", + "channelType":"Invalid channel type!", + "notInGuild":"This option requires you to be in a server!" + }, + "permissions":{ + "developer":"You need to be the developer of the bot.", + "owner":"You need to be the server owner.", + "admin":"You need to be a server admin.", + "moderator":"You need to be a moderator.", + "support":"You need to be in the support team.", + "member":"You need to be a member.", + "discord-administrator":"You need to have the `ADMINISTRATOR` permission." + }, + "actionInvalid":{ + "close":"Ticket is already closed!", + "reopen":"Ticket is not closed yet!", + "claim":"Ticket is already claimed!", + "unclaim":"Ticket is not claimed yet!", + "pin":"Ticket is already pinned!", + "unpin":"Ticket is not pinned yet!", + "add":"This user is already able to access the ticket!", + "remove":"Unable to remove this user from the ticket!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickets", + "reason":"Reason", + "creator":"Creator", + "remaining":"Time Remaining", + "added":"Added", + "removed":"Removed", + "filter":"Filter", + "claimedBy":"Claimed By {0}", + "method":"Method", + "type":"Type", + "blacklisted":"Blacklisted", + "panel":"Panel", + "command":"Command", + "system":"System", + "true":"True", + "false":"False", + "syntax":"Syntax", + "originalName":"Original Name", + "newName":"New Name", + "until":"Until", + "validOptions":"Valid Options", + "validPanels":"Valid Panels", + "autoclose":"Autoclose", + "autodelete":"Autodelete", + "startupDate":"Startup Date", + "version":"Version", + "name":"Name", + "role":"Role", + "status":"Status", + "claimed":"Claimed", + "pinned":"Pinned", + "creationDate":"Creation Date" + }, + "lowercase":{ + "text":"text", + "html":"html", + "command":"command", + "modal":"modal", + "button":"button", + "dropdown":"dropdown", + "method":"method" + } + }, + "commands":{ + "reason":"Specify an optional reason that will be visible in logs.", + "help":"Get a list of all the available commands.", + "panel":"Spawn a message with a dropdown or buttons (for ticket creation).", + "panelId":"The identifier of the panel that you want to spawn.", + "panelAutoUpdate":"Do you want this panel to automatically update when edited?", + "ticket":"Instantly create a ticket.", + "ticketId":"The identifier of the ticket that you want to create.", + "close":"Close a ticket.", + "delete":"Delete a ticket.", + "deleteNoTranscript":"Delete this ticket without creating a transcript.", + "reopen":"Reopen a ticket.", + "claim":"Claim a ticket.", + "claimUser":"Claim this ticket to someone else instead of yourself.", + "unclaim":"Unclaim a ticket.", + "pin":"Pin a ticket.", + "unpin":"Unpin a ticket.", + "move":"Move a ticket.", + "moveId":"The identifier of the option that you want to move to.", + "rename":"Rename a ticket.", + "renameName":"The new name for this ticket.", + "add":"Add a user to a ticket.", + "addUser":"The user to add.", + "remove":"Remove a user from a ticket.", + "removeUser":"The user to remove.", + "blacklist":"Manage the ticket blacklist.", + "blacklistView":"View a list of the current blacklist.", + "blacklistAdd":"Add a user to the blacklist.", + "blacklistRemove":"Remove a user from the blacklist.", + "blacklistGet":"Get the details from a blacklisted user.", + "blacklistGetUser":"The user to get details from.", + "stats":"View statistics from the bot, a member or a ticket.", + "statsReset":"Reset all the stats of the bot (and start counting from zero).", + "statsGlobal":"View the global stats.", + "statsUser":"View the stats from a user in the server.", + "statsUserUser":"The user to view.", + "statsTicket":"View the stats of a ticket in the server.", + "statsTicketTicket":"The ticket to view.", + "clear":"Delete multiple tickets at the same time.", + "clearFilter":"The filter for clearing tickets.", + "clearFilters":{ + "all":"All", + "open":"Open", + "close":"Closed", + "claim":"Claimed", + "unclaim":"Unclaimed", + "pin":"Pinned", + "unpin":"Unpinned", + "autoclose":"Autoclosed" + }, + "autoclose":"Manage autoclose in a ticket.", + "autocloseDisable":"Disable autoclose in this ticket.", + "autocloseEnable":"Enable autoclose in this ticket.", + "autocloseEnableTime":"The amount of hours this ticket needs to be inactive to close it.", + "autodelete":"Manage autodelete in a ticket.", + "autodeleteDisable":"Disable autodelete in this ticket.", + "autodeleteEnable":"Enable autodelete in this ticket.", + "autodeleteEnableTime":"The amount of days this ticket needs to be inactive to delete it." + }, + "helpMenu":{ + "help":"Get a list of all the available commands.", + "ticket":"Instantly create a ticket.", + "close":"Close a ticket, this disables writing in this channel.", + "delete":"Delete a ticket, this creates a transcript when enabled.", + "reopen":"Reopen a ticket, this enables writing in this channel again.", + "pin":"Pin a ticket. This will move the ticket to the top and will add a '📌' emoij to the name.", + "unpin":"Unpin a ticket. The ticket will stay on it's position but will lose the '📌' emoij.", + "move":"Move a ticket. This will change the type of this ticket.", + "rename":"Rename a ticket. This will change the channel name of this ticket.", + "claim":"Claim a ticket. With this, you can let your team know you are handling this ticket.", + "unclaim":"Unclaim a ticket. With this, you can let your team know that this ticket is free again.", + "add":"Add a user to a ticket. This will allow the user to read & write in this ticket.", + "remove":"Remove a user from a ticket. This will remove the ability to read & write for a user in this ticket.", + "panel":"Spawn a message with a dropdown or buttons (for ticket creation).", + "blacklistView":"View a list of the current blacklist.", + "blacklistAdd":"Add a user to the blacklist.", + "blacklistRemove":"Remove a user from the blacklist.", + "blacklistGet":"Get the details from a blacklisted user.", + "statsGlobal":"View the global stats.", + "statsTicket":"View the stats of a ticket in the server.", + "statsUser":"View the stats from a user in the server.", + "statsReset":"Reset all the stats of the bot (and start counting from zero).", + "autocloseDisable":"Disable autoclose in this ticket.", + "autocloseEnable":"Enable autoclose in this ticket.", + "autodeleteDisable":"Disable autodelete in this ticket.", + "autodeleteEnable":"Enable autodelete in this ticket." + }, + "stats":{ + "scopes":{ + "global":"Global Stats", + "system":"System Stats", + "user":"User Stats", + "ticket":"Ticket Stats", + "participants":"Participants" + }, + "properties":{ + "ticketsCreated":"Tickets Created", + "ticketsClosed":"Tickets Closed", + "ticketsDeleted":"Tickets Deleted", + "ticketsReopened":"Tickets Reopened", + "ticketsAutoclosed":"Tickets Autoclosed", + "ticketsClaimed":"Tickets Claimed", + "ticketsPinned":"Tickets Pinned", + "ticketsMoved":"Tickets Moved", + "usersBlacklisted":"Users Blacklisted", + "transcriptsCreated":"Transcripts Created" + } + } +} \ No newline at end of file diff --git a/languages/portuguese.json b/languages/portuguese.json new file mode 100644 index 0000000..181ea58 --- /dev/null +++ b/languages/portuguese.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"quiradon", + "lastedited":"20/08/2024", + "language":"Portuguese" + }, + "checker":{ + "system":{ + "typeError": "[ERRO]", + "headerOpenTicket": "ABRIR TICKET", + "typeWarning": "[AVISO]", + "typeInfo": "[INFORMAÇÃO]", + "headerConfigChecker": "Verificador de Configuração", + "headerDescription": "verifique erros nos seus arquivos de configuração!", + "footerError": "o bot não iniciará até que todos os {0} sejam corrigidos!", + "footerWarning": "é recomendado corrigir todos os {0} antes de iniciar!", + "footerSupport": "SUPORTE: {0} - DOCS: {1}", + "compactInformation": "use {0} para mais informações!", + "dataPath": "caminho", + "dataDocs": "documentos", + "dataMessages": "mensagem" + }, + "messages":{ + "stringTooShort": "Esta string não pode ter menos de {0} caracteres!", + "stringTooLong": "Esta string não pode ter mais de {0} caracteres!", + "stringLengthInvalid": "Esta string precisa ter {0} caracteres!", + "stringStartsWith": "Esta string precisa começar com {0}!", + "stringEndsWith": "Esta string precisa terminar com {0}!", + "stringContains": "Esta string precisa conter {0}!", + "stringChoices": "Esta string só pode ser um dos seguintes valores: {0}!", + "stringRegex": "Esta string é inválida!", + + "numberTooShort": "Este número não pode ter menos de {0} caracteres!", + "numberTooLong": "Este número não pode ter mais de {0} caracteres!", + "numberLengthInvalid": "Este número precisa ter {0} caracteres!", + "numberTooSmall": "Este número precisa ser pelo menos {0}!", + "numberTooLarge": "Este número precisa ser no máximo {0}!", + "numberNotEqual": "Este número precisa ser {0}!", + "numberStep": "Este número precisa ser um múltiplo de {0}!", + "numberStepOffset": "Este número precisa ser um múltiplo de {0} começando com {1}!", + "numberStartsWith": "Este número precisa começar com {0}!", + "numberEndsWith": "Este número precisa terminar com {0}!", + "numberContains": "Este número precisa conter {0}!", + "numberChoices": "Este número só pode ser um dos seguintes valores: {0}!", + "numberFloat": "Este número não pode ser decimal!", + "numberNegative": "Este número não pode ser negativo!", + "numberPositive": "Este número não pode ser positivo!", + "numberZero": "Este número não pode ser zero!", + + "booleanTrue": "Este booleano não pode ser verdadeiro!", + "booleanFalse": "Este booleano não pode ser falso!", + + "arrayEmptyDisabled": "Este array não pode estar vazio!", + "arrayEmptyRequired": "Este array deve estar vazio!", + "arrayTooShort": "Este array precisa ter um comprimento de pelo menos {0}!", + "arrayTooLong": "Este array precisa ter um comprimento de no máximo {0}!", + "arrayLengthInvalid": "Este array precisa ter um comprimento de {0}!", + "arrayInvalidTypes": "Este array só pode conter os seguintes tipos: {0}!", + "arrayDouble": "Este array não permite o mesmo valor duas vezes!", + + "discordInvalidId": "Este é um ID do Discord inválido {0}!", + "discordInvalidIdOptions": "Este é um ID do Discord inválido {0}! Você também pode usar um destes: {1}!", + "discordInvalidToken": "Este é um token do Discord inválido (sintaticamente)!", + "colorInvalid": "Esta é uma cor hexadecimal inválida!", + "emojiTooShort": "Esta string precisa ter pelo menos {0} emojis!", + "emojiTooLong": "Esta string precisa ter no máximo {0} emojis!", + "emojiCustom": "Este emoji não pode ser um emoji personalizado do Discord!", + "emojiInvalid": "Este é um emoji inválido!", + "urlInvalid": "Esta URL é inválida!", + "urlInvalidHttp": "Esta URL só pode usar o protocolo https://!", + "urlInvalidProtocol": "Esta URL só pode usar os protocolos http:// e https://!", + "urlInvalidHostname": "Esta URL tem um hostname não permitido!", + "urlInvalidExtension": "Esta URL tem uma extensão inválida! Escolha entre: {0}!", + "urlInvalidPath": "Esta URL tem um caminho inválido!", + "idNotUnique": "Este ID não é único, use outro ID!", + "idNonExistent": "O ID {0} não existe!", + + "invalidType": "Esta propriedade precisa ser do tipo: {0}!", + "propertyMissing": "A propriedade {0} está faltando neste objeto!", + "propertyOptional": "A propriedade {0} é opcional neste objeto!", + "objectDisabled": "Este objeto está desabilitado, habilite-o usando {0}!", + "nullInvalid": "Esta propriedade não pode ser nula!", + "switchInvalidType": "Isso precisa ser um dos seguintes tipos: {0}!", + "objectSwitchInvalid": "Este objeto precisa ser um dos seguintes tipos: {0}!", + + "invalidLanguage": "Este é um idioma inválido!", + "invalidButton": "Este botão precisa ter pelo menos um {0} ou {1}!", + "unusedOption": "A opção {0} não é usada em nenhum lugar!", + "unusedQuestion": "A pergunta {0} não é usada em nenhum lugar!", + "dropdownOption": "Um painel com dropdown habilitado só pode conter opções do tipo 'ticket'!" + } + }, + "actions":{ + "buttons":{ + "create": "Visitar Ticket", + "close": "Fechar Ticket", + "delete": "Excluir Ticket", + "reopen": "Reabrir Ticket", + "claim": "Reivindicar Ticket", + "unclaim": "Desreivindicar Ticket", + "pin": "Fixar Ticket", + "unpin": "Desfixar Ticket", + "clear": "Excluir Tickets", + "helpSwitchSlash": "Ver Comandos Slash", + "helpSwitchText": "Ver Comandos de Texto", + "helpPage": "Página {0}", + "withReason": "Com Motivo", + "withoutTranscript": "Sem Transcrição" + }, + "titles":{ + "created":"Ticket Criado", + "close":"Ticket Fechado", + "delete":"Ticket Deletado", + "reopen":"Ticket Re-abeto", + "claim":"Ticket Resgatado", + "unclaim":"Ticket Não Resgatado", + "pin":"Ticket Fixado", + "unpin":"Ticket Desfixado", + "rename":"Ticket Renomeado", + "move":"Ticket Movido", + "add":"Ticket Usuário Adicionado", + "remove":"Ticket Usuário Removido", + + "help":"Comandos disponíveis", + "statsReset":"Redefinir Status", + "blacklistAdd":"User Blacklisted", + "blacklistRemove":"User Released", + "blacklistGet":"Usuário na Blacklisted", + "blacklistView":"Atualmente na Blacklist", + "blacklistAddDm":"Adicionado a Blacklist", + "blacklistRemoveDm":"Removido da Blacklist", + "clear":"Tickets Limpos", + "roles":"Cargos Atualizados", + + "autoclose": "Ticket Fechado Automaticamente", + "autocloseEnabled": "Fechamento Automático Habilitado", + "autocloseDisabled": "Fechamento Automático Desabilitado", + "autodelete": "Ticket Excluído Automaticamente", + "autodeleteEnabled": "Exclusão Automática Habilitada", + "autodeleteDisabled": "Exclusão Automática Desabilitada" + }, + "descriptions":{ + "create": "Seu ticket foi criado. Clique no botão abaixo para acessá-lo!", + "close": "O ticket foi fechado com sucesso!", + "delete": "O ticket foi excluído com sucesso!", + "reopen": "O ticket foi reaberto com sucesso!", + "claim": "O ticket foi reivindicado com sucesso!", + "unclaim": "O ticket foi desreivindicado com sucesso!", + "pin": "O ticket foi fixado com sucesso!", + "unpin": "O ticket foi desfixado com sucesso!", + "rename": "O ticket foi renomeado para {0} com sucesso!", + "move": "O ticket foi movido para {0} com sucesso!", + "add": "{0} foi adicionado ao ticket com sucesso!", + "remove": "{0} foi removido do ticket com sucesso!", + + "helpExplanation":"`` => parâmetro obrigatório\n`[nome]` => parâmetro opcional", + "statsReset":"As estatísticas do bot foram redefinidas com sucesso!", + "statsError":"Não foi possível visualizar as estatísticas do ticket!\n{0} não é um ticket!", + "blacklistAdd":"{0} foi adicionado à lista negra com sucesso!", + "blacklistRemove":"{0} foi removido da lista negra com sucesso!", + "blacklistGetSuccess":"{0} está atualmente na lista negra!", + "blacklistGetEmpty":"{0} não está atualmente na lista negra!", + "blacklistViewEmpty":"Ninguém foi adicionado à lista negra ainda!", + "blacklistViewTip":"Use \"/blacklist add\" para adicionar um usuário à lista negra!", + "clearVerify":"Você tem certeza de que deseja excluir vários tickets?\nEsta ação não pode ser desfeita!", + "clearReady":"{0} tickets foram excluídos com sucesso!", + "rolesEmpty":"Nenhum cargo foi atualizado!", + + "autocloseLeave": "Este ticket foi fechado automaticamente porque o criador saiu do servidor!", + "autocloseTimeout": "Este ticket foi fechado automaticamente porque ficou inativo por mais de `{0}h`!", + "autodeleteLeave": "Este ticket foi excluído automaticamente porque o criador saiu do servidor!", + "autodeleteTimeout": "Este ticket foi excluído automaticamente porque ficou inativo por mais de `{0} dias`!", + "autocloseEnabled": "O fechamento automático foi habilitado neste ticket!\nEle será fechado quando ficar inativo por mais de `{0}h`!", + "autocloseDisabled": "O fechamento automático foi desabilitado neste ticket!\nEle não será mais fechado automaticamente!", + "autodeleteEnabled": "A exclusão automática foi habilitada neste ticket!\nEle será excluído quando ficar inativo por mais de `{0} dias`!", + "autodeleteDisabled": "A exclusão automática foi desabilitada neste ticket!\nEle não será mais excluído automaticamente!", + + "ticketMessageLimit": "Você só pode criar {0} ticket(s) ao mesmo tempo!", + "ticketMessageAutoclose": "Este ticket será fechado automaticamente quando inativo por {0}h!", + "ticketMessageAutodelete": "Este ticket será excluído automaticamente quando inativo por {0} dias!", + "panelReady": "Você pode encontrar o painel abaixo!\nEsta mensagem agora pode ser excluída!" + }, + "modal":{ + "closePlaceholder": "Por que você fechou este ticket?", + "deletePlaceholder": "Por que você excluiu este ticket?", + "reopenPlaceholder": "Por que você reabriu este ticket?", + "claimPlaceholder": "Por que você reivindicou este ticket?", + "unclaimPlaceholder": "Por que você desreivindicou este ticket?", + "pinPlaceholder": "Por que você fixou este ticket?", + "unpinPlaceholder": "Por que você desfixou este ticket?" + }, + "logs":{ + "createLog": "Um novo ticket foi criado por {0}!", + "closeLog": "Este ticket foi fechado por {0}!", + "closeDm": "Seu ticket foi fechado em nosso servidor!", + "deleteLog": "Este ticket foi excluído por {0}!", + "deleteDm": "Seu ticket foi excluído em nosso servidor!", + "reopenLog": "Este ticket foi reaberto por {0}!", + "reopenDm": "Seu ticket foi reaberto em nosso servidor!", + "claimLog": "Este ticket foi reivindicado por {0}!", + "claimDm": "Seu ticket foi reivindicado em nosso servidor!", + "unclaimLog": "Este ticket foi desreivindicado por {0}!", + "unclaimDm": "Seu ticket foi desreivindicado em nosso servidor!", + "pinLog": "Este ticket foi fixado por {0}!", + "pinDm": "Seu ticket foi fixado em nosso servidor!", + "unpinLog": "Este ticket foi desfixado por {0}!", + "unpinDm": "Seu ticket foi desfixado em nosso servidor!", + "renameLog": "Este ticket foi renomeado para {0} por {1}!", + "renameDm": "Seu ticket foi renomeado para {0} em nosso servidor!", + "moveLog": "Este ticket foi movido para {0} por {1}!", + "moveDm": "Seu ticket foi movido para {0} em nosso servidor!", + "addLog": "{0} foi adicionado a este ticket por {1}!", + "addDm": "{0} foi adicionado ao seu ticket em nosso servidor!", + "removeLog": "{0} foi removido deste ticket por {1}!", + "removeDm": "{0} foi removido do seu ticket em nosso servidor!", + + "blacklistAddLog": "{0} foi adicionado à lista negra por {1}!", + "blacklistRemoveLog": "{0} foi removido da lista negra por {1}!", + "blacklistAddDm": "Você foi adicionado à lista negra em nosso servidor!\nA partir de agora, você não pode criar um ticket!", + "blacklistRemoveDm": "Você foi removido da lista negra em nosso servidor!\nAgora você pode criar tickets novamente!", + "clearLog": "{0} tickets foram excluídos por {1}!" + } + }, + "transcripts":{ + "success":{ + "visit": "Visitar Transcrição", + "ready": "Transcrição Criada", + "textFileDescription": "Esta é a transcrição em texto de um ticket excluído!", + "htmlProgress": "Por favor, aguarde enquanto esta transcrição em HTML está sendo processada...", + + "createdChannel": "Uma nova transcrição de {0} foi criada no servidor!", + "createdCreator": "Uma nova transcrição de {0} foi criada para um dos seus tickets!", + "createdParticipant": "Uma nova transcrição de {0} foi criada em um dos tickets em que você participou!", + "createdActiveAdmin": "Uma nova transcrição de {0} foi criada em um dos tickets em que você participou como administrador!", + "createdEveryAdmin": "Uma nova transcrição de {0} foi criada em um dos tickets em que você era administrador!", + "createdOther": "Uma nova transcrição de {0} foi criada!" + }, + "errors":{ + "retry": "Tentar Novamente", + "continue": "Excluir Sem Transcrição", + "backup": "Criar Transcrição de Backup", + "error": "Algo deu errado ao tentar criar a transcrição.\nO que você gostaria de fazer?\n\nEste ticket não será excluído até que você clique em um desses botões." + } + }, + "errors":{ + "titles":{ + "internalError": "Erro Interno", + "optionMissing": "Opção de Comando Ausente", + "optionInvalid": "Opção de Comando Inválida", + "unknownCommand": "Comando Desconhecido", + "noPermissions": "Sem Permissões", + "unknownTicket": "Ticket Desconhecido", + "deprecatedTicket": "Ticket Obsoleto", + "unknownOption": "Opção Desconhecida", + "unknownPanel": "Painel Desconhecido", + "notInGuild": "Não Está no Servidor", + "channelRename": "Incapaz de Renomear Canal", + "busy": "Ticket Está Ocupado" + }, + "descriptions":{ + "askForInfo": "Entre em contato com o proprietário deste bot para mais informações!", + "askForInfoResolve": "Entre em contato com o proprietário deste bot se este problema não for resolvido após algumas tentativas.", + "internalError": "Falha ao responder a este {0} devido a um erro interno!", + "optionMissing": "Um parâmetro obrigatório está faltando neste comando!", + "optionInvalid": "Um parâmetro neste comando é inválido!", + "optionInvalidChoose": "Escolha entre", + "unknownCommand": "Tente visitar o menu de ajuda para mais informações!", + "noPermissions": "Você não tem permissão para usar este {0}!", + "noPermissionsList": "Permissões Necessárias: (uma delas)", + "noPermissionsCooldown": "Você não tem permissão para usar este {0} porque você está em período de cooldown!", + "noPermissionsBlacklist": "Você não tem permissão para usar este {0} porque você foi colocado na lista negra!", + "noPermissionsLimitGlobal": "Você não tem permissão para criar um ticket porque o servidor atingiu o limite máximo de tickets!", + "noPermissionsLimitGlobalUser": "Você não tem permissão para criar um ticket porque você atingiu o limite máximo de tickets!", + "noPermissionsLimitOption": "Você não tem permissão para criar um ticket porque o servidor atingiu o limite máximo de tickets para esta opção!", + "noPermissionsLimitOptionUser": "Você não tem permissão para criar um ticket porque você atingiu o limite máximo de tickets para esta opção!", + "unknownTicket": "Tente este comando novamente em um ticket válido!", + "deprecatedTicket": "O canal atual não é um ticket válido! Pode ter sido um ticket de uma versão antiga do Open Ticket!", + "notInGuild": "Este {0} não funciona em DM! Por favor, tente novamente em um servidor!", + "channelRename": "Devido aos limites de taxa do Discord, atualmente é impossível para o bot renomear o canal. O canal será renomeado automaticamente em 10 minutos se o bot não for reiniciado.", + "channelRenameSource": "A fonte deste erro é: {0}", + "busy": "Não é possível usar este {0}!\nO ticket está sendo processado pelo bot no momento.\n\nPor favor, tente novamente em alguns segundos!" + }, + "optionInvalidReasons":{ + "stringRegex": "O valor não corresponde ao padrão!", + "stringMinLength": "O valor precisa ter pelo menos {0} caracteres!", + "stringMaxLength": "O valor precisa ter no máximo {0} caracteres!", + "numberInvalid": "Número inválido!", + "numberMin": "O número precisa ser pelo menos {0}!", + "numberMax": "O número precisa ser no máximo {0}!", + "numberDecimal": "Não é permitido que o número seja decimal!", + "numberNegative": "Não é permitido que o número seja negativo!", + "numberPositive": "Não é permitido que o número seja positivo!", + "numberZero": "Não é permitido que o número seja zero!", + "channelNotFound": "Não foi possível encontrar o canal!", + "userNotFound": "Não foi possível encontrar o usuário!", + "roleNotFound": "Não foi possível encontrar o cargo!", + "memberNotFound": "Não foi possível encontrar o usuário!", + "mentionableNotFound": "Não foi possível encontrar o usuário ou cargo!", + "channelType": "Tipo de canal inválido!", + "notInGuild": "Esta opção requer que você esteja em um servidor!" + }, + "permissions": { + "developer": "Você precisa ser o desenvolvedor do bot.", + "owner": "Você precisa ser o dono do servidor.", + "admin": "Você precisa ser um administrador do servidor.", + "moderator": "Você precisa ser um moderador.", + "support": "Você precisa estar na equipe de suporte.", + "member": "Você precisa ser um membro.", + "discord-administrator": "Você precisa ter a permissão `ADMINISTRATOR`." + }, + "actionInvalid":{ + "close": "O ticket já está fechado!", + "reopen": "O ticket ainda não está fechado!", + "claim": "O ticket já está reivindicado!", + "unclaim": "O ticket ainda não está reivindicado!", + "pin": "O ticket já está fixado!", + "unpin": "O ticket ainda não está fixado!", + "add": "Este usuário já pode acessar o ticket!", + "remove": "Não foi possível remover este usuário do ticket!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickets", + "reason":"Motivo", + "creator":"Criador", + "remaining":"Tempo Restante", + "added":"Adicionado", + "removed":"Removido", + "filter":"Filtro", + "claimedBy":"Reivindicado por {0}", + "method":"Método", + "type":"Tipo", + "blacklisted":"Na Lista Negra", + "panel":"Painel", + "command":"Comando", + "system":"Sistema", + "true":"Verdadeiro", + "false":"Falso", + "syntax":"Sintaxe", + "originalName":"Nome Original", + "newName":"Novo Nome", + "until":"Até", + "validOptions":"Opções Válidas", + "validPanels":"Painéis Válidos", + "autoclose":"Auto-fechar", + "autodelete":"Auto-deletar", + "startupDate":"Data de Início", + "version":"Versão", + "name":"Nome", + "role":"Cargo", + "status":"Status", + "claimed":"Reivindicado", + "pinned":"Fixado", + "creationDate":"Data de Criação" + }, + "lowercase":{ + "text":"texto", + "html":"html", + "command":"comando", + "modal":"modal", + "button":"botão", + "dropdown":"dropdown", + "method":"método" + } + }, + "commands":{ + "reason": "Especifique um motivo opcional que será visível nos logs.", + "help": "Obtenha uma lista de todos os comandos disponíveis.", + "panel": "Gerar uma mensagem com um dropdown ou botões (para criação de tickets).", + "panelId": "O identificador do painel que você deseja gerar.", + "panelAutoUpdate": "Você quer que este painel atualize automaticamente quando editado?", + "ticket": "Crie um ticket instantaneamente.", + "ticketId": "O identificador do ticket que você deseja criar.", + "close": "Feche um ticket.", + "delete": "Exclua um ticket.", + "deleteNoTranscript": "Exclua este ticket sem criar uma transcrição.", + "reopen": "Reabra um ticket.", + "claim": "Assuma um ticket.", + "claimUser": "Assuma este ticket para outra pessoa em vez de você mesmo.", + "unclaim": "Desassuma um ticket.", + "pin": "Fixe um ticket.", + "unpin": "Desfixe um ticket.", + "move": "Mova um ticket.", + "moveId": "O identificador do opção para o qual você deseja mover.", + "rename": "Renomeie um ticket.", + "renameName": "O novo nome para este ticket.", + "add": "Adicione um usuário a um ticket.", + "addUser": "O usuário a ser adicionado.", + "remove": "Remover um usuário de um ticket.", + "removeUser": "O usuário a ser removido.", + "blacklist": "Gerenciar a lista negra de tickets.", + "blacklistView": "Ver uma lista da blacklist atual.", + "blacklistAdd": "Adicionar um usuário à blacklist.", + "blacklistRemove": "Remover um usuário da blacklist.", + "blacklistGet": "Obter os detalhes de um usuário na blacklist.", + "blacklistGetUser": "O usuário para obter detalhes.", + "stats": "Ver estatísticas do bot, de um membro ou de um ticket.", + "statsReset": "Redefinir todas as estatísticas do bot (e começar a contar do zero).", + "statsGlobal": "Ver as estatísticas globais.", + "statsUser": "Ver as estatísticas de um usuário no servidor.", + "statsUserUser": "O usuário para visualizar.", + "statsTicket": "Ver as estatísticas de um ticket no servidor.", + "statsTicketTicket": "O ticket para visualizar.", + "clear": "Excluir vários tickets ao mesmo tempo. Um filtro opcional pode ser especificado.", + "clearFilter": "O filtro para limpar tickets.", + "clearFilters": { + "all": "Todos", + "open": "Aberto", + "close": "Fechado", + "claim": "Reivindicado", + "unclaim": "Não Reivindicado", + "pin": "Fixado", + "unpin": "Desfixado", + "autoclose": "Fechado Automaticamente" + }, + "autoclose": "Gerenciar fechamento automático em um ticket.", + "autocloseDisable": "Desabilitar fechamento automático neste ticket.", + "autocloseEnable": "Habilitar fechamento automático neste ticket.", + "autocloseEnableTime": "A quantidade de horas que este ticket precisa estar inativo para ser fechado.", + "autodelete": "Gerenciar exclusão automática em um ticket.", + "autodeleteDisable": "Desabilitar exclusão automática neste ticket.", + "autodeleteEnable": "Habilitar exclusão automática neste ticket.", + "autodeleteEnableTime": "A quantidade de dias que este ticket precisa estar inativo para ser excluído." + }, + "helpMenu": { + "help": "Obtenha uma lista de todos os comandos disponíveis.", + "ticket": "Crie um ticket instantaneamente.", + "close": "Feche um ticket, isso desabilita a escrita neste canal.", + "delete": "Exclua um ticket, isso cria uma transcrição quando habilitado.", + "reopen": "Reabra um ticket, isso habilita a escrita neste canal novamente.", + "pin": "Fixe um ticket. Isso moverá o ticket para o topo e adicionará um emoji '📌' ao nome.", + "unpin": "Desfixe um ticket. O ticket permanecerá na sua posição, mas perderá o emoji '📌'.", + "move": "Mova um ticket. Isso mudará o tipo deste ticket.", + "rename": "Renomeie um ticket. Isso mudará o nome do canal deste ticket.", + "claim": "Assuma um ticket. Com isso, você pode informar à sua equipe que está lidando com este ticket.", + "unclaim": "Desassuma um ticket. Com isso, você pode informar à sua equipe que este ticket está livre novamente.", + "add": "Adicione um usuário a um ticket. Isso permitirá que o usuário leia e escreva neste ticket.", + "remove": "Remova um usuário de um ticket. Isso removerá a capacidade de ler e escrever para um usuário neste ticket.", + "panel": "Gere uma mensagem com um dropdown ou botões (para criação de tickets).", + "blacklistView": "Veja uma lista da blacklist atual.", + "blacklistAdd": "Adicione um usuário à blacklist.", + "blacklistRemove": "Remova um usuário da blacklist.", + "blacklistGet": "Obtenha os detalhes de um usuário na blacklist.", + "statsGlobal": "Veja as estatísticas globais.", + "statsTicket": "Veja as estatísticas de um ticket no servidor.", + "statsUser": "Veja as estatísticas de um usuário no servidor.", + "statsReset": "Redefina todas as estatísticas do bot (e comece a contar do zero).", + "autocloseDisable": "Desabilite o fechamento automático neste ticket.", + "autocloseEnable": "Habilite o fechamento automático neste ticket.", + "autodeleteDisable": "Desabilite a exclusão automática neste ticket.", + "autodeleteEnable": "Habilite a exclusão automática neste ticket." + }, + "stats":{ + "scopes": { + "global": "Status Global", + "system": "Status do Sistema", + "user": "Status do Usuário", + "ticket": "Status do Ticket", + "participants": "Participantes" + }, + "properties":{ + "ticketsCreated":"Tickets Criados", + "ticketsClosed":"Tickets Fechados", + "ticketsDeleted":"Tickets Deletados", + "ticketsReopened":"Tickets Re-Abertos", + "ticketsAutoclosed":"Tickets Auto Fechados", + "ticketsClaimed":"Tickets Claimados", + "ticketsPinned":"Tickets Fixados", + "ticketsMoved":"Tickets Movidos", + "usersBlacklisted":"Usuários na Blacklist", + "transcriptsCreated":"Transcrição Criada" + } + } +} \ No newline at end of file diff --git a/plugins/example-plugin/config.json b/plugins/example-plugin/config.json new file mode 100644 index 0000000..cf41d25 --- /dev/null +++ b/plugins/example-plugin/config.json @@ -0,0 +1,5 @@ +{ + "testVariable1":true, + "testVariable2":123, + "testVariable3":"abc" +} \ No newline at end of file diff --git a/plugins/example-plugin/index.ts b/plugins/example-plugin/index.ts new file mode 100644 index 0000000..94f18a3 --- /dev/null +++ b/plugins/example-plugin/index.ts @@ -0,0 +1,44 @@ +import {api, openticket, utilities} from "../../src/index" +import * as discord from "discord.js" + +///////////////////////////////////////////// +//// This plugin is not enabled yet! //// +//// Enable it in the plugin.json file! //// +///////////////////////////////////////////// + +if (utilities.project != "openticket") throw new api.ODPluginError("This plugin only works in Open Ticket!") +if (!utilities.isBeta) throw new api.ODPluginError("This plugin is made for the beta version of Open Ticket!") + +//Add Typescript autocomplete support for plugin data. (!!!OPTIONAL!!!) +declare module "../../src/core/api/api.ts" { + export interface ODConfigManagerIds_Default { + "example-plugin:config":api.ODJsonConfig + } +} + +//Let's register the example config. This way it's available for all plugins & systems. +openticket.events.get("onConfigLoad").listen((configManager) => { + configManager.add(new api.ODJsonConfig("example-plugin:config","config.json","./plugins/example-plugin/")) + /*===== What did we do? ===== + - "example-plugin:config" Is the ID of this config. You can use this id troughout the bot to access this config file. Even in other plugins. + - "config.json" Is the FILE of this config. It is just the filename. + - "./plugins/example-plugin/" Is the DIRECTORY of this config. By default it's "./config/", but we want to change it to point at the plugin directory. + */ + + //Let's also log it to the console to let us know it worked! + const ourConfig = configManager.get("example-plugin:config") + openticket.log("The example config loaded succesfully!","plugin",[ + {key:"var-1",value:ourConfig.data.testVariable1}, + {key:"var-2",value:ourConfig.data.testVariable2.toString()}, + {key:"var-3",value:ourConfig.data.testVariable3.toString()} + ]) +}) + +openticket.events.get("onTicketCreate").listen((creator) => { + //This is logged before the ticket is created (after the button is pressed) + openticket.log("Ticket is getting created...","plugin") +}) +openticket.events.get("afterTicketCreated").listen((ticket,creator,channel) => { + //This is logged after the ticket is created + openticket.log("Ticket ready!","plugin") +}) \ No newline at end of file diff --git a/plugins/example-plugin/plugin.json b/plugins/example-plugin/plugin.json new file mode 100644 index 0000000..76fd490 --- /dev/null +++ b/plugins/example-plugin/plugin.json @@ -0,0 +1,23 @@ +{ + "name":"Example Plugin", + "id":"example-plugin", + "version":"1.0.0", + "startFile":"index.ts", + + "enabled":false, + "priority":0, + "events":[], + + "npmDependencies":["discord.js"], + "requiredPlugins":[], + "incompatiblePlugins":[], + + "details":{ + "author":"DJj123dj", + "shortDescription":"A simple template for an Open Ticket v4 plugin!", + "longDescription":"A simple example of an Open Ticket v4 plugin!", + "imageUrl":"", + "projectUrl":"", + "tags":["template","example","default"] + } +} \ No newline at end of file diff --git a/src/actions/addTicketUser.ts b/src/actions/addTicketUser.ts new file mode 100644 index 0000000..8081b91 --- /dev/null +++ b/src/actions/addTicketUser.ts @@ -0,0 +1,87 @@ +/////////////////////////////////////// +//TICKET ADD USER SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:add-ticket-user")) + openticket.actions.get("openticket:add-ticket-user").workers.add([ + new api.ODWorker("openticket:add-ticket-user",2,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason,data} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to add user to ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketUserAdd").emit([ticket,user,data,channel,reason]) + + //update ticket + ticket.get("openticket:participants").value.push({type:"user",id:data.id}) + ticket.get("openticket:participants").refreshDatabase() + ticket.get("openticket:busy").value = true + + //update channel permissions + try{ + await channel.permissionOverwrites.create(data,{ + ViewChannel:true, + SendMessages:true, + AddReactions:true, + AttachFiles:true, + SendPolls:true, + ReadMessageHistory:true + }) + }catch{ + openticket.log("Failed to add channel permission overwrites on add-ticket-user","error") + } + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket user adding!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value,hidden:true} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //reply with new message + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:add-message").build(source,{guild,channel,user,ticket,reason,data})).message) + ticket.get("openticket:busy").value = false + await openticket.events.get("afterTicketUserAdded").emit([ticket,user,data,channel,reason]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason,data} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.adding.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) + } + + //to dm + if (generalConfig.data.system.messages.adding.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket,data} = params + + openticket.log(user.displayName+" added "+data.displayName+" to a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source} + ]) + }) + ]) + openticket.actions.get("openticket:add-ticket-user").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + }) +} \ No newline at end of file diff --git a/src/actions/claimTicket.ts b/src/actions/claimTicket.ts new file mode 100644 index 0000000..e3b6aa5 --- /dev/null +++ b/src/actions/claimTicket.ts @@ -0,0 +1,276 @@ +/////////////////////////////////////// +//TICKET CLAIMING SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:claim-ticket")) + openticket.actions.get("openticket:claim-ticket").workers.add([ + new api.ODWorker("openticket:claim-ticket",2,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to claim ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketClaim").emit([ticket,user,channel,reason]) + + //update ticket + ticket.get("openticket:claimed").value = true + ticket.get("openticket:claimed-by").value = user.id + ticket.get("openticket:claimed-on").value = new Date().getTime() + ticket.get("openticket:busy").value = true + + //update stats + openticket.stats.get("openticket:global").setStat("openticket:tickets-claimed",1,"increase") + openticket.stats.get("openticket:user").setStat("openticket:tickets-claimed",user.id,1,"increase") + + //update category + const rawClaimCategory = ticket.option.get("openticket:channel-categories-claimed").value.find((c) => c.user == user.id) + const claimCategory = (rawClaimCategory) ? rawClaimCategory.category : null + if (claimCategory){ + try { + channel.setParent(claimCategory,{lockPermissions:false}) + ticket.get("openticket:category-mode").value = "claimed" + ticket.get("openticket:category").value = claimCategory + }catch(e){ + openticket.log("Unable to move ticket to 'claimed category'!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"categoryid",value:claimCategory} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket claiming!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //reply with new message + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:claim-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("openticket:busy").value = false + await openticket.events.get("afterTicketClaimed").emit([ticket,user,channel,reason]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.claiming.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) + } + + //to dm + if (generalConfig.data.system.messages.claiming.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket} = params + + openticket.log(user.displayName+" claimed a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source} + ]) + }) + ]) + openticket.actions.get("openticket:claim-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + }) +} + +export const registerVerifyBars = async () => { + //CLAIM TICKET TICKET MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:claim-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:claim-ticket-ticket-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.claim + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when already claimed + if (ticket.get("openticket:claimed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start claiming ticket + if (params.data == "reason"){ + //claim with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:claim-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + }else{ + //claim without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:claim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + } + }) + ]) + openticket.verifybars.get("openticket:claim-ticket-ticket-message").failure.add([ + new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }) + ]) + + //CLAIM TICKET UNCLAIM MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:claim-ticket-unclaim-message",openticket.builders.messages.getSafe("openticket:verifybar-unclaim-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:claim-ticket-unclaim-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.claim + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when already claimed + if (ticket.get("openticket:claimed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start claiming ticket + if (params.data == "reason"){ + //claim with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:claim-ticket-reason").build("unclaim-message",{guild,channel,user,ticket})) + }else{ + //claim without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:claim-ticket").run("unclaim-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:claim-message").build("unclaim-message",{guild,channel,user,ticket,reason:null})) + } + }) + ]) + openticket.verifybars.get("openticket:claim-ticket-unclaim-message").failure.add([ + new api.ODWorker("openticket:back-to-unclaim-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const {verifybarMessage} = params + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + await instance.update(await openticket.builders.messages.getSafe("openticket:unclaim-message").build("other",{guild,channel,user,ticket,reason})) + }) + ]) +} \ No newline at end of file diff --git a/src/actions/clearTickets.ts b/src/actions/clearTickets.ts new file mode 100644 index 0000000..97ecbf4 --- /dev/null +++ b/src/actions/clearTickets.ts @@ -0,0 +1,45 @@ +/////////////////////////////////////// +//CLEAR TICKETS SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:clear-tickets")) + openticket.actions.get("openticket:clear-tickets").workers.add([ + new api.ODWorker("openticket:clear-tickets",2,async (instance,params,source,cancel) => { + const {guild,channel,user,filter,list} = params + + await openticket.events.get("onTicketsClear").emit([list,user,channel,filter]) + const nameList: string[] = [] + for (const ticket of list){ + const ticketChannel = await openticket.tickets.getTicketChannel(ticket) + if (!ticketChannel) return + nameList.push("#"+ticketChannel.name) + await openticket.actions.get("openticket:delete-ticket").run("clear",{guild,channel:ticketChannel,user,ticket,reason:"Cleared Ticket",sendMessage:true,withoutTranscript:false}) + } + instance.list = nameList + await openticket.events.get("afterTicketsCleared").emit([list,user,channel,filter]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,filter,list} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.deleting.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:clear-logs").build(source,{guild,channel,user,filter,list:instance.list ?? []})) + } + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,user,filter,list} = params + openticket.log(user.displayName+" cleared "+list.length+" tickets!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"method",value:source}, + {key:"filter",value:filter} + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/actions/closeTicket.ts b/src/actions/closeTicket.ts new file mode 100644 index 0000000..ded141e --- /dev/null +++ b/src/actions/closeTicket.ts @@ -0,0 +1,328 @@ +/////////////////////////////////////// +//TICKET CLOSING SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:close-ticket")) + openticket.actions.get("openticket:close-ticket").workers.add([ + new api.ODWorker("openticket:close-ticket",2,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to close ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketClose").emit([ticket,user,channel,reason]) + + //update ticket + ticket.get("openticket:closed").value = true + if (source == "autoclose") ticket.get("openticket:autoclosed").value = true + ticket.get("openticket:open").value = false + ticket.get("openticket:closed-by").value = user.id + ticket.get("openticket:closed-on").value = new Date().getTime() + ticket.get("openticket:busy").value = true + + //update stats + openticket.stats.get("openticket:global").setStat("openticket:tickets-closed",1,"increase") + openticket.stats.get("openticket:user").setStat("openticket:tickets-closed",user.id,1,"increase") + + //update category + const closeCategory = ticket.option.get("openticket:channel-category-closed").value + if (closeCategory !== ""){ + try { + channel.setParent(closeCategory,{lockPermissions:false}) + ticket.get("openticket:category-mode").value = "closed" + ticket.get("openticket:category").value = closeCategory + }catch(e){ + openticket.log("Unable to move ticket to 'closed category'!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"categoryid",value:closeCategory} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //update permissions (non-staff => readonly) + const permissions: discord.OverwriteResolvable[] = [{ + type:discord.OverwriteType.Role, + id:guild.roles.everyone.id, + allow:[], + deny:["ViewChannel","SendMessages","ReadMessageHistory"] + }] + const globalAdmins = openticket.configs.get("openticket:general").data.globalAdmins + const optionAdmins = ticket.option.get("openticket:admins").value + const readonlyAdmins = ticket.option.get("openticket:admins-readonly").value + + globalAdmins.forEach((admin) => { + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory","ManageMessages"], + deny:[] + }) + }) + optionAdmins.forEach((admin) => { + if (globalAdmins.includes(admin)) return + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory","ManageMessages"], + deny:[] + }) + }) + readonlyAdmins.forEach((admin) => { + if (globalAdmins.includes(admin)) return + if (optionAdmins.includes(admin)) return + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","ReadMessageHistory"], + deny:["SendMessages","AddReactions","AttachFiles","SendPolls"] + }) + }) + ticket.get("openticket:participants").value.forEach((participant) => { + //all participants that aren't roles/admins => readonly + if (participant.type == "user"){ + permissions.push({ + type:discord.OverwriteType.Member, + id:user.id, + allow:["ViewChannel","ReadMessageHistory"], + deny:["SendMessages","AddReactions","AttachFiles","SendPolls"] + }) + } + }) + channel.permissionOverwrites.set(permissions) + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket closing!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //reply with new message + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:close-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("openticket:busy").value = false + await openticket.events.get("afterTicketClosed").emit([ticket,user,channel,reason]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.closing.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) + } + + //to dm + if (generalConfig.data.system.messages.closing.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket} = params + + openticket.log(user.displayName+" closed a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source} + ]) + }) + ]) + openticket.actions.get("openticket:close-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + }) +} + +export const registerVerifyBars = async () => { + //CLOSE TICKET TICKET MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:close-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:close-ticket-ticket-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.close + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:close-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when already closed + if (ticket.get("openticket:closed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start closing ticket + if (params.data == "reason"){ + //close with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:close-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + }else{ + //close without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:close-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + } + }) + ]) + openticket.verifybars.get("openticket:close-ticket-ticket-message").failure.add([ + new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }) + ]) + + //CLOSE TICKET REOPEN MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:close-ticket-reopen-message",openticket.builders.messages.getSafe("openticket:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:close-ticket-reopen-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.close + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:close-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when already closed + if (ticket.get("openticket:closed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start closing ticket + if (params.data == "reason"){ + //close with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:close-ticket-reason").build("reopen-message",{guild,channel,user,ticket})) + }else{ + //close without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:close-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:close-message").build("reopen-message",{guild,channel,user,ticket,reason:null})) + } + }) + ]) + openticket.verifybars.get("openticket:close-ticket-reopen-message").failure.add([ + new api.ODWorker("openticket:back-to-reopen-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const {verifybarMessage} = params + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + }) + ]) +} \ No newline at end of file diff --git a/src/actions/createTicket.ts b/src/actions/createTicket.ts new file mode 100644 index 0000000..8bd8c36 --- /dev/null +++ b/src/actions/createTicket.ts @@ -0,0 +1,229 @@ +/////////////////////////////////////// +//TICKET CREATION SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:create-ticket")) + openticket.actions.get("openticket:create-ticket").workers.add([ + new api.ODWorker("openticket:create-ticket",3,async (instance,params,source,cancel) => { + const {guild,user,answers,option} = params + + await openticket.events.get("onTicketCreate").emit([user]) + await openticket.events.get("onTicketChannelCreation").emit([option,user]) + + //get channel properties + const channelPrefix = option.get("openticket:channel-prefix").value + const channelCategory = option.get("openticket:channel-category").value + const channelBackupCategory = option.get("openticket:channel-category-backup").value + const channelDescription = option.get("openticket:channel-description").value + const channelSuffix = openticket.options.suffix.getSuffixFromOption(option,user) + const channelName = channelPrefix+channelSuffix + + //handle category + let category: string|null = null + let categoryMode: "backup"|"normal"|null = null + if (channelCategory != ""){ + //category enabled + const normalCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelCategory) + if (!normalCategory){ + //default category was not found + openticket.log("Ticket Creation Error: Unable to find category! #1","error",[ + {key:"categoryid",value:channelCategory}, + {key:"backup",value:"false"} + ]) + }else{ + //default category was found + if (normalCategory.children.cache.size >= 50 && channelBackupCategory != ""){ + //use backup category + const backupCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelBackupCategory) + if (!backupCategory){ + //default category was not found + openticket.log("Ticket Creation Error: Unable to find category! #2","error",[ + {key:"categoryid",value:channelBackupCategory}, + {key:"backup",value:"true"} + ]) + }else{ + category = backupCategory.id + categoryMode = "backup" + } + }else{ + //use default category + category = normalCategory.id + categoryMode = "normal" + } + } + } + + //handle permissions + const permissions: discord.OverwriteResolvable[] = [{ + type:discord.OverwriteType.Role, + id:guild.roles.everyone.id, + allow:[], + deny:["ViewChannel","SendMessages","ReadMessageHistory"] + }] + const globalAdmins = openticket.configs.get("openticket:general").data.globalAdmins + const optionAdmins = option.get("openticket:admins").value + const readonlyAdmins = option.get("openticket:admins-readonly").value + + globalAdmins.forEach((admin) => { + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory","ManageMessages"], + deny:[] + }) + }) + optionAdmins.forEach((admin) => { + if (globalAdmins.includes(admin)) return + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory","ManageMessages"], + deny:[] + }) + }) + readonlyAdmins.forEach((admin) => { + if (globalAdmins.includes(admin)) return + if (optionAdmins.includes(admin)) return + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","ReadMessageHistory"], + deny:["SendMessages","AddReactions","AttachFiles","SendPolls"] + }) + }) + permissions.push({ + type:discord.OverwriteType.Member, + id:user.id, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory"], + deny:[] + }) + + //create channel + const channel = await guild.channels.create({ + type:discord.ChannelType.GuildText, + name:channelName, + nsfw:false, + topic:channelDescription, + parent:category, + reason:"Ticket Created By "+user.displayName, + permissionOverwrites:permissions + }) + + await openticket.events.get("afterTicketChannelCreated").emit([option,channel,user]) + + //create participants + const participants: {type:"role"|"user",id:string}[] = [] + permissions.forEach((permission,index) => { + if (index == 0) return //don't include @everyone + const type = (permission.type == discord.OverwriteType.Role) ? "role" : "user" + const id = permission.id as string + participants.push({type,id}) + }) + + //create ticket + const ticket = new api.ODTicket(channel.id,option,[ + new api.ODTicketData("openticket:busy",false), + new api.ODTicketData("openticket:ticket-message",null), + new api.ODTicketData("openticket:participants",participants), + new api.ODTicketData("openticket:channel-suffix",channelSuffix), + + new api.ODTicketData("openticket:open",true), + new api.ODTicketData("openticket:opened-by",user.id), + new api.ODTicketData("openticket:opened-on",new Date().getTime()), + new api.ODTicketData("openticket:closed",false), + new api.ODTicketData("openticket:closed-by",null), + new api.ODTicketData("openticket:closed-on",null), + new api.ODTicketData("openticket:claimed",false), + new api.ODTicketData("openticket:claimed-by",null), + new api.ODTicketData("openticket:claimed-on",null), + new api.ODTicketData("openticket:pinned",false), + new api.ODTicketData("openticket:pinned-by",null), + new api.ODTicketData("openticket:pinned-on",null), + new api.ODTicketData("openticket:for-deletion",false), + + new api.ODTicketData("openticket:category",category), + new api.ODTicketData("openticket:category-mode",categoryMode), + + new api.ODTicketData("openticket:autoclose-enabled",option.get("openticket:autoclose-enable-hours").value), + new api.ODTicketData("openticket:autoclose-hours",(option.get("openticket:autoclose-enable-hours").value ? option.get("openticket:autoclose-hours").value : 0)), + new api.ODTicketData("openticket:autoclosed",false), + new api.ODTicketData("openticket:autodelete-enabled",option.get("openticket:autodelete-enable-days").value), + new api.ODTicketData("openticket:autodelete-days",(option.get("openticket:autodelete-enable-days").value ? option.get("openticket:autodelete-days").value : 0)), + + new api.ODTicketData("openticket:answers",answers) + ]) + + //manage stats + openticket.stats.get("openticket:global").setStat("openticket:tickets-created",1,"increase") + openticket.stats.get("openticket:user").setStat("openticket:tickets-created",user.id,1,"increase") + + //manage bot permissions + await openticket.events.get("onTicketPermissionsCreated").emit([option,openticket.permissions,channel,user]) + await (await import("../data/framework/permissionLoader.ts")).addTicketPermissions(ticket) + await openticket.events.get("afterTicketPermissionsCreated").emit([option,openticket.permissions,channel,user]) + + //export channel & ticket + instance.channel = channel + instance.ticket = ticket + openticket.tickets.add(ticket) + }), + new api.ODWorker("openticket:send-ticket-message",2,async (instance,params,source,cancel) => { + const {guild,user,answers,option} = params + const {ticket,channel} = instance + + if (!ticket || !channel) return openticket.log("Ticket Creation Error: Unable to send ticket message. Previous worker failed!","error") + + await openticket.events.get("onTicketMainMessageCreated").emit([ticket,channel,user]) + //check if ticket message is enabled + if (!option.get("openticket:ticket-message-enabled").value) return + try { + const msg = await channel.send((await openticket.builders.messages.getSafe("openticket:ticket-message").build(source,{guild,channel,user,ticket})).message) + + ticket.get("openticket:ticket-message").value = msg.id + + //manage stats + openticket.stats.get("openticket:ticket").setStat("openticket:messages-sent",ticket.id.value,1,"increase") + + await openticket.events.get("afterTicketMainMessageCreated").emit([ticket,msg,channel,user]) + }catch(err){ + process.emit("uncaughtException",err) + //something went wrong while sending the ticket message + channel.send((await openticket.builders.messages.getSafe("openticket:error").build("other",{guild,channel,user,error:"Ticket Message: Creation Error!\n=> Ticket Is Still Created Succesfully",layout:"advanced"})).message) + } + await openticket.events.get("afterTicketCreated").emit([ticket,user,channel]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,user,answers,option} = params + const {ticket,channel} = instance + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.creation.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-created-logs").build(source,{guild,channel,user,ticket})) + } + + //to dm + if (generalConfig.data.system.messages.creation.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-created-dm").build(source,{guild,channel,user,ticket})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,user,answers,option} = params + const {ticket,channel} = instance + + if (!ticket || !channel) return openticket.log("Ticket Creation Error: Unable to create logs. Previous worker failed!","error") + + openticket.log(user.displayName+" created a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"method",value:source}, + {key:"option",value:option.id.value} + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/actions/createTicketPermissions.ts b/src/actions/createTicketPermissions.ts new file mode 100644 index 0000000..342cbb4 --- /dev/null +++ b/src/actions/createTicketPermissions.ts @@ -0,0 +1,106 @@ +/////////////////////////////////////// +//TICKET CREATION SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:create-ticket-permissions")) + openticket.actions.get("openticket:create-ticket-permissions").workers.add([ + new api.ODWorker("openticket:check-blacklist",4,(instance,params,source,cancel) => { + if (!params.option.get("openticket:allow-blacklisted-users").value && openticket.blacklist.exists(params.user.id)){ + instance.valid = false + instance.reason = "blacklist" + openticket.log(params.user.displayName+" tried to create a ticket but is blacklisted!","info",[ + {key:"user",value:params.user.username}, + {key:"userid",value:params.user.id,hidden:true}, + {key:"option",value:params.option.id.value} + ]) + return cancel() + } + }), + new api.ODWorker("openticket:check-cooldown",3,(instance,params,source,cancel) => { + const cooldown = openticket.cooldowns.get("openticket:option-cooldown_"+params.option.id.value) + if (cooldown && cooldown instanceof api.ODTimeoutCooldown && cooldown.use(params.user.id)){ + instance.valid = false + instance.reason = "cooldown" + const remaining = cooldown.remaining(params.user.id) ?? 0 + instance.cooldownUntil = new Date(new Date().getTime() + remaining) + + openticket.log(params.user.displayName+" tried to create a ticket but is on cooldown!","info",[ + {key:"user",value:params.user.username}, + {key:"userid",value:params.user.id,hidden:true}, + {key:"option",value:params.option.id.value}, + {key:"remaining",value:(remaining/1000).toString()+"sec"} + ]) + return cancel() + } + }), + new api.ODWorker("openticket:check-global-limits",2,(instance,params,source,cancel) => { + const generalConfig = openticket.configs.get("openticket:general") + if (!generalConfig.data.system.limits.enabled) return + + const allTickets = openticket.tickets.getAll() + const globalTicketCount = allTickets.length + const userTickets = openticket.tickets.getFiltered((ticket) => ticket.exists("openticket:opened-by") && (ticket.get("openticket:opened-by").value == params.user.id)) + const userTicketCount = userTickets.length + + if (globalTicketCount >= generalConfig.data.system.limits.globalMaximum){ + instance.valid = false + instance.reason = "global-limit" + openticket.log(params.user.displayName+" tried to create a ticket but reached the limit!","info",[ + {key:"user",value:params.user.username}, + {key:"userid",value:params.user.id,hidden:true}, + {key:"option",value:params.option.id.value}, + {key:"limit",value:"global"} + ]) + return cancel() + }else if (userTicketCount >= generalConfig.data.system.limits.userMaximum){ + instance.valid = false + instance.reason = "global-user-limit" + openticket.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ + {key:"user",value:params.user.username}, + {key:"userid",value:params.user.id,hidden:true}, + {key:"option",value:params.option.id.value}, + {key:"limit",value:"global-user"} + ]) + return cancel() + } + }), + new api.ODWorker("openticket:check-option-limits",1,(instance,params,source,cancel) => { + if (!params.option.exists("openticket:limits-enabled") || !params.option.get("openticket:limits-enabled").value) return + + const allTickets = openticket.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value) + const globalTicketCount = allTickets.length + const userTickets = openticket.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value && ticket.exists("openticket:opened-by") && (ticket.get("openticket:opened-by").value == params.user.id)) + const userTicketCount = userTickets.length + + if (globalTicketCount >= params.option.get("openticket:limits-maximum-global").value){ + instance.valid = false + instance.reason = "option-limit" + openticket.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ + {key:"user",value:params.user.username}, + {key:"userid",value:params.user.id,hidden:true}, + {key:"option",value:params.option.id.value}, + {key:"limit",value:"option"} + ]) + return cancel() + }else if (userTicketCount >= params.option.get("openticket:limits-maximum-user").value){ + instance.valid = false + instance.reason = "option-user-limit" + openticket.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ + {key:"user",value:params.user.username}, + {key:"userid",value:params.user.id,hidden:true}, + {key:"option",value:params.option.id.value}, + {key:"limit",value:"option-user"} + ]) + return cancel() + } + }), + new api.ODWorker("openticket:valid",0,(instance,params,source,cancel) => { + instance.valid = true + instance.reason = null + cancel() + }) + ]) +} \ No newline at end of file diff --git a/src/actions/createTranscript.ts b/src/actions/createTranscript.ts new file mode 100644 index 0000000..e95dc29 --- /dev/null +++ b/src/actions/createTranscript.ts @@ -0,0 +1,164 @@ +/////////////////////////////////////// +//TRANSCRIPT CREATION SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const transcriptConfig = openticket.configs.get("openticket:transcripts") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:create-transcript")) + openticket.actions.get("openticket:create-transcript").workers.add([ + new api.ODWorker("openticket:select-compiler",4,async (instance,params,source,cancel) => { + const {channel,user,ticket} = params + if (channel.type != discord.ChannelType.GuildText) return cancel() + if (!transcriptConfig.data.general.enabled) return cancel() + + await openticket.events.get("onTranscriptCreate").emit([openticket.transcripts,ticket,channel,user]) + + instance.errorReason = null + const participants = await openticket.tickets.getAllTicketParticipants(params.ticket) + if (!participants){ + instance.pendingMessage = null + instance.errorReason = "Unable to fetch ticket channel participants!" + throw new api.ODSystemError("ODAction(ot:create-transcript) => Unable to fetch ticket channel participants!") + } + instance.participants = participants + + //select transcript compiler + if (transcriptConfig.data.general.mode == "text") instance.compiler = openticket.transcripts.get("openticket:text-compiler") + else if (transcriptConfig.data.general.mode == "html") instance.compiler = openticket.transcripts.get("openticket:html-compiler") + }), + new api.ODWorker("openticket:init-transcript",3,async (instance,params,source,cancel) => { + const {channel,user,ticket} = params + if (channel.type != discord.ChannelType.GuildText) return cancel() + if (!transcriptConfig.data.general.enabled) return cancel() + + //run transcript compiler init() + await openticket.events.get("onTranscriptInit").emit([openticket.transcripts,ticket,channel,user]) + if (instance.compiler.init){ + try{ + const result = await instance.compiler.init(ticket,channel,user) + if (result.success && result.pendingMessage && transcriptConfig.data.general.enableChannel){ + //send init message to channel + const post = openticket.posts.get("openticket:transcripts") + if (post){ + instance.pendingMessage = await post.send(result.pendingMessage) + } + }else if (!result.success){ + instance.pendingMessage = null + instance.errorReason = result.errorReason + throw new api.ODSystemError("ODAction(ot:create-transcript) => Known Init Error => "+result.errorReason) + }else instance.pendingMessage = null + }catch(err){ + instance.success = false + cancel() + process.emit("uncaughtException",err) + throw new api.ODSystemError("ODAction(ot:create-transcript) => Failed transcript compiler init()! (see error above)") + } + } + await openticket.events.get("afterTranscriptInitiated").emit([openticket.transcripts,ticket,channel,user]) + }), + new api.ODWorker("openticket:compile-transcript",2,async (instance,params,source,cancel) => { + const {channel,user,ticket} = params + if (channel.type != discord.ChannelType.GuildText) return cancel() + if (!instance.compiler){ + instance.success = false + cancel() + throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:compile-transcript) => Instance is missing transcript compiler!") + } + + //run transcript compiler compile() + await openticket.events.get("onTranscriptCompile").emit([openticket.transcripts,ticket,channel,user]) + if (instance.compiler.compile){ + try{ + const result = await instance.compiler.compile(ticket,channel,user) + if (!result.success){ + instance.errorReason = result.errorReason + throw new api.ODSystemError("ODAction(ot:create-transcript) => Known Compiler Error => "+result.errorReason) + }else{ + instance.result = result + instance.success = true + } + }catch(err){ + instance.success = false + cancel() + process.emit("uncaughtException",err) + throw new api.ODSystemError("ODAction(ot:create-transcript) => Failed transcript compiler compile()! (see error above)") + } + } + await openticket.events.get("afterTranscriptCompiled").emit([openticket.transcripts,ticket,channel,user]) + }), + new api.ODWorker("openticket:ready-transcript",1,async (instance,params,source,cancel) => { + if (!instance.result){ + instance.success = false + cancel() + throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript result!") + } + + //run transcript compiler ready() + utilities.runAsync(async () => { + await openticket.events.get("onTranscriptReady").emit([openticket.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) + if (instance.compiler.ready){ + try{ + const {channelMessage,creatorDmMessage,participantDmMessage,activeAdminDmMessage,everyAdminDmMessage} = await instance.compiler.ready(instance.result) + + //send channel message + if (transcriptConfig.data.general.enableChannel && channelMessage){ + if (instance.pendingMessage && instance.pendingMessage.message && instance.pendingMessage.success){ + //edit "pending" message to be the "ready" message + instance.pendingMessage.message.edit(channelMessage.message) + }else{ + //send ready message to channel + const post = openticket.posts.get("openticket:transcripts") + if (post) await post.send(channelMessage) + } + } + + //send dm mesages + if (instance.participants){ + for (const p of instance.participants){ + if (p.role == "creator" && transcriptConfig.data.general.enableCreatorDM && creatorDmMessage){ + //send creator dm message + await openticket.client.sendUserDm(p.user,creatorDmMessage) + }else if (p.role == "participant" && transcriptConfig.data.general.enableParticipantDM && participantDmMessage){ + //send participant dm message + await openticket.client.sendUserDm(p.user,participantDmMessage) + }else if (p.role == "admin" && transcriptConfig.data.general.enableActiveAdminDM && instance.result.success && instance.result.messages && instance.result.messages.some((msg) => msg.author.id == p.user.id) && activeAdminDmMessage){ + //send active admin dm message + await openticket.client.sendUserDm(p.user,activeAdminDmMessage) + }else if (p.role == "admin" && transcriptConfig.data.general.enableEveryAdminDM && everyAdminDmMessage){ + //send every admin dm message + await openticket.client.sendUserDm(p.user,everyAdminDmMessage) + } + } + } + + }catch(err){ + instance.success = false + cancel() + process.emit("uncaughtException",err) + throw new api.ODSystemError("ODAction(ot:create-transcript) => Failed transcript compiler ready()! (see error above)") + } + } + await openticket.events.get("afterTranscriptReady").emit([openticket.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) + }) + + //update stats + openticket.stats.get("openticket:global").setStat("openticket:transcripts-created",1,"increase") + await openticket.events.get("afterTranscriptCreated").emit([openticket.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {user,channel,ticket} = params + openticket.log(user.displayName+" created a transcript!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"option",value:ticket.option.id.value}, + {key:"method",value:source,hidden:true}, + {key:"compiler",value:instance.compiler.id.value}, + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/actions/deleteTicket.ts b/src/actions/deleteTicket.ts new file mode 100644 index 0000000..6988b5e --- /dev/null +++ b/src/actions/deleteTicket.ts @@ -0,0 +1,463 @@ +/////////////////////////////////////// +//TICKET DELETION SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:delete-ticket")) + openticket.actions.get("openticket:delete-ticket").workers.add([ + new api.ODWorker("openticket:delete-ticket",3,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to delete ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketDelete").emit([ticket,user,channel,reason]) + + //update ticket + ticket.get("openticket:for-deletion").value = true + ticket.get("openticket:busy").value = true + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket deletion!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:delete-message").build(source,{guild,channel,user,ticket,reason})).message) + + //create transcript + if (!params.withoutTranscript){ + const transcriptRes = await openticket.actions.get("openticket:create-transcript").run(source,{guild,channel,user,ticket}) + if (typeof transcriptRes.success == "boolean" && !transcriptRes.success && transcriptRes.compiler){ + const {compiler} = transcriptRes + await channel.send((await openticket.builders.messages.getSafe("openticket:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason:transcriptRes.errorReason ?? null})).message) + + //undo deletion + ticket.get("openticket:for-deletion").value = false + ticket.get("openticket:busy").value = false + openticket.log("Canceled ticket deletion because of transcript system malfunction!","warning",[ + {key:"compiler",value:compiler.id.value}, + {key:"reason",value:transcriptRes.errorReason ?? "/"}, + ]) + return cancel() + } + } + + //update stats + openticket.stats.get("openticket:global").setStat("openticket:tickets-deleted",1,"increase") + openticket.stats.get("openticket:user").setStat("openticket:tickets-deleted",user.id,1,"increase") + + //delete ticket from manager + openticket.tickets.remove(ticket.id) + + //delete permissions from manager + await (await import("../data/framework/permissionLoader.ts")).removeTicketPermissions(ticket) + }), + new api.ODWorker("openticket:discord-logs",2,async (instance,params,source,cancel) => { + //logs before channel deletion => channel might still be used in log embeds + const {guild,channel,user,ticket,reason} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.deleting.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) + } + + //to dm + if (generalConfig.data.system.messages.deleting.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) + }), + new api.ODWorker("openticket:delete-channel",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + //delete channel & events + await openticket.events.get("onTicketChannelDeletion").emit([ticket,channel,user]) + await channel.delete("Ticket Deleted") + await openticket.events.get("afterTicketChannelDeleted").emit([ticket,user]) + + //delete permissions from manager + await (await import("../data/framework/permissionLoader.ts")).removeTicketPermissions(ticket) + + await openticket.events.get("afterTicketDeleted").emit([ticket,user,reason]) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket} = params + + openticket.log(user.displayName+" deleted a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source}, + {key:"transcript",value:(!params.withoutTranscript).toString()}, + ]) + }) + ]) + openticket.actions.get("openticket:delete-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + params.ticket.get("openticket:for-deletion").value = false + }) +} + +export const registerVerifyBars = async () => { + //DELETE TICKET TICKET MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:delete-ticket-ticket-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.delete + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start deleting ticket + if (params.data == "reason"){ + //delete with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:delete-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + }else{ + //delete without reason + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true,withoutTranscript:(params.data == "no-transcript")}) + //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable + ticket.get("openticket:for-deletion").value = true + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + } + }) + ]) + openticket.verifybars.get("openticket:delete-ticket-ticket-message").failure.add([ + new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }) + ]) + + //DELETE TICKET CLOSE MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-close-message",openticket.builders.messages.getSafe("openticket:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:delete-ticket-close-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.delete + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start deleting ticket + if (params.data == "reason"){ + //delete with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:delete-ticket-reason").build("close-message",{guild,channel,user,ticket})) + }else{ + //delete without reason + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) + //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable + ticket.get("openticket:for-deletion").value = true + await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("close-message",{guild,channel,user,ticket,reason:null})) + } + }) + ]) + openticket.verifybars.get("openticket:delete-ticket-close-message").failure.add([ + new api.ODWorker("openticket:back-to-close-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const {verifybarMessage} = params + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + await instance.update(await openticket.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + }) + ]) + + //DELETE TICKET REOPEN MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-reopen-message",openticket.builders.messages.getSafe("openticket:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:delete-ticket-reopen-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.delete + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start deleting ticket + if (params.data == "reason"){ + //delete with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:delete-ticket-reason").build("reopen-message",{guild,channel,user,ticket})) + }else{ + //delete without reason + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) + //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable + ticket.get("openticket:for-deletion").value = true + await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("reopen-message",{guild,channel,user,ticket,reason:null})) + } + }) + ]) + openticket.verifybars.get("openticket:delete-ticket-reopen-message").failure.add([ + new api.ODWorker("openticket:back-to-reopen-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const {verifybarMessage} = params + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + }) + ]) + + //DELETE TICKET AUTOCLOSE MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-autoclose-message",openticket.builders.messages.getSafe("openticket:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:delete-ticket-autoclose-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.delete + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start deleting ticket + if (params.data == "reason"){ + //delete with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:delete-ticket-reason").build("autoclose-message",{guild,channel,user,ticket})) + }else{ + //delete without reason + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) + //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable + ticket.get("openticket:for-deletion").value = true + await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("autoclose-message",{guild,channel,user,ticket,reason:null})) + } + }) + ]) + openticket.verifybars.get("openticket:delete-ticket-autoclose-message").failure.add([ + new api.ODWorker("openticket:back-to-autoclose-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const {verifybarMessage} = params + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + await instance.update(await openticket.builders.messages.getSafe("openticket:autoclose-message").build("other",{guild,channel,user,ticket})) + }) + ]) +} \ No newline at end of file diff --git a/src/actions/handleTranscriptErrors.ts b/src/actions/handleTranscriptErrors.ts new file mode 100644 index 0000000..e15eae6 --- /dev/null +++ b/src/actions/handleTranscriptErrors.ts @@ -0,0 +1,164 @@ +/////////////////////////////////////// +//TRANSCRIPT ERROR SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerButtonResponders = async () => { + //TRANSCRIPT ERROR RETRY + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:transcript-error-retry",/^od:transcript-error-retry_([^_]+)/)) + openticket.responders.buttons.get("openticket:transcript-error-retry").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.delete + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const originalSource = instance.interaction.customId.split("_")[1] + if (originalSource != "slash" && originalSource != "text" && originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "other") return + + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start deleting ticket (without reason) + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Retried)",sendMessage:false,withoutTranscript:false}) + //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable + ticket.get("openticket:for-deletion").value = true + await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Retried)"})) + + }), + new api.ODWorker("openticket:logs",-1,async (instance,params,source,cancel) => { + const {user,channel} = instance + if (channel.isDMBased()) return + openticket.log(user.displayName+" retried deleting a ticket with transcript!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) + + //TRANSCRIPT ERROR CONTINUE + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:transcript-error-continue",/^od:transcript-error-continue_([^_]+)/)) + openticket.responders.buttons.get("openticket:transcript-error-continue").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.delete + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const originalSource = instance.interaction.customId.split("_")[1] + if (originalSource != "slash" && originalSource != "text" && originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "other") return + + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start deleting ticket (without reason) + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Continued)",sendMessage:false,withoutTranscript:true}) + //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable + ticket.get("openticket:for-deletion").value = true + await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Continued)"})) + + }), + new api.ODWorker("openticket:logs",-1,async (instance,params,source,cancel) => { + const {user,channel} = instance + if (channel.isDMBased()) return + openticket.log(user.displayName+" continued deleting a ticket without transcript!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/actions/handleVerifyBar.ts b/src/actions/handleVerifyBar.ts new file mode 100644 index 0000000..4154a4b --- /dev/null +++ b/src/actions/handleVerifyBar.ts @@ -0,0 +1,32 @@ +/////////////////////////////////////// +//VERIFYBAR SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" + +export const registerButtonResponders = async () => { + //VERIFYBAR SUCCESS + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:verifybar-success",/^od:verifybar-success_([^_]+)/)) + openticket.responders.buttons.get("openticket:verifybar-success").workers.add( + new api.ODWorker("openticket:handle-verifybar",0,async (instance,params,source,cancel) => { + const id = instance.interaction.customId.split("_")[1] + const customData = instance.interaction.customId.split("_")[2] as string|undefined + + const verifybar = openticket.verifybars.get(id) + if (!verifybar) return + if (verifybar.success) await verifybar.success.executeWorkers(instance,"verifybar",{data:customData ?? null,verifybarMessage:instance.message}) + }) + ) + + //VERIFYBAR FAILURE + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:verifybar-failure",/^od:verifybar-failure_([^_]+)/)) + openticket.responders.buttons.get("openticket:verifybar-failure").workers.add( + new api.ODWorker("openticket:handle-verifybar",0,async (instance,params,source,cancel) => { + const id = instance.interaction.customId.split("_")[1] + const customData = instance.interaction.customId.split("_")[2] as string|undefined + + const verifybar = openticket.verifybars.get(id) + if (!verifybar) return + if (verifybar.failure) await verifybar.failure.executeWorkers(instance,"verifybar",{data:customData ?? null,verifybarMessage:instance.message}) + }) + ) +} \ No newline at end of file diff --git a/src/actions/moveTicket.ts b/src/actions/moveTicket.ts new file mode 100644 index 0000000..7d95b82 --- /dev/null +++ b/src/actions/moveTicket.ts @@ -0,0 +1,220 @@ +/////////////////////////////////////// +//TICKET MOVING SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:move-ticket")) + openticket.actions.get("openticket:move-ticket").workers.add([ + new api.ODWorker("openticket:move-ticket",2,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason,data} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to move ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketMove").emit([ticket,user,channel,reason]) + ticket.option = data + + //update stats + openticket.stats.get("openticket:global").setStat("openticket:tickets-moved",1,"increase") + openticket.stats.get("openticket:user").setStat("openticket:tickets-moved",user.id,1,"increase") + + //get new channel properties + const channelPrefix = ticket.option.get("openticket:channel-prefix").value + const channelSuffix = ticket.get("openticket:channel-suffix").value + const channelCategory = ticket.option.get("openticket:channel-category").value + const channelBackupCategory = ticket.option.get("openticket:channel-category-backup").value + const rawClaimCategory = ticket.option.get("openticket:channel-categories-claimed").value.find((c) => c.user == user.id) + const claimCategory = (rawClaimCategory) ? rawClaimCategory.category : null + const closeCategory = ticket.option.get("openticket:channel-category-closed").value + const channelDescription = ticket.option.get("openticket:channel-description").value + const channelName = channelPrefix+channelSuffix + + //handle category + let category: string|null = null + let categoryMode: "backup"|"normal"|"closed"|"claimed"|null = null + if (claimCategory){ + //use claim category + category = claimCategory + categoryMode = "claimed" + }else if (closeCategory != "" && ticket.get("openticket:closed").value){ + //use close category + category = closeCategory + categoryMode = "closed" + }else if (channelCategory != ""){ + //category enabled + const normalCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelCategory) + if (!normalCategory){ + //default category was not found + openticket.log("Ticket Move Error: Unable to find category! #1","error",[ + {key:"categoryid",value:channelCategory}, + {key:"backup",value:"false"} + ]) + }else{ + //default category was found + if (normalCategory.children.cache.size >= 50 && channelBackupCategory != ""){ + //use backup category + const backupCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelBackupCategory) + if (!backupCategory){ + //default category was not found + openticket.log("Ticket Move Error: Unable to find category! #2","error",[ + {key:"categoryid",value:channelBackupCategory}, + {key:"backup",value:"true"} + ]) + }else{ + category = backupCategory.id + categoryMode = "backup" + } + }else{ + //use default category + category = normalCategory.id + categoryMode = "normal" + } + } + } + + try { + //only move category when not the same. + if (channel.parentId != category) await utilities.timedAwait(channel.setParent(category,{lockPermissions:false}),2500,(err) => { + openticket.log("Failed to change channel category on ticket move","error") + }) + ticket.get("openticket:category-mode").value = categoryMode + ticket.get("openticket:category").value = category + }catch(e){ + openticket.log("Unable to move ticket to 'moved category'!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"categoryid",value:category ?? "/"} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + + //handle permissions + const permissions: discord.OverwriteResolvable[] = [{ + type:discord.OverwriteType.Role, + id:guild.roles.everyone.id, + allow:[], + deny:["ViewChannel","SendMessages","ReadMessageHistory"] + }] + const globalAdmins = openticket.configs.get("openticket:general").data.globalAdmins + const optionAdmins = ticket.option.get("openticket:admins").value + const readonlyAdmins = ticket.option.get("openticket:admins-readonly").value + + globalAdmins.forEach((admin) => { + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory","ManageMessages"], + deny:[] + }) + }) + optionAdmins.forEach((admin) => { + if (globalAdmins.includes(admin)) return + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory","ManageMessages"], + deny:[] + }) + }) + readonlyAdmins.forEach((admin) => { + if (globalAdmins.includes(admin)) return + if (optionAdmins.includes(admin)) return + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","ReadMessageHistory"], + deny:["SendMessages","AddReactions","AttachFiles","SendPolls"] + }) + }) + //transfer all old user-participants over to the new ticket (creator & participants) + ticket.get("openticket:participants").value.forEach((p) => { + if (p.type == "user") permissions.push({ + type:discord.OverwriteType.Member, + id:p.id, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory"], + deny:[] + }) + }) + try{ + await channel.permissionOverwrites.set(permissions) + }catch{ + openticket.log("Failed to reset channel permissions on ticket move!","error") + } + + //handle participants + const participants: {type:"role"|"user",id:string}[] = [] + permissions.forEach((permission,index) => { + if (index == 0) return //don't include @everyone + const type = (permission.type == discord.OverwriteType.Role) ? "role" : "user" + const id = permission.id as string + participants.push({type,id}) + }) + ticket.get("openticket:participants").value = participants + ticket.get("openticket:participants").refreshDatabase() + + //rename channel (and give error when crashed) + const originalName = channel.name + try{ + await utilities.timedAwait(channel.setName(channelName),2500,(err) => { + openticket.log("Failed to rename channel on ticket move","error") + }) + }catch(err){ + await channel.send((await openticket.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-move",{guild,channel,user,originalName,newName:channelName})).message) + } + try{ + if (channel.type == discord.ChannelType.GuildText) channel.setTopic(channelDescription) + }catch{} + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket renaming!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //reply with new message + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:move-message").build(source,{guild,channel,user,ticket,reason,data})).message) + ticket.get("openticket:busy").value = false + await openticket.events.get("afterTicketMoved").emit([ticket,user,channel,reason]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason,data} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.moving.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) + } + + //to dm + if (generalConfig.data.system.messages.moving.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket} = params + + openticket.log(user.displayName+" moved a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source} + ]) + }) + ]) + openticket.actions.get("openticket:move-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + }) +} \ No newline at end of file diff --git a/src/actions/pinTicket.ts b/src/actions/pinTicket.ts new file mode 100644 index 0000000..3f06af4 --- /dev/null +++ b/src/actions/pinTicket.ts @@ -0,0 +1,274 @@ +/////////////////////////////////////// +//TICKET PINNING SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:pin-ticket")) + openticket.actions.get("openticket:pin-ticket").workers.add([ + new api.ODWorker("openticket:pin-ticket",2,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to pin ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketPin").emit([ticket,user,channel,reason]) + + //update ticket + ticket.get("openticket:pinned").value = true + ticket.get("openticket:pinned-by").value = user.id + ticket.get("openticket:pinned-on").value = new Date().getTime() + ticket.get("openticket:busy").value = true + + //update stats + openticket.stats.get("openticket:global").setStat("openticket:tickets-pinned",1,"increase") + openticket.stats.get("openticket:user").setStat("openticket:tickets-pinned",user.id,1,"increase") + + //move to top of category + if (channel.parent){ + await channel.setPosition(0,{reason:"Ticket Pinned!"}) + } + + //rename channel (and give error when crashed) + const originalName = channel.name + const newName = "📌"+channel.name + try{ + await utilities.timedAwait(channel.setName(newName),2500,(err) => { + openticket.log("Failed to rename channel on ticket pin","error") + }) + }catch(err){ + await channel.send((await openticket.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-pin",{guild,channel,user,originalName,newName})).message) + } + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket pinning!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"message",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //reply with new message + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:pin-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("openticket:busy").value = false + await openticket.events.get("afterTicketPinned").emit([ticket,user,channel,reason]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.pinning.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) + } + + //to dm + if (generalConfig.data.system.messages.pinning.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket} = params + + openticket.log(user.displayName+" pinned a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerVerifyBars = async () => { + //PIN TICKET TICKET MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:pin-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:pin-ticket-ticket-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.pin + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when already pinned + if (ticket.get("openticket:pinned").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start pinning ticket + if (params.data == "reason"){ + //pin with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:pin-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + }else{ + //pin without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:pin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + } + }) + ]) + openticket.verifybars.get("openticket:pin-ticket-ticket-message").failure.add([ + new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }) + ]) + + //PIN TICKET UNPIN MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:pin-ticket-unpin-message",openticket.builders.messages.getSafe("openticket:verifybar-unpin-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:pin-ticket-unpin-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.pin + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when already pinned + if (ticket.get("openticket:pinned").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start pinning ticket + if (params.data == "reason"){ + //pin with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:pin-ticket-reason").build("unpin-message",{guild,channel,user,ticket})) + }else{ + //pin without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:pin-ticket").run("unpin-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:pin-message").build("unpin-message",{guild,channel,user,ticket,reason:null})) + } + }) + ]) + openticket.verifybars.get("openticket:pin-ticket-unpin-message").failure.add([ + new api.ODWorker("openticket:back-to-unpin-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const {verifybarMessage} = params + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + await instance.update(await openticket.builders.messages.getSafe("openticket:unpin-message").build("other",{guild,channel,user,ticket,reason})) + }) + ]) + openticket.actions.get("openticket:pin-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + }) +} \ No newline at end of file diff --git a/src/actions/reactionRole.ts b/src/actions/reactionRole.ts new file mode 100644 index 0000000..884a2cd --- /dev/null +++ b/src/actions/reactionRole.ts @@ -0,0 +1,94 @@ +/////////////////////////////////////// +//REACTION ROLE SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:reaction-role")) + openticket.actions.get("openticket:reaction-role").workers.add([ + new api.ODWorker("openticket:reaction-role",2,async (instance,params,source,cancel) => { + const {guild,user,option,overwriteMode} = params + const role = openticket.roles.get(option.id) + if (!role) throw new api.ODSystemError("ODAction(ot:reaction-role) => Unknown reaction role (ODRole)") + instance.role = role + const mode = (overwriteMode) ? overwriteMode : role.get("openticket:mode").value + + await openticket.events.get("onRoleUpdate").emit([user,role]) + + //get guild member + const member = await openticket.client.fetchGuildMember(guild,user.id) + if (!member) throw new api.ODSystemError("ODAction(ot:reaction-role) => User isn't a member of the server!") + + //get all roles + const roleIds = role.get("openticket:roles").value + const roles: discord.Role[] = [] + for (const id of roleIds){ + const r = await openticket.client.fetchGuildRole(guild,id) + if (r) roles.push(r) + else openticket.log("Unable to find role in server!","warning",[ + {key:"roleid",value:id} + ]) + } + + //update roles of user + const result: api.OTRoleUpdateResult[] = [] + for (const r of roles){ + try{ + if (r.members.has(user.id) && (mode == "add&remove" || mode == "remove")){ + //user has role (remove) + await member.roles.remove(r) + result.push({role:r,action:"removed"}) + }else if (!r.members.has(user.id) && (mode == "add&remove" || mode == "add")){ + //user doesn't have role (add) + await member.roles.add(r) + result.push({role:r,action:"added"}) + }else{ + //don't do anything + result.push({role:r,action:null}) + } + }catch{ + result.push({role:r,action:null}) + } + } + + //get roles to remove on add + if (result.find((r) => r.action == "added")){ + //get all remove roles + const removeRoleIds = role.get("openticket:remove-roles-on-add").value + const removeRoles: discord.Role[] = [] + for (const id of removeRoleIds){ + const r = await openticket.client.fetchGuildRole(guild,id) + if (r) removeRoles.push(r) + else openticket.log("Unable to find role in server!","warning",[ + {key:"roleid",value:id} + ]) + } + + //remove roles from user + for (const r of removeRoles){ + try{ + if (r.members.has(user.id)){ + //user has role (remove) + await member.roles.remove(r) + result.push({role:r,action:"removed"}) + } + }catch{} + } + } + + //update instance & finish event + instance.result = result + await openticket.events.get("afterRolesUpdated").emit([user,role]) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,user,option} = params + openticket.log(user.displayName+" updated his roles!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"method",value:source}, + {key:"option",value:option.id.value} + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/actions/removeTicketUser.ts b/src/actions/removeTicketUser.ts new file mode 100644 index 0000000..b22b62b --- /dev/null +++ b/src/actions/removeTicketUser.ts @@ -0,0 +1,81 @@ +/////////////////////////////////////// +//TICKET REMOVE USER SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:remove-ticket-user")) + openticket.actions.get("openticket:remove-ticket-user").workers.add([ + new api.ODWorker("openticket:remove-ticket-user",2,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason,data} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to remove user from ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketUserRemove").emit([ticket,user,data,channel,reason]) + + //update ticket + const index = ticket.get("openticket:participants").value.findIndex((p) => p.type == "user" && p.id == data.id) + if (index < 0) return cancel() + ticket.get("openticket:participants").value.splice(index,1) + ticket.get("openticket:participants").refreshDatabase() + ticket.get("openticket:busy").value = true + + //update channel permissions + try{ + await channel.permissionOverwrites.delete(data) + }catch{ + openticket.log("Failed to remove channel permission overwrites on remove-ticket-user","error") + } + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket user removal!","error",[ + {key:"channel",value:channel.id}, + {key:"message",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //reply with new message + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:remove-message").build(source,{guild,channel,user,ticket,reason,data})).message) + ticket.get("openticket:busy").value = false + await openticket.events.get("afterTicketUserRemoved").emit([ticket,user,data,channel,reason]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason,data} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.removing.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) + } + + //to dm + if (generalConfig.data.system.messages.removing.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket,data} = params + + openticket.log(user.displayName+" removed "+data.displayName+" from a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source} + ]) + }) + ]) + openticket.actions.get("openticket:remove-ticket-user").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + }) +} \ No newline at end of file diff --git a/src/actions/renameTicket.ts b/src/actions/renameTicket.ts new file mode 100644 index 0000000..312be72 --- /dev/null +++ b/src/actions/renameTicket.ts @@ -0,0 +1,78 @@ +/////////////////////////////////////// +//TICKET RENAMING SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:rename-ticket")) + openticket.actions.get("openticket:rename-ticket").workers.add([ + new api.ODWorker("openticket:rename-ticket",2,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason,data} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to rename ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketRename").emit([ticket,user,channel,reason]) + + //rename channel (and give error when crashed) + const originalName = channel.name + try{ + await utilities.timedAwait(channel.setName(data),2500,(err) => { + openticket.log("Failed to rename channel on ticket rename","error") + }) + }catch(err){ + await channel.send((await openticket.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-rename",{guild,channel,user,originalName,newName:data})).message) + } + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket renaming!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //reply with new message + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:rename-message").build(source,{guild,channel,user,ticket,reason,data})).message) + ticket.get("openticket:busy").value = false + await openticket.events.get("afterTicketRenamed").emit([ticket,user,channel,reason]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason,data} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.renaming.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) + } + + //to dm + if (generalConfig.data.system.messages.renaming.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket} = params + + openticket.log(user.displayName+" renamed a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source} + ]) + }) + ]) + openticket.actions.get("openticket:rename-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + }) +} \ No newline at end of file diff --git a/src/actions/reopenTicket.ts b/src/actions/reopenTicket.ts new file mode 100644 index 0000000..77bd5ab --- /dev/null +++ b/src/actions/reopenTicket.ts @@ -0,0 +1,448 @@ +/////////////////////////////////////// +//TICKET REOPENING SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:reopen-ticket")) + openticket.actions.get("openticket:reopen-ticket").workers.add([ + new api.ODWorker("openticket:reopen-ticket",2,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to reopen ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketReopen").emit([ticket,user,channel,reason]) + + //update ticket + ticket.get("openticket:closed").value = false + ticket.get("openticket:open").value = true + ticket.get("openticket:autoclosed").value = false + ticket.get("openticket:closed-by").value = null + ticket.get("openticket:closed-on").value = null + ticket.get("openticket:busy").value = true + + //update stats + openticket.stats.get("openticket:global").setStat("openticket:tickets-reopened",1,"increase") + openticket.stats.get("openticket:user").setStat("openticket:tickets-reopened",user.id,1,"increase") + + //update category + const channelCategory = ticket.option.get("openticket:channel-category").value + const channelBackupCategory = ticket.option.get("openticket:channel-category-backup").value + if (channelCategory !== ""){ + //category enabled + try { + const normalCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelCategory) + if (!normalCategory){ + //default category was not found + openticket.log("Ticket Reopening Error: Unable to find category! #1","error",[ + {key:"categoryid",value:channelCategory}, + {key:"backup",value:"false"} + ]) + }else{ + //default category was found + if (normalCategory.children.cache.size >= 49 && channelBackupCategory != ""){ + //use backup category + const backupCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelBackupCategory) + if (!backupCategory){ + //default category was not found + openticket.log("Ticket Reopening Error: Unable to find category! #2","error",[ + {key:"categoryid",value:channelBackupCategory}, + {key:"backup",value:"true"} + ]) + }else{ + //use backup category + channel.setParent(backupCategory,{lockPermissions:false}) + ticket.get("openticket:category-mode").value = "backup" + ticket.get("openticket:category").value = backupCategory.id + } + }else{ + //use default category + channel.setParent(normalCategory,{lockPermissions:false}) + ticket.get("openticket:category-mode").value = "normal" + ticket.get("openticket:category").value = normalCategory.id + } + } + }catch(e){ + openticket.log("Unable to move ticket to 'reopened category'!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + }else{ + channel.setParent(null,{lockPermissions:false}) + ticket.get("openticket:category-mode").value = null + ticket.get("openticket:category").value = null + } + + //update permissions + const permissions: discord.OverwriteResolvable[] = [{ + type:discord.OverwriteType.Role, + id:guild.roles.everyone.id, + allow:[], + deny:["ViewChannel","SendMessages","ReadMessageHistory"] + }] + const globalAdmins = openticket.configs.get("openticket:general").data.globalAdmins + const optionAdmins = ticket.option.get("openticket:admins").value + const readonlyAdmins = ticket.option.get("openticket:admins-readonly").value + + globalAdmins.forEach((admin) => { + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory","ManageMessages"], + deny:[] + }) + }) + optionAdmins.forEach((admin) => { + if (globalAdmins.includes(admin)) return + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory","ManageMessages"], + deny:[] + }) + }) + readonlyAdmins.forEach((admin) => { + if (globalAdmins.includes(admin)) return + if (optionAdmins.includes(admin)) return + permissions.push({ + type:discord.OverwriteType.Role, + id:admin, + allow:["ViewChannel","ReadMessageHistory"], + deny:["SendMessages","AddReactions","AttachFiles","SendPolls"] + }) + }) + ticket.get("openticket:participants").value.forEach((participant) => { + //all participants that aren't roles/admins + if (participant.type == "user"){ + permissions.push({ + type:discord.OverwriteType.Member, + id:user.id, + allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory"], + deny:[] + }) + } + }) + channel.permissionOverwrites.set(permissions) + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket reopening!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:reopen-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("openticket:busy").value = false + await openticket.events.get("afterTicketReopened").emit([ticket,user,channel,reason]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.reopening.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) + } + + //to dm + if (generalConfig.data.system.messages.reopening.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket} = params + + openticket.log(user.displayName+" reopened a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerVerifyBars = async () => { + //REOPEN TICKET TICKET MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:reopen-ticket-ticket-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.reopen + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when not closed + if (!ticket.get("openticket:closed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start reopening ticket + if (params.data == "reason"){ + //reopen with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:reopen-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + }else{ + //reopen without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:reopen-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + } + }) + ]) + openticket.verifybars.get("openticket:reopen-ticket-ticket-message").failure.add([ + new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }) + ]) + + //REOPEN TICKET CLOSE MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-close-message",openticket.builders.messages.getSafe("openticket:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:reopen-ticket-close-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.reopen + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when not closed + if (!ticket.get("openticket:closed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start reopening ticket + if (params.data == "reason"){ + //reopen with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:reopen-ticket-reason").build("close-message",{guild,channel,user,ticket})) + }else{ + //reopen without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:reopen-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("close-message",{guild,channel,user,ticket,reason:null})) + } + }) + ]) + openticket.verifybars.get("openticket:reopen-ticket-close-message").failure.add([ + new api.ODWorker("openticket:back-to-close-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const {verifybarMessage} = params + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + await instance.update(await openticket.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + }) + ]) + + //REOPEN TICKET AUTOCLOSE MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-autoclose-message",openticket.builders.messages.getSafe("openticket:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:reopen-ticket-autoclose-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.reopen + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when not closed + if (!ticket.get("openticket:closed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start reopening ticket + if (params.data == "reason"){ + //reopen with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:reopen-ticket-reason").build("autoclose-message",{guild,channel,user,ticket})) + }else{ + //reopen without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:reopen-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("autoclose-message",{guild,channel,user,ticket,reason:null})) + } + }) + ]) + openticket.verifybars.get("openticket:reopen-ticket-autoclose-message").failure.add([ + new api.ODWorker("openticket:back-to-autoclose-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const {verifybarMessage} = params + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + await instance.update(await openticket.builders.messages.getSafe("openticket:autoclose-message").build("other",{guild,channel,user,ticket})) + }) + ]) + openticket.actions.get("openticket:reopen-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + }) +} \ No newline at end of file diff --git a/src/actions/unclaimTicket.ts b/src/actions/unclaimTicket.ts new file mode 100644 index 0000000..302fb3a --- /dev/null +++ b/src/actions/unclaimTicket.ts @@ -0,0 +1,305 @@ +/////////////////////////////////////// +//TICKET UNCLAIMING SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:unclaim-ticket")) + openticket.actions.get("openticket:unclaim-ticket").workers.add([ + new api.ODWorker("openticket:unclaim-ticket",2,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to unclaim ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketUnclaim").emit([ticket,user,channel,reason]) + + //update ticket + ticket.get("openticket:claimed").value = false + ticket.get("openticket:claimed-by").value = null + ticket.get("openticket:claimed-on").value = null + ticket.get("openticket:busy").value = true + + //update category + const channelCategory = ticket.option.get("openticket:channel-category").value + const channelBackupCategory = ticket.option.get("openticket:channel-category-backup").value + if (channelCategory !== ""){ + //category enabled + try { + const normalCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelCategory) + if (!normalCategory){ + //default category was not found + openticket.log("Ticket Unclaiming Error: Unable to find category! #1","error",[ + {key:"categoryid",value:channelCategory}, + {key:"backup",value:"false"} + ]) + }else{ + //default category was found + if (normalCategory.children.cache.size >= 49 && channelBackupCategory != ""){ + //use backup category + const backupCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelBackupCategory) + if (!backupCategory){ + //default category was not found + openticket.log("Ticket Unclaiming Error: Unable to find category! #2","error",[ + {key:"categoryid",value:channelBackupCategory}, + {key:"backup",value:"true"} + ]) + }else{ + //use backup category + channel.setParent(backupCategory,{lockPermissions:false}) + ticket.get("openticket:category-mode").value = "backup" + ticket.get("openticket:category").value = backupCategory.id + } + }else{ + //use default category + channel.setParent(normalCategory,{lockPermissions:false}) + ticket.get("openticket:category-mode").value = "normal" + ticket.get("openticket:category").value = normalCategory.id + } + } + + }catch(e){ + openticket.log("Unable to move ticket to 'unclaimed category'!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + }else{ + channel.setParent(null,{lockPermissions:false}) + ticket.get("openticket:category-mode").value = null + ticket.get("openticket:category").value = null + } + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket unclaiming!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //reply with new message + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:unclaim-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("openticket:busy").value = false + await openticket.events.get("afterTicketUnclaimed").emit([ticket,user,channel,reason]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.claiming.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) + } + + //to dm + if (generalConfig.data.system.messages.claiming.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket} = params + + openticket.log(user.displayName+" unclaimed a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerVerifyBars = async () => { + //UNCLAIM TICKET TICKET MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:unclaim-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:unclaim-ticket-ticket-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.unclaim + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when not claimed + if (!ticket.get("openticket:claimed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start unclaiming ticket + if (params.data == "reason"){ + //unclaim with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:unclaim-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + }else{ + //unclaim without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:unclaim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + } + }) + ]) + openticket.verifybars.get("openticket:unclaim-ticket-ticket-message").failure.add([ + new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }) + ]) + + //UNCLAIM TICKET CLAIM MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:unclaim-ticket-claim-message",openticket.builders.messages.getSafe("openticket:verifybar-claim-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:unclaim-ticket-claim-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.unclaim + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when not claimed + if (!ticket.get("openticket:claimed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start unclaiming ticket + if (params.data == "reason"){ + //unclaim with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:unclaim-ticket-reason").build("claim-message",{guild,channel,user,ticket})) + }else{ + //unclaim without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:unclaim-ticket").run("claim-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:unclaim-message").build("claim-message",{guild,channel,user,ticket,reason:null})) + } + }) + ]) + openticket.verifybars.get("openticket:unclaim-ticket-claim-message").failure.add([ + new api.ODWorker("openticket:back-to-claim-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const {verifybarMessage} = params + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + await instance.update(await openticket.builders.messages.getSafe("openticket:claim-message").build("other",{guild,channel,user,ticket,reason})) + }) + ]) + openticket.actions.get("openticket:unclaim-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + }) +} \ No newline at end of file diff --git a/src/actions/unpinTicket.ts b/src/actions/unpinTicket.ts new file mode 100644 index 0000000..e624c65 --- /dev/null +++ b/src/actions/unpinTicket.ts @@ -0,0 +1,267 @@ +/////////////////////////////////////// +//TICKET UNPINNING SYSTEM +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerActions = async () => { + openticket.actions.add(new api.ODAction("openticket:unpin-ticket")) + openticket.actions.get("openticket:unpin-ticket").workers.add([ + new api.ODWorker("openticket:unpin-ticket",2,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + if (channel.isThread()) throw new api.ODSystemError("Unable to unpin ticket! Open Ticket doesn't support threads!") + + await openticket.events.get("onTicketUnpin").emit([ticket,user,channel,reason]) + + //update ticket + ticket.get("openticket:pinned").value = false + ticket.get("openticket:pinned-by").value = null + ticket.get("openticket:pinned-on").value = null + ticket.get("openticket:busy").value = true + + //rename channel (and give error when crashed) + const originalName = channel.name + if (originalName.startsWith("📌")){ + const newName = originalName.replace("📌",""); + try{ + await utilities.timedAwait(channel.setName(newName),2500,(err) => { + openticket.log("Failed to rename channel on ticket unpin","error") + }) + }catch(err){ + await channel.send((await openticket.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-unpin",{guild,channel,user,originalName,newName})).message) + } + } + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on ticket unpinning!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } + + //reply with new message + if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:unpin-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("openticket:busy").value = false + await openticket.events.get("afterTicketUnpinned").emit([ticket,user,channel,reason]) + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user,ticket,reason} = params + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.pinning.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) + } + + //to dm + if (generalConfig.data.system.messages.pinning.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) + }), + new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + const {guild,channel,user,ticket} = params + + openticket.log(user.displayName+" unpinned a ticket!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"reason",value:params.reason ?? "/"}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerVerifyBars = async () => { + //UNPIN TICKET TICKET MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:unpin-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:unpin-ticket-ticket-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.unpin + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when not pinned + if (!ticket.get("openticket:pinned").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start unpining ticket + if (params.data == "reason"){ + //unpin with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:unpin-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + }else{ + //unpin without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:unpin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + } + }) + ]) + openticket.verifybars.get("openticket:unpin-ticket-ticket-message").failure.add([ + new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }) + ]) + + //UNPIN TICKET PIN MESSAGE + openticket.verifybars.add(new api.ODVerifyBar("openticket:unpin-ticket-pin-message",openticket.builders.messages.getSafe("openticket:verifybar-pin-message"),!generalConfig.data.system.disableVerifyBars)) + openticket.verifybars.get("openticket:unpin-ticket-pin-message").success.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.unpin + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when not pinned + if (!ticket.get("openticket:pinned").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + //start unpinning ticket + if (params.data == "reason"){ + //unpin with reason + instance.modal(await openticket.builders.modals.getSafe("openticket:unpin-ticket-reason").build("pin-message",{guild,channel,user,ticket})) + }else{ + //unpin without reason + await instance.defer("update",false) + await openticket.actions.get("openticket:unpin-ticket").run("pin-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:unpin-message").build("pin-message",{guild,channel,user,ticket,reason:null})) + } + }) + ]) + openticket.verifybars.get("openticket:unpin-ticket-pin-message").failure.add([ + new api.ODWorker("openticket:back-to-pin-message",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + const {verifybarMessage} = params + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + + const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + await instance.update(await openticket.builders.messages.getSafe("openticket:pin-message").build("other",{guild,channel,user,ticket,reason})) + }) + ]) + openticket.actions.get("openticket:unpin-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + //set busy to false in case of crash or cancel + params.ticket.get("openticket:busy").value = false + }) +} \ No newline at end of file diff --git a/src/builders/buttons.ts b/src/builders/buttons.ts new file mode 100644 index 0000000..78f088e --- /dev/null +++ b/src/builders/buttons.ts @@ -0,0 +1,351 @@ +/////////////////////////////////////// +//BUTTON BUILDERS +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const buttons = openticket.builders.buttons +const lang = openticket.languages +const generalConfig = openticket.configs.get("openticket:general") + +export const registerAllButtons = async () => { + verifybarButtons() + errorButtons() + helpMenuButtons() + panelButtons() + ticketButtons() + transcriptButtons() + clearButtons() +} + +const verifybarButtons = () => { + //VERIFYBAR SUCCESS + buttons.add(new api.ODButton("openticket:verifybar-success")) + buttons.get("openticket:verifybar-success").workers.add( + new api.ODWorker("openticket:verifybar-success",0,async (instance,params) => { + const {verifybar,customData,customColor,customLabel,customEmoji} = params + + if (customData && customData.length > 40) throw new api.ODSystemError("ODButton:openticket:verifybar-success => customData exceeds 40 characters limit!") + + const newData = (customData) ? "_"+customData : "" + const newColor = customColor ?? "gray" + const newLabel = customLabel ?? "" + const newEmoji = customEmoji ?? "✅" + + instance.setCustomId("od:verifybar-success_"+verifybar.id.value+newData) + instance.setMode("button") + instance.setColor(newColor) + if (newLabel) instance.setLabel(newLabel) + if (newEmoji) instance.setEmoji(newEmoji) + }) + ) + + //VERIFYBAR FAILURE + buttons.add(new api.ODButton("openticket:verifybar-failure")) + buttons.get("openticket:verifybar-failure").workers.add( + new api.ODWorker("openticket:verifybar-failure",0,async (instance,params) => { + const {verifybar,customData,customColor,customLabel,customEmoji} = params + + if (customData && customData.length > 40) throw new api.ODSystemError("ODButton:openticket:verifybar-success => customData exceeds 40 characters limit!") + + const newData = (customData) ? "_"+customData : "" + const newColor = customColor ?? "gray" + const newLabel = customLabel ?? "" + const newEmoji = customEmoji ?? "❌" + + instance.setCustomId("od:verifybar-failure_"+verifybar.id.value+newData) + instance.setMode("button") + instance.setColor(newColor) + if (newLabel) instance.setLabel(newLabel) + if (newEmoji) instance.setEmoji(newEmoji) + }) + ) +} + +const errorButtons = () => { + //ERROR TICKET DEPRECATED TRANSCRIPT + buttons.add(new api.ODButton("openticket:error-ticket-deprecated-transcript")) + buttons.get("openticket:error-ticket-deprecated-transcript").workers.add( + new api.ODWorker("openticket:error-ticket-deprecated-transcript",0,async (instance,params) => { + + instance.setCustomId("od:error-ticket-deprecated-transcript") + instance.setMode("button") + instance.setColor("gray") + instance.setLabel(lang.getTranslation("transcripts.errors.backup")) + instance.setEmoji("📄") + }) + ) +} + +const helpMenuButtons = () => { + //HELP MENU PAGE + buttons.add(new api.ODButton("openticket:help-menu-page")) + buttons.get("openticket:help-menu-page").workers.add( + new api.ODWorker("openticket:help-menu-page",0,async (instance,params) => { + const {mode,page} = params + const totalPages = (await openticket.helpmenu.render(mode)).length + const pageText = (page+1).toString()+"/"+totalPages.toString() + + instance.setCustomId("od:help-menu-page_"+page.toString()) + instance.setMode("button") + instance.setColor("gray") + instance.setLabel(lang.getTranslationWithParams("actions.buttons.helpPage",[pageText])) + instance.setDisabled(true) + }) + ) + + //HELP MENU SWITCH + buttons.add(new api.ODButton("openticket:help-menu-switch")) + buttons.get("openticket:help-menu-switch").workers.add( + new api.ODWorker("openticket:help-menu-switch",0,async (instance,params) => { + const {mode} = params + + instance.setCustomId("od:help-menu-switch_"+mode) + instance.setMode("button") + instance.setColor("gray") + if (mode == "slash") instance.setLabel(lang.getTranslation("actions.buttons.helpSwitchText")) + else instance.setLabel(lang.getTranslation("actions.buttons.helpSwitchSlash")) + }) + ) + + //HELP MENU PREVIOUS + buttons.add(new api.ODButton("openticket:help-menu-previous")) + buttons.get("openticket:help-menu-previous").workers.add( + new api.ODWorker("openticket:help-menu-previous",0,async (instance,params) => { + const {page} = params + + instance.setCustomId("od:help-menu-previous") + instance.setMode("button") + instance.setColor("gray") + instance.setEmoji("◀️") + if (page == 0) instance.setDisabled(true) + }) + ) + + //HELP MENU NEXT + buttons.add(new api.ODButton("openticket:help-menu-next")) + buttons.get("openticket:help-menu-next").workers.add( + new api.ODWorker("openticket:help-menu-next",0,async (instance,params) => { + const {mode,page} = params + const totalPages = (await openticket.helpmenu.render(mode)).length + + instance.setCustomId("od:help-menu-next") + instance.setMode("button") + instance.setColor("gray") + instance.setEmoji("▶️") + if (page == totalPages-1) instance.setDisabled(true) + }) + ) +} + +const panelButtons = () => { + //TICKET OPTION + buttons.add(new api.ODButton("openticket:ticket-option")) + buttons.get("openticket:ticket-option").workers.add( + new api.ODWorker("openticket:ticket-option",0,async (instance,params) => { + const {panel,option} = params + + instance.setCustomId("od:ticket-option_"+panel.id.value+"_"+option.id.value) + instance.setMode("button") + instance.setColor(option.get("openticket:button-color").value) + if (option.get("openticket:button-emoji").value) instance.setEmoji(option.get("openticket:button-emoji").value) + if (option.get("openticket:button-label").value) instance.setLabel(option.get("openticket:button-label").value) + if (!option.get("openticket:button-emoji").value && !option.get("openticket:button-label").value) instance.setLabel("<"+option.id.value+">") + }) + ) + + //WEBSITE OPTION + buttons.add(new api.ODButton("openticket:website-option")) + buttons.get("openticket:website-option").workers.add( + new api.ODWorker("openticket:website-option",0,async (instance,params) => { + const {panel,option} = params + + instance.setMode("url") + instance.setUrl(option.get("openticket:url").value) + if (option.get("openticket:button-emoji").value) instance.setEmoji(option.get("openticket:button-emoji").value) + if (option.get("openticket:button-label").value) instance.setLabel(option.get("openticket:button-label").value) + if (!option.get("openticket:button-emoji").value && !option.get("openticket:button-label").value) instance.setLabel("<"+option.id.value+">") + }) + ) + + //ROLE OPTION + buttons.add(new api.ODButton("openticket:role-option")) + buttons.get("openticket:role-option").workers.add( + new api.ODWorker("openticket:role-option",0,async (instance,params) => { + const {panel,option} = params + + instance.setCustomId("od:role-option_"+panel.id.value+"_"+option.id.value) + instance.setMode("button") + instance.setColor(option.get("openticket:button-color").value) + if (option.get("openticket:button-emoji").value) instance.setEmoji(option.get("openticket:button-emoji").value) + if (option.get("openticket:button-label").value) instance.setLabel(option.get("openticket:button-label").value) + if (!option.get("openticket:button-emoji").value && !option.get("openticket:button-label").value) instance.setLabel("<"+option.id.value+">") + }) + ) +} + +const ticketButtons = () => { + //VISIT TICKET + buttons.add(new api.ODButton("openticket:visit-ticket")) + buttons.get("openticket:visit-ticket").workers.add( + new api.ODWorker("openticket:visit-ticket",0,async (instance,params) => { + const {guild,channel,ticket} = params + + instance.setMode("url") + instance.setUrl(channel.url) + instance.setEmoji("🎫") + instance.setLabel(lang.getTranslation("actions.buttons.create")) + }) + ) + + //CLOSE TICKET + buttons.add(new api.ODButton("openticket:close-ticket")) + buttons.get("openticket:close-ticket").workers.add( + new api.ODWorker("openticket:close-ticket",0,async (instance,params,source) => { + const {guild,channel,ticket} = params + + instance.setMode("button") + instance.setCustomId("od:close-ticket_"+source) + instance.setColor("gray") + instance.setEmoji("🔒") + instance.setLabel(lang.getTranslation("actions.buttons.close")) + }) + ) + + //DELETE TICKET + buttons.add(new api.ODButton("openticket:delete-ticket")) + buttons.get("openticket:delete-ticket").workers.add( + new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source) => { + const {guild,channel,ticket} = params + + instance.setMode("button") + instance.setCustomId("od:delete-ticket_"+source) + instance.setColor("red") + instance.setEmoji("✖") + instance.setLabel(lang.getTranslation("actions.buttons.delete")) + }) + ) + + //REOPEN TICKET + buttons.add(new api.ODButton("openticket:reopen-ticket")) + buttons.get("openticket:reopen-ticket").workers.add( + new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source) => { + const {guild,channel,ticket} = params + + instance.setMode("button") + instance.setCustomId("od:reopen-ticket_"+source) + instance.setColor("green") + instance.setEmoji("🔓") + instance.setLabel(lang.getTranslation("actions.buttons.reopen")) + }) + ) + + //CLAIM TICKET + buttons.add(new api.ODButton("openticket:claim-ticket")) + buttons.get("openticket:claim-ticket").workers.add( + new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source) => { + const {guild,channel,ticket} = params + + instance.setMode("button") + instance.setCustomId("od:claim-ticket_"+source) + instance.setColor("green") + instance.setEmoji("👋") + instance.setLabel(lang.getTranslation("actions.buttons.claim")) + }) + ) + + //UNCLAIM TICKET + buttons.add(new api.ODButton("openticket:unclaim-ticket")) + buttons.get("openticket:unclaim-ticket").workers.add( + new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source) => { + const {guild,channel,ticket} = params + + instance.setMode("button") + instance.setCustomId("od:unclaim-ticket_"+source) + instance.setColor("green") + instance.setEmoji("↩️") + instance.setLabel(lang.getTranslation("actions.buttons.unclaim")) + }) + ) + + //PIN TICKET + buttons.add(new api.ODButton("openticket:pin-ticket")) + buttons.get("openticket:pin-ticket").workers.add( + new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source) => { + const {guild,channel,ticket} = params + + instance.setMode("button") + instance.setCustomId("od:pin-ticket_"+source) + instance.setColor("gray") + instance.setEmoji("📌") + instance.setLabel(lang.getTranslation("actions.buttons.pin")) + }) + ) + + //UNPIN TICKET + buttons.add(new api.ODButton("openticket:unpin-ticket")) + buttons.get("openticket:unpin-ticket").workers.add( + new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source) => { + const {guild,channel,ticket} = params + + instance.setMode("button") + instance.setCustomId("od:unpin-ticket_"+source) + instance.setColor("gray") + instance.setEmoji("📌") + instance.setLabel(lang.getTranslation("actions.buttons.unpin")) + }) + ) +} + +const transcriptButtons = () => { + //TRANSCRIPT HTML VISIT + buttons.add(new api.ODButton("openticket:transcript-html-visit")) + buttons.get("openticket:transcript-html-visit").workers.add( + new api.ODWorker("openticket:transcript-html-visit",0,async (instance,params,source) => { + const {result} = params + instance.setMode("url") + if (result.data) instance.setUrl(result.data.url) + else throw new api.ODSystemError("ODButton:openticket:transcript-html-visit => Missing Transcript Result Data!") + instance.setEmoji("📄") + instance.setLabel(lang.getTranslation("transcripts.success.visit")) + }) + ) + + //TRANSCRIPT ERROR RETRY + buttons.add(new api.ODButton("openticket:transcript-error-retry")) + buttons.get("openticket:transcript-error-retry").workers.add( + new api.ODWorker("openticket:transcript-error-retry",0,async (instance,params,source) => { + instance.setMode("button") + instance.setCustomId("od:transcript-error-retry_"+source) + instance.setColor("gray") + instance.setEmoji("🔄") + instance.setLabel(lang.getTranslation("transcripts.errors.retry")) + }) + ) + + //TRANSCRIPT ERROR CONTINUE + buttons.add(new api.ODButton("openticket:transcript-error-continue")) + buttons.get("openticket:transcript-error-continue").workers.add( + new api.ODWorker("openticket:transcript-error-continue",0,async (instance,params,source) => { + instance.setMode("button") + instance.setCustomId("od:transcript-error-continue_"+source) + instance.setColor("red") + instance.setEmoji("✖") + instance.setLabel(lang.getTranslation("transcripts.errors.continue")) + }) + ) +} + +const clearButtons = () => { + //CLEAR CONTINUE + buttons.add(new api.ODButton("openticket:clear-continue")) + buttons.get("openticket:clear-continue").workers.add( + new api.ODWorker("openticket:clear-continue",0,async (instance,params,source) => { + instance.setMode("button") + instance.setCustomId("od:clear-continue_"+source+"_"+params.filter) + instance.setColor("red") + instance.setEmoji("✖") + instance.setLabel(lang.getTranslation("actions.buttons.clear")) + }) + ) +} \ No newline at end of file diff --git a/src/builders/dropdowns.ts b/src/builders/dropdowns.ts new file mode 100644 index 0000000..d2f9b60 --- /dev/null +++ b/src/builders/dropdowns.ts @@ -0,0 +1,37 @@ +/////////////////////////////////////// +//DROPDOWN BUILDERS +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const dropdowns = openticket.builders.dropdowns + +export const registerAllDropdowns = async () => { + panelDropdowns() +} + +const panelDropdowns = () => { + //TICKET OPTION + dropdowns.add(new api.ODDropdown("openticket:panel-dropdown-tickets")) + dropdowns.get("openticket:panel-dropdown-tickets").workers.add( + new api.ODWorker("openticket:panel-dropdown-tickets",0,async (instance,params) => { + const {panel,options} = params + + const parsedOptions = options.map((option) => { + return { + label:option.get("openticket:button-label").value.substring(0,100), + value:"od:ticket-option_"+panel.id.value+"_"+option.id.value, + emoji:option.get("openticket:button-emoji").value, + description:option.get("openticket:description").value.substring(0,100) + } + }) + + instance.setCustomId("od:panel-dropdown_"+panel.id.value) + instance.setType("string") + instance.setMaxValues(1) + instance.setMinValues(0) + instance.setPlaceholder(panel.get("openticket:dropdown-placeholder").value) + instance.setOptions(parsedOptions) + }) + ) +} \ No newline at end of file diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts new file mode 100644 index 0000000..4eb4d0e --- /dev/null +++ b/src/builders/embeds.ts @@ -0,0 +1,1272 @@ +/////////////////////////////////////// +//EMBED BUILDERS +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" +import nodepath from "path" + +const embeds = openticket.builders.embeds +const lang = openticket.languages +const generalConfig = openticket.configs.get("openticket:general") + +export const registerAllEmbeds = async () => { + errorEmbeds() + helpMenuEmbeds() + statsEmbeds() + panelEmbeds() + ticketEmbeds() + blacklistEmbeds() + transcriptEmbeds() + roleEmbeds() + clearEmbeds() + autoEmbeds() +} + +/**Utility function to get the translated "method" from the source. Mostly used in error embeds. */ +const getMethodFromSource = (source:"slash"|"text"|"button"|"dropdown"|"modal"|"other"): string => { + if (source == "slash" || source == "text") return lang.getTranslation("params.lowercase.command") + else if (source == "button") return lang.getTranslation("params.lowercase.button") + else if (source == "dropdown") return lang.getTranslation("params.lowercase.dropdown") + else if (source == "modal") return lang.getTranslation("params.lowercase.modal") + else return lang.getTranslation("params.lowercase.method") +} +//lang.getTranslation() + +const errorEmbeds = () => { + //ERROR + embeds.add(new api.ODEmbed("openticket:error")) + embeds.get("openticket:error").workers.add( + new api.ODWorker("openticket:error",0,async (instance,params,source) => { + const {user,error,layout} = params + + const method = getMethodFromSource(source) + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.internalError"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslationWithParams("errors.descriptions.internalError",[method]) + (layout == "simple") ? "\n"+error : "") + if (layout == "advanced" && error) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+error+"```"}) + instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo")) + }) + ) + + //ERROR OPTION MISSING + embeds.add(new api.ODEmbed("openticket:error-option-missing")) + embeds.get("openticket:error-option-missing").workers.add( + new api.ODWorker("openticket:error-option-missing",0,async (instance,params) => { + const {user,error} = params + + const options = error.command.builder.options ?? [] + const optionSyntax = options.map((opt,index) => { + if (index == error.location){ + if (opt.required){ + return "`<"+opt.name+":"+opt.type.replace("guildmember","user")+">`" + }else{ + return "`["+opt.name+":"+opt.type.replace("guildmember","user")+"]`" + } + }else{ + if (opt.required){ + return "<"+opt.name+":"+opt.type.replace("guildmember","user")+">" + }else{ + return "["+opt.name+":"+opt.type.replace("guildmember","user")+"]" + } + } + }) + const commandSyntax = "**"+error.prefix+error.name+" "+optionSyntax.join(" ")+"**" + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.optionMissing"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslation("errors.descriptions.optionMissing")) + instance.addFields({name:lang.getTranslation("params.uppercase.syntax")+":",value:commandSyntax}) + }) + ) + + //ERROR OPTION INVALID + embeds.add(new api.ODEmbed("openticket:error-option-invalid")) + embeds.get("openticket:error-option-invalid").workers.add( + new api.ODWorker("openticket:error-option-invalid",0,async (instance,params) => { + const {user,error} = params + + const options = error.command.builder.options ?? [] + const optionSyntax = options.map((opt,index) => { + if (index == error.location){ + if (opt.required){ + return "`<"+opt.name+":"+opt.type.replace("guildmember","user")+">`" + }else{ + return "`["+opt.name+":"+opt.type.replace("guildmember","user")+"]`" + } + }else{ + if (opt.required){ + return "<"+opt.name+":"+opt.type.replace("guildmember","user")+">" + }else{ + return "["+opt.name+":"+opt.type.replace("guildmember","user")+"]" + } + } + }) + const commandSyntax = "**"+error.prefix+error.name+" "+optionSyntax.join(" ")+"**" + + let reasonTitle = (error.reason == "boolean" || error.reason == "string_choice") ? lang.getTranslation("errors.descriptions.optionInvalidChoose") : lang.getTranslation("params.uppercase.reason") + let reasonValue = "" + + if (error.reason == "boolean" && error.option.type == "boolean") reasonValue = (error.option.falseValue ?? "false")+" OR "+(error.option.trueValue ?? "true") + else if (error.reason == "string_choice" && error.option.type == "string" && error.option.choices) reasonValue = error.option.choices.join(" OR ") + else if (error.reason == "string_regex" && error.option.type == "string" && error.option.regex) reasonValue = lang.getTranslation("errors.optionInvalidReasons.stringRegex") + else if (error.reason == "string_min_length" && error.option.type == "string" && error.option.minLength) reasonValue = lang.getTranslationWithParams("errors.optionInvalidReasons.stringMinLength",[error.option.minLength.toString()]) + else if (error.reason == "string_max_length" && error.option.type == "string" && error.option.maxLength) reasonValue = lang.getTranslationWithParams("errors.optionInvalidReasons.stringMaxLength",[error.option.maxLength.toString()]) + else if (error.reason == "number_invalid" && error.option.type == "number") reasonValue = lang.getTranslation("errors.optionInvalidReasons.numberInvalid") + else if (error.reason == "number_min" && error.option.type == "number" && error.option.min) reasonValue = lang.getTranslationWithParams("errors.optionInvalidReasons.numberMin",[error.option.min.toString()]) + else if (error.reason == "number_max" && error.option.type == "number" && error.option.max) reasonValue = lang.getTranslationWithParams("errors.optionInvalidReasons.numberMax",[error.option.max.toString()]) + else if (error.reason == "number_decimal" && error.option.type == "number") reasonValue = lang.getTranslation("errors.optionInvalidReasons.numberDecimal") + else if (error.reason == "number_negative" && error.option.type == "number") reasonValue = lang.getTranslation("errors.optionInvalidReasons.numberNegative") + else if (error.reason == "number_positive" && error.option.type == "number") reasonValue = lang.getTranslation("errors.optionInvalidReasons.numberPositive") + else if (error.reason == "number_zero" && error.option.type == "number") reasonValue = lang.getTranslation("errors.optionInvalidReasons.numberZero") + else if (error.reason == "channel_not_found" && error.option.type == "channel") reasonValue = lang.getTranslation("errors.optionInvalidReasons.channelNotFound") + else if (error.reason == "user_not_found" && error.option.type == "user") reasonValue = lang.getTranslation("errors.optionInvalidReasons.userNotFound") + else if (error.reason == "role_not_found" && error.option.type == "role") reasonValue = lang.getTranslation("errors.optionInvalidReasons.roleNotFound") + else if (error.reason == "member_not_found" && error.option.type == "guildmember") reasonValue = lang.getTranslation("errors.optionInvalidReasons.memberNotFound") + else if (error.reason == "mentionable_not_found" && error.option.type == "mentionable") reasonValue = lang.getTranslation("errors.optionInvalidReasons.mentionableNotFound") + else if (error.reason == "channel_type" && error.option.type == "channel") reasonValue = lang.getTranslation("errors.optionInvalidReasons.channelType") + else if (error.reason == "not_in_guild") reasonValue = lang.getTranslation("errors.optionInvalidReasons.notInGuild") + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.optionInvalid"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslation("errors.descriptions.optionInvalid")+"\n"+reasonTitle+": `"+reasonValue+"`") + instance.addFields({name:lang.getTranslation("params.uppercase.syntax")+":",value:commandSyntax}) + }) + ) + + //ERROR UNKNOWN COMMAND + embeds.add(new api.ODEmbed("openticket:error-unknown-command")) + embeds.get("openticket:error-unknown-command").workers.add( + new api.ODWorker("openticket:error-unknown-command",0,async (instance,params) => { + const {user} = params + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownCommand"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslation("errors.descriptions.unknownCommand")) + }) + ) + + //ERROR NO PERMISSIONS + embeds.add(new api.ODEmbed("openticket:error-no-permissions")) + embeds.get("openticket:error-no-permissions").workers.add( + new api.ODWorker("openticket:error-no-permissions",0,async (instance,params,source) => { + const {user,permissions} = params + + const method = getMethodFromSource(source) + + const renderedPerms = permissions.map((perm) => { + if (perm == "developer") return "- "+lang.getTranslation("errors.permissions.developer") + else if (perm == "owner") return "- "+lang.getTranslation("errors.permissions.owner") + else if (perm == "admin") return "- "+lang.getTranslation("errors.permissions.admin") + else if (perm == "moderator") return "- "+lang.getTranslation("errors.permissions.moderator") + else if (perm == "support") return "- "+lang.getTranslation("errors.permissions.support") + else if (perm == "member") return "- "+lang.getTranslation("errors.permissions.member") + else if (perm == "discord-administrator") return "- "+lang.getTranslation("errors.permissions.discord-administrator") + }).join("\n") + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissions",[method])) + if (renderedPerms) instance.addFields({name:lang.getTranslation("errors.descriptions.noPermissionsList"),value:renderedPerms}) + }) + ) + + //ERROR NO PERMISSIONS COOLDOWN + embeds.add(new api.ODEmbed("openticket:error-no-permissions-cooldown")) + embeds.get("openticket:error-no-permissions-cooldown").workers.add( + new api.ODWorker("openticket:error-no-permissions-cooldown",0,async (instance,params,source) => { + const {user} = params + + const method = getMethodFromSource(source) + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissionsCooldown",[method])) + instance.addFields({name:lang.getTranslation("params.uppercase.until")+":",value:discord.time(params.until ?? new Date(),"R")}) + }) + ) + + //ERROR NO PERMISSIONS BLACKLISTED + embeds.add(new api.ODEmbed("openticket:error-no-permissions-blacklisted")) + embeds.get("openticket:error-no-permissions-blacklisted").workers.add( + new api.ODWorker("openticket:error-no-permissions-blacklisted",0,async (instance,params,source) => { + const {user} = params + + const method = getMethodFromSource(source) + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslation("errors.descriptions.noPermissionsBlacklist")) + }) + ) + + //ERROR NO PERMISSIONS LIMITS + embeds.add(new api.ODEmbed("openticket:error-no-permissions-limits")) + embeds.get("openticket:error-no-permissions-limits").workers.add( + new api.ODWorker("openticket:error-no-permissions-limits",0,async (instance,params,source) => { + const {user,limit} = params + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + if (limit == "global") instance.setDescription(lang.getTranslation("errors.descriptions.noPermissionsLimitGlobal")) + else if (limit == "global-user") instance.setDescription(lang.getTranslation("errors.descriptions.noPermissionsLimitGlobalUser")) + else if (limit == "option") instance.setDescription(lang.getTranslation("errors.descriptions.noPermissionsLimitOption")) + else if (limit == "option-user") instance.setDescription(lang.getTranslation("errors.descriptions.noPermissionsLimitOptionUser")) + }) + ) + + //ERROR RESPONDER TIMEOUT + embeds.add(new api.ODEmbed("openticket:error-responder-timeout")) + embeds.get("openticket:error-responder-timeout").workers.add( + new api.ODWorker("openticket:error-responder-timeout",0,async (instance,params,source) => { + const {user} = params + + const method = getMethodFromSource(source) + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.internalError"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslationWithParams("errors.descriptions.internalError",[method])) + instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```Responder Timeout```"}) + instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo")) + }) + ) + + //ERROR TICKET UNKNOWN + embeds.add(new api.ODEmbed("openticket:error-ticket-unknown")) + embeds.get("openticket:error-ticket-unknown").workers.add( + new api.ODWorker("openticket:error-ticket-unknown",0,async (instance,params,source) => { + const {user} = params + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownTicket"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslation("errors.descriptions.unknownTicket")) + instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo")) + }) + ) + + //ERROR TICKET DEPRECATED + embeds.add(new api.ODEmbed("openticket:error-ticket-deprecated")) + embeds.get("openticket:error-ticket-deprecated").workers.add( + new api.ODWorker("openticket:error-ticket-deprecated",0,async (instance,params,source) => { + const {user} = params + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.deprecatedTicket"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslation("errors.descriptions.deprecatedTicket")) + instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo")) + }) + ) + + //ERROR OPTION UNKNOWN + embeds.add(new api.ODEmbed("openticket:error-option-unknown")) + embeds.get("openticket:error-option-unknown").workers.add( + new api.ODWorker("openticket:error-option-unknown",0,async (instance,params,source) => { + const {user} = params + + const renderedTicketOptions = openticket.options.getAll().map((option) => { + if (option instanceof api.ODTicketOption && option.exists("openticket:name")){ + return "- **"+option.get("openticket:name").value+":** `"+option.id.value+"`" + }else return "- `"+option.id.value+"`" + }).join("\n") + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownOption"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo")) + instance.addFields({name:lang.getTranslation("params.uppercase.validOptions")+":",value:renderedTicketOptions}) + }) + ) + + //ERROR PANEL UNKNOWN + embeds.add(new api.ODEmbed("openticket:error-panel-unknown")) + embeds.get("openticket:error-panel-unknown").workers.add( + new api.ODWorker("openticket:error-panel-unknown",0,async (instance,params,source) => { + const {user} = params + + const renderedPanels = openticket.panels.getAll().map((panel) => { + if (panel.exists("openticket:name")){ + return "- **"+panel.get("openticket:name").value+":** `"+panel.id.value+"`" + }else return "- `"+panel.id.value+"`" + }).join("\n") + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownPanel"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.addFields({name:lang.getTranslation("params.uppercase.validPanels")+":",value:renderedPanels}) + instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo")) + }) + ) + + //ERROR NOT IN GUILD + embeds.add(new api.ODEmbed("openticket:error-not-in-guild")) + embeds.get("openticket:error-not-in-guild").workers.add( + new api.ODWorker("openticket:error-not-in-guild",0,async (instance,params,source) => { + const {user} = params + + const method = getMethodFromSource(source) + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.notInGuild"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslationWithParams("errors.descriptions.notInGuild",[method])) + }) + ) + + //ERROR CHANNEL RENAME + embeds.add(new api.ODEmbed("openticket:error-channel-rename")) + embeds.get("openticket:error-channel-rename").workers.add( + new api.ODWorker("openticket:error-channel-rename",0,async (instance,params,source) => { + const {channel,user,originalName,newName} = params + + const method = (source == "ticket-move" || source == "ticket-pin" || source == "ticket-rename" || source == "ticket-unpin") ? source : getMethodFromSource(source) + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.channelRename"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslation("errors.descriptions.channelRename")) + instance.setFooter(lang.getTranslationWithParams("errors.descriptions.channelRenameSource",[method])) + instance.addFields( + {name:lang.getTranslation("params.uppercase.originalName")+":",value:"```#"+originalName+"```",inline:false}, + {name:lang.getTranslation("params.uppercase.newName")+":",value:"```#"+newName+"```",inline:false} + ) + }) + ) + + //ERROR TICKET BUSY + embeds.add(new api.ODEmbed("openticket:error-ticket-busy")) + embeds.get("openticket:error-ticket-busy").workers.add( + new api.ODWorker("openticket:error-ticket-busy",0,async (instance,params,source) => { + const {user} = params + + const method = getMethodFromSource(source) + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.busy"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslationWithParams("errors.descriptions.busy",[method])) + instance.setFooter(lang.getTranslation("errors.descriptions.askForInfoResolve")) + }) + ) +} + +const helpMenuEmbeds = () => { + //HELP MENU + embeds.add(new api.ODEmbed("openticket:help-menu")) + embeds.get("openticket:help-menu").workers.add( + new api.ODWorker("openticket:help-menu",0,async (instance,params) => { + const {mode,page} = params + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("ℹ️",lang.getTranslation("actions.titles.help"))) + instance.setDescription(lang.getTranslation("actions.descriptions.helpExplanation")) + instance.setThumbnail(openticket.client.client.user.displayAvatarURL()) + + const data = await openticket.helpmenu.render(mode) + const currentData = data[page] ?? [] + instance.setFields(currentData) + }) + ) +} + +const statsEmbeds = () => { + //STATS GLOBAL + embeds.add(new api.ODEmbed("openticket:stats-global")) + embeds.get("openticket:stats-global").workers.add( + new api.ODWorker("openticket:stats-global",0,async (instance,params) => { + const {guild,channel,user} = params + + const scope = openticket.stats.get("openticket:global") + if (!scope) return + const data = await scope.render("GLOBAL",guild,channel,user) + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(scope.name) + instance.setDescription(data) + + if (openticket.permissions.hasPermissions("owner",await openticket.permissions.getPermissions(user,channel,guild))){ + //show system data when owner or developer + const systemScope = openticket.stats.get("openticket:system") + if (!systemScope) return + const systemData = await systemScope.render("GLOBAL",guild,channel,user) + instance.addFields({name:systemScope.name,value:systemData,inline:false}) + } + }) + ) + + //STATS TICKET + embeds.add(new api.ODEmbed("openticket:stats-ticket")) + embeds.get("openticket:stats-ticket").workers.add( + new api.ODWorker("openticket:stats-ticket",0,async (instance,params) => { + const {guild,channel,user,scopeData} = params + + const scope = openticket.stats.get("openticket:ticket") + const participantsScope = openticket.stats.get("openticket:participants") + if (!scope || !participantsScope) return + const data = await scope.render(scopeData.id.value,guild,channel,user) + const participantsData = await participantsScope.render(scopeData.id.value,guild,channel,user) + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(scope.name) + instance.setDescription(data) + instance.addFields({name:participantsScope.name,value:participantsData,inline:false}) + }) + ) + + //STATS USER + embeds.add(new api.ODEmbed("openticket:stats-user")) + embeds.get("openticket:stats-user").workers.add([ + new api.ODWorker("openticket:stats-user",0,async (instance,params) => { + const {guild,channel,user,scopeData} = params + + const scope = openticket.stats.get("openticket:user") + if (!scope) return + const data = await scope.render(scopeData.id,guild,channel,user) + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(scope.name) + instance.setDescription(data) + instance.setThumbnail(scopeData.displayAvatarURL()) + }), + new api.ODWorker("openticket:easter-egg",-1,async (instance,params) => { + if (!openticket.flags.exists("openticket:no-easter")) return + const easterFlag = openticket.flags.get("openticket:no-easter") + if (!easterFlag.value){ + //🥚 add easter egg 🥚 + const {user} = params + if (user.id == utilities.easterEggs.creator){ + instance.setFooter("💻 Open Ticket Developer") + }else if (utilities.easterEggs.translators.includes(user.id)){ + instance.setFooter("💬 Open Ticket Translator") + } + } + }) + ]) + + //STATS RESET + embeds.add(new api.ODEmbed("openticket:stats-reset")) + embeds.get("openticket:stats-reset").workers.add( + new api.ODWorker("openticket:stats-reset",0,async (instance,params) => { + const {user,reason} = params + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🗑️",lang.getTranslation("actions.titles.statsReset"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslation("actions.descriptions.statsReset")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //STATS TICKET UNKNOWN + embeds.add(new api.ODEmbed("openticket:stats-ticket-unknown")) + embeds.get("openticket:stats-ticket-unknown").workers.add( + new api.ODWorker("openticket:stats-ticket-unknown",0,async (instance,params) => { + const {user,id} = params + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownTicket"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.statsError",[discord.channelMention(id)])) + }) + ) +} + +const panelEmbeds = () => { + //PANEL + embeds.add(new api.ODEmbed("openticket:panel")) + embeds.get("openticket:panel").workers.add( + new api.ODWorker("openticket:panel",0,async (instance,params) => { + const {panel} = params + if (!panel.exists("openticket:embed")) return + const embedOptions = panel.get("openticket:embed").value + + instance.setColor(embedOptions.customColor ? (embedOptions.customColor as discord.ColorResolvable) : generalConfig.data.mainColor) + instance.setTitle(embedOptions.title) + if (embedOptions.thumbnail) instance.setThumbnail(embedOptions.thumbnail) + if (embedOptions.image) instance.setImage(embedOptions.image) + if (embedOptions.url) instance.setUrl(embedOptions.url) + if (embedOptions.footer) instance.setFooter(embedOptions.footer) + if (embedOptions.timestamp) instance.setTimestamp(new Date()) + + if (panel.get("openticket:describe-options-in-embed-description").value){ + //describe options in description + const text = (await import("../data/openticket/panelLoader.ts")).describePanelOptions("text",panel) + instance.setDescription(embedOptions.description+"\n\n"+text) + }else if (embedOptions.description){ + instance.setDescription(embedOptions.description) + } + + if (panel.get("openticket:enable-max-tickets-warning-embed").value && generalConfig.data.system.limits.enabled){ + instance.setDescription(instance.data.description+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.system.limits.userMaximum.toString()])+"*") + } + + if (panel.get("openticket:describe-options-in-embed-fields").value){ + //describe options in fields + const fields = (await import("../data/openticket/panelLoader.ts")).describePanelOptions("fields",panel) + instance.setFields(fields) + }else if(embedOptions.fields.length > 0){ + instance.setFields(embedOptions.fields) + } + }) + ) +} + +const ticketEmbeds = () => { + //TICKET CREATED + embeds.add(new api.ODEmbed("openticket:ticket-created")) + embeds.get("openticket:ticket-created").workers.add( + new api.ODWorker("openticket:ticket-created",0,async (instance,params,source) => { + const {user} = params + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🎫",lang.getTranslation("actions.titles.created"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setTimestamp(new Date()) + instance.setDescription(lang.getTranslation("actions.descriptions.create")) + }) + ) + + //TICKET CREATED DM + embeds.add(new api.ODEmbed("openticket:ticket-created-dm")) + embeds.get("openticket:ticket-created-dm").workers.add( + new api.ODWorker("openticket:ticket-created-dm",0,async (instance,params,source) => { + const {user,ticket} = params + const embedOptions = ticket.option.get("openticket:dm-message-embed").value + + instance.setColor(embedOptions.customColor ? (embedOptions.customColor as discord.ColorResolvable) : generalConfig.data.mainColor) + instance.setTitle(embedOptions.title) + if (embedOptions.thumbnail) instance.setThumbnail(embedOptions.thumbnail) + if (embedOptions.image) instance.setImage(embedOptions.image) + if (embedOptions.timestamp) instance.setTimestamp(new Date()) + if (embedOptions.description) instance.setDescription(embedOptions.description) + if (embedOptions.fields) instance.setFields(embedOptions.fields) + + if (ticket.get("openticket:closed").value && ticket.get("openticket:autodelete-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutodelete",[ticket.option.get("openticket:autodelete-days").value.toString()])) + else if (!ticket.get("openticket:closed").value && ticket.get("openticket:autoclose-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutoclose",[ticket.option.get("openticket:autoclose-hours").value.toString()])) + }) + ) + + //TICKET CREATED LOGS + embeds.add(new api.ODEmbed("openticket:ticket-created-logs")) + embeds.get("openticket:ticket-created-logs").workers.add( + new api.ODWorker("openticket:ticket-created-logs",0,async (instance,params,source) => { + const {user,ticket} = params + + const method = (source == "panel-button" || source == "panel-dropdown") ? lang.getTranslation("params.uppercase.panel") : (source == "slash" || source == "text") ? lang.getTranslation("params.uppercase.command") : lang.getTranslation("params.uppercase.system") + const blacklisted = openticket.blacklist.exists(user.id) ? lang.getTranslation("params.uppercase.true") : lang.getTranslation("params.uppercase.false") + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🎫",lang.getTranslation("actions.titles.created"))) + instance.setThumbnail(user.displayAvatarURL()) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setTimestamp(new Date()) + instance.setDescription(lang.getTranslationWithParams("actions.logs.createLog",[discord.userMention(user.id)])) + instance.addFields( + {name:lang.getTranslation("params.uppercase.type")+":",value:"```"+ticket.option.get("openticket:name").value+"```",inline:false}, + {name:lang.getTranslation("params.uppercase.method")+":",value:"```"+method+"```",inline:true}, + {name:lang.getTranslation("params.uppercase.blacklisted")+":",value:"```"+blacklisted+"```", inline:true} + ) + }) + ) + + //TICKET MESSAGE + embeds.add(new api.ODEmbed("openticket:ticket-message")) + embeds.get("openticket:ticket-message").workers.add( + new api.ODWorker("openticket:ticket-message",0,async (instance,params,source) => { + const {user,ticket} = params + const embedOptions = ticket.option.get("openticket:ticket-message-embed").value + + instance.setColor(embedOptions.customColor ? (embedOptions.customColor as discord.ColorResolvable) : generalConfig.data.mainColor) + if (embedOptions.title) instance.setTitle(embedOptions.title) + if (embedOptions.thumbnail) instance.setThumbnail(embedOptions.thumbnail) + if (embedOptions.image) instance.setImage(embedOptions.image) + if (embedOptions.timestamp) instance.setTimestamp(new Date()) + if (embedOptions.description) instance.setDescription(embedOptions.description) + + if (ticket.option.get("openticket:questions").value.length > 0){ + const answers = ticket.get("openticket:answers").value + answers.forEach((answer) => { + if (!answer.value || answer.value.length == 0) return + if (generalConfig.data.system.questionFieldsInCodeBlock) instance.addFields({name:answer.name,value:"```"+answer.value+"```",inline:false}) + else instance.addFields({name:answer.name,value:answer.value,inline:false}) + }) + }else if (embedOptions.fields){ + instance.setFields(embedOptions.fields) + } + + if (ticket.get("openticket:closed").value && ticket.get("openticket:autodelete-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutodelete",[ticket.option.get("openticket:autodelete-days").value.toString()])) + else if (!ticket.get("openticket:closed").value && ticket.get("openticket:autoclose-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutoclose",[ticket.option.get("openticket:autoclose-hours").value.toString()])) + + if (ticket.get("openticket:claimed").value){ + const claimUser = await openticket.tickets.getTicketUser(ticket,"claimer") + if (!claimUser) return + instance.setAuthor(lang.getTranslationWithParams("params.uppercase.claimedBy",[claimUser.displayName]),claimUser.displayAvatarURL()) + } + }) + ) + + //TICKET CLOSED + embeds.add(new api.ODEmbed("openticket:close-message")) + embeds.get("openticket:close-message").workers.add( + new api.ODWorker("openticket:close-message",0,async (instance,params,source) => { + const {user,ticket,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close"))) + instance.setDescription(lang.getTranslation("actions.descriptions.close")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET REOPENED + embeds.add(new api.ODEmbed("openticket:reopen-message")) + embeds.get("openticket:reopen-message").workers.add( + new api.ODWorker("openticket:reopen-message",0,async (instance,params,source) => { + const {user,ticket,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🔓",lang.getTranslation("actions.titles.reopen"))) + instance.setDescription(lang.getTranslation("actions.descriptions.reopen")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET DELETED + embeds.add(new api.ODEmbed("openticket:delete-message")) + embeds.get("openticket:delete-message").workers.add( + new api.ODWorker("openticket:delete-message",0,async (instance,params,source) => { + const {user,ticket,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🗑️",lang.getTranslation("actions.titles.delete"))) + instance.setDescription(lang.getTranslation("actions.descriptions.delete")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET CLAIMED + embeds.add(new api.ODEmbed("openticket:claim-message")) + embeds.get("openticket:claim-message").workers.add( + new api.ODWorker("openticket:claim-message",0,async (instance,params,source) => { + const {user,ticket,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("👋",lang.getTranslation("actions.titles.claim"))) + instance.setDescription(lang.getTranslation("actions.descriptions.claim")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET UNCLAIMED + embeds.add(new api.ODEmbed("openticket:unclaim-message")) + embeds.get("openticket:unclaim-message").workers.add( + new api.ODWorker("openticket:unclaim-message",0,async (instance,params,source) => { + const {user,ticket,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim"))) + instance.setDescription(lang.getTranslation("actions.descriptions.unclaim")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET PINNED + embeds.add(new api.ODEmbed("openticket:pin-message")) + embeds.get("openticket:pin-message").workers.add( + new api.ODWorker("openticket:pin-message",0,async (instance,params,source) => { + const {user,ticket,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("📌",lang.getTranslation("actions.titles.pin"))) + instance.setDescription(lang.getTranslation("actions.descriptions.pin")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET UNPINNED + embeds.add(new api.ODEmbed("openticket:unpin-message")) + embeds.get("openticket:unpin-message").workers.add( + new api.ODWorker("openticket:unpin-message",0,async (instance,params,source) => { + const {user,ticket,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("📌",lang.getTranslation("actions.titles.unpin"))) + instance.setDescription(lang.getTranslation("actions.descriptions.unpin")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET RENAMED + embeds.add(new api.ODEmbed("openticket:rename-message")) + embeds.get("openticket:rename-message").workers.add( + new api.ODWorker("openticket:rename-message",0,async (instance,params,source) => { + const {user,ticket,reason,data} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename"))) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.rename",["`#"+data+"`"])) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET MOVED + embeds.add(new api.ODEmbed("openticket:move-message")) + embeds.get("openticket:move-message").workers.add( + new api.ODWorker("openticket:move-message",0,async (instance,params,source) => { + const {user,ticket,reason,data} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.move"))) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.move",["`"+data.get("openticket:name").value+"`"])) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET USER ADDED + embeds.add(new api.ODEmbed("openticket:add-message")) + embeds.get("openticket:add-message").workers.add( + new api.ODWorker("openticket:add-message",0,async (instance,params,source) => { + const {user,ticket,reason,data} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.add"))) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.add",[discord.userMention(data.id)])) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET USER REMOVED + embeds.add(new api.ODEmbed("openticket:remove-message")) + embeds.get("openticket:remove-message").workers.add( + new api.ODWorker("openticket:remove-message",0,async (instance,params,source) => { + const {user,ticket,reason,data} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.remove"))) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.remove",[discord.userMention(data.id)])) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //TICKET ACTION DM + embeds.add(new api.ODEmbed("openticket:ticket-action-dm")) + embeds.get("openticket:ticket-action-dm").workers.add( + new api.ODWorker("openticket:ticket-action-dm",0,async (instance,params,source) => { + const {user,mode,ticket,reason,additionalData} = params + const channel = await openticket.tickets.getTicketChannel(ticket) + + instance.setColor(generalConfig.data.mainColor) + instance.setTimestamp(new Date()) + instance.addFields({name:lang.getTranslation("params.uppercase.ticket")+":",value:"```#"+(channel ? channel.name : "")+"```",inline:false}) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```",inline:false}) + + if (mode == "close"){ + instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close"))) + instance.setDescription(lang.getTranslation("actions.logs.closeDm")) + }else if (mode == "reopen"){ + instance.setTitle(utilities.emojiTitle("🔓",lang.getTranslation("actions.titles.reopen"))) + instance.setDescription(lang.getTranslation("actions.logs.reopenDm")) + }else if (mode == "delete"){ + instance.setTitle(utilities.emojiTitle("🗑️",lang.getTranslation("actions.titles.delete"))) + instance.setDescription(lang.getTranslation("actions.logs.deleteDm")) + }else if (mode == "claim"){ + instance.setTitle(utilities.emojiTitle("👋",lang.getTranslation("actions.titles.claim"))) + instance.setDescription(lang.getTranslation("actions.logs.claimDm")) + }else if (mode == "unclaim"){ + instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim"))) + instance.setDescription(lang.getTranslation("actions.logs.unclaimDm")) + }else if (mode == "pin"){ + instance.setTitle(utilities.emojiTitle("📌",lang.getTranslation("actions.titles.pin"))) + instance.setDescription(lang.getTranslation("actions.logs.pinDm")) + }else if (mode == "unpin"){ + instance.setTitle(utilities.emojiTitle("📌",lang.getTranslation("actions.titles.unpin"))) + instance.setDescription(lang.getTranslation("actions.logs.unpinDm")) + }else if (mode == "rename"){ + instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.renameDm",["`#"+(typeof additionalData == "string" ? additionalData : "")+"`"])) + }else if (mode == "move"){ + instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.move"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.moveDm",["`"+(additionalData instanceof api.ODTicketOption ? additionalData.get("openticket:name").value : "")+"`"])) + }else if (mode == "add"){ + instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.add"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.addDm",[(additionalData instanceof discord.User ? discord.userMention(additionalData.id) : "")])) + }else if (mode == "remove"){ + instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.remove"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.removeDm",[(additionalData instanceof discord.User ? discord.userMention(additionalData.id) : "")])) + } + }) + ) + + //TICKET ACTION LOGS + embeds.add(new api.ODEmbed("openticket:ticket-action-logs")) + embeds.get("openticket:ticket-action-logs").workers.add( + new api.ODWorker("openticket:ticket-action-logs",0,async (instance,params,source) => { + const {user,mode,ticket,reason,additionalData} = params + const channel = await openticket.tickets.getTicketChannel(ticket) + + instance.setColor(generalConfig.data.mainColor) + instance.setThumbnail(user.displayAvatarURL()) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setTimestamp(new Date()) + instance.addFields( + {name:lang.getTranslation("params.uppercase.ticket")+":",value:"```#"+(channel ? channel.name : "")+"```",inline:false}, + //TODO TRANSLATION!!! + {name:"Option"+":",value:"```"+(ticket.option.get("openticket:name").value)+"```",inline:false}, + ) + if (reason) instance.addFields({name:"Reason:",value:"```"+reason+"```",inline:false}) + + if (mode == "close"){ + instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.closeLog",[discord.userMention(user.id)])) + }else if (mode == "reopen"){ + instance.setTitle(utilities.emojiTitle("🔓",lang.getTranslation("actions.titles.reopen"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.reopenLog",[discord.userMention(user.id)])) + }else if (mode == "delete"){ + instance.setTitle(utilities.emojiTitle("🗑️",lang.getTranslation("actions.titles.delete"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.deleteLog",[discord.userMention(user.id)])) + }else if (mode == "claim"){ + instance.setTitle(utilities.emojiTitle("👋",lang.getTranslation("actions.titles.claim"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.claimLog",[discord.userMention(user.id)])) + }else if (mode == "unclaim"){ + instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.unclaimLog",[discord.userMention(user.id)])) + }else if (mode == "pin"){ + instance.setTitle(utilities.emojiTitle("📌",lang.getTranslation("actions.titles.pin"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.pinLog",[discord.userMention(user.id)])) + }else if (mode == "unpin"){ + instance.setTitle(utilities.emojiTitle("📌",lang.getTranslation("actions.titles.unpin"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.unpinLog",[discord.userMention(user.id)])) + }else if (mode == "rename"){ + instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.renameLog",["`#"+(typeof additionalData == "string" ? additionalData : "")+"`",discord.userMention(user.id)])) + }else if (mode == "move"){ + instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.move"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.moveLog",["`"+(additionalData instanceof api.ODTicketOption ? additionalData.get("openticket:name").value : "")+"`",discord.userMention(user.id)])) + }else if (mode == "add"){ + instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.add"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.addLog",[(additionalData instanceof discord.User ? discord.userMention(additionalData.id) : ""),discord.userMention(user.id)])) + }else if (mode == "remove"){ + instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.remove"))) + instance.setDescription(lang.getTranslationWithParams("actions.logs.removeLog",[(additionalData instanceof discord.User ? discord.userMention(additionalData.id) : ""),discord.userMention(user.id)])) + } + }) + ) +} + +const blacklistEmbeds = () => { + //BLACKLIST VIEW + embeds.add(new api.ODEmbed("openticket:blacklist-view")) + embeds.get("openticket:blacklist-view").workers.add( + new api.ODWorker("openticket:blacklist-view",0,async (instance,params,source) => { + const {user} = params + + const renderedUsers: string[] = [] + openticket.blacklist.getAll().forEach((blacklist) => renderedUsers.push(discord.userMention(blacklist.id.value)+" - "+(blacklist.reason ? blacklist.reason : "/"))) + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🚫",lang.getTranslation("actions.titles.blacklistView"))) + + if (renderedUsers.length > 0) instance.setDescription(renderedUsers.join("\n")) + else{ + instance.setDescription("*"+lang.getTranslation("actions.descriptions.blacklistViewEmpty")+"*") + instance.setFooter(lang.getTranslation("actions.descriptions.blacklistViewTip")) + } + }) + ) + //BLACKLIST GET + embeds.add(new api.ODEmbed("openticket:blacklist-get")) + embeds.get("openticket:blacklist-get").workers.add( + new api.ODWorker("openticket:blacklist-get",0,async (instance,params,source) => { + const {user,data} = params + const blacklist = openticket.blacklist.get(data.id) + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🚫",lang.getTranslation("actions.titles.blacklistGet"))) + + if (blacklist){ + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistGetSuccess",[discord.userMention(data.id)])) + if (blacklist.reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+blacklist.reason+"```"}) + + }else instance.setDescription("*"+lang.getTranslationWithParams("actions.descriptions.blacklistGetEmpty",[discord.userMention(data.id)])+"*") + }) + ) + + //BLACKLIST ADD + embeds.add(new api.ODEmbed("openticket:blacklist-add")) + embeds.get("openticket:blacklist-add").workers.add( + new api.ODWorker("openticket:blacklist-add",0,async (instance,params,source) => { + const {user,data,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🚫",lang.getTranslation("actions.titles.blacklistAdd"))) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistAdd",[discord.userMention(data.id)])) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //BLACKLIST REMOVE + embeds.add(new api.ODEmbed("openticket:blacklist-remove")) + embeds.get("openticket:blacklist-remove").workers.add( + new api.ODWorker("openticket:blacklist-remove",0,async (instance,params,source) => { + const {user,data,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🆓",lang.getTranslation("actions.titles.blacklistRemove"))) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistRemove",[discord.userMention(data.id)])) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //BLACKLIST DM + embeds.add(new api.ODEmbed("openticket:blacklist-dm")) + embeds.get("openticket:blacklist-dm").workers.add( + new api.ODWorker("openticket:blacklist-dm",0,async (instance,params,source) => { + const {user,mode,data,reason} = params + + const title = (mode == "add") ? lang.getTranslation("actions.titles.blacklistAddDm") : lang.getTranslation("actions.titles.blacklistRemoveDm") + const text = (mode == "add") ? lang.getTranslation("actions.logs.blacklistAddDm") : lang.getTranslation("actions.logs.blacklistRemoveDm") + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle((mode == "add") ? "🚫" : "🆓",title)) + instance.setTimestamp(new Date()) + instance.setDescription(text) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```",inline:false}) + }) + ) + + //BLACKLIST LOGS + embeds.add(new api.ODEmbed("openticket:blacklist-logs")) + embeds.get("openticket:blacklist-logs").workers.add( + new api.ODWorker("openticket:blacklist-logs",0,async (instance,params,source) => { + const {user,mode,data,reason} = params + + const title = (mode == "add") ? lang.getTranslation("actions.titles.blacklistAdd") : lang.getTranslation("actions.titles.blacklistRemove") + const text = (mode == "add") ? lang.getTranslationWithParams("actions.logs.blacklistAddLog",[discord.userMention(data.id),discord.userMention(user.id)]) : lang.getTranslationWithParams("actions.logs.blacklistRemoveLog",[discord.userMention(data.id),discord.userMention(user.id)]) + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle((mode == "add") ? "🚫" : "🆓",title)) + instance.setThumbnail(data.displayAvatarURL()) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setTimestamp(new Date()) + instance.setDescription(text) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```",inline:false}) + }) + ) +} + +const transcriptEmbeds = () => { + //TRANSCRIPT TEXT READY + embeds.add(new api.ODEmbed("openticket:transcript-text-ready")) + embeds.get("openticket:transcript-text-ready").workers.add( + new api.ODWorker("openticket:transcript-text-ready",0,async (instance,params,source) => { + const {guild,channel,user,ticket,compiler} = params + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("📄",lang.getTranslation("transcripts.success.ready"))) + instance.setTimestamp(new Date()) + instance.addFields({name:lang.getTranslation("params.uppercase.ticket")+":",value:"#"+channel.name,inline:false}) + + const creatorId = ticket.get("openticket:opened-by").value + if (creatorId){ + try{ + const creator = await channel.client.users.fetch(creatorId) + instance.addFields({name:lang.getTranslation("params.uppercase.creator")+":",value:creator.username+" ("+discord.userMention(creator.id)+")"}) + instance.setThumbnail(creator.displayAvatarURL()) + }catch{} + } + + if (source == "channel") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdChannel",[lang.getTranslation("params.lowercase.text")])) + else if (source == "creator-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdCreator",[lang.getTranslation("params.lowercase.text")])) + else if (source == "participant-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdParticipant",[lang.getTranslation("params.lowercase.text")])) + else if (source == "active-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdActiveAdmin",[lang.getTranslation("params.lowercase.text")])) + else if (source == "every-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdEveryAdmin",[lang.getTranslation("params.lowercase.text")])) + else instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdOther",[lang.getTranslation("params.lowercase.text")])) + }) + ) + + //TRANSCRIPT HTML READY + embeds.add(new api.ODEmbed("openticket:transcript-html-ready")) + embeds.get("openticket:transcript-html-ready").workers.add( + new api.ODWorker("openticket:transcript-html-ready",0,async (instance,params,source) => { + const {guild,channel,user,ticket,compiler,result} = params + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("📄",lang.getTranslation("transcripts.success.ready"))) + instance.setTimestamp(new Date()) + instance.addFields({name:lang.getTranslation("params.uppercase.ticket")+":",value:"#"+channel.name,inline:false}) + if (result.data) instance.setUrl(result.data.url) + + const creatorId = ticket.get("openticket:opened-by").value + if (creatorId){ + try{ + const creator = await channel.client.users.fetch(creatorId) + instance.addFields({name:lang.getTranslation("params.uppercase.creator")+":",value:creator.username+" ("+discord.userMention(creator.id)+")"}) + instance.setThumbnail(creator.displayAvatarURL()) + }catch{} + } + + if (source == "channel") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdChannel",[lang.getTranslation("params.lowercase.html")])) + else if (source == "creator-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdCreator",[lang.getTranslation("params.lowercase.html")])) + else if (source == "participant-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdParticipant",[lang.getTranslation("params.lowercase.html")])) + else if (source == "active-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdActiveAdmin",[lang.getTranslation("params.lowercase.html")])) + else if (source == "every-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdEveryAdmin",[lang.getTranslation("params.lowercase.html")])) + else instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdOther",[lang.getTranslation("params.lowercase.html")])) + }) + ) + + //TRANSCRIPT HTML PROGRESS + embeds.add(new api.ODEmbed("openticket:transcript-html-progress")) + embeds.get("openticket:transcript-html-progress").workers.add( + new api.ODWorker("openticket:transcript-html-progress",0,async (instance,params,source) => { + const {guild,channel,user,ticket,compiler,remaining} = params + + const remainingDate = new Date(new Date().getTime()+remaining) + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("📄",lang.getTranslation("transcripts.success.ready"))) + instance.setDescription(lang.getTranslation("transcripts.success.htmlProgress")) + instance.setTimestamp(new Date()) + instance.addFields({name:lang.getTranslation("params.uppercase.remaining")+":",value:discord.time(remainingDate,"R"),inline:false}) + instance.addFields({name:lang.getTranslation("params.uppercase.ticket")+":",value:"#"+channel.name,inline:false}) + + const creatorId = ticket.get("openticket:opened-by").value + if (creatorId){ + try{ + const creator = await channel.client.users.fetch(creatorId) + instance.addFields({name:lang.getTranslation("params.uppercase.creator")+":",value:creator.username+" ("+discord.userMention(creator.id)+")"}) + instance.setThumbnail(creator.displayAvatarURL()) + }catch{} + } + }) + ) + + //TRANSCRIPT ERROR + embeds.add(new api.ODEmbed("openticket:transcript-error")) + embeds.get("openticket:transcript-error").workers.add( + new api.ODWorker("openticket:transcript-error",0,async (instance,params,source) => { + const {guild,channel,user,ticket,compiler,reason} = params + + instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("❌","Transcript Error")) //TODO TRANSLATION!!! + instance.setTimestamp(new Date()) + instance.setDescription(lang.getTranslation("transcripts.errors.error")) + instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```",inline:false}) + }) + ) +} + +const roleEmbeds = () => { + //REACTION ROLE + embeds.add(new api.ODEmbed("openticket:reaction-role")) + embeds.get("openticket:reaction-role").workers.add( + new api.ODWorker("openticket:reaction-role",0,async (instance,params,source) => { + const {guild,user,role,result} = params + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🎨",lang.getTranslation("actions.titles.roles"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setTimestamp(new Date()) + + const newResult = result.filter((r) => r.action != null).sort((a,b) => { + if (a.action == "added" && b.action == "removed") return -1 + else if (a.action == "removed" && b.action == "added") return 1 + else return 0 + }).map((r) => { + return (r.action == "added") ? "🟢 "+lang.getTranslation("params.uppercase.added")+" "+discord.roleMention(r.role.id) : "🔴 "+lang.getTranslation("params.uppercase.removed")+" "+discord.roleMention(r.role.id) + }) + + if (newResult.length > 0) instance.setDescription(newResult.join("\n")) + else instance.setDescription(lang.getTranslation("actions.descriptions.rolesEmpty")) + }) + ) +} + +const clearEmbeds = () => { + //CLEAR VERIFY MESSAGE + embeds.add(new api.ODEmbed("openticket:clear-verify-message")) + embeds.get("openticket:clear-verify-message").workers.add( + new api.ODWorker("openticket:clear-verify-message",0,async (instance,params,source) => { + const {guild,channel,user,filter,list} = params + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("⚠️","Clear Tickets")) //TODO TRANSLATION!!! + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setTimestamp(new Date()) + instance.setDescription(lang.getTranslation("actions.descriptions.clearVerify")) + instance.addFields( + {name:lang.getTranslation("params.uppercase.filter")+":",value:filter,inline:false}, + {name:lang.getTranslation("params.uppercase.tickets")+":",value:"`"+list.join("`\n`")+"`",inline:false} + ) + }) + ) + + //CLEAR MESSAGE + embeds.add(new api.ODEmbed("openticket:clear-message")) + embeds.get("openticket:clear-message").workers.add( + new api.ODWorker("openticket:clear-message",0,async (instance,params,source) => { + const {guild,channel,user,filter,list} = params + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("⚠️",lang.getTranslation("actions.titles.clear"))) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setTimestamp(new Date()) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.clearReady",[list.length.toString()])) + instance.addFields( + {name:lang.getTranslation("params.uppercase.tickets")+":",value:"`"+list.join("`\n`")+"`",inline:false} + ) + }) + ) + + //CLEAR LOGS + embeds.add(new api.ODEmbed("openticket:clear-logs")) + embeds.get("openticket:clear-logs").workers.add( + new api.ODWorker("openticket:clear-logs",0,async (instance,params,source) => { + const {guild,channel,user,filter,list} = params + + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("⚠️",lang.getTranslation("actions.titles.clear"))) + instance.setThumbnail(user.displayAvatarURL()) + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setTimestamp(new Date()) + instance.setDescription(lang.getTranslationWithParams("actions.logs.clearLog",[list.length.toString(),discord.userMention(user.id)])) + instance.addFields( + {name:lang.getTranslation("params.uppercase.tickets")+":",value:"`"+list.join("`\n`")+"`",inline:false} + ) + }) + ) +} + +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE +//TRANSLATION FINISHED UNTIL HERE + +const autoEmbeds = () => { + //AUTOCLOSE MESSAGE + embeds.add(new api.ODEmbed("openticket:autoclose-message")) + embeds.get("openticket:autoclose-message").workers.add( + new api.ODWorker("openticket:autoclose-message",0,async (instance,params,source) => { + const {user,ticket} = params + const hours: number = ticket.get("openticket:autoclose-hours").value + const description = (source == "leave") ? lang.getTranslation("actions.descriptions.autocloseLeave") : lang.getTranslationWithParams("actions.descriptions.autocloseTimeout",[hours.toString()]) + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autoclose"))) + instance.setDescription(description) + instance.setTimestamp(new Date()) + }) + ) + + //AUTODELETE MESSAGE + embeds.add(new api.ODEmbed("openticket:autodelete-message")) + embeds.get("openticket:autodelete-message").workers.add( + new api.ODWorker("openticket:autodelete-message",0,async (instance,params,source) => { + const {user,ticket} = params + const days: number = ticket.get("openticket:autodelete-days").value + const description = (source == "leave") ? lang.getTranslation("actions.descriptions.autodeleteLeave") : lang.getTranslationWithParams("actions.descriptions.autodeleteTimeout",[days.toString()]) + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodelete"))) + instance.setDescription(description) + instance.setTimestamp(new Date()) + }) + ) + + //AUTOCLOSE ENABLE + embeds.add(new api.ODEmbed("openticket:autoclose-enable")) + embeds.get("openticket:autoclose-enable").workers.add( + new api.ODWorker("openticket:autoclose-enable",0,async (instance,params,source) => { + const {user,ticket,reason,time} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autocloseEnabled"))) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.autocloseEnabled",[time.toString()])) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //AUTODELETE ENABLE + embeds.add(new api.ODEmbed("openticket:autodelete-enable")) + embeds.get("openticket:autodelete-enable").workers.add( + new api.ODWorker("openticket:autodelete-enable",0,async (instance,params,source) => { + const {user,ticket,reason,time} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodeleteEnabled"))) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.autodeleteEnabled",[time.toString()])) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //AUTOCLOSE DISABLE + embeds.add(new api.ODEmbed("openticket:autoclose-disable")) + embeds.get("openticket:autoclose-disable").workers.add( + new api.ODWorker("openticket:autoclose-disable",0,async (instance,params,source) => { + const {user,ticket,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autocloseDisabled"))) + instance.setDescription(lang.getTranslation("actions.descriptions.autocloseDisabled")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) + + //AUTODELETE DISABLE + embeds.add(new api.ODEmbed("openticket:autodelete-disable")) + embeds.get("openticket:autodelete-disable").workers.add( + new api.ODWorker("openticket:autodelete-disable",0,async (instance,params,source) => { + const {user,ticket,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodeleteDisabled"))) + instance.setDescription(lang.getTranslation("actions.descriptions.autodeleteDisabled")) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) + }) + ) +} \ No newline at end of file diff --git a/src/builders/files.ts b/src/builders/files.ts new file mode 100644 index 0000000..ae00fca --- /dev/null +++ b/src/builders/files.ts @@ -0,0 +1,45 @@ +/////////////////////////////////////// +//FILE BUILDERS +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const files = openticket.builders.files +const lang = openticket.languages +const transcriptConfig = openticket.configs.get("openticket:transcripts") + +export const registerAllFiles = async () => { + transcriptFiles() +} + + +const transcriptFiles = () => { + //TEXT TRANSCRIPT + files.add(new api.ODFile("openticket:text-transcript")) + files.get("openticket:text-transcript").workers.add( + new api.ODWorker("openticket:text-transcript",0,async (instance,params,source) => { + const {guild,channel,user,ticket,compiler,result} = params + + const fileMode = transcriptConfig.data.textTranscriptStyle.fileMode + const customName = transcriptConfig.data.textTranscriptStyle.customFileName + + const creatorId = ticket.get("openticket:opened-by").value ?? "unknown-creator-id" + const creator = (await openticket.tickets.getTicketUser(ticket,"creator")) + + if (fileMode == "custom") instance.setName(customName.split(".")[0]+".txt") + else if (fileMode == "user-id") instance.setName(creatorId+".txt") + else if (fileMode == "user-name") instance.setName((creator ? creator.username : "unknown-creator-name")+".txt") + else if (fileMode == "channel-id") instance.setName(channel.id+".txt") + else if (fileMode == "channel-name") instance.setName(channel.name+".txt") + else instance.setName("transcript.txt") + + instance.setDescription(lang.getTranslation("transcripts.success.textFileDescription")) + + if (compiler.id.value != "openticket:text-compiler" || !result.data || typeof result.data.contents != "string"){ + instance.setContents("") + return + } + instance.setContents(result.data.contents) + }) + ) +} \ No newline at end of file diff --git a/src/builders/messages.ts b/src/builders/messages.ts new file mode 100644 index 0000000..25dd7a3 --- /dev/null +++ b/src/builders/messages.ts @@ -0,0 +1,1055 @@ +/////////////////////////////////////// +//MESSAGE BUILDERS +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const messages = openticket.builders.messages +const buttons = openticket.builders.buttons +const dropdowns = openticket.builders.dropdowns +const files = openticket.builders.files +const embeds = openticket.builders.embeds +const lang = openticket.languages +const generalConfig = openticket.configs.get("openticket:general") + +export const registerAllMessages = async () => { + verifyBarMessages() + errorMessages() + helpMenuMessages() + statsMessages() + panelMessages() + ticketMessages() + blacklistMessages() + transcriptMessages() + roleMessages() + clearMessages() + autoMessages() +} + +const verifyBarMessages = () => { + //VERIFYBAR TICKET MESSAGE + messages.add(new api.ODMessage("openticket:verifybar-ticket-message")) + messages.get("openticket:verifybar-ticket-message").workers.add( + new api.ODWorker("openticket:verifybar-ticket-message",0,async (instance,params,source) => { + const {guild,channel,user,verifybar} = params + if (!guild){ + instance.setContent("ODError: Not In Guild => `openticket:verifybar-ticket-message`") + return + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket){ + instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-ticket-message`") + return + } + const option = ticket.option + + //add pings + const pingOptions = option.get("openticket:ticket-message-ping").value + const pings: string[] = [discord.userMention(user.id)] + if (pingOptions["@everyone"]) pings.push("@everyone") + if (pingOptions["@here"]) pings.push("@here") + pingOptions.custom.forEach((ping) => pings.push(discord.roleMention(ping))) + const pingText = (pings.length > 0) ? pings.join(" ")+"\n" : "" + + //add text + const text = option.get("openticket:ticket-message-text").value + if (text !== "") instance.setContent(pingText+text) + else instance.setContent(pingText) + + //add embed + if (option.get("openticket:ticket-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + + //add verifybar components + if (verifybar.id.value == "openticket:claim-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + + }else if (verifybar.id.value == "openticket:unclaim-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + + }else if (verifybar.id.value == "openticket:pin-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + + }else if (verifybar.id.value == "openticket:unpin-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + + }else if (verifybar.id.value == "openticket:close-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + + }else if (verifybar.id.value == "openticket:reopen-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + + }else if (verifybar.id.value == "openticket:delete-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:"Without Transcript",customColor:"red"})) + } + }) + ) + + //TICKET CLOSED + messages.add(new api.ODMessage("openticket:verifybar-close-message")) + messages.get("openticket:verifybar-close-message").workers.add( + new api.ODWorker("openticket:verifybar-close-message",0,async (instance,params,source) => { + const {guild,channel,user,verifybar,originalMessage} = params + if (!guild){ + instance.setContent("ODError: Not In Guild => `openticket:verifybar-close-message`") + return + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket){ + instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-close-message`") + return + } + + const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + //add embed + instance.addEmbed(await embeds.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + + //add verifybar components + if (verifybar.id.value == "openticket:reopen-ticket-close-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + + }else if (verifybar.id.value == "openticket:delete-ticket-close-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:"Without Transcript",customColor:"red"})) + } + }) + ) + + //TICKET REOPENED + messages.add(new api.ODMessage("openticket:verifybar-reopen-message")) + messages.get("openticket:verifybar-reopen-message").workers.add( + new api.ODWorker("openticket:verifybar-reopen-message",0,async (instance,params,source) => { + const {guild,channel,user,verifybar,originalMessage} = params + if (!guild){ + instance.setContent("ODError: Not In Guild => `openticket:verifybar-reopen-message`") + return + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket){ + instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-reopen-message`") + return + } + + const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + //add embed + instance.addEmbed(await embeds.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + + //add verifybar components + if (verifybar.id.value == "openticket:close-ticket-reopen-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + + }else if (verifybar.id.value == "openticket:delete-ticket-reopen-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:"Without Transcript",customColor:"red"})) + } + }) + ) + + //TICKET CLAIM + messages.add(new api.ODMessage("openticket:verifybar-claim-message")) + messages.get("openticket:verifybar-claim-message").workers.add( + new api.ODWorker("openticket:verifybar-claim-message",0,async (instance,params,source) => { + const {guild,channel,user,verifybar,originalMessage} = params + if (!guild){ + instance.setContent("ODError: Not In Guild => `openticket:verifybar-claim-message`") + return + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket){ + instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-claim-message`") + return + } + + const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + //add embed + instance.addEmbed(await embeds.getSafe("openticket:claim-message").build("other",{guild,channel,user,ticket,reason})) + + //add verifybar components + if (verifybar.id.value == "openticket:unclaim-ticket-claim-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + } + }) + ) + + //TICKET UNCLAIM + messages.add(new api.ODMessage("openticket:verifybar-unclaim-message")) + messages.get("openticket:verifybar-unclaim-message").workers.add( + new api.ODWorker("openticket:verifybar-unclaim-message",0,async (instance,params,source) => { + const {guild,channel,user,verifybar,originalMessage} = params + if (!guild){ + instance.setContent("ODError: Not In Guild => `openticket:verifybar-unclaim-message`") + return + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket){ + instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-unclaim-message`") + return + } + + const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + //add embed + instance.addEmbed(await embeds.getSafe("openticket:unclaim-message").build("other",{guild,channel,user,ticket,reason})) + + //add verifybar components + if (verifybar.id.value == "openticket:claim-ticket-unclaim-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + } + }) + ) + + //TICKET PIN + messages.add(new api.ODMessage("openticket:verifybar-pin-message")) + messages.get("openticket:verifybar-pin-message").workers.add( + new api.ODWorker("openticket:verifybar-pin-message",0,async (instance,params,source) => { + const {guild,channel,user,verifybar,originalMessage} = params + if (!guild){ + instance.setContent("ODError: Not In Guild => `openticket:verifybar-pin-message`") + return + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket){ + instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-pin-message`") + return + } + + const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + //add embed + instance.addEmbed(await embeds.getSafe("openticket:pin-message").build("other",{guild,channel,user,ticket,reason})) + + //add verifybar components + if (verifybar.id.value == "openticket:unpin-ticket-pin-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + } + }) + ) + + //TICKET UNPIN + messages.add(new api.ODMessage("openticket:verifybar-unpin-message")) + messages.get("openticket:verifybar-unpin-message").workers.add( + new api.ODWorker("openticket:verifybar-unpin-message",0,async (instance,params,source) => { + const {guild,channel,user,verifybar,originalMessage} = params + if (!guild){ + instance.setContent("ODError: Not In Guild => `openticket:verifybar-unpin-message`") + return + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket){ + instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-unpin-message`") + return + } + + const rawReason = (originalMessage.embeds[0] && originalMessage.embeds[0].fields[0]) ? originalMessage.embeds[0].fields[0].value : null + const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) + + //add embed + instance.addEmbed(await embeds.getSafe("openticket:unpin-message").build("other",{guild,channel,user,ticket,reason})) + + //add verifybar components + if (verifybar.id.value == "openticket:pin-ticket-unpin-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + } + }) + ) + + //TICKET AUTOCLOSED + messages.add(new api.ODMessage("openticket:verifybar-autoclose-message")) + messages.get("openticket:verifybar-autoclose-message").workers.add( + new api.ODWorker("openticket:verifybar-autoclose-message",0,async (instance,params,source) => { + const {guild,channel,user,verifybar,originalMessage} = params + if (!guild || channel.isDMBased()){ + instance.setContent("ODError: Not In Guild => `openticket:verifybar-autoclose-message`") + return + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket){ + instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-autoclose-message`") + return + } + + //add embed + instance.addEmbed(await embeds.getSafe("openticket:autoclose-message").build("other",{guild,channel,user,ticket})) + + //add verifybar components + if (verifybar.id.value == "openticket:reopen-ticket-autoclose-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + + }else if (verifybar.id.value == "openticket:delete-ticket-autoclose-message"){ + instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:"Without Transcript",customColor:"red"})) + } + }) + ) +} + +const errorMessages = () => { + //ERROR + messages.add(new api.ODMessage("openticket:error")) + messages.get("openticket:error").workers.add( + new api.ODWorker("openticket:error",0,async (instance,params,source) => { + const {guild,channel,user,error,layout} = params + instance.addEmbed(await embeds.getSafe("openticket:error").build(source,{guild,channel,user,error,layout})) + instance.setEphemeral(true) + }) + ) + + //ERROR OPTION MISSING + messages.add(new api.ODMessage("openticket:error-option-missing")) + messages.get("openticket:error-option-missing").workers.add( + new api.ODWorker("openticket:error-option-missing",0,async (instance,params,source) => { + const {guild,channel,user,error} = params + instance.addEmbed(await embeds.getSafe("openticket:error-option-missing").build(source,{guild,channel,user,error})) + instance.setEphemeral(true) + }) + ) + + //ERROR OPTION INVALID + messages.add(new api.ODMessage("openticket:error-option-invalid")) + messages.get("openticket:error-option-invalid").workers.add( + new api.ODWorker("openticket:error-option-invalid",0,async (instance,params,source) => { + const {guild,channel,user,error} = params + instance.addEmbed(await embeds.getSafe("openticket:error-option-invalid").build(source,{guild,channel,user,error})) + instance.setEphemeral(true) + }) + ) + + //ERROR UNKNOWN COMMAND + messages.add(new api.ODMessage("openticket:error-unknown-command")) + messages.get("openticket:error-unknown-command").workers.add( + new api.ODWorker("openticket:error-unknown-command",0,async (instance,params,source) => { + const {guild,channel,user,error} = params + instance.addEmbed(await embeds.getSafe("openticket:error-unknown-command").build(source,{guild,channel,user,error})) + instance.setEphemeral(true) + }) + ) + + //ERROR NO PERMISSIONS + messages.add(new api.ODMessage("openticket:error-no-permissions")) + messages.get("openticket:error-no-permissions").workers.add( + new api.ODWorker("openticket:error-no-permissions",0,async (instance,params,source) => { + const {guild,channel,user,permissions} = params + instance.addEmbed(await embeds.getSafe("openticket:error-no-permissions").build(source,{guild,channel,user,permissions})) + instance.setEphemeral(true) + }) + ) + + //ERROR NO PERMISSIONS COOLDOWN + messages.add(new api.ODMessage("openticket:error-no-permissions-cooldown")) + messages.get("openticket:error-no-permissions-cooldown").workers.add( + new api.ODWorker("openticket:error-no-permissions-cooldown",0,async (instance,params,source) => { + const {guild,channel,user,until} = params + instance.addEmbed(await embeds.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild,channel,user,until})) + instance.setEphemeral(true) + }) + ) + + //ERROR NO PERMISSIONS BLACKLISTED + messages.add(new api.ODMessage("openticket:error-no-permissions-blacklisted")) + messages.get("openticket:error-no-permissions-blacklisted").workers.add( + new api.ODWorker("openticket:error-no-permissions-blacklisted",0,async (instance,params,source) => { + const {guild,channel,user} = params + instance.addEmbed(await embeds.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild,channel,user})) + instance.setEphemeral(true) + }) + ) + + //ERROR NO PERMISSIONS LIMITS + messages.add(new api.ODMessage("openticket:error-no-permissions-limits")) + messages.get("openticket:error-no-permissions-limits").workers.add( + new api.ODWorker("openticket:error-no-permissions-limits",0,async (instance,params,source) => { + const {guild,channel,user,limit} = params + instance.addEmbed(await embeds.getSafe("openticket:error-no-permissions-limits").build(source,{guild,channel,user,limit})) + instance.setEphemeral(true) + }) + ) + + //ERROR RESPONDER TIMEOUT + messages.add(new api.ODMessage("openticket:error-responder-timeout")) + messages.get("openticket:error-responder-timeout").workers.add( + new api.ODWorker("openticket:error-responder-timeout",0,async (instance,params,source) => { + const {guild,channel,user} = params + instance.addEmbed(await embeds.getSafe("openticket:error-responder-timeout").build(source,{guild,channel,user})) + instance.setEphemeral(true) + }) + ) + + //ERROR TICKET UNKNOWN + messages.add(new api.ODMessage("openticket:error-ticket-unknown")) + messages.get("openticket:error-ticket-unknown").workers.add( + new api.ODWorker("openticket:error-ticket-unknown",0,async (instance,params,source) => { + const {guild,channel,user} = params + instance.addEmbed(await embeds.getSafe("openticket:error-ticket-unknown").build(source,{guild,channel,user})) + instance.setEphemeral(true) + }) + ) + + //ERROR TICKET DEPRECATED + messages.add(new api.ODMessage("openticket:error-ticket-deprecated")) + messages.get("openticket:error-ticket-deprecated").workers.add( + new api.ODWorker("openticket:error-ticket-deprecated",0,async (instance,params,source) => { + const {guild,channel,user} = params + instance.addEmbed(await embeds.getSafe("openticket:error-ticket-deprecated").build(source,{guild,channel,user})) + instance.addComponent(await buttons.getSafe("openticket:error-ticket-deprecated-transcript").build(source,{})) + instance.setEphemeral(true) + }) + ) + + //ERROR OPTION UNKNOWN + messages.add(new api.ODMessage("openticket:error-option-unknown")) + messages.get("openticket:error-option-unknown").workers.add( + new api.ODWorker("openticket:error-option-unknown",0,async (instance,params,source) => { + const {guild,channel,user} = params + instance.addEmbed(await embeds.getSafe("openticket:error-option-unknown").build(source,{guild,channel,user})) + instance.setEphemeral(true) + }) + ) + + //ERROR PANEL UNKNOWN + messages.add(new api.ODMessage("openticket:error-panel-unknown")) + messages.get("openticket:error-panel-unknown").workers.add( + new api.ODWorker("openticket:error-panel-unknown",0,async (instance,params,source) => { + const {guild,channel,user} = params + instance.addEmbed(await embeds.getSafe("openticket:error-panel-unknown").build(source,{guild,channel,user})) + instance.setEphemeral(true) + }) + ) + + //ERROR NOD IN GUILD + messages.add(new api.ODMessage("openticket:error-not-in-guild")) + messages.get("openticket:error-not-in-guild").workers.add( + new api.ODWorker("openticket:error-not-in-guild",0,async (instance,params,source) => { + const {channel,user} = params + instance.addEmbed(await embeds.getSafe("openticket:error-not-in-guild").build(source,{channel,user})) + instance.setEphemeral(true) + }) + ) + + //ERROR CHANNEL RENAME + messages.add(new api.ODMessage("openticket:error-channel-rename")) + messages.get("openticket:error-channel-rename").workers.add( + new api.ODWorker("openticket:error-channel-rename",0,async (instance,params,source) => { + const {guild,channel,user,originalName,newName} = params + instance.addEmbed(await embeds.getSafe("openticket:error-channel-rename").build(source,{guild,channel,user,originalName,newName})) + instance.setEphemeral(true) + }) + ) + + //ERROR TICKET BUSY + messages.add(new api.ODMessage("openticket:error-ticket-busy")) + messages.get("openticket:error-ticket-busy").workers.add( + new api.ODWorker("openticket:error-ticket-busy",0,async (instance,params,source) => { + const {guild,channel,user} = params + instance.addEmbed(await embeds.getSafe("openticket:error-ticket-busy").build(source,{guild,channel,user})) + instance.setEphemeral(true) + }) + ) +} + +const helpMenuMessages = () => { + //HELP MENU + messages.add(new api.ODMessage("openticket:help-menu")) + messages.get("openticket:help-menu").workers.add( + new api.ODWorker("openticket:help-menu",0,async (instance,params,source) => { + const {mode,page} = params + const totalPages = (await openticket.helpmenu.render(mode)).length + + const embed = await embeds.getSafe("openticket:help-menu").build(source,{mode,page}) + instance.addEmbed(embed) + if (totalPages > 1){ + //when more than 1 page + instance.addComponent(await buttons.getSafe("openticket:help-menu-previous").build(source,{mode,page})) + instance.addComponent(await buttons.getSafe("openticket:help-menu-page").build(source,{mode,page})) + instance.addComponent(await buttons.getSafe("openticket:help-menu-next").build(source,{mode,page})) + instance.addComponent(buttons.getNewLine("openticket:help-menu-divider")) + } + if (generalConfig.data.textCommands && generalConfig.data.slashCommands) instance.addComponent(await buttons.get("openticket:help-menu-switch").build(source,{mode,page})) + }) + ) +} + +const statsMessages = () => { + //STATS GLOBAL + messages.add(new api.ODMessage("openticket:stats-global")) + messages.get("openticket:stats-global").workers.add( + new api.ODWorker("openticket:stats-global",0,async (instance,params,source) => { + const {guild,channel,user} = params + instance.addEmbed(await embeds.getSafe("openticket:stats-global").build(source,{guild,channel,user})) + }) + ) + + //STATS TICKET + messages.add(new api.ODMessage("openticket:stats-ticket")) + messages.get("openticket:stats-ticket").workers.add( + new api.ODWorker("openticket:stats-ticket",0,async (instance,params,source) => { + const {guild,channel,user,scopeData} = params + instance.addEmbed(await embeds.getSafe("openticket:stats-ticket").build(source,{guild,channel,user,scopeData})) + }) + ) + + //STATS USER + messages.add(new api.ODMessage("openticket:stats-user")) + messages.get("openticket:stats-user").workers.add( + new api.ODWorker("openticket:stats-user",0,async (instance,params,source) => { + const {guild,channel,user,scopeData} = params + instance.addEmbed(await embeds.getSafe("openticket:stats-user").build(source,{guild,channel,user,scopeData})) + }) + ) + + //STATS RESET + messages.add(new api.ODMessage("openticket:stats-reset")) + messages.get("openticket:stats-reset").workers.add( + new api.ODWorker("openticket:stats-reset",0,async (instance,params,source) => { + const {guild,channel,user,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:stats-reset").build(source,{guild,channel,user,reason})) + }) + ) + + //STATS TICKET UNKNOWN + messages.add(new api.ODMessage("openticket:stats-ticket-unknown")) + messages.get("openticket:stats-ticket-unknown").workers.add( + new api.ODWorker("openticket:stats-ticket-unknown",0,async (instance,params,source) => { + const {guild,channel,user,id} = params + instance.addEmbed(await embeds.getSafe("openticket:stats-ticket-unknown").build(source,{guild,channel,user,id})) + instance.setEphemeral(true) + }) + ) +} + +const panelMessages = () => { + //PANEL + messages.add(new api.ODMessage("openticket:panel")) + messages.get("openticket:panel").workers.add([ + new api.ODWorker("openticket:panel-layout",1,async (instance,params,source) => { + const {guild,channel,user,panel} = params + + //add text + const text = panel.get("openticket:text").value + if (panel.get("openticket:describe-options-in-text").value){ + //describe options in text + const describeText = (await import("../data/openticket/panelLoader.ts")).describePanelOptions("text",panel) + instance.setContent(text+"\n\n"+describeText) + }else if (text){ + instance.setContent(text) + } + + if (panel.get("openticket:enable-max-tickets-warning-text").value && generalConfig.data.system.limits.enabled){ + instance.setContent(instance.data.content+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.system.limits.userMaximum.toString()])+"*") + } + + //add embed + const embedOptions = panel.get("openticket:embed").value + if (embedOptions.enabled) instance.addEmbed(await embeds.getSafe("openticket:panel").build(source,{guild,channel,user,panel})) + }), + new api.ODWorker("openticket:panel-components",0,async (instance,params,source) => { + const {guild,channel,user,panel} = params + const options: api.ODOption[] = [] + panel.get("openticket:options").value.forEach((id) => { + const opt = openticket.options.get(id) + if (opt) options.push(opt) + }) + + if (panel.get("openticket:dropdown").value){ + //dropdown + const ticketOptions: api.ODTicketOption[] = [] + options.forEach((option) => { + if (option instanceof api.ODTicketOption) ticketOptions.push(option) + }) + instance.addComponent(await dropdowns.getSafe("openticket:panel-dropdown-tickets").build(source,{guild,channel,user,panel,options:ticketOptions})) + }else{ + //buttons + for (const option of options){ + if (option instanceof api.ODTicketOption) instance.addComponent(await buttons.getSafe("openticket:ticket-option").build(source,{guild,channel,user,panel,option})) + else if (option instanceof api.ODWebsiteOption) instance.addComponent(await buttons.getSafe("openticket:website-option").build(source,{guild,channel,user,panel,option})) + else if (option instanceof api.ODRoleOption) instance.addComponent(await buttons.getSafe("openticket:role-option").build(source,{guild,channel,user,panel,option})) + } + } + }) + ]) + + //PANEL READY + messages.add(new api.ODMessage("openticket:panel-ready")) + messages.get("openticket:panel-ready").workers.add( + new api.ODWorker("openticket:panel-ready",0,async (instance,params,source) => { + instance.setContent("## "+lang.getTranslation("actions.descriptions.panelReady")) + instance.setEphemeral(true) + }) + ) +} + +const ticketMessages = () => { + //TICKET CREATED + messages.add(new api.ODMessage("openticket:ticket-created")) + messages.get("openticket:ticket-created").workers.add( + new api.ODWorker("openticket:ticket-created",0,async (instance,params,source) => { + const {guild,channel,user,ticket} = params + + instance.addEmbed(await embeds.getSafe("openticket:ticket-created").build(source,{guild,channel,user,ticket})) + instance.addComponent(await buttons.getSafe("openticket:visit-ticket").build("ticket-created",{guild,channel,user,ticket})) + instance.setEphemeral(true) + }) + ) + + //TICKET CREATED DM + messages.add(new api.ODMessage("openticket:ticket-created-dm")) + messages.get("openticket:ticket-created-dm").workers.add( + new api.ODWorker("openticket:ticket-created-dm",0,async (instance,params,source) => { + const {guild,channel,user,ticket} = params + + //add text + const text = ticket.option.get("openticket:dm-message-text").value + if (text !== "") instance.setContent(text) + + //add embed + if (ticket.option.get("openticket:dm-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("openticket:ticket-created-dm").build(source,{guild,channel,user,ticket})) + + //add components + instance.addComponent(await buttons.getSafe("openticket:visit-ticket").build("ticket-created",{guild,channel,user,ticket})) + }) + ) + + //TICKET CREATED LOGS + messages.add(new api.ODMessage("openticket:ticket-created-logs")) + messages.get("openticket:ticket-created-logs").workers.add( + new api.ODWorker("openticket:ticket-created-logs",0,async (instance,params,source) => { + const {guild,channel,user,ticket} = params + + instance.addEmbed(await embeds.getSafe("openticket:ticket-created-logs").build(source,{guild,channel,user,ticket})) + instance.addComponent(await buttons.getSafe("openticket:visit-ticket").build("ticket-created",{guild,channel,user,ticket})) + }) + ) + + //TICKET MESSAGE + messages.add(new api.ODMessage("openticket:ticket-message")) + messages.get("openticket:ticket-message").workers.add([ + new api.ODWorker("openticket:ticket-message-layout",0,async (instance,params,source) => { + const {guild,channel,user,ticket} = params + + //add pings + const pingOptions = ticket.option.get("openticket:ticket-message-ping").value + const pings: string[] = [discord.userMention(user.id)] + if (pingOptions["@everyone"]) pings.push("@everyone") + if (pingOptions["@here"]) pings.push("@here") + pingOptions.custom.forEach((ping) => pings.push(discord.roleMention(ping))) + const pingText = (pings.length > 0) ? pings.join(" ")+"\n" : "" + + //add text + const text = ticket.option.get("openticket:ticket-message-text").value + if (text !== "") instance.setContent(pingText+text) + else instance.setContent(pingText) + + //add embed + if (ticket.option.get("openticket:ticket-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("openticket:ticket-message").build(source,{guild,channel,user,ticket})) + + + }), + new api.ODWorker("openticket:ticket-message-components",1,async (instance,params,source) => { + const {guild,channel,user,ticket} = params + //add components + if (generalConfig.data.system.enableTicketClaimButtons && !ticket.get("openticket:closed").value){ + //enable ticket claiming + if (ticket.get("openticket:claimed").value){ + instance.addComponent(await buttons.getSafe("openticket:unclaim-ticket").build("ticket-message",{guild,channel,user,ticket})) + }else{ + instance.addComponent(await buttons.getSafe("openticket:claim-ticket").build("ticket-message",{guild,channel,user,ticket})) + } + } + if (generalConfig.data.system.enableTicketPinButtons && !ticket.get("openticket:closed").value){ + //enable ticket pinning + if (ticket.get("openticket:pinned").value){ + instance.addComponent(await buttons.getSafe("openticket:unpin-ticket").build("ticket-message",{guild,channel,user,ticket})) + }else{ + instance.addComponent(await buttons.getSafe("openticket:pin-ticket").build("ticket-message",{guild,channel,user,ticket})) + } + } + if (generalConfig.data.system.enableTicketCloseButtons){ + //enable ticket closing + if (ticket.get("openticket:closed").value){ + instance.addComponent(await buttons.getSafe("openticket:reopen-ticket").build("ticket-message",{guild,channel,user,ticket})) + }else{ + instance.addComponent(await buttons.getSafe("openticket:close-ticket").build("ticket-message",{guild,channel,user,ticket})) + } + } + //enable ticket deletion + if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("openticket:delete-ticket").build("ticket-message",{guild,channel,user,ticket})) + }), + new api.ODWorker("openticket:ticket-message-disable-components",2,async (instance,params,source) => { + const {ticket} = params + if (ticket.get("openticket:for-deletion").value){ + //disable all buttons when ticket is being prepared for deletion + instance.data.components.forEach((component) => { + if ((component.component instanceof discord.ButtonBuilder) || (component.component instanceof discord.BaseSelectMenuBuilder)){ + component.component.setDisabled(true) + } + }) + } + }) + ]) + + //TICKET CLOSED + messages.add(new api.ODMessage("openticket:close-message")) + messages.get("openticket:close-message").workers.add( + new api.ODWorker("openticket:close-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:close-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("openticket:reopen-ticket").build("close-message",{guild,channel,user,ticket})) + if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("openticket:delete-ticket").build("close-message",{guild,channel,user,ticket})) + }) + ) + + //TICKET REOPENED + messages.add(new api.ODMessage("openticket:reopen-message")) + messages.get("openticket:reopen-message").workers.add( + new api.ODWorker("openticket:reopen-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:reopen-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("openticket:close-ticket").build("reopen-message",{guild,channel,user,ticket})) + if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("openticket:delete-ticket").build("reopen-message",{guild,channel,user,ticket})) + }) + ) + + //TICKET DELETED + messages.add(new api.ODMessage("openticket:delete-message")) + messages.get("openticket:delete-message").workers.add( + new api.ODWorker("openticket:delete-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:delete-message").build(source,{guild,channel,user,ticket,reason})) + }) + ) + + //TICKET CLAIMED + messages.add(new api.ODMessage("openticket:claim-message")) + messages.get("openticket:claim-message").workers.add( + new api.ODWorker("openticket:claim-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:claim-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("openticket:unclaim-ticket").build("claim-message",{guild,channel,user,ticket})) + }) + ) + + //TICKET UNCLAIMED + messages.add(new api.ODMessage("openticket:unclaim-message")) + messages.get("openticket:unclaim-message").workers.add( + new api.ODWorker("openticket:unclaim-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:unclaim-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("openticket:claim-ticket").build("unclaim-message",{guild,channel,user,ticket})) + }) + ) + + //TICKET PINNED + messages.add(new api.ODMessage("openticket:pin-message")) + messages.get("openticket:pin-message").workers.add( + new api.ODWorker("openticket:pin-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:pin-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("openticket:unpin-ticket").build("pin-message",{guild,channel,user,ticket})) + }) + ) + + //TICKET UNPINNED + messages.add(new api.ODMessage("openticket:unpin-message")) + messages.get("openticket:unpin-message").workers.add( + new api.ODWorker("openticket:unpin-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:unpin-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("openticket:pin-ticket").build("unpin-message",{guild,channel,user,ticket})) + }) + ) + + //TICKET RENAMED + messages.add(new api.ODMessage("openticket:rename-message")) + messages.get("openticket:rename-message").workers.add( + new api.ODWorker("openticket:rename-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason,data} = params + instance.addEmbed(await embeds.getSafe("openticket:rename-message").build(source,{guild,channel,user,ticket,reason,data})) + }) + ) + + //TICKET MOVED + messages.add(new api.ODMessage("openticket:move-message")) + messages.get("openticket:move-message").workers.add( + new api.ODWorker("openticket:move-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason,data} = params + instance.addEmbed(await embeds.getSafe("openticket:move-message").build(source,{guild,channel,user,ticket,reason,data})) + }) + ) + + //TICKET USER ADDED + messages.add(new api.ODMessage("openticket:add-message")) + messages.get("openticket:add-message").workers.add( + new api.ODWorker("openticket:add-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason,data} = params + instance.addEmbed(await embeds.getSafe("openticket:add-message").build(source,{guild,channel,user,ticket,reason,data})) + }) + ) + + //TICKET USER REMOVED + messages.add(new api.ODMessage("openticket:remove-message")) + messages.get("openticket:remove-message").workers.add( + new api.ODWorker("openticket:remove-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason,data} = params + instance.addEmbed(await embeds.getSafe("openticket:remove-message").build(source,{guild,channel,user,ticket,reason,data})) + }) + ) + + //TICKET ACTION DM + messages.add(new api.ODMessage("openticket:ticket-action-dm")) + messages.get("openticket:ticket-action-dm").workers.add( + new api.ODWorker("openticket:ticket-action-dm",0,async (instance,params,source) => { + const {guild,channel,user,mode,ticket,reason,additionalData} = params + instance.addEmbed(await embeds.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,mode,ticket,reason,additionalData})) + }) + ) + + //TICKET ACTION LOGS + messages.add(new api.ODMessage("openticket:ticket-action-logs")) + messages.get("openticket:ticket-action-logs").workers.add( + new api.ODWorker("openticket:ticket-action-logs",0,async (instance,params,source) => { + const {guild,channel,user,mode,ticket,reason,additionalData} = params + instance.addEmbed(await embeds.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,mode,ticket,reason,additionalData})) + }) + ) +} + +const blacklistMessages = () => { + //BLACKLIST VIEW + messages.add(new api.ODMessage("openticket:blacklist-view")) + messages.get("openticket:blacklist-view").workers.add( + new api.ODWorker("openticket:blacklist-view",0,async (instance,params,source) => { + const {guild,channel,user} = params + instance.addEmbed(await embeds.getSafe("openticket:blacklist-view").build(source,{guild,channel,user})) + }) + ) + + //BLACKLIST GET + messages.add(new api.ODMessage("openticket:blacklist-get")) + messages.get("openticket:blacklist-get").workers.add( + new api.ODWorker("openticket:blacklist-get",0,async (instance,params,source) => { + const {guild,channel,user,data} = params + instance.addEmbed(await embeds.getSafe("openticket:blacklist-get").build(source,{guild,channel,user,data})) + }) + ) + + //BLACKLIST ADD + messages.add(new api.ODMessage("openticket:blacklist-add")) + messages.get("openticket:blacklist-add").workers.add( + new api.ODWorker("openticket:blacklist-add",0,async (instance,params,source) => { + const {guild,channel,user,data,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:blacklist-add").build(source,{guild,channel,user,data,reason})) + }) + ) + + //BLACKLIST REMOVE + messages.add(new api.ODMessage("openticket:blacklist-remove")) + messages.get("openticket:blacklist-remove").workers.add( + new api.ODWorker("openticket:blacklist-remove",0,async (instance,params,source) => { + const {guild,channel,user,data,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:blacklist-remove").build(source,{guild,channel,user,data,reason})) + }) + ) + + //BLACKLIST DM + messages.add(new api.ODMessage("openticket:blacklist-dm")) + messages.get("openticket:blacklist-dm").workers.add( + new api.ODWorker("openticket:blacklist-dm",0,async (instance,params,source) => { + const {guild,channel,user,mode,data,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:blacklist-dm").build(source,{guild,channel,user,mode,data,reason})) + }) + ) + + //BLACKLIST LOGS + messages.add(new api.ODMessage("openticket:blacklist-logs")) + messages.get("openticket:blacklist-logs").workers.add( + new api.ODWorker("openticket:blacklist-logs",0,async (instance,params,source) => { + const {guild,channel,user,mode,data,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:blacklist-logs").build(source,{guild,channel,user,mode,data,reason})) + }) + ) +} + +const transcriptMessages = () => { + //TRANSCRIPT TEXT READY + messages.add(new api.ODMessage("openticket:transcript-text-ready")) + messages.get("openticket:transcript-text-ready").workers.add( + new api.ODWorker("openticket:transcript-text-ready",0,async (instance,params,source) => { + const {guild,channel,user,ticket,compiler,result} = params + instance.addEmbed(await embeds.getSafe("openticket:transcript-text-ready").build(source,{guild,channel,user,ticket,compiler,result})) + instance.addFile(await files.getSafe("openticket:text-transcript").build(source,{guild,channel,user,ticket,compiler,result})) + }) + ) + + //TRANSCRIPT HTML READY + messages.add(new api.ODMessage("openticket:transcript-html-ready")) + messages.get("openticket:transcript-html-ready").workers.add( + new api.ODWorker("openticket:transcript-html-ready",0,async (instance,params,source) => { + const {guild,channel,user,ticket,compiler,result} = params + instance.addEmbed(await embeds.getSafe("openticket:transcript-html-ready").build(source,{guild,channel,user,ticket,compiler,result})) + instance.addComponent(await buttons.getSafe("openticket:transcript-html-visit").build(source,{guild,channel,user,ticket,compiler,result})) + }) + ) + + //TRANSCRIPT HTML PROGRESS + messages.add(new api.ODMessage("openticket:transcript-html-progress")) + messages.get("openticket:transcript-html-progress").workers.add( + new api.ODWorker("openticket:transcript-html-progress",0,async (instance,params,source) => { + const {guild,channel,user,ticket,compiler,remaining} = params + instance.addEmbed(await embeds.getSafe("openticket:transcript-html-progress").build(source,{guild,channel,user,ticket,compiler,remaining})) + }) + ) + + //TRANSCRIPT ERROR + messages.add(new api.ODMessage("openticket:transcript-error")) + messages.get("openticket:transcript-error").workers.add( + new api.ODWorker("openticket:transcript-error",0,async (instance,params,source) => { + const {guild,channel,user,ticket,compiler,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason})) + instance.addComponent(await buttons.getSafe("openticket:transcript-error-retry").build(source,{guild,channel,user,ticket,compiler,reason})) + instance.addComponent(await buttons.getSafe("openticket:transcript-error-continue").build(source,{guild,channel,user,ticket,compiler,reason})) + }) + ) +} + +const roleMessages = () => { + //REACTION ROLE + messages.add(new api.ODMessage("openticket:reaction-role")) + messages.get("openticket:reaction-role").workers.add( + new api.ODWorker("openticket:reaction-role",0,async (instance,params,source) => { + const {guild,user,role,result} = params + instance.addEmbed(await embeds.getSafe("openticket:reaction-role").build(source,{guild,user,role,result})) + instance.setEphemeral(true) + }) + ) +} + +const clearMessages = () => { + //CLEAR VERIFY MESSAGE + messages.add(new api.ODMessage("openticket:clear-verify-message")) + messages.get("openticket:clear-verify-message").workers.add( + new api.ODWorker("openticket:clear-verify-message",0,async (instance,params,source) => { + const {guild,channel,user,filter,list} = params + instance.addEmbed(await embeds.getSafe("openticket:clear-verify-message").build(source,{guild,channel,user,filter,list})) + instance.addComponent(await buttons.getSafe("openticket:clear-continue").build(source,{guild,channel,user,filter,list})) + instance.setEphemeral(true) + }) + ) + + //CLEAR MESSAGE + messages.add(new api.ODMessage("openticket:clear-message")) + messages.get("openticket:clear-message").workers.add( + new api.ODWorker("openticket:clear-message",0,async (instance,params,source) => { + const {guild,channel,user,filter,list} = params + instance.addEmbed(await embeds.getSafe("openticket:clear-message").build(source,{guild,channel,user,filter,list})) + instance.setEphemeral(true) + }) + ) + + //CLEAR LOGS + messages.add(new api.ODMessage("openticket:clear-logs")) + messages.get("openticket:clear-logs").workers.add( + new api.ODWorker("openticket:clear-logs",0,async (instance,params,source) => { + const {guild,channel,user,filter,list} = params + instance.addEmbed(await embeds.getSafe("openticket:clear-logs").build(source,{guild,channel,user,filter,list})) + }) + ) +} + +const autoMessages = () => { + //AUTOCLOSE MESSAGE + messages.add(new api.ODMessage("openticket:autoclose-message")) + messages.get("openticket:autoclose-message").workers.add( + new api.ODWorker("openticket:autoclose-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket} = params + instance.addEmbed(await embeds.getSafe("openticket:autoclose-message").build(source,{guild,channel,user,ticket})) + if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("openticket:reopen-ticket").build("autoclose-message",{guild,channel,user,ticket})) + if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("openticket:delete-ticket").build("autoclose-message",{guild,channel,user,ticket})) + }) + ) + + //AUTODELETE MESSAGE + messages.add(new api.ODMessage("openticket:autodelete-message")) + messages.get("openticket:autodelete-message").workers.add( + new api.ODWorker("openticket:autodelete-message",0,async (instance,params,source) => { + const {guild,channel,user,ticket} = params + instance.addEmbed(await embeds.getSafe("openticket:autodelete-message").build(source,{guild,channel,user,ticket})) + }) + ) + + //AUTOCLOSE ENABLE + messages.add(new api.ODMessage("openticket:autoclose-enable")) + messages.get("openticket:autoclose-enable").workers.add( + new api.ODWorker("openticket:autoclose-enable",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason,time} = params + instance.addEmbed(await embeds.getSafe("openticket:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time})) + }) + ) + + //AUTODELETE ENABLE + messages.add(new api.ODMessage("openticket:autodelete-enable")) + messages.get("openticket:autodelete-enable").workers.add( + new api.ODWorker("openticket:autodelete-enable",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason,time} = params + instance.addEmbed(await embeds.getSafe("openticket:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time})) + }) + ) + + //AUTOCLOSE DISABLE + messages.add(new api.ODMessage("openticket:autoclose-disable")) + messages.get("openticket:autoclose-disable").workers.add( + new api.ODWorker("openticket:autoclose-disable",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:autoclose-disable").build(source,{guild,channel,user,ticket,reason})) + }) + ) + + //AUTODELETE DISABLE + messages.add(new api.ODMessage("openticket:autodelete-disable")) + messages.get("openticket:autodelete-disable").workers.add( + new api.ODWorker("openticket:autodelete-disable",0,async (instance,params,source) => { + const {guild,channel,user,ticket,reason} = params + instance.addEmbed(await embeds.getSafe("openticket:autodelete-disable").build(source,{guild,channel,user,ticket,reason})) + }) + ) +} \ No newline at end of file diff --git a/src/builders/modals.ts b/src/builders/modals.ts new file mode 100644 index 0000000..6412467 --- /dev/null +++ b/src/builders/modals.ts @@ -0,0 +1,173 @@ +/////////////////////////////////////// +//MODAL BUILDERS +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const modals = openticket.builders.modals +const lang = openticket.languages + +export const registerAllModals = async () => { + ticketModals() +} +const ticketModals = () => { + //TICKET QUESTIONS + modals.add(new api.ODModal("openticket:ticket-questions")) + modals.get("openticket:ticket-questions").workers.add( + new api.ODWorker("openticket:ticket-questions",0,async (instance,params,source) => { + const {option} = params + + instance.setCustomId("od:ticket-questions_"+option.id.value+"_"+source) + instance.setTitle(option.exists("openticket:name") ? option.get("openticket:name").value : option.id.value) + const questionIds = option.get("openticket:questions").value + questionIds.forEach((id) => { + const question = openticket.questions.get(id) + if (!question) return + if (question instanceof api.ODShortQuestion) instance.addQuestion({ + customId:question.id.value, + label:question.get("openticket:name").value, + style:"short", + required:question.get("openticket:required").value, + placeholder:(question.get("openticket:placeholder").value) ? question.get("openticket:placeholder").value : undefined, + minLength:(question.get("openticket:length-enabled").value) ? question.get("openticket:length-min").value : undefined, + maxLength:(question.get("openticket:length-enabled").value) ? question.get("openticket:length-max").value : undefined + }) + else if (question instanceof api.ODParagraphQuestion) instance.addQuestion({ + customId:question.id.value, + label:question.get("openticket:name").value, + style:"paragraph", + required:question.get("openticket:required").value, + placeholder:(question.get("openticket:placeholder").value) ? question.get("openticket:placeholder").value : undefined, + minLength:(question.get("openticket:length-enabled").value) ? question.get("openticket:length-min").value : undefined, + maxLength:(question.get("openticket:length-enabled").value) ? question.get("openticket:length-max").value : undefined + }) + }) + }) + ) + + //CLOSE TICKET REASON + modals.add(new api.ODModal("openticket:close-ticket-reason")) + modals.get("openticket:close-ticket-reason").workers.add( + new api.ODWorker("openticket:close-ticket-reason",0,async (instance,params,source) => { + const {ticket} = params + + instance.setCustomId("od:close-ticket-reason_"+ticket.id.value+"_"+source) + instance.setTitle(lang.getTranslation("actions.buttons.close")) + instance.addQuestion({ + customId:"reason", + label:lang.getTranslation("params.uppercase.reason"), + style:"paragraph", + required:true, + placeholder:lang.getTranslation("actions.modal.closePlaceholder") + }) + }) + ) + + //REOPEN TICKET REASON + modals.add(new api.ODModal("openticket:reopen-ticket-reason")) + modals.get("openticket:reopen-ticket-reason").workers.add( + new api.ODWorker("openticket:reopen-ticket-reason",0,async (instance,params,source) => { + const {ticket} = params + + instance.setCustomId("od:reopen-ticket-reason_"+ticket.id.value+"_"+source) + instance.setTitle(lang.getTranslation("actions.buttons.reopen")) + instance.addQuestion({ + customId:"reason", + label:lang.getTranslation("params.uppercase.reason"), + style:"paragraph", + required:true, + placeholder:lang.getTranslation("actions.modal.reopenPlaceholder") + }) + }) + ) + + //DELETE TICKET REASON + modals.add(new api.ODModal("openticket:delete-ticket-reason")) + modals.get("openticket:delete-ticket-reason").workers.add( + new api.ODWorker("openticket:delete-ticket-reason",0,async (instance,params,source) => { + const {ticket} = params + + instance.setCustomId("od:delete-ticket-reason_"+ticket.id.value+"_"+source) + instance.setTitle(lang.getTranslation("actions.buttons.delete")) + instance.addQuestion({ + customId:"reason", + label:lang.getTranslation("params.uppercase.reason"), + style:"paragraph", + required:true, + placeholder:lang.getTranslation("actions.modal.deletePlaceholder") + }) + }) + ) + + //CLAIM TICKET REASON + modals.add(new api.ODModal("openticket:claim-ticket-reason")) + modals.get("openticket:claim-ticket-reason").workers.add( + new api.ODWorker("openticket:claim-ticket-reason",0,async (instance,params,source) => { + const {ticket} = params + + instance.setCustomId("od:claim-ticket-reason_"+ticket.id.value+"_"+source) + instance.setTitle(lang.getTranslation("actions.buttons.claim")) + instance.addQuestion({ + customId:"reason", + label:lang.getTranslation("params.uppercase.reason"), + style:"paragraph", + required:true, + placeholder:lang.getTranslation("actions.modal.claimPlaceholder") + }) + }) + ) + + //UNCLAIM TICKET REASON + modals.add(new api.ODModal("openticket:unclaim-ticket-reason")) + modals.get("openticket:unclaim-ticket-reason").workers.add( + new api.ODWorker("openticket:unclaim-ticket-reason",0,async (instance,params,source) => { + const {ticket} = params + + instance.setCustomId("od:unclaim-ticket-reason_"+ticket.id.value+"_"+source) + instance.setTitle(lang.getTranslation("actions.buttons.unclaim")) + instance.addQuestion({ + customId:"reason", + label:lang.getTranslation("params.uppercase.reason"), + style:"paragraph", + required:true, + placeholder:lang.getTranslation("actions.modal.unclaimPlaceholder") + }) + }) + ) + + //PIN TICKET REASON + modals.add(new api.ODModal("openticket:pin-ticket-reason")) + modals.get("openticket:pin-ticket-reason").workers.add( + new api.ODWorker("openticket:pin-ticket-reason",0,async (instance,params,source) => { + const {ticket} = params + + instance.setCustomId("od:pin-ticket-reason_"+ticket.id.value+"_"+source) + instance.setTitle(lang.getTranslation("actions.buttons.pin")) + instance.addQuestion({ + customId:"reason", + label:lang.getTranslation("params.uppercase.reason"), + style:"paragraph", + required:true, + placeholder:lang.getTranslation("actions.modal.pinPlaceholder") + }) + }) + ) + + //UNPIN TICKET REASON + modals.add(new api.ODModal("openticket:unpin-ticket-reason")) + modals.get("openticket:unpin-ticket-reason").workers.add( + new api.ODWorker("openticket:unpin-ticket-reason",0,async (instance,params,source) => { + const {ticket} = params + + instance.setCustomId("od:unpin-ticket-reason_"+ticket.id.value+"_"+source) + instance.setTitle(lang.getTranslation("actions.buttons.unpin")) + instance.addQuestion({ + customId:"reason", + label:lang.getTranslation("params.uppercase.reason"), + style:"paragraph", + required:true, + placeholder:lang.getTranslation("actions.modal.unpinPlaceholder") + }) + }) + ) +} \ No newline at end of file diff --git a/src/commands/add.ts b/src/commands/add.ts new file mode 100644 index 0000000..4ad48b9 --- /dev/null +++ b/src/commands/add.ts @@ -0,0 +1,87 @@ +/////////////////////////////////////// +//ADD COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //ADD COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:add",generalConfig.data.prefix,"add")) + openticket.responders.commands.get("openticket:add").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.add + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:add",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const data = instance.options.getUser("user",true) + const reason = instance.options.getString("reason",false) + + //return when user already added to ticket + const participants = await openticket.tickets.getAllTicketParticipants(ticket) + if (!participants || participants.find((p) => p.user.id == data.id)){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"This user is already able to access the ticket!",layout:"simple"})) + return cancel() + } + + //start adding user to ticket + await instance.defer(false) + await openticket.actions.get("openticket:add-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data}) + await instance.reply(await openticket.builders.messages.getSafe("openticket:add-message").build(source,{guild,channel,user,ticket,reason,data})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'add' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/commands/autoclose.ts b/src/commands/autoclose.ts new file mode 100644 index 0000000..e731e96 --- /dev/null +++ b/src/commands/autoclose.ts @@ -0,0 +1,98 @@ +/////////////////////////////////////// +//AUTOCLOSE COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //AUTOCLOSE COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:autoclose",generalConfig.data.prefix,/^autoclose/)) + openticket.responders.commands.get("openticket:autoclose").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.autoclose + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:autoclose",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return + } + //return when already closed + if (ticket.get("openticket:closed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is already closed!",layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const scope = instance.options.getSubCommand() + if (!scope || (scope != "disable" && scope != "enable")) return + + if (scope == "disable"){ + const reason = instance.options.getString("reason",false) + ticket.get("openticket:autoclose-enabled").value = false + ticket.get("openticket:autoclose-hours").value = 0 + await instance.reply(await openticket.builders.messages.getSafe("openticket:autoclose-disable").build(source,{guild,channel,user,ticket,reason})) + + }else if (scope == "enable"){ + const time = instance.options.getNumber("time",true) + const reason = instance.options.getString("reason",false) + ticket.get("openticket:autoclose-enabled").value = true + ticket.get("openticket:autoclose-hours").value = time + await instance.reply(await openticket.builders.messages.getSafe("openticket:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time})) + } + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + const scope = instance.options.getSubCommand() + const reason = instance.options.getString("reason",false) + openticket.log(instance.user.displayName+" used the 'autoclose "+scope+"' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source}, + {key:"reason",value:reason ?? "/"}, + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/commands/autodelete.ts b/src/commands/autodelete.ts new file mode 100644 index 0000000..4744804 --- /dev/null +++ b/src/commands/autodelete.ts @@ -0,0 +1,93 @@ +/////////////////////////////////////// +//AUTODELETE COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //AUTODELETE COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:autodelete",generalConfig.data.prefix,/^autodelete/)) + openticket.responders.commands.get("openticket:autodelete").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.autodelete + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:autodelete",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const scope = instance.options.getSubCommand() + if (!scope || (scope != "disable" && scope != "enable")) return + + if (scope == "disable"){ + const reason = instance.options.getString("reason",false) + ticket.get("openticket:autodelete-enabled").value = false + ticket.get("openticket:autodelete-days").value = 0 + await instance.reply(await openticket.builders.messages.getSafe("openticket:autodelete-disable").build(source,{guild,channel,user,ticket,reason})) + + }else if (scope == "enable"){ + const time = instance.options.getNumber("time",true) + const reason = instance.options.getString("reason",false) + ticket.get("openticket:autodelete-enabled").value = true + ticket.get("openticket:autodelete-days").value = time + await instance.reply(await openticket.builders.messages.getSafe("openticket:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time})) + } + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + const scope = instance.options.getSubCommand() + const reason = instance.options.getString("reason",false) + openticket.log(instance.user.displayName+" used the 'autodelete "+scope+"' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source}, + {key:"reason",value:reason ?? "/"}, + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/commands/blacklist.ts b/src/commands/blacklist.ts new file mode 100644 index 0000000..f0d3a6e --- /dev/null +++ b/src/commands/blacklist.ts @@ -0,0 +1,127 @@ +/////////////////////////////////////// +//BLACKLIST COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //BLACKLIST COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:blacklist",generalConfig.data.prefix,/^blacklist/)) + openticket.responders.commands.get("openticket:blacklist").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.blacklist + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:blacklist",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + return cancel() + } + const scope = instance.options.getSubCommand() + if (!scope || (scope != "add" && scope != "get" && scope != "remove" && scope != "view")) return + + if (scope == "view"){ + await instance.reply(await openticket.builders.messages.getSafe("openticket:blacklist-view").build(source,{guild,channel,user})) + + }else if (scope == "get"){ + const data = instance.options.getUser("user",true) + await instance.reply(await openticket.builders.messages.getSafe("openticket:blacklist-get").build(source,{guild,channel,user,data})) + + }else if (scope == "add"){ + const data = instance.options.getUser("user",true) + const reason = instance.options.getString("reason",false) + + openticket.blacklist.add(new api.ODBlacklist(data.id,reason),true) + openticket.log(instance.user.displayName+" added "+data.displayName+" to blacklist!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"method",value:source}, + {key:"reason",value:reason ?? "/"} + ]) + + //manage stats + openticket.stats.get("openticket:global").setStat("openticket:users-blacklisted",1,"increase") + openticket.stats.get("openticket:user").setStat("openticket:users-blacklisted",user.id,1,"increase") + + await instance.reply(await openticket.builders.messages.getSafe("openticket:blacklist-add").build(source,{guild,channel,user,data,reason})) + + }else if (scope == "remove"){ + const data = instance.options.getUser("user",true) + const reason = instance.options.getString("reason",false) + + openticket.blacklist.remove(data.id) + openticket.log(instance.user.displayName+" removed "+data.displayName+" from blacklist!","info",[ + {key:"user",value:user.username}, + {key:"userid",value:user.id,hidden:true}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"method",value:source}, + {key:"reason",value:reason ?? "/"} + ]) + + await instance.reply(await openticket.builders.messages.getSafe("openticket:blacklist-remove").build(source,{guild,channel,user,data,reason})) + } + }), + new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild) return + + const scope = instance.options.getSubCommand() + if (!scope || (scope != "add" && scope != "remove")) return + + const data = instance.options.getUser("user",true) + const reason = instance.options.getString("reason",false) + + //to logs + if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.blacklisting.logs){ + const logChannel = openticket.posts.get("openticket:logs") + if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:blacklist-logs").build(source,{guild,channel,user,mode:scope,data,reason})) + } + + //to dm + if (generalConfig.data.system.messages.blacklisting.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:blacklist-dm").build(source,{guild,channel,user,mode:scope,data,reason})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + const scope = instance.options.getSubCommand() + openticket.log(instance.user.displayName+" used the 'blacklist "+scope+"' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/commands/claim.ts b/src/commands/claim.ts new file mode 100644 index 0000000..84316f7 --- /dev/null +++ b/src/commands/claim.ts @@ -0,0 +1,138 @@ +/////////////////////////////////////// +//CLAIM COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //CLAIM COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:claim",generalConfig.data.prefix,"claim")) + openticket.responders.commands.get("openticket:claim").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.claim + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:claim",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when already claimed + if (ticket.get("openticket:claimed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is already claimed!",layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const claimUser = instance.options.getUser("user",false) ?? user + const reason = instance.options.getString("reason",false) + + //start claiming ticket + await instance.defer(false) + await openticket.actions.get("openticket:claim-ticket").run(source,{guild,channel,user:claimUser,ticket,reason,sendMessage:false}) + await instance.reply(await openticket.builders.messages.getSafe("openticket:claim-message").build(source,{guild,channel,user:claimUser,ticket,reason})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'claim' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerButtonResponders = async () => { + //CLAIM TICKET BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:claim-ticket",/^od:claim-ticket/)) + openticket.responders.buttons.get("openticket:claim-ticket").workers.add( + new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source,cancel) => { + const originalSource = instance.interaction.customId.split("_")[1] + if (originalSource != "ticket-message" && originalSource != "unclaim-message") return + + if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:claim-ticket-ticket-message").activate(instance) + else await openticket.verifybars.get("openticket:claim-ticket-unclaim-message").activate(instance) + }) + ) +} + +export const registerModalResponders = async () => { + //CLAIM WITH REASON MODAL RESPONDER + openticket.responders.modals.add(new api.ODModalResponder("openticket:claim-ticket-reason",/^od:claim-ticket-reason_/)) + openticket.responders.modals.get("openticket:claim-ticket-reason").workers.add([ + new api.ODWorker("openticket:claim-ticket-reason",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!channel) return + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + return cancel() + } + const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return + } + + const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"unclaim-message"|"other") + const reason = instance.values.getTextField("reason",true) + + //claim with reason + if (originalSource == "ticket-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }else if (originalSource == "unclaim-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:claim-message").build("other",{guild,channel,user,ticket,reason})) + }else if (originalSource == "other"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + } + + }) + ]) +} \ No newline at end of file diff --git a/src/commands/clear.ts b/src/commands/clear.ts new file mode 100644 index 0000000..61a0e7f --- /dev/null +++ b/src/commands/clear.ts @@ -0,0 +1,122 @@ +/////////////////////////////////////// +//CLEAR COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //CLEAR COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:clear",generalConfig.data.prefix,"clear")) + openticket.responders.commands.get("openticket:clear").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.clear + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + //only allow global admins (ticket admins aren't allowed to clear tickets) + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild,{allowChannelUserScope:false,allowChannelRoleScope:false}))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:clear",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + + const tempFilter = instance.options.getString("filter",false) + const filter = (tempFilter) ? tempFilter.toLowerCase() as api.ODTicketClearFilter : "all" + const list: string[] = [] + const ticketList = openticket.tickets.getAll().filter((ticket) => { + if (filter == "all") return true + else if (filter == "open" && ticket.get("openticket:open").value) return true + else if (filter == "closed" && ticket.get("openticket:closed").value) return true + else if (filter == "claimed" && ticket.get("openticket:claimed").value) return true + else if (filter == "pinned" && ticket.get("openticket:pinned").value) return true + else if (filter == "unclaimed" && !ticket.get("openticket:claimed").value) return true + else if (filter == "unpinned" && !ticket.get("openticket:pinned").value) return true + else if (filter == "autoclosed" && ticket.get("openticket:closed").value) return true + else return false + }) + for (const ticket of ticketList){ + const ticketChannel = await openticket.tickets.getTicketChannel(ticket) + if (ticketChannel) list.push("#"+ticketChannel.name) + } + + //reply with clear verify + await instance.defer(true) + await instance.reply(await openticket.builders.messages.getSafe("openticket:clear-verify-message").build(source,{guild,channel,user,filter,list})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'clear' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerButtonResponders = async () => { + //CLEAR CONTINUE BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:clear-continue",/^od:clear-continue_/)) + openticket.responders.buttons.get("openticket:clear-continue").workers.add( + new api.ODWorker("openticket:clear-continue",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild || channel.isDMBased()) return + const originalSource = instance.interaction.customId.split("_")[1] + if (originalSource != "slash" && originalSource != "text" && originalSource != "other") return + const filter = instance.interaction.customId.split("_")[2] as api.ODTicketClearFilter + + //start ticket clear + instance.defer("update",true) + const list: string[] = [] + const ticketList = openticket.tickets.getAll().filter((ticket) => { + if (filter == "all") return true + else if (filter == "open" && ticket.get("openticket:open").value) return true + else if (filter == "closed" && ticket.get("openticket:closed").value) return true + else if (filter == "claimed" && ticket.get("openticket:claimed").value) return true + else if (filter == "pinned" && ticket.get("openticket:pinned").value) return true + else if (filter == "unclaimed" && !ticket.get("openticket:claimed").value) return true + else if (filter == "unpinned" && !ticket.get("openticket:pinned").value) return true + else if (filter == "autoclosed" && ticket.get("openticket:closed").value) return true + else return false + }) + for (const ticket of ticketList){ + const ticketChannel = await openticket.tickets.getTicketChannel(ticket) + if (ticketChannel) list.push("#"+ticketChannel.name) + } + + await openticket.actions.get("openticket:clear-tickets").run(originalSource,{guild,channel,user,filter,list:ticketList}) + await instance.update(await openticket.builders.messages.getSafe("openticket:clear-message").build(originalSource,{guild,channel,user,filter,list})) + }) + ) +} \ No newline at end of file diff --git a/src/commands/close.ts b/src/commands/close.ts new file mode 100644 index 0000000..dc39dc6 --- /dev/null +++ b/src/commands/close.ts @@ -0,0 +1,137 @@ +/////////////////////////////////////// +//CLOSE COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //CLOSE COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:close",generalConfig.data.prefix,"close")) + openticket.responders.commands.get("openticket:close").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.close + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:close",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when already closed + if (ticket.get("openticket:closed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is already closed!",layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const reason = instance.options.getString("reason",false) + + //start closing ticket + await instance.defer(false) + await openticket.actions.get("openticket:close-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await openticket.builders.messages.getSafe("openticket:close-message").build(source,{guild,channel,user,ticket,reason})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'close' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerButtonResponders = async () => { + //CLOSE TICKET BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:close-ticket",/^od:close-ticket_/)) + openticket.responders.buttons.get("openticket:close-ticket").workers.add( + new api.ODWorker("openticket:close-ticket",0,async (instance,params,source,cancel) => { + const originalSource = instance.interaction.customId.split("_")[1] + if (originalSource != "ticket-message" && originalSource != "reopen-message") return + + if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:close-ticket-ticket-message").activate(instance) + else await openticket.verifybars.get("openticket:close-ticket-reopen-message").activate(instance) + }) + ) +} + +export const registerModalResponders = async () => { + //CLOSE WITH REASON MODAL RESPONDER + openticket.responders.modals.add(new api.ODModalResponder("openticket:close-ticket-reason",/^od:close-ticket-reason_/)) + openticket.responders.modals.get("openticket:close-ticket-reason").workers.add([ + new api.ODWorker("openticket:close-ticket-reason",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!channel) return + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + return cancel() + } + const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return + } + + const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"reopen-message"|"other") + const reason = instance.values.getTextField("reason",true) + + //close with reason + if (originalSource == "ticket-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }else if (originalSource == "reopen-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + }else if (originalSource == "other"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + } + + }) + ]) +} \ No newline at end of file diff --git a/src/commands/delete.ts b/src/commands/delete.ts new file mode 100644 index 0000000..e80f677 --- /dev/null +++ b/src/commands/delete.ts @@ -0,0 +1,149 @@ +/////////////////////////////////////// +//DELETE COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //DELETE COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:delete",generalConfig.data.prefix,"delete")) + openticket.responders.commands.get("openticket:delete").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.delete + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:delete",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const reason = instance.options.getString("reason",false) + const withoutTranscript = instance.options.getBoolean("notranscript",false) ?? false + + //start deleting ticket + await instance.defer(false) + await instance.reply(await openticket.builders.messages.getSafe("openticket:delete-message").build(source,{guild,channel,user,ticket,reason})) + await openticket.actions.get("openticket:delete-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript}) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'delete' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerButtonResponders = async () => { + //DELETE TICKET BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:delete-ticket",/^od:delete-ticket/)) + openticket.responders.buttons.get("openticket:delete-ticket").workers.add( + new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + const originalSource = instance.interaction.customId.split("_")[1] + if (originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "autoclose-message") return + + if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:delete-ticket-ticket-message").activate(instance) + else if (originalSource == "close-message") await openticket.verifybars.get("openticket:delete-ticket-close-message").activate(instance) + else if (originalSource == "reopen-message") await openticket.verifybars.get("openticket:delete-ticket-reopen-message").activate(instance) + else if (originalSource == "autoclose-message") await openticket.verifybars.get("openticket:delete-ticket-autoclose-message").activate(instance) + }) + ) +} + +export const registerModalResponders = async () => { + //REOPEN WITH REASON MODAL RESPONDER + openticket.responders.modals.add(new api.ODModalResponder("openticket:delete-ticket-reason",/^od:delete-ticket-reason_/)) + openticket.responders.modals.get("openticket:delete-ticket-reason").workers.add([ + new api.ODWorker("openticket:delete-ticket-reason",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!channel) return + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + return cancel() + } + const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return + } + + const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"other") + const reason = instance.values.getTextField("reason",true) + + //delete with reason + if (originalSource == "ticket-message"){ + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) + //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable + ticket.get("openticket:for-deletion").value = true + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }else if (originalSource == "close-message"){ + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) + }else if (originalSource == "reopen-message"){ + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) + }else if (originalSource == "autoclose-message"){ + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) + }else if (originalSource == "other"){ + await instance.defer("update",false) + //don't await DELETE action => else it will update the message after the channel has been deleted + openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) + } + }) + ]) +} \ No newline at end of file diff --git a/src/commands/help.ts b/src/commands/help.ts new file mode 100644 index 0000000..36b7ec1 --- /dev/null +++ b/src/commands/help.ts @@ -0,0 +1,112 @@ +/////////////////////////////////////// +//HELP COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //HELP COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:help",generalConfig.data.prefix,"help")) + openticket.responders.commands.get("openticket:help").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.help + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:help",0,async (instance,params,source,cancel) => { + const preferSlashOverText = generalConfig.data.system.preferSlashOverText + + let mode: "slash"|"text" + if (generalConfig.data.slashCommands && generalConfig.data.textCommands){ + mode = (preferSlashOverText) ? "slash" : "text" + + }else if (!generalConfig.data.slashCommands) mode = "text" + else mode = "slash" + + await instance.reply(await openticket.builders.messages.getSafe("openticket:help-menu").build(source,{mode,page:0})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'help' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerButtonResponders = async () => { + //HELP MENU SWITCH BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-switch",/^od:help-menu-switch_(slash|text)/)) + openticket.responders.buttons.get("openticket:help-menu-switch").workers.add( + new api.ODWorker("openticket:update-help-menu",0,async (instance,params,source,cancel) => { + const mode = instance.interaction.customId.split("_")[1] as "slash"|"text" + const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/) + const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0 + + const newMode = (mode == "slash") ? "text" : "slash" + + const msg = await openticket.builders.messages.getSafe("openticket:help-menu").build("button",{mode:newMode,page:currentPage}) + await instance.update(msg) + }) + ) + + //HELP MENU PREVIOUS BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-previous",/^od:help-menu-previous/)) + openticket.responders.buttons.get("openticket:help-menu-previous").workers.add( + new api.ODWorker("openticket:update-help-menu",0,async (instance,params,source,cancel) => { + const switchButton = instance.getMessageComponent("button",/^od:help-menu-switch_(slash|text)/) + const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/) + const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0 + const currentMode = (switchButton && switchButton.customId) ? switchButton.customId.split("_")[1] as "text"|"slash" : "slash" + + const msg = await openticket.builders.messages.getSafe("openticket:help-menu").build("button",{mode:currentMode,page:currentPage-1}) + await instance.update(msg) + }) + ) + + //HELP MENU NEXT BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-next",/^od:help-menu-next/)) + openticket.responders.buttons.get("openticket:help-menu-next").workers.add( + new api.ODWorker("openticket:update-help-menu",0,async (instance,params,source,cancel) => { + const switchButton = instance.getMessageComponent("button",/^od:help-menu-switch_(slash|text)/) + const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/) + const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0 + const currentMode = (switchButton && switchButton.customId) ? switchButton.customId.split("_")[1] as "text"|"slash" : "slash" + + const msg = await openticket.builders.messages.getSafe("openticket:help-menu").build("button",{mode:currentMode,page:currentPage+1}) + await instance.update(msg) + }) + ) +} \ No newline at end of file diff --git a/src/commands/move.ts b/src/commands/move.ts new file mode 100644 index 0000000..a33cb55 --- /dev/null +++ b/src/commands/move.ts @@ -0,0 +1,92 @@ +/////////////////////////////////////// +//MOVE COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //MOVE COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:move",generalConfig.data.prefix,"move")) + openticket.responders.commands.get("openticket:move").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.move + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:move",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const id = instance.options.getString("id",true) + const reason = instance.options.getString("reason",false) + + const option = openticket.options.get(id) + //return if unknown option + if (!option || !(option instanceof api.ODTicketOption)){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Unknown Option",layout:"simple"})) + return cancel() + } + //return if option is the same + if (ticket.option.id.value == option.id.value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"This ticket is already the same as the chosen option!",layout:"simple"})) + return cancel() + } + + //start moving ticket + await instance.defer(false) + await openticket.actions.get("openticket:move-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:option}) + await instance.reply(await openticket.builders.messages.getSafe("openticket:move-message").build(source,{guild,channel,user,ticket,reason,data:option})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'move' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/commands/panel.ts b/src/commands/panel.ts new file mode 100644 index 0000000..72cf050 --- /dev/null +++ b/src/commands/panel.ts @@ -0,0 +1,82 @@ +/////////////////////////////////////// +//STATS COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //PANEL COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:panel",generalConfig.data.prefix,/^panel/)) + openticket.responders.commands.get("openticket:panel").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.panel + + //command is disabled + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:panel",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + return cancel() + } + + const id = instance.options.getString("id",true) + const panel = openticket.panels.get(id) + + if (!panel){ + //invalid panel + instance.reply(await openticket.builders.messages.getSafe("openticket:error-panel-unknown").build(source,{guild,channel,user})) + return cancel() + } + + await instance.reply(await openticket.builders.messages.getSafe("openticket:panel-ready").build(source,{guild,channel,user,panel})) + const panelMessage = await instance.channel.send((await openticket.builders.messages.getSafe("openticket:panel").build(source,{guild,channel,user,panel})).message) + + //add panel to database on auto-update + if (instance.options.getBoolean("auto-update",false)){ + const globalDatabase = openticket.databases.get("openticket:global") + globalDatabase.set("openticket:panel-update",panelMessage.channel.id+"_"+panelMessage.id,panel.id.value) + } + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'panel' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/commands/pin.ts b/src/commands/pin.ts new file mode 100644 index 0000000..64d5c2b --- /dev/null +++ b/src/commands/pin.ts @@ -0,0 +1,137 @@ +/////////////////////////////////////// +//PIN COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //PIN COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:pin",generalConfig.data.prefix,"pin")) + openticket.responders.commands.get("openticket:pin").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.pin + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:pin",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when already pinned + if (ticket.get("openticket:pinned").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is already pinned!",layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const reason = instance.options.getString("reason",false) + + //start pinning ticket + await instance.defer(false) + await openticket.actions.get("openticket:pin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await openticket.builders.messages.getSafe("openticket:pin-message").build(source,{guild,channel,user,ticket,reason})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'pin' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerButtonResponders = async () => { + //PIN TICKET BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:pin-ticket",/^od:pin-ticket/)) + openticket.responders.buttons.get("openticket:pin-ticket").workers.add( + new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source,cancel) => { + const originalSource = instance.interaction.customId.split("_")[1] + if (originalSource != "ticket-message" && originalSource != "unpin-message") return + + if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:pin-ticket-ticket-message").activate(instance) + else await openticket.verifybars.get("openticket:pin-ticket-unpin-message").activate(instance) + }) + ) +} + +export const registerModalResponders = async () => { + //PIN WITH REASON MODAL RESPONDER + openticket.responders.modals.add(new api.ODModalResponder("openticket:pin-ticket-reason",/^od:pin-ticket-reason_/)) + openticket.responders.modals.get("openticket:pin-ticket-reason").workers.add([ + new api.ODWorker("openticket:pin-ticket-reason",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!channel) return + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + return cancel() + } + const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return + } + + const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"unpin-message"|"other") + const reason = instance.values.getTextField("reason",true) + + //pin with reason + if (originalSource == "ticket-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }else if (originalSource == "unpin-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:pin-message").build("other",{guild,channel,user,ticket,reason})) + }else if (originalSource == "other"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + } + + }) + ]) +} \ No newline at end of file diff --git a/src/commands/remove.ts b/src/commands/remove.ts new file mode 100644 index 0000000..f984372 --- /dev/null +++ b/src/commands/remove.ts @@ -0,0 +1,87 @@ +/////////////////////////////////////// +//REMOVE COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //REMOVE COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:remove",generalConfig.data.prefix,"remove")) + openticket.responders.commands.get("openticket:remove").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.remove + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:remove",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const data = instance.options.getUser("user",true) + const reason = instance.options.getString("reason",false) + + //return when user is not a participant of the ticket (admins & creator can't be removed) + const participants = await openticket.tickets.getAllTicketParticipants(ticket) + if (!participants || !participants.find((p) => p.user.id == data.id && p.role == "participant")){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Unable to remove this user from the ticket!",layout:"simple"})) + return cancel() + } + + //start removing user from ticket + await instance.defer(false) + await openticket.actions.get("openticket:remove-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data}) + await instance.reply(await openticket.builders.messages.getSafe("openticket:remove-message").build(source,{guild,channel,user,ticket,reason,data})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'remove' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/commands/rename.ts b/src/commands/rename.ts new file mode 100644 index 0000000..e5fafb5 --- /dev/null +++ b/src/commands/rename.ts @@ -0,0 +1,80 @@ +/////////////////////////////////////// +//RENAME COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //RENAME COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:rename",generalConfig.data.prefix,"rename")) + openticket.responders.commands.get("openticket:rename").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.rename + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:rename",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const name = instance.options.getString("name",true) + const reason = instance.options.getString("reason",false) + + //start renaming ticket + await instance.defer(false) + await openticket.actions.get("openticket:rename-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:name}) + await instance.reply(await openticket.builders.messages.getSafe("openticket:rename-message").build(source,{guild,channel,user,ticket,reason,data:name})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'rename' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/commands/reopen.ts b/src/commands/reopen.ts new file mode 100644 index 0000000..82ccb36 --- /dev/null +++ b/src/commands/reopen.ts @@ -0,0 +1,142 @@ +/////////////////////////////////////// +//REOPEN COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //REOPEN COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:reopen",generalConfig.data.prefix,"reopen")) + openticket.responders.commands.get("openticket:reopen").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.reopen + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:reopen",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when not closed + if (!ticket.get("openticket:closed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is not closed yet!",layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const reason = instance.options.getString("reason",false) + + //start reopening ticket + await instance.defer(false) + await openticket.actions.get("openticket:reopen-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await openticket.builders.messages.getSafe("openticket:reopen-message").build(source,{guild,channel,user,ticket,reason})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'reopen' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerButtonResponders = async () => { + //REOPEN TICKET BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:reopen-ticket",/^od:reopen-ticket/)) + openticket.responders.buttons.get("openticket:reopen-ticket").workers.add( + new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { + const originalSource = instance.interaction.customId.split("_")[1] + if (originalSource != "ticket-message" && originalSource != "close-message" && originalSource != "autoclose-message") return + + if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:reopen-ticket-ticket-message").activate(instance) + else if (originalSource == "close-message") await openticket.verifybars.get("openticket:reopen-ticket-close-message").activate(instance) + else await openticket.verifybars.get("openticket:reopen-ticket-autoclose-message").activate(instance) + }) + ) +} + +export const registerModalResponders = async () => { + //REOPEN WITH REASON MODAL RESPONDER + openticket.responders.modals.add(new api.ODModalResponder("openticket:reopen-ticket-reason",/^od:reopen-ticket-reason_/)) + openticket.responders.modals.get("openticket:reopen-ticket-reason").workers.add([ + new api.ODWorker("openticket:reopen-ticket-reason",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!channel) return + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + return cancel() + } + const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return + } + + const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"close-message"|"autoclose-message"|"other") + const reason = instance.values.getTextField("reason",true) + + //reopen with reason + if (originalSource == "ticket-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }else if (originalSource == "close-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + }else if (originalSource == "autoclose-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + }else if (originalSource == "other"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + } + + }) + ]) +} \ No newline at end of file diff --git a/src/commands/role.ts b/src/commands/role.ts new file mode 100644 index 0000000..88ea4f6 --- /dev/null +++ b/src/commands/role.ts @@ -0,0 +1,41 @@ +/////////////////////////////////////// +//ROLE BUTTON (not command) +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerButtonResponders = async () => { + //ROLE OPTION BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:role-option",/^od:role-option_/)) + openticket.responders.buttons.get("openticket:role-option").workers.add( + new api.ODWorker("openticket:role-option",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + return cancel() + } + + //get option + const optionId = instance.interaction.customId.split("_")[2] + const option = openticket.options.get(optionId) + if (!option || !(option instanceof api.ODRoleOption)){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + return cancel() + } + + //reaction role + await instance.defer("reply",true) + const res = await openticket.actions.get("openticket:reaction-role").run("panel-button",{guild,user,option,overwriteMode:null}) + if (!res.result || !res.role){ + //error + await instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive role update data from worker!",layout:"advanced"})) + return cancel() + } + if (generalConfig.data.system.replyOnReactionRole) await instance.reply(await openticket.builders.messages.getSafe("openticket:reaction-role").build("panel-button",{guild,user,role:res.role,result:res.result})) + }) + ) +} \ No newline at end of file diff --git a/src/commands/stats.ts b/src/commands/stats.ts new file mode 100644 index 0000000..1c35760 --- /dev/null +++ b/src/commands/stats.ts @@ -0,0 +1,107 @@ +/////////////////////////////////////// +//STATS COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //STATS COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:stats",generalConfig.data.prefix,/^stats/)) + openticket.responders.commands.get("openticket:stats").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.stats + + //command is disabled + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + } + + //reset subcommand is owner/developer only + if (instance.options.getSubCommand() == "reset"){ + if (!openticket.permissions.hasPermissions("owner",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]})) + return cancel() + }else return + } + + //permissions for normal scopes + if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:stats",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + return cancel() + } + const scope = instance.options.getSubCommand() + if (!scope || (scope != "global" && scope != "ticket" && scope != "user" && scope != "reset")) return + + if (scope == "global"){ + await instance.reply(await openticket.builders.messages.getSafe("openticket:stats-global").build(source,{guild,channel,user})) + + }else if (scope == "ticket"){ + const id = instance.options.getChannel("ticket",false)?.id ?? channel.id + const ticket = openticket.tickets.get(id) + + if (ticket) await instance.reply(await openticket.builders.messages.getSafe("openticket:stats-ticket").build(source,{guild,channel,user,scopeData:ticket})) + else await instance.reply(await openticket.builders.messages.getSafe("openticket:stats-ticket-unknown").build(source,{guild,channel,user,id})) + + }else if (scope == "user"){ + const statsUser = instance.options.getUser("user",false) ?? user + await instance.reply(await openticket.builders.messages.getSafe("openticket:stats-user").build(source,{guild,channel,user,scopeData:statsUser})) + + }else if (scope == "reset"){ + const reason = instance.options.getString("reason",false) + openticket.stats.reset() + await instance.reply(await openticket.builders.messages.getSafe("openticket:stats-reset").build(source,{guild,channel,user,reason})) + + } + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + const scope = instance.options.getSubCommand() + let data: string + if (scope == "ticket"){ + data = instance.options.getChannel("ticket",false)?.id ?? instance.channel.id + }else if (scope == "user"){ + data = instance.options.getUser("user",false)?.id ?? instance.user.id + }else data = "/" + openticket.log(instance.user.displayName+" used the 'stats "+scope+"' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source}, + {key:"data",value:data}, + ]) + }) + ]) +} \ No newline at end of file diff --git a/src/commands/ticket.ts b/src/commands/ticket.ts new file mode 100644 index 0000000..ffa00ea --- /dev/null +++ b/src/commands/ticket.ts @@ -0,0 +1,269 @@ +/////////////////////////////////////// +//TICKET COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //TICKET COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:ticket",generalConfig.data.prefix,/^ticket/)) + openticket.responders.commands.get("openticket:ticket").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.ticket + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:ticket",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + return cancel() + } + + //get option + const optionId = instance.options.getString("id",true) + const option = openticket.options.get(optionId) + if (!option || !(option instanceof api.ODTicketOption)){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + return cancel() + } + + //check ticket permissions + const res = await openticket.actions.get("openticket:create-ticket-permissions").run(source,{guild,user,option}) + if (!res.valid){ + //error + if (res.reason == "blacklist") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + else if (res.reason == "cooldown") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) + else if (res.reason == "global-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) + else if (res.reason == "global-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) + else if (res.reason == "option-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) + else if (res.reason == "option-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) + else instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) + return cancel() + } + + //start ticket creation + if (option.exists("openticket:questions") && option.get("openticket:questions").value.length > 0){ + //send modal + instance.modal(await openticket.builders.modals.getSafe("openticket:ticket-questions").build(source,{guild,channel,user,option})) + }else{ + //create ticket + await instance.defer(true) + const res = await openticket.actions.get("openticket:create-ticket").run(source,{guild,user,answers:[],option}) + if (!res.channel || !res.ticket){ + //error + await instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) + return cancel() + } + await instance.reply(await openticket.builders.messages.getSafe("openticket:ticket-created").build(source,{guild,channel:res.channel,user,ticket:res.ticket})) + } + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'ticket' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerButtonResponders = async () => { + //TICKET OPTION BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:ticket-option",/^od:ticket-option_/)) + openticket.responders.buttons.get("openticket:ticket-option").workers.add( + new api.ODWorker("openticket:ticket-option",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + return cancel() + } + + //get option + const optionId = instance.interaction.customId.split("_")[2] + const option = openticket.options.get(optionId) + if (!option || !(option instanceof api.ODTicketOption)){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + return cancel() + } + + //check ticket permissions + const res = await openticket.actions.get("openticket:create-ticket-permissions").run("panel-button",{guild,user,option}) + if (!res.valid){ + //error + if (res.reason == "blacklist") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + else if (res.reason == "cooldown") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) + else if (res.reason == "global-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) + else if (res.reason == "global-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) + else if (res.reason == "option-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) + else if (res.reason == "option-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) + else instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) + return cancel() + } + + //start ticket creation + if (option.exists("openticket:questions") && option.get("openticket:questions").value.length > 0){ + //send modal + instance.modal(await openticket.builders.modals.getSafe("openticket:ticket-questions").build("panel-button",{guild,channel,user,option})) + }else{ + //create ticket + await instance.defer("reply",true) + const res = await openticket.actions.get("openticket:create-ticket").run("panel-button",{guild,user,answers:[],option}) + if (!res.channel || !res.ticket){ + //error + await instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) + return cancel() + } + if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await openticket.builders.messages.getSafe("openticket:ticket-created").build("panel-button",{guild,channel:res.channel,user,ticket:res.ticket})) + } + }) + ) +} + +export const registerDropdownResponders = async () => { + //PANEL DROPDOWN TICKETS DROPDOWN RESPONDER + openticket.responders.dropdowns.add(new api.ODDropdownResponder("openticket:panel-dropdown-tickets",/^od:panel-dropdown_/)) + openticket.responders.dropdowns.get("openticket:panel-dropdown-tickets").workers.add( + new api.ODWorker("openticket:panel-dropdown-tickets",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + return cancel() + } + + //get option + const optionId = instance.values.getStringValues()[0].split("_")[2] + const option = openticket.options.get(optionId) + if (!option || !(option instanceof api.ODTicketOption)){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + return cancel() + } + + //check ticket permissions + const res = await openticket.actions.get("openticket:create-ticket-permissions").run("panel-dropdown",{guild,user,option}) + if (!res.valid){ + //error + if (res.reason == "blacklist") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + else if (res.reason == "cooldown") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) + else if (res.reason == "global-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) + else if (res.reason == "global-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) + else if (res.reason == "option-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) + else if (res.reason == "option-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) + else instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) + return cancel() + } + + //start ticket creation + if (option.exists("openticket:questions") && option.get("openticket:questions").value.length > 0){ + //send modal + instance.modal(await openticket.builders.modals.getSafe("openticket:ticket-questions").build("panel-dropdown",{guild,channel,user,option})) + }else{ + //create ticket + await instance.defer("reply",true) + const res = await openticket.actions.get("openticket:create-ticket").run("panel-dropdown",{guild,user,answers:[],option}) + if (!res.channel || !res.ticket){ + //error + await instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) + return cancel() + } + if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await openticket.builders.messages.getSafe("openticket:ticket-created").build("panel-dropdown",{guild,channel:res.channel,user,ticket:res.ticket})) + } + }) + ) +} + +export const registerModalResponders = async () => { + //TICKET QUESTIONS RESPONDER + openticket.responders.modals.add(new api.ODModalResponder("openticket:ticket-questions",/^od:ticket-questions_/)) + openticket.responders.modals.get("openticket:ticket-questions").workers.add([ + new api.ODWorker("openticket:ticket-questions",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!channel) throw new api.ODSystemError("The 'Ticket Questions' modal Requires a channel for responding!") + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + return cancel() + } + + const originalSource = instance.interaction.customId.split("_")[2] as ("panel-button"|"panel-dropdown"|"slash"|"text"|"other") + + //get option + const optionId = instance.interaction.customId.split("_")[1] + const option = openticket.options.get(optionId) + if (!option || !(option instanceof api.ODTicketOption)){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel,user:instance.user})) + return cancel() + } + + //get answers + const answers: {id:string,name:string,type:"short"|"paragraph",value:string|null}[] = [] + option.get("openticket:questions").value.forEach((id) => { + const question = openticket.questions.get(id) + if (!question) return + if (question instanceof api.ODShortQuestion){ + answers.push({ + id, + name:question.exists("openticket:name") ? question.get("openticket:name")?.value : id, + type:"short", + value:instance.values.getTextField(id,false) + }) + }else if (question instanceof api.ODParagraphQuestion){ + answers.push({ + id, + name:question.exists("openticket:name") ? question.get("openticket:name")?.value : id, + type:"paragraph", + value:instance.values.getTextField(id,false) + }) + } + }) + + //create ticket + await instance.defer("reply",true) + const res = await openticket.actions.get("openticket:create-ticket").run(originalSource,{guild,user,answers,option}) + if (!res.channel || !res.ticket){ + //error + await instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild,channel,user,error:"Unable to receive ticket or channel from callback! #2",layout:"advanced"})) + return cancel() + } + if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await openticket.builders.messages.getSafe("openticket:ticket-created").build(originalSource,{guild,channel:res.channel,user,ticket:res.ticket})) + }) + ]) +} \ No newline at end of file diff --git a/src/commands/unclaim.ts b/src/commands/unclaim.ts new file mode 100644 index 0000000..784fa8a --- /dev/null +++ b/src/commands/unclaim.ts @@ -0,0 +1,136 @@ +/////////////////////////////////////// +//UNCLAIM COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //UNCLAIM COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:unclaim",generalConfig.data.prefix,"unclaim")) + openticket.responders.commands.get("openticket:unclaim").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.unclaim + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:unclaim",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when not claimed + if (!ticket.get("openticket:claimed").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is not claimed yet!",layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const reason = instance.options.getString("reason",false) + + //start unclaiming ticket + await instance.defer(false) + await openticket.actions.get("openticket:unclaim-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await openticket.builders.messages.getSafe("openticket:unclaim-message").build(source,{guild,channel,user,ticket,reason})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'unclaim' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerButtonResponders = async () => { + //UNCLAIM TICKET BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:unclaim-ticket",/^od:unclaim-ticket/)) + openticket.responders.buttons.get("openticket:unclaim-ticket").workers.add( + new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source,cancel) => { + const originalSource = instance.interaction.customId.split("_")[1] + if (originalSource != "ticket-message" && originalSource != "claim-message") return + + if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:unclaim-ticket-ticket-message").activate(instance) + else await openticket.verifybars.get("openticket:unclaim-ticket-claim-message").activate(instance) + }) + ) +} + +export const registerModalResponders = async () => { + //UNCLAIM WITH REASON MODAL RESPONDER + openticket.responders.modals.add(new api.ODModalResponder("openticket:unclaim-ticket-reason",/^od:unclaim-ticket-reason_/)) + openticket.responders.modals.get("openticket:unclaim-ticket-reason").workers.add([ + new api.ODWorker("openticket:unclaim-ticket-reason",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!channel) return + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + return cancel() + } + const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return + } + + const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"claim-message"|"other") + const reason = instance.values.getTextField("reason",true) + + //unclaim with reason + if (originalSource == "ticket-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }else if (originalSource == "claim-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:unclaim-message").build("other",{guild,channel,user,ticket,reason})) + }else if (originalSource == "other"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + } + }) + ]) +} \ No newline at end of file diff --git a/src/commands/unpin.ts b/src/commands/unpin.ts new file mode 100644 index 0000000..c39daf2 --- /dev/null +++ b/src/commands/unpin.ts @@ -0,0 +1,136 @@ +/////////////////////////////////////// +//UNPIN COMMAND +/////////////////////////////////////// +import {openticket, api, utilities} from "../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") + +export const registerCommandResponders = async () => { + //UNPIN COMMAND RESPONDER + openticket.responders.commands.add(new api.ODCommandResponder("openticket:unpin",generalConfig.data.prefix,"unpin")) + openticket.responders.commands.get("openticket:unpin").workers.add([ + new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + const permissionMode = generalConfig.data.system.permissions.unpin + + if (permissionMode == "none"){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else if (permissionMode == "everyone") return + else if (permissionMode == "admin"){ + if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + return cancel() + }else return + }else{ + if (!instance.guild || !instance.member){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + return cancel() + } + const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + if (!role){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + return cancel() + } + if (!role.members.has(instance.member.id)){ + //no permissions + instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + return cancel() + }else return + } + }), + new api.ODWorker("openticket:unpin",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!guild){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + return cancel() + } + const ticket = openticket.tickets.get(channel.id) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return cancel() + } + //return when not pinned yet + if (!ticket.get("openticket:pinned").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is not pinned yet!",layout:"simple"})) + return cancel() + } + //return when busy + if (ticket.get("openticket:busy").value){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + return cancel() + } + + const reason = instance.options.getString("reason",false) + + //start unpinning ticket + await instance.defer(false) + await openticket.actions.get("openticket:unpin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await openticket.builders.messages.getSafe("openticket:unpin-message").build(source,{guild,channel,user,ticket,reason})) + }), + new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + openticket.log(instance.user.displayName+" used the 'unpin' command!","info",[ + {key:"user",value:instance.user.username}, + {key:"userid",value:instance.user.id,hidden:true}, + {key:"channelid",value:instance.channel.id,hidden:true}, + {key:"method",value:source} + ]) + }) + ]) +} + +export const registerButtonResponders = async () => { + //UNPIN TICKET BUTTON RESPONDER + openticket.responders.buttons.add(new api.ODButtonResponder("openticket:unpin-ticket",/^od:unpin-ticket/)) + openticket.responders.buttons.get("openticket:unpin-ticket").workers.add( + new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source,cancel) => { + const originalSource = instance.interaction.customId.split("_")[1] + if (originalSource != "ticket-message" && originalSource != "pin-message") return + + if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:unpin-ticket-ticket-message").activate(instance) + else await openticket.verifybars.get("openticket:unpin-ticket-pin-message").activate(instance) + }) + ) +} + +export const registerModalResponders = async () => { + //UNPIN WITH REASON MODAL RESPONDER + openticket.responders.modals.add(new api.ODModalResponder("openticket:unpin-ticket-reason",/^od:unpin-ticket-reason_/)) + openticket.responders.modals.get("openticket:unpin-ticket-reason").workers.add([ + new api.ODWorker("openticket:unpin-ticket-reason",0,async (instance,params,source,cancel) => { + const {guild,channel,user} = instance + if (!channel) return + if (!guild){ + //error + instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + return cancel() + } + const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + if (!ticket || channel.isDMBased()){ + instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + return + } + + const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"pin-message"|"other") + const reason = instance.values.getTextField("reason",true) + + //unpin with reason + if (originalSource == "ticket-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + }else if (originalSource == "pin-message"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await openticket.builders.messages.getSafe("openticket:unpin-message").build("other",{guild,channel,user,ticket,reason})) + }else if (originalSource == "other"){ + await instance.defer("update",false) + await openticket.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + } + }) + ]) +} \ No newline at end of file diff --git a/src/core/api/api.ts b/src/core/api/api.ts new file mode 100644 index 0000000..387de94 --- /dev/null +++ b/src/core/api/api.ts @@ -0,0 +1,60 @@ +//MAIN MODULE +export * from "./main" + +//BASE MODULES +export * from "./modules/base" +export * from "./modules/event" +export * from "./modules/config" +export * from "./modules/database" +export * from "./modules/language" +export * from "./modules/flag" +export * from "./modules/console" +export * from "./modules/defaults" +export * from "./modules/plugin" +export * from "./modules/checker" +export * from "./modules/client" +export * from "./modules/worker" +export * from "./modules/builder" +export * from "./modules/responder" +export * from "./modules/action" +export * from "./modules/permission" +export * from "./modules/helpmenu" +export * from "./modules/session" +export * from "./modules/stat" +export * from "./modules/code" +export * from "./modules/cooldown" +export * from "./modules/post" +export * from "./modules/verifybar" +export * from "./modules/startscreen" + +//OPENTICKET DEFAULT MODULES +export * from "./defaults/base" +export * from "./defaults/event" +export * from "./defaults/config" +export * from "./defaults/database" +export * from "./defaults/checker" +export * from "./defaults/client" +export * from "./defaults/language" +export * from "./defaults/builder" +export * from "./defaults/responder" +export * from "./defaults/action" +export * from "./defaults/flag" +export * from "./defaults/permission" +export * from "./defaults/helpmenu" +export * from "./defaults/session" +export * from "./defaults/stat" +export * from "./defaults/worker" +export * from "./defaults/code" +export * from "./defaults/cooldown" +export * from "./defaults/post" +export * from "./defaults/startscreen" +export * from "./defaults/console" + +//OPENTICKET MODULES +export * from "./openticket/question" +export * from "./openticket/option" +export * from "./openticket/panel" +export * from "./openticket/ticket" +export * from "./openticket/blacklist" +export * from "./openticket/transcript" +export * from "./openticket/role" \ No newline at end of file diff --git a/src/core/api/defaults/action.ts b/src/core/api/defaults/action.ts new file mode 100644 index 0000000..c8d68a8 --- /dev/null +++ b/src/core/api/defaults/action.ts @@ -0,0 +1,154 @@ +/////////////////////////////////////// +//DEFAULT ACTION MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODAction, ODActionManager } from "../modules/action" +import { ODWorkerManager_Default } from "./worker" +import * as discord from "discord.js" +import { ODRoleOption, ODTicketOption } from "../openticket/option" +import { ODTicket, ODTicketClearFilter } from "../openticket/ticket" +import { ODTranscriptCompiler, ODTranscriptCompilerCompileResult } from "../openticket/transcript" +import { ODMessageBuildSentResult } from "../modules/builder" +import { ODRole, OTRoleUpdateMode, OTRoleUpdateResult } from "../openticket/role" + +/**## ODActionManagerIds_Default `type` + * This type is an array of ids available in the `ODActionManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODActionManagerIds_Default { + "openticket:create-ticket-permissions":{ + source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other", + params:{guild:discord.Guild,user:discord.User,option:ODTicketOption}, + result:{valid:boolean,reason:"blacklist"|"cooldown"|"global-limit"|"global-user-limit"|"option-limit"|"option-user-limit"|null,cooldownUntil?:Date}, + workers:"openticket:check-blacklist"|"openticket:check-cooldown"|"openticket:check-global-limits"|"openticket:check-option-limits"|"openticket:valid" + }, + "openticket: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, success:boolean, result:ODTranscriptCompilerCompileResult, errorReason:string|null, pendingMessage:ODMessageBuildSentResult|null, participants:{user:discord.User,role:"creator"|"participant"|"admin"}[]}, + workers:"openticket:select-compiler"|"openticket:init-transcript"|"openticket:compile-transcript"|"openticket:ready-transcript"|"openticket:logs" + }, + "openticket:create-ticket":{ + source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other", + params:{guild:discord.Guild,user:discord.User,option:ODTicketOption,answers:{id:string,name:string,type:"short"|"paragraph",value:string|null}[]}, + result:{channel:discord.GuildTextBasedChannel,ticket:ODTicket}, + workers:"openticket:create-ticket"|"openticket:send-ticket-message"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:close-ticket":{ + source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, + result:{}, + workers:"openticket:close-ticket"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:delete-ticket":{ + 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,reason:string|null,sendMessage:boolean,withoutTranscript:boolean}, + result:{}, + workers:"openticket:delete-ticket"|"openticket:discord-logs"|"openticket:delete-channel"|"openticket:logs" + }, + "openticket:reopen-ticket":{ + source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, + result:{}, + workers:"openticket:reopen-ticket"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:claim-ticket":{ + source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, + result:{}, + workers:"openticket:claim-ticket"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:unclaim-ticket":{ + source:"slash"|"text"|"ticket-message"|"claim-message"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, + result:{}, + workers:"openticket:unclaim-ticket"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:pin-ticket":{ + source:"slash"|"text"|"ticket-message"|"unpin-message"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, + result:{}, + workers:"openticket:pin-ticket"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:unpin-ticket":{ + source:"slash"|"text"|"ticket-message"|"pin-message"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, + result:{}, + workers:"openticket:unpin-ticket"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:rename-ticket":{ + source:"slash"|"text"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:string}, + result:{}, + workers:"openticket:rename-ticket"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:move-ticket":{ + source:"slash"|"text"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:ODTicketOption}, + result:{}, + workers:"openticket:move-ticket"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:add-ticket-user":{ + source:"slash"|"text"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:discord.User}, + result:{}, + workers:"openticket:add-ticket-user"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:remove-ticket-user":{ + source:"slash"|"text"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:discord.User}, + result:{}, + workers:"openticket:remove-ticket-user"|"openticket:discord-logs"|"openticket:logs" + }, + "openticket:reaction-role":{ + source:"panel-button"|"other", + params:{guild:discord.Guild,user:discord.User,option:ODRoleOption,overwriteMode:OTRoleUpdateMode|null}, + result:{result:OTRoleUpdateResult[],role:ODRole}, + workers:"openticket:reaction-role"|"openticket:logs" + }, + "openticket:clear-tickets":{ + source:"slash"|"text"|"other", + params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:ODTicket[]}, + result:{list:string[]}, + workers:"openticket:clear-tickets"|"openticket:discord-logs"|"openticket:logs" + } +} + +/**## ODActionManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODActionManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.actions`! + */ +export class ODActionManager_Default extends ODActionManager { + get(id:ActionId): ODAction_Default + get(id:ODValidId): ODAction|null + + get(id:ODValidId): ODAction|null { + return super.get(id) + } + + remove(id:ActionId): ODAction_Default + remove(id:ODValidId): ODAction|null + + remove(id:ODValidId): ODAction|null { + return super.remove(id) + } + + exists(id:keyof ODActionManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODAction_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODAction class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODAction`'s! + */ +export class ODAction_Default extends ODAction { + declare workers: ODWorkerManager_Default +} \ No newline at end of file diff --git a/src/core/api/defaults/base.ts b/src/core/api/defaults/base.ts new file mode 100644 index 0000000..fceda6e --- /dev/null +++ b/src/core/api/defaults/base.ts @@ -0,0 +1,45 @@ +/////////////////////////////////////// +//BASE MODULE +/////////////////////////////////////// +import { ODVersion, ODVersionManager, ODValidId } from "../modules/base" + +/**## ODVersionManagerIds_Default `type` + * This type is an array of ids available in the `ODVersionManager` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODVersionManagerIds_Default { + "openticket:version":ODVersion, + "openticket:last-version":ODVersion, + "openticket:api":ODVersion, + "openticket:transcripts":ODVersion, + "openticket:livestatus":ODVersion +} + +/**## ODFlagManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODFlagManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.flags`! + */ +export class ODVersionManager_Default extends ODVersionManager { + get(id:VersionId): ODVersionManagerIds_Default[VersionId] + get(id:ODValidId): ODVersion|null + + get(id:ODValidId): ODVersion|null { + return super.get(id) + } + + remove(id:VersionId): ODVersionManagerIds_Default[VersionId] + remove(id:ODValidId): ODVersion|null + + remove(id:ODValidId): ODVersion|null { + return super.remove(id) + } + + exists(id:keyof ODVersionManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/builder.ts b/src/core/api/defaults/builder.ts new file mode 100644 index 0000000..0620071 --- /dev/null +++ b/src/core/api/defaults/builder.ts @@ -0,0 +1,532 @@ +/////////////////////////////////////// +//DEFAULT BUILDER MODULE +/////////////////////////////////////// +import { ODValidButtonColor, ODValidId } from "../modules/base" +import { ODBuilderManager, ODButton, ODButtonInstance, ODButtonManager, ODDropdown, ODDropdownInstance, ODDropdownManager, ODEmbed, ODEmbedInstance, ODEmbedManager, ODFile, ODFileInstance, ODFileManager, ODMessage, ODMessageInstance, ODMessageManager, ODModal, ODModalInstance, ODModalManager } from "../modules/builder" +import { ODWorkerManager_Default } from "./worker" +import { ODTicket, ODTicketClearFilter } from "../openticket/ticket" +import { ODPermissionEmbedType } from "../defaults/permission" +import { ODTextCommandErrorInvalidOption, ODTextCommandErrorMissingOption, ODTextCommandErrorUnknownCommand } from "../modules/client" +import { ODPanel } from "../openticket/panel" +import { ODRoleOption, ODTicketOption, ODWebsiteOption } from "../openticket/option" +import { ODVerifyBar } from "../modules/verifybar" +import * as discord from "discord.js" +import { ODTranscriptCompiler, ODTranscriptCompilerCompileResult } from "../openticket/transcript" +import { ODRole, OTRoleUpdateResult } from "../openticket/role" + +/**## ODBuilderManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODBuilderManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.builders`! + */ +export class ODBuilderManager_Default extends ODBuilderManager { + declare buttons: ODButtonManager_Default + declare dropdowns: ODDropdownManager_Default + declare files: ODFileManager_Default + declare embeds: ODEmbedManager_Default + declare messages: ODMessageManager_Default + declare modals: ODModalManager_Default +} + +/**## ODButtonManagerIds_Default `type` + * This type is an array of ids available in the `ODButtonManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODButtonManagerIds_Default { + "openticket:verifybar-success":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"openticket:verifybar-success"}, + "openticket:verifybar-failure":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"openticket:verifybar-failure"}, + + "openticket:error-ticket-deprecated-transcript":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{},workers:"openticket:error-ticket-deprecated-transcript"}, + + "openticket:help-menu-previous":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-previous"}, + "openticket:help-menu-next":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-next"}, + "openticket:help-menu-page":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-page"} + "openticket:help-menu-switch":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-switch"}, + + "openticket:ticket-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODTicketOption},workers:"openticket:ticket-option"}, + "openticket:website-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODWebsiteOption},workers:"openticket:website-option"}, + "openticket:role-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODRoleOption},workers:"openticket:role-option"} + + "openticket:visit-ticket":{source:"ticket-created"|"dm"|"logs"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:visit-ticket"}, + + "openticket:close-ticket":{source:"ticket-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:close-ticket"}, + "openticket:delete-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:delete-ticket"}, + "openticket:reopen-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:reopen-ticket"}, + "openticket:claim-ticket":{source:"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:claim-ticket"}, + "openticket:unclaim-ticket":{source:"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:unclaim-ticket"}, + "openticket:pin-ticket":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:pin-ticket"}, + "openticket:unpin-ticket":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:unpin-ticket"}, + + "openticket: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:"openticket:transcript-html-visit"}, + "openticket:transcript-error-retry":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"openticket:transcript-error-retry"}, + "openticket:transcript-error-continue":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"openticket:transcript-error-continue"}, + + "openticket:clear-continue":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-continue"}, +} + +/**## ODButtonManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODButtonManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.builders.buttons`! + */ +export class ODButtonManager_Default extends ODButtonManager { + get(id:ButtonId): ODButton_Default + get(id:ODValidId): ODButton|null + + get(id:ODValidId): ODButton|null { + return super.get(id) + } + + remove(id:ButtonId): ODButton_Default + remove(id:ODValidId): ODButton|null + + remove(id:ODValidId): ODButton|null { + return super.remove(id) + } + + exists(id:keyof ODButtonManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getSafe(id:ButtonId): ODButton_Default + getSafe(id:ODValidId): ODButton + + getSafe(id:ODValidId): ODButton { + return super.getSafe(id) + } +} + +/**## ODButton_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODButton class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODButton`'s! + */ +export class ODButton_Default extends ODButton { + declare workers: ODWorkerManager_Default +} + +/**## ODDropdownManagerIds_Default `type` + * This type is an array of ids available in the `ODDropdownManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODDropdownManagerIds_Default { + "openticket:panel-dropdown-tickets":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,options:ODTicketOption[]},workers:"openticket:panel-dropdown-tickets"} +} + +/**## ODDropdownManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODDropdownManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.builders.dropdowns`! + */ +export class ODDropdownManager_Default extends ODDropdownManager { + get(id:DropdownId): ODDropdown_Default + get(id:ODValidId): ODDropdown|null + + get(id:ODValidId): ODDropdown|null { + return super.get(id) + } + + remove(id:DropdownId): ODDropdown_Default + remove(id:ODValidId): ODDropdown|null + + remove(id:ODValidId): ODDropdown|null { + return super.remove(id) + } + + exists(id:keyof ODDropdownManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getSafe(id:DropdownId): ODDropdown_Default + getSafe(id:ODValidId): ODDropdown + + getSafe(id:ODValidId): ODDropdown { + return super.getSafe(id) + } +} + +/**## ODDropdown_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODDropdown class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODDropdown`'s! + */ +export class ODDropdown_Default extends ODDropdown { + declare workers: ODWorkerManager_Default +} + +/**## ODFileManagerIds_Default `type` + * This type is an array of ids available in the `ODFileManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODFileManagerIds_Default { + "openticket:text-transcript":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,result:ODTranscriptCompilerCompileResult},workers:"openticket:text-transcript"} +} + +/**## ODFileManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODFileManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.builders.files`! + */ +export class ODFileManager_Default extends ODFileManager { + get(id:FileId): ODFile_Default + get(id:ODValidId): ODFile|null + + get(id:ODValidId): ODFile|null { + return super.get(id) + } + + remove(id:FileId): ODFile_Default + remove(id:ODValidId): ODFile|null + + remove(id:ODValidId): ODFile|null { + return super.remove(id) + } + + exists(id:keyof ODFileManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getSafe(id:FileId): ODFile_Default + getSafe(id:ODValidId): ODFile + + getSafe(id:ODValidId): ODFile { + return super.getSafe(id) + } +} + +/**## ODFile_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODFile class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODFile`'s! + */ +export class ODFile_Default extends ODFile { + declare workers: ODWorkerManager_Default +} + +/**## ODEmbedManagerIds_Default `type` + * This type is an array of ids available in the `ODEmbedManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODEmbedManagerIds_Default { + "openticket:error":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:string,layout:"simple"|"advanced"},workers:"openticket:error"}, + "openticket:error-option-missing":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorMissingOption},workers:"openticket:error-option-missing"}, + "openticket:error-option-invalid":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorInvalidOption},workers:"openticket:error-option-invalid"}, + "openticket:error-unknown-command":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorUnknownCommand},workers:"openticket:error-unknown-command"}, + "openticket:error-no-permissions":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,permissions:ODPermissionEmbedType[]},workers:"openticket:error-no-permissions"}, + "openticket:error-no-permissions-cooldown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,until?:Date},workers:"openticket:error-no-permissions-cooldown"}, + "openticket:error-no-permissions-blacklisted":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-no-permissions-blacklisted"}, + "openticket:error-no-permissions-limits":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,limit:"global"|"global-user"|"option"|"option-user"},workers:"openticket:error-no-permissions-limits"}, + "openticket:error-responder-timeout":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-responder-timeout"}, + "openticket:error-ticket-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-unknown"}, + "openticket:error-ticket-deprecated":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-deprecated"}, + "openticket:error-option-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-option-unknown"}, + "openticket:error-panel-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-panel-unknown"}, + "openticket:error-not-in-guild":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-not-in-guild"}, + "openticket:error-channel-rename":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"ticket-pin"|"ticket-unpin"|"ticket-rename"|"ticket-move"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"openticket:error-channel-rename"}, + "openticket:error-ticket-busy":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-busy"}, + + "openticket:help-menu":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu"}, + + "openticket:stats-global":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:stats-global"}, + "openticket:stats-ticket":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:ODTicket},workers:"openticket:stats-ticket"}, + "openticket:stats-user":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:discord.User},workers:"openticket:stats-user"|"openticket:easter-egg"}, + "openticket:stats-reset":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,reason:string|null},workers:"openticket:stats-reset"}, + "openticket:stats-ticket-unknown":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,id:string},workers:"openticket:stats-ticket-unknown"}, + + "openticket:panel":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"openticket:panel"}, + "openticket:ticket-created":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created"}, + "openticket:ticket-created-dm":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created-dm"}, + "openticket:ticket-created-logs":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created-logs"}, + "openticket:ticket-message":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-message"}, + "openticket:close-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:close-message"}, + "openticket:reopen-message":{source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:reopen-message"}, + "openticket:delete-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:delete-message"}, + "openticket:claim-message":{source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:claim-message"}, + "openticket:unclaim-message":{source:"slash"|"text"|"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:unclaim-message"}, + "openticket:pin-message":{source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:pin-message"}, + "openticket:unpin-message":{source:"slash"|"text"|"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:unpin-message"}, + "openticket:rename-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:string},workers:"openticket:rename-message"}, + "openticket:move-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:ODTicketOption},workers:"openticket:move-message"}, + "openticket:add-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"openticket:add-message"}, + "openticket:remove-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"openticket:remove-message"}, + "openticket:ticket-action-dm":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"openticket:ticket-action-dm"}, + "openticket:ticket-action-logs":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"openticket:ticket-action-logs"}, + + "openticket:blacklist-view":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:blacklist-view"}, + "openticket:blacklist-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User},workers:"openticket:blacklist-get"}, + "openticket:blacklist-add":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"openticket:blacklist-add"}, + "openticket:blacklist-remove":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"openticket:blacklist-remove"} + "openticket: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:"openticket:blacklist-dm"}, + "openticket: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:"openticket:blacklist-logs"}, + + "openticket: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:"openticket:transcript-text-ready"}, + "openticket: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:"openticket:transcript-html-ready"}, + "openticket: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:"openticket:transcript-html-progress"}, + "openticket:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"openticket:transcript-error"}, + + "openticket:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:OTRoleUpdateResult[]},workers:"openticket:reaction-role"}, + "openticket:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-verify-message"}, + "openticket:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-message"}, + "openticket:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-logs"}, + + "openticket:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autoclose-message"}, + "openticket:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autodelete-message"}, + "openticket:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autoclose-enable"}, + "openticket:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autodelete-enable"}, + "openticket:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autoclose-disable"}, + "openticket:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autodelete-disable"}, +} + +/**## ODEmbedManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODEmbedManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.builders.embeds`! + */ +export class ODEmbedManager_Default extends ODEmbedManager { + get(id:EmbedId): ODEmbed_Default + get(id:ODValidId): ODEmbed|null + + get(id:ODValidId): ODEmbed|null { + return super.get(id) + } + + remove(id:EmbedId): ODEmbed_Default + remove(id:ODValidId): ODEmbed|null + + remove(id:ODValidId): ODEmbed|null { + return super.remove(id) + } + + exists(id:keyof ODEmbedManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getSafe(id:EmbedId): ODEmbed_Default + getSafe(id:ODValidId): ODEmbed + + getSafe(id:ODValidId): ODEmbed { + return super.getSafe(id) + } +} + +/**## ODEmbed_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODEmbed class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODEmbed`'s! + */ +export class ODEmbed_Default extends ODEmbed { + declare workers: ODWorkerManager_Default +} + +/**## ODMessageManagerIds_Default `type` + * This type is an array of ids available in the `ODMessageManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODMessageManagerIds_Default { + "openticket:verifybar-ticket-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-ticket-message"}, + "openticket:verifybar-close-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-close-message"}, + "openticket:verifybar-reopen-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-reopen-message"}, + "openticket:verifybar-claim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-claim-message"}, + "openticket:verifybar-unclaim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-unclaim-message"}, + "openticket:verifybar-pin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-pin-message"}, + "openticket:verifybar-unpin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-unpin-message"} + "openticket:verifybar-autoclose-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-autoclose-message"} + + "openticket:error":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:string,layout:"simple"|"advanced"},workers:"openticket:error"}, + "openticket:error-option-missing":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorMissingOption},workers:"openticket:error-option-missing"}, + "openticket:error-option-invalid":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorInvalidOption},workers:"openticket:error-option-invalid"}, + "openticket:error-unknown-command":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorUnknownCommand},workers:"openticket:error-unknown-command"}, + "openticket:error-no-permissions":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,permissions:ODPermissionEmbedType[]},workers:"openticket:error-no-permissions"}, + "openticket:error-no-permissions-cooldown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,until?:Date},workers:"openticket:error-no-permissions-cooldown"}, + "openticket:error-no-permissions-blacklisted":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-no-permissions-blacklisted"}, + "openticket:error-no-permissions-limits":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,limit:"global"|"global-user"|"option"|"option-user"},workers:"openticket:error-no-permissions-limits"}, + "openticket:error-responder-timeout":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-responder-timeout"}, + "openticket:error-ticket-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-unknown"}, + "openticket:error-ticket-deprecated":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-deprecated"}, + "openticket:error-option-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-option-unknown"}, + "openticket:error-panel-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-panel-unknown"}, + "openticket:error-not-in-guild":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-not-in-guild"}, + "openticket:error-channel-rename":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"ticket-pin"|"ticket-unpin"|"ticket-rename"|"ticket-move"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"openticket:error-channel-rename"}, + "openticket:error-ticket-busy":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-busy"}, + + "openticket:help-menu":{source:"slash"|"text"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu"}, + + "openticket:stats-global":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:stats-global"}, + "openticket:stats-ticket":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:ODTicket},workers:"openticket:stats-ticket"}, + "openticket:stats-user":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:discord.User},workers:"openticket:stats-user"|"openticket:easter-egg"}, + "openticket:stats-reset":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,reason:string|null},workers:"openticket:stats-reset"}, + "openticket:stats-ticket-unknown":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,id:string},workers:"openticket:stats-ticket-unknown"}, + + "openticket:panel":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"openticket:panel-layout"|"openticket:panel-components"}, + "openticket:panel-ready":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"openticket:panel-ready"}, + + "openticket:ticket-created":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created"}, + "openticket:ticket-created-dm":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created-dm"}, + "openticket:ticket-created-logs":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created-logs"}, + "openticket:ticket-message":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-message-layout"|"openticket:ticket-message-components"|"openticket:ticket-message-disable-components"}, + "openticket:close-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:close-message"}, + "openticket:reopen-message":{source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:reopen-message"}, + "openticket:delete-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:delete-message"}, + "openticket:claim-message":{source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:claim-message"}, + "openticket:unclaim-message":{source:"slash"|"text"|"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:unclaim-message"}, + "openticket:pin-message":{source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:pin-message"}, + "openticket:unpin-message":{source:"slash"|"text"|"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:unpin-message"}, + "openticket:rename-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:string},workers:"openticket:rename-message"}, + "openticket:move-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:ODTicketOption},workers:"openticket:move-message"}, + "openticket:add-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"openticket:add-message"}, + "openticket:remove-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"openticket:remove-message"}, + "openticket:ticket-action-dm":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"openticket:ticket-action-dm"}, + "openticket:ticket-action-logs":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"openticket:ticket-action-logs"}, + + "openticket:blacklist-view":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:blacklist-view"}, + "openticket:blacklist-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User},workers:"openticket:blacklist-get"}, + "openticket:blacklist-add":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"openticket:blacklist-add"}, + "openticket:blacklist-remove":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"openticket:blacklist-remove"}, + "openticket: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:"openticket:blacklist-dm"}, + "openticket: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:"openticket:blacklist-logs"}, + + "openticket: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:"openticket:transcript-text-ready"}, + "openticket: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:"openticket:transcript-html-ready"}, + "openticket: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:"openticket:transcript-html-progress"}, + "openticket:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"openticket:transcript-error"}, + + "openticket:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:OTRoleUpdateResult[]},workers:"openticket:reaction-role"}, + "openticket:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-verify-message"}, + "openticket:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-message"}, + "openticket:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-logs"}, + + "openticket:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autoclose-message"}, + "openticket:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autodelete-message"}, + "openticket:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autoclose-enable"}, + "openticket:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autodelete-enable"}, + "openticket:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autoclose-disable"}, + "openticket:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autodelete-disable"}, +} + +/**## ODMessageManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODMessageManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.builders.messages`! + */ +export class ODMessageManager_Default extends ODMessageManager { + get(id:MessageId): ODMessage_Default + get(id:ODValidId): ODMessage|null + + get(id:ODValidId): ODMessage|null { + return super.get(id) + } + + remove(id:MessageId): ODMessage_Default + remove(id:ODValidId): ODMessage|null + + remove(id:ODValidId): ODMessage|null { + return super.remove(id) + } + + exists(id:keyof ODMessageManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getSafe(id:MessageId): ODMessage_Default + getSafe(id:ODValidId): ODMessage + + getSafe(id:ODValidId): ODMessage { + return super.getSafe(id) + } +} + +/**## ODMessage_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODMessage class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODMessage`'s! + */ +export class ODMessage_Default extends ODMessage { + declare workers: ODWorkerManager_Default +} + +/**## ODModalManagerIds_Default `type` + * This type is an array of ids available in the `ODModalManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODModalManagerIds_Default { + "openticket:ticket-questions":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,option:ODTicketOption},workers:"openticket:ticket-questions"} + "openticket:close-ticket-reason":{source:"ticket-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:close-ticket-reason"} + "openticket:reopen-ticket-reason":{source:"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:reopen-ticket-reason"} + "openticket:delete-ticket-reason":{source:"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:delete-ticket-reason"} + "openticket:claim-ticket-reason":{source:"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:claim-ticket-reason"} + "openticket:unclaim-ticket-reason":{source:"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:unclaim-ticket-reason"} + "openticket:pin-ticket-reason":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:pin-ticket-reason"} + "openticket:unpin-ticket-reason":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:unpin-ticket-reason"} +} + +/**## ODModalManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODModalManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.builders.modals`! + */ +export class ODModalManager_Default extends ODModalManager { + get(id:ModalId): ODModal_Default + get(id:ODValidId): ODModal|null + + get(id:ODValidId): ODModal|null { + return super.get(id) + } + + remove(id:ModalId): ODModal_Default + remove(id:ODValidId): ODModal|null + + remove(id:ODValidId): ODModal|null { + return super.remove(id) + } + + exists(id:keyof ODModalManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getSafe(id:ModalId): ODModal_Default + getSafe(id:ODValidId): ODModal + + getSafe(id:ODValidId): ODModal { + return super.getSafe(id) + } +} + +/**## ODModal_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODModal class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODModal`'s! + */ +export class ODModal_Default extends ODModal { + declare workers: ODWorkerManager_Default +} \ No newline at end of file diff --git a/src/core/api/defaults/checker.ts b/src/core/api/defaults/checker.ts new file mode 100644 index 0000000..69e6d53 --- /dev/null +++ b/src/core/api/defaults/checker.ts @@ -0,0 +1,378 @@ +/////////////////////////////////////// +//DEFAULT CONFIG CHECKER MODULE +/////////////////////////////////////// +import { ODLanguageManager_Default } from "../api" +import { ODValidId } from "../modules/base" +import { ODCheckerManager, ODChecker, ODCheckerTranslationRegister, ODCheckerRenderer, ODCheckerFunctionManager, ODCheckerResult, ODCheckerFunction } from "../modules/checker" +import ansis from "ansis" + +/**## ODCheckerManagerIds_Default `type` + * This type is an array of ids available in the `ODCheckerManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODCheckerManagerIds_Default { + "openticket:general":ODChecker, + "openticket:options":ODChecker, + "openticket:messages":ODChecker, + "openticket:transcripts":ODChecker +} + +/**## ODCheckerManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODCheckerManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.checkers`! + */ +export class ODCheckerManager_Default extends ODCheckerManager { + declare translation: ODCheckerTranslationRegister_Default + declare renderer: ODCheckerRenderer_Default + declare functions: ODCheckerFunctionManager_Default + + get(id:CheckerId): ODCheckerManagerIds_Default[CheckerId] + get(id:ODValidId): ODChecker|null + + get(id:ODValidId): ODChecker|null { + return super.get(id) + } + + remove(id:CheckerId): ODCheckerManagerIds_Default[CheckerId] + remove(id:ODValidId): ODChecker|null + + remove(id:ODValidId): ODChecker|null { + return super.remove(id) + } + + exists(id:keyof ODCheckerManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODCheckerRenderer_Default `default_class` + * This is a special class that adds type definitions & features to the ODCheckerRenderer class. + * It contains the code that renders the default config checker. + * + * This default class is made for the global variable `openticket.checkers.renderer`! + */ +export class ODCheckerRenderer_Default extends ODCheckerRenderer { + extraHeaderText: string[] = [] + extraFooterText: string[] = [] + extraTopText: string[] = [] + extraBottomText: string[] = [] + + horizontalFiller: string = "=" + verticalFiller: string = "|" + descriptionSeparator: string = " => " + footerTipPrefix: string = "=> " + + disableHeader: boolean = false + disableFooter: boolean = false + + getComponents(compact:boolean, renderEmpty:boolean, translation:ODCheckerTranslationRegister_Default, data:ODCheckerResult): string[] { + const tm = translation + const t = { + headerOpenticket:tm.get("other","openticket:header-openticket") ?? "OPEN TICKET", + headerConfigchecker:tm.get("other","openticket:header-configchecker") ?? "CONFIG CHECKER", + headerDescription:tm.get("other","openticket:header-description") ?? "check for errors in you config files!", + footerError:tm.get("other","openticket:footer-error") ?? "the bot won't start until all {0}'s are fixed!", + footerWarning:tm.get("other","openticket:footer-warning") ?? "it's recommended to fix all {0}'s before starting!", + footerSupport:tm.get("other","openticket:footer-support") ?? "SUPPORT: {0} - DOCS: {1}", + error:tm.get("other","openticket:type-error") ?? "[ERROR]", + warning:tm.get("other","openticket:type-warning") ?? "[WARNING]", + info:tm.get("other","openticket:type-info") ?? "[INFO]", + compactInfo:tm.get("other","openticket:compact-information") ?? "use {0} for more information!", + dataPath:tm.get("other","openticket:data-path") ?? "path", + dataDocs:tm.get("other","openticket:data-docs") ?? "docs", + dataMessage:tm.get("other","openticket:data-message") ?? "message" + } + const hasErrors = data.messages.filter((m) => m.type == "error").length > 0 + const hasWarnings = data.messages.filter((m) => m.type == "warning").length > 0 + const hasInfo = data.messages.filter((m) => m.type == "info").length > 0 + + if (!renderEmpty && !hasErrors && !hasWarnings && (!hasInfo || compact)) return [] + + const headerText = ansis.bold.hex("#f8ba00")(t.headerOpenticket)+" "+t.headerConfigchecker+" => "+ansis.hex("#f8ba00")(t.headerDescription) + const footerErrorText = (hasErrors) ? this.footerTipPrefix+ansis.gray(tm.insertTranslationParams(t.footerError,[ansis.bold.red(t.error)])) : "" + const footerWarningText = (hasWarnings) ? this.footerTipPrefix+ansis.gray(tm.insertTranslationParams(t.footerWarning,[ansis.bold.yellow(t.warning)])) : "" + const footerSupportText = tm.insertTranslationParams(t.footerSupport,[ansis.green("https://discord.dj-dj.be"),ansis.green("https://otdocs.dj-dj.be")]) + const bottomCompactInfo = (compact) ? ansis.gray(tm.insertTranslationParams(t.compactInfo,[ansis.bold.green("npm start -- --checker")])) : "" + + const finalHeader = [headerText,...this.extraHeaderText] + const finalFooter = [footerErrorText,footerWarningText,footerSupportText,...this.extraFooterText] + const finalTop = [...this.extraTopText] + const finalBottom = [bottomCompactInfo,...this.extraBottomText] + const borderLength = this.#getLongestLength([...finalHeader,...finalFooter]) + + const finalComponents: string[] = [] + + //header + if (!this.disableHeader){ + finalHeader.forEach((text) => { + if (text.length < 1) return + finalComponents.push(this.#createBlockFromText(text,borderLength)) + }) + } + finalComponents.push(this.#getHorizontalDivider(borderLength+4)) + + //top + finalTop.forEach((text) => { + if (text.length < 1) return + finalComponents.push(this.verticalFiller+" "+text) + }) + finalComponents.push(this.verticalFiller) + + //messages + if (compact){ + //use compact messages + data.messages.forEach((msg,index) => { + //compact mode doesn't render info + if (msg.type == "info") return + + //check if translation available & use it if possible + const rawTranslation = tm.get("message",msg.messageId.value) + const translatedMessage = (rawTranslation) ? tm.insertTranslationParams(rawTranslation,msg.translationParams) : msg.message + + if (msg.type == "error") finalComponents.push(this.verticalFiller+" "+ansis.bold.red(`${t.error} ${translatedMessage}`)) + else if (msg.type == "warning") finalComponents.push(this.verticalFiller+" "+ansis.bold.yellow(`${t.warning} ${translatedMessage}`)) + + const pathSplitter = msg.path ? ":" : "" + finalComponents.push(this.verticalFiller+ansis.bold(this.descriptionSeparator)+ansis.cyan(`${ansis.magenta(msg.filepath+pathSplitter)} ${msg.path}`)) + if (index != data.messages.length-1) finalComponents.push(this.verticalFiller) + }) + }else{ + //use full messages + data.messages.forEach((msg,index) => { + //check if translation available & use it if possible + const rawTranslation = tm.get("message",msg.messageId.value) + const translatedMessage = (rawTranslation) ? tm.insertTranslationParams(rawTranslation,msg.translationParams) : msg.message + + if (msg.type == "error") finalComponents.push(this.verticalFiller+" "+ansis.bold.red(`${t.error} ${translatedMessage}`)) + else if (msg.type == "warning") finalComponents.push(this.verticalFiller+" "+ansis.bold.yellow(`${t.warning} ${translatedMessage}`)) + else if (msg.type == "info") finalComponents.push(this.verticalFiller+" "+ansis.bold.blue(`${t.info} ${translatedMessage}`)) + + const pathSplitter = msg.path ? ":" : "" + finalComponents.push(this.verticalFiller+" "+ansis.bold((t.dataPath)+this.descriptionSeparator)+ansis.cyan(`${ansis.magenta(msg.filepath+pathSplitter)} ${msg.path}`)) + if (msg.locationDocs) finalComponents.push(this.verticalFiller+" "+ansis.bold(t.dataDocs+this.descriptionSeparator)+ansis.italic.gray(msg.locationDocs)) + if (msg.messageDocs) finalComponents.push(this.verticalFiller+" "+ansis.bold(t.dataMessage+this.descriptionSeparator)+ansis.italic.gray(msg.messageDocs)) + if (index != data.messages.length-1) finalComponents.push(this.verticalFiller) + }) + } + + //bottom + finalComponents.push(this.verticalFiller) + finalBottom.forEach((text) => { + if (text.length < 1) return + finalComponents.push(this.verticalFiller+" "+text) + }) + + //footer + finalComponents.push(this.#getHorizontalDivider(borderLength+4)) + if (!this.disableFooter){ + finalFooter.forEach((text) => { + if (text.length < 1) return + finalComponents.push(this.#createBlockFromText(text,borderLength)) + }) + finalComponents.push(this.#getHorizontalDivider(borderLength+4)) + } + + //return all components + return finalComponents + } + /**Get the length of the longest string in the array. */ + #getLongestLength(text:string[]): number { + let finalLength = 0 + text.forEach((t) => { + const l = ansis.strip(t).length + if (l > finalLength) finalLength = l + }) + + return finalLength + } + /**Get a horizontal divider used between different parts of the config checker result. */ + #getHorizontalDivider(width:number): string { + if (width > 2) width = width-2 + else return this.verticalFiller+this.verticalFiller + let divider = this.verticalFiller + this.horizontalFiller.repeat(width) + this.verticalFiller + return divider + } + /**Create a block of text with a vertical divider on the left & right side. */ + #createBlockFromText(text:string,width:number): string { + if (width < 3) return this.verticalFiller+this.verticalFiller + let newWidth = width-ansis.strip(text).length+1 + let final = this.verticalFiller+" "+text+" ".repeat(newWidth)+this.verticalFiller + return final + } +} + +/**## ODCheckerTranslationRegisterOtherIds_Default `type` + * This type is an array of ids available in the `ODCheckerTranslationRegister_Default` class. + * It's used to generate typescript declarations for this class. + */ +export type ODCheckerTranslationRegisterOtherIds_Default = ( + "openticket:header-openticket"| + "openticket:header-configchecker"| + "openticket:header-description"| + "openticket:type-error"| + "openticket:type-warning"| + "openticket:type-info"| + "openticket:data-path"| + "openticket:data-docs"| + "openticket:data-message"| + "openticket:compact-information"| + "openticket:footer-error"| + "openticket:footer-warning"| + "openticket:footer-support" +) + +/**## ODCheckerTranslationRegisterMessageIds_Default `type` + * This type is an array of ids available in the `ODCheckerTranslationRegister_Default` class. + * It's used to generate typescript declarations for this class. + */ +export type ODCheckerTranslationRegisterMessageIds_Default = ( + "openticket:invalid-type"| + "openticket:property-missing"| + "openticket:property-optional"| + "openticket:object-disabled"| + "openticket:null-invalid"| + "openticket:switch-invalid-type"| + "openticket:object-switch-invalid-type"| + + "openticket:string-too-short"| + "openticket:string-too-long"| + "openticket:string-length-invalid"| + "openticket:string-starts-with"| + "openticket:string-ends-with"| + "openticket:string-contains"| + "openticket:string-choices"| + "openticket:string-regex"| + + "openticket:number-too-short"| + "openticket:number-too-long"| + "openticket:number-length-invalid"| + "openticket:number-too-small"| + "openticket:number-too-large"| + "openticket:number-not-equal"| + "openticket:number-step"| + "openticket:number-step-offset"| + "openticket:number-starts-with"| + "openticket:number-ends-with"| + "openticket:number-contains"| + "openticket:number-choices"| + "openticket:number-float"| + "openticket:number-negative"| + "openticket:number-positive"| + "openticket:number-zero"| + + "openticket:boolean-true"| + "openticket:boolean-false"| + + "openticket:array-empty-disabled"| + "openticket:array-empty-required"| + "openticket:array-too-short"| + "openticket:array-too-long"| + "openticket:array-length-invalid"| + "openticket:array-invalid-types"| + "openticket:array-double"| + + "openticket:discord-invalid-id"| + "openticket:discord-invalid-id-options"| + "openticket:discord-invalid-token"| + "openticket:color-invalid"| + "openticket:emoji-too-short"| + "openticket:emoji-too-long"| + "openticket:emoji-custom"| + "openticket:emoji-invalid"| + "openticket:url-invalid"| + "openticket:url-invalid-http"| + "openticket:url-invalid-protocol"| + "openticket:url-invalid-hostname"| + "openticket:url-invalid-extension"| + "openticket:url-invalid-path"| + "openticket:id-not-unique"| + "openticket:id-non-existent"| + + "openticket:invalid-language"| + "openticket:invalid-button"| + "openticket:unused-option"| + "openticket:unused-question"| + "openticket:dropdown-option" +) + +/**## ODCheckerTranslationRegister_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODCheckerTranslationRegister class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.checkers.translation`! + */ +export class ODCheckerTranslationRegister_Default extends ODCheckerTranslationRegister { + get(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default): string + get(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default): string + get(type:"message"|"other", id:string): string|null + + get(type:"message"|"other", id:string): string|null { + return super.get(type,id) + } + + set(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default, translation:string): boolean + set(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default, translation:string): boolean + set(type:"message"|"other", id:string, translation:string): boolean + + set(type:"message"|"other", id:string, translation:string): boolean { + return super.set(type,id,translation) + } + + delete(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default): boolean + delete(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default): boolean + delete(type:"message"|"other", id:string): boolean + + delete(type:"message"|"other", id:string): boolean { + return super.delete(type,id) + } + + quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:ODCheckerTranslationRegisterOtherIds_Default|ODCheckerTranslationRegisterMessageIds_Default) + quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:string) + + quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:ODCheckerTranslationRegisterOtherIds_Default|ODCheckerTranslationRegisterMessageIds_Default|string){ + super.quickTranslate(manager,translationId,type,id) + } +} + +/**## ODCheckerFunctionManagerIds_Default `type` + * This type is an array of ids available in the `ODCheckerFunctionManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODCheckerFunctionManagerIds_Default { + "openticket:unused-options":ODCheckerFunction, + "openticket:dropdown-options":ODCheckerFunction +} + +/**## ODCheckerFunctionManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODCheckerFunctionManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.checkers.functions`! + */ +export class ODCheckerFunctionManager_Default extends ODCheckerFunctionManager { + get(id:CheckerFunctionId): ODCheckerManagerIds_Default[CheckerFunctionId] + get(id:ODValidId): ODCheckerFunction|null + + get(id:ODValidId): ODCheckerFunction|null { + return super.get(id) + } + + remove(id:CheckerFunctionId): ODCheckerManagerIds_Default[CheckerFunctionId] + remove(id:ODValidId): ODCheckerFunction|null + + remove(id:ODValidId): ODCheckerFunction|null { + return super.remove(id) + } + + exists(id:keyof ODCheckerFunctionManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/client.ts b/src/core/api/defaults/client.ts new file mode 100644 index 0000000..d03d26f --- /dev/null +++ b/src/core/api/defaults/client.ts @@ -0,0 +1,147 @@ +/////////////////////////////////////// +//DEFAULT CLIENT MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODClientManager, ODSlashCommand, ODTextCommand, ODSlashCommandManager, ODTextCommandManager, ODSlashCommandInteractionCallback, ODTextCommandInteractionCallback } from "../modules/client" + +/**## ODClientManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODClientManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.client`! + */ +export class ODClientManager_Default extends ODClientManager { + declare slashCommands: ODSlashCommandManager_Default + declare textCommands: ODTextCommandManager_Default +} + +/**## ODSlashCommandManagerIds_Default `type` + * This type is an array of ids available in the `ODSlashCommandManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODSlashCommandManagerIds_Default { + "openticket:help":ODSlashCommand, + "openticket:panel":ODSlashCommand, + "openticket:ticket":ODSlashCommand, + "openticket:close":ODSlashCommand, + "openticket:delete":ODSlashCommand, + "openticket:reopen":ODSlashCommand, + "openticket:claim":ODSlashCommand, + "openticket:unclaim":ODSlashCommand, + "openticket:pin":ODSlashCommand, + "openticket:unpin":ODSlashCommand, + "openticket:move":ODSlashCommand, + "openticket:rename":ODSlashCommand, + "openticket:add":ODSlashCommand, + "openticket:remove":ODSlashCommand, + "openticket:blacklist":ODSlashCommand, + "openticket:stats":ODSlashCommand, + "openticket:clear":ODSlashCommand, + "openticket:autoclose":ODSlashCommand, + "openticket:autodelete":ODSlashCommand, +} + +/**## ODSlashCommandManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODSlashCommandManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.client.slashCommands`! + */ +export class ODSlashCommandManager_Default extends ODSlashCommandManager { + get(id:SlashCommandId): ODSlashCommandManagerIds_Default[SlashCommandId] + get(id:ODValidId): ODSlashCommand|null + + get(id:ODValidId): ODSlashCommand|null { + return super.get(id) + } + + remove(id:SlashCommandId): ODSlashCommandManagerIds_Default[SlashCommandId] + remove(id:ODValidId): ODSlashCommand|null + + remove(id:ODValidId): ODSlashCommand|null { + return super.remove(id) + } + + exists(id:keyof ODSlashCommandManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + onInteraction(commandName:keyof ODSlashCommandManagerIds_Default, callback:ODSlashCommandInteractionCallback): void + onInteraction(commandName:string|RegExp, callback:ODSlashCommandInteractionCallback): void + + onInteraction(commandName:string|RegExp, callback:ODSlashCommandInteractionCallback): void { + return super.onInteraction(commandName,callback) + } +} + +/**## ODTextCommandManagerIds_Default `type` + * This type is an array of ids available in the `ODTextCommandManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODTextCommandManagerIds_Default { + "openticket:help":ODTextCommand, + "openticket:panel":ODTextCommand, + "openticket:close":ODTextCommand, + "openticket:delete":ODTextCommand, + "openticket:reopen":ODTextCommand, + "openticket:claim":ODTextCommand, + "openticket:unclaim":ODTextCommand, + "openticket:pin":ODTextCommand, + "openticket:unpin":ODTextCommand, + "openticket:move":ODTextCommand, + "openticket:rename":ODTextCommand, + "openticket:add":ODTextCommand, + "openticket:remove":ODTextCommand, + "openticket:blacklist-view":ODTextCommand, + "openticket:blacklist-add":ODTextCommand, + "openticket:blacklist-remove":ODTextCommand, + "openticket:blacklist-get":ODTextCommand, + "openticket:stats-global":ODTextCommand, + "openticket:stats-reset":ODTextCommand, + "openticket:stats-ticket":ODTextCommand, + "openticket:stats-user":ODTextCommand, + "openticket:clear":ODTextCommand, + "openticket:autoclose-disable":ODTextCommand, + "openticket:autoclose-enable":ODTextCommand, + "openticket:autodelete-disable":ODTextCommand, + "openticket:autodelete-enable":ODTextCommand +} + +/**## ODTextCommandManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODTextCommandManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.client.textCommands`! + */ +export class ODTextCommandManager_Default extends ODTextCommandManager { + get(id:TextCommandId): ODTextCommandManagerIds_Default[TextCommandId] + get(id:ODValidId): ODTextCommand|null + + get(id:ODValidId): ODTextCommand|null { + return super.get(id) + } + + remove(id:TextCommandId): ODTextCommandManagerIds_Default[TextCommandId] + remove(id:ODValidId): ODTextCommand|null + + remove(id:ODValidId): ODTextCommand|null { + return super.remove(id) + } + + exists(id:keyof ODTextCommandManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + onInteraction(prefix:string, id:keyof ODTextCommandManagerIds_Default, callback:ODTextCommandInteractionCallback): void + onInteraction(commandPrefix:string, commandName:string|RegExp, callback:ODTextCommandInteractionCallback): void + + onInteraction(commandPrefix:string, commandName:string|RegExp, callback:ODTextCommandInteractionCallback): void { + return super.onInteraction(commandPrefix,commandName,callback) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/code.ts b/src/core/api/defaults/code.ts new file mode 100644 index 0000000..4275298 --- /dev/null +++ b/src/core/api/defaults/code.ts @@ -0,0 +1,56 @@ +/////////////////////////////////////// +//DEFAULT CODE MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODCode, ODCodeManager } from "../modules/code" + +/**## ODCodeManagerIds_Default `type` + * This type is an array of ids available in the `ODCodeManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODCodeManagerIds_Default { + "openticket:command-error-handling":ODCode, + "openticket:start-listening-interactions":ODCode, + "openticket:panel-database-cleaner":ODCode, + "openticket:suffix-database-cleaner":ODCode, + "openticket:option-database-cleaner":ODCode, + "openticket:user-database-cleaner":ODCode, + "openticket:ticket-database-cleaner":ODCode, + "openticket:panel-auto-update":ODCode, + "openticket:ticket-saver":ODCode, + "openticket:blacklist-saver":ODCode, + "openticket:auto-role-on-join":ODCode, + "openticket:autoclose-timeout":ODCode, + "openticket:autoclose-leave":ODCode, + "openticket:autodelete-timeout":ODCode, + "openticket:autodelete-leave":ODCode +} + +/**## ODCodeManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODCodeManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.code`! + */ +export class ODCodeManager_Default extends ODCodeManager { + get(id:CodeId): ODCodeManagerIds_Default[CodeId] + get(id:ODValidId): ODCode|null + + get(id:ODValidId): ODCode|null { + return super.get(id) + } + + remove(id:CodeId): ODCodeManagerIds_Default[CodeId] + remove(id:ODValidId): ODCode|null + + remove(id:ODValidId): ODCode|null { + return super.remove(id) + } + + exists(id:keyof ODCodeManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/config.ts b/src/core/api/defaults/config.ts new file mode 100644 index 0000000..e4db760 --- /dev/null +++ b/src/core/api/defaults/config.ts @@ -0,0 +1,470 @@ +/////////////////////////////////////// +//DEFAULT CONFIG MODULE +/////////////////////////////////////// +import { ODValidButtonColor, ODValidId } from "../modules/base" +import * as discord from "discord.js" +import { ODConfigManager, ODConfig, ODJsonConfig } from "../modules/config" +import { ODClientActivityStatus, ODClientActivityType } from "../modules/client" +import { OTRoleUpdateMode } from "../openticket/role" + +/**## ODConfigManagerIds_Default `type` + * This type is an array of ids available in the `ODConfigManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODConfigManagerIds_Default { + "openticket:general":ODJsonConfig_DefaultGeneral, + "openticket:options":ODJsonConfig_DefaultOptions, + "openticket:panels":ODJsonConfig_DefaultPanels, + "openticket:questions":ODJsonConfig_DefaultQuestions, + "openticket:transcripts":ODJsonConfig_DefaultTranscripts +} + +/**## ODConfigManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODConfigManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.configs`! + */ +export class ODConfigManager_Default extends ODConfigManager { + get(id:ConfigId): ODConfigManagerIds_Default[ConfigId] + get(id:ODValidId): ODConfig|null + + get(id:ODValidId): ODConfig|null { + return super.get(id) + } + + remove(id:ConfigId): ODConfigManagerIds_Default[ConfigId] + remove(id:ODValidId): ODConfig|null + + remove(id:ODValidId): ODConfig|null { + return super.remove(id) + } + + exists(id:keyof ODConfigManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODJsonConfig_DefaultStatusType `interface` + * This interface is an object which has all properties for the status object in the `general.json` config! + */ +export interface ODJsonConfig_DefaultStatusType { + enabled:boolean, + type:Exclude, + text:string, + status:ODClientActivityStatus +} + +/**## ODJsonConfig_DefaultMessageSettingsType `interface` + * This interface is an object which has all properties for the system/messages/... object in the `general.json` config! + */ +export interface ODJsonConfig_DefaultMessageSettingsType { + dm:boolean, + logs:boolean +} + +/**## ODJsonConfig_DefaultCmdPermissionSettingsType `type` + * This type is a collection of command permission settings for the system/permissions/... object in the `general.json` config! + */ +export type ODJsonConfig_DefaultCmdPermissionSettingsType = "admin"|"everyone"|"none"|string + +/**## ODJsonConfig_DefaultGeneral `default_class` + * This is a special class that adds type definitions & typescript to the ODJsonConfig class. + * It doesn't add any extra features! + * + * This default class is made for the `general.json` config! + */ +export class ODJsonConfig_DefaultGeneral extends ODJsonConfig { + declare data: { + _INFO:{ + support:string, + discord:string, + version:string + }, + + token:string, + tokenFromENV:boolean, + + mainColor:discord.ColorResolvable, + language:string, + prefix:string, + serverId:string, + globalAdmins:string[], + + slashCommands:boolean, + textCommands:boolean, + + status:ODJsonConfig_DefaultStatusType, + + system:{ + removeParticipantsOnClose:boolean, + replyOnTicketCreation:boolean, + replyOnReactionRole:boolean, + useTranslatedConfigChecker:boolean, + preferSlashOverText:boolean, + sendErrorOnUnknownCommand:boolean, + questionFieldsInCodeBlock:boolean, + disableVerifyBars:boolean, + useRedErrorEmbeds:boolean, + emojiStyle:"before"|"after"|"double"|"disabled", + + enableTicketClaimButtons:boolean, + enableTicketCloseButtons:boolean, + enableTicketPinButtons:boolean, + enableTicketDeleteButtons:boolean, + enableTicketActionWithReason:boolean, + enableDeleteWithoutTranscript:boolean, + + logs:{ + enabled:boolean, + channel:string + }, + + limits:{ + enabled:boolean, + globalMaximum:number, + userMaximum:number + }, + + permissions:{ + help:ODJsonConfig_DefaultCmdPermissionSettingsType, + panel:ODJsonConfig_DefaultCmdPermissionSettingsType, + ticket:ODJsonConfig_DefaultCmdPermissionSettingsType, + close:ODJsonConfig_DefaultCmdPermissionSettingsType, + delete:ODJsonConfig_DefaultCmdPermissionSettingsType, + reopen:ODJsonConfig_DefaultCmdPermissionSettingsType, + claim:ODJsonConfig_DefaultCmdPermissionSettingsType, + unclaim:ODJsonConfig_DefaultCmdPermissionSettingsType, + pin:ODJsonConfig_DefaultCmdPermissionSettingsType, + unpin:ODJsonConfig_DefaultCmdPermissionSettingsType, + move:ODJsonConfig_DefaultCmdPermissionSettingsType, + rename:ODJsonConfig_DefaultCmdPermissionSettingsType, + add:ODJsonConfig_DefaultCmdPermissionSettingsType, + remove:ODJsonConfig_DefaultCmdPermissionSettingsType, + blacklist:ODJsonConfig_DefaultCmdPermissionSettingsType, + stats:ODJsonConfig_DefaultCmdPermissionSettingsType, + clear:ODJsonConfig_DefaultCmdPermissionSettingsType, + autoclose:ODJsonConfig_DefaultCmdPermissionSettingsType, + autodelete:ODJsonConfig_DefaultCmdPermissionSettingsType + }, + + messages:{ + creation:ODJsonConfig_DefaultMessageSettingsType, + closing:ODJsonConfig_DefaultMessageSettingsType, + deleting:ODJsonConfig_DefaultMessageSettingsType, + reopening:ODJsonConfig_DefaultMessageSettingsType, + claiming:ODJsonConfig_DefaultMessageSettingsType, + pinning:ODJsonConfig_DefaultMessageSettingsType, + adding:ODJsonConfig_DefaultMessageSettingsType, + removing:ODJsonConfig_DefaultMessageSettingsType, + renaming:ODJsonConfig_DefaultMessageSettingsType, + moving:ODJsonConfig_DefaultMessageSettingsType, + blacklisting:ODJsonConfig_DefaultMessageSettingsType, + roleAdding:ODJsonConfig_DefaultMessageSettingsType, + roleRemoving:ODJsonConfig_DefaultMessageSettingsType + } + } + } +} + +/**## ODJsonConfig_DefaultOptionType `interface` + * This interface is an object which has all basic properties for options in the `options.json` config! + */ +export interface ODJsonConfig_DefaultOptionType { + id:string, + name:string, + description:string, + type:"ticket"|"website"|"role", + button:{ + emoji:string, + label:string + } +} + +/**## ODJsonConfig_DefaultOptionButtonSettingsType `interface` + * This interface is an object which has all button settings for ticket options in the `options.json` config! + */ +export interface ODJsonConfig_DefaultOptionButtonSettingsType { + emoji:string, + label:string, + color:ODValidButtonColor +} + +/**## ODJsonConfig_DefaultOptionEmbedSettingsType `interface` + * This interface is an object which has all message embed settings for ticket options in the `options.json` config! + */ +export interface ODJsonConfig_DefaultOptionEmbedSettingsType { + enabled:boolean, + title:string, + description:string, + customColor:string, + + image:string, + thumbnail:string, + fields:{name:string, value:string, inline:boolean}[], + timestamp:boolean +} + +/**## ODJsonConfig_DefaultOptionPingSettingsType `interface` + * This interface is an object which has all message ping settings for ticket options in the `options.json` config! + */ +export interface ODJsonConfig_DefaultOptionPingSettingsType { + "@here":boolean, + "@everyone":boolean, + custom:string[] +} + +/**## ODJsonConfig_DefaultOptionTicketType `interface` + * This interface is an object which has all ticket properties for options in the `options.json` config! + */ +export interface ODJsonConfig_DefaultOptionTicketType extends ODJsonConfig_DefaultOptionType { + type:"ticket", + button:ODJsonConfig_DefaultOptionButtonSettingsType, + ticketAdmins:string[], + readonlyAdmins:string[], + allowCreationByBlacklistedUsers:boolean, + questions:string[], + channel:{ + prefix:string, + suffix:"user-name"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed", + category:string, + closedCategory:string, + backupCategory:string, + claimedCategory:{user:string, category:string}[], + description:string + }, + dmMessage:{ + enabled:boolean, + text:string, + embed:ODJsonConfig_DefaultOptionEmbedSettingsType + }, + ticketMessage:{ + enabled:boolean, + text:string, + embed:ODJsonConfig_DefaultOptionEmbedSettingsType, + ping:ODJsonConfig_DefaultOptionPingSettingsType + }, + autoclose:{ + enableInactiveHours:boolean, + inactiveHours:number, + enableUserLeave:boolean, + disableOnClaim:boolean + }, + autodelete:{ + enableInactiveDays:boolean, + inactiveDays:number, + enableUserLeave:boolean, + disableOnClaim:boolean + }, + cooldown:{ + enabled:boolean, + cooldownMinutes:number + }, + limits:{ + enabled:boolean, + globalMaximum:number, + userMaximum:number + } +} + +/**## ODJsonConfig_DefaultOptionWebsiteType `interface` + * This interface is an object which has all website properties for options in the `options.json` config! + */ +export interface ODJsonConfig_DefaultOptionWebsiteType extends ODJsonConfig_DefaultOptionType { + type:"website", + url:string +} + +/**## ODJsonConfig_DefaultOptionRoleType `interface` + * This interface is an object which has all reaction role properties for options in the `options.json` config! + */ +export interface ODJsonConfig_DefaultOptionRoleType extends ODJsonConfig_DefaultOptionType { + type:"role", + button:ODJsonConfig_DefaultOptionButtonSettingsType, + roles:string[], + mode:OTRoleUpdateMode, + removeRolesOnAdd:string[], + addOnMemberJoin:boolean +} + +/**## ODJsonConfig_DefaultOptions `default_class` + * This is a special class that adds type definitions & typescript to the ODJsonConfig class. + * It doesn't add any extra features! + * + * This default class is made for the `options.json` config! + */ +export class ODJsonConfig_DefaultOptions extends ODJsonConfig { + declare data: ( + ODJsonConfig_DefaultOptionTicketType| + ODJsonConfig_DefaultOptionWebsiteType| + ODJsonConfig_DefaultOptionRoleType + )[] +} + +/**## ODJsonConfig_DefaultPanelEmbedSettingsType `interface` + * This interface is an object which has all message embed settings for panels in the `panels.json` config! + */ +export interface ODJsonConfig_DefaultPanelEmbedSettingsType { + enabled:boolean, + title:string, + description:string, + + customColor:string, + url:string, + + image:string, + thumbnail:string, + + footer:string, + fields:{name:string,value:string,inline:boolean}[], + timestamp:boolean +} + +/**## ODJsonConfig_DefaultPanelType `interface` + * This interface is an object which has all properties for panels in the `panels.json` config! + */ +export interface ODJsonConfig_DefaultPanelType { + id:string, + name:string, + dropdown:boolean, + options:string[], + + text:string, + embed:ODJsonConfig_DefaultPanelEmbedSettingsType, + settings:{ + dropdownPlaceholder:string, + + enableMaxTicketsWarningInText:boolean, + enableMaxTicketsWarningInEmbed:boolean, + + describeOptionsLayout:"simple"|"normal"|"detailed", + describeOptionsCustomTitle:string, + describeOptionsInText:boolean, + describeOptionsInEmbedFields:boolean, + describeOptionsInEmbedDescription:boolean + } +} + +/**## ODJsonConfig_DefaultPanels `default_class` + * This is a special class that adds type definitions & typescript to the ODJsonConfig class. + * It doesn't add any extra features! + * + * This default class is made for the `panels.json` config! + */ +export class ODJsonConfig_DefaultPanels extends ODJsonConfig { + declare data: ODJsonConfig_DefaultPanelType[] +} + +/**## ODJsonConfig_DefaultShortQuestionType `interface` + * This interface is an object which has all properties for short questions in the `questions.json` config! + */ +export interface ODJsonConfig_DefaultShortQuestionType { + id:string, + name:string, + type:"short", + + required:boolean, + placeholder:string, + length:{ + enabled:boolean, + min:number, + max:number + } +} + +/**## ODJsonConfig_DefaultParagraphQuestionType `interface` + * This interface is an object which has all properties for paragraph questions in the `questions.json` config! + */ +export interface ODJsonConfig_DefaultParagraphQuestionType { + id:string, + name:string, + type:"paragraph", + + required:boolean, + placeholder:string, + length:{ + enabled:boolean, + min:number, + max:number + } +} + +/**## ODJsonConfig_DefaultQuestions `default_class` + * This is a special class that adds type definitions & typescript to the ODJsonConfig class. + * It doesn't add any extra features! + * + * This default class is made for the `questions.json` config! + */ +export class ODJsonConfig_DefaultQuestions extends ODJsonConfig { + declare data: ( + ODJsonConfig_DefaultShortQuestionType| + ODJsonConfig_DefaultParagraphQuestionType + )[] +} + +/**## ODJsonConfig_DefaultTranscripts `default_class` + * This is a special class that adds type definitions & typescript to the ODJsonConfig class. + * It doesn't add any extra features! + * + * This default class is made for the `transcripts.json` config! + */ +export class ODJsonConfig_DefaultTranscripts extends ODJsonConfig { + declare data: { + general:{ + enabled:boolean, + + enableChannel:boolean, + enableCreatorDM:boolean, + enableParticipantDM:boolean, + enableActiveAdminDM:boolean, + enableEveryAdminDM:boolean, + + channel:string, + mode:"html"|"text" + }, + embedSettings:{ + customColor:string, + listAllParticipants:boolean, + includeTicketStats:boolean + }, + textTranscriptStyle:{ + layout:"simple"|"normal"|"detailed", + includeStats:boolean, + includeIds:boolean, + includeEmbeds:boolean, + includeFiles:boolean, + includeBotMessages:boolean, + + fileMode:"custom"|"channel-name"|"channel-id"|"user-name"|"user-id", + customFileName:string + }, + htmlTranscriptStyle:{ + background:{ + enableCustomBackground:boolean, + backgroundColor:string, + backgroundImage:string + }, + header:{ + enableCustomHeader:boolean, + backgroundColor:string, + decoColor:string, + textColor:string + }, + stats:{ + enableCustomStats:false, + backgroundColor:string, + keyTextColor:string, + valueTextColor:string, + hideBackgroundColor:string, + hideTextColor:string + }, + favicon:{ + enableCustomFavicon:boolean, + imageUrl:string + } + } + } +} \ No newline at end of file diff --git a/src/core/api/defaults/console.ts b/src/core/api/defaults/console.ts new file mode 100644 index 0000000..58f6feb --- /dev/null +++ b/src/core/api/defaults/console.ts @@ -0,0 +1,42 @@ +/////////////////////////////////////// +//DEFAULT CONSOLE MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODLiveStatusUrlSource, ODLiveStatusManager, ODLiveStatusSource } from "../modules/console" + +/**## ODLiveStatusManagerIds_Default `type` + * This type is an array of ids available in the `ODLiveStatusManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODLiveStatusManagerIds_Default { + "openticket:default-djdj-dev":ODLiveStatusUrlSource +} + +/**## ODLiveStatusManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODLiveStatusManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.livestatus`! + */ +export class ODLiveStatusManager_Default extends ODLiveStatusManager { + get(id:LiveStatusId): ODLiveStatusManagerIds_Default[LiveStatusId] + get(id:ODValidId): ODLiveStatusSource|null + + get(id:ODValidId): ODLiveStatusSource|null { + return super.get(id) + } + + remove(id:LiveStatusId): ODLiveStatusManagerIds_Default[LiveStatusId] + remove(id:ODValidId): ODLiveStatusSource|null + + remove(id:ODValidId): ODLiveStatusSource|null { + return super.remove(id) + } + + exists(id:keyof ODLiveStatusManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/cooldown.ts b/src/core/api/defaults/cooldown.ts new file mode 100644 index 0000000..0a0c1a2 --- /dev/null +++ b/src/core/api/defaults/cooldown.ts @@ -0,0 +1,42 @@ +/////////////////////////////////////// +//DEFAULT COOLDOWN MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODCooldown, ODCooldownManager } from "../modules/cooldown" + +/**## ODCooldownManagerIds_Default `type` + * This type is an array of ids available in the `ODCooldownManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODCooldownManagerIds_Default { + +} + +/**## ODCooldownManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODCooldownManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.cooldowns`! + */ +export class ODCooldownManager_Default extends ODCooldownManager { + get(id:CooldownId): ODCooldownManagerIds_Default[CooldownId] + get(id:ODValidId): ODCooldown|null + + get(id:ODValidId): ODCooldown|null { + return super.get(id) + } + + remove(id:CooldownId): ODCooldownManagerIds_Default[CooldownId] + remove(id:ODValidId): ODCooldown|null + + remove(id:ODValidId): ODCooldown|null { + return super.remove(id) + } + + exists(id:keyof ODCooldownManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/database.ts b/src/core/api/defaults/database.ts new file mode 100644 index 0000000..1805d90 --- /dev/null +++ b/src/core/api/defaults/database.ts @@ -0,0 +1,256 @@ +/////////////////////////////////////// +//DEFAULT DATABASE MODULE +/////////////////////////////////////// +import { ODValidId, ODValidJsonType } from "../modules/base" +import { ODDatabaseManager, ODDatabase, ODFormattedJsonDatabase } from "../modules/database" +import { ODTicketJson } from "../openticket/ticket" +import { ODOptionJson } from "../openticket/option" + +/**## ODDatabaseManagerIds_Default `type` + * This type is an array of ids available in the `ODDatabaseManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODDatabaseManagerIds_Default { + "openticket:global":ODFormattedJsonDatabase_DefaultGlobal, + "openticket:stats":ODFormattedJsonDatabase, + "openticket:tickets":ODFormattedJsonDatabase_DefaultTickets, + "openticket:users":ODFormattedJsonDatabase_DefaultUsers, + "openticket:options":ODFormattedJsonDatabase_DefaultOptions, +} + +/**## ODDatabaseManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODDatabaseManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.databases`! + */ +export class ODDatabaseManager_Default extends ODDatabaseManager { + get(id:DatabaseId): ODDatabaseManagerIds_Default[DatabaseId] + get(id:ODValidId): ODDatabase|null + + get(id:ODValidId): ODDatabase|null { + return super.get(id) + } + + remove(id:DatabaseId): ODDatabaseManagerIds_Default[DatabaseId] + remove(id:ODValidId): ODDatabase|null + + remove(id:ODValidId): ODDatabase|null { + return super.remove(id) + } + + exists(id:keyof ODDatabaseManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODFormattedJsonDatabaseIds_DefaultGlobal `type` + * This type is an array of ids available in the `ODFormattedJsonDatabase_DefaultGlobal` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODFormattedJsonDatabaseIds_DefaultGlobal { + "openticket:panel-update":string, + "openticket:option-suffix-counter":number, + "openticket:option-suffix-history":string[], + "openticket:last-version":string +} + +/**## ODFormattedJsonDatabase_DefaultGlobal `default_class` + * This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class. + * It doesn't add any extra features! + * + * This default class is made for the `global.json` database! + */ +export class ODFormattedJsonDatabase_DefaultGlobal extends ODFormattedJsonDatabase { + set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]): boolean + set(category:string, key:string, value:ODValidJsonType): boolean + + set(category:string, key:string, value:ODValidJsonType): boolean { + return super.set(category,key,value) + } + + get(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]|undefined + get(category:string, key:string): ODValidJsonType|undefined + + get(category:string, key:string): ODValidJsonType|undefined { + return super.get(category,key) + } + + delete(category:CategoryId, key:string): boolean + delete(category:string, key:string): boolean + + delete(category:string, key:string): boolean { + return super.delete(category,key) + } + + exists(category:keyof ODFormattedJsonDatabaseIds_DefaultGlobal, key:string): boolean + exists(category:string, key:string): boolean + + exists(category:string, key:string): boolean { + return super.exists(category,key) + } + + getCategory(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]}[]|undefined + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined + + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + return super.getCategory(category) + } +} + +/**## ODFormattedJsonDatabaseIds_DefaultTickets `type` + * This type is an array of ids available in the `ODDatabaseManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODFormattedJsonDatabaseIds_DefaultTickets { + "openticket:ticket":ODTicketJson +} + +/**## ODFormattedJsonDatabase_DefaultTickets `default_class` + * This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class. + * It doesn't add any extra features! + * + * This default class is made for the `tickets.json` database! + */ +export class ODFormattedJsonDatabase_DefaultTickets extends ODFormattedJsonDatabase { + set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]): boolean + set(category:string, key:string, value:ODValidJsonType): boolean + + set(category:string, key:string, value:ODValidJsonType): boolean { + return super.set(category,key,value) + } + + get(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]|undefined + get(category:string, key:string): ODValidJsonType|undefined + + get(category:string, key:string): ODValidJsonType|undefined { + return super.get(category,key) + } + + delete(category:CategoryId, key:string): boolean + delete(category:string, key:string): boolean + + delete(category:string, key:string): boolean { + return super.delete(category,key) + } + + exists(category:keyof ODFormattedJsonDatabaseIds_DefaultTickets, key:string): boolean + exists(category:string, key:string): boolean + + exists(category:string, key:string): boolean { + return super.exists(category,key) + } + + getCategory(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]}[]|undefined + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined + + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + return super.getCategory(category) + } +} + +/**## ODFormattedJsonDatabaseIds_DefaultUsers `type` + * This type is an array of ids available in the `ODDatabaseManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODFormattedJsonDatabaseIds_DefaultUsers { + "openticket:blacklist":ODTicketJson +} + +/**## ODFormattedJsonDatabase_DefaultUsers `default_class` + * This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class. + * It doesn't add any extra features! + * + * This default class is made for the `users.json` database! + */ +export class ODFormattedJsonDatabase_DefaultUsers extends ODFormattedJsonDatabase { + set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]): boolean + set(category:string, key:string, value:ODValidJsonType): boolean + + set(category:string, key:string, value:ODValidJsonType): boolean { + return super.set(category,key,value) + } + + get(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]|undefined + get(category:string, key:string): ODValidJsonType|undefined + + get(category:string, key:string): ODValidJsonType|undefined { + return super.get(category,key) + } + + delete(category:CategoryId, key:string): boolean + delete(category:string, key:string): boolean + + delete(category:string, key:string): boolean { + return super.delete(category,key) + } + + exists(category:keyof ODFormattedJsonDatabaseIds_DefaultUsers, key:string): boolean + exists(category:string, key:string): boolean + + exists(category:string, key:string): boolean { + return super.exists(category,key) + } + + getCategory(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]}[]|undefined + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined + + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + return super.getCategory(category) + } +} + + +/**## ODFormattedJsonDatabaseIds_DefaultOptions `type` + * This type is an array of ids available in the `ODDatabaseManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODFormattedJsonDatabaseIds_DefaultOptions { + "openticket:used-option":ODOptionJson +} + +/**## ODFormattedJsonDatabase_DefaultOptions `default_class` + * This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class. + * It doesn't add any extra features! + * + * This default class is made for the `options.json` database! + */ +export class ODFormattedJsonDatabase_DefaultOptions extends ODFormattedJsonDatabase { + set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]): boolean + set(category:string, key:string, value:ODValidJsonType): boolean + + set(category:string, key:string, value:ODValidJsonType): boolean { + return super.set(category,key,value) + } + + get(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]|undefined + get(category:string, key:string): ODValidJsonType|undefined + + get(category:string, key:string): ODValidJsonType|undefined { + return super.get(category,key) + } + + delete(category:CategoryId, key:string): boolean + delete(category:string, key:string): boolean + + delete(category:string, key:string): boolean { + return super.delete(category,key) + } + + exists(category:keyof ODFormattedJsonDatabaseIds_DefaultOptions, key:string): boolean + exists(category:string, key:string): boolean + + exists(category:string, key:string): boolean { + return super.exists(category,key) + } + + getCategory(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]}[]|undefined + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined + + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + return super.getCategory(category) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts new file mode 100644 index 0000000..c9b02b1 --- /dev/null +++ b/src/core/api/defaults/event.ts @@ -0,0 +1,331 @@ +/////////////////////////////////////// +//DEFAULT EVENT MODULE +/////////////////////////////////////// +//BASE MODULES +import { ODPromiseVoid, ODValidId } from "../modules/base" +import { ODPluginClassManager, ODPluginEventManager, ODPluginManager } from "../modules/plugin" +import { ODConsoleManager, ODError } from "../modules/console" +import { ODCheckerResult, ODCheckerStorage } from "../modules/checker" +import { ODDefaultsManager } from "../modules/defaults" +import { ODLanguage } from "../modules/language" +import { ODClientActivityManager } from "../modules/client" +import { ODEvent, ODEventManager } from "../modules/event" +import * as discord from "discord.js" + +//DEFAULT MODULES +import { ODVersionManager_Default } from "./base" +import { ODConfigManager_Default} from "./config" +import { ODDatabaseManager_Default } from "./database" +import { ODFlagManager_Default } from "./flag" +import { ODSessionManager_Default } from "./session" +import { ODLanguageManager_Default } from "./language" +import { ODCheckerFunctionManager_Default, ODCheckerManager_Default, ODCheckerRenderer_Default, ODCheckerTranslationRegister_Default } from "./checker" +import { ODClientManager_Default, ODSlashCommandManager_Default, ODTextCommandManager_Default } from "./client" +import { ODBuilderManager_Default, ODButtonManager_Default, ODDropdownManager_Default, ODEmbedManager_Default, ODFileManager_Default, ODMessageManager_Default, ODModalManager_Default } from "./builder" +import { ODButtonResponderManager_Default, ODCommandResponderManager_Default, ODDropdownResponderManager_Default, ODModalResponderManager_Default, ODResponderManager_Default } from "./responder" +import { ODActionManager_Default } from "./action" +import { ODPermissionManager_Default } from "./permission" +import { ODHelpMenuManager_Default } from "./helpmenu" +import { ODStatsManager_Default } from "./stat" +import { ODCodeManager_Default } from "./code" +import { ODCooldownManager_Default } from "./cooldown" +import { ODPostManager_Default } from "./post" +import { ODVerifyBarManager_Default } from "./verifybar" +import { ODStartScreenManager_Default } from "./startscreen" +import { ODLiveStatusManager_Default } from "./console" + +//OPEN TICKET MODULES +import { ODOptionManager, ODTicketOption } from "../openticket/option" +import { ODPanel, ODPanelManager } from "../openticket/panel" +import { ODTicket, ODTicketClearFilter, ODTicketManager } from "../openticket/ticket" +import { ODQuestionManager } from "../openticket/question" +import { ODBlacklistManager } from "../openticket/blacklist" +import { ODTranscriptManager_Default } from "../openticket/transcript" +import { ODRole, ODRoleManager } from "../openticket/role" + +/**## ODEventIds_Default `type` + * This type is an array of ids available in the `ODEvent_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODEventIds_Default { + //error handling + "onErrorHandling": ODEvent_Default<(error:Error, origin:NodeJS.UncaughtExceptionOrigin) => ODPromiseVoid> + "afterErrorHandling": ODEvent_Default<(error:Error, origin:NodeJS.UncaughtExceptionOrigin, message:ODError) => ODPromiseVoid> + + //plugins + "afterPluginsLoaded": ODEvent_Default<(plugins:ODPluginManager) => ODPromiseVoid> + "onPluginClassLoad": ODEvent_Default<(classes:ODPluginClassManager, plugins:ODPluginManager) => ODPromiseVoid> + "afterPluginClassesLoaded": ODEvent_Default<(classes:ODPluginClassManager, plugins:ODPluginManager) => ODPromiseVoid> + "onPluginEventLoad": ODEvent_Default<(classes:ODPluginEventManager, plugins:ODPluginManager) => ODPromiseVoid> + "afterPluginEventsLoaded": ODEvent_Default<(classes:ODPluginEventManager, plugins:ODPluginManager) => ODPromiseVoid> + + + "onFlagLoad": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> + "afterFlagsLoaded": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> + "onFlagInit": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> + "afterFlagsInitiated": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> + + //configs + "onConfigLoad": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> + "afterConfigsLoaded": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> + + //databases + "onDatabaseLoad": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid> + "afterDatabasesLoaded": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid> + + //languages + "onLanguageLoad": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid> + "afterLanguagesLoaded": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid> + "onLanguageSelect": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid> + "afterLanguagesSelected": ODEvent_Default<(main:ODLanguage|null, backup:ODLanguage|null, languages:ODLanguageManager_Default) => ODPromiseVoid> + + //sessions + "onSessionLoad": ODEvent_Default<(languages:ODSessionManager_Default) => ODPromiseVoid> + "afterSessionsLoaded": ODEvent_Default<(languages:ODSessionManager_Default) => ODPromiseVoid> + + //config checkers + "onCheckerLoad": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid> + "afterCheckersLoaded": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid> + "onCheckerFunctionLoad": ODEvent_Default<(functions:ODCheckerFunctionManager_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid> + "afterCheckerFunctionsLoaded": ODEvent_Default<(functions:ODCheckerFunctionManager_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid> + "onCheckerExecute": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid> + "afterCheckersExecuted": ODEvent_Default<(result:ODCheckerResult, checkers:ODCheckerManager_Default) => ODPromiseVoid> + "onCheckerTranslationLoad": ODEvent_Default<(translations:ODCheckerTranslationRegister_Default, enabled:boolean, checkers:ODCheckerManager_Default) => ODPromiseVoid> + "afterCheckerTranslationsLoaded": ODEvent_Default<(translations:ODCheckerTranslationRegister_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid> + "onCheckerRender": ODEvent_Default<(renderer:ODCheckerRenderer_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid> + "afterCheckersRendered": ODEvent_Default<(renderer:ODCheckerRenderer_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid> + "onCheckerQuit": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid> + + //client configuration + "onClientLoad": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid> + "afterClientLoaded": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid> + "onClientInit": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid> + "afterClientInitiated": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid> + "onClientReady": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid> + "afterClientReady": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid> + "onClientActivityLoad": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid> + "afterClientActivityLoaded": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid> + "onClientActivityInit": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid> + "afterClientActivityInitiated": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid> + + //client slash commands + "onSlashCommandLoad": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid> + "afterSlashCommandsLoaded": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid> + "onSlashCommandRegister": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid> + "afterSlashCommandsRegistered": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid> + + //client text commands + "onTextCommandLoad": ODEvent_Default<(text:ODTextCommandManager_Default, client:ODClientManager_Default,) => ODPromiseVoid> + "afterTextCommandsLoaded": ODEvent_Default<(text:ODTextCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid> + + //questions + "onQuestionLoad": ODEvent_Default<(questions:ODQuestionManager) => ODPromiseVoid> + "afterQuestionsLoaded": ODEvent_Default<(questions:ODQuestionManager) => ODPromiseVoid> + + //options + "onOptionLoad": ODEvent_Default<(options:ODOptionManager) => ODPromiseVoid> + "afterOptionsLoaded": ODEvent_Default<(options:ODOptionManager) => ODPromiseVoid> + + //panels + "onPanelLoad": ODEvent_Default<(panels:ODPanelManager) => ODPromiseVoid> + "afterPanelsLoaded": ODEvent_Default<(panels:ODPanelManager) => ODPromiseVoid> + "onPanelSpawn": ODEvent_Default<(panel:ODPanel) => ODPromiseVoid> + "afterPanelSpawned": ODEvent_Default<(panel:ODPanel) => ODPromiseVoid> + + //tickets + "onTicketLoad": ODEvent_Default<(tickets:ODTicketManager) => ODPromiseVoid> + "afterTicketsLoaded": ODEvent_Default<(tickets:ODTicketManager) => ODPromiseVoid> + + //ticket creation + "onTicketChannelCreation": ODEvent_Default<(option:ODTicketOption, user:discord.User) => ODPromiseVoid> + "afterTicketChannelCreated": ODEvent_Default<(option:ODTicketOption, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid> + "onTicketChannelDeletion": ODEvent_Default<(ticket:ODTicket, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid> + "afterTicketChannelDeleted": ODEvent_Default<(ticket:ODTicket, user:discord.User) => ODPromiseVoid> + "onTicketPermissionsCreated": ODEvent_Default<(option:ODTicketOption, permissions:ODPermissionManager_Default, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid> + "afterTicketPermissionsCreated": ODEvent_Default<(option:ODTicketOption, permissions:ODPermissionManager_Default, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid> + "onTicketMainMessageCreated": ODEvent_Default<(ticket:ODTicket, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid> + "afterTicketMainMessageCreated": ODEvent_Default<(ticket:ODTicket, message:discord.Message, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid> + + //ticket actions + "onTicketCreate": ODEvent_Default<(creator:discord.User) => ODPromiseVoid> + "afterTicketCreated": ODEvent_Default<(ticket:ODTicket, creator:discord.User, channel:discord.GuildTextBasedChannel) => ODPromiseVoid> + "onTicketClose": ODEvent_Default<(ticket:ODTicket, closer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketClosed": ODEvent_Default<(ticket:ODTicket, closer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "onTicketReopen": ODEvent_Default<(ticket:ODTicket, reopener:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketReopened": ODEvent_Default<(ticket:ODTicket, reopener:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "onTicketDelete": ODEvent_Default<(ticket:ODTicket, deleter:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketDeleted": ODEvent_Default<(ticket:ODTicket, deleter:discord.User, reason:string|null) => ODPromiseVoid> + "onTicketMove": ODEvent_Default<(ticket:ODTicket, mover:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketMoved": ODEvent_Default<(ticket:ODTicket, mover:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "onTicketClaim": ODEvent_Default<(ticket:ODTicket, claimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketClaimed": ODEvent_Default<(ticket:ODTicket, claimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "onTicketUnclaim": ODEvent_Default<(ticket:ODTicket, unclaimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketUnclaimed": ODEvent_Default<(ticket:ODTicket, unclaimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "onTicketPin": ODEvent_Default<(ticket:ODTicket, pinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketPinned": ODEvent_Default<(ticket:ODTicket, pinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "onTicketUnpin": ODEvent_Default<(ticket:ODTicket, unpinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketUnpinned": ODEvent_Default<(ticket:ODTicket, unpinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "onTicketUserAdd": ODEvent_Default<(ticket:ODTicket, adder:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketUserAdded": ODEvent_Default<(ticket:ODTicket, adder:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "onTicketUserRemove": ODEvent_Default<(ticket:ODTicket, remover:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketUserRemoved": ODEvent_Default<(ticket:ODTicket, remover:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "onTicketRename": ODEvent_Default<(ticket:ODTicket, renamer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "afterTicketRenamed": ODEvent_Default<(ticket:ODTicket, renamer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid> + "onTicketsClear": ODEvent_Default<(tickets:ODTicket[], clearer:discord.User, channel:discord.GuildTextBasedChannel, filter:ODTicketClearFilter) => ODPromiseVoid> + "afterTicketsCleared": ODEvent_Default<(tickets:ODTicket[], clearer:discord.User, channel:discord.GuildTextBasedChannel, filter:ODTicketClearFilter) => ODPromiseVoid> + + //roles + "onRoleLoad": ODEvent_Default<(roles:ODRoleManager) => ODPromiseVoid> + "afterRolesLoaded": ODEvent_Default<(roles:ODRoleManager) => ODPromiseVoid> + "onRoleUpdate": ODEvent_Default<(user:discord.User,role:ODRole) => ODPromiseVoid> + "afterRolesUpdated": ODEvent_Default<(user:discord.User,role:ODRole) => ODPromiseVoid> + + //blacklist + "onBlacklistLoad": ODEvent_Default<(blacklist:ODBlacklistManager) => ODPromiseVoid> + "afterBlacklistLoaded": ODEvent_Default<(blacklist:ODBlacklistManager) => ODPromiseVoid> + + //transcripts + "onTranscriptCompilerLoad": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid> + "afterTranscriptCompilersLoaded": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid> + "onTranscriptHistoryLoad": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid> + "afterTranscriptHistoryLoaded": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid> + + //transcript creation + "onTranscriptCreate": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid> + "afterTranscriptCreated": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid> + "onTranscriptInit": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid> + "afterTranscriptInitiated": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid> + "onTranscriptCompile": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid> + "afterTranscriptCompiled": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid> + "onTranscriptReady": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid> + "afterTranscriptReady": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid> + + //builders + "onButtonBuilderLoad": ODEvent_Default<(buttons:ODButtonManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "afterButtonBuildersLoaded": ODEvent_Default<(buttons:ODButtonManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "onDropdownBuilderLoad": ODEvent_Default<(dropdowns:ODDropdownManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "afterDropdownBuildersLoaded": ODEvent_Default<(dropdowns:ODDropdownManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "onFileBuilderLoad": ODEvent_Default<(files:ODFileManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "afterFileBuildersLoaded": ODEvent_Default<(files:ODFileManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "onEmbedBuilderLoad": ODEvent_Default<(embeds:ODEmbedManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "afterEmbedBuildersLoaded": ODEvent_Default<(embeds:ODEmbedManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "onMessageBuilderLoad": ODEvent_Default<(messages:ODMessageManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "afterMessageBuildersLoaded": ODEvent_Default<(messages:ODMessageManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "onModalBuilderLoad": ODEvent_Default<(modals:ODModalManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "afterModalBuildersLoaded": ODEvent_Default<(modals:ODModalManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + + //responders + "onCommandResponderLoad": ODEvent_Default<(commands:ODCommandResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "afterCommandRespondersLoaded": ODEvent_Default<(commands:ODCommandResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "onButtonResponderLoad": ODEvent_Default<(buttons:ODButtonResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "afterButtonRespondersLoaded": ODEvent_Default<(buttons:ODButtonResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "onDropdownResponderLoad": ODEvent_Default<(dropdowns:ODDropdownResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "afterDropdownRespondersLoaded": ODEvent_Default<(dropdowns:ODDropdownResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "onModalResponderLoad": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + "afterModalRespondersLoaded": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + + //actions + "onActionLoad": ODEvent_Default<(actions:ODActionManager_Default) => ODPromiseVoid> + "afterActionsLoaded": ODEvent_Default<(actions:ODActionManager_Default) => ODPromiseVoid> + + //verifybars + "onVerifyBarLoad": ODEvent_Default<(verifybars:ODVerifyBarManager_Default) => ODPromiseVoid> + "afterVerifyBarsLoaded": ODEvent_Default<(verifybars:ODVerifyBarManager_Default) => ODPromiseVoid> + + //permissions + "onPermissionLoad": ODEvent_Default<(permissions:ODPermissionManager_Default) => ODPromiseVoid> + "afterPermissionsLoaded": ODEvent_Default<(permissions:ODPermissionManager_Default) => ODPromiseVoid> + + //posts + "onPostLoad": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid> + "afterPostsLoaded": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid> + "onPostInit": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid> + "afterPostsInitiated": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid> + + //cooldowns + "onCooldownLoad": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid> + "afterCooldownsLoaded": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid> + "onCooldownInit": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid> + "afterCooldownsInitiated": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid> + + //help menu + "onHelpMenuCategoryLoad": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid> + "afterHelpMenuCategoriesLoaded": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid> + "onHelpMenuComponentLoad": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid> + "afterHelpMenuComponentsLoaded": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid> + + //stats + "onStatScopeLoad": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid> + "afterStatScopesLoaded": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid> + "onStatLoad": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid> + "afterStatsLoaded": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid> + "onStatInit": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid> + "afterStatsInitiated": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid> + + //code + "onCodeLoad": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid> + "afterCodeLoaded": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid> + "onCodeExecute": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid> + "afterCodeExecuted": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid> + + //livestatus + "onLiveStatusSourceLoad": ODEvent_Default<(livestatus:ODLiveStatusManager_Default) => ODPromiseVoid> + "afterLiveStatusSourcesLoaded": ODEvent_Default<(livestatus:ODLiveStatusManager_Default) => ODPromiseVoid> + + //startscreen + "onStartScreenLoad": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid> + "afterStartScreensLoaded": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid> + "onStartScreenRender": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid> + "afterStartScreensRendered": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid> +} + +/**## ODEventManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODEvent class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.events`! + */ +export class ODEventManager_Default extends ODEventManager { + get(id:StartScreenId): ODEventIds_Default[StartScreenId] + get(id:ODValidId): ODEvent|null + + get(id:ODValidId): ODEvent|null { + return super.get(id) + } + + remove(id:StartScreenId): ODEventIds_Default[StartScreenId] + remove(id:ODValidId): ODEvent|null + + remove(id:ODValidId): ODEvent|null { + return super.remove(id) + } + + exists(id:keyof ODEventIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODEventManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODEvent class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.events`! + */ +export class ODEvent_Default ODPromiseVoid)> extends ODEvent { + listen(callback:Callback): void { + return super.listen(callback) + } + listenOnce(callback:Callback): void { + return super.listenOnce(callback) + } + wait(): Promise> + wait(): Promise { + return super.wait() + } + emit(params:Parameters): Promise { + return super.emit(params) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/flag.ts b/src/core/api/defaults/flag.ts new file mode 100644 index 0000000..0d4b835 --- /dev/null +++ b/src/core/api/defaults/flag.ts @@ -0,0 +1,53 @@ +/////////////////////////////////////// +//DEFAULT PROCESS MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODFlagManager, ODFlag } from "../modules/flag" + +/**## ODFlagManagerIds_Default `type` + * This type is an array of ids available in the `ODFlagManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODFlagManagerIds_Default { + "openticket:no-migration":ODFlag, + "openticket:dev-config":ODFlag, + "openticket:dev-database":ODFlag, + "openticket:debug":ODFlag, + "openticket:crash":ODFlag, + "openticket:no-transcripts":ODFlag, + "openticket:no-checker":ODFlag, + "openticket:checker":ODFlag, + "openticket:no-easter":ODFlag, + "openticket:no-plugins":ODFlag, + "openticket:soft-plugins":ODFlag, + "openticket:force-slash-update":ODFlag, +} + +/**## ODFlagManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODFlagManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.flags`! + */ +export class ODFlagManager_Default extends ODFlagManager { + get(id:FlagId): ODFlagManagerIds_Default[FlagId] + get(id:ODValidId): ODFlag|null + + get(id:ODValidId): ODFlag|null { + return super.get(id) + } + + remove(id:FlagId): ODFlagManagerIds_Default[FlagId] + remove(id:ODValidId): ODFlag|null + + remove(id:ODValidId): ODFlag|null { + return super.remove(id) + } + + exists(id:keyof ODFlagManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/helpmenu.ts b/src/core/api/defaults/helpmenu.ts new file mode 100644 index 0000000..7add16f --- /dev/null +++ b/src/core/api/defaults/helpmenu.ts @@ -0,0 +1,323 @@ +/////////////////////////////////////// +//DEFAULT HELP MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODHelpMenuCategory, ODHelpMenuCommandComponent, ODHelpMenuComponent, ODHelpMenuManager } from "../modules/helpmenu" + +/**## ODHelpMenuManagerIds_Default `type` + * This type is an array of ids available in the `ODHelpMenuManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODHelpMenuManagerIds_Default { + "openticket:general":ODHelpMenuCategory_DefaultGeneral, + "openticket:ticket-basic":ODHelpMenuCategory_DefaultTicketBasic, + "openticket:ticket-advanced":ODHelpMenuCategory_DefaultTicketAdvanced, + "openticket:ticket-user":ODHelpMenuCategory_DefaultTicketUser, + "openticket:admin":ODHelpMenuCategory_DefaultAdmin, + "openticket:advanced":ODHelpMenuCategory_DefaultAdvanced, + "openticket:extra":ODHelpMenuCategory_DefaultExtra +} + +/**## ODHelpMenuManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.helpmenu`! + */ +export class ODHelpMenuManager_Default extends ODHelpMenuManager { + get(id:HelpMenuCategoryId): ODHelpMenuManagerIds_Default[HelpMenuCategoryId] + get(id:ODValidId): ODHelpMenuCategory|null + + get(id:ODValidId): ODHelpMenuCategory|null { + return super.get(id) + } + + remove(id:HelpMenuCategoryId): ODHelpMenuManagerIds_Default[HelpMenuCategoryId] + remove(id:ODValidId): ODHelpMenuCategory|null + + remove(id:ODValidId): ODHelpMenuCategory|null { + return super.remove(id) + } + + exists(id:keyof ODHelpMenuManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODHelpMenuManagerCategoryIds_DefaultGeneral `type` + * This type is an array of ids available in the `ODHelpMenuCategory_DefaultGeneral` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODHelpMenuManagerCategoryIds_DefaultGeneral { + "openticket:help":ODHelpMenuCommandComponent, + "openticket:ticket":ODHelpMenuCommandComponent|null +} + +/**## ODHelpMenuCategory_DefaultGeneral `default_class` + * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:general` category in `openticket.helpmenu`! + */ +export class ODHelpMenuCategory_DefaultGeneral extends ODHelpMenuCategory { + get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultGeneral[HelpMenuCategoryId] + get(id:ODValidId): ODHelpMenuComponent|null + + get(id:ODValidId): ODHelpMenuComponent|null { + return super.get(id) + } + + remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultGeneral[HelpMenuCategoryId] + remove(id:ODValidId): ODHelpMenuComponent|null + + remove(id:ODValidId): ODHelpMenuComponent|null { + return super.remove(id) + } + + exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultGeneral): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODHelpMenuManagerCategoryIds_DefaultTicketBasic `type` + * This type is an array of ids available in the `ODHelpMenuCategory_DefaultTicketBasic` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODHelpMenuManagerCategoryIds_DefaultTicketBasic { + "openticket:close":ODHelpMenuCommandComponent, + "openticket:delete":ODHelpMenuCommandComponent, + "openticket:reopen":ODHelpMenuCommandComponent +} + +/**## ODHelpMenuCategory_DefaultTicketBasic `default_class` + * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:ticket` category in `openticket.helpmenu`! + */ +export class ODHelpMenuCategory_DefaultTicketBasic extends ODHelpMenuCategory { + get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketBasic[HelpMenuCategoryId] + get(id:ODValidId): ODHelpMenuComponent|null + + get(id:ODValidId): ODHelpMenuComponent|null { + return super.get(id) + } + + remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketBasic[HelpMenuCategoryId] + remove(id:ODValidId): ODHelpMenuComponent|null + + remove(id:ODValidId): ODHelpMenuComponent|null { + return super.remove(id) + } + + exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketBasic): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced `type` + * This type is an array of ids available in the `ODHelpMenuCategory_DefaultTicketAdvanced` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced { + "openticket:pin":ODHelpMenuCommandComponent, + "openticket:unpin":ODHelpMenuCommandComponent, + "openticket:move":ODHelpMenuCommandComponent, + "openticket:rename":ODHelpMenuCommandComponent +} + +/**## ODHelpMenuCategory_DefaultTicketAdvanced `default_class` + * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:ticket` category in `openticket.helpmenu`! + */ +export class ODHelpMenuCategory_DefaultTicketAdvanced extends ODHelpMenuCategory { + get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced[HelpMenuCategoryId] + get(id:ODValidId): ODHelpMenuComponent|null + + get(id:ODValidId): ODHelpMenuComponent|null { + return super.get(id) + } + + remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced[HelpMenuCategoryId] + remove(id:ODValidId): ODHelpMenuComponent|null + + remove(id:ODValidId): ODHelpMenuComponent|null { + return super.remove(id) + } + + exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODHelpMenuManagerCategoryIds_DefaultTicketUser `type` + * This type is an array of ids available in the `ODHelpMenuCategory_DefaultTicketUser` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODHelpMenuManagerCategoryIds_DefaultTicketUser { + "openticket:claim":ODHelpMenuCommandComponent, + "openticket:unclaim":ODHelpMenuCommandComponent, + "openticket:add":ODHelpMenuCommandComponent, + "openticket:remove":ODHelpMenuCommandComponent +} + +/**## ODHelpMenuCategory_DefaultTicketUser `default_class` + * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:ticket` category in `openticket.helpmenu`! + */ +export class ODHelpMenuCategory_DefaultTicketUser extends ODHelpMenuCategory { + get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketUser[HelpMenuCategoryId] + get(id:ODValidId): ODHelpMenuComponent|null + + get(id:ODValidId): ODHelpMenuComponent|null { + return super.get(id) + } + + remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketUser[HelpMenuCategoryId] + remove(id:ODValidId): ODHelpMenuComponent|null + + remove(id:ODValidId): ODHelpMenuComponent|null { + return super.remove(id) + } + + exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketUser): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODHelpMenuManagerCategoryIds_DefaultAdmin `type` + * This type is an array of ids available in the `ODHelpMenuCategory_DefaultAdmin` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODHelpMenuManagerCategoryIds_DefaultAdmin { + "openticket:panel":ODHelpMenuCommandComponent, + "openticket:blacklist-view":ODHelpMenuCommandComponent, + "openticket:blacklist-add":ODHelpMenuCommandComponent, + "openticket:blacklist-remove":ODHelpMenuCommandComponent, + "openticket:blacklist-get":ODHelpMenuCommandComponent +} + +/**## ODHelpMenuCategory_DefaultAdmin `default_class` + * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:admin` category in `openticket.helpmenu`! + */ +export class ODHelpMenuCategory_DefaultAdmin extends ODHelpMenuCategory { + get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdmin[HelpMenuCategoryId] + get(id:ODValidId): ODHelpMenuComponent|null + + get(id:ODValidId): ODHelpMenuComponent|null { + return super.get(id) + } + + remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdmin[HelpMenuCategoryId] + remove(id:ODValidId): ODHelpMenuComponent|null + + remove(id:ODValidId): ODHelpMenuComponent|null { + return super.remove(id) + } + + exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultAdmin): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODHelpMenuManagerCategoryIds_DefaultAdvanced `type` + * This type is an array of ids available in the `ODHelpMenuCategory_DefaultAdvanced` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODHelpMenuManagerCategoryIds_DefaultAdvanced { + "openticket:stats-global":ODHelpMenuCommandComponent, + "openticket:stats-reset":ODHelpMenuCommandComponent, + "openticket:stats-ticket":ODHelpMenuCommandComponent, + "openticket:stats-user":ODHelpMenuCommandComponent, + "openticket:autoclose-disable":ODHelpMenuCommandComponent, + "openticket:autoclose-enable":ODHelpMenuCommandComponent +} + +/**## ODHelpMenuCategory_DefaultAdvanced `default_class` + * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:advanced` category in `openticket.helpmenu`! + */ +export class ODHelpMenuCategory_DefaultAdvanced extends ODHelpMenuCategory { + get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdvanced[HelpMenuCategoryId] + get(id:ODValidId): ODHelpMenuComponent|null + + get(id:ODValidId): ODHelpMenuComponent|null { + return super.get(id) + } + + remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdvanced[HelpMenuCategoryId] + remove(id:ODValidId): ODHelpMenuComponent|null + + remove(id:ODValidId): ODHelpMenuComponent|null { + return super.remove(id) + } + + exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultAdvanced): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODHelpMenuManagerCategoryIds_DefaultExtra `type` + * This type is an array of ids available in the `ODHelpMenuCategory_DefaultExtra` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODHelpMenuManagerCategoryIds_DefaultExtra {} + +/**## ODHelpMenuCategory_DefaultExtra `default_class` + * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:general` category in `openticket.helpmenu`! + */ +export class ODHelpMenuCategory_DefaultExtra extends ODHelpMenuCategory { + get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultExtra[HelpMenuCategoryId] + get(id:ODValidId): ODHelpMenuComponent|null + + get(id:ODValidId): ODHelpMenuComponent|null { + return super.get(id) + } + + remove(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultExtra[HelpMenuCategoryId] + remove(id:ODValidId): ODHelpMenuComponent|null + + remove(id:ODValidId): ODHelpMenuComponent|null { + return super.remove(id) + } + + exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultExtra): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts new file mode 100644 index 0000000..d8ad7ab --- /dev/null +++ b/src/core/api/defaults/language.ts @@ -0,0 +1,510 @@ +/////////////////////////////////////// +//DEFAULT LANGUAGE MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODLanguageManager, ODLanguage } from "../modules/language" + +/**## ODLanguageManagerTranslations_Default `type` + * This type is an array of ids available in the `ODLanguageManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export type ODLanguageManagerTranslations_Default = ( + "checker.system.headerOpenTicket"| + "checker.system.typeError"| + "checker.system.typeWarning"| + "checker.system.typeInfo"| + "checker.system.headerConfigChecker"| + "checker.system.headerDescription"| + "checker.system.footerError"| + "checker.system.footerWarning"| + "checker.system.footerSupport"| + "checker.system.compactInformation"| + "checker.system.dataPath"| + "checker.system.dataDocs"| + "checker.system.dataMessages"| + "checker.messages.invalidType"| + "checker.messages.propertyMissing"| + "checker.messages.propertyOptional"| + "checker.messages.objectDisabled"| + "checker.messages.nullInvalid"| + "checker.messages.switchInvalidType"| + "checker.messages.objectSwitchInvalid"| + "checker.messages.stringTooShort"| + "checker.messages.stringTooLong"| + "checker.messages.stringLengthInvalid"| + "checker.messages.stringStartsWith"| + "checker.messages.stringEndsWith"| + "checker.messages.stringContains"| + "checker.messages.stringChoices"| + "checker.messages.stringRegex"| + "checker.messages.numberTooShort"| + "checker.messages.numberTooLong"| + "checker.messages.numberLengthInvalid"| + "checker.messages.numberTooSmall"| + "checker.messages.numberTooLarge"| + "checker.messages.numberNotEqual"| + "checker.messages.numberStep"| + "checker.messages.numberStepOffset"| + "checker.messages.numberStartsWith"| + "checker.messages.numberEndsWith"| + "checker.messages.numberContains"| + "checker.messages.numberChoices"| + "checker.messages.numberFloat"| + "checker.messages.numberNegative"| + "checker.messages.numberPositive"| + "checker.messages.numberZero"| + "checker.messages.booleanTrue"| + "checker.messages.booleanFalse"| + "checker.messages.arrayEmptyDisabled"| + "checker.messages.arrayEmptyRequired"| + "checker.messages.arrayTooShort"| + "checker.messages.arrayTooLong"| + "checker.messages.arrayLengthInvalid"| + "checker.messages.arrayInvalidTypes"| + "checker.messages.arrayDouble"| + "checker.messages.discordInvalidId"| + "checker.messages.discordInvalidIdOptions"| + "checker.messages.discordInvalidToken"| + "checker.messages.colorInvalid"| + "checker.messages.emojiTooShort"| + "checker.messages.emojiTooLong"| + "checker.messages.emojiCustom"| + "checker.messages.emojiInvalid"| + "checker.messages.urlInvalid"| + "checker.messages.urlInvalidHttp"| + "checker.messages.urlInvalidProtocol"| + "checker.messages.urlInvalidHostname"| + "checker.messages.urlInvalidExtension"| + "checker.messages.urlInvalidPath"| + "checker.messages.idNotUnique"| + "checker.messages.idNonExistent"| + "checker.messages.invalidLanguage"| + "checker.messages.invalidButton"| + "checker.messages.unusedOption"| + "checker.messages.unusedQuestion"| + "checker.messages.dropdownOption"| + "actions.buttons.create"| + "actions.buttons.close"| + "actions.buttons.delete"| + "actions.buttons.reopen"| + "actions.buttons.claim"| + "actions.buttons.unclaim"| + "actions.buttons.pin"| + "actions.buttons.unpin"| + "actions.buttons.clear"| + "actions.buttons.helpSwitchSlash"| + "actions.buttons.helpSwitchText"| + "actions.buttons.helpPage"| + "actions.buttons.withReason"| + "actions.buttons.withoutTranscript"| + + "actions.titles.created"| + "actions.titles.close"| + "actions.titles.delete"| + "actions.titles.reopen"| + "actions.titles.claim"| + "actions.titles.unclaim"| + "actions.titles.pin"| + "actions.titles.unpin"| + "actions.titles.rename"| + "actions.titles.move"| + "actions.titles.add"| + "actions.titles.remove"| + + "actions.titles.help"| + "actions.titles.statsReset"| + "actions.titles.blacklistAdd"| + "actions.titles.blacklistRemove"| + "actions.titles.blacklistGet"| + "actions.titles.blacklistView"| + "actions.titles.blacklistAddDm"| + "actions.titles.blacklistRemoveDm"| + "actions.titles.clear"| + "actions.titles.roles"| + + "actions.titles.autoclose"| + "actions.titles.autocloseEnabled"| + "actions.titles.autocloseDisabled"| + "actions.titles.autodelete"| + "actions.titles.autodeleteEnabled"| + "actions.titles.autodeleteDisabled"| + + "actions.descriptions.create"| + "actions.descriptions.close"| + "actions.descriptions.delete"| + "actions.descriptions.reopen"| + "actions.descriptions.claim"| + "actions.descriptions.unclaim"| + "actions.descriptions.pin"| + "actions.descriptions.unpin"| + "actions.descriptions.rename"| + "actions.descriptions.move"| + "actions.descriptions.add"| + "actions.descriptions.remove"| + + "actions.descriptions.helpExplanation"| + "actions.descriptions.statsReset"| + "actions.descriptions.statsError"| + "actions.descriptions.blacklistAdd"| + "actions.descriptions.blacklistRemove"| + "actions.descriptions.blacklistGetSuccess"| + "actions.descriptions.blacklistGetEmpty"| + "actions.descriptions.blacklistViewEmpty"| + "actions.descriptions.blacklistViewTip"| + "actions.descriptions.clearVerify"| + "actions.descriptions.clearReady"| + "actions.descriptions.rolesEmpty"| + + "actions.descriptions.autocloseLeave"| + "actions.descriptions.autocloseTimeout"| + "actions.descriptions.autodeleteLeave"| + "actions.descriptions.autodeleteTimeout"| + "actions.descriptions.autocloseEnabled"| + "actions.descriptions.autocloseDisabled"| + "actions.descriptions.autodeleteEnabled"| + "actions.descriptions.autodeleteDisabled"| + + "actions.descriptions.ticketMessageLimit"| + "actions.descriptions.ticketMessageAutoclose"| + "actions.descriptions.ticketMessageAutodelete"| + "actions.descriptions.panelReady"| + + "actions.modal.closePlaceholder"| + "actions.modal.deletePlaceholder"| + "actions.modal.reopenPlaceholder"| + "actions.modal.claimPlaceholder"| + "actions.modal.unclaimPlaceholder"| + "actions.modal.pinPlaceholder"| + "actions.modal.unpinPlaceholder"| + + "actions.logs.createLog"| + "actions.logs.closeLog"| + "actions.logs.closeDm"| + "actions.logs.deleteLog"| + "actions.logs.deleteDm"| + "actions.logs.reopenLog"| + "actions.logs.reopenDm"| + "actions.logs.claimLog"| + "actions.logs.claimDm"| + "actions.logs.unclaimLog"| + "actions.logs.unclaimDm"| + "actions.logs.pinLog"| + "actions.logs.pinDm"| + "actions.logs.unpinLog"| + "actions.logs.unpinDm"| + "actions.logs.renameLog"| + "actions.logs.renameDm"| + "actions.logs.moveLog"| + "actions.logs.moveDm"| + "actions.logs.addLog"| + "actions.logs.addDm"| + "actions.logs.removeLog"| + "actions.logs.removeDm"| + + "actions.logs.blacklistAddLog"| + "actions.logs.blacklistRemoveLog"| + "actions.logs.blacklistAddDm"| + "actions.logs.blacklistRemoveDm"| + "actions.logs.clearLog"| + + "transcripts.success.visit"| + "transcripts.success.ready"| + "transcripts.success.textFileDescription"| + "transcripts.success.htmlProgress"| + + "transcripts.success.createdChannel"| + "transcripts.success.createdCreator"| + "transcripts.success.createdParticipant"| + "transcripts.success.createdActiveAdmin"| + "transcripts.success.createdEveryAdmin"| + "transcripts.success.createdOther"| + + "transcripts.errors.retry"| + "transcripts.errors.continue"| + "transcripts.errors.backup"| + "transcripts.errors.error"| + + "errors.titles.internalError"| + "errors.titles.optionMissing"| + "errors.titles.optionInvalid"| + "errors.titles.unknownCommand"| + "errors.titles.noPermissions"| + "errors.titles.unknownTicket"| + "errors.titles.deprecatedTicket"| + "errors.titles.unknownOption"| + "errors.titles.unknownPanel"| + "errors.titles.notInGuild"| + "errors.titles.channelRename"| + "errors.titles.busy"| + + "errors.descriptions.askForInfo"| + "errors.descriptions.askForInfoResolve"| + "errors.descriptions.internalError"| + "errors.descriptions.optionMissing"| + "errors.descriptions.optionInvalid"| + "errors.descriptions.optionInvalidChoose"| + "errors.descriptions.unknownCommand"| + "errors.descriptions.noPermissions"| + "errors.descriptions.noPermissionsList"| + "errors.descriptions.noPermissionsCooldown"| + "errors.descriptions.noPermissionsBlacklist"| + "errors.descriptions.noPermissionsLimitGlobal"| + "errors.descriptions.noPermissionsLimitGlobalUser"| + "errors.descriptions.noPermissionsLimitOption"| + "errors.descriptions.noPermissionsLimitOptionUser"| + "errors.descriptions.unknownTicket"| + "errors.descriptions.deprecatedTicket"| + "errors.descriptions.notInGuild"| + "errors.descriptions.channelRename"| + "errors.descriptions.channelRenameSource"| + "errors.descriptions.busy"| + + "errors.optionInvalidReasons.stringRegex"| + "errors.optionInvalidReasons.stringMinLength"| + "errors.optionInvalidReasons.stringMaxLength"| + "errors.optionInvalidReasons.numberInvalid"| + "errors.optionInvalidReasons.numberMin"| + "errors.optionInvalidReasons.numberMax"| + "errors.optionInvalidReasons.numberDecimal"| + "errors.optionInvalidReasons.numberNegative"| + "errors.optionInvalidReasons.numberPositive"| + "errors.optionInvalidReasons.numberZero"| + "errors.optionInvalidReasons.channelNotFound"| + "errors.optionInvalidReasons.userNotFound"| + "errors.optionInvalidReasons.roleNotFound"| + "errors.optionInvalidReasons.memberNotFound"| + "errors.optionInvalidReasons.mentionableNotFound"| + "errors.optionInvalidReasons.channelType"| + "errors.optionInvalidReasons.notInGuild"| + + "errors.permissions.developer"| + "errors.permissions.owner"| + "errors.permissions.admin"| + "errors.permissions.moderator"| + "errors.permissions.support"| + "errors.permissions.member"| + "errors.permissions.discord-administrator"| + + "errors.actionInvalid.close"| + "errors.actionInvalid.reopen"| + "errors.actionInvalid.claim"| + "errors.actionInvalid.unclaim"| + "errors.actionInvalid.pin"| + "errors.actionInvalid.unpin"| + "errors.actionInvalid.add"| + "errors.actionInvalid.remove"| + + "params.uppercase.ticket"| + "params.uppercase.tickets"| + "params.uppercase.reason"| + "params.uppercase.creator"| + "params.uppercase.remaining"| + "params.uppercase.added"| + "params.uppercase.removed"| + "params.uppercase.filter"| + "params.uppercase.claimedBy"| + "params.uppercase.method"| + "params.uppercase.type"| + "params.uppercase.blacklisted"| + "params.uppercase.panel"| + "params.uppercase.command"| + "params.uppercase.system"| + "params.uppercase.true"| + "params.uppercase.false"| + "params.uppercase.syntax"| + "params.uppercase.originalName"| + "params.uppercase.newName"| + "params.uppercase.until"| + "params.uppercase.validOptions"| + "params.uppercase.validPanels"| + "params.uppercase.autoclose"| + "params.uppercase.autodelete"| + "params.uppercase.startupDate"| + "params.uppercase.version"| + "params.uppercase.name"| + "params.uppercase.role"| + "params.uppercase.status"| + "params.uppercase.claimed"| + "params.uppercase.pinned"| + "params.uppercase.creationDate"| + + "params.lowercase.text"| + "params.lowercase.html"| + "params.lowercase.command"| + "params.lowercase.modal"| + "params.lowercase.button"| + "params.lowercase.dropdown"| + "params.lowercase.method"| + + "commands.reason"| + "commands.help"| + "commands.panel"| + "commands.panelId"| + "commands.panelAutoUpdate"| + "commands.ticket"| + "commands.ticketId"| + "commands.close"| + "commands.delete"| + "commands.deleteNoTranscript"| + "commands.reopen"| + "commands.claim"| + "commands.claimUser"| + "commands.unclaim"| + "commands.pin"| + "commands.unpin"| + "commands.move"| + "commands.moveId"| + "commands.rename"| + "commands.renameName"| + "commands.add"| + "commands.addUser"| + "commands.remove"| + "commands.removeUser"| + "commands.blacklist"| + "commands.blacklistView"| + "commands.blacklistAdd"| + "commands.blacklistRemove"| + "commands.blacklistGet"| + "commands.blacklistGetUser"| + "commands.stats"| + "commands.statsReset"| + "commands.statsGlobal"| + "commands.statsUser"| + "commands.statsUserUser"| + "commands.statsTicket"| + "commands.statsTicketTicket"| + "commands.clear"| + "commands.clearFilter"| + + "commands.clearFilters.all"| + "commands.clearFilters.open"| + "commands.clearFilters.close"| + "commands.clearFilters.claim"| + "commands.clearFilters.unclaim"| + "commands.clearFilters.pin"| + "commands.clearFilters.unpin"| + "commands.clearFilters.autoclose"| + + "commands.autoclose"| + "commands.autocloseDisable"| + "commands.autocloseEnable"| + "commands.autocloseEnableTime"| + "commands.autodelete"| + "commands.autodeleteDisable"| + "commands.autodeleteEnable"| + "commands.autodeleteEnableTime"| + + "helpMenu.help"| + "helpMenu.ticket"| + "helpMenu.close"| + "helpMenu.delete"| + "helpMenu.reopen"| + "helpMenu.pin"| + "helpMenu.unpin"| + "helpMenu.move"| + "helpMenu.rename"| + "helpMenu.claim"| + "helpMenu.unclaim"| + "helpMenu.add"| + "helpMenu.remove"| + "helpMenu.panel"| + "helpMenu.blacklistView"| + "helpMenu.blacklistAdd"| + "helpMenu.blacklistRemove"| + "helpMenu.blacklistGet"| + "helpMenu.statsGlobal"| + "helpMenu.statsTicket"| + "helpMenu.statsUser"| + "helpMenu.statsReset"| + "helpMenu.autocloseDisable"| + "helpMenu.autocloseEnable"| + "helpMenu.autodeleteDisable"| + "helpMenu.autodeleteEnable"| + + "stats.scopes.global"| + "stats.scopes.system"| + "stats.scopes.user"| + "stats.scopes.ticket"| + "stats.scopes.participants"| + + "stats.properties.ticketsCreated"| + "stats.properties.ticketsClosed"| + "stats.properties.ticketsDeleted"| + "stats.properties.ticketsReopened"| + "stats.properties.ticketsAutoclosed"| + "stats.properties.ticketsClaimed"| + "stats.properties.ticketsPinned"| + "stats.properties.ticketsMoved"| + "stats.properties.usersBlacklisted"| + "stats.properties.transcriptsCreated" +) + +/**## ODLanguageManagerIds_Default `type` + * This type is an array of ids available in the `ODLanguageManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODLanguageManagerIds_Default { + "openticket:custom":ODLanguage, + "openticket:english":ODLanguage, + "openticket:dutch":ODLanguage, + "openticket:portuguese":ODLanguage, + "openticket:czech":ODLanguage, + //ADD NEW LANGUAGES HERE!!! +} + +/**## ODLanguageManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODLanguageManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.languages`! + */ +export class ODLanguageManager_Default extends ODLanguageManager { + get(id:LanguageId): ODLanguageManagerIds_Default[LanguageId] + get(id:ODValidId): ODLanguage|null + + get(id:ODValidId): ODLanguage|null { + return super.get(id) + } + + remove(id:LanguageId): ODLanguageManagerIds_Default[LanguageId] + remove(id:ODValidId): ODLanguage|null + + remove(id:ODValidId): ODLanguage|null { + return super.remove(id) + } + + exists(id:keyof ODLanguageManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getTranslation(id:ODLanguageManagerTranslations_Default): string + getTranslation(id:string): string|null + + getTranslation(id:string): string|null { + return super.getTranslation(id) + } + + setCurrentLanguage(id:keyof ODLanguageManagerIds_Default): void + setCurrentLanguage(id:ODValidId): void + + setCurrentLanguage(id:ODValidId): void { + return super.setCurrentLanguage(id) + } + + setBackupLanguage(id:keyof ODLanguageManagerIds_Default): void + setBackupLanguage(id:ODValidId): void + + setBackupLanguage(id:ODValidId): void { + return super.setBackupLanguage(id) + } + + getTranslationWithParams(id:ODLanguageManagerTranslations_Default, params:string[]): string + getTranslationWithParams(id:string, params:string[]): string|null + + getTranslationWithParams(id:string, params:string[]): string|null { + return super.getTranslationWithParams(id,params) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/permission.ts b/src/core/api/defaults/permission.ts new file mode 100644 index 0000000..0f01536 --- /dev/null +++ b/src/core/api/defaults/permission.ts @@ -0,0 +1,30 @@ +/////////////////////////////////////// +//DEFAULT PERMISSION MODULE +/////////////////////////////////////// +import { ODDebugger } from "../modules/console" +import { ODPermissionManager } from "../modules/permission" + +/**## ODPermissionManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODPermissionManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.permissions`! + */ +export class ODPermissionManager_Default extends ODPermissionManager { + constructor(debug:ODDebugger){ + super(debug,true) + } +} + +/**## ODPermissionEmbedType `type` + * This type contains all types available in the `openticket:no-permissions` embed. + */ +export type ODPermissionEmbedType = ( + "developer"| + "owner"| + "admin"| + "moderator"| + "support"| + "member"| + "discord-administrator" +) \ No newline at end of file diff --git a/src/core/api/defaults/post.ts b/src/core/api/defaults/post.ts new file mode 100644 index 0000000..0b0dc27 --- /dev/null +++ b/src/core/api/defaults/post.ts @@ -0,0 +1,44 @@ +/////////////////////////////////////// +//DEFAULT POST MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODPost, ODPostManager } from "../modules/post" +import * as discord from "discord.js" + +/**## ODPostManagerIds_Default `type` + * This type is an array of ids available in the `ODPostManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODPostManagerIds_Default { + "openticket:logs":ODPost|null, + "openticket:transcripts":ODPost|null +} + +/**## ODPostManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODPostManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.code`! + */ +export class ODPostManager_Default extends ODPostManager { + get(id:PostId): ODPostManagerIds_Default[PostId] + get(id:ODValidId): ODPost|null + + get(id:ODValidId): ODPost|null { + return super.get(id) + } + + remove(id:PostId): ODPostManagerIds_Default[PostId] + remove(id:ODValidId): ODPost|null + + remove(id:ODValidId): ODPost|null { + return super.remove(id) + } + + exists(id:keyof ODPostManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/responder.ts b/src/core/api/defaults/responder.ts new file mode 100644 index 0000000..ffe944f --- /dev/null +++ b/src/core/api/defaults/responder.ts @@ -0,0 +1,255 @@ +/////////////////////////////////////// +//DEFAULT RESPONDER MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODButtonResponder, ODButtonResponderInstance, ODButtonResponderManager, ODCommandResponder, ODCommandResponderInstance, ODCommandResponderManager, ODDropdownResponder, ODDropdownResponderInstance, ODDropdownResponderManager, ODModalResponder, ODModalResponderInstance, ODModalResponderManager, ODResponderManager } from "../modules/responder" +import { ODWorkerManager_Default } from "./worker" + +/**## ODResponderManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODResponderManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.responders`! + */ +export class ODResponderManager_Default extends ODResponderManager { + declare commands: ODCommandResponderManager_Default + declare buttons: ODButtonResponderManager_Default + declare dropdowns: ODDropdownResponderManager_Default + declare modals: ODModalResponderManager_Default +} + +/**## ODCommandResponderManagerIds_Default `type` + * This type is an array of ids available in the `ODCommandResponderManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODCommandResponderManagerIds_Default { + "openticket:help":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:help"|"openticket:logs"}, + "openticket:stats":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:stats"|"openticket:logs"}, + "openticket:panel":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:panel"|"openticket:logs"}, + "openticket:ticket":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:ticket"|"openticket:logs"}, + "openticket:blacklist":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:blacklist"|"openticket:discord-logs"|"openticket:logs"}, + + "openticket:close":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:close"|"openticket:logs"}, + "openticket:reopen":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:reopen"|"openticket:logs"}, + "openticket:delete":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:delete"|"openticket:logs"}, + "openticket:claim":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:claim"|"openticket:logs"}, + "openticket:unclaim":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:unclaim"|"openticket:logs"}, + "openticket:pin":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:pin"|"openticket:logs"}, + "openticket:unpin":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:unpin"|"openticket:logs"}, + + "openticket:rename":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:rename"|"openticket:logs"}, + "openticket:move":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:move"|"openticket:logs"}, + "openticket:add":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:add"|"openticket:logs"}, + "openticket:remove":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:remove"|"openticket:logs"}, + "openticket:clear":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:clear"|"openticket:logs"}, + + "openticket:autoclose":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:autoclose"|"openticket:logs"}, + "openticket:autodelete":{source:"slash"|"text",params:{},workers:"openticket:permissions"|"openticket:autodelete"|"openticket:logs"}, +} + +/**## ODCommandResponderManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODCommandResponderManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.responders.commands`! + */ +export class ODCommandResponderManager_Default extends ODCommandResponderManager { + get(id:CommandResponderId): ODCommandResponder_Default + get(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null + + get(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null { + return super.get(id) + } + + remove(id:CommandResponderId): ODCommandResponder_Default + remove(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null + + remove(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null { + return super.remove(id) + } + + exists(id:keyof ODCommandResponderManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODCommandResponder_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODCommandResponder class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODCommandResponder`'s! + */ +export class ODCommandResponder_Default extends ODCommandResponder { + declare workers: ODWorkerManager_Default +} + +/**## ODButtonResponderManagerIds_Default `type` + * This type is an array of ids available in the `ODButtonResponderManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODButtonResponderManagerIds_Default { + "openticket:verifybar-success":{source:"button",params:{},workers:"openticket:handle-verifybar"}, + "openticket:verifybar-failure":{source:"button",params:{},workers:"openticket:handle-verifybar"}, + + "openticket:help-menu-switch":{source:"button",params:{},workers:"openticket:update-help-menu"}, + "openticket:help-menu-previous":{source:"button",params:{},workers:"openticket:update-help-menu"}, + "openticket:help-menu-next":{source:"button",params:{},workers:"openticket:update-help-menu"}, + + "openticket:ticket-option":{source:"button",params:{},workers:"openticket:ticket-option"}, + "openticket:role-option":{source:"button",params:{},workers:"openticket:role-option"}, + + "openticket:claim-ticket":{source:"button",params:{},workers:"openticket:claim-ticket"}, + "openticket:unclaim-ticket":{source:"button",params:{},workers:"openticket:unclaim-ticket"}, + "openticket:pin-ticket":{source:"button",params:{},workers:"openticket:pin-ticket"}, + "openticket:unpin-ticket":{source:"button",params:{},workers:"openticket:unpin-ticket"}, + "openticket:close-ticket":{source:"button",params:{},workers:"openticket:close-ticket"}, + "openticket:reopen-ticket":{source:"button",params:{},workers:"openticket:reopen-ticket"}, + "openticket:delete-ticket":{source:"button",params:{},workers:"openticket:delete-ticket"}, + + "openticket:transcript-error-retry":{source:"button",params:{},workers:"openticket:permissions"|"openticket:delete-ticket"|"openticket:logs"}, + "openticket:transcript-error-continue":{source:"button",params:{},workers:"openticket:permissions"|"openticket:delete-ticket"|"openticket:logs"}, + "openticket:clear-continue":{source:"button",params:{},workers:"openticket:clear-continue"}, +} + +/**## ODButtonResponderManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODButtonResponderManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.responders.buttons`! + */ +export class ODButtonResponderManager_Default extends ODButtonResponderManager { + get(id:ButtonResponderId): ODButtonResponder_Default + get(id:ODValidId): ODButtonResponder<"button",any>|null + + get(id:ODValidId): ODButtonResponder<"button",any>|null { + return super.get(id) + } + + remove(id:ButtonResponderId): ODButtonResponder_Default + remove(id:ODValidId): ODButtonResponder<"button",any>|null + + remove(id:ODValidId): ODButtonResponder<"button",any>|null { + return super.remove(id) + } + + exists(id:keyof ODButtonResponderManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODButtonResponder_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODButtonResponder class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODButtonResponder`'s! + */ +export class ODButtonResponder_Default extends ODButtonResponder { + declare workers: ODWorkerManager_Default +} + +/**## ODDropdownResponderManagerIds_Default `type` + * This type is an array of ids available in the `ODDropdownResponderManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODDropdownResponderManagerIds_Default { + "openticket:panel-dropdown-tickets":{source:"dropdown",params:{},workers:"openticket:panel-dropdown-tickets"}, +} + +/**## ODDropdownResponderManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODDropdownResponderManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.responders.dropdowns`! + */ +export class ODDropdownResponderManager_Default extends ODDropdownResponderManager { + get(id:DropdownResponderId): ODDropdownResponder_Default + get(id:ODValidId): ODDropdownResponder<"dropdown",any>|null + + get(id:ODValidId): ODDropdownResponder<"dropdown",any>|null { + return super.get(id) + } + + remove(id:DropdownResponderId): ODDropdownResponder_Default + remove(id:ODValidId): ODDropdownResponder<"dropdown",any>|null + + remove(id:ODValidId): ODDropdownResponder<"dropdown",any>|null { + return super.remove(id) + } + + exists(id:keyof ODDropdownResponderManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODDropdownResponder_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODDropdownResponder class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODDropdownResponder`'s! + */ +export class ODDropdownResponder_Default extends ODDropdownResponder { + declare workers: ODWorkerManager_Default +} + +/**## ODModalResponderManagerIds_Default `type` + * This type is an array of ids available in the `ODModalResponderManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODModalResponderManagerIds_Default { + "openticket:ticket-questions":{source:"modal",params:{},workers:"openticket:ticket-questions"}, + "openticket:close-ticket-reason":{source:"modal",params:{},workers:"openticket:close-ticket-reason"}, + "openticket:reopen-ticket-reason":{source:"modal",params:{},workers:"openticket:reopen-ticket-reason"}, + "openticket:delete-ticket-reason":{source:"modal",params:{},workers:"openticket:delete-ticket-reason"}, + "openticket:claim-ticket-reason":{source:"modal",params:{},workers:"openticket:claim-ticket-reason"}, + "openticket:unclaim-ticket-reason":{source:"modal",params:{},workers:"openticket:unclaim-ticket-reason"}, + "openticket:pin-ticket-reason":{source:"modal",params:{},workers:"openticket:pin-ticket-reason"}, + "openticket:unpin-ticket-reason":{source:"modal",params:{},workers:"openticket:unpin-ticket-reason"}, +} + +/**## ODModalResponderManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODModalResponderManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.responders.dropdowns`! + */ +export class ODModalResponderManager_Default extends ODModalResponderManager { + get(id:ModalResponderId): ODModalResponder_Default + get(id:ODValidId): ODModalResponder<"modal",any>|null + + get(id:ODValidId): ODModalResponder<"modal",any>|null { + return super.get(id) + } + + remove(id:ModalResponderId): ODModalResponder_Default + remove(id:ODValidId): ODModalResponder<"modal",any>|null + + remove(id:ODValidId): ODModalResponder<"modal",any>|null { + return super.remove(id) + } + + exists(id:keyof ODModalResponderManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODModalResponder_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODModalResponder class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODModalResponder`'s! + */ +export class ODModalResponder_Default extends ODModalResponder { + declare workers: ODWorkerManager_Default +} \ No newline at end of file diff --git a/src/core/api/defaults/session.ts b/src/core/api/defaults/session.ts new file mode 100644 index 0000000..cce95ec --- /dev/null +++ b/src/core/api/defaults/session.ts @@ -0,0 +1,42 @@ +/////////////////////////////////////// +//DEFAULT SESSION MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODSession, ODSessionManager } from "../modules/session" + +/**## ODSessionManagerIds_Default `type` + * This type is an array of ids available in the `ODSessionManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODSessionManagerIds_Default { + "test-session":ODSession +} + +/**## ODSessionManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODSessionManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.sessions`! + */ +export class ODSessionManager_Default extends ODSessionManager { + get(id:SessionId): ODSessionManagerIds_Default[SessionId] + get(id:ODValidId): ODSession|null + + get(id:ODValidId): ODSession|null { + return super.get(id) + } + + remove(id:SessionId): ODSessionManagerIds_Default[SessionId] + remove(id:ODValidId): ODSession|null + + remove(id:ODValidId): ODSession|null { + return super.remove(id) + } + + exists(id:keyof ODSessionManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/startscreen.ts b/src/core/api/defaults/startscreen.ts new file mode 100644 index 0000000..4d49c07 --- /dev/null +++ b/src/core/api/defaults/startscreen.ts @@ -0,0 +1,48 @@ +/////////////////////////////////////// +//DEFAULT STARTSCREEN MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODStartScreenCategoryComponent, ODStartScreenComponent, ODStartScreenFlagsCategoryComponent, ODStartScreenHeaderComponent, ODStartScreenLiveStatusCategoryComponent, ODStartScreenLogoComponent, ODStartScreenManager, ODStartScreenPluginsCategoryComponent, ODStartScreenPropertiesCategoryComponent } from "../modules/startscreen" + +/**## ODStartScreenManagerIds_Default `type` + * This type is an array of ids available in the `ODStartScreenManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODStartScreenManagerIds_Default { + "openticket:logo":ODStartScreenLogoComponent, + "openticket:header":ODStartScreenHeaderComponent, + "openticket:flags":ODStartScreenFlagsCategoryComponent, + "openticket:plugins":ODStartScreenPluginsCategoryComponent, + "openticket:stats":ODStartScreenPropertiesCategoryComponent, + "openticket:livestatus":ODStartScreenLiveStatusCategoryComponent, + "openticket:logs":ODStartScreenCategoryComponent +} + +/**## ODStartScreenManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODStartScreenManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.startscreen`! + */ +export class ODStartScreenManager_Default extends ODStartScreenManager { + get(id:StartScreenId): ODStartScreenManagerIds_Default[StartScreenId] + get(id:ODValidId): ODStartScreenComponent|null + + get(id:ODValidId): ODStartScreenComponent|null { + return super.get(id) + } + + remove(id:StartScreenId): ODStartScreenManagerIds_Default[StartScreenId] + remove(id:ODValidId): ODStartScreenComponent|null + + remove(id:ODValidId): ODStartScreenComponent|null { + return super.remove(id) + } + + exists(id:keyof ODStartScreenManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/stat.ts b/src/core/api/defaults/stat.ts new file mode 100644 index 0000000..3366d7d --- /dev/null +++ b/src/core/api/defaults/stat.ts @@ -0,0 +1,363 @@ +/////////////////////////////////////// +//DEFAULT SESSION MODULE +/////////////////////////////////////// +import { Guild, TextBasedChannel, User } from "discord.js" +import { ODValidId } from "../modules/base" +import { ODStatScope, ODStatGlobalScope, ODStatsManager, ODStat, ODBasicStat, ODDynamicStat, ODValidStatValue, ODStatScopeSetMode } from "../modules/stat" + +/**## ODStatsManagerIds_Default `type` + * This type is an array of ids available in the `ODStatsManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODStatsManagerIds_Default { + "openticket:global":ODStatGlobalScope_DefaultGlobal, + "openticket:system":ODStatGlobalScope_DefaultSystem, + "openticket:user":ODStatScope_DefaultUser, + "openticket:ticket":ODStatScope_DefaultTicket, + "openticket:participants":ODStatScope_DefaultParticipants +} + +/**## ODStatsManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODStatsManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.stats`! + */ +export class ODStatsManager_Default extends ODStatsManager { + get(id:StatsId): ODStatsManagerIds_Default[StatsId] + get(id:ODValidId): ODStatScope|null + + get(id:ODValidId): ODStatScope|null { + return super.get(id) + } + + remove(id:StatsId): ODStatsManagerIds_Default[StatsId] + remove(id:ODValidId): ODStatScope|null + + remove(id:ODValidId): ODStatScope|null { + return super.remove(id) + } + + exists(id:keyof ODStatsManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODStatGlobalScopeIds_DefaultGlobal `type` + * This type is an array of ids available in the `ODStatGlobalScope_DefaultGlobal` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODStatGlobalScopeIds_DefaultGlobal { + "openticket:tickets-created":ODBasicStat, + "openticket:tickets-closed":ODBasicStat, + "openticket:tickets-deleted":ODBasicStat, + "openticket:tickets-reopened":ODBasicStat, + "openticket:tickets-autoclosed":ODBasicStat, + "openticket:tickets-autodeleted":ODBasicStat, + "openticket:tickets-claimed":ODBasicStat, + "openticket:tickets-pinned":ODBasicStat, + "openticket:tickets-moved":ODBasicStat, + "openticket:users-blacklisted":ODBasicStat, + "openticket:transcripts-created":ODBasicStat +} + +/**## ODStatGlobalScope_DefaultGlobal `default_class` + * This is a special class that adds type definitions & typescript to the ODStatsManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:global` category in `openticket.stats`! + */ +export class ODStatGlobalScope_DefaultGlobal extends ODStatGlobalScope { + get(id:StatsId): ODStatGlobalScopeIds_DefaultGlobal[StatsId] + get(id:ODValidId): ODStat|null + + get(id:ODValidId): ODStat|null { + return super.get(id) + } + + remove(id:StatsId): ODStatGlobalScopeIds_DefaultGlobal[StatsId] + remove(id:ODValidId): ODStat|null + + remove(id:ODValidId): ODStat|null { + return super.remove(id) + } + + exists(id:keyof ODStatGlobalScopeIds_DefaultGlobal): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getStat(id:StatsId): ODValidStatValue|null + getStat(id:ODValidId): ODValidStatValue|null + + getStat(id:ODValidId): ODValidStatValue|null { + return super.getStat(id) + } + + setStat(id:StatsId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + + setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + return super.setStat(id,value,mode) + } + + resetStat(id:ODValidId): ODValidStatValue|null + resetStat(id:ODValidId): ODValidStatValue|null + + resetStat(id:ODValidId): ODValidStatValue|null { + return super.resetStat(id) + } +} + +/**## ODStatGlobalScopeIds_DefaultSystem `type` + * This type is an array of ids available in the `ODStatScope_DefaultSystem` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODStatGlobalScopeIds_DefaultSystem { + "openticket:startup-date":ODDynamicStat, + "openticket:version":ODDynamicStat +} + +/**## ODStatGlobalScope_DefaultSystem `default_class` + * This is a special class that adds type definitions & typescript to the ODStatsManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:system` category in `openticket.stats`! + */ +export class ODStatGlobalScope_DefaultSystem extends ODStatGlobalScope { + get(id:StatsId): ODStatGlobalScopeIds_DefaultSystem[StatsId] + get(id:ODValidId): ODStat|null + + get(id:ODValidId): ODStat|null { + return super.get(id) + } + + remove(id:StatsId): ODStatGlobalScopeIds_DefaultSystem[StatsId] + remove(id:ODValidId): ODStat|null + + remove(id:ODValidId): ODStat|null { + return super.remove(id) + } + + exists(id:keyof ODStatGlobalScopeIds_DefaultSystem): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getStat(id:StatsId): ODValidStatValue|null + getStat(id:ODValidId): ODValidStatValue|null + + getStat(id:ODValidId): ODValidStatValue|null { + return super.getStat(id) + } + + setStat(id:StatsId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + + setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + return super.setStat(id,value,mode) + } + + resetStat(id:ODValidId): ODValidStatValue|null + resetStat(id:ODValidId): ODValidStatValue|null + + resetStat(id:ODValidId): ODValidStatValue|null { + return super.resetStat(id) + } +} + +/**## ODStatScopeIds_DefaultUser `type` + * This type is an array of ids available in the `ODStatScope_DefaultUser` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODStatScopeIds_DefaultUser { + "openticket:name":ODDynamicStat, + "openticket:role":ODDynamicStat, + "openticket:tickets-created":ODBasicStat, + "openticket:tickets-closed":ODBasicStat, + "openticket:tickets-deleted":ODBasicStat, + "openticket:tickets-reopened":ODBasicStat, + "openticket:tickets-claimed":ODBasicStat, + "openticket:tickets-pinned":ODBasicStat, + "openticket:tickets-moved":ODBasicStat, + "openticket:users-blacklisted":ODBasicStat, + "openticket:transcripts-created":ODBasicStat +} + +/**## ODStatScope_DefaultUser `default_class` + * This is a special class that adds type definitions & typescript to the ODStatsManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:user` category in `openticket.stats`! + */ +export class ODStatScope_DefaultUser extends ODStatScope { + get(id:StatsId): ODStatScopeIds_DefaultUser[StatsId] + get(id:ODValidId): ODStat|null + + get(id:ODValidId): ODStat|null { + return super.get(id) + } + + remove(id:StatsId): ODStatScopeIds_DefaultUser[StatsId] + remove(id:ODValidId): ODStat|null + + remove(id:ODValidId): ODStat|null { + return super.remove(id) + } + + exists(id:keyof ODStatScopeIds_DefaultUser): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getStat(id:StatsId, scopeId:string): ODValidStatValue|null + getStat(id:ODValidId, scopeId:string): ODValidStatValue|null + + getStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + return super.getStat(id,scopeId) + } + + setStat(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + return super.setStat(id,scopeId,value,mode) + } + + resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null + resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null + + resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + return super.resetStat(id,scopeId) + } +} + +/**## ODStatScopeIds_DefaultTicket `type` + * This type is an array of ids available in the `ODStatScope_DefaultTicket` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODStatScopeIds_DefaultTicket { + "openticket:name":ODDynamicStat, + "openticket:status":ODDynamicStat, + "openticket:claimed":ODDynamicStat, + "openticket:pinned":ODDynamicStat, + "openticket:creation-date":ODDynamicStat, + "openticket:creator":ODDynamicStat +} + +/**## ODStatScope_DefaultTicket `default_class` + * This is a special class that adds type definitions & typescript to the ODStatsManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:ticket` category in `openticket.stats`! + */ +export class ODStatScope_DefaultTicket extends ODStatScope { + get(id:StatsId): ODStatScopeIds_DefaultTicket[StatsId] + get(id:ODValidId): ODStat|null + + get(id:ODValidId): ODStat|null { + return super.get(id) + } + + remove(id:StatsId): ODStatScopeIds_DefaultTicket[StatsId] + remove(id:ODValidId): ODStat|null + + remove(id:ODValidId): ODStat|null { + return super.remove(id) + } + + exists(id:keyof ODStatScopeIds_DefaultTicket): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getStat(id:StatsId, scopeId:string): ODValidStatValue|null + getStat(id:ODValidId, scopeId:string): ODValidStatValue|null + + getStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + return super.getStat(id,scopeId) + } + + setStat(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + return super.setStat(id,scopeId,value,mode) + } + + resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null + resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null + + resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + return super.resetStat(id,scopeId) + } +} + +/**## ODStatScopeIds_DefaultParticipants `type` + * This type is an array of ids available in the `ODStatScope_DefaultParticipants` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODStatScopeIds_DefaultParticipants { + "openticket:participants":ODDynamicStat +} + +/**## ODStatScope_DefaultParticipants `default_class` + * This is a special class that adds type definitions & typescript to the ODStatsManager class. + * It doesn't add any extra features! + * + * This default class is made for the `openticket:participants` category in `openticket.stats`! + */ +export class ODStatScope_DefaultParticipants extends ODStatScope { + get(id:StatsId): ODStatScopeIds_DefaultParticipants[StatsId] + get(id:ODValidId): ODStat|null + + get(id:ODValidId): ODStat|null { + return super.get(id) + } + + remove(id:StatsId): ODStatScopeIds_DefaultParticipants[StatsId] + remove(id:ODValidId): ODStat|null + + remove(id:ODValidId): ODStat|null { + return super.remove(id) + } + + exists(id:keyof ODStatScopeIds_DefaultParticipants): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + getStat(id:StatsId, scopeId:string): ODValidStatValue|null + getStat(id:ODValidId, scopeId:string): ODValidStatValue|null + + getStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + return super.getStat(id,scopeId) + } + + setStat(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + return super.setStat(id,scopeId,value,mode) + } + + resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null + resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null + + resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + return super.resetStat(id,scopeId) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/verifybar.ts b/src/core/api/defaults/verifybar.ts new file mode 100644 index 0000000..3df5f8f --- /dev/null +++ b/src/core/api/defaults/verifybar.ts @@ -0,0 +1,72 @@ +/////////////////////////////////////// +//DEFAULT VERIFYBAR MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODButtonResponderInstance } from "../modules/responder" +import { ODWorkerManager_Default } from "../defaults/worker" +import { ODVerifyBarManager, ODVerifyBar } from "../modules/verifybar" +import * as discord from "discord.js" + +/**## ODVerifyBarManagerIds_Default `type` + * This type is an array of ids available in the `ODVerifyBarManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODVerifyBarManagerIds_Default { + "openticket:claim-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:claim-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, + "openticket:claim-ticket-unclaim-message":{successWorkerIds:"openticket:permissions"|"openticket:claim-ticket",failureWorkerIds:"openticket:back-to-unclaim-message"}, + "openticket:unclaim-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:unclaim-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, + "openticket:unclaim-ticket-claim-message":{successWorkerIds:"openticket:permissions"|"openticket:unclaim-ticket",failureWorkerIds:"openticket:back-to-claim-message"}, + "openticket:pin-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:pin-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, + "openticket:pin-ticket-unpin-message":{successWorkerIds:"openticket:permissions"|"openticket:pin-ticket",failureWorkerIds:"openticket:back-to-unpin-message"}, + "openticket:unpin-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:unpin-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, + "openticket:unpin-ticket-pin-message":{successWorkerIds:"openticket:permissions"|"openticket:unpin-ticket",failureWorkerIds:"openticket:back-to-pin-message"}, + "openticket:close-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:close-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, + "openticket:close-ticket-reopen-message":{successWorkerIds:"openticket:permissions"|"openticket:close-ticket",failureWorkerIds:"openticket:back-to-reopen-message"}, + "openticket:reopen-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:reopen-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, + "openticket:reopen-ticket-close-message":{successWorkerIds:"openticket:permissions"|"openticket:reopen-ticket",failureWorkerIds:"openticket:back-to-close-message"}, + "openticket:reopen-ticket-autoclose-message":{successWorkerIds:"openticket:permissions"|"openticket:reopen-ticket",failureWorkerIds:"openticket:back-to-autoclose-message"}, + "openticket:delete-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-ticket-message"} + "openticket:delete-ticket-close-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-close-message"} + "openticket:delete-ticket-reopen-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-reopen-message"} + "openticket:delete-ticket-autoclose-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-autoclose-message"} +} + +/**## ODVerifyBarManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODVerifyBarManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.verifybars`! + */ +export class ODVerifyBarManager_Default extends ODVerifyBarManager { + get(id:VerifyBarId): ODVerifyBar_Default + get(id:ODValidId): ODVerifyBar|null + + get(id:ODValidId): ODVerifyBar|null { + return super.get(id) + } + + remove(id:VerifyBarId): ODVerifyBar_Default + remove(id:ODValidId): ODVerifyBar|null + + remove(id:ODValidId): ODVerifyBar|null { + return super.remove(id) + } + + exists(id:keyof ODVerifyBarManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODVerifyBar_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODVerifyBar class. + * It doesn't add any extra features! + * + * This default class is made for the default `ODVerifyBar`'s! + */ +export class ODVerifyBar_Default extends ODVerifyBar { + declare success: ODWorkerManager_Default|null},SuccessWorkerIds> + declare failure: ODWorkerManager_Default|null},FailureWorkerIds> +} \ No newline at end of file diff --git a/src/core/api/defaults/worker.ts b/src/core/api/defaults/worker.ts new file mode 100644 index 0000000..3642aee --- /dev/null +++ b/src/core/api/defaults/worker.ts @@ -0,0 +1,35 @@ +/////////////////////////////////////// +//DEFAULT WORKER MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODWorker, ODWorkerManager } from "../modules/worker" + + +/**## ODWorkerManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODWorkerManager class. + * It doesn't add any extra features! + * + * This default class is made for the worker manager in actions, builders & responders! + */ +export class ODWorkerManager_Default extends ODWorkerManager { + get(id:WorkerIds): ODWorker + get(id:ODValidId): ODWorker|null + + get(id:ODValidId): ODWorker|null { + return super.get(id) + } + + remove(id:WorkerIds): ODWorker + remove(id:ODValidId): ODWorker|null + + remove(id:ODValidId): ODWorker|null { + return super.remove(id) + } + + exists(id:WorkerIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/main.ts b/src/core/api/main.ts new file mode 100644 index 0000000..84a3873 --- /dev/null +++ b/src/core/api/main.ts @@ -0,0 +1,180 @@ +//BASE MODULES +import { ODEnvHelper, ODVersion } from "./modules/base" +import { ODPluginManager } from "./modules/plugin" +import { ODConsoleManager, ODConsoleMessage, ODConsoleMessageParam, ODConsoleMessageTypes, ODDebugFileManager, ODDebugger, ODError } from "./modules/console" +import { ODCheckerStorage } from "./modules/checker" +import { ODDefaultsManager } from "./modules/defaults" + +//DEFAULT MODULES +import { ODVersionManager_Default } from "./defaults/base" +import { ODEventManager_Default } from "./defaults/event" +import { ODConfigManager_Default} from "./defaults/config" +import { ODDatabaseManager_Default } from "./defaults/database" +import { ODFlagManager_Default } from "./defaults/flag" +import { ODSessionManager_Default } from "./defaults/session" +import { ODLanguageManager_Default } from "./defaults/language" +import { ODCheckerFunctionManager_Default, ODCheckerManager_Default, ODCheckerRenderer_Default, ODCheckerTranslationRegister_Default } from "./defaults/checker" +import { ODClientManager_Default } from "./defaults/client" +import { ODBuilderManager_Default } from "./defaults/builder" +import { ODResponderManager_Default } from "./defaults/responder" +import { ODActionManager_Default } from "./defaults/action" +import { ODPermissionManager_Default } from "./defaults/permission" +import { ODHelpMenuManager_Default } from "./defaults/helpmenu" +import { ODStatsManager_Default } from "./defaults/stat" +import { ODCodeManager_Default } from "./defaults/code" +import { ODCooldownManager_Default } from "./defaults/cooldown" +import { ODPostManager_Default } from "./defaults/post" +import { ODVerifyBarManager_Default } from "./defaults/verifybar" +import { ODStartScreenManager_Default } from "./defaults/startscreen" +import { ODLiveStatusManager_Default } from "./defaults/console" + +//OPEN TICKET MODULES +import { ODOptionManager } from "./openticket/option" +import { ODPanelManager } from "./openticket/panel" +import { ODTicketManager } from "./openticket/ticket" +import { ODQuestionManager } from "./openticket/question" +import { ODBlacklistManager } from "./openticket/blacklist" +import { ODTranscriptManager_Default } from "./openticket/transcript" +import { ODRoleManager } from "./openticket/role" + +/**## ODMain `class` + * This is the main Open Ticket class. + * It contains all managers from the entire bot & has shortcuts to the event & logging system. + * + * This class can't be overwritten or extended & is available as the global variable `openticket`! + */ +export class ODMain { + /**The manager that handles all versions in the bot. */ + versions: ODVersionManager_Default + + /**The manager responsible for the debug file. (`otdebug.txt`) */ + debugfile: ODDebugFileManager + /**The manager responsible for the console system. (logs, errors, etc) */ + console: ODConsoleManager + /**The manager responsible for sending debug logs to the debug file. (`otdebug.txt`) */ + debug: ODDebugger + /**The manager containing all Open Ticket events. */ + events: ODEventManager_Default + + /**The manager that handles & executes all plugins in the bot. */ + plugins: ODPluginManager + /**The manager that manages & checks all the console flags of the bot. (like `--debug`) */ + flags: ODFlagManager_Default + /**The manager that manages & contains all the config files of the bot. (like `config/general.json`) */ + configs: ODConfigManager_Default + /**The manager that manages & contains all the databases of the bot. (like `database/global.json`) */ + databases: ODDatabaseManager_Default + /**The manager that manages all the data sessions of the bot. (it's a temporary database) */ + sessions: ODSessionManager_Default + /**The manager that manages all languages & translations of the bot. (but not for plugins) */ + languages: ODLanguageManager_Default + + /**The manager that handles & executes all config checkers in the bot. (the code that checks if you have something wrong in your config) */ + checkers: ODCheckerManager_Default + /**The manager that manages all builders in the bot. (e.g. buttons, dropdowns, messages, modals, etc) */ + builders: ODBuilderManager_Default + /**The manager that manages all responders in the bot. (e.g. commands, buttons, dropdowns, modals) */ + responders: ODResponderManager_Default + /**The manager that manages all actions or procedures in the bot. (e.g. ticket-creation, ticket-deletion, ticket-claiming, etc) */ + actions: ODActionManager_Default + /**The manager that manages all verify bars in the bot. (the ✅ ❌ buttons) */ + verifybars: ODVerifyBarManager_Default + /**The manager that contains all permissions for commands & actions in the bot. (use it to check if someone has admin perms or not) */ + permissions: ODPermissionManager_Default + /**The manager that contains all cooldowns of the bot. (e.g. ticket-cooldowns) */ + cooldowns: ODCooldownManager_Default + /**The manager that manages & renders the Open Ticket help menu. (not the embed, but the text) */ + helpmenu: ODHelpMenuManager_Default + /**The manager that manages, saves & renders the Open Ticket statistics. (not the embed, but the text & database) */ + stats: ODStatsManager_Default + /**This manager is a place where you can put code that executes when the bot almost finishes the setup. (can be used for less important stuff that doesn't require an exact time-order) */ + code: ODCodeManager_Default + /**The manager that manages all posts (static discord channels) in the bot. (e.g. (transcript) logs, etc) */ + posts: ODPostManager_Default + + /**The manager responsible for everything related to the client. (e.g. status, login, slash & text commands, etc) */ + client: ODClientManager_Default + /**This manager contains A LOD of booleans. With these switches, you can turn off "default behaviours" from the bot. This is used if you want to replace the default Open Ticket code. */ + defaults: ODDefaultsManager + /**This manager manages all the variables in the ENV. It reads from both the `.env` file & the `process.env`. (these 2 will be combined) */ + env: ODEnvHelper + + /**The manager responsible for the livestatus system. (remote console logs) */ + livestatus: ODLiveStatusManager_Default + /**The manager responsible for the livestatus system. (remote console logs) */ + startscreen: ODStartScreenManager_Default + + //OPEN TICKET + /**The manager that manages all the data of questions in the bot. (these are used in options & tickets) */ + questions: ODQuestionManager + /**The manager that manages all the data of options in the bot. (these are used for panels, ticket creation, reaction roles) */ + options: ODOptionManager + /**The manager that manages all the data of panels in the bot. (panels contain the options) */ + panels: ODPanelManager + /**The manager that manages all tickets in the bot. (here, you can get & edit a lot of data from tickets) */ + tickets: ODTicketManager + /**The manager that manages the ticket blacklist. (people who are blacklisted can't create a ticket) */ + blacklist: ODBlacklistManager + /**The manager that manages the ticket transcripts. (both the history & compilers) */ + transcripts: ODTranscriptManager_Default + /**The manager that manages all reaction roles in the bot. (here, you can add additional data to roles) */ + roles: ODRoleManager + + constructor(){ + this.versions = new ODVersionManager_Default() + this.versions.add(ODVersion.fromString("openticket:version","v4.0.0")) + this.versions.add(ODVersion.fromString("openticket:api","v1.0.0")) + this.versions.add(ODVersion.fromString("openticket:transcripts","v2.0.0")) + this.versions.add(ODVersion.fromString("openticket:livestatus","v2.0.0")) + + this.debugfile = new ODDebugFileManager("./","otdebug.txt",5000,this.versions.get("openticket:version")) + this.console = new ODConsoleManager(100,this.debugfile) + this.debug = new ODDebugger(this.console) + this.events = new ODEventManager_Default(this.debug) + + this.plugins = new ODPluginManager(this.debug) + this.flags = new ODFlagManager_Default(this.debug) + this.configs = new ODConfigManager_Default(this.debug) + this.databases = new ODDatabaseManager_Default(this.debug) + this.sessions = new ODSessionManager_Default(this.debug) + this.languages = new ODLanguageManager_Default(this.debug,false) + + this.checkers = new ODCheckerManager_Default(this.debug,new ODCheckerStorage(),new ODCheckerRenderer_Default(),new ODCheckerTranslationRegister_Default(),new ODCheckerFunctionManager_Default(this.debug)) + this.builders = new ODBuilderManager_Default(this.debug) + this.client = new ODClientManager_Default(this.debug) + this.responders = new ODResponderManager_Default(this.debug,this.client) + this.actions = new ODActionManager_Default(this.debug) + this.verifybars = new ODVerifyBarManager_Default(this.debug) + this.permissions = new ODPermissionManager_Default(this.debug) + this.cooldowns = new ODCooldownManager_Default(this.debug) + this.helpmenu = new ODHelpMenuManager_Default(this.debug) + this.stats = new ODStatsManager_Default(this.debug) + this.code = new ODCodeManager_Default(this.debug) + this.posts = new ODPostManager_Default(this.debug) + + this.defaults = new ODDefaultsManager() + this.env = new ODEnvHelper() + + this.livestatus = new ODLiveStatusManager_Default(this.debug,this) + this.startscreen = new ODStartScreenManager_Default(this.debug,this.livestatus) + + //OPEN TICKET + this.questions = new ODQuestionManager(this.debug) + this.options = new ODOptionManager(this.debug) + this.panels = new ODPanelManager(this.debug) + this.tickets = new ODTicketManager(this.debug,this.client) + this.blacklist = new ODBlacklistManager(this.debug) + this.transcripts = new ODTranscriptManager_Default(this.debug,this.tickets) + this.roles = new ODRoleManager(this.debug) + } + + /**Log a message to the console. But in the Open Ticket style :) */ + log(message:ODConsoleMessage): void + log(message:ODError): void + log(message:string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]): void + log(message:ODConsoleMessage|ODError|string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]){ + if (message instanceof ODConsoleMessage) this.console.log(message) + else if (message instanceof ODError) this.console.log(message) + else if (["string","number","boolean","object"].includes(typeof message)) this.console.log(message,type,params) + } +} \ No newline at end of file diff --git a/src/core/api/modules/action.ts b/src/core/api/modules/action.ts new file mode 100644 index 0000000..dd9a46f --- /dev/null +++ b/src/core/api/modules/action.ts @@ -0,0 +1,58 @@ +/////////////////////////////////////// +//ACTION MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODValidId, ODSystemError, ODManagerData } from "./base" +import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker" +import { ODDebugger } from "./console" + +/**## ODActionImplementation `class` + * This is an open ticket action implementation. + * + * It is a basic implementation of the `ODWorkerManager` used by all `ODAction` classes. + * + * This class can't be used stand-alone & needs to be extended from! + */ +export class ODActionImplementation extends ODManagerData { + /**The manager that has all workers of this implementation */ + workers: ODWorkerManager + + constructor(id:ODValidId, callback?:ODWorkerCallback, priority?:number, callbackId?:ODValidId){ + super(id) + this.workers = new ODWorkerManager("descending") + if (callback) this.workers.add(new ODWorker(callbackId ? callbackId : id,priority ?? 0,callback)) + } + /**Execute all workers & return the result. */ + async run(source:Source, params:Params): Promise> { + throw new ODSystemError("Tried to build an unimplemented ODResponderImplementation") + } +} + +/**## ODActionManager `class` + * This is an open ticket action manager. + * + * It contains all Open Ticket actions. You can compare actions with some sort of "procedure". + * It's a complicated task that is divided into multiple functions. + * + * Some examples are `ticket-creation`, `ticket-closing`, `ticket-claiming`, ... + * + * It's recommended to use this system in combination with Open Ticket responders! + */ +export class ODActionManager extends ODManager> { + constructor(debug:ODDebugger){ + super(debug,"action") + } +} + +export class ODAction extends ODActionImplementation { + /**Run this action */ + async run(source:Source, params:Params): Promise> { + //create instance + const instance = {} + + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + + //return data generated by workers + return instance + } +} \ No newline at end of file diff --git a/src/core/api/modules/base.ts b/src/core/api/modules/base.ts new file mode 100644 index 0000000..20eda1f --- /dev/null +++ b/src/core/api/modules/base.ts @@ -0,0 +1,749 @@ +/////////////////////////////////////// +//BASE MODULE +/////////////////////////////////////// +import * as fs from "fs" +import { ODConsoleWarningMessage, ODDebugger } from "./console" + +/**## ODPromiseVoid `type` + * This is a simple type to represent a callback return value that could be a promise or not. + */ +export type ODPromiseVoid = void|Promise + +/**## ODValidButtonColor `type` + * This is a collection of all the possible button colors. + */ +export type ODValidButtonColor = "gray"|"red"|"green"|"blue" + +/**## ODValidId `type` + * This is a valid open ticket identifier. It can be an `ODId` or `string`! + * + * You will see this type in many functions from open ticket. + */ +export type ODValidId = string|ODId + +/**## ODValidJsonType `type` + * This is a collection of all types that can be stored in a JSON file! + * + * list: `string`, `number`, `boolean`, `array`, `object`, `null` + */ +export type ODValidJsonType = string|number|boolean|object|ODValidJsonType[]|null + + +/**## ODInterfaceWithPartialProperty `type` + * This is a utility type to create an interface where some properties are optional! + */ +export type ODInterfaceWithPartialProperty = Omit & Partial> + +/**## ODId `class` + * This is an open ticket identifier. + * + * It can only contain the following characters: `a-z`, `A-Z`, `0-9`, `:`, `-` & `_` + * + * You will use this class to assign a unique id when creating configs, databases, languages & more! + * @example + * const id = new api.ODId("openticket:test-id") //this is valid + * const id = new api.ODId("example%id?") //this is invalid + */ +export class ODId { + /**The full value of this `ODId` as a `string` */ + value: string + /**The source of the id (part before `:`). For example `openticket` for all built-in ids! */ + source: string + /**The identifier of the id (part after `:`). */ + identifier: string + + constructor(id:ODValidId){ + if (typeof id != "string" && !(id instanceof ODId)) throw new ODSystemError("Invalid constructor parameter => id:ODValidId") + + if (typeof id == "string"){ + //id is string + const result: string[] = [] + const charregex = /[a-zA-Z0-9éèçàêâôûî\:\-\_]/ + + id.split("").forEach((char) => { + if (charregex.test(char)){ + result.push(char) + } + }) + + if (result.length > 0) this.value = result.join("") + else throw new ODSystemError("invalid ID at 'new ODID(id: "+id+")'") + + const splitted = this.value.split(":") + if (splitted.length > 1){ + this.source = splitted[0] + splitted.shift() + this.identifier = splitted.join(":") + }else{ + this.identifier = splitted.join(":") + this.source = "" + } + }else{ + //id is ODId + this.value = id.value + this.source = id.source + this.identifier = id.identifier + } + } + + /**Returns a string representation of this id. (same as `this.value`) */ + toString(){ + return this.value + } +} + +/**## ODManagerChangeHelper `class` + * This is an open ticket manager change helper. + * + * It is used to let the "onChange" event in the `ODManager` class work. + * You will probably use this class when extending your own `ODManager` + */ +export class ODManagerChangeHelper { + #change: (() => void)|null = null + + protected _change(){ + if (this.#change){ + try{ + this.#change() + }catch(err){ + process.emit("uncaughtException",err) + throw new ODSystemError("Failed to execute _change() callback!") + } + } + } + /****(❌ SYSTEM ONLY!!)** Set the callback executed when a value inside this class changes */ + changed(callback:(() => void)|null){ + this.#change = callback + } +} + +/**## ODManagerRedirectHelper `class` + * This is open ticket ticket manager redirect helper. + * + * It is used to redirect a source to another source when the id isn't found. + * + * It will be used in **Open Discord** to allow plugins from all projects to work seamlessly! + * ## **(❌ SYSTEM ONLY!!)** + */ +export class ODManagerRedirectHelper { + #data: {fromSource:string,toSource:string}[] = [] + + /****(❌ SYSTEM ONLY!!)** Add a redirect to this manager. Returns `true` when overwritten. */ + add(fromSource:string, toSource:string){ + const index = this.#data.findIndex((data) => data.fromSource === fromSource) + if (index > -1){ + //already exists + this.#data[index] = {fromSource,toSource} + return true + }else{ + //doesn't exist + this.#data.push({fromSource,toSource}) + return false + } + } + /****(❌ SYSTEM ONLY!!)** Remove a redirect from this manager. Returns `true` when it existed. */ + remove(fromSource:string, toSource:string){ + const index = this.#data.findIndex((data) => data.fromSource === fromSource && data.toSource == toSource) + if (index > -1){ + //already exists + this.#data.splice(index,1) + return true + }else return false + } + /**List all redirects from this manager. */ + list(){ + return [...this.#data] + } +} + +/**## ODManagerData `class` + * This is open ticket manager data. + * + * It provides a template for all classes that are used in the `ODManager`. + * + * There is an `id:ODId` property & also some events used in the manager. + */ +export class ODManagerData extends ODManagerChangeHelper { + /**The id of this data */ + id: ODId + + constructor(id:ODValidId){ + if (typeof id != "string" && !(id instanceof ODId)) throw new ODSystemError("Invalid constructor parameter => id:ODValidId") + super() + this.id = new ODId(id) + } +} + +/**## ODManagerCallback `type` + * This is a callback for the `onChange` and `onRemove` events in the `ODManager` + */ +export type ODManagerCallback = (data:DataType) => void +/**## ODManagerAddCallback `type` + * This is a callback for the `onAdd` event in the `ODManager` + */ +export type ODManagerAddCallback = (data:DataType, overwritten:boolean) => void + +/**## ODManager `class` + * This is an open ticket manager. + * + * It can be used to store & manage different aspects of the bot! + * You will probably to extend this class when creating your own classes & managers. + * + * This class has many useful functions based on `ODId` (add, get, remove, getAll, getFiltered, exists) + */ +export class ODManager extends ODManagerChangeHelper { + /**Alias to open ticket debugger. */ + #debug?: ODDebugger + /**The message to send when debugging this manager. */ + #debugname?: string + /**An array storing all data classes ❌ **(don't edit unless really needed!)***/ + #data: DataType[] = [] + /**An array storing all listeners when data is added. */ + #addListeners: ODManagerAddCallback[] = [] + /**An array storing all listeners when data has changed. */ + #changeListeners: ODManagerCallback[] = [] + /**An array storing all listeners when data is removed. */ + #removeListeners: ODManagerCallback[] = [] + /**Handle all redirects in this `ODManager` */ + redirects: ODManagerRedirectHelper = new ODManagerRedirectHelper() + + constructor(debug?:ODDebugger, debugname?:string){ + super() + this.#debug = debug + this.#debugname = debugname + } + + /**Add data to the manager. The id will be fetched from the data class! You can optionally select to overwrite existing data!*/ + add(data:DataType|DataType[], overwrite?:boolean): boolean { + //repeat same command when data is an array + if (Array.isArray(data)){ + data.forEach((arrayData) => { + this.add(arrayData,overwrite) + }) + return false + } + + //add data + const existIndex = this.#data.findIndex((d) => d.id.value === data.id.value) + if (existIndex < 0){ + this.#data.push(data) + if (this.#debug) this.#debug.debug("Added new "+this.#debugname+" to manager",[{key:"id",value:data.id.value},{key:"overwrite",value:"false"}]) + + //change listeners + data.changed(() => { + //notify change in upper-manager (because data in this manager changed) + this._change() + this.#changeListeners.forEach((cb) => { + try{ + cb(data) + }catch(err){ + throw new ODSystemError("Failed to run manager onChange() listener.\n"+err) + } + }) + }) + + //add listeners + this.#addListeners.forEach((cb) => { + try{ + cb(data,false) + }catch(err){ + throw new ODSystemError("Failed to run manager onAdd() listener.\n"+err) + } + }) + + //notify change in upper-manager (because data added) + this._change() + + return false + }else{ + if (!overwrite) throw new ODSystemError("Id '"+data.id.value+"' already exists in "+this.#debugname+" manager. Use 'overwrite:true' to allow overwriting!") + this.#data[existIndex] = data + if (this.#debug) this.#debug.debug("Added new "+this.#debugname+" to manager",[{key:"id",value:data.id.value},{key:"overwrite",value:"true"}]) + + //change listeners + data.changed(() => { + //notify change in upper-manager (because data in this manager changed) + this._change() + this.#changeListeners.forEach((cb) => { + try{ + cb(data) + }catch(err){ + throw new ODSystemError("Failed to run manager onChange() listener.\n"+err) + } + }) + }) + + //add listeners + this.#addListeners.forEach((cb) => { + try{ + cb(data,true) + }catch(err){ + throw new ODSystemError("Failed to run manager onAdd() listener.\n"+err) + } + }) + + //notify change in upper-manager (because data added) + this._change() + + return true + } + } + /**Get data that matches the `ODId`. Returns the found data.*/ + get(id:ODValidId): DataType|null { + const newId = new ODId(id) + const d = this.#data.find((a) => a.id.value == newId.value) + if (d) return d + else{ + const redirect = this.redirects.list().find((redirect) => redirect.fromSource === newId.source) + if (!redirect) return null + else{ + const redirectId = new ODId(redirect.toSource+":"+newId.identifier) + return this.get(redirectId) + } + } + } + /**Remove data that matches the `ODId`. Returns the removed data.*/ + remove(id:ODValidId): DataType|null { + const newId = new ODId(id) + const index = this.#data.findIndex((a) => a.id.value == newId.value) + if (index < 0){ + const redirect = this.redirects.list().find((redirect) => redirect.fromSource === newId.source) + if (!redirect){ + if (this.#debug) this.#debug.debug("Removed "+this.#debugname+" from manager",[{key:"id",value:newId.value},{key:"found",value:"false"}]) + return null + }else{ + const redirectId = new ODId(redirect.toSource+":"+newId.identifier) + return this.remove(redirectId) + } + } + if (this.#debug) this.#debug.debug("Removed "+this.#debugname+" from manager",[{key:"id",value:newId.value},{key:"found",value:"true"}]) + const data = this.#data.splice(index,1)[0] + + //change listeners + data.changed(null) + + //remove listeners + this.#removeListeners.forEach((cb) => { + try{ + cb(data) + }catch(err){ + throw new ODSystemError("Failed to run manager onRemove() listener.\n"+err) + } + }) + + //notify change in upper-manager (because data removed) + this._change() + + return data + } + /**Check if data that matches the `ODId` exists. Returns a boolean.*/ + exists(id:ODValidId): boolean { + const newId = new ODId(id) + const d = this.#data.find((a) => a.id.value == newId.value) + if (d) return true + else{ + const redirect = this.redirects.list().find((redirect) => redirect.fromSource === newId.source) + if (!redirect) return false + else{ + const redirectId = new ODId(redirect.toSource+":"+newId.identifier) + return this.exists(redirectId) + } + } + } + /**Get all data inside this manager*/ + getAll(): DataType[] { + return [...this.#data] + } + /**Get all data that matches inside the filter function*/ + getFiltered(predicate:(value:DataType, index:number, array:DataType[]) => unknown): DataType[] { + return this.#data.filter(predicate) + } + /**Get all data that matches the regex*/ + getRegex(regex:RegExp): DataType[] { + return this.#data.filter((data) => regex.test(data.id.value)) + } + /**Get the length of the data inside this manager*/ + getLength(){ + return this.#data.length + } + /**Get a list of all the ids inside this manager*/ + getIds(): ODId[] { + return this.#data.map((d) => d.id) + } + /**Use the open ticket debugger in this manager for logs*/ + useDebug(debug?:ODDebugger, debugname?:string){ + this.#debug = debug + this.#debugname = debugname + } + /**Listen for when data is added to this manager. */ + onAdd(callback:ODManagerAddCallback){ + this.#addListeners.push(callback) + } + /**Listen for when data is changed in this manager. */ + onChange(callback:ODManagerCallback){ + this.#changeListeners.push(callback) + } + /**Listen for when data is removed from this manager. */ + onRemove(callback:ODManagerCallback){ + this.#removeListeners.push(callback) + } +} + +/**## ODManagerWithSafety `class` + * This is an open ticket safe manager. + * + * It functions exactly the same as a normal `ODManager`, but it has 1 function extra! + * The `getSafe()` function will always return data, because when it doesn't find an id, it returns pre-configured backup data. + */ +export class ODManagerWithSafety extends ODManager { + /**The function that creates backup data returned in `getSafe()` when an id is missing in this manager. */ + #backupCreator: () => DataType + /** Temporary storage for manager debug name. */ + #debugname: string + + constructor(backupCreator:() => DataType, debug?:ODDebugger, debugname?:string){ + super(debug,debugname) + this.#backupCreator = backupCreator + this.#debugname = debugname ?? "unknown" + } + + /**Get data that matches the `ODId`. Returns the backup data when not found. + * + * ### ⚠️ This should only be used when the data doesn't need to be written/edited + */ + getSafe(id:ODValidId): DataType { + const data = super.get(id) + if (!data){ + process.emit("uncaughtException",new ODSystemError("ODManagerWithSafety:getSafe(\""+id+"\") => Unknown Id => Used backup data ("+this.#debugname+" manager)")) + return this.#backupCreator() + } + else return data + } +} + +/**## ODVersionManager `class` + * A open ticket version manager. + * + * It is used to manage different `ODVersion`'s from the bot. You will use it to check which version of the bot is used. + */ +export class ODVersionManager extends ODManager { + constructor(){ + super() + } +} + +/**## ODVersion `class` + * This is an open ticket version. + * + * It has many features like comparing versions & checking if they are compatible. + * + * You can use it in your own plugin, but most of the time you will use it to check the open ticket version! + */ +export class ODVersion extends ODManagerData { + /**The first number of the version (example: `v1.2.3` => `1`) */ + primary: number + /**The second number of the version (example: `v1.2.3` => `2`) */ + secondary: number + /**The third number of the version (example: `v1.2.3` => `3`) */ + tertiary: number + + constructor(id:ODValidId, primary:number, secondary:number, tertiary:number){ + super(id) + if (typeof primary != "number") throw new ODSystemError("Invalid constructor parameter => primary:number") + if (typeof secondary != "number") throw new ODSystemError("Invalid constructor parameter => secondary:number") + if (typeof tertiary != "number") throw new ODSystemError("Invalid constructor parameter => tertiary:number") + + this.primary = primary + this.secondary = secondary + this.tertiary = tertiary + } + + /**Get the version from a string (also possible with `v` prefix) + * @example const version = api.ODVersion.fromString("id","v1.2.3") //creates version 1.2.3 + */ + static fromString(id:ODValidId, version:string){ + if (typeof id != "string" && !(id instanceof ODId)) throw new ODSystemError("Invalid function parameter => id:ODValidId") + if (typeof version != "string") throw new ODSystemError("Invalid function parameter => version:string") + + const versionCheck = (version.startsWith("v")) ? version.substring(1) : version + const splittedVersion = versionCheck.split(".") + + return new this(id,Number(splittedVersion[0]),Number(splittedVersion[1]),Number(splittedVersion[2])) + } + /**Get the version as a string (`noprefix:true` => with `v` prefix) + * @example + * new api.ODVersion(1,0,0).toString(false) //returns "v1.0.0" + * new api.ODVersion(1,0,0).toString(true) //returns "1.0.0" + */ + toString(noprefix?:boolean){ + const prefix = noprefix ? "" : "v" + return prefix+[this.primary,this.secondary,this.tertiary].join(".") + } + /**Compare this version with another version and returns the result: `higher`, `lower` or `equal` + * @example + * new api.ODVersion(1,0,0).compare(new api.ODVersion(1,2,0)) //returns "lower" + * new api.ODVersion(1,3,0).compare(new api.ODVersion(1,2,0)) //returns "higher" + * new api.ODVersion(1,2,0).compare(new api.ODVersion(1,2,0)) //returns "equal" + */ + compare(comparator:ODVersion): "higher"|"lower"|"equal" { + if (!(comparator instanceof ODVersion)) throw new ODSystemError("Invalid function parameter => comparator:ODVersion") + + if (this.primary < comparator.primary) return "lower" + else if (this.primary > comparator.primary) return "higher" + else { + if (this.secondary < comparator.secondary) return "lower" + else if (this.secondary > comparator.secondary) return "higher" + else { + if (this.tertiary < comparator.tertiary) return "lower" + else if (this.tertiary > comparator.tertiary) return "higher" + else return "equal" + } + } + } + /**Check if this version is included in the list + * @example + * const list = [ + * new api.ODVersion(1,0,0), + * new api.ODVersion(1,0,1), + * new api.ODVersion(1,0,2) + * ] + * new api.ODVersion(1,0,0).compatible(list) //returns true + * new api.ODVersion(1,0,1).compatible(list) //returns true + * new api.ODVersion(1,0,3).compatible(list) //returns false + */ + compatible(list:ODVersion[]): boolean { + if (!Array.isArray(list)) throw new ODSystemError("Invalid function parameter => list:ODVersion[]") + if (!list.every((v) => (v instanceof ODVersion))) throw new ODSystemError("Invalid function parameter => list:ODVersion[]") + + return list.some((v) => { + return (v.toString() === this.toString()) + }) + } +} + +/**## ODHTTPGetRequest `class` + * This is a class that can help you with creating simple HTTP GET requests. + * + * It works using the native node.js fetch() method. You can configure all options in the constructor! + * @example + * const request = new api.ODHTTPGetRequest("https://www.example.com/abc.txt",false,{}) + * + * const result = await request.run() + * result.body //the response body (string) + * result.status //the response code (number) + * result.response //the full response (object) + */ +export class ODHTTPGetRequest { + /**The url used in the request */ + url: string + /**The request config for additional options */ + config: RequestInit + /**Throw on error OR return http code 500 */ + throwOnError: boolean + + constructor(url:string,throwOnError:boolean,config?:RequestInit){ + if (typeof url != "string") throw new ODSystemError("Invalid constructor parameter => url:string") + if (typeof throwOnError != "boolean") throw new ODSystemError("Invalid constructor parameter => throwOnError:boolean") + if (typeof config != "undefined" && typeof config != "object") throw new ODSystemError("Invalid constructor parameter => config?:RequestInit") + + this.url = url + this.throwOnError = throwOnError + const newConfig = config ?? {} + newConfig.method = "GET" + this.config = newConfig + } + + /**Execute the GET request.*/ + run(): Promise<{status:number, body:string, response?:Response}> { + return new Promise(async (resolve,reject) => { + try{ + const response = await fetch(this.url,this.config) + resolve({ + status:response.status, + body:(await response.text()), + response:response + }) + }catch(err){ + if (this.throwOnError) return reject("[OPENTICKET ERROR]: ODHTTPGetRequest => Unknown fetch() error: "+err) + else return resolve({ + status:500, + body:"Open Ticket Error: Unknown fetch() error: "+err, + }) + } + }) + } +} + +/**## ODHTTPPostRequest `class` + * This is a class that can help you with creating simple HTTP POST requests. + * + * It works using the native node.js fetch() method. You can configure all options in the constructor! + * @example + * const request = new api.ODHTTPPostRequest("https://www.example.com/abc.txt",false,{}) + * + * const result = await request.run() + * result.body //the response body (string) + * result.status //the response code (number) + * result.response //the full response (object) + */ +export class ODHTTPPostRequest { + /**The url used in the request */ + url: string + /**The request config for additional options */ + config: RequestInit + /**Throw on error OR return http code 500 */ + throwOnError: boolean + + constructor(url:string,throwOnError:boolean,config?:RequestInit){ + if (typeof url != "string") throw new ODSystemError("Invalid constructor parameter => url:string") + if (typeof throwOnError != "boolean") throw new ODSystemError("Invalid constructor parameter => throwOnError:boolean") + if (typeof config != "undefined" && typeof config != "object") throw new ODSystemError("Invalid constructor parameter => config?:RequestInit") + + this.url = url + this.throwOnError = throwOnError + const newConfig = config ?? {} + newConfig.method = "POST" + this.config = newConfig + } + + /**Execute the POST request.*/ + run(): Promise<{status:number, body:string, response?:Response}> { + return new Promise(async (resolve,reject) => { + try{ + const response = await fetch(this.url,this.config) + resolve({ + status:response.status, + body:(await response.text()), + response:response + }) + }catch(err){ + if (this.throwOnError) return reject("[OPENTICKET ERROR]: ODHTTPPostRequest => Unknown fetch() error: "+err) + else return resolve({ + status:500, + body:"Open Ticket Error: Unknown fetch() error!", + }) + } + }) + } +} + +/**## ODEnvHelper `class` + * This is a utility class that helps you with reading the ENV. + * + * It has support for the built-in `process.env` & `.env` file + * @example + * const envHelper = new api.ODEnvHelper() + * + * const variableA = envHelper.getVariable("value-a") + * const variableB = envHelper.getVariable("value-b","dotenv") //only get from .env + * const variableA = envHelper.getVariable("value-c","env") //only get from process.env + */ +export class ODEnvHelper { + /**All variables found in the `.env` file */ + dotenv: object + /**All variables found in `process.env` */ + env: object + + constructor(customEnvPath?:string){ + if (typeof customEnvPath != "undefined" && typeof customEnvPath != "string") throw new ODSystemError("Invalid constructor parameter => customEnvPath?:string") + + const path = customEnvPath ? customEnvPath : ".env" + this.dotenv = fs.existsSync(path) ? this.#readDotEnv(fs.readFileSync(path)) : {} + this.env = process.env + } + + /**Get a variable from the env */ + getVariable(name:string,source?:"dotenv"|"env"): any|undefined { + if (typeof name != "string") throw new ODSystemError("Invalid function parameter => name:string") + if ((typeof source != "undefined" && typeof source != "string") || (source && !["env","dotenv"].includes(source))) throw new ODSystemError("Invalid function parameter => source:'dotenv'|'env'") + + if (source == "dotenv"){ + return this.dotenv[name] + }else if (source == "env"){ + return this.env[name] + }else{ + //when no source specified => .env has priority over process.env + if (this.dotenv[name]) return this.dotenv[name] + else return this.env[name] + } + } + + //THIS CODE IS COPIED FROM THE DODENV-LIB + //Repo: https://github.com/motdotla/dotenv + //Source: https://github.com/motdotla/dotenv/blob/master/lib/main.js#L12 + #readDotEnv(src:Buffer){ + const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg + const obj = {} + + // Convert buffer to string + let lines = src.toString() + + // Convert line breaks to same format + lines = lines.replace(/\r\n?/mg, '\n') + + let match + while ((match = LINE.exec(lines)) != null) { + const key = match[1] + + // Default undefined or null to empty string + let value = (match[2] || '') + + // Remove whitespace + value = value.trim() + + // Check if double quoted + const maybeQuote = value[0] + + // Remove surrounding quotes + value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2') + + // Expand newlines if double quoted + if (maybeQuote === '"') { + value = value.replace(/\\n/g, '\n') + value = value.replace(/\\r/g, '\r') + } + + // Add to object + obj[key] = value + } + return obj + } +} + +/**## ODSystemError `class` + * A wrapper for the node.js `Error` class that makes the error look better in the console! + * + * This wrapper is made for open ticket system errors! **It can only be used by open ticket itself!** + */ +export class ODSystemError extends Error { + /**This variable gets detected by the error handling system to know how to render it */ + _ODErrorType = "system" + + /**Create an `ODSystemError` directly from an `Error` class */ + static fromError(err:Error){ + err["_ODErrorType"] = "system" + return err as ODSystemError + } +} + +/**## ODPluginError `class` + * A wrapper for the node.js `Error` class that makes the error look better in the console! + * + * This wrapper is made for open ticket plugin errors! **It can only be used by plugins!** + */ +export class ODPluginError extends Error { + /**This variable gets detected by the error handling system to know how to render it */ + _ODErrorType = "plugin" + + /**Create an `ODPluginError` directly from an `Error` class */ + static fromError(err:Error){ + err["_ODErrorType"] = "plugin" + return err as ODPluginError + } +} + +/**Oh, what could this be `¯\_(ツ)_/¯` */ +export interface ODEasterEggs { + creator:string, + translators:string[] +} \ No newline at end of file diff --git a/src/core/api/modules/builder.ts b/src/core/api/modules/builder.ts new file mode 100644 index 0000000..9fb9f4a --- /dev/null +++ b/src/core/api/modules/builder.ts @@ -0,0 +1,1245 @@ +/////////////////////////////////////// +//BUILDER MODULE +/////////////////////////////////////// +import { ODId, ODValidButtonColor, ODValidId, ODSystemError, ODInterfaceWithPartialProperty, ODManagerWithSafety, ODManagerData } from "./base" +import * as discord from "discord.js" +import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker" +import { ODDebugger } from "./console" + +/**## ODBuilderImplementation `class` + * This is an open ticket builder implementation. + * + * It is a basic implementation of the `ODWorkerManager` used by all `ODBuilder` classes. + * + * This class can't be used stand-alone & needs to be extended from! + */ +export class ODBuilderImplementation extends ODManagerData { + /**The manager that has all workers of this implementation */ + workers: ODWorkerManager + /**Cache a build or create it every time from scratch when this.build() gets executed. */ + allowCache: boolean = false + /**Did the build already got created/cached? */ + didCache: boolean = false + /**The cache of this build. */ + cache:BuildType|null = null + + constructor(id:ODValidId, callback?:ODWorkerCallback, priority?:number, callbackId?:ODValidId){ + super(id) + this.workers = new ODWorkerManager("ascending") + if (callback) this.workers.add(new ODWorker(callbackId ? callbackId : id,priority ?? 0,callback)) + } + + /**Set if caching is allowed */ + setCacheMode(allowed:boolean){ + this.allowCache = allowed + this.resetCache() + return this + } + /**Reset the current cache */ + resetCache(){ + this.cache = null + this.didCache = false + return this + } + /**Execute all workers & return the result. */ + async build(source:Source, params:Params): Promise { + throw new ODSystemError("Tried to build an unimplemented ODBuilderImplementation") + } +} + +/**## ODBuilderManager `class` + * This is an open ticket builder manager. + * + * It contains all Open Ticket builders. You can find messages, embeds, files & dropdowns, buttons & modals all here! + * + * Using the Open Ticket builder system has a few advantages compared to vanilla discord.js: + * - plugins can extend/edit messages + * - automatically reply on error + * - independent workers (with priority) + * - fail-safe design using try-catch + * - cache frequently used objects + * - get to know the source of the build request for a specific message, button, etc + * - And so much more! + */ +export class ODBuilderManager { + /**The manager for all button builders */ + buttons: ODButtonManager + /**The manager for all dropdown builders */ + dropdowns: ODDropdownManager + /**The manager for all file/attachment builders */ + files: ODFileManager + /**The manager for all embed builders */ + embeds: ODEmbedManager + /**The manager for all message builders */ + messages: ODMessageManager + /**The manager for all modal builders */ + modals: ODModalManager + + constructor(debug:ODDebugger){ + this.buttons = new ODButtonManager(debug) + this.dropdowns = new ODDropdownManager(debug) + this.files = new ODFileManager(debug) + this.embeds = new ODEmbedManager(debug) + this.messages = new ODMessageManager(debug) + this.modals = new ODModalManager(debug) + } +} + +/**## ODComponentBuildResult `interface` + * This interface contains the result from a built component (button/dropdown). This can be used in the `ODMessage` builder! + */ +export interface ODComponentBuildResult { + /**The id of this component (button or dropdown) */ + id:ODId, + /**The discord component or `\n` when it is a spacer between action rows */ + component:discord.MessageActionRowComponentBuilder|"\n"|null +} + +/**## ODButtonManager `class` + * This is an open ticket button manager. + * + * It contains all Open Ticket button builders. Here, you can add your own buttons or edit existing ones! + * + * It's recommended to use this system in combination with all the other Open Ticket builders! + */ +export class ODButtonManager extends ODManagerWithSafety> { + constructor(debug:ODDebugger){ + super(() => { + return new ODButton("openticket:unknown-button",(instance,params,source,cancel) => { + instance.setCustomId("od:unknown-button") + instance.setMode("button") + instance.setColor("red") + instance.setLabel("") + instance.setEmoji("✖") + instance.setDisabled(true) + cancel() + }) + },debug,"button") + } + + /**Get a newline component for buttons & dropdowns! */ + getNewLine(id:ODValidId): ODComponentBuildResult { + return { + id:new ODId(id), + component:"\n" + } + } +} + +/**## ODButtonData `interface` + * This interface contains the data to build a button. + */ +export interface ODButtonData { + /**The custom id of this button */ + customId:string, + /**The mode of this button */ + mode:"button"|"url", + /**The url for when the mode is set to "url" */ + url:string|null, + /**The button color */ + color:ODValidButtonColor|null, + /**The button label */ + label:string|null, + /**The button emoji */ + emoji:string|null, + /**Is the button disabled? */ + disabled:boolean +} + +/**## ODButtonInstance `class` + * This is an open ticket button instance. + * + * It contains all properties & functions to build a button! + */ +export class ODButtonInstance { + /**The current data of this button */ + data: ODButtonData = { + customId:"", + mode:"button", + url:null, + color:null, + label:null, + emoji:null, + disabled:false + } + + /**Set the custom id of this button */ + setCustomId(id:ODButtonData["customId"]){ + this.data.customId = id + return this + } + /**Set the mode of this button */ + setMode(mode:ODButtonData["mode"]){ + this.data.mode = mode + return this + } + /**Set the url of this button */ + setUrl(url:ODButtonData["url"]){ + this.data.url = url + return this + } + /**Set the color of this button */ + setColor(color:ODButtonData["color"]){ + this.data.color = color + return this + } + /**Set the label of this button */ + setLabel(label:ODButtonData["label"]){ + this.data.label = label + return this + } + /**Set the emoji of this button */ + setEmoji(emoji:ODButtonData["emoji"]){ + this.data.emoji = emoji + return this + } + /**Disable this button */ + setDisabled(disabled:ODButtonData["disabled"]){ + this.data.disabled = disabled + return this + } +} + +/**## ODButton `class` + * This is an open ticket button builder. + * + * With this class, you can create a button to use in a message. + * The only difference with normal buttons is that this one can be edited by Open Ticket plugins! + * + * This is possible by using "workers" or multiple functions that will be executed in priority order! + */ +export class ODButton extends ODBuilderImplementation { + /**Build this button & compile it for discord.js */ + async build(source:Source, params:Params){ + if (this.didCache && this.cache && this.allowCache) return this.cache + + try { + //create instance + const instance = new ODButtonInstance() + + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + + //create the discord.js button + const button = new discord.ButtonBuilder() + if (instance.data.mode == "button") button.setCustomId(instance.data.customId) + if (instance.data.mode == "url") button.setStyle(discord.ButtonStyle.Link) + else if (instance.data.color == "gray") button.setStyle(discord.ButtonStyle.Secondary) + else if (instance.data.color == "blue") button.setStyle(discord.ButtonStyle.Primary) + else if (instance.data.color == "green") button.setStyle(discord.ButtonStyle.Success) + else if (instance.data.color == "red") button.setStyle(discord.ButtonStyle.Danger) + if (instance.data.url) button.setURL(instance.data.url) + if (instance.data.label) button.setLabel(instance.data.label) + if (instance.data.emoji) button.setEmoji(instance.data.emoji) + if (instance.data.disabled) button.setDisabled(instance.data.disabled) + if (!instance.data.emoji && !instance.data.label) button.setLabel(instance.data.customId) + + this.cache = {id:this.id,component:button} + this.didCache = true + return {id:this.id,component:button} + }catch(err){ + process.emit("uncaughtException",new ODSystemError("ODButton:build(\""+this.id.value+"\") => Major Error (see next error)")) + process.emit("uncaughtException",err) + return {id:this.id,component:null} + } + } +} + +/**## ODDropdownManager `class` + * This is an open ticket dropdown manager. + * + * It contains all Open Ticket dropdown builders. Here, you can add your own dropdowns or edit existing ones! + * + * It's recommended to use this system in combination with all the other Open Ticket builders! + */ +export class ODDropdownManager extends ODManagerWithSafety> { + constructor(debug:ODDebugger){ + super(() => { + return new ODDropdown("openticket:unknown-dropdown",(instance,params,source,cancel) => { + instance.setCustomId("od:unknown-dropdown") + instance.setType("string") + instance.setPlaceholder("❌ ") + instance.setDisabled(true) + instance.setOptions([ + {emoji:"❌",label:"",value:"error"} + ]) + cancel() + }) + },debug,"dropdown") + } + + /**Get a newline component for buttons & dropdowns! */ + getNewLine(id:ODValidId): ODComponentBuildResult { + return { + id:new ODId(id), + component:"\n" + } + } +} + +/**## ODDropdownData `interface` + * This interface contains the data to build a dropdown. + */ +export interface ODDropdownData { + /**The custom id of this dropdown */ + customId:string, + /**The type of this dropdown */ + type:"string"|"role"|"channel"|"user"|"mentionable", + /**The placeholder of this dropdown */ + placeholder:string|null, + /**The minimum amount of items to be selected in this dropdown */ + minValues:number|null, + /**The maximum amount of items to be selected in this dropdown */ + maxValues:number|null, + /**Is this dropdown disabled? */ + disabled:boolean, + /**Allowed channel types when the type is "channel" */ + channelTypes:discord.ChannelType[] + + /**The options when the type is "string" */ + options:discord.SelectMenuComponentOptionData[], + /**The options when the type is "user" */ + users:discord.User[], + /**The options when the type is "role" */ + roles:discord.Role[], + /**The options when the type is "channel" */ + channels:discord.Channel[], + /**The options when the type is "mentionable" */ + mentionables:(discord.User|discord.Role)[], +} + +/**## ODDropdownInstance `class` + * This is an open ticket dropdown instance. + * + * It contains all properties & functions to build a dropdown! + */ +export class ODDropdownInstance { + /**The current data of this dropdown */ + data: ODDropdownData = { + customId:"", + type:"string", + placeholder:null, + minValues:null, + maxValues:null, + disabled:false, + channelTypes:[], + + options:[], + users:[], + roles:[], + channels:[], + mentionables:[] + } + + /**Set the custom id of this dropdown */ + setCustomId(id:ODDropdownData["customId"]){ + this.data.customId = id + return this + } + /**Set the type of this dropdown */ + setType(type:ODDropdownData["type"]){ + this.data.type = type + return this + } + /**Set the placeholder of this dropdown */ + setPlaceholder(placeholder:ODDropdownData["placeholder"]){ + this.data.placeholder = placeholder + return this + } + /**Set the minimum amount of values in this dropdown */ + setMinValues(minValues:ODDropdownData["minValues"]){ + this.data.minValues = minValues + return this + } + /**Set the maximum amount of values ax this dropdown */ + setMaxValues(maxValues:ODDropdownData["maxValues"]){ + this.data.maxValues = maxValues + return this + } + /**Set the disabled of this dropdown */ + setDisabled(disabled:ODDropdownData["disabled"]){ + this.data.disabled = disabled + return this + } + /**Set the channel types of this dropdown */ + setChannelTypes(channelTypes:ODDropdownData["channelTypes"]){ + this.data.channelTypes = channelTypes + return this + } + /**Set the options of this dropdown (when `type == "string"`) */ + setOptions(options:ODDropdownData["options"]){ + this.data.options = options + return this + } + /**Set the users of this dropdown (when `type == "user"`) */ + setUsers(users:ODDropdownData["users"]){ + this.data.users = users + return this + } + /**Set the roles of this dropdown (when `type == "role"`) */ + setRoles(roles:ODDropdownData["roles"]){ + this.data.roles = roles + return this + } + /**Set the channels of this dropdown (when `type == "channel"`) */ + setChannels(channels:ODDropdownData["channels"]){ + this.data.channels = channels + return this + } + /**Set the mentionables of this dropdown (when `type == "mentionable"`) */ + setMentionables(mentionables:ODDropdownData["mentionables"]){ + this.data.mentionables = mentionables + return this + } +} + +/**## ODDropdown `class` + * This is an open ticket dropdown builder. + * + * With this class, you can create a dropdown to use in a message. + * The only difference with normal dropdowns is that this one can be edited by Open Ticket plugins! + * + * This is possible by using "workers" or multiple functions that will be executed in priority order! + */ +export class ODDropdown extends ODBuilderImplementation { + /**Build this dropdown & compile it for discord.js */ + async build(source:Source, params:Params){ + if (this.didCache && this.cache && this.allowCache) return this.cache + + try{ + //create instance + const instance = new ODDropdownInstance() + + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + + //create the discord.js dropdown + if (instance.data.type == "string"){ + const dropdown = new discord.StringSelectMenuBuilder() + dropdown.setCustomId(instance.data.customId) + dropdown.setOptions(...instance.data.options) + if (instance.data.placeholder) dropdown.setPlaceholder(instance.data.placeholder) + if (instance.data.minValues) dropdown.setMinValues(instance.data.minValues) + if (instance.data.maxValues) dropdown.setMaxValues(instance.data.maxValues) + if (instance.data.disabled) dropdown.setDisabled(instance.data.disabled) + + this.cache = {id:this.id,component:dropdown} + this.didCache = true + return {id:this.id,component:dropdown} + + }else if (instance.data.type == "user"){ + const dropdown = new discord.UserSelectMenuBuilder() + dropdown.setCustomId(instance.data.customId) + if (instance.data.users.length > 0) dropdown.setDefaultUsers(...instance.data.users.map((u) => u.id)) + if (instance.data.placeholder) dropdown.setPlaceholder(instance.data.placeholder) + if (instance.data.minValues) dropdown.setMinValues(instance.data.minValues) + if (instance.data.maxValues) dropdown.setMaxValues(instance.data.maxValues) + if (instance.data.disabled) dropdown.setDisabled(instance.data.disabled) + + this.cache = {id:this.id,component:dropdown} + this.didCache = true + return {id:this.id,component:dropdown} + + }else if (instance.data.type == "role"){ + const dropdown = new discord.RoleSelectMenuBuilder() + dropdown.setCustomId(instance.data.customId) + if (instance.data.roles.length > 0) dropdown.setDefaultRoles(...instance.data.roles.map((r) => r.id)) + if (instance.data.placeholder) dropdown.setPlaceholder(instance.data.placeholder) + if (instance.data.minValues) dropdown.setMinValues(instance.data.minValues) + if (instance.data.maxValues) dropdown.setMaxValues(instance.data.maxValues) + if (instance.data.disabled) dropdown.setDisabled(instance.data.disabled) + + this.cache = {id:this.id,component:dropdown} + this.didCache = true + return {id:this.id,component:dropdown} + + }else if (instance.data.type == "channel"){ + const dropdown = new discord.ChannelSelectMenuBuilder() + dropdown.setCustomId(instance.data.customId) + if (instance.data.channels.length > 0) dropdown.setDefaultChannels(...instance.data.channels.map((c) => c.id)) + if (instance.data.placeholder) dropdown.setPlaceholder(instance.data.placeholder) + if (instance.data.minValues) dropdown.setMinValues(instance.data.minValues) + if (instance.data.maxValues) dropdown.setMaxValues(instance.data.maxValues) + if (instance.data.disabled) dropdown.setDisabled(instance.data.disabled) + + this.cache = {id:this.id,component:dropdown} + this.didCache = true + return {id:this.id,component:dropdown} + + }else if (instance.data.type == "mentionable"){ + const dropdown = new discord.MentionableSelectMenuBuilder() + + const values: ({type:discord.SelectMenuDefaultValueType.User,id:string}|{type:discord.SelectMenuDefaultValueType.Role,id:string})[] = [] + instance.data.mentionables.forEach((m) => { + if (m instanceof discord.User){ + values.push({type:discord.SelectMenuDefaultValueType.User,id:m.id}) + }else{ + values.push({type:discord.SelectMenuDefaultValueType.Role,id:m.id}) + } + }) + + dropdown.setCustomId(instance.data.customId) + if (instance.data.mentionables.length > 0) dropdown.setDefaultValues(...values) + if (instance.data.placeholder) dropdown.setPlaceholder(instance.data.placeholder) + if (instance.data.minValues) dropdown.setMinValues(instance.data.minValues) + if (instance.data.maxValues) dropdown.setMaxValues(instance.data.maxValues) + if (instance.data.disabled) dropdown.setDisabled(instance.data.disabled) + + this.cache = {id:this.id,component:dropdown} + this.didCache = true + return {id:this.id,component:dropdown} + }else{ + throw new Error("Tried to build an ODDropdown with unknown type!") + } + }catch(err){ + process.emit("uncaughtException",new ODSystemError("ODDropdown:build(\""+this.id.value+"\") => Major Error (see next error)")) + process.emit("uncaughtException",err) + return {id:this.id,component:null} + } + } +} + +/**## ODFileManager `class` + * This is an open ticket file manager. + * + * It contains all Open Ticket file builders. Here, you can add your own files or edit existing ones! + * + * It's recommended to use this system in combination with all the other Open Ticket builders! + */ +export class ODFileManager extends ODManagerWithSafety> { + constructor(debug:ODDebugger){ + super(() => { + return new ODFile("openticket:unknown-file",(instance,params,source,cancel) => { + instance.setName("openticket_unknown-file.txt") + instance.setDescription("❌ ") + instance.setContents("Couldn't find file in registery `openticket.builders.files`") + cancel() + }) + },debug,"file") + } +} + +/**## ODFileData `interface` + * This interface contains the data to build a file. + */ +export interface ODFileData { + /**The file buffer, string or raw data */ + file:discord.BufferResolvable + /**The name of the file */ + name:string, + /**The description of the file */ + description:string|null, + /**Set the file to be a spoiler */ + spoiler:boolean +} + +/**## ODFileBuildResult `interface` + * This interface contains the result from a built file (attachment). This can be used in the `ODMessage` builder! + */ +export interface ODFileBuildResult { + /**The id of this file */ + id:ODId, + /**The discord file */ + file:discord.AttachmentBuilder|null +} + +/**## ODFileInstance `class` + * This is an open ticket file instance. + * + * It contains all properties & functions to build a file! + */ +export class ODFileInstance { + /**The current data of this file */ + data: ODFileData = { + file:"", + name:"file.txt", + description:null, + spoiler:false + } + + /**Set the file path of this attachment */ + setFile(file:string){ + this.data.file = file + return this + } + /**Set the file contents of this attachment */ + setContents(contents:string|Buffer){ + this.data.file = (typeof contents == "string") ? Buffer.from(contents) : contents + return this + } + /**Set the name of this attachment */ + setName(name:ODFileData["name"]){ + this.data.name = name + return this + } + /**Set the description of this attachment */ + setDescription(description:ODFileData["description"]){ + this.data.description = description + return this + } + /**Set this attachment to show as a spoiler */ + setSpoiler(spoiler:ODFileData["spoiler"]){ + this.data.spoiler = spoiler + return this + } +} + +/**## ODFile `class` + * This is an open ticket file builder. + * + * With this class, you can create a file to use in a message. + * The only difference with normal files is that this one can be edited by Open Ticket plugins! + * + * This is possible by using "workers" or multiple functions that will be executed in priority order! + */ +export class ODFile extends ODBuilderImplementation { + /**Build this attachment & compile it for discord.js */ + async build(source:Source, params:Params){ + if (this.didCache && this.cache && this.allowCache) return this.cache + + try{ + //create instance + const instance = new ODFileInstance() + + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + + //create the discord.js attachment + const file = new discord.AttachmentBuilder(instance.data.file) + file.setName(instance.data.name ? instance.data.name : "file.txt") + if (instance.data.description) file.setDescription(instance.data.description) + if (instance.data.spoiler) file.setSpoiler(instance.data.spoiler) + + + this.cache = {id:this.id,file} + this.didCache = true + return {id:this.id,file} + }catch(err){ + process.emit("uncaughtException",new ODSystemError("ODFile:build(\""+this.id.value+"\") => Major Error (see next error)")) + process.emit("uncaughtException",err) + return {id:this.id,file:null} + } + } +} + +/**## ODEmbedManager `class` + * This is an open ticket embed manager. + * + * It contains all Open Ticket embed builders. Here, you can add your own embeds or edit existing ones! + * + * It's recommended to use this system in combination with all the other Open Ticket builders! + */ +export class ODEmbedManager extends ODManagerWithSafety> { + constructor(debug:ODDebugger){ + super(() => { + return new ODEmbed("openticket:unknown-embed",(instance,params,source,cancel) => { + instance.setFooter("openticket:unknown-embed") + instance.setColor("#ff0000") + instance.setTitle("❌ ") + instance.setDescription("Couldn't find embed in registery `openticket.builders.embeds`") + cancel() + }) + },debug,"embed") + } +} + +/**## ODEmbedData `interface` + * This interface contains the data to build an embed. + */ +export interface ODEmbedData { + /**The title of the embed */ + title:string|null, + /**The color of the embed */ + color:discord.ColorResolvable|null, + /**The url of the embed */ + url:string|null, + /**The description of the embed */ + description:string|null, + /**The author text of the embed */ + authorText:string|null, + /**The author image of the embed */ + authorImage:string|null, + /**The author url of the embed */ + authorUrl:string|null, + /**The footer text of the embed */ + footerText:string|null, + /**The footer image of the embed */ + footerImage:string|null, + /**The image of the embed */ + image:string|null, + /**The thumbnail of the embed */ + thumbnail:string|null, + /**The fields of the embed */ + fields:ODInterfaceWithPartialProperty[], + /**The timestamp of the embed */ + timestamp:number|Date|null +} + +/**## ODEmbedBuildResult `interface` + * This interface contains the result from a built embed. This can be used in the `ODMessage` builder! + */ +export interface ODEmbedBuildResult { + /**The id of this embed */ + id:ODId, + /**The discord embed */ + embed:discord.EmbedBuilder|null +} + +/**## ODEmbedInstance `class` + * This is an open ticket embed instance. + * + * It contains all properties & functions to build an embed! + */ +export class ODEmbedInstance { + /**The current data of this embed */ + data: ODEmbedData = { + title:null, + color:null, + url:null, + description:null, + authorText:null, + authorImage:null, + authorUrl:null, + footerText:null, + footerImage:null, + image:null, + thumbnail:null, + fields:[], + timestamp:null + } + + /**Set the title of this embed */ + setTitle(title:ODEmbedData["title"]){ + this.data.title = title + return this + } + /**Set the color of this embed */ + setColor(color:ODEmbedData["color"]){ + this.data.color = color + return this + } + /**Set the url of this embed */ + setUrl(url:ODEmbedData["url"]){ + this.data.url = url + return this + } + /**Set the description of this embed */ + setDescription(description:ODEmbedData["description"]){ + this.data.description = description + return this + } + /**Set the author of this embed */ + setAuthor(text:ODEmbedData["authorText"], image?:ODEmbedData["authorImage"], url?:ODEmbedData["authorUrl"]){ + this.data.authorText = text + this.data.authorImage = image ?? null + this.data.authorUrl = url ?? null + return this + } + /**Set the footer of this embed */ + setFooter(text:ODEmbedData["footerText"], image?:ODEmbedData["footerImage"]){ + this.data.footerText = text + this.data.footerImage = image ?? null + return this + } + /**Set the image of this embed */ + setImage(image:ODEmbedData["image"]){ + this.data.image = image + return this + } + /**Set the thumbnail of this embed */ + setThumbnail(thumbnail:ODEmbedData["thumbnail"]){ + this.data.thumbnail = thumbnail + return this + } + /**Set the fields of this embed */ + setFields(fields:ODEmbedData["fields"]){ + //TEMP CHECKS + fields.forEach((field,index) => { + if (field.value.length >= 1024) throw new ODSystemError("ODEmbed:setFields() => field "+index+" reached 1024 character limit!") + if (field.name.length >= 256) throw new ODSystemError("ODEmbed:setFields() => field "+index+" reached 256 name character limit!") + }) + + this.data.fields = fields + return this + } + /**Add fields to this embed */ + addFields(...fields:ODEmbedData["fields"]){ + //TEMP CHECKS + fields.forEach((field,index) => { + if (field.value.length >= 1024) throw new ODSystemError("ODEmbed:addFields() => field "+index+" reached 1024 character limit!") + if (field.name.length >= 256) throw new ODSystemError("ODEmbed:addFields() => field "+index+" reached 256 name character limit!") + }) + + this.data.fields.push(...fields) + return this + } + /**Clear all fields from this embed */ + clearFields(){ + this.data.fields = [] + return this + } + /**Set the timestamp of this embed */ + setTimestamp(timestamp:ODEmbedData["timestamp"]){ + this.data.timestamp = timestamp + return this + } +} + +/**## ODEmbed `class` + * This is an open ticket embed builder. + * + * With this class, you can create a embed to use in a message. + * The only difference with normal embeds is that this one can be edited by Open Ticket plugins! + * + * This is possible by using "workers" or multiple functions that will be executed in priority order! + */ +export class ODEmbed extends ODBuilderImplementation { + /**Build this embed & compile it for discord.js */ + async build(source:Source, params:Params){ + if (this.didCache && this.cache && this.allowCache) return this.cache + + try{ + //create instance + const instance = new ODEmbedInstance() + + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + + //create the discord.js embed + const embed = new discord.EmbedBuilder() + if (instance.data.title) embed.setTitle(instance.data.title) + if (instance.data.color) embed.setColor(instance.data.color) + if (instance.data.url) embed.setURL(instance.data.url) + if (instance.data.description) embed.setDescription(instance.data.description) + if (instance.data.authorText) embed.setAuthor({ + name:instance.data.authorText, + iconURL:instance.data.authorImage ?? undefined, + url:instance.data.authorUrl ?? undefined + }) + if (instance.data.footerText) embed.setFooter({ + text:instance.data.footerText, + iconURL:instance.data.footerImage ?? undefined, + }) + if (instance.data.image) embed.setImage(instance.data.image) + if (instance.data.thumbnail) embed.setThumbnail(instance.data.thumbnail) + if (instance.data.timestamp) embed.setTimestamp(instance.data.timestamp) + if (instance.data.fields.length > 0) embed.setFields(instance.data.fields) + + this.cache = {id:this.id,embed} + this.didCache = true + return {id:this.id,embed} + }catch(err){ + process.emit("uncaughtException",new ODSystemError("ODEmbed:build(\""+this.id.value+"\") => Major Error (see next error)")) + process.emit("uncaughtException",err) + return {id:this.id,embed:null} + } + } +} + +/**## ODMessageManager `class` + * This is an open ticket message manager. + * + * It contains all Open Ticket message builders. Here, you can add your own messages or edit existing ones! + * + * It's recommended to use this system in combination with all the other Open Ticket builders! + */ +export class ODMessageManager extends ODManagerWithSafety> { + constructor(debug:ODDebugger){ + super(() => { + return new ODMessage("openticket:unknown-message",(instance,params,source,cancel) => { + instance.setContent("**❌ **\nCouldn't find message in registery `openticket.builders.messages`") + cancel() + }) + },debug,"message") + } +} + +/**## ODMessageData `interface` + * This interface contains the data to build a message. + */ +export interface ODMessageData { + /**The content of this message. `null` when no content */ + content:string|null, + /**Poll data for this message */ + poll:discord.PollData|null, + /**Try to make this message ephemeral when available */ + ephemeral:boolean, + + /**Embeds from this message */ + embeds:ODEmbedBuildResult[], + /**Components from this message */ + components:ODComponentBuildResult[], + /**Files from this message */ + files:ODFileBuildResult[], + + /**Additional options that aren't covered by the Open Ticket api!*/ + additionalOptions:Omit +} + +/**## ODMessageBuildResult `interface` + * This interface contains the result from a built message. This can be sent in a discord channel! + */ +export interface ODMessageBuildResult { + /**The id of this message */ + id:ODId, + /**The discord message */ + message:Omit, + /**When enabled, the bot will try to send this as an ephemeral message */ + ephemeral:boolean +} + +/**## ODMessageBuildSentResult `interface` + * This interface contains the result from a sent built message. This can be used to edit, view & save the message that got created. + */ +export interface ODMessageBuildSentResult { + /**Did the message get sent succesfully? */ + success:boolean, + /**The message that got sent. */ + message:discord.Message|null +} + +/**## ODMessageInstance `class` + * This is an open ticket message instance. + * + * It contains all properties & functions to build a message! + */ +export class ODMessageInstance { + /**The current data of this message */ + data: ODMessageData = { + content:null, + poll:null, + ephemeral:false, + + embeds:[], + components:[], + files:[], + + additionalOptions:{ + } + } + + /**Set the content of this message */ + setContent(content:ODMessageData["content"]){ + this.data.content = content + return this + } + /**Set the poll of this message */ + setPoll(poll:ODMessageData["poll"]){ + this.data.poll = poll + return this + } + /**Make this message ephemeral when possible */ + setEphemeral(ephemeral:ODMessageData["ephemeral"]){ + this.data.ephemeral = ephemeral + return this + } + /**Set the embeds of this message */ + setEmbeds(...embeds:ODEmbedBuildResult[]){ + this.data.embeds = embeds + return this + } + /**Add an embed to this message! */ + addEmbed(embed:ODEmbedBuildResult){ + this.data.embeds.push(embed) + return this + } + /**Remove an embed from this message */ + removeEmbed(id:ODValidId){ + const index = this.data.embeds.findIndex((embed) => embed.id.value === new ODId(id).value) + if (index > -1) this.data.embeds.splice(index,1) + return this + } + /**Get an embed from this message */ + getEmbed(id:ODValidId){ + const embed = this.data.embeds.find((embed) => embed.id.value === new ODId(id).value) + if (embed) return embed.embed + else return null + } + /**Set the components of this message */ + setComponents(...components:ODComponentBuildResult[]){ + this.data.components = components + return this + } + /**Add a component to this message! */ + addComponent(component:ODComponentBuildResult){ + this.data.components.push(component) + return this + } + /**Remove a component from this message */ + removeComponent(id:ODValidId){ + const index = this.data.components.findIndex((component) => component.id.value === new ODId(id).value) + if (index > -1) this.data.components.splice(index,1) + return this + } + /**Get a component from this message */ + getComponent(id:ODValidId){ + const component = this.data.components.find((component) => component.id.value === new ODId(id).value) + if (component) return component.component + else return null + } + /**Set the files of this message */ + setFiles(...files:ODFileBuildResult[]){ + this.data.files = files + return this + } + /**Add a file to this message! */ + addFile(file:ODFileBuildResult){ + this.data.files.push(file) + return this + } + /**Remove a file from this message */ + removeFile(id:ODValidId){ + const index = this.data.files.findIndex((file) => file.id.value === new ODId(id).value) + if (index > -1) this.data.files.splice(index,1) + return this + } + /**Get a file from this message */ + getFile(id:ODValidId){ + const file = this.data.files.find((file) => file.id.value === new ODId(id).value) + if (file) return file.file + else return null + } +} + +/**## ODMessage `class` + * This is an open ticket message builder. + * + * With this class, you can create a message to send in a discord channel. + * The only difference with normal messages is that this one can be edited by Open Ticket plugins! + * + * This is possible by using "workers" or multiple functions that will be executed in priority order! + */ +export class ODMessage extends ODBuilderImplementation { + /**Build this message & compile it for discord.js */ + async build(source:Source, params:Params){ + if (this.didCache && this.cache && this.allowCache) return this.cache + + //create instance + const instance = new ODMessageInstance() + + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + + //create the discord.js message + const componentArray: discord.ActionRowBuilder[] = [] + let currentRow: discord.ActionRowBuilder = new discord.ActionRowBuilder() + instance.data.components.forEach((c) => { + //return when component crashed + if (c.component == null) return + else if (c.component == "\n"){ + //create new current row when required + if (currentRow.components.length > 0){ + componentArray.push(currentRow) + currentRow = new discord.ActionRowBuilder() + } + }else if (c.component instanceof discord.BaseSelectMenuBuilder){ + //push current row when not empty + if (currentRow.components.length > 0){ + componentArray.push(currentRow) + currentRow = new discord.ActionRowBuilder() + } + currentRow.addComponents(c.component) + //create new current row after dropdown + componentArray.push(currentRow) + currentRow = new discord.ActionRowBuilder() + }else{ + //push button to current row + currentRow.addComponents(c.component) + } + + //create new row when 5 rows in length + if (currentRow.components.length == 5){ + componentArray.push(currentRow) + currentRow = new discord.ActionRowBuilder() + } + }) + //push final row to array + if (currentRow.components.length > 0) componentArray.push(currentRow) + + const filteredEmbeds = instance.data.embeds.map((e) => e.embed).filter((e) => e instanceof discord.EmbedBuilder) as discord.EmbedBuilder[] + const filteredFiles = instance.data.files.map((f) => f.file).filter((f) => f instanceof discord.AttachmentBuilder) as discord.AttachmentBuilder[] + + const message : discord.MessageCreateOptions = { + content:instance.data.content ?? "", + poll:instance.data.poll ?? undefined, + embeds:filteredEmbeds, + components:componentArray, + files:filteredFiles + } + + let result = {id:this.id,message,ephemeral:instance.data.ephemeral} + + Object.assign(result.message,instance.data.additionalOptions) + + this.cache = result + this.didCache = true + return result + } +} + +/**## ODModalManager `class` + * This is an open ticket modal manager. + * + * It contains all Open Ticket modal builders. Here, you can add your own modals or edit existing ones! + * + * It's recommended to use this system in combination with all the other Open Ticket builders! + */ +export class ODModalManager extends ODManagerWithSafety> { + constructor(debug:ODDebugger){ + super(() => { + return new ODModal("openticket:unknown-modal",(instance,params,source,cancel) => { + instance.setCustomId("od:unknown-modal") + instance.setTitle("❌ ") + instance.setQuestions( + { + style:"short", + customId:"error", + label:"error", + placeholder:"Contact the bot creator for more info!" + } + ) + cancel() + }) + },debug,"modal") + } +} + +/**## ODModalDataQuestion `interface` + * This interface contains the data to build a modal question. + */ +export interface ODModalDataQuestion { + /**The style of this modal question */ + style:"short"|"paragraph", + /**The custom id of this modal question */ + customId:string + /**The label of this modal question */ + label?:string, + /**The min length of this modal question */ + minLength?:number, + /**The max length of this modal question */ + maxLength?:number, + /**Is this modal question required? */ + required?:boolean, + /**The placeholder of this modal question */ + placeholder?:string, + /**The initial value of this modal question */ + value?:string +} + +/**## ODModalData `interface` + * This interface contains the data to build a modal. + */ +export interface ODModalData { + /**The custom id of this modal */ + customId:string, + /**The title of this modal */ + title:string|null, + /**The collection of questions in this modal */ + questions:ODModalDataQuestion[], +} + +/**## ODModalBuildResult `interface` + * This interface contains the result from a built modal (form). This can be used in the `ODMessage` builder! + */ +export interface ODModalBuildResult { + /**The id of this modal */ + id:ODId, + /**The discord modal */ + modal:discord.ModalBuilder +} + +/**## ODModalInstance `class` + * This is an open ticket modal instance. + * + * It contains all properties & functions to build a modal! + */ +export class ODModalInstance { + /**The current data of this modal */ + data: ODModalData = { + customId:"", + title:null, + questions:[] + } + + /**Set the custom id of this modal */ + setCustomId(customId:ODModalData["customId"]){ + this.data.customId = customId + return this + } + /**Set the title of this modal */ + setTitle(title:ODModalData["title"]){ + this.data.title = title + return this + } + /**Set the questions of this modal */ + setQuestions(...questions:ODModalData["questions"]){ + this.data.questions = questions + return this + } + /**Add a question to this modal! */ + addQuestion(question:ODModalDataQuestion){ + this.data.questions.push(question) + return this + } + /**Remove a question from this modal */ + removeQuestion(customId:string){ + const index = this.data.questions.findIndex((question) => question.customId === customId) + if (index > -1) this.data.questions.splice(index,1) + return this + } + /**Get a question from this modal */ + getQuestion(customId:string){ + const question = this.data.questions.find((question) => question.customId === customId) + if (question) return question + else return null + } +} + +/**## ODModal `class` + * This is an open ticket modal builder. + * + * With this class, you can create a modal to use as response in interactions. + * The only difference with normal modals is that this one can be edited by Open Ticket plugins! + * + * This is possible by using "workers" or multiple functions that will be executed in priority order! + */ +export class ODModal extends ODBuilderImplementation { + /**Build this modal & compile it for discord.js */ + async build(source:Source, params:Params){ + if (this.didCache && this.cache && this.allowCache) return this.cache + + //create instance + const instance = new ODModalInstance() + + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + + //create the discord.js modal + const modal = new discord.ModalBuilder() + modal.setCustomId(instance.data.customId) + if (instance.data.title) modal.setTitle(instance.data.title) + else modal.setTitle(instance.data.customId) + + instance.data.questions.forEach((question) => { + const input = new discord.TextInputBuilder() + .setStyle(question.style == "paragraph" ? discord.TextInputStyle.Paragraph : discord.TextInputStyle.Short) + .setCustomId(question.customId) + .setLabel(question.label ? question.label : question.customId) + .setRequired(question.required ? true : false) + + if (question.minLength) input.setMinLength(question.minLength) + if (question.maxLength) input.setMaxLength(question.maxLength) + if (question.value) input.setValue(question.value) + if (question.placeholder) input.setPlaceholder(question.placeholder) + + modal.addComponents( + new discord.ActionRowBuilder() + .addComponents(input) + ) + }) + + this.cache = {id:this.id,modal} + this.didCache = true + return {id:this.id,modal} + } +} \ No newline at end of file diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts new file mode 100644 index 0000000..5f5f727 --- /dev/null +++ b/src/core/api/modules/checker.ts @@ -0,0 +1,1465 @@ +/////////////////////////////////////// +//CONFIG CHECKER MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODValidId, ODValidJsonType } from "./base" +import { ODConfig } from "./config" +import { ODLanguageManager } from "./language" +import { ODDebugger } from "./console" + +/**## ODCheckerResult `interface` + * This interface is the result from a config checker check() function. + */ +export interface ODCheckerResult { + valid:boolean + messages:ODCheckerMessage[] +} + +/**## ODCheckerManager `class` + * This is an open ticket checker manager. + * + * It manages all config checkers in the bot and allows plugins to access config checkers from open ticket & other plugins! + * + * You will use this class to get/add a config checker (`ODChecker`) in your plugin! + * @example + * //get checker for ./config/general.json => ODChecker class + * const testChecker = openticket.checkers.get("openticket:general") + * + * //add a new checker with id "test" => ./config/test.json + * const testConfig = new api.ODConfig("test","test.json") + * const testChecker = new api.ODChecker("test",openticket.checkers.storage,0,testConfig,[]) + * openticket.checkers.add(testChecker) + */ +export class ODCheckerManager extends ODManager { + /**The global temporary storage shared between all config checkers. */ + storage: ODCheckerStorage + /**The class responsible for rendering the config checker report. */ + renderer: ODCheckerRenderer + /**The class responsible for translating the config checker report. */ + translation: ODCheckerTranslationRegister + /**Final functions are global functions executed just before the report is created. */ + functions: ODCheckerFunctionManager + /**A variable containing the last result returned from `checkAll()` */ + lastResult: ODCheckerResult|null = null + + constructor(debug:ODDebugger, storage:ODCheckerStorage, renderer:ODCheckerRenderer, translation:ODCheckerTranslationRegister, functions:ODCheckerFunctionManager){ + super(debug,"config checker") + this.storage = storage + this.renderer = renderer + this.translation = translation + this.functions = functions + } + /**Check all config checkers registered in this manager.*/ + checkAll(sort:boolean): ODCheckerResult { + this.storage.reset() + + let isValid = true + const final: ODCheckerMessage[] = [] + + const checkers = this.getAll() + checkers.sort((a,b) => b.priority-a.priority) + + checkers.forEach((checker) => { + const res = checker.check() + final.push(...res.messages) + + if (!res.valid) isValid = false + }) + + this.functions.getAll().forEach((func) => { + const res = func.func(this,this.functions) + final.push(...res.messages) + + if (!res.valid) isValid = false + }) + + //sort messages => (info, warning, error) + if (sort) final.sort((a,b) => { + const typeA = (a.type == "error") ? 2 : (a.type == "warning") ? 1 : 0 + const typeB = (b.type == "error") ? 2 : (b.type == "warning") ? 1 : 0 + + return typeA-typeB + }) + + this.lastResult = { + valid:isValid, + messages:final + } + + return { + valid:isValid, + messages:final + } + } +} + +/**## ODCheckerStorage `class` + * This is an open ticket checker storage. + * + * It stores temporary data to share between config checkers! + * (e.g. The `messages.json` needs to access the `"id"` from `options.json`) + * + * + * You will probably use this class when you create your own config checker! + */ +export class ODCheckerStorage { + /**This is the array that stores all the data. ❌ **(don't edit unless really needed!)***/ + storage: {source:ODId, key:string, value:any}[] = [] + + /**Get data from the database (`source` => id of `ODChecker`) */ + get(source:ODValidId, key:string): any|null { + const result = this.storage.find(d => (d.source.value == new ODId(source).value) && (d.key == key)) + return (result) ? result.value : null + } + /**Add data to the database (`source` => id of `ODChecker`). This function also overwrites existing data!*/ + set(source:ODValidId, key:string, value:any){ + const index = this.storage.findIndex(d => (d.source.value == new ODId(source).value) && (d.key == key)) + if (index > -1){ + //overwrite + this.storage[index] = { + source:new ODId(source), + key,value + } + return true + }else{ + this.storage.push({ + source:new ODId(source), + key,value + }) + return false + } + } + /**Delete data from the database (`source` => id of `ODChecker`) */ + delete(source:ODValidId, key:string){ + const index = this.storage.findIndex(d => (d.source.value == new ODId(source).value) && (d.key == key)) + if (index > -1){ + //delete + this.storage.splice(index,1) + return true + }else return false + } + + /**Reset the entire database */ + reset(){ + this.storage = [] + } +} + +/**## ODCheckerRenderer `class` + * This is an open ticket checker renderer. + * + * It's responsible for rendering the config checker result in the console. + * This class doesn't provide any components! You need to create them by extending this class + * + * You will only use this class if you want to change how the config checker looks! + */ +export class ODCheckerRenderer { + /**Get all components */ + getComponents(compact:boolean, renderEmpty:boolean, translation:ODCheckerTranslationRegister, data:ODCheckerResult): string[] { + return [] + } + /**Render all components */ + render(components:string[]){ + if (components.length < 1) return + console.log("\n") + components.forEach((c) => { + console.log(c) + }) + console.log("\n") + } +} + +/**## ODCheckerTranslationRegister `class` + * This is an open ticket checker translation register. + * + * It's used to store & manage the translation for each message from the config checker! + * Most translations are stored by message id, but there are some exceptions like the additional text on the checker report. + * + * You will use this class if you want to translate your config checker messages! **This is optional & isn't required for the checker to work!** + */ +export class ODCheckerTranslationRegister { + /**This is the array that stores all the data. ❌ **(don't edit unless really needed!)***/ + #translations: {type:"message"|"other", id:string, translation:string}[] = [] + + /**Get the translation from a config checker message/sentence */ + get(type:"message"|"other", id:string): string|null { + const result = this.#translations.find(d => (d.id == id) && (d.type == type)) + return (result) ? result.translation : null + } + /**Set the translation for a config checker message/sentence. This function also overwrites existing translations!*/ + set(type:"message"|"other", id:string, translation:string){ + const index = this.#translations.findIndex(d => (d.id == id) && (d.type == type)) + if (index > -1){ + //overwrite + this.#translations[index] = {type,id,translation} + return true + }else{ + this.#translations.push({type,id,translation}) + return false + } + } + /**Delete the translation for a config checker message/sentence. */ + delete(type:"message"|"other", id:string){ + const index = this.#translations.findIndex(d => (d.id == id) && (d.type == type)) + if (index > -1){ + //delete + this.#translations.splice(index,1) + return true + }else return false + } + + /**Get all translations */ + getAll(){ + return this.#translations + } + + /**Insert the translation params into the text. */ + insertTranslationParams(text:string, translationParams:string[]){ + translationParams.forEach((value,index) => { + text = text.replace(`{${index}}`,value) + }) + return text + } + /**A shortcut to copy translations from the `ODLanguageManager` to `ODCheckerTranslationRegister` */ + quickTranslate(manager:ODLanguageManager, translationId:string, type:"other"|"message", id:string){ + const translation = manager.getTranslation(translationId) + if (translation) this.set(type,id,translation) + } +} + +/**## ODCheckerFunction `class` + * This is an open ticket config checker function. + * + * It is a global function that will be executed after all config checkers. It can do additional checks for invalid/missing configurations. + * It's mostly used for things that need to be checked globally! + */ +export class ODCheckerFunction extends ODManagerData { + /**The function itself :) */ + func: (manager:ODCheckerManager, functions:ODCheckerFunctionManager) => ODCheckerResult + + constructor(id:ODValidId, func:(manager:ODCheckerManager, functions:ODCheckerFunctionManager) => ODCheckerResult){ + super(id) + this.func = func + } +} + +/**## ODCheckerFunctionManager `class` + * This is an open ticket config checker function manager. + * + * It manages all `ODCheckerFunction`'s and it has some extra shortcuts for frequently used methods. + */ +export class ODCheckerFunctionManager extends ODManager { + constructor(debug:ODDebugger){ + super(debug,"config checker function") + } + + /**A shortcut to create a warning, info or error message */ + createMessage(checkerId:ODValidId, id:ODValidId, filepath:string, type:"info"|"warning"|"error", message:string, locationTrace:ODCheckerLocationTrace, docs:string|null, translationParams:string[], locationId:ODId, locationDocs:string|null): ODCheckerMessage { + return { + checkerId:new ODId(checkerId), + messageId:new ODId(id), + locationId, + + type,message, + path:this.locationTraceToString(locationTrace), + filepath, + translationParams, + + messageDocs:docs, + locationDocs + } + } + /**Create a string from the location trace (path)*/ + locationTraceToString(trace:ODCheckerLocationTrace){ + const final: ODCheckerLocationTrace = [] + trace.forEach((t) => { + if (typeof t == "number"){ + final.push(`:${t}`) + }else{ + final.push(`."${t}"`) + } + }) + return final.join("").substring(1) + } + /**De-reference the locationTrace array. Use this before adding a value to the array*/ + locationTraceDeref(trace:ODCheckerLocationTrace): ODCheckerLocationTrace { + return JSON.parse(JSON.stringify(trace)) + } +} + +/**## ODCheckerLocationTrace `type` + * This type is an array of strings & numbers which represents the location trace from the config checker. + * It's used to generate a path to the error (e.g. `"abc"."efg".1."something"`) + */ +export type ODCheckerLocationTrace = (string|number)[] + +/**## ODChecker `class` + * This is an open ticket config checker. + * + * It checks a specific config file for invalid/missing configurations. This data can then be used to show to the user what's wrong! + * You can check for example if a string is longer/shorter than a certain amount of characters & more! + * + * You will use this class when you create your own custom config file & you want to check it for syntax errors. + * @example + * //create a new checker with id "test" => ./config/test.json + * const testConfig = new api.ODConfig("test","test.json") + * const testChecker = new api.ODChecker("test",openticket.checkers.storage,0,testConfig,new api.ODCheckerStructure()) + * openticket.checkers.add(testChecker) + * + * //you will still need to build the structure & insert it in the constructor + */ +export class ODChecker extends ODManagerData { + /**The storage of this checker (reference for `ODCheckerManager.storage`) */ + storage: ODCheckerStorage + /**The higher the priority, the faster it gets checked! */ + priority: number + /**The config file that needs to be checked */ + config: ODConfig + /**The structure of the config file */ + structure: ODCheckerStructure + /**Temporary storage for all error messages from the check() method (not recommended to use) */ + messages: ODCheckerMessage[] = [] + /**Temporary storage for the quit status from the check() method (not recommended to use) */ + quit: boolean = false + + constructor(id:ODValidId, storage: ODCheckerStorage, priority:number, config:ODConfig, structure: ODCheckerStructure){ + super(id) + this.storage = storage + this.priority = priority + this.config = config + this.structure = structure + } + + /**Run this checker. Returns all errors*/ + check(): ODCheckerResult { + this.messages = [] + this.quit = false + + this.structure.check(this,this.config.data,[]) + return { + valid:!this.quit, + messages:this.messages + } + } + /**Create a string from the location trace (path)*/ + locationTraceToString(trace:ODCheckerLocationTrace){ + const final: ODCheckerLocationTrace = [] + trace.forEach((t) => { + if (typeof t == "number"){ + final.push(`:${t}`) + }else{ + final.push(`."${t}"`) + } + }) + return final.join("").substring(1) + } + /**De-reference the locationTrace array. Use this before adding a value to the array*/ + locationTraceDeref(trace:ODCheckerLocationTrace): ODCheckerLocationTrace { + return JSON.parse(JSON.stringify(trace)) + } + + /**A shortcut to create a warning, info or error message */ + createMessage(id:ODValidId, type:"info"|"warning"|"error", message:string, locationTrace:ODCheckerLocationTrace, docs:string|null, translationParams:string[], locationId:ODId, locationDocs:string|null){ + if (type == "error") this.quit = true + this.messages.push({ + checkerId:this.id, + messageId:new ODId(id), + locationId, + + type,message, + path:this.locationTraceToString(locationTrace), + filepath:this.config.file, + translationParams, + + messageDocs:docs, + locationDocs + }) + } +} + +/**## ODCheckerMessage `interface` + * This interface is an object which has all variables required for a config checker message! + */ +export interface ODCheckerMessage { + checkerId:ODId, + messageId:ODId, + locationId:ODId, + + type:"info"|"warning"|"error", + message:string, + path:string, + filepath:string, + translationParams:string[], + + messageDocs:string|null, + locationDocs:string|null +} + +/**## ODCheckerStructureOptions `interface` + * This interface has the basic options for the `ODCheckerStructure`! + */ +export interface ODCheckerStructureOptions { + /**Add a custom checker function */ + custom?:(checker:ODChecker, value:ODValidJsonType, locationTrace:ODCheckerLocationTrace, locationId:ODId, locationDocs:string|null) => boolean, + /**Set the url to the documentation of this variable. */ + docs?:string +} + +/**## ODCheckerStructure `class` + * This is an open ticket config checker structure. + * + * This class will check for a single variable in a config file, customise it in the settings! + * If you want prebuilt checkers (for strings, booleans, numbers, ...), check the other `ODCheckerStructure`'s! + * + * You will almost never use this class! It's better if you extend on another `ODConfigCheckerStructure`! + */ +export class ODCheckerStructure { + /**The id of this checker structure */ + id: ODId + /**The options for this checker structure */ + options: ODCheckerStructureOptions + + constructor(id:ODValidId, options:ODCheckerStructureOptions){ + this.id = new ODId(id) + this.options = options + } + + /**Check a variable if it matches all settings in this checker. This function is automatically executed by open ticket! */ + check(checker:ODChecker, value:ODValidJsonType, locationTrace:ODCheckerLocationTrace): boolean { + if (typeof this.options.custom != "undefined"){ + return this.options.custom(checker,value,locationTrace,this.id,(this.options.docs ?? null)) + }else return true + } +} + +/**## ODCheckerObjectStructureOptions `interface` + * This interface has the options for `ODCheckerObjectStructure`! + */ +export interface ODCheckerObjectStructureOptions extends ODCheckerStructureOptions { + /**Add a checker for a property in an object (can also be optional) */ + children?:{key:string, checker:ODCheckerStructure, priority:number, optional:boolean}[] +} + +/**## ODCheckerObjectStructure `class` + * This is an open ticket config checker structure. + * + * This class will check for an object variable in a config file, customise it in the settings! + * A checker for the children can be set in the settings. + */ +export class ODCheckerObjectStructure extends ODCheckerStructure { + declare options: ODCheckerObjectStructureOptions + + constructor(id:ODValidId, options:ODCheckerObjectStructureOptions){ + super(id,options) + } + + check(checker:ODChecker, value:object, locationTrace:ODCheckerLocationTrace): boolean { + const lt = checker.locationTraceDeref(locationTrace) + + //check type & options + if (typeof value != "object"){ + checker.createMessage("openticket:invalid-type","error","This property needs to be the type: object!",lt,null,["object"],this.id,(this.options.docs ?? null)) + return false + } + + //sort children + if (typeof this.options.children == "undefined") return super.check(checker,value,locationTrace) + const sortedChildren = this.options.children.sort((a,b) => { + if (a.priority < b.priority) return -1 + else if (a.priority > b.priority) return 1 + else return 0 + }) + + //check children + let localQuit = false + sortedChildren.forEach((child) => { + const localLt = checker.locationTraceDeref(lt) + localLt.push(child.key) + + if (typeof value[child.key] == "undefined"){ + if (!child.optional){ + localQuit = true + checker.createMessage("openticket:property-missing","error",`The property "${child.key}" is mising from this object!`,lt,null,[`"${child.key}"`],this.id,(this.options.docs ?? null)) + }else{ + checker.createMessage("openticket:property-optional","info",`The property "${child.key}" is optional in this object!`,lt,null,[`"${child.key}"`],this.id,(this.options.docs ?? null)) + } + }else if (!child.checker.check(checker,value[child.key],localLt)) localQuit = true + }) + + //do local quit or check custom function + if (localQuit) return false + else return super.check(checker,value,locationTrace) + } +} + +/**## ODCheckerStringStructureOptions `interface` + * This interface has the options for `ODCheckerStringStructure`! + */ +export interface ODCheckerStringStructureOptions extends ODCheckerStructureOptions { + /**The minimum length of this string */ + minLength?:number, + /**The maximum length of this string */ + maxLength?:number, + /**Set the required length of this string */ + length?:number, + /**This string needs to start with ... */ + startsWith?:string, + /**This string needs to end with ... */ + endsWith?:string, + /**This string needs to contain ... */ + contains?:string, + /**You need to choose between ... */ + choices?:string[], + /**The string needs to match this regex */ + regex?:RegExp +} + +/**## ODCheckerStringStructure `class` + * This is an open ticket config checker structure. + * + * This class will check for a string variable in a config file, customise it in the settings! + */ +export class ODCheckerStringStructure extends ODCheckerStructure { + declare options: ODCheckerStringStructureOptions + + constructor(id:ODValidId, options:ODCheckerStringStructureOptions){ + super(id,options) + } + + check(checker:ODChecker, value:string, locationTrace:ODCheckerLocationTrace): boolean { + const lt = checker.locationTraceDeref(locationTrace) + + //check type & options + if (typeof value != "string"){ + checker.createMessage("openticket:invalid-type","error","This property needs to be the type: string!",lt,null,["string"],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.minLength != "undefined" && value.length < this.options.minLength){ + checker.createMessage("openticket:string-too-short","error",`This string can't be shorter than ${this.options.minLength} characters!`,lt,null,[this.options.minLength.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.maxLength != "undefined" && value.length > this.options.maxLength){ + checker.createMessage("openticket:string-too-long","error",`This string can't be longer than ${this.options.maxLength} characters!`,lt,null,[this.options.maxLength.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.length != "undefined" && value.length !== this.options.length){ + checker.createMessage("openticket:string-length-invalid","error",`This string needs to be ${this.options.length} characters long!`,lt,null,[this.options.length.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.startsWith != "undefined" && !value.startsWith(this.options.startsWith)){ + checker.createMessage("openticket:string-starts-with","error",`This string needs to start with "${this.options.startsWith}"!`,lt,null,[`"${this.options.startsWith}"`],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.endsWith != "undefined" && !value.endsWith(this.options.endsWith)){ + checker.createMessage("openticket:string-ends-with","error",`This string needs to end with "${this.options.endsWith}"!`,lt,null,[`"${this.options.endsWith}"`],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.contains != "undefined" && !value.includes(this.options.contains)){ + checker.createMessage("openticket:string-contains","error",`This string needs to contain "${this.options.contains}"!`,lt,null,[`"${this.options.contains}"`],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.choices != "undefined" && !this.options.choices.includes(value)){ + checker.createMessage("openticket:string-choices","error",`This string can only be one of the following values: "${this.options.choices.join(`", "`)}"!`,lt,null,[`"${this.options.choices.join(`", "`)}"`],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.regex != "undefined" && !this.options.regex.test(value)){ + checker.createMessage("openticket:string-regex","error","This string is invalid!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else return super.check(checker,value,locationTrace) + } +} + +/**## ODCheckerNumberStructureOptions `interface` + * This interface has the options for `ODCheckerNumberStructure`! + */ +export interface ODCheckerNumberStructureOptions extends ODCheckerStructureOptions { + /**The minimum length of this number */ + minLength?:number, + /**The maximum length of this number */ + maxLength?:number, + /**Set the required length of this number */ + length?:number, + /**The minimum value of this number */ + min?:number, + /**The maximum value of this number */ + max?:number, + /**This number is required to match the value */ + is?:number, + /**Only allow a multiple of ... starting at `this.offset` or 0 */ + step?:number, + /**The offset for the step function. */ + offset?:number, + /**This number needs to start with ... */ + startsWith?:string, + /**This number needs to end with ... */ + endsWith?:string, + /**This number needs to contain ... */ + contains?:string, + /**You need to choose between ... */ + choices?:number[], + /**Are numbers with a decimal value allowed? */ + floatAllowed?:boolean, + /**Are negative numbers allowed (without zero) */ + negativeAllowed?:boolean, + /**Are positive numers allowed (without zero) */ + positiveAllowed?:boolean, + /**Is zero allowed? */ + zeroAllowed?:boolean +} + +/**## ODCheckerNumberStructure `class` + * This is an open ticket config checker structure. + * + * This class will check for a number variable in a config file, customise it in the settings! + */ +export class ODCheckerNumberStructure extends ODCheckerStructure { + declare options: ODCheckerNumberStructureOptions + + constructor(id:ODValidId, options:ODCheckerNumberStructureOptions){ + super(id,options) + } + + check(checker:ODChecker, value:number, locationTrace:ODCheckerLocationTrace): boolean { + const lt = checker.locationTraceDeref(locationTrace) + + //offset for step + const stepOffset = (typeof this.options.offset != "undefined") ? this.options.offset : 0 + + //check type & options + if (typeof value != "number"){ + checker.createMessage("openticket:invalid-type","error","This property needs to be the type: number!",lt,null,["number"],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.minLength != "undefined" && value.toString().length < this.options.minLength){ + checker.createMessage("openticket:number-too-short","error",`This number can't be shorter than ${this.options.minLength} characters!`,lt,null,[this.options.minLength.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.maxLength != "undefined" && value.toString().length > this.options.maxLength){ + checker.createMessage("openticket:number-too-long","error",`This number can't be longer than ${this.options.maxLength} characters!`,lt,null,[this.options.maxLength.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.length != "undefined" && value.toString().length !== this.options.length){ + checker.createMessage("openticket:number-length-invalid","error",`This number needs to be ${this.options.length} characters long!`,lt,null,[this.options.length.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.min != "undefined" && value < this.options.min){ + checker.createMessage("openticket:number-too-small","error",`This number needs to be at least ${this.options.min}!`,lt,null,[this.options.min.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.max != "undefined" && value > this.options.max){ + checker.createMessage("openticket:number-too-large","error",`This number needs to be at most ${this.options.max}!`,lt,null,[this.options.max.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.is != "undefined" && value == this.options.is){ + checker.createMessage("openticket:number-not-equal","error",`This number needs to be ${this.options.is}!`,lt,null,[this.options.is.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.step != "undefined" && ((value - stepOffset) % this.options.step) !== 0){ + if (stepOffset > 0) checker.createMessage("openticket:number-step-offset","error",`This number needs to be a multiple of ${this.options.step} starting with ${stepOffset}!`,lt,null,[this.options.step.toString(),stepOffset.toString()],this.id,(this.options.docs ?? null)) + else checker.createMessage("openticket:number-step","error",`This number needs to be a multiple of ${this.options.step}!`,lt,null,[this.options.step.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.startsWith != "undefined" && !value.toString().startsWith(this.options.startsWith)){ + checker.createMessage("openticket:number-starts-with","error",`This number needs to start with "${this.options.startsWith}"!`,lt,null,[`"${this.options.startsWith}"`],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.endsWith != "undefined" && !value.toString().endsWith(this.options.endsWith)){ + checker.createMessage("openticket:number-ends-with","error",`This number needs to end with "${this.options.endsWith}"!`,lt,null,[`"${this.options.endsWith}"`],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.contains != "undefined" && !value.toString().includes(this.options.contains)){ + checker.createMessage("openticket:number-contains","error",`This number needs to contain "${this.options.contains}"!`,lt,null,[`"${this.options.contains}"`],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.choices != "undefined" && !this.options.choices.includes(value)){ + checker.createMessage("openticket:number-choices","error",`This number can only be one of the following values: "${this.options.choices.join(`", "`)}"!`,lt,null,[`"${this.options.choices.join(`", "`)}"`],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.floatAllowed != "undefined" && !this.options.floatAllowed && (value % 1) !== 0){ + checker.createMessage("openticket:number-float","error","This number can't be a decimal!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.negativeAllowed != "undefined" && value < 0){ + checker.createMessage("openticket:number-negative","error","This number can't be negative!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.positiveAllowed != "undefined" && value > 0){ + checker.createMessage("openticket:number-positive","error","This number can't be positive!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.zeroAllowed != "undefined" && value === 0){ + checker.createMessage("openticket:number-zero","error","This number can't be zero!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else return super.check(checker,value,locationTrace) + } +} + +/**## ODCheckerBooleanStructureOptions `interface` + * This interface has the options for `ODCheckerBooleanStructure`! + */ +export interface ODCheckerBooleanStructureOptions extends ODCheckerStructureOptions { + /**Is `true` allowed? */ + trueAllowed?:boolean, + /**Is `false` allowed? */ + falseAllowed?:boolean +} + +/**## ODCheckerBooleanStructure `class` + * This is an open ticket config checker structure. + * + * This class will check for a boolean variable in a config file, customise it in the settings! + */ +export class ODCheckerBooleanStructure extends ODCheckerStructure { + declare options: ODCheckerBooleanStructureOptions + + constructor(id:ODValidId, options:ODCheckerBooleanStructureOptions){ + super(id,options) + } + + check(checker:ODChecker, value:boolean, locationTrace:ODCheckerLocationTrace): boolean { + const lt = checker.locationTraceDeref(locationTrace) + + //check type & options + if (typeof value != "boolean"){ + checker.createMessage("openticket:invalid-type","error","This property needs to be the type: boolean!",lt,null,["boolean"],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.trueAllowed != "undefined" && !this.options.trueAllowed && value == true){ + checker.createMessage("openticket:boolean-true","error","This boolean can't be true!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.falseAllowed != "undefined" && !this.options.falseAllowed && value == false){ + checker.createMessage("openticket:boolean-false","error","This boolean can't be false!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else return super.check(checker,value,locationTrace) + } +} + +/**## ODCheckerArrayStructureOptions `interface` + * This interface has the options for `ODCheckerArrayStructure`! + */ +export interface ODCheckerArrayStructureOptions extends ODCheckerStructureOptions { + /**The checker for all the properties in this array */ + propertyChecker?:ODCheckerStructure, + /**Don't allow this array to be empty */ + disableEmpty?:boolean, + /**This array is required to be empty */ + emptyRequired?:boolean, + /**The minimum length of this array */ + minLength?:number, + /**The maximum length of this array */ + maxLength?:number, + /**The length of the array needs to be the same as this value */ + length?:number, + /**Allow double values (only for `string`, `number` & `boolean`) */ + allowDoubles?:boolean + /**Only allow these types in the array (for multi-type propertyCheckers) */ + allowedTypes?:("string"|"number"|"boolean"|"null"|"array"|"object"|"other")[] +} + +/**## ODCheckerArrayStructure `class` + * This is an open ticket config checker structure. + * + * This class will check for an array variable in a config file, customise it in the settings! + */ +export class ODCheckerArrayStructure extends ODCheckerStructure { + declare options: ODCheckerArrayStructureOptions + + constructor(id:ODValidId, options:ODCheckerArrayStructureOptions){ + super(id,options) + } + + check(checker:ODChecker, value:Array, locationTrace:ODCheckerLocationTrace): boolean { + const lt = checker.locationTraceDeref(locationTrace) + + if (!Array.isArray(value)){ + checker.createMessage("openticket:invalid-type","error","This property needs to be the type: array!",lt,null,["array"],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.disableEmpty != "undefined" && this.options.disableEmpty && value.length == 0){ + checker.createMessage("openticket:array-empty-disabled","error","This array isn't allowed to be empty!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.emptyRequired != "undefined" && this.options.emptyRequired && value.length != 0){ + checker.createMessage("openticket:array-empty-required","error","This array is required to be empty!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.minLength != "undefined" && value.length < this.options.minLength){ + checker.createMessage("openticket:array-too-short","error",`This array needs to have a length of at least ${this.options.minLength}!`,lt,null,[this.options.minLength.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.maxLength != "undefined" && value.length > this.options.maxLength){ + checker.createMessage("openticket:array-too-long","error",`This array needs to have a length of at most ${this.options.maxLength}!`,lt,null,[this.options.maxLength.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.length != "undefined" && value.length == this.options.length){ + checker.createMessage("openticket:array-length-invalid","error",`This array needs to have a length of ${this.options.length}!`,lt,null,[this.options.length.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.allowedTypes != "undefined" && !this.#arrayAllowedTypesCheck(value,this.options.allowedTypes)){ + checker.createMessage("openticket:array-invalid-types","error",`This array can only contain the following types: ${this.options.allowedTypes.join(", ")}!`,lt,null,[this.options.allowedTypes.join(", ").toString()],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.options.allowDoubles != "undefined" && !this.options.allowDoubles && this.#arrayHasDoubles(value)){ + checker.createMessage("openticket:array-double","error","This array doesn't allow the same value twice!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else{ + //check all properties + let localQuit = false + if (this.options.propertyChecker) value.forEach((property,index) => { + if (!this.options.propertyChecker) return + + const localLt = checker.locationTraceDeref(lt) + localLt.push(index) + + if (!this.options.propertyChecker.check(checker,property,localLt)) localQuit = true + }) + + //return false if invalid properties + if (localQuit){ + checker.quit = true + return false + }else return super.check(checker,value,locationTrace) + } + } + + /**Check this array for the allowed types */ + #arrayAllowedTypesCheck(array:any[],allowedTypes:("string"|"number"|"boolean"|"null"|"array"|"object"|"other")[]): boolean { + //return TRUE if ALL values are valid + return !array.some((value) => { + if (allowedTypes.includes("string") && typeof value == "string"){ + return false //this value is valid + }else if (allowedTypes.includes("number") && typeof value == "number"){ + return false //this value is valid + }else if (allowedTypes.includes("boolean") && typeof value == "boolean"){ + return false //this value is valid + }else if (allowedTypes.includes("object") && typeof value == "object"){ + return false //this value is valid + }else if (allowedTypes.includes("array") && Array.isArray(value)){ + return false //this value is valid + }else if (allowedTypes.includes("null") && value === null){ + return false //this value is valid + }else if (allowedTypes.includes("other")){ + return false //this value is valid + }else{ + return true //this value is invalid + } + }) + } + /**Check this array for doubles */ + #arrayHasDoubles(array:any[]): boolean { + const alreadyFound: string[] = [] + let hasDoubles = false + array.forEach((value) => { + if (alreadyFound.includes(value)) hasDoubles = true + else alreadyFound.push(value) + }) + + return hasDoubles + } +} + +/**## ODCheckerNullStructureOptions `interface` + * This interface has the options for `ODCheckerNullStructure`! + */ +export interface ODCheckerNullStructureOptions extends ODCheckerStructureOptions { + /**Is the value allowed to be null */ + nullAllowed?:boolean +} + +/**## ODCheckerNullStructure `class` + * This is an open ticket config checker structure. + * + * This class will check for a null variable in a config file, customise it in the settings! + */ +export class ODCheckerNullStructure extends ODCheckerStructure { + declare options: ODCheckerNullStructureOptions + + constructor(id:ODValidId, options:ODCheckerNullStructureOptions){ + super(id,options) + } + + check(checker:ODChecker, value:null, locationTrace:ODCheckerLocationTrace): boolean { + const lt = checker.locationTraceDeref(locationTrace) + + //check type & options + if (typeof this.options.nullAllowed != "undefined" && !this.options.nullAllowed && value == null){ + checker.createMessage("openticket:null-invalid","error","This property can't be null!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (value !== null){ + checker.createMessage("openticket:invalid-type","error","This property needs to be the type: null!",lt,null,["null"],this.id,(this.options.docs ?? null)) + return false + }else return super.check(checker,value,locationTrace) + } +} + +/**## ODCheckerTypeSwitchStructureOptions `interface` + * This interface has the options for `ODCheckerTypeSwitchStructure`! + */ +export interface ODCheckerTypeSwitchStructureOptions extends ODCheckerStructureOptions { + /**A checker that will always run (replaces all other checkers) */ + all?:ODCheckerStructure, + /**A checker when the property is a string */ + string?:ODCheckerStringStructure, + /**A checker when the property is a number */ + number?:ODCheckerNumberStructure, + /**A checker when the property is a boolean */ + boolean?:ODCheckerBooleanStructure, + /**A checker when the property is null */ + null?:ODCheckerStructure, + /**A checker when the property is an array */ + array?:ODCheckerStructure, + /**A checker when the property is an object */ + object?:ODCheckerObjectStructure, + /**A checker when the property is something else */ + other?:ODCheckerStructure, + /**A list of allowed types */ + allowedTypes?:("string"|"number"|"boolean"|"null"|"array"|"object"|"other")[] +} + +/**## ODCheckerTypeSwitchStructure `class` + * This is an open ticket config checker structure. + * + * This class will switch checkers based on the type of the variable in a config file, customise it in the settings! + */ +export class ODCheckerTypeSwitchStructure extends ODCheckerStructure { + declare options: ODCheckerTypeSwitchStructureOptions + + constructor(id:ODValidId, options:ODCheckerTypeSwitchStructureOptions){ + super(id,options) + } + + check(checker:ODChecker, value:any, locationTrace:ODCheckerLocationTrace): boolean { + const lt = checker.locationTraceDeref(locationTrace) + + if (this.options.all){ + return this.options.all.check(checker,value,lt) + + }else if (this.options.string && typeof value == "string"){ + return this.options.string.check(checker,value,lt) + + }else if (this.options.number && typeof value == "number"){ + return this.options.number.check(checker,value,lt) + + }else if (this.options.boolean && typeof value == "boolean"){ + return this.options.boolean.check(checker,value,lt) + + }else if (this.options.array && Array.isArray(value)){ + return this.options.array.check(checker,value,lt) + + }else if (this.options.null && value === null){ + return this.options.null.check(checker,value,lt) + + }else if (this.options.object && typeof value == "object"){ + return this.options.object.check(checker,value,lt) + + }else if (this.options.other){ + return this.options.other.check(checker,value,lt) + + }else if (this.options.allowedTypes && this.options.allowedTypes.length > 0){ + checker.createMessage("openticket:switch-invalid-type","error",`This needs to be one of the following types: ${this.options.allowedTypes.join(", ")}!`,lt,null,[this.options.allowedTypes.join(", ")],this.id,(this.options.docs ?? null)) + return false + }else return super.check(checker,value,locationTrace) + } +} + +/**## ODCheckerObjectSwitchStructureOptions `interface` + * This interface has the options for `ODCheckerObjectSwitchStructure`! + */ +export interface ODCheckerObjectSwitchStructureOptions extends ODCheckerStructureOptions { + /**An array of object checkers with their name, properties & priority. */ + objects?:{ + /**The properties to match for this checker to be used. */ + properties:{key:string, value:any}[], + /**The name for this object type (used in rendering) */ + name:string, + /**The higher the priority, the earlier this checker will be tested. */ + priority:number, + /**The object checker used once the properties have been matched. */ + checker:ODCheckerObjectStructure + }[] +} + +/**## ODCheckerObjectSwitchStructure `class` + * This is an open ticket config checker structure. + * + * This class will switch object checkers based on a variable match in one of the objects, customise it in the settings! + */ +export class ODCheckerObjectSwitchStructure extends ODCheckerStructure { + declare options: ODCheckerObjectSwitchStructureOptions + + constructor(id:ODValidId, options:ODCheckerObjectSwitchStructureOptions){ + super(id,options) + } + + check(checker:ODChecker, value:object, locationTrace:ODCheckerLocationTrace): boolean { + const lt = checker.locationTraceDeref(locationTrace) + + if (this.options.objects){ + //check type & options + if (typeof value != "object"){ + checker.createMessage("openticket:invalid-type","error","This property needs to be the type: object!",lt,null,["object"],this.id,(this.options.docs ?? null)) + return false + } + + //sort objects + const sortedObjects = this.options.objects.sort((a,b) => { + if (a.priority < b.priority) return -1 + else if (a.priority > b.priority) return 1 + else return 0 + }) + + + //check objects + let localQuit = false + let didSelectObject = false + sortedObjects.forEach((obj) => { + if (!obj.properties.some((p) => value[p.key] !== p.value)){ + didSelectObject = true + if (!obj.checker.check(checker,value,lt)) localQuit = true + } + }) + + //do local quit or check custom function + if (!didSelectObject){ + checker.createMessage("openticket:object-switch-invalid-type","error",`This object needs to be one of the following types: ${this.options.objects.map((obj) => obj.name).join(", ")}!`,lt,null,[this.options.objects.map((obj) => obj.name).join(", ")],this.id,(this.options.docs ?? null)) + return false + }else if (localQuit){ + return false + }else return super.check(checker,value,locationTrace) + }else return super.check(checker,value,locationTrace) + } +} + +/**## ODCheckerEnabledObjectStructureOptions `interface` + * This interface has the options for `ODCheckerEnabledObjectStructure`! + */ +export interface ODCheckerEnabledObjectStructureOptions extends ODCheckerStructureOptions { + /**The name of the property to match the `enabledValue`. */ + property?:string, + /**The value of the property to be enabled. Defaults to `true` */ + enabledValue?:any, + /**The object checker to use once the property has been matched. */ + checker?:ODCheckerObjectStructure +} + +/**## ODCheckerEnabledObjectStructure `class` + * This is an open ticket config checker structure. + * + * This class will enable an object checker based on a variable match in the object, customise it in the settings! + */ +export class ODCheckerEnabledObjectStructure extends ODCheckerStructure { + declare options: ODCheckerEnabledObjectStructureOptions + + constructor(id:ODValidId, options:ODCheckerEnabledObjectStructureOptions){ + super(id,options) + } + + check(checker:ODChecker, value:object, locationTrace:ODCheckerLocationTrace): boolean { + const lt = checker.locationTraceDeref(locationTrace) + + if (typeof value != "object"){ + //value isn't an object + checker.createMessage("openticket:invalid-type","error","This property needs to be the type: object!",lt,null,["object"],this.id,(this.options.docs ?? null)) + return false + + }else if (this.options.property && typeof value[this.options.property] == "undefined"){ + //property doesn't exist + checker.createMessage("openticket:property-missing","error",`The property "${this.options.property}" is mising from this object!`,lt,null,[`"${this.options.property}"`],this.id,(this.options.docs ?? null)) + return false + + }else if (this.options.property && value[this.options.property] === (typeof this.options.enabledValue == "undefined" ? true : this.options.enabledValue)){ + //this object is enabled + if (this.options.checker) return this.options.checker.check(checker,value,lt) + else return super.check(checker,value,locationTrace) + + }else{ + //this object is disabled + if (this.options.property) checker.createMessage("openticket:object-disabled","info",`This object is disabled, enable it using "${this.options.property}"!`,lt,null,[`"${this.options.property}"`],this.id,(this.options.docs ?? null)) + return super.check(checker,value,locationTrace) + } + } +} + +/**## ODCheckerCustomStructure_DiscordId `class` + * This is an open ticket custom checker structure. + * + * This class extends a primitive config checker & adds another layer of checking in the `custom` function. + * You can compare it to a blueprint for a specific checker. + * + * **This custom checker is made for discord ids (channel, user, role, ...)** + */ +export class ODCheckerCustomStructure_DiscordId extends ODCheckerStringStructure { + /**The type of id (used in rendering) */ + readonly type: "role"|"server"|"channel"|"category"|"user"|"member"|"interaction"|"message" + /**Is this id allowed to be empty */ + readonly emptyAllowed: boolean + /**Extra matches (value will also be valid when one of these options match) */ + readonly extraOptions: string[] + + constructor(id:ODValidId, type:"role"|"server"|"channel"|"category"|"user"|"member"|"interaction"|"message", emptyAllowed:boolean, extraOptions:string[], options?:ODCheckerStringStructureOptions){ + //add premade custom structure checker + const newOptions = options ?? {} + newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + + if (typeof value != "string") return false + else if ((!emptyAllowed && value.length < 15) || value.length > 50 || !/^[0-9]*$/.test(value)){ + if (!(extraOptions.length > 0 && extraOptions.some((opt) => opt == value))){ + //value is not an id & not one of the extra options + if (extraOptions.length > 0) checker.createMessage("openticket:discord-invalid-id-options","error",`This is an invalid discord ${type} id! You can also use one of these: ${extraOptions.join(", ")}!`,lt,null,[type,extraOptions.join(", ")],this.id,(this.options.docs ?? null)) + else checker.createMessage("openticket:discord-invalid-id","error",`This is an invalid discord ${type} id!`,lt,null,[type],this.id,(this.options.docs ?? null)) + return false + }else return true + } + return true + } + super(id,newOptions) + this.type = type + this.emptyAllowed = emptyAllowed + this.extraOptions = extraOptions + } +} + +/**## ODCheckerCustomStructure_DiscordIdArray `class` + * This is an open ticket custom checker structure. + * + * This class extends a primitive config checker & adds another layer of checking in the `custom` function. + * You can compare it to a blueprint for a specific checker. + * + * **This custom checker is made for discord id arrays (channel, user, role, ...)** + */ +export class ODCheckerCustomStructure_DiscordIdArray extends ODCheckerArrayStructure { + /**The type of id (used in rendering) */ + readonly type: "role"|"server"|"channel"|"category"|"user"|"member"|"interaction"|"message" + /**Extra matches (value will also be valid when one of these options match) */ + readonly extraOptions: string[] + + constructor(id:ODValidId, type:"role"|"server"|"channel"|"category"|"user"|"member"|"interaction"|"message", extraOptions:string[], options?:ODCheckerArrayStructureOptions, idOptions?:ODCheckerStringStructureOptions){ + //add premade custom structure checker + const newOptions = options ?? {} + newOptions.propertyChecker = new ODCheckerCustomStructure_DiscordId(id,type,false,extraOptions,idOptions) + super(id,newOptions) + this.type = type + this.extraOptions = extraOptions + } +} + +/**## ODCheckerCustomStructure_DiscordToken `class` + * This is an open ticket custom checker structure. + * + * This class extends a primitive config checker & adds another layer of checking in the `custom` function. + * You can compare it to a blueprint for a specific checker. + * + * **This custom checker is made for a discord (auth) token** + */ +export class ODCheckerCustomStructure_DiscordToken extends ODCheckerStringStructure { + constructor(id:ODValidId, options?:ODCheckerStringStructureOptions){ + //add premade custom structure checker + const newOptions = options ?? {} + newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + + if (typeof value != "string" || !/^[A-Za-z0-9-_\.]+$/.test(value)){ + checker.createMessage("openticket:discord-invalid-token","error","This is an invalid discord token (syntactically)!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + } + return true + } + super(id,newOptions) + } +} + +/**## ODCheckerCustomStructure_DiscordToken `class` + * This is an open ticket custom checker structure. + * + * This class extends a primitive config checker & adds another layer of checking in the `custom` function. + * You can compare it to a blueprint for a specific checker. + * + * **This custom checker is made for a hex color** + */ +export class ODCheckerCustomStructure_HexColor extends ODCheckerStringStructure { + /**When enabled, you are also allowed to use `#fff` instead of `#ffffff` */ + readonly allowShortForm: boolean + /**Allow this hex color to be empty. */ + readonly emptyAllowed: boolean + + constructor(id:ODValidId, allowShortForm:boolean, emptyAllowed:boolean, options?:ODCheckerStringStructureOptions){ + //add premade custom structure checker + const newOptions = options ?? {} + newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + + if (typeof value != "string") return false + else if (emptyAllowed && value.length == 0){ + return true + }else if ((!allowShortForm && !/^#[a-f0-9]{6}$/.test(value)) || (allowShortForm && !/^#[a-f0-9]{6}$/.test(value) && !/^#[a-f0-9]{3}$/.test(value))){ + checker.createMessage("openticket:color-invalid","error","This is an invalid hex color!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else return true + } + super(id,newOptions) + this.allowShortForm = allowShortForm + this.emptyAllowed = emptyAllowed + } +} + +/**## ODCheckerCustomStructure_EmojiString `class` + * This is an open ticket custom checker structure. + * + * This class extends a primitive config checker & adds another layer of checking in the `custom` function. + * You can compare it to a blueprint for a specific checker. + * + * **This custom checker is made for an emoji (string)** + */ +export class ODCheckerCustomStructure_EmojiString extends ODCheckerStringStructure { + /**The minimum amount of emojis required (0 to allow empty) */ + readonly minLength: number + /**The maximum amount of emojis allowed */ + readonly maxLength: number + /**Allow custom discord emoji ids (`<:12345678910:emoji_name>`) */ + readonly allowCustomDiscordEmoji: boolean + + constructor(id:ODValidId, minLength:number, maxLength:number, allowCustomDiscordEmoji:boolean, options?:ODCheckerStringStructureOptions){ + //add premade custom structure checker + const newOptions = options ?? {} + newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + + if (typeof value != "string") return false + else if ([...value].length < minLength){ + checker.createMessage("openticket:emoji-too-short","error",`This string needs to have at least ${minLength} emoji's!`,lt,null,[maxLength.toString()],this.id,(this.options.docs ?? null)) + return false + }else if ([...value].length > maxLength){ + checker.createMessage("openticket:emoji-too-long","error",`This string needs to have at most ${maxLength} emoji's!`,lt,null,[maxLength.toString()],this.id,(this.options.docs ?? null)) + return false + }else if (!allowCustomDiscordEmoji && //.test(value)){ + checker.createMessage("openticket:emoji-custom","error",`This emoji can't be a custom discord emoji!`,lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (!/^(?:(?:\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])|(?:))*$/.test(value)){ + checker.createMessage("openticket:emoji-invalid","error","This is an invalid emoji!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + } + return true + } + super(id,newOptions) + this.minLength = minLength + this.maxLength = maxLength + this.allowCustomDiscordEmoji = allowCustomDiscordEmoji + } +} + +/**## ODCheckerCustomStructureOptions_UrlString `interface` + * This interface has the options for `ODCheckerCustomStructure_UrlString`! + */ +export interface ODCheckerCustomStructureOptions_UrlString { + /**Allow urls with `http://` instead of `https://` */ + allowHttp?:boolean + /**Allowed hostnames (string or regex) => will match domain + subdomain */ + allowedHostnames?: (string|RegExp)[] + /**Allowed extentions (string) => will match the end of the url (`.png`,`.svg`,...) */ + allowedExtensions?: string[] + /**Allowed paths (string or regex) => will match path + extension (not domain + subdomain) */ + allowedPaths?: (string|RegExp)[], + /**A regex that will be executed on the entire url (including search params, protcol, domain, ...) */ + regex?:RegExp +} + +/**## ODCheckerCustomStructure_UrlString `class` + * This is an open ticket custom checker structure. + * + * This class extends a primitive config checker & adds another layer of checking in the `custom` function. + * You can compare it to a blueprint for a specific checker. + * + * **This custom checker is made for a URL (string)** + */ +export class ODCheckerCustomStructure_UrlString extends ODCheckerStringStructure { + /**The settings for this url */ + readonly urlSettings: ODCheckerCustomStructureOptions_UrlString + /**Is this url allowed to be empty? */ + readonly emptyAllowed: boolean + + constructor(id:ODValidId, emptyAllowed:boolean, urlSettings:ODCheckerCustomStructureOptions_UrlString, options?:ODCheckerStringStructureOptions){ + //add premade custom structure checker + const newOptions = options ?? {} + newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + + if (typeof value != "string") return false + else if (emptyAllowed && value.length == 0){ + return true + }else if (!this.#urlIsValid(value)){ + checker.createMessage("openticket:url-invalid","error","This url is invalid!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.urlSettings.allowHttp != "undefined" && !this.urlSettings.allowHttp && !/^(https:\/\/)/.test(value)){ + checker.createMessage("openticket:url-invalid-http","error","This url can only use the https:// protocol!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (!/^(http(s)?:\/\/)/.test(value)){ + checker.createMessage("openticket:url-invalid-protocol","error","This url can only use the http:// & https:// protocols!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.urlSettings.allowedHostnames != "undefined" && !this.#urlHasValidHostname(value,this.urlSettings.allowedHostnames)){ + checker.createMessage("openticket:url-invalid-hostname","error","This url has a disallowed hostname!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.urlSettings.allowedExtensions != "undefined" && !this.#urlHasValidExtension(value,this.urlSettings.allowedExtensions)){ + checker.createMessage("openticket:url-invalid-extension","error",`This url has an invalid extension! Choose between: ${this.urlSettings.allowedExtensions.join(", ")}!"`,lt,null,[this.urlSettings.allowedExtensions.join(", ")],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.urlSettings.allowedPaths != "undefined" && !this.#urlHasValidPath(value,this.urlSettings.allowedPaths)){ + checker.createMessage("openticket:url-invalid-path","error","This url has an invalid path!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else if (typeof this.urlSettings.regex != "undefined" && !this.urlSettings.regex.test(value)){ + checker.createMessage("openticket:url-invalid","error","This url is invalid!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else return true + } + super(id,newOptions) + this.urlSettings = urlSettings + this.emptyAllowed = emptyAllowed + } + + /**Check for the hostname */ + #urlHasValidHostname(url:string,hostnames:(string|RegExp)[]): boolean { + try { + const hostname = new URL(url).hostname + return hostnames.some((rule) => { + if (typeof rule == "string"){ + return rule == hostname + }else{ + return rule.test(hostname) + } + }) + + }catch{ + return false + } + } + /**Check for the extension */ + #urlHasValidExtension(url:string,extensions:string[]): boolean { + try { + const path = new URL(url).pathname + return extensions.some((rule) => { + return path.endsWith(rule) + }) + }catch{ + return false + } + } + /**Check for the path */ + #urlHasValidPath(url:string,paths:(string|RegExp)[]): boolean { + try { + const path = new URL(url).pathname + return paths.some((rule) => { + if (typeof rule == "string"){ + return rule == path + }else{ + return rule.test(path) + } + }) + }catch{ + return false + } + } + /**Do general syntax check on url */ + #urlIsValid(url:string){ + try { + new URL(url) + return true + }catch{ + return false + } + } +} + +/**## ODCheckerCustomStructure_UniqueId `class` + * This is an open ticket custom checker structure. + * + * This class extends a primitive config checker & adds another layer of checking in the `custom` function. + * You can compare it to a blueprint for a specific checker. + * + * **This custom checker is made for a unique id (per source & scope)** + */ +export class ODCheckerCustomStructure_UniqueId extends ODCheckerStringStructure { + /**The source of this unique id (generally the plugin name or `openticket`) */ + readonly source: string + /**The scope of this unique id (id needs to be unique in this scope) */ + readonly scope: string + + constructor(id:ODValidId, source:string, scope:string, options?:ODCheckerStringStructureOptions){ + //add premade custom structure checker + const newOptions = options ?? {} + newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + + if (typeof value != "string") return false + const uniqueArray: string[] = (checker.storage.get(source,scope) === null) ? [] : checker.storage.get(source,scope) + if (uniqueArray.includes(value)){ + //unique id already exists => throw error + checker.createMessage("openticket:id-not-unique","error","This id isn't unique, use another id instead!",lt,null,[],this.id,(this.options.docs ?? null)) + return false + }else{ + //unique id doesn't exists => add to list + uniqueArray.push(value) + checker.storage.set(source,scope,uniqueArray) + return true + } + } + super(id,newOptions) + this.source = source + this.scope = scope + } +} + +/**## ODCheckerCustomStructure_UniqueIdArray `class` + * This is an open ticket custom checker structure. + * + * This class extends a primitive config checker & adds another layer of checking in the `custom` function. + * You can compare it to a blueprint for a specific checker. + * + * **This custom checker is made for a unique id array (per source & scope)** + */ +export class ODCheckerCustomStructure_UniqueIdArray extends ODCheckerArrayStructure { + /**The source to read unique ids (generally the plugin name or `openticket`) */ + readonly source: string + /**The scope to read unique ids (id needs to be unique in this scope) */ + readonly scope: string + /**The scope to push unique ids when used in this array! */ + readonly usedScope: string|null + + constructor(id:ODValidId, source:string, scope:string, usedScope?:string, options?:ODCheckerArrayStructureOptions){ + //add premade custom structure checker + const newOptions = options ?? {} + newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + + if (!Array.isArray(value)) return false + const uniqueArray: string[] = (checker.storage.get(source,scope) === null) ? [] : checker.storage.get(source,scope) + + let localQuit = false + value.forEach((id,index) => { + if (typeof id != "string") return + const localLt = checker.locationTraceDeref(lt) + localLt.push(index) + if (uniqueArray.includes(id)){ + //exists + if (usedScope){ + const current: string[] = checker.storage.get(source,usedScope) ?? [] + current.push(id) + checker.storage.set(source,usedScope,current) + } + }else{ + //doesn't exist + checker.createMessage("openticket:id-non-existent","error",`The id "${id}" doesn't exist!`,localLt,null,[`"${id}"`],this.id,(this.options.docs ?? null)) + localQuit = true + } + }) + return !localQuit + } + super(id,newOptions) + this.source = source + this.scope = scope + this.usedScope = usedScope ?? null + } +} + +/*TEMPLATE!!!! +export interface ODCheckerTemplateStructureOptions extends ODCheckerStructureOptions { + +} +export class ODCheckerTemplateStructure extends ODCheckerStructure { + declare options: ODCheckerTemplateStructureOptions + + constructor(id:ODValidId, options:ODCheckerTemplateStructureOptions){ + super(id,options) + } + + check(checker:ODChecker, value:any, locationTrace:ODCheckerLocationTrace): boolean { + const lt = checker.locationTraceDeref(locationTrace) + + return super.check(checker,value,locationTrace) + } +} +*/ +/*CUSTOM TEMPLATE!!!! +export class ODCheckerCustomStructure_Template extends ODCheckerTemplateStructure { + idk: string + + constructor(id:ODValidId, idk:string, options?:ODCheckerStringStructureOptions){ + //add premade custom structure checker + const newOptions = options ?? {} + newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + + //do custom check & push error message. Return true if correct + return boolean + } + super(id,newOptions) + this.idk = idk + } +} +*/ \ No newline at end of file diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts new file mode 100644 index 0000000..c7ca8dc --- /dev/null +++ b/src/core/api/modules/client.ts @@ -0,0 +1,1470 @@ +/////////////////////////////////////// +//DISCORD CLIENT MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base" +import * as discord from "discord.js" +import { ODConsoleWarningMessage, ODDebugger } from "./console" +import { ODMessageBuildResult, ODMessageBuildSentResult } from "./builder" + +/**## ODClientIntents `type` + * A list of intents required when inviting the bot. + */ +export type ODClientIntents = ("Guilds"|"GuildMembers"|"GuildModeration"|"GuildEmojisAndStickers"|"GuildIntegrations"|"GuildWebhooks"|"GuildInvites"|"GuildVoiceStates"|"GuildPresences"|"GuildMessages"|"GuildMessageReactions"|"GuildMessageTyping"|"DirectMessages"|"DirectMessageReactions"|"DirectMessageTyping"|"MessageContent"|"GuildScheduledEvents"|"AutoModerationConfiguration"|"AutoModerationExecution") +/**## ODClientPriviligedIntents `type` + * A list of priviliged intents required to be enabled in the developer portal. + */ +export type ODClientPriviligedIntents = ("GuildMembers"|"MessageContent"|"Presence") +/**## ODClientPartials `type` + * A list of partials required for the bot to work. (`Message` & `Channel` are for receiving DM messages from uncached channels) + */ +export type ODClientPartials = ("User"|"Channel"|"GuildMember"|"Message"|"Reaction"|"GuildScheduledEvent"|"ThreadMember") +/**## ODClientPermissions `type` + * A list of permissions required in the server that the bot is active in. + */ +export type ODClientPermissions = ("CreateInstantInvite"|"KickMembers"|"BanMembers"|"Administrator"|"ManageChannels"|"ManageGuild"|"AddReactions"|"ViewAuditLog"|"PrioritySpeaker"|"Stream"|"ViewChannel"|"SendMessages"|"SendTTSMessages"|"ManageMessages"|"EmbedLinks"|"AttachFiles"|"ReadMessageHistory"|"MentionEveryone"|"UseExternalEmojis"|"ViewGuildInsights"|"Connect"|"Speak"|"MuteMembers"|"DeafenMembers"|"MoveMembers"|"UseVAD"|"ChangeNickname"|"ManageNicknames"|"ManageRoles"|"ManageWebhooks"|"ManageGuildExpressions"|"UseApplicationCommands"|"RequestToSpeak"|"ManageEvents"|"ManageThreads"|"CreatePublicThreads"|"CreatePrivateThreads"|"UseExternalStickers"|"SendMessagesInThreads"|"UseEmbeddedActivities"|"ModerateMembers"|"ViewCreatorMonetizationAnalytics"|"UseSoundboard"|"UseExternalSounds"|"SendVoiceMessages") + +/**## ODClientManager `class` + * This is an open ticket client manager. + * + * It is responsible for managing the discord.js client. Here, you can set the status, register slash commands and much more! + * + * If you want, you can also listen for custom events on the `ODClientManager.client` variable (`discord.Client`) + */ +export class ODClientManager { + /**Alias to open ticket debugger. */ + #debug: ODDebugger + + /**List of required bot intents. Add intents to this list using the `onClientConfiguration` event. */ + intents: ODClientIntents[] = [] + /**List of required bot privileged intents. Add intents to this list using the `onClientConfiguration` event. */ + privileges: ODClientPriviligedIntents[] = [] + /**List of required bot partials. Add intents to this list using the `onClientConfiguration` event. **❌ Only use when neccessery!** */ + partials: ODClientPartials[] = [] + /**List of required bot permissions. Add permissions to this list using the `onClientConfiguration` event. */ + permissions: ODClientPermissions[] = [] + /**The bot token, empty by default. */ + token: string = "" + + /**The discord.js `discord.Client`. Only use it when initiated! */ + client: discord.Client = new discord.Client({intents:[]}) //temporary client + /**Is the bot initiated? */ + initiated: boolean = false + /**Is the bot logged in? */ + loggedIn: boolean = false + /**Is the bot ready? */ + ready: boolean = false + + /**The main server of the bot. Provided by serverId in the config */ + mainServer: discord.Guild|null = null + /**(❌ DO NOD OVERWRITE ❌) Internal open ticket function to continue the startup when the client is ready! */ + readyListener: (() => Promise)|null = null + /**The status manager is responsible for setting the bot status. */ + activity: ODClientActivityManager + /**The slash command manager is responsible for all slash commands & their events inside the bot. */ + slashCommands: ODSlashCommandManager + /**The text command manager is responsible for all text commands & their events inside the bot. */ + textCommands: ODTextCommandManager + + constructor(debug:ODDebugger){ + this.#debug = debug + this.activity = new ODClientActivityManager(this.#debug,this) + this.slashCommands = new ODSlashCommandManager(this.#debug,this) + this.textCommands = new ODTextCommandManager(this.#debug,this) + } + + /**Initiate the `client` variable & add the intents & partials to the bot. */ + initClient(){ + if (!this.intents.every((value) => typeof discord.GatewayIntentBits[value] != "undefined")) throw new ODSystemError("Client has non-existing intents!") + if (!this.privileges.every((value) => typeof {GuildMembers:true,MessageContent:true,Presence:true}[value] != "undefined")) throw new ODSystemError("Client has non-existing privileged intents!") + if (!this.partials.every((value) => typeof discord.Partials[value] != "undefined")) throw new ODSystemError("Client has non-existing partials!") + if (!this.permissions.every((value) => typeof discord.PermissionFlagsBits[value] != "undefined")) throw new ODSystemError("Client has non-existing partials!") + + const intents = this.intents.map((value) => discord.GatewayIntentBits[value]) + const partials = this.partials.map((value) => discord.Partials[value]) + + const oldClient = this.client + this.client = new discord.Client({intents,partials}) + + //@ts-ignore + oldClient.eventNames().forEach((event:keyof discord.ClientEvents) => { + //@ts-ignore + const callbacks = oldClient.rawListeners(event) + callbacks.forEach((cb:() => void) => { + this.client.on(event,cb) + }) + }) + + this.initiated = true + + this.#debug.debug("Created client with intents: "+this.intents.join(", ")) + this.#debug.debug("Created client with privileged intents: "+this.privileges.join(", ")) + this.#debug.debug("Created client with partials: "+this.partials.join(", ")) + this.#debug.debug("Created client with permissions: "+this.permissions.join(", ")) + } + /**Get all servers the bot is part of. */ + getGuilds(){ + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + + return this.client.guilds.cache.map((guild) => guild) + } + /**Check if the bot is in a specific guild */ + checkBotInGuild(guild:discord.Guild){ + return (guild.members.me) ? true : false + } + /**Check if a specific guild has all required permissions (or `Administrator`) */ + checkGuildPerms(guild:discord.Guild){ + if (!guild.members.me) throw new ODSystemError("Client isn't a member in this server!") + const perms = guild.members.me.permissions + if (perms.has("Administrator")) return true + else{ + return this.permissions.every((perm) => { + return perms.has(perm) + }) + } + } + /**Log-in with a discord auth token. */ + login(): Promise { + return new Promise(async (resolve,reject) => { + if (!this.initiated) reject("Client isn't initiated yet!") + if (!this.token) reject("Client doesn't have a token!") + + try { + this.client.once("ready",async () => { + this.ready = true + + //set slashCommandManager to client applicationCommandManager + if (!this.client.application) throw new ODSystemError("Couldn't get client application! Unable to register slash commands!") + this.slashCommands.commandManager = this.client.application.commands + + if (this.readyListener) await this.readyListener() + resolve(true) + }) + + this.#debug.debug("Actual discord.js client.login()") + await this.client.login(this.token) + this.#debug.debug("Finished discord.js client.login()") + this.loggedIn = true + }catch(err){ + if (err.message.toLowerCase() == "used disallowed intents"){ + process.emit("uncaughtException",new ODSystemError("Used disallowed intents")) + }else reject("login error: "+err) + } + }) + } + /**A simplified shortcut to get a `discord.User` :) */ + async fetchUser(id:string): Promise { + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + + try{ + return await this.client.users.fetch(id) + }catch{ + return null + } + } + /**A simplified shortcut to get a `discord.Guild` :) */ + async fetchGuild(id:string): Promise { + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + + try{ + return await this.client.guilds.fetch(id) + }catch{ + return null + } + } + /**A simplified shortcut to get a `discord.Channel` :) */ + async fetchChannel(id:string): Promise { + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + + try{ + return await this.client.channels.fetch(id) + }catch{ + return null + } + } + /**A simplified shortcut to get a `discord.GuildBasedChannel` :) */ + async fetchGuildChannel(guildId:string|discord.Guild, id:string): Promise { + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + + try{ + const guild = (guildId instanceof discord.Guild) ? guildId : await this.fetchGuild(guildId) + if (!guild) return null + const channel = await guild.channels.fetch(id) + return channel + }catch{ + return null + } + } + /**A simplified shortcut to get a `discord.TextChannel` :) */ + async fetchGuildTextChannel(guildId:string|discord.Guild, id:string): Promise { + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + + try{ + const guild = (guildId instanceof discord.Guild) ? guildId : await this.fetchGuild(guildId) + if (!guild) return null + const channel = await guild.channels.fetch(id) + if (!channel || channel.type != discord.ChannelType.GuildText) return null + return channel + }catch{ + return null + } + } + /**A simplified shortcut to get a `discord.CategoryChannel` :) */ + async fetchGuildCategoryChannel(guildId:string|discord.Guild, id:string): Promise { + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + + try{ + const guild = (guildId instanceof discord.Guild) ? guildId : await this.fetchGuild(guildId) + if (!guild) return null + const channel = await guild.channels.fetch(id) + if (!channel || channel.type != discord.ChannelType.GuildCategory) return null + return channel + }catch{ + return null + } + } + /**A simplified shortcut to get a `discord.GuildMember` :) */ + async fetchGuildMember(guildId:string|discord.Guild, id:string): Promise { + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + if (typeof id != "string") throw new ODSystemError("TEMP ERROR => ODClientManager.fetchGuildMember() => id param isn't string") + + try{ + const guild = (guildId instanceof discord.Guild) ? guildId : await this.fetchGuild(guildId) + if (!guild) return null + return await guild.members.fetch(id) + }catch{ + return null + } + } + /**A simplified shortcut to get a `discord.Role` :) */ + async fetchGuildRole(guildId:string|discord.Guild, id:string): Promise { + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + if (typeof id != "string") throw new ODSystemError("TEMP ERROR => ODClientManager.fetchGuildRole() => id param isn't string") + + try{ + const guild = (guildId instanceof discord.Guild) ? guildId : await this.fetchGuild(guildId) + if (!guild) return null + return await guild.roles.fetch(id) + }catch{ + return null + } + } + /**A simplified shortcut to get a `discord.Message` :) */ + async fetchGuildChannelMessage(guildId:string|discord.Guild, channelId:string|discord.TextChannel, id:string): Promise|null> + async fetchGuildChannelMessage(channelId:discord.TextChannel, id:string): Promise|null> + async fetchGuildChannelMessage(guildId:string|discord.Guild|discord.TextChannel, channelId:string|discord.TextChannel|string, id?:string): Promise|null> { + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + + try{ + if (guildId instanceof discord.TextChannel && typeof channelId == "string"){ + const channel = guildId + return await channel.messages.fetch(channelId) + }else if (!(guildId instanceof discord.TextChannel) && id){ + const channel = (channelId instanceof discord.TextChannel) ? channelId : await this.fetchGuildTextChannel(guildId,channelId) + if (!channel) return null + return await channel.messages.fetch(id) + }else return null + }catch{ + return null + } + } + /**A simplified shortcut to send a DM to a user :) */ + async sendUserDm(user:string|discord.User, message:ODMessageBuildResult): Promise> { + if (!this.initiated) throw new ODSystemError("Client isn't initiated yet!") + if (!this.ready) throw new ODSystemError("Client isn't ready yet!") + + try{ + if (user instanceof discord.User){ + if (user.bot) return {success:false,message:null} + const channel = await user.createDM() + const msg = await channel.send(message.message) + return {success:true,message:msg} + }else{ + const newUser = await this.fetchUser(user) + if (!newUser) throw new Error() + if (newUser.bot) return {success:false,message:null} + const channel = await newUser.createDM() + const msg = await channel.send(message.message) + return {success:true,message:msg} + } + }catch{ + try{ + this.#debug.console.log("Failed to send DM to user! ","warning",[ + {key:"id",value:(user instanceof discord.User ? user.id : user)}, + {key:"message",value:message.id.value} + ]) + }catch{} + return {success:false,message:null} + } + } +} + +/**## ODClientActivityType `type` + * Possible activity types for the bot. + */ +export type ODClientActivityType = ("playing"|"listening"|"watching"|"custom"|false) +/**## ODClientPermissions `type` + * Possible activity statuses for the bot. + */ +export type ODClientActivityStatus = ("online"|"invisible"|"idle"|"dnd") + + +/**## ODClientActivityManager `class` + * This is an open ticket client activity manager. + * + * It's responsible for managing the client status. Here, you can set the activity & status of the bot. + * + * It also has a built-in refresh function, so the status will refresh every 10 minutes to keep it visible. + */ +export class ODClientActivityManager { + /**Alias to open ticket debugger. */ + #debug: ODDebugger + + /**Copy of discord.js client */ + manager: ODClientManager + /**The current status type */ + type: ODClientActivityType = false + /**The current status text */ + text: string = "" + /**The current status status */ + status: ODClientActivityStatus = "online" + + /**The timer responsible for refreshing the status. Stop it using `clearInterval(interval)` */ + interval?: NodeJS.Timeout + /**status refresh interval in seconds*/ + refreshInterval: number = 600 + /**Is the status already initiated? */ + initiated: boolean = false + + constructor(debug:ODDebugger, manager:ODClientManager){ + this.#debug = debug + this.manager = manager + } + + /**Update the status. When already initiated, it can take up to 10min to see the updated status in discord. */ + setStatus(type:ODClientActivityType,text:string,status:ODClientActivityStatus){ + this.type = type + this.text = text + this.status = status + } + + /**When initiating the status, the bot starts updating the status using `discord.js`. Returns if succesfull or not. */ + initStatus(): boolean { + if (this.initiated || !this.manager.ready) return false + this.#updateClientActivity(this.type,this.text) + this.interval = setInterval(() => { + this.#updateClientActivity(this.type,this.text) + this.#debug.debug("Client status update cycle") + },this.refreshInterval*1000) + this.initiated = true + this.#debug.debug("Client status initiated") + return true + } + + /**Update the client status */ + #updateClientActivity(type:ODClientActivityType,text:string){ + if (!this.manager.client.user) throw new ODSystemError("Couldn't set client status: client.user == undefined") + if (type == false){ + this.manager.client.user.setActivity() + return + } + this.manager.client.user.setPresence({ + activities:[{ + type:this.#getStatusTypeEnum(type), + state:text, + name:text, + }], + status:this.status + }) + } + /**Get the enum that links to the correct type */ + #getStatusTypeEnum(type:Exclude){ + if (type == "playing") return discord.ActivityType.Playing + else if (type == "listening") return discord.ActivityType.Listening + else if (type == "watching") return discord.ActivityType.Watching + else if (type == "custom") return discord.ActivityType.Custom + else return discord.ActivityType.Listening + } + /**Get the status type (for displaying the status) */ + getStatusType(): "listening "|"playing "|"watching "|"" { + if (this.type == "listening" || this.type == "playing" || this.type == "watching") return this.type+" " as "listening "|"playing "|"watching "|"" + else return "" + } +} + +/**## ODSlashCommandInteractionCallback `type` + * Callback for the slash command interaction listener. + */ +export type ODSlashCommandInteractionCallback = (interaction:discord.ChatInputCommandInteraction,cmd:ODSlashCommand) => void + +/**## ODSlashCommandManager `class` + * This is an open ticket client slash manager. + * + * It's responsible for managing all the slash commands from the client. + * + * Here, you can add & remove slash commands & the bot will do the (de)registering. + */ +export class ODSlashCommandManager extends ODManager { + /**Alias to open ticket debugger. */ + #debug: ODDebugger + + /**Copy of discord.js client. */ + manager: ODClientManager + /**Discord.js application commands manager. */ + commandManager: discord.ApplicationCommandManager|null + /**Collection of all interaction listeners. */ + #interactionListeners: {name:string|RegExp, callback:ODSlashCommandInteractionCallback}[] = [] + /**Set the soft limit for maximum amount of listeners. A warning will be shown when there are more listeners than this limit. */ + listenerLimit: number = 100 + + constructor(debug:ODDebugger, manager:ODClientManager){ + super(debug,"slash command") + this.#debug = debug + this.manager = manager + this.commandManager = (manager.client.application) ? manager.client.application.commands : null + } + + /**Create all commands that don't exist yet. (global by default OR guildId for per-server) */ + async createNewCommands(guildId?:string){ + if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") + const cmds = await this.#existsCmd(guildId) + + let i = 0 + while (i < cmds.nonExisting.length){ + await this.#createCmd(cmds.nonExisting[i]) + this.#debug.debug("Created new slash command",[{key:"id",value:cmds.nonExisting[i].id.value},{key:"name",value:cmds.nonExisting[i].name}]) + i++ + } + } + /**Update all commands that already exist. (global by default OR guildId for per-server) */ + async updateExistingCommands(guildId?:string,force?:boolean){ + if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") + const cmds = await this.#existsCmd(guildId) + const filtered = cmds.existing.filter((cmd) => (cmd.requiresUpdate == true || force)) + + for (const cmd of filtered){ + await this.#createCmd(cmd.cmd) + this.#debug.debug("Updated existing slash command",[ + {key:"id",value:cmd.cmd.id.value}, + {key:"name",value:cmd.cmd.name}, + {key:"force",value:force ? "true" : "false"} + ]) + } + } + /**Remove all commands that exist but aren't used by open ticket. (global by default OR guildId for per-server) */ + async removeUnusedCommands(guildId?:string){ + if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") + const cmds = (await this.#unusedCmd(guildId)).map((cmd) => cmd.name) + await this.#removeCmd(cmds,guildId) + } + /**Create a slash command from an `ODSlashCommand` class */ + async #createCmd(cmd:ODSlashCommand){ + if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") + try { + await this.commandManager.create(cmd.builder,(cmd.guildId ?? undefined)) + }catch(err){ + process.emit("uncaughtException",err) + throw new ODSystemError("Failed to register slash command '/"+cmd.name+"'!") + } + } + /**Remove slash cmds by name */ + async #removeCmd(names:string[],guildId?:string){ + if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") + + const cmds = await this.commandManager.fetch({guildId}) + + cmds?.forEach((cmd) => { + if (!names.includes(cmd.name)) return + cmd.delete() + this.#debug.debug("Removed existing slash command",[{key:"name",value:cmd.name}]) + }) + } + /**Get all existing & non-existing slash commands. */ + async #existsCmd(guildId?:string){ + if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") + + const cmds = await this.commandManager.fetch({guildId}) + const existing: {cmd:ODSlashCommand, requiresUpdate:boolean}[] = [] + const nonExisting: ODSlashCommand[] = [] + + this.getAll().forEach((cmd) => { + if (guildId && cmd.guildId != guildId) return + const result = cmds.find((cmddata) => cmddata.name == cmd.name) + if (result){ + //command already exists (and may need to be updated) + const requiresUpdate = cmd.requiresUpdate ? cmd.requiresUpdate({ + name:result.name, + description:result.description, + options:result.options as readonly discord.ApplicationCommandOptionData[], + nsfw:result.nsfw, + dmPermission:result.dmPermission ?? undefined, + defaultMemberPermissions:result.defaultMemberPermissions, + nameLocalizations:result.nameLocalizations ?? undefined, + descriptionLocalizations:result.descriptionLocalizations ?? undefined + }) : false + existing.push({cmd,requiresUpdate}) + + //command doesn't exists yet + }else nonExisting.push(cmd) + }) + + return {existing,nonExisting} + } + /**Get all unused slash commands. */ + async #unusedCmd(guildId?:string){ + if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") + + const cmds = await this.commandManager.fetch({guildId}) + const unused: discord.ApplicationCommand[] = [] + + const allCommands = this.getAll() + cmds.forEach((cmddata) => { + if (guildId && cmddata.guildId != guildId) return + + if (!allCommands.find((cmd) => { + if (cmd.name != cmddata.name) return false + if (cmd.builder.description != cmddata.description) return false + return this.#checkUnusedOptions(cmddata.options,cmd.builder.options ?? []) + + })) unused.push(cmddata) + }) + + return unused + } + /**Returns `true` if the options are the same in both arrays. It will work recursively! */ + #checkUnusedOptions(currentOptions:readonly discord.ApplicationCommandOption[], newOptions:readonly discord.ApplicationCommandOptionData[]){ + if ((!newOptions || newOptions.length == 0) && currentOptions.length == 0) return true + else if (newOptions && newOptions.length != currentOptions.length) return false + + if (!currentOptions.every((currentOpt,index) => { + const newOpt = newOptions[index] + if (newOpt.name != currentOpt.name) return false + if (newOpt.type != currentOpt.type) return false + if (newOpt.description != currentOpt.description) return false + + if (newOpt.type == discord.ApplicationCommandOptionType.Number && currentOpt.type == discord.ApplicationCommandOptionType.Number){ + //check for min & max values when type is number + if (newOpt.minValue != currentOpt.minValue) return false + if (newOpt.maxValue != currentOpt.maxValue) return false + } + if (newOpt.type == discord.ApplicationCommandOptionType.String && currentOpt.type == discord.ApplicationCommandOptionType.String){ + //check for min & max length values when type is string + if (newOpt.minLength != currentOpt.minLength) return false + if (newOpt.maxLength != currentOpt.maxLength) return false + } + + //check for required normal options + if (currentOpt.type != discord.ApplicationCommandOptionType.SubcommandGroup && currentOpt.type != discord.ApplicationCommandOptionType.Subcommand && newOpt.type != discord.ApplicationCommandOptionType.SubcommandGroup && newOpt.type != discord.ApplicationCommandOptionType.Subcommand){ + if (currentOpt.required != newOpt.required) return false + + //check for sub-options in subcommands + }else if ((currentOpt.type == discord.ApplicationCommandOptionType.SubcommandGroup && newOpt.type == discord.ApplicationCommandOptionType.SubcommandGroup) || (currentOpt.type == discord.ApplicationCommandOptionType.Subcommand && newOpt.type == discord.ApplicationCommandOptionType.Subcommand)){ + if (currentOpt.options && newOpt.options){ + return this.#checkUnusedOptions(currentOpt.options,newOpt.options) + } + } + + return true + })) return false + return true + } + /**Start listening to the discord.js client `interactionCreate` event. */ + startListeningToInteractions(){ + this.manager.client.on("interactionCreate",(interaction) => { + //return when not in main server or DM + if (!this.manager.mainServer || (interaction.guild && interaction.guild.id != this.manager.mainServer.id)) return + + if (!interaction.isChatInputCommand()) return + const cmd = this.getFiltered((cmd) => cmd.name == interaction.commandName)[0] + if (!cmd) return + + this.#interactionListeners.forEach((listener) => { + if (typeof listener.name == "string" && (interaction.commandName != listener.name)) return + else if (listener.name instanceof RegExp && !listener.name.test(interaction.commandName)) return + + //this is a valid listener + listener.callback(interaction,cmd) + }) + }) + } + /**Callback on interaction from one or multiple slash commands. */ + onInteraction(commandName:string|RegExp, callback:ODSlashCommandInteractionCallback){ + this.#interactionListeners.push({ + name:commandName, + callback + }) + + if (this.#interactionListeners.length > this.listenerLimit){ + this.#debug.console.log(new ODConsoleWarningMessage("Possible slash command interaction memory leak detected!",[ + {key:"listeners",value:this.#interactionListeners.length.toString()} + ])) + } + } +} + +/**## ODSlashCommandBuilder `interface` + * The builder for slash commands. Here you can add options to the command. + */ +export interface ODSlashCommandBuilder extends discord.ChatInputApplicationCommandData {} + +/**## ODSlashCommandUpdateFunction `type` + * The function responsible for updating slash commands when they already exist. + */ +export type ODSlashCommandUpdateFunction = (current:ODSlashCommandBuilder) => boolean + +/**## ODSlashCommand `class` + * This is an open ticket slash command. + * + * When registered, you can listen for this command using the `ODCommandResponder`. The advantages of using this class for creating a slash command are: + * - automatic option parsing (even for channels, users, roles & mentions)! + * - automatic registration in discord.js + * - error reporting to the user when the bot fails to respond + * - plugins can extend this command + * - the bot won't re-register the command when it already exists (except when requested)! + * + * And more! + */ +export class ODSlashCommand extends ODManagerData { + /**The discord.js builder for this slash command. */ + builder: ODSlashCommandBuilder + /**The name of this slash command. */ + name: string + /**The id of the guild this command is for. Null when not set. */ + guildId: string|null + /**Function to check if the slash command requires to be updated (when it already exists). */ + requiresUpdate: ODSlashCommandUpdateFunction|null = null + + constructor(id:ODValidId, builder:ODSlashCommandBuilder, requiresUpdate?:ODSlashCommandUpdateFunction, guildId?:string){ + super(id) + if (builder.type != discord.ApplicationCommandType.ChatInput) throw new ODSystemError("ApplicationCommandData is required to be the 'ChatInput' type!") + + this.builder = builder + this.name = builder.name + this.guildId = guildId ?? null + this.requiresUpdate = requiresUpdate ?? null + } +} + +/**## ODTextCommandBuilderBaseOptionType `type` + * The types available in the text command option builder. + */ +export type ODTextCommandBuilderBaseOptionType = "string"|"number"|"boolean"|"user"|"guildmember"|"role"|"mentionable"|"channel" + +/**## ODTextCommandBuilderBaseOption `interface` + * The default option builder for text commands. + */ +export interface ODTextCommandBuilderBaseOption { + /**The name of this option */ + name:string, + /**The type of this option */ + type:ODTextCommandBuilderBaseOptionType, + /**Is this option required? (optional options can only exist at the end of the command!) */ + required?:boolean +} + +/**## ODTextCommandBuilderStringOption `interface` + * The string option builder for text commands. + */ +export interface ODTextCommandBuilderStringOption extends ODTextCommandBuilderBaseOption { + type:"string", + /**Set the maximum length of this string */ + maxLength?:number, + /**Set the minimum length of this string */ + minLength?:number, + /**The string needs to match this regex or it will be invalid */ + regex?:RegExp, + /**The string needs to match one of these choices or it will be invalid */ + choices?:string[], + /**When this is the last option, allow this string to contain spaces */ + allowSpaces?:boolean +} + +/**## ODTextCommandBuilderNumberOption `interface` + * The number option builder for text commands. + */ +export interface ODTextCommandBuilderNumberOption extends ODTextCommandBuilderBaseOption { + type:"number", + /**The number can't be higher than this value */ + max?:number, + /**The number can't be lower than this value */ + min?:number, + /**Allow the number to be negative */ + allowNegative?:boolean, + /**Allow the number to be positive */ + allowPositive?:boolean, + /**Allow the number to be zero */ + allowZero?:boolean, + /**Allow a number with decimal */ + allowDecimal?:boolean +} + +/**## ODTextCommandBuilderBooleanOption `interface` + * The boolean option builder for text commands. + */ +export interface ODTextCommandBuilderBooleanOption extends ODTextCommandBuilderBaseOption { + type:"boolean", + /**The value when `true` */ + trueValue?:string, + /**The value when `false` */ + falseValue?:string +} + +/**## ODTextCommandBuilderChannelOption `interface` + * The channel option builder for text commands. + */ +export interface ODTextCommandBuilderChannelOption extends ODTextCommandBuilderBaseOption { + type:"channel", + /**When specified, only allow the following channel types */ + channelTypes?:discord.GuildChannelType[] +} + +/**## ODTextCommandBuilderRoleOption `interface` + * The role option builder for text commands. + */ +export interface ODTextCommandBuilderRoleOption extends ODTextCommandBuilderBaseOption { + type:"role" +} + +/**## ODTextCommandBuilderUserOption `interface` + * The user option builder for text commands. + */ +export interface ODTextCommandBuilderUserOption extends ODTextCommandBuilderBaseOption { + type:"user" +} + +/**## ODTextCommandBuilderGuildMemberOption `interface` + * The guild member option builder for text commands. + */ +export interface ODTextCommandBuilderGuildMemberOption extends ODTextCommandBuilderBaseOption { + type:"guildmember" +} + +/**## ODTextCommandBuilderMentionableOption `interface` + * The mentionable option builder for text commands. + */ +export interface ODTextCommandBuilderMentionableOption extends ODTextCommandBuilderBaseOption { + type:"mentionable" +} + +/**## ODTextCommandBuilderOption `type` + * The option builder for text commands. + */ +export type ODTextCommandBuilderOption = ( + ODTextCommandBuilderStringOption| + ODTextCommandBuilderBooleanOption| + ODTextCommandBuilderNumberOption| + ODTextCommandBuilderChannelOption| + ODTextCommandBuilderRoleOption| + ODTextCommandBuilderUserOption| + ODTextCommandBuilderGuildMemberOption| + ODTextCommandBuilderMentionableOption +) + +/**## ODTextCommandBuilder `interface` + * The builder for text commands. Here you can add options to the command. + */ +export interface ODTextCommandBuilder { + /**The prefix of this command */ + prefix:string, + /**The name of this command (can include spaces for subcommands) */ + name:string, + /**Is this command allowed in dm? */ + dmPermission?:boolean, + /**Is this command allowed in guilds? */ + guildPermission?:boolean, + /**When specified, only allow this command to be executed in the following guilds */ + allowedGuildIds?:string[], + /**Are bots allowed to execute this command? */ + allowBots?:boolean + /**The options for this text command (like slash commands) */ + options?:ODTextCommandBuilderOption[] +} + +/**## ODTextCommand `class` + * This is an open ticket text command. + * + * When registered, you can listen for this command using the `ODCommandResponder`. The advantages of using this class for creating a text command are: + * - automatic option parsing (even for channels, users, roles & mentions)! + * - automatic errors on invalid parameters + * - error reporting to the user when the bot fails to respond + * - plugins can extend this command + * + * And more! + */ +export class ODTextCommand extends ODManagerData { + /**The builder for this slash command. */ + builder: ODTextCommandBuilder + /**The name of this slash command. */ + name: string + + constructor(id:ODValidId, builder:ODTextCommandBuilder){ + super(id) + this.builder = builder + this.name = builder.name + } +} + +/**## ODTextCommandInteractionOptionBase `interface` + * The object returned for options from a text command interaction. + */ +export interface ODTextCommandInteractionOptionBase { + /**The name of this option */ + name:string, + /**The type of this option */ + type:Name, + /**The value of this option */ + value:Type +} + +/**## ODTextCommandInteractionOption `type` + * A list of types returned for options from a text command interaction. + */ +export type ODTextCommandInteractionOption = ( + ODTextCommandInteractionOptionBase<"string",string>| + ODTextCommandInteractionOptionBase<"number",number>| + ODTextCommandInteractionOptionBase<"boolean",boolean>| + ODTextCommandInteractionOptionBase<"channel",discord.GuildBasedChannel>| + ODTextCommandInteractionOptionBase<"role",discord.Role>| + ODTextCommandInteractionOptionBase<"user",discord.User>| + ODTextCommandInteractionOptionBase<"guildmember",discord.GuildMember>| + ODTextCommandInteractionOptionBase<"mentionable",discord.Role|discord.User> +) + +/**## ODTextCommandInteractionCallback `type` + * Callback for the text command interaction listener. + */ +export type ODTextCommandInteractionCallback = (msg:discord.Message, cmd:ODTextCommand, options:ODTextCommandInteractionOption[]) => void + +/**## ODTextCommandErrorBase `interface` + * The object returned from a text command error callback. + */ +export interface ODTextCommandErrorBase { + /**The type of text command error */ + type:"unknown_prefix"|"unknown_command"|"invalid_option"|"missing_option", + /**The message this error originates from */ + msg:discord.Message +} + +/**## ODTextCommandErrorUnknownPrefix `interface` + * The object returned from a text command unknown prefix error callback. + */ +export interface ODTextCommandErrorUnknownPrefix extends ODTextCommandErrorBase { + type:"unknown_prefix" +} + +/**## ODTextCommandErrorUnknownCommand `interface` + * The object returned from a text command unknown command error callback. + */ +export interface ODTextCommandErrorUnknownCommand extends ODTextCommandErrorBase { + type:"unknown_command" +} + +/**## ODTextCommandErrorInvalidOptionReason `type` + * A list of reasons for the invalid_option error to be thrown. + */ +export type ODTextCommandErrorInvalidOptionReason = ( + "boolean"| + "number_max"| + "number_min"| + "number_decimal"| + "number_negative"| + "number_positive"| + "number_zero"| + "number_invalid"| + "string_max_length"| + "string_min_length"| + "string_regex"| + "string_choice"| + "not_in_guild"| + "channel_not_found"| + "channel_type"| + "user_not_found"| + "member_not_found"| + "role_not_found"| + "mentionable_not_found" +) + +/**## ODTextCommandErrorInvalidOption `interface` + * The object returned from a text command invalid option error callback. + */ +export interface ODTextCommandErrorInvalidOption extends ODTextCommandErrorBase { + type:"invalid_option", + /**The command this error originates from */ + command:ODTextCommand, + /**The command prefix this error originates from */ + prefix:string, + /**The command name this error originates from (can include spaces for subcommands) */ + name:string, + /**The option that this error originates from */ + option:ODTextCommandBuilderOption + /**The location that this option was found */ + location:number, + /**The current value of this invalid option */ + value:string, + /**The reason for this invalid option */ + reason:ODTextCommandErrorInvalidOptionReason +} + +/**## ODTextCommandErrorMissingOption `interface` + * The object returned from a text command missing option error callback. + */ +export interface ODTextCommandErrorMissingOption extends ODTextCommandErrorBase { + type:"missing_option", + /**The command this error originates from */ + command:ODTextCommand, + /**The command prefix this error originates from */ + prefix:string, + /**The command name this error originates from (can include spaces for subcommands) */ + name:string, + /**The option that this error originates from */ + option:ODTextCommandBuilderOption + /**The location that this option was found */ + location:number +} + +/**## ODTextCommandError `type` + * A list of types returned for errors from a text command interaction. + */ +export type ODTextCommandError = ( + ODTextCommandErrorUnknownPrefix| + ODTextCommandErrorUnknownCommand| + ODTextCommandErrorInvalidOption| + ODTextCommandErrorMissingOption +) + +/**## ODTextCommandErrorCallback `type` + * Callback for the text command error listener. + */ +export type ODTextCommandErrorCallback = (error:ODTextCommandError) => void + +/**## ODTextCommandManager `class` + * This is an open ticket client text manager. + * + * It's responsible for managing all the text commands from the client. + * + * Here, you can add & remove text commands & the bot will do the (de)registering. + */ +export class ODTextCommandManager extends ODManager { + /**Alias to open ticket debugger. */ + #debug: ODDebugger + /**Copy of discord.js client. */ + manager: ODClientManager + /**Collection of all interaction listeners. */ + #interactionListeners: {prefix:string, name:string|RegExp, callback:ODTextCommandInteractionCallback}[] = [] + /**Collection of all error listeners. */ + #errorListeners: ODTextCommandErrorCallback[] = [] + /**Set the soft limit for maximum amount of listeners. A warning will be shown when there are more listeners than this limit. */ + listenerLimit: number = 100 + + constructor(debug:ODDebugger, manager:ODClientManager){ + super(debug,"text command") + this.#debug = debug + this.manager = manager + } + + /*Check if a message is a registered command. */ + async #checkMessage(msg:discord.Message){ + if (this.manager.client.user && msg.author.id == this.manager.client.user.id) return false + + //filter commands for correct prefix + const validPrefixCommands: {cmd:ODTextCommand,newContent:string}[] = [] + this.getAll().forEach((cmd) => { + if (msg.content.startsWith(cmd.builder.prefix)) validPrefixCommands.push({ + cmd:cmd, + newContent:msg.content.substring(cmd.builder.prefix.length) + }) + }) + + //return when no command with prefix + if (validPrefixCommands.length == 0){ + this.#errorListeners.forEach((cb) => cb({ + type:"unknown_prefix", + msg:msg + })) + return false + } + + //filter commands for correct name + const validNameCommands: {cmd:ODTextCommand,newContent:string}[] = [] + validPrefixCommands.forEach((cmd) => { + if (cmd.newContent.startsWith(cmd.cmd.builder.name)) validNameCommands.push({ + cmd:cmd.cmd, + newContent:cmd.newContent.substring(cmd.cmd.builder.name.length+1) //+1 because of space after command name + }) + }) + + //return when no command with name + if (validNameCommands.length == 0){ + this.#errorListeners.forEach((cb) => cb({ + type:"unknown_command", + msg:msg + })) + return false + } + + //the final command + const command = validNameCommands[0] + const builder = command.cmd.builder + + //check additional options + if (typeof builder.allowBots != "undefined" && !builder.allowBots && msg.author.bot) return false + else if (typeof builder.dmPermission != "undefined" && !builder.dmPermission && msg.channel.type == discord.ChannelType.DM) return false + else if (typeof builder.guildPermission != "undefined" && !builder.guildPermission && msg.guild) return false + else if (typeof builder.allowedGuildIds != "undefined" && msg.guild && !builder.allowedGuildIds.includes(msg.guild.id)) return false + + //check all command options & return when incorrect + const options = await this.#checkOptions(command.cmd,command.newContent,msg) + if (!options.valid) return false + + //a command matched this message => emit event + this.#interactionListeners.forEach((listener) => { + if (typeof listener.prefix == "string" && (command.cmd.builder.prefix != listener.prefix)) return + if (typeof listener.name == "string" && (command.cmd.name.split(" ")[0] != listener.name)) return + else if (listener.name instanceof RegExp && !listener.name.test(command.cmd.name.split(" ")[0])) return + + //this is a valid listener + listener.callback(msg,command.cmd,options.data) + }) + return true + } + /**Check if all options of a command are correct. */ + async #checkOptions(cmd:ODTextCommand, newContent:string, msg:discord.Message){ + const options = cmd.builder.options + if (!options) return {valid:true,data:[]} + + let tempContent = newContent + let optionInvalid = false + const optionData: ODTextCommandInteractionOption[] = [] + + const optionError = (type:"invalid_option"|"missing_option", option:ODTextCommandBuilderOption, location:number, value?:string, reason?:ODTextCommandErrorInvalidOptionReason) => { + //ERROR INVALID + if (type == "invalid_option" && value && reason){ + this.#errorListeners.forEach((cb) => cb({ + type:"invalid_option", + msg:msg, + prefix:cmd.builder.prefix, + command:cmd, + name:cmd.builder.name, + option, + location, + value, + reason + })) + }else if (type == "missing_option"){ + this.#errorListeners.forEach((cb) => cb({ + type:"missing_option", + msg:msg, + prefix:cmd.builder.prefix, + command:cmd, + name:cmd.builder.name, + option, + location + })) + } + optionInvalid = true + } + + for (let location = 0;location < options.length;location++){ + const option = options[location] + if (optionInvalid) break + + //CHECK BOOLEAN + if (option.type == "boolean"){ + const falseValue = option.falseValue ?? "false" + const trueValue = option.trueValue ?? "true" + + if (tempContent.startsWith(falseValue+" ")){ + //FALSE VALUE + optionData.push({ + name:option.name, + type:"boolean", + value:false + }) + tempContent = tempContent.substring(falseValue.length+1) + + }else if (tempContent.startsWith(trueValue+" ")){ + //TRUE VALUE + optionData.push({ + name:option.name, + type:"boolean", + value:true + }) + tempContent = tempContent.substring(trueValue.length+1) + + }else if (option.required){ + //REQUIRED => ERROR IF NOD EXISTING + const invalidregex = /^[^ ]+/ + const invalidRes = invalidregex.exec(tempContent) + if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"boolean") + else optionError("missing_option",option,location) + } + + //CHECK NUMBER + }else if (option.type == "number"){ + const numRegex = /^[0-9\.\,]+/ + const res = numRegex.exec(tempContent) + if (res){ + const value = res[0].replace(/\,/g,".") + tempContent = tempContent.substring(value.length+1) + const numValue = Number(value) + + if (isNaN(numValue)){ + optionError("invalid_option",option,location,value,"number_invalid") + + }else if (typeof option.allowDecimal == "boolean" && !option.allowDecimal && (numValue % 1) !== 0){ + optionError("invalid_option",option,location,value,"number_decimal") + + }else if (typeof option.allowNegative == "boolean" && !option.allowNegative && numValue < 0){ + optionError("invalid_option",option,location,value,"number_negative") + + }else if (typeof option.allowPositive == "boolean" && !option.allowPositive && numValue > 0){ + optionError("invalid_option",option,location,value,"number_positive") + + }else if (typeof option.allowZero == "boolean" && !option.allowZero && numValue == 0){ + optionError("invalid_option",option,location,value,"number_zero") + + }else if (typeof option.max == "number" && numValue > option.max){ + optionError("invalid_option",option,location,value,"number_max") + + }else if (typeof option.min == "number" && numValue < option.min){ + optionError("invalid_option",option,location,value,"number_min") + + }else{ + //VALID NUMBER + optionData.push({ + name:option.name, + type:"number", + value:numValue + }) + } + }else if (option.required){ + //REQUIRED => ERROR IF NOD EXISTING + const invalidRegex = /^[^ ]+/ + const invalidRes = invalidRegex.exec(tempContent) + if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"number_invalid") + else optionError("missing_option",option,location) + } + //CHECK STRING + }else if (option.type == "string"){ + if (option.allowSpaces){ + //STRING WITH SPACES + const value = tempContent + tempContent = "" + + if (typeof option.minLength == "number" && value.length < option.minLength){ + optionError("invalid_option",option,location,value,"string_min_length") + + }else if (typeof option.maxLength == "number" && value.length > option.maxLength){ + optionError("invalid_option",option,location,value,"string_max_length") + + }else if (option.regex && !option.regex.test(value)){ + optionError("invalid_option",option,location,value,"string_regex") + + }else if (option.choices && !option.choices.includes(value)){ + optionError("invalid_option",option,location,value,"string_choice") + + }else if (option.required && value === ""){ + //REQUIRED => ERROR IF NOD EXISTING + optionError("missing_option",option,location) + + }else{ + //VALID STRING + optionData.push({ + name:option.name, + type:"string", + value + }) + } + }else{ + //STRING WITHOUT SPACES + const stringRegex = /^[^ ]+/ + const res = stringRegex.exec(tempContent) + if (res){ + const value = res[0] + tempContent = tempContent.substring(value.length+1) + + if (typeof option.minLength == "number" && value.length < option.minLength){ + optionError("invalid_option",option,location,value,"string_min_length") + + }else if (typeof option.maxLength == "number" && value.length > option.maxLength){ + optionError("invalid_option",option,location,value,"string_max_length") + + }else if (option.regex && !option.regex.test(value)){ + optionError("invalid_option",option,location,value,"string_regex") + + }else if (option.choices && !option.choices.includes(value)){ + optionError("invalid_option",option,location,value,"string_choice") + + }else{ + //VALID STRING + optionData.push({ + name:option.name, + type:"string", + value + }) + } + }else if (option.required){ + //REQUIRED => ERROR IF NOD EXISTING + optionError("missing_option",option,location) + } + } + //CHECK CHANNEL + }else if (option.type == "channel"){ + const channelRegex = /^(?:<#)?([0-9]+)>?/ + const res = channelRegex.exec(tempContent) + if (res){ + const value = res[0] + tempContent = tempContent.substring(value.length+1) + const channelId = res[1] + + if (!msg.guild){ + optionError("invalid_option",option,location,value,"not_in_guild") + }else{ + try{ + const channel = await msg.guild.channels.fetch(channelId) + if (!channel){ + optionError("invalid_option",option,location,value,"channel_not_found") + + }else if (option.channelTypes && !option.channelTypes.includes(channel.type)){ + optionError("invalid_option",option,location,value,"channel_type") + + }else{ + //VALID CHANNEL + optionData.push({ + name:option.name, + type:"channel", + value:channel + }) + } + }catch{ + optionError("invalid_option",option,location,value,"channel_not_found") + } + } + }else if (option.required){ + //REQUIRED => ERROR IF NOD EXISTING + const invalidRegex = /^[^ ]+/ + const invalidRes = invalidRegex.exec(tempContent) + if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"channel_not_found") + else optionError("missing_option",option,location) + } + //CHECK ROLE + }else if (option.type == "role"){ + const roleRegex = /^(?:<@&)?([0-9]+)>?/ + const res = roleRegex.exec(tempContent) + if (res){ + const value = res[0] + tempContent = tempContent.substring(value.length+1) + const roleId = res[1] + + if (!msg.guild){ + optionError("invalid_option",option,location,value,"not_in_guild") + }else{ + try{ + const role = await msg.guild.roles.fetch(roleId) + if (!role){ + optionError("invalid_option",option,location,value,"role_not_found") + }else{ + //VALID ROLE + optionData.push({ + name:option.name, + type:"role", + value:role + }) + } + }catch{ + optionError("invalid_option",option,location,value,"role_not_found") + } + } + }else if (option.required){ + //REQUIRED => ERROR IF NOD EXISTING + const invalidRegex = /^[^ ]+/ + const invalidRes = invalidRegex.exec(tempContent) + if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"role_not_found") + else optionError("missing_option",option,location) + } + //CHECK GUILD MEMBER + }else if (option.type == "guildmember"){ + const memberRegex = /^(?:<@)?([0-9]+)>?/ + const res = memberRegex.exec(tempContent) + if (res){ + const value = res[0] + tempContent = tempContent.substring(value.length+1) + const memberId = res[1] + + if (!msg.guild){ + optionError("invalid_option",option,location,value,"not_in_guild") + }else{ + try{ + const member = await msg.guild.members.fetch(memberId) + if (!member){ + optionError("invalid_option",option,location,value,"member_not_found") + }else{ + //VALID GUILD MEMBER + optionData.push({ + name:option.name, + type:"guildmember", + value:member + }) + } + }catch{ + optionError("invalid_option",option,location,value,"member_not_found") + } + } + }else if (option.required){ + //REQUIRED => ERROR IF NOD EXISTING + const invalidRegex = /^[^ ]+/ + const invalidRes = invalidRegex.exec(tempContent) + if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"member_not_found") + else optionError("missing_option",option,location) + } + //CHECK USER + }else if (option.type == "user"){ + const userRegex = /^(?:<@)?([0-9]+)>?/ + const res = userRegex.exec(tempContent) + if (res){ + const value = res[0] + tempContent = tempContent.substring(value.length+1) + const userId = res[1] + + try{ + const user = await this.manager.client.users.fetch(userId) + if (!user){ + optionError("invalid_option",option,location,value,"user_not_found") + }else{ + //VALID USER + optionData.push({ + name:option.name, + type:"user", + value:user + }) + } + }catch{ + optionError("invalid_option",option,location,value,"user_not_found") + } + }else if (option.required){ + //REQUIRED => ERROR IF NOD EXISTING + const invalidRegex = /^[^ ]+/ + const invalidRes = invalidRegex.exec(tempContent) + if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"user_not_found") + else optionError("missing_option",option,location) + } + //CHECK MENTIONABLE + }else if (option.type == "mentionable"){ + const mentionableRegex = /^<(@&?)([0-9]+)>/ + const res = mentionableRegex.exec(tempContent) + if (res){ + const value = res[0] + const type = (res[1] == "@&") ? "role" : "user" + tempContent = tempContent.substring(value.length+1) + const mentionableId = res[2] + + if (!msg.guild){ + optionError("invalid_option",option,location,value,"not_in_guild") + }else if (type == "role"){ + try { + const role = await msg.guild.roles.fetch(mentionableId) + if (!role){ + optionError("invalid_option",option,location,value,"mentionable_not_found") + }else{ + //VALID ROLE + optionData.push({ + name:option.name, + type:"mentionable", + value:role + }) + } + }catch{ + optionError("invalid_option",option,location,value,"mentionable_not_found") + } + }else if (type == "user"){ + try{ + const user = await this.manager.client.users.fetch(mentionableId) + if (!user){ + optionError("invalid_option",option,location,value,"mentionable_not_found") + }else{ + //VALID USER + optionData.push({ + name:option.name, + type:"mentionable", + value:user + }) + } + }catch{ + optionError("invalid_option",option,location,value,"mentionable_not_found") + } + } + }else if (option.required){ + //REQUIRED => ERROR IF NOD EXISTING + const invalidRegex = /^[^ ]+/ + const invalidRes = invalidRegex.exec(tempContent) + if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"mentionable_not_found") + else optionError("missing_option",option,location) + } + } + } + return {valid:!optionInvalid,data:optionData} + } + /**Start listening to the discord.js client `messageCreate` event. */ + startListeningToInteractions(){ + this.manager.client.on("messageCreate",(msg) => { + //return when not in main server or DM + if (!this.manager.mainServer || (msg.guild && msg.guild.id != this.manager.mainServer.id)) return + this.#checkMessage(msg) + }) + } + /**Check if optional values are only present at the end of the command. */ + #checkBuilderOptions(builder:ODTextCommandBuilder): {valid:boolean,reason:"required_after_optional"|"allowspaces_not_last"|null} { + let optionalVisited = false + let valid = true + let reason: "required_after_optional"|"allowspaces_not_last"|null = null + if (!builder.options) return {valid:true,reason:null} + builder.options.forEach((opt,index,list) => { + if (!opt.required) optionalVisited = true + if (optionalVisited && opt.required){ + valid = false + reason = "required_after_optional" + } + + if (opt.type == "string" && opt.allowSpaces && ((index+1) != list.length)){ + valid = false + reason = "allowspaces_not_last" + } + }) + + return {valid,reason} + } + /**Callback on interaction from one of the registered text commands */ + onInteraction(commandPrefix:string,commandName:string|RegExp, callback:ODTextCommandInteractionCallback){ + this.#interactionListeners.push({ + prefix:commandPrefix, + name:commandName, + callback + }) + + if (this.#interactionListeners.length > this.listenerLimit){ + this.#debug.console.log(new ODConsoleWarningMessage("Possible text command interaction memory leak detected!",[ + {key:"listeners",value:this.#interactionListeners.length.toString()} + ])) + } + } + /**Callback on error from all the registered text commands */ + onError(callback:ODTextCommandErrorCallback){ + this.#errorListeners.push(callback) + } + + add(data:ODTextCommand, overwrite?:boolean): boolean { + const checkResult = this.#checkBuilderOptions(data.builder) + if (!checkResult.valid && checkResult.reason == "required_after_optional") throw new ODSystemError("Invalid text command '"+data.id.value+"' => optional options are only allowed at the end of a command!") + else if (!checkResult.valid && checkResult.reason == "allowspaces_not_last") throw new ODSystemError("Invalid text command '"+data.id.value+"' => string option with 'allowSpaces' is only allowed at the end of a command!") + else return super.add(data,overwrite) + } +} \ No newline at end of file diff --git a/src/core/api/modules/code.ts b/src/core/api/modules/code.ts new file mode 100644 index 0000000..08cb395 --- /dev/null +++ b/src/core/api/modules/code.ts @@ -0,0 +1,55 @@ +/////////////////////////////////////// +//CODE MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODValidId } from "./base" +import { ODDebugger } from "./console" + + +/**## ODCode `class` + * This is an open ticket code runner. + * + * It is just a function that will run just before the bot has started completely! + * This can be used for code that needs to run at startup, but isn't really time dependent. + * + * - It has an `id` for identification of the function + * - A `priority` to know when to execute this function (related to others) + */ +export class ODCode extends ODManagerData { + /**The priority of this code */ + priority: number + /**The main function of this code */ + func: () => void|Promise + + constructor(id:ODValidId, priority:number, func:() => void|Promise){ + super(id) + this.priority = priority + this.func = func + } +} + +/**## ODCodeManager `class` + * This is an open ticket code manager. + * + * It manages & executes `ODCode`'s in the correct order. + * + * You will probably register a function/code in this class for something that doesn't really need to be timed. + */ +export class ODCodeManager extends ODManager { + constructor(debug:ODDebugger){ + super(debug,"code") + } + + /**Execute all functions or code. */ + async execute(){ + const derefArray = [...this.getAll()] + const workers = derefArray.sort((a,b) => b.priority-a.priority) + + for (const worker of workers){ + try { + await worker.func() + }catch(err){ + process.emit("uncaughtException",err) + } + } + } +} \ No newline at end of file diff --git a/src/core/api/modules/config.ts b/src/core/api/modules/config.ts new file mode 100644 index 0000000..95edbb2 --- /dev/null +++ b/src/core/api/modules/config.ts @@ -0,0 +1,96 @@ +/////////////////////////////////////// +//CONFIG MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base" +import nodepath from "path" +import { ODDebugger } from "./console" + +/**## ODConfigManager `class` + * This is an open ticket config manager. + * + * It manages all config files in the bot and allows plugins to access config files from open ticket & other plugins! + * + * You will use this class to get/add a config file (`ODConfig`) in your plugin! + * @example + * //get ./config/general.json => ODConfig class + * const generalConfig = openticket.configs.get("openticket:general") + * + * //add a new config with id "test" => ./config/test.json + * const testConfig = new api.ODConfig("test","test.json") + * openticket.configs.add(testConfig) + */ +export class ODConfigManager extends ODManager { + constructor(debug:ODDebugger){ + super(debug,"config") + } + + /**Add data to the manager. The id will be fetched from the data class! You can optionally select to overwrite existing data! + * @example + * //add a new config with id "test" => ./config/test.json + * const testConfig = new api.ODConfig("test","test.json") + * openticket.configs.add(testConfig) + */ + add(data:ODConfig, overwrite?:boolean): boolean { + return super.add(data,overwrite) + } + /**Get data that matches the `ODId`. Returns the found data. + * @example + * //get "./config/general.json" (ot-general) => ODConfig class + * const generalConfig = openticket.configs.get("openticket:general") + */ + get(id:ODValidId): ODConfig|null { + return super.get(id) + } + /**Remove data that matches the `ODId`. Returns the removed data. + * @example + * //remove the "test" config + * openticket.configs.remove("test") //returns null if non-existing + */ + remove(id:ODValidId): ODConfig|null { + return super.remove(id) + } + /**Check if data that matches the `ODId` exists. Returns a boolean. + * @example + * //check if "./config/general.json" (ot-general) exists => boolean + * const exists = openticket.configs.exists("openticket:general") + */ + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODConfig `class` + * This is an open ticket config helper. + * This class doesn't do anything at all, it just gives a template & basic methods for a config. Use `ODJsonConfig` instead! + * + * You will only use this class if you want to create your own config implementation (e.g. `yml`, `xml`,...)! + */ +export class ODConfig extends ODManagerData { + /**The full path to this config with extension */ + file: string = "" + /**An object/array of the entire config file! Variables inside it can be edited while the bot is running! */ + data: any = undefined +} + +/**## ODJsonConfig `class` + * This is an open ticket config helper. + * You will use this class to get & edit variables from the config files or to create your own config! + * @example + * //create a config from: ./config/test.json with the id "some-config" + * const config = new api.ODJsonConfig("some-config","test.json") + * + * //create a config with custom dir: ./plugins/testplugin/test.json + * const config = new api.ODJsonConfig("plugin-config","test.json","./plugins/testplugin/") + */ +export class ODJsonConfig extends ODConfig { + constructor(id:ODValidId, file:string, customPath?:string){ + super(id) + try { + const filename = (file.endsWith(".json")) ? file : file+".json" + this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./config/",filename) + this.data = customPath ? require(nodepath.join("../../../../",customPath,filename)) : require(nodepath.join("../../../../config",filename)) + }catch{ + throw new ODSystemError("config \""+nodepath.join("./",customPath ?? "",file)+"\" doesn't exist!") + } + } +} \ No newline at end of file diff --git a/src/core/api/modules/console.ts b/src/core/api/modules/console.ts new file mode 100644 index 0000000..6c1afc3 --- /dev/null +++ b/src/core/api/modules/console.ts @@ -0,0 +1,663 @@ +/////////////////////////////////////// +//CONSOLE MODULE +/////////////////////////////////////// +import { ODHTTPGetRequest, ODVersion, ODSystemError, ODPluginError, ODManager, ODManagerData, ODValidId } from "./base" +import { ODMain } from "../main" +import nodepath from "path" +import fs from "fs" +import ansis from "ansis" + +/**## ODValidConsoleColor `type` + * This is a collection of all the supported console colors within Open Ticket. + */ +export type ODValidConsoleColor = "white"|"red"|"yellow"|"green"|"blue"|"gray"|"cyan"|"magenta" + +/**## ODConsoleMessageParam `type` + * This interface contains all data required for a console log parameter within Open Ticket. + */ +export interface ODConsoleMessageParam { + /**The key of this parameter. */ + key:string, + /**The value of this parameter. */ + value:string, + /**When enabled, this parameter will only be shown in the debug file. */ + hidden?:boolean +} + +/**## ODConsoleMessage `class` + * This is an open ticket console message. + * + * It is used to create beautiful & styled logs in the console with a prefix, message & parameters. + * It also has full color support using `ansis` and parameters are parsed for you! + */ +export class ODConsoleMessage { + /**The main message sent in the console */ + message: string + /**An array of all the parameters in this message */ + params: ODConsoleMessageParam[] + /**The prefix of this message (!uppercase recommended!) */ + prefix: string + /**The color of the prefix of this message */ + color: ODValidConsoleColor + + constructor(message:string, prefix:string, color:ODValidConsoleColor, params?:ODConsoleMessageParam[]){ + this.message = message + this.params = params ? params : [] + this.prefix = prefix + + if (["white","red","yellow","green","blue","gray","cyan","magenta"].includes(color)){ + this.color = color + }else{ + this.color = "white" + } + } + /**Render this message to the console using `console.log`! Returns `false` when something went wrong. */ + render(){ + try { + const prefixcolor = ansis[this.color] + + const paramsstring = " "+this.createParamsString("gray") + const message = prefixcolor("["+this.prefix+"] ")+this.message + + console.log(message+paramsstring) + return true + }catch{ + return false + } + } + /**Create a more-detailed, non-colored version of this message to store it in the `otdebug.txt` file! */ + toDebugString(){ + const pstrings: string[] = [] + this.params.forEach((p) => { + pstrings.push(p.key+": "+p.value) + }) + const pstring = (pstrings.length > 0) ? " ("+pstrings.join(", ")+")" : "" + const date = new Date() + const dstring = `${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}` + return `[${dstring} ${this.prefix}] ${this.message}${pstring}` + } + /**Render the parameters of this message in a specific color. */ + createParamsString(color:ODValidConsoleColor){ + let validcolor: ODValidConsoleColor = "white" + if (["white","red","yellow","green","blue","gray","cyan","magenta"].includes(color)){ + validcolor = color + } + + const pstrings: string[] = [] + this.params.forEach((p) => { + if (!p.hidden) pstrings.push(p.key+": "+p.value) + }) + + return (pstrings.length > 0) ? ansis[validcolor](" ("+pstrings.join(", ")+")") : "" + } + /**Set the message */ + setMessage(message:string){ + this.message = message + return this + } + /**Set the params */ + setParams(params:ODConsoleMessageParam[]){ + this.params = params + return this + } + /**Set the prefix */ + setPrefix(prefix:string){ + this.prefix = prefix + return this + } + /**Set the prefix color */ + setColor(color:ODValidConsoleColor){ + if (["white","red","yellow","green","blue","gray","cyan","magenta"].includes(color)){ + this.color = color + }else{ + this.color = "white" + } + return this + } +} + +/**## ODConsoleInfoMessage `class` + * This is an open ticket console info message. + * + * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "INFO" messages! + */ +export class ODConsoleInfoMessage extends ODConsoleMessage { + constructor(message:string,params?:ODConsoleMessageParam[]){ + super(message,"INFO","blue",params) + } +} + +/**## ODConsoleSystemMessage `class` + * This is an open ticket console system message. + * + * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "SYSTEM" messages! + */ +export class ODConsoleSystemMessage extends ODConsoleMessage { + constructor(message:string,params?:ODConsoleMessageParam[]){ + super(message,"SYSTEM","green",params) + } +} + +/**## ODConsolePluginMessage `class` + * This is an open ticket console plugin message. + * + * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "PLUGIN" messages! + */ +export class ODConsolePluginMessage extends ODConsoleMessage { + constructor(message:string,params?:ODConsoleMessageParam[]){ + super(message,"PLUGIN","magenta",params) + } +} + +/**## ODConsoleDebugMessage `class` + * This is an open ticket console debug message. + * + * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "DEBUG" messages! + */ +export class ODConsoleDebugMessage extends ODConsoleMessage { + constructor(message:string,params?:ODConsoleMessageParam[]){ + super(message,"DEBUG","cyan",params) + } +} + +/**## ODConsoleWarningMessage `class` + * This is an open ticket console warning message. + * + * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "WARNING" messages! + */ +export class ODConsoleWarningMessage extends ODConsoleMessage { + constructor(message:string,params?:ODConsoleMessageParam[]){ + super(message,"WARNING","yellow",params) + } +} + +/**## ODConsoleErrorMessage `class` + * This is an open ticket console error message. + * + * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "ERROR" messages! + */ +export class ODConsoleErrorMessage extends ODConsoleMessage { + constructor(message:string,params?:ODConsoleMessageParam[]){ + super(message,"ERROR","red",params) + } +} + +/**## ODError `class` + * This is an open ticket error. + * + * It is used to render and log Node.js errors & crashes in a styled way to the console & `otdebug.txt` file! + */ +export class ODError { + /**The original error that this class wraps around */ + error: Error|ODSystemError|ODPluginError + /**The origin of the original error */ + origin: NodeJS.UncaughtExceptionOrigin + + constructor(error:Error|ODSystemError|ODPluginError, origin:NodeJS.UncaughtExceptionOrigin){ + this.error = error + this.origin = origin + } + + /**Render this error to the console using `console.log`! Returns `false` when something went wrong. */ + render(){ + try { + let prefix = (this.error["_ODErrorType"] == "plugin") ? "PLUGIN ERROR" : ((this.error["_ODErrorType"] == "system") ? "OPENTICKET ERROR" : "UNKNOWN ERROR") + //title + console.log(ansis.red("["+prefix+"]: ")+this.error.message+" | origin: "+this.origin) + //stack trace + if (this.error.stack) console.log(ansis.gray(this.error.stack)) + //additional message + if (this.error["_ODErrorType"] == "plugin") console.log(ansis.red.bold("\nPlease report this error to the plugin developer and help us create a more stable plugin!")) + else console.log(ansis.red.bold("\nPlease report this error to our discord server and help us create a more stable ticket bot!")) + console.log(ansis.red("Also send the "+ansis.cyan.bold("otdebug.txt")+" file! It would help a lot!\n")) + return true + }catch{ + return false + } + } + /**Create a more-detailed, non-colored version of this error to store it in the `otdebug.txt` file! */ + toDebugString(){ + return "[UNKNOWN OD ERROR]: "+this.error.message+" | origin: "+this.origin+"\n"+this.error.stack + } +} + +/**## ODConsoleMessageTypes `type` + * This is a collection of all the default console message types within Open Ticket. + */ +export type ODConsoleMessageTypes = "info"|"system"|"plugin"|"debug"|"warning"|"error" + +/**## ODConsoleManager `class` + * This is the open ticket console manager. + * + * It handles the entire console system of Open Ticket. It's also the place where you need to log `ODConsoleMessage`'s. + * This manager keeps a short history of messages sent to the console which is configurable by plugins. + * + * The debug file (`otdebug.txt`) is handled in a sub-manager! + */ +export class ODConsoleManager { + /**The history of `ODConsoleMessage`'s and `ODError`'s since startup */ + history: (ODConsoleMessage|ODError)[] = [] + /**The max length of the history. The oldest messages will be removed when over the limit */ + historylength = 100 + /**An alias to the debugfile manager. (`otdebug.txt`) */ + debugfile: ODDebugFileManager + + constructor(historylength:number, debugfile:ODDebugFileManager){ + this.historylength = historylength + this.debugfile = debugfile + } + + /**Log a message to the console ... But in the Open Ticket way :) */ + log(message:ODConsoleMessage): void + log(message:ODError): void + log(message:string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]): void + log(message:ODConsoleMessage|ODError|string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]){ + if (message instanceof ODConsoleMessage){ + message.render() + if (this.debugfile) this.debugfile.writeConsoleMessage(message) + this.history.push(message) + + }else if (message instanceof ODError){ + message.render() + if (this.debugfile) this.debugfile.writeErrorMessage(message) + this.history.push(message) + + }else if (["string","number","boolean","object"].includes(typeof message)){ + let newMessage: ODConsoleMessage + if (type == "info") newMessage = new ODConsoleInfoMessage(message,params) + else if (type == "system") newMessage = new ODConsoleSystemMessage(message,params) + else if (type == "plugin") newMessage = new ODConsolePluginMessage(message,params) + else if (type == "debug") newMessage = new ODConsoleDebugMessage(message,params) + else if (type == "warning") newMessage = new ODConsoleWarningMessage(message,params) + else if (type == "error") newMessage = new ODConsoleErrorMessage(message,params) + else newMessage = new ODConsoleSystemMessage(message,params) + + newMessage.render() + if (this.debugfile) this.debugfile.writeConsoleMessage(newMessage) + this.history.push(newMessage) + } + this.#purgeHistory() + } + /**Shorten the history when it exceeds the max history length! */ + #purgeHistory(){ + if (this.history.length > this.historylength) this.history.shift() + } +} + +/**## ODDebugFileManager `class` + * This is the open ticket debug file manager. + * + * It manages the Open Ticket debug file (`otdebug.txt`) which keeps a history of all system logs. + * There are even internal logs that aren't logged to the console which are available in this file! + * + * Using this class, you can change the max length of this file and some other cool things! + */ +export class ODDebugFileManager { + /**The path to the debugfile (`./otdebug.txt` by default) */ + path: string + /**The filename of the debugfile (`otdebug.txt` by default) */ + filename: string + /**The current version of the bot used in the debug file. */ + version: ODVersion + /**The max length of the debug file. */ + maxlines: number + + constructor(path:string, filename:string, maxlines:number, version:ODVersion){ + this.path = nodepath.join(path,filename) + this.filename = filename + this.version = version + this.maxlines = maxlines + + this.#writeStartupStats() + } + + /**Check if the debug file exists */ + #existsDebugFile(){ + return fs.existsSync(this.path) + } + /**Read from the debug file */ + #readDebugFile(){ + if (this.#existsDebugFile()){ + try { + return fs.readFileSync(this.path).toString() + }catch{ + return false + } + }else{ + return false + } + } + /**Write to the debug file and shorten it when needed. */ + #writeDebugFile(text:string){ + const currenttext = this.#readDebugFile() + if (currenttext){ + const splitted = currenttext.split("\n") + + if (splitted.length+text.split("\n").length > this.maxlines){ + splitted.splice(7,(text.split("\n").length)) + } + + splitted.push(text) + fs.writeFileSync(this.path,splitted.join("\n")) + }else{ + //write new file: + const newtext = this.#createStatsText()+text + fs.writeFileSync(this.path,newtext) + } + } + /**Generate the stats/header of the debug file (containing the version) */ + #createStatsText(){ + const date = new Date() + const dstring = `${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}` + return [ + "=========================", + "OPEN TICKET DEBUG FILE:", + "version: "+this.version.toString(), + "last startup: "+dstring, + "=========================\n\n" + ].join("\n") + } + /**Write the stats/header to the debug file on startup */ + #writeStartupStats(){ + const currenttext = this.#readDebugFile() + if (currenttext){ + //edit previous file: + const splitted = currenttext.split("\n") + splitted.splice(0,7) + + if (splitted.length+11 > this.maxlines){ + splitted.splice(0,((splitted.length+11) - this.maxlines)) + } + + splitted.unshift(this.#createStatsText()) + splitted.push("\n---------------------------------------------------------------------\n---------------------------------------------------------------------\n") + + fs.writeFileSync(this.path,splitted.join("\n")) + }else{ + //write new file: + const newtext = this.#createStatsText() + fs.writeFileSync(this.path,newtext) + } + } + /**Write an `ODConsoleMessage` to the debug file */ + writeConsoleMessage(message:ODConsoleMessage){ + this.#writeDebugFile(message.toDebugString()) + } + /**Write an `ODError` to the debug file */ + writeErrorMessage(error:ODError){ + this.#writeDebugFile(error.toDebugString()) + } + /**Write custom text to the debug file */ + writeText(text:string){ + this.#writeDebugFile(text) + } + /**Write a custom note to the debug file (starting with `[NODE]:`) */ + writeNote(text:string){ + this.#writeDebugFile("[NODE]: "+text) + } +} + +/**## ODDebugger `class` + * This is the open ticket debugger. + * + * It is a simple wrapper around the `ODConsoleManager` to handle debugging (primarily for `ODManagers`). + * Messages created using this debugger are only logged to the debug file unless specified otherwise. + * + * You will probably notice this class being used in the `ODManager` constructor. + * + * Using this system, all additions & removals inside a manager are logged to the debug file. This makes searching for errors a lot easier! + */ +export class ODDebugger { + /**An alias to the open ticket console manager. */ + console: ODConsoleManager + /**When enabled, debug logs are also shown in the console. */ + visible: boolean = false + + constructor(console:ODConsoleManager){ + this.console = console + } + + /**Create a debug message. This will always be logged to `otdebug.txt` & sometimes to the console (when enabled). Returns `true` when visible */ + debug(message:string, params?:{key:string,value:string}[]): boolean { + if (this.visible){ + this.console.log(new ODConsoleDebugMessage(message,params)) + return true + }else{ + this.console.debugfile.writeConsoleMessage(new ODConsoleDebugMessage(message,params)) + return false + } + } +} + +/**## ODLivestatusColor `type` + * This is a collection of all the colors available within the LiveStatus system. + */ +export type ODLiveStatusColor = "normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan" + +/**## ODLiveStatusSourceData `interface` + * This is an interface containing all raw data received from the LiveStatus system. + */ +export interface ODLiveStatusSourceData { + /**The message to display */ + message:{ + /**The title of the message to display */ + title:string, + /**The title color of the message to display */ + titleColor:ODLiveStatusColor, + /**The description of the message to display */ + description:string, + /**The description color of the message to display */ + descriptionColor:ODLiveStatusColor + }, + /**The message will only be shown when the bot matches all statements */ + active:{ + /**A list of versions to match */ + versions:string[], + /**A list of languages to match */ + languages:string[], + /**All languages should match */ + allLanguages:boolean, + /**Match when the bot is using plugins */ + usingPlugins:boolean, + /**Match when the bot is not using plugins */ + notUsingPlugins:boolean, + /**Match when the bot is using slash commands */ + usingSlashCommands:boolean, + /**Match when the bot is not using slash commands */ + notUsingSlashCommands:boolean, + /**Match when the bot is not using transcripts */ + notUsingTranscripts:boolean, + /**Match when the bot is using text transcripts */ + usingTextTranscripts:boolean, + /**Match when the bot is using html transcripts */ + usingHtmlTranscripts:boolean + } +} + +/**## ODLiveStatusSource `class` + * This is the open ticket livestatus source. + * + * It is an empty template for a livestatus source. + * By default, you should use `ODLiveStatusUrlSource` or `ODLiveStatusFileSource`, + * unless you want to create one on your own! + * + * This class doesn't do anything on it's own! It's just a template! + */ +export class ODLiveStatusSource extends ODManagerData { + /**The raw data of this source */ + data: ODLiveStatusSourceData[] + + constructor(id:ODValidId, data:ODLiveStatusSourceData[]){ + super(id) + this.data = data + } + + /**Change the current data using this method! */ + setData(data:ODLiveStatusSourceData[]){ + this.data = data + } + /**Get all messages relevant to the bot based on some parameters. */ + async getMessages(main:ODMain): Promise { + const validMessages: ODLiveStatusSourceData[] = [] + + //parse data from ODMain + const currentVersion: string = main.versions.get("openticket:version").toString(true) + const usingSlashCommands: boolean = main.configs.get("openticket:general").data.slashCommands + const usingTranscripts: false|"text"|"html" = false as false|"text"|"html" //TODO + const currentLanguage: string = main.languages.getCurrentLanguageId() + const usingPlugins: boolean = (main.plugins.getLength() > 0) + + //check data for each message + this.data.forEach((msg) => { + const {active} = msg + + const correctVersion = active.versions.includes(currentVersion) + const correctSlashMode = (usingSlashCommands && active.usingSlashCommands) || (!usingSlashCommands && active.notUsingSlashCommands) + const correctTranscriptMode = (usingTranscripts == "text" && active.usingTextTranscripts) || (usingTranscripts == "html" && active.usingHtmlTranscripts) || (!usingTranscripts && active.notUsingTranscripts) + const correctLanguage = active.languages.includes(currentLanguage) || active.allLanguages + const correctPlugins = (usingPlugins && active.usingPlugins) || (!usingPlugins && active.notUsingPlugins) + + if (correctVersion && correctLanguage && correctPlugins && correctSlashMode && correctTranscriptMode) validMessages.push(msg) + }) + + //return the valid messages + return validMessages + } +} + +/**## ODLiveStatusFileSource `class` + * This is the open ticket livestatus file source. + * + * It is a LiveStatus source that will read the data from a local file. + * + * This can be used for testing/extending the LiveStatus system! + */ +export class ODLiveStatusFileSource extends ODLiveStatusSource { + /**The path to the source file */ + path: string + + constructor(id:ODValidId, path:string){ + if (fs.existsSync(path)){ + super(id,JSON.parse(fs.readFileSync(path).toString())) + }else throw new ODSystemError("LiveStatus source file doesn't exist!") + this.path = path + } +} + +/**## ODLiveStatusUrlSource `class` + * This is the open ticket livestatus url source. + * + * It is a LiveStatus source that will read the data from a http URL (json file). + * + * This is the default way of receiving LiveStatus messages! + */ +export class ODLiveStatusUrlSource extends ODLiveStatusSource { + /**The url used in the request */ + url: string + /**The `ODHTTPGetRequest` helper to fetch the url! */ + request: ODHTTPGetRequest + + constructor(id:ODValidId, url:string){ + super(id,[]) + this.url = url + this.request = new ODHTTPGetRequest(url,false) + } + async getMessages(main:ODMain): Promise { + //additional setup + this.request.url = this.url + const rawRes = await this.request.run() + if (rawRes.status != 200) throw new ODSystemError("ODLiveStatusUrlSource => Request Failed!") + try{ + this.setData(JSON.parse(rawRes.body)) + }catch{ + throw new ODSystemError("ODLiveStatusUrlSource => Request Failed!") + } + + //default + return super.getMessages(main) + } +} + +/**## ODLiveStatusManager `class` + * This is the open ticket livestatus manager. + * + * It manages all LiveStatus sources and has the renderer for all LiveStatus messages. + * + * You will probably use this to customise or add stuff to the LiveStatus system. + * Access it in the global `openticket.startscreen.livestatus` variable! + */ +export class ODLiveStatusManager extends ODManager { + /**The class responsible for rendering the livestatus messages. */ + renderer: ODLiveStatusRenderer + /**A reference to the ODMain or "openticket" global variable */ + #main: ODMain + + constructor(debug:ODDebugger, main:ODMain){ + super(debug,"livestatus source") + this.renderer = new ODLiveStatusRenderer(main.console) + this.#main = main + } + + /**Get the messages from all sources combined! */ + async getAllMessages(): Promise { + const messages: ODLiveStatusSourceData[] = [] + for (const source of this.getAll()){ + try { + messages.push(...(await source.getMessages(this.#main))) + }catch{} + } + return messages + } +} + +/**## ODLiveStatusRenderer `class` + * This is the open ticket livestatus renderer. + * + * It's responsible for rendering all LiveStatus messages to the console. + */ +export class ODLiveStatusRenderer { + /**A reference to the ODConsoleManager or "openticket.console" global variable */ + #console: ODConsoleManager + + constructor(console:ODConsoleManager){ + this.#console = console + } + + /**Render all messages */ + render(messages:ODLiveStatusSourceData[]): string { + try { + //process data + const final: string[] = [] + messages.forEach((msg) => { + const titleColor = msg.message.titleColor + const title = "["+msg.message.title+"] " + + const descriptionColor = msg.message.descriptionColor + const description = msg.message.description.split("\n").map((text,row) => { + //first row row doesn't need prefix + if (row < 1) return text + //other rows do need a prefix + let text2 = text + for (const i of title){ + text2 = " "+text2 + } + return text2 + }).join("\n") + + + if (!["red","yellow","green","blue","gray","magenta","cyan"].includes(titleColor)) var finalTitle = ansis.white(title) + else var finalTitle = ansis[titleColor](title) + if (!["red","yellow","green","blue","gray","magenta","cyan"].includes(descriptionColor)) var finalDescription = ansis.white(description) + else var finalDescription = ansis[descriptionColor](description) + + final.push(finalTitle+finalDescription) + }) + + //return all messages + return final.join("\n") + }catch{ + this.#console.log("Failed to render LiveStatus messages!","error") + return "" + } + } +} \ No newline at end of file diff --git a/src/core/api/modules/cooldown.ts b/src/core/api/modules/cooldown.ts new file mode 100644 index 0000000..254a45a --- /dev/null +++ b/src/core/api/modules/cooldown.ts @@ -0,0 +1,348 @@ +/////////////////////////////////////// +//COOLDOWN MODULE +/////////////////////////////////////// +import { ODId, ODValidId, ODManager, ODSystemError, ODManagerData } from "./base" +import { ODDebugger } from "./console" + +/**## ODCooldownManager `class` + * This is an open ticket cooldown manager. + * + * It is responsible for managing all cooldowns in Open Ticket. An example of this is the ticket creation cooldown. + * + * There are many types of cooldowns available, but you can also create your own! + */ +export class ODCooldownManager extends ODManager> { + constructor(debug:ODDebugger){ + super(debug,"cooldown") + } + /**Initiate all cooldowns in this manager. */ + async init(){ + for (const cooldown of this.getAll()){ + await cooldown.init() + } + } +} + +/**## ODCooldownData `class` + * This is open ticket cooldown data. + * + * It contains the instance of an active cooldown (e.g. for a user). It is handled by the cooldown itself. + */ +export class ODCooldownData extends ODManagerData { + /**Is this cooldown active? */ + active: boolean + /**Additional data of this cooldown instance. (different for each cooldown type) */ + data: Data + + constructor(id:ODValidId,active:boolean,data:Data){ + super(id) + this.active = active + this.data = data + } +} + +/**## ODCooldown `class` + * This is an open ticket cooldown. + * + * It doesn't do anything on it's own, but it provides the methods that are used to interact with a cooldown. + * This class can be extended from to create a working cooldown. + * + * There are also premade cooldowns available in the bot! + */ +export class ODCooldown extends ODManagerData { + data: ODManager> = new ODManager() + /**Is this cooldown already initialized? */ + ready: boolean = false + + constructor(id:ODValidId){ + super(id) + } + + /**Check this id and start cooldown when it exeeds the limit! Returns `true` when on cooldown! */ + use(id:string): boolean { + throw new ODSystemError("Tried to use an unimplemented ODCooldown!") + } + /**Check this id without starting or updating the cooldown. Returns `true` when on cooldown! */ + check(id:string): boolean { + throw new ODSystemError("Tried to use an unimplemented ODCooldown!") + } + /**Remove the cooldown for an id when available.*/ + delete(id:string){ + throw new ODSystemError("Tried to use an unimplemented ODCooldown!") + } + /**Initialize the internal systems of this cooldown. */ + async init(){ + throw new ODSystemError("Tried to use an unimplemented ODCooldown!") + } +} + +/**## ODCounterCooldown `class` + * This is an open ticket counter cooldown. + * + * It is is a cooldown based on a counter. When the number exceeds the limit, the cooldown is activated. + * The number will automatically be decreased with a set amount & interval. + */ +export class ODCounterCooldown extends ODCooldown<{value:number}> { + /**The cooldown will activate when exceeding this limit. */ + activeLimit: number + /**The cooldown will deactivate when below this limit. */ + cancelLimit: number + /**The amount to increase the counter with everytime the cooldown is triggered/updated. */ + increment: number + /**The amount to decrease the counter over time. */ + decrement: number + /**The interval between decrements in milliseconds. */ + invervalMs: number + + constructor(id:ODValidId, activeLimit:number, cancelLimit:number, increment:number, decrement:number, intervalMs:number){ + super(id) + this.activeLimit = activeLimit + this.cancelLimit = cancelLimit + this.increment = increment + this.decrement = decrement + this.invervalMs = intervalMs + } + + use(id:string): boolean { + const cooldown = this.data.get(id) + if (cooldown){ + //cooldown for this id already exists + if (cooldown.active){ + return true + + }else if (cooldown.data.value < this.activeLimit){ + cooldown.data.value = cooldown.data.value + this.increment + return false + + }else{ + cooldown.active = true + return false + } + }else{ + //cooldown for this id doesn't exist + this.data.add(new ODCooldownData(id,(this.increment >= this.activeLimit),{ + value:this.increment + })) + return false + } + } + check(id:string): boolean { + const cooldown = this.data.get(id) + if (cooldown){ + //cooldown for this id already exists + return cooldown.active + }else return false + } + delete(id:string): void { + this.data.remove(id) + } + async init(){ + if (this.ready) return + setInterval(() => { + this.data.getAll().forEach((cooldown) => { + cooldown.data.value = cooldown.data.value - this.decrement + if (cooldown.data.value <= this.cancelLimit){ + cooldown.active = false + } + if (cooldown.data.value <= 0){ + this.data.remove(cooldown.id) + } + }) + },this.invervalMs) + this.ready = true + } +} + +/**## ODIncrementalCounterCooldown `class` + * This is an open ticket incremental counter cooldown. + * + * It is is a cooldown based on an incremental counter. It is exactly the same as the normal counter, + * with the only difference being that it still increments when the limit is already exeeded. + */ +export class ODIncrementalCounterCooldown extends ODCooldown<{value:number}> { + /**The cooldown will activate when exceeding this limit. */ + activeLimit: number + /**The cooldown will deactivate when below this limit. */ + cancelLimit: number + /**The amount to increase the counter with everytime the cooldown is triggered/updated. */ + increment: number + /**The amount to decrease the counter over time. */ + decrement: number + /**The interval between decrements in milliseconds. */ + invervalMs: number + + constructor(id:ODValidId, activeLimit:number, cancelLimit:number, increment:number, decrement:number, intervalMs:number){ + super(id) + this.activeLimit = activeLimit + this.cancelLimit = cancelLimit + this.increment = increment + this.decrement = decrement + this.invervalMs = intervalMs + } + + use(id:string): boolean { + const cooldown = this.data.get(id) + if (cooldown){ + //cooldown for this id already exists + if (cooldown.active){ + cooldown.data.value = cooldown.data.value + this.increment + return true + + }else if (cooldown.data.value < this.activeLimit){ + cooldown.data.value = cooldown.data.value + this.increment + return false + + }else{ + cooldown.active = true + return false + } + }else{ + //cooldown for this id doesn't exist + this.data.add(new ODCooldownData(id,(this.increment >= this.activeLimit),{ + value:this.increment + })) + return false + } + } + check(id:string): boolean { + const cooldown = this.data.get(id) + if (cooldown){ + //cooldown for this id already exists + return cooldown.active + }else return false + } + delete(id:string): void { + this.data.remove(id) + } + async init(){ + if (this.ready) return + setInterval(() => { + this.data.getAll().forEach((cooldown) => { + cooldown.data.value = cooldown.data.value - this.decrement + if (cooldown.data.value <= this.cancelLimit){ + cooldown.active = false + } + if (cooldown.data.value <= 0){ + this.data.remove(cooldown.id) + } + }) + },this.invervalMs) + this.ready = true + } +} + +/**## ODTimeoutCooldown `class` + * This is an open ticket timeout cooldown. + * + * It is a cooldown based on a timer. When triggered/updated, the cooldown is activated for the set amount of time. + * After the timer has timed out, the cooldown will be deleted. + */ +export class ODTimeoutCooldown extends ODCooldown<{date:number}> { + /**The amount of milliseconds before the cooldown times-out */ + timeoutMs: number + + constructor(id:ODValidId, timeoutMs:number){ + super(id) + this.timeoutMs = timeoutMs + } + + use(id:string): boolean { + const cooldown = this.data.get(id) + if (cooldown){ + //cooldown for this id already exists + if ((new Date().getTime() - cooldown.data.date) > this.timeoutMs){ + this.data.remove(id) + return false + }else{ + return true + } + }else{ + //cooldown for this id doesn't exist + this.data.add(new ODCooldownData(id,true,{ + date:new Date().getTime() + })) + return false + } + } + check(id:string): boolean { + const cooldown = this.data.get(id) + if (cooldown){ + //cooldown for this id already exists + return true + }else return false + } + delete(id:string): void { + this.data.remove(id) + } + /**Get the remaining amount of milliseconds before the timeout stops. */ + remaining(id:string): number|null { + const cooldown = this.data.get(id) + if (!cooldown) return null + const rawResult = this.timeoutMs - (new Date().getTime() - cooldown.data.date) + return (rawResult > 0) ? rawResult : 0 + } + async init(){ + if (this.ready) return + this.ready = true + } +} + +/**## ODIncrementalTimeoutCooldown `class` + * This is an open ticket incremental timeout cooldown. + * + * It is is a cooldown based on an incremental timer. It is exactly the same as the normal timer, + * with the only difference being that it adds additional time when triggered/updated while the cooldown is already active. + */ +export class ODIncrementalTimeoutCooldown extends ODCooldown<{date:number}> { + /**The amount of milliseconds before the cooldown times-out */ + timeoutMs: number + /**The amount of milliseconds to add when triggered/updated while the cooldown is already active. */ + incrementMs: number + + constructor(id:ODValidId, timeoutMs:number, incrementMs:number){ + super(id) + this.timeoutMs = timeoutMs + this.incrementMs = incrementMs + } + + use(id:string): boolean { + const cooldown = this.data.get(id) + if (cooldown){ + //cooldown for this id already exists + if ((new Date().getTime() - cooldown.data.date) > this.timeoutMs){ + this.data.remove(id) + return false + }else{ + cooldown.data.date = cooldown.data.date + this.incrementMs + return true + } + }else{ + //cooldown for this id doesn't exist + this.data.add(new ODCooldownData(id,true,{ + date:new Date().getTime() + })) + return false + } + } + check(id:string): boolean { + const cooldown = this.data.get(id) + if (cooldown){ + //cooldown for this id already exists + return true + }else return false + } + delete(id:string): void { + this.data.remove(id) + } + /**Get the remaining amount of milliseconds before the timeout stops. */ + remaining(id:string): number|null { + const cooldown = this.data.get(id) + if (!cooldown) return null + const rawResult = this.timeoutMs - (new Date().getTime() - cooldown.data.date) + return (rawResult > 0) ? rawResult : 0 + } + async init(){ + if (this.ready) return + this.ready = true + } +} \ No newline at end of file diff --git a/src/core/api/modules/database.ts b/src/core/api/modules/database.ts new file mode 100644 index 0000000..15047b5 --- /dev/null +++ b/src/core/api/modules/database.ts @@ -0,0 +1,316 @@ +/////////////////////////////////////// +//DATABASE MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODValidId, ODValidJsonType } from "./base" +import fs from "fs" +import nodepath from "path" +import { ODDebugger } from "./console" +import * as fjs from "formatted-json-stringify" + +/**## ODDatabaseManager `class` + * This is an open ticket database manager. + * + * It manages all databases in the bot and allows to permanently store data from the bot! + * + * You will use this class to get/add a database (`ODDatabase`) in your plugin! + * @example + * //get ./database/ot-global.json => ODDatabase class + * const globalDB = openticket.databases.get("openticket:global") + * + * //add a new database with id "test" => ./database/idk-test.json + * const testDatabase = new api.ODDatabase("test","idk-test.json") + * openticket.databases.add(testDatabase) + */ +export class ODDatabaseManager extends ODManager { + constructor(debug:ODDebugger){ + super(debug,"database") + } + + /**Add data to the manager. The id will be fetched from the data class! You can optionally select to overwrite existing data! + * @example + * //add a new database with id "test" => ./database/idk-test.json + * const testDatabase = new api.ODDatabase("test","idk-test.json") + * openticket.databases.add(testDatabase) + */ + add(data:ODDatabase, overwrite?:boolean): boolean { + return super.add(data,overwrite) + } + /**Get data that matches the `ODId`. Returns the found data. + * @example + * //get ./database/ot-global.json => ODDatabase class + * const globalDB = openticket.databases.get("openticket:global") + */ + get(id:ODValidId): ODDatabase|null { + return super.get(id) + } + /**Remove data that matches the `ODId`. Returns the removed data. + * @example + * //remove the "test" database + * openticket.databases.remove("test") //returns null if non-existing + */ + remove(id:ODValidId): ODDatabase|null { + return super.remove(id) + } + /**Check if data that matches the `ODId` exists. Returns a boolean. + * @example + * //check if "./database/idk-test.json" (test) exists => boolean + * const exists = openticket.databases.exists("test") + */ + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODDatabase `class` + * This is an open ticket database template. + * This class doesn't do anything at all, it just gives a template & basic methods for a database. Use `ODJsonDatabase` instead! + * + * You will only use this class if you want to create your own database implementation (e.g. `mongodb`, `mysql`,...)! + * @example + * class SomeDatabase extends ODDatabase { + * //override this method + * setData(category:string, key:string, value:ODValidJsonType): boolean { + * return false + * } + * //override this method + * getData(category:string, key:string): ODValidJsonType|undefined { + * return undefined + * } + * //override this method + * deleteData(category:string, key:string): boolean { + * return false + * } + * } + */ +export class ODDatabase extends ODManagerData { + /**The full path to this database with extension */ + file: string = "" + + /**Add/Overwrite a specific category & key in the database. Returns `true` when overwritten. */ + set(category:string, key:string, value:ODValidJsonType): boolean { + return false + } + /**Get a specific category & key in the database */ + get(category:string, key:string): ODValidJsonType|undefined { + return undefined + } + /**Delete a specific category & key in the database */ + delete(category:string, key:string): boolean { + return false + } + /**Check if a specific category & key exists in the database */ + exists(category:string, key:string): boolean { + return false + } + /**Get a specific category in the database */ + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + return undefined + } + /**Get all values in the database */ + getAll(): ODJsonDatabaseStructure { + return [] + } +} + +/**## ODJsonDatabaseStructure `type` + * This is the structure of how a JSON database file! + */ +export type ODJsonDatabaseStructure = {category:string, key:string, value:ODValidJsonType}[] + +/**## ODJsonDatabase `class` + * This is an open ticket JSON database. + * It stores data in a `json` file as a large `Array` using the `category`, `key`, `value` strategy. + * You can store the following types: `string`, `number`, `boolean`, `array`, `object` & `null`! + * + * You will only use this class if you want to create your own database or use an existing one! + * @example + * //get,set & delete data + * const data = database.getData("category","key") //data will be the value + * const didOverwrite = database.setData("category","key","value") //value can be any of the valid types + * const didExist = database.deleteData("category","key") //delete this value + * //You need an ODJsonDatabase class named "database" for this example to work! + */ +export class ODJsonDatabase extends ODDatabase { + constructor(id:ODValidId, file:string, customPath?:string){ + super(id) + const filename = (file.endsWith(".json")) ? file : file+".json" + this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./database/",filename) + + //init file if it doesn't exist yet + this.#system.getData() + } + + /**Set/overwrite the value of `category` & `key`. Returns `true` when overwritten! + * @example + * const didOverwrite = database.setData("category","key","value") //value can be any of the valid types + * //You need an ODJsonDatabase class named "database" for this example to work! + */ + set(category:string, key:string, value:ODValidJsonType): boolean { + const currentList = this.#system.getData() + const currentData = currentList.find((d) => (d.category === category) && (d.key === key)) + + //overwrite when already present + if (currentData){ + currentList[currentList.indexOf(currentData)].value = value + }else{ + currentList.push({category,key,value}) + } + + this.#system.setData(currentList) + return currentData ? true : false + } + /**Get the value of `category` & `key`. Returns `undefined` when non-existent! + * @example + * const data = database.getData("category","key") //data will be the value + * //You need an ODJsonDatabase class named "database" for this example to work! + */ + get(category:string, key:string): ODValidJsonType|undefined { + const currentList = this.#system.getData() + const tempresult = currentList.find((d) => (d.category === category) && (d.key === key)) + return tempresult ? tempresult.value : undefined + } + /**Remove the value of `category` & `key`. Returns `undefined` when non-existent! + * @example + * const didExist = database.deleteData("category","key") //delete this value + * //You need an ODJsonDatabase class named "database" for this example to work! + */ + delete(category:string, key:string): boolean { + const currentList = this.#system.getData() + const currentData = currentList.find((d) => (d.category === category) && (d.key === key)) + if (currentData) currentList.splice(currentList.indexOf(currentData),1) + + this.#system.setData(currentList) + return currentData ? true : false + } + /**Check if a value of `category` & `key` exists. Returns `false` when non-existent! */ + exists(category:string, key:string): boolean { + const currentList = this.#system.getData() + const tempresult = currentList.find((d) => (d.category === category) && (d.key === key)) + return tempresult ? true : false + } + /**Get all values in `category`. Returns `undefined` when non-existent! */ + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + const currentList = this.#system.getData() + const tempresult = currentList.filter((d) => (d.category === category)) + return tempresult ? tempresult.map((data) => {return {key:data.key,value:data.value}}) : undefined + } + /**Get all values in `category`. */ + getAll(): ODJsonDatabaseStructure { + return this.#system.getData() + } + + #system = { + /**Read parsed data from the json file */ + getData: (): ODJsonDatabaseStructure => { + if (fs.existsSync(this.file)){ + return JSON.parse(fs.readFileSync(this.file).toString()) + }else{ + fs.writeFileSync(this.file,"[]") + return [] + } + }, + /**Write parsed data to the json file */ + setData: (data:ODJsonDatabaseStructure) => { + fs.writeFileSync(this.file,JSON.stringify(data,null,"\t")) + } + } +} + + +/**## ODFormattedJsonDatabase `class` + * This is an open ticket Formatted JSON database. + * It stores data in a `json` file as a large `Array` using the `category`, `key`, `value` strategy. + * You can store the following types: `string`, `number`, `boolean`, `array`, `object` & `null`! + * + * This one is exactly the same as `ODJsonDatabase`, but it has a formatter from the `formatted-json-stringify` package. + * This can help you organise it a little bit better! + */ +export class ODFormattedJsonDatabase extends ODDatabase { + /**The formatter to use on the database array */ + formatter: fjs.ArrayFormatter + + constructor(id:ODValidId, file:string, formatter:fjs.ArrayFormatter, customPath?:string){ + super(id) + const filename = (file.endsWith(".json")) ? file : file+".json" + this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./database/",filename) + this.formatter = formatter + + //init file if it doesn't exist yet + this.#system.getData() + } + + /**Set/overwrite the value of `category` & `key`. Returns `true` when overwritten! + * @example + * const didOverwrite = database.setData("category","key","value") //value can be any of the valid types + * //You need an ODFormattedJsonDatabase class named "database" for this example to work! + */ + set(category:string, key:string, value:ODValidJsonType): boolean { + const currentList = this.#system.getData() + const currentData = currentList.find((d) => (d.category === category) && (d.key === key)) + + //overwrite when already present + if (currentData){ + currentList[currentList.indexOf(currentData)].value = value + }else{ + currentList.push({category,key,value}) + } + + this.#system.setData(currentList) + return currentData ? true : false + } + /**Get the value of `category` & `key`. Returns `undefined` when non-existent! + * @example + * const data = database.getData("category","key") //data will be the value + * //You need an ODFormattedJsonDatabase class named "database" for this example to work! + */ + get(category:string, key:string): ODValidJsonType|undefined { + const currentList = this.#system.getData() + const tempresult = currentList.find((d) => (d.category === category) && (d.key === key)) + return tempresult ? tempresult.value : undefined + } + /**Remove the value of `category` & `key`. Returns `undefined` when non-existent! + * @example + * const didExist = database.deleteData("category","key") //delete this value + * //You need an ODFormattedJsonDatabase class named "database" for this example to work! + */ + delete(category:string, key:string): boolean { + const currentList = this.#system.getData() + const currentData = currentList.find((d) => (d.category === category) && (d.key === key)) + if (currentData) currentList.splice(currentList.indexOf(currentData),1) + + this.#system.setData(currentList) + return currentData ? true : false + } + /**Check if a value of `category` & `key` exists. Returns `false` when non-existent! */ + exists(category:string, key:string): boolean { + const currentList = this.#system.getData() + const tempresult = currentList.find((d) => (d.category === category) && (d.key === key)) + return tempresult ? true : false + } + /**Get all values in `category`. Returns `undefined` when non-existent! */ + getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + const currentList = this.#system.getData() + const tempresult = currentList.filter((d) => (d.category === category)) + return tempresult ? tempresult.map((data) => {return {key:data.key,value:data.value}}) : undefined + } + /**Get all values in `category`. */ + getAll(): ODJsonDatabaseStructure { + return this.#system.getData() + } + + #system = { + /**Read parsed data from the json file */ + getData: (): ODJsonDatabaseStructure => { + if (fs.existsSync(this.file)){ + return JSON.parse(fs.readFileSync(this.file).toString()) + }else{ + fs.writeFileSync(this.file,"[]") + return [] + } + }, + /**Write parsed data to the json file */ + setData: (data:ODJsonDatabaseStructure) => { + fs.writeFileSync(this.file,this.formatter.stringify(data)) + } + } +} \ No newline at end of file diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts new file mode 100644 index 0000000..a2f1910 --- /dev/null +++ b/src/core/api/modules/defaults.ts @@ -0,0 +1,319 @@ +/////////////////////////////////////// +//DEFAULTS MODULE +/////////////////////////////////////// + +/**## ODDefaults `interface` + * This type is a list of all defaults available in the `ODDefaultsManager` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODDefaults { + /**Enable the default error handling system. */ + errorHandling:boolean, + /**Crash when there is an unknown bot error. */ + crashOnError:boolean, + /**Enable the system responsible for the `--debug` flag. */ + debugLoading:boolean, + /**Enable loading all Open Ticket plugins, sadly enough is only useful for the system :) */ + pluginLoading:boolean, + /**Don't crash the bot when a plugin crashes! */ + softPluginLoading:boolean, + + /**Load the default open ticket plugin classes. */ + pluginClassLoading:boolean, + /**Load the default open ticket plugin events. */ + pluginEventLoading:boolean, + + /**Load the default open ticket flags. */ + flagLoading:boolean, + /**Enable the default initializer for open ticket flags. */ + flagInitiating:boolean, + /**Load the default open ticket configs. */ + configLoading:boolean, + /**Load the default open ticket databases. */ + databaseLoading:boolean, + /**Load the default open ticket sessions. */ + sessionLoading:boolean, + + /**Load the default open ticket languages. */ + languageLoading:boolean, + /**Enable selecting the current language from `config/general.json`. */ + languageSelection:boolean, + /**Set the backup language when the primary language is missing a property. */ + backupLanguage:string, + /****[NOD FOR PLUGIN TRANSLATIONS]** The full list of available languages (used in the default config checker). */ + languageList:string[], + + /**Load the default open ticket config checker. */ + checkerLoading:boolean, + /**Load the default open ticket config checker functions. */ + checkerFunctionLoading:boolean, + /**Enable the default execution of the config checkers. */ + checkerExecution:boolean, + /**Load the default open ticket config checker translations. */ + checkerTranslationLoading:boolean, + /**Enable the default rendering of the config checkers. */ + checkerRendering:boolean, + /**Enable the default quit action when there is an error in the config checker. */ + checkerQuit:boolean, + /**Render the checker even when there are no errors & warnings. */ + checkerRenderEmpty:boolean, + + /**Load the default open ticket client configuration. */ + clientLoading:boolean, + /**Load the default open ticket client initialization. */ + clientInitiating:boolean, + /**Load the default open ticket client ready actions (status, commands, permissions, ...). */ + clientReady:boolean, + /**Create a warning when the bot is present in multiple guilds. */ + clientMultiGuildWarning:boolean, + /**Load the default open ticket client activity (from `config/general.json`). */ + clientActivityLoading:boolean, + /**Load the default open ticket client activity initialization (& status refresh). */ + clientActivityInitiating:boolean, + + /**Load the default open ticket slash commands. */ + slashCommandLoading:boolean, + /**Load the default open ticket slash command registerer (register slash cmds in discord). */ + slashCommandRegistering:boolean, + /**When enabled, the bot is forced to re-register all slash commands in the server. This can be used in case of a auto-update malfunction. */ + forceSlashCommandRegistration:boolean, + /**Load the default open ticket text commands. */ + textCommandLoading:boolean, + + /**Load the default open ticket questions (from `config/questions.json`) */ + questionLoading:boolean, + /**Load the default open ticket options (from `config/options.json`) */ + optionLoading:boolean, + /**Load the default open ticket panels (from `config/panels.json`) */ + panelLoading:boolean, + /**Load the default open ticket tickets (from `database/tickets.json`) */ + ticketLoading:boolean, + /**Load the default open ticket reaction roles (from `config/options.json`) */ + roleLoading:boolean, + /**Load the default open ticket blacklist (from `database/users.json`) */ + blacklistLoading:boolean, + /**Load the default open ticket transcript compilers. */ + transcriptCompilerLoading:boolean, + /**Load the default open ticket transcript history (from `database/transcripts.json`) */ + transcriptHistoryLoading:boolean, + + /**Load the default open ticket button builders. */ + buttonBuildersLoading:boolean, + /**Load the default open ticket dropdown builders. */ + dropdownBuildersLoading:boolean, + /**Load the default open ticket file builders. */ + fileBuildersLoading:boolean, + /**Load the default open ticket embed builders. */ + embedBuildersLoading:boolean, + /**Load the default open ticket message builders. */ + messageBuildersLoading:boolean, + /**Load the default open ticket modal builders. */ + modalBuildersLoading:boolean, + + /**Load the default open ticket command responders. */ + commandRespondersLoading:boolean, + /**Load the default open ticket button responders. */ + buttonRespondersLoading:boolean, + /**Load the default open ticket dropdown responders. */ + dropdownRespondersLoading:boolean, + /**Load the default open ticket modal responders. */ + modalRespondersLoading:boolean, + /**Set the time (in ms) before open ticket sends an error message when no reply is sent in a responder. */ + responderTimeoutMs:number, + + /**Load the default open ticket actions. */ + actionsLoading:boolean, + + /**Load the default open ticket verify bars. */ + verifyBarsLoading:boolean, + /**Load the default open ticket permissions. */ + permissionsLoading:boolean, + /**Load the default open ticket posts. */ + postsLoading:boolean, + /**Initiate the default open ticket posts. */ + postsInitiating:boolean, + /**Load the default open ticket cooldowns. */ + cooldownsLoading:boolean, + /**Initiate the default open ticket cooldowns. */ + cooldownsInitiating:boolean, + /**Load the default open ticket help menu categories. */ + helpMenuCategoryLoading:boolean, + /**Load the default open ticket help menu components. */ + helpMenuComponentLoading:boolean, + + /**Load the default open ticket stat scopes. */ + statScopesLoading:boolean, + /**Load the default open ticket stats. */ + statLoading:boolean, + /**Initiate the default open ticket stats. */ + statInitiating:boolean, + + /**Load the default open ticket code/functions. */ + codeLoading:boolean, + /**Execute the default open ticket code/functions. */ + codeExecution:boolean, + + /**Load the default open ticket livestatus. */ + liveStatusLoading:boolean, + /**Load the default open ticket startscreen. */ + startScreenLoading:boolean, + /**Render the default open ticket startscreen. */ + startScreenRendering:boolean, + + /**The emoji style to use in embed & message titles using `utilities.emoijTitle()` */ + emojiTitleStyle:"disabled"|"before"|"after"|"double", + /**The emoji divider to use in embed & message titles using `utilities.emoijTitle()` */ + emojiTitleDivider:string + /**The interval in milliseconds that are between autoclose timeout checkers. */ + autocloseCheckInterval:number + /**The interval in milliseconds that are between autodelete timeout checkers. */ + autodeleteCheckInterval:number +} + +/**## ODDefaultsBooleans `type` + * This type is a list of boolean defaults available in the `ODDefaultsManager` class. + * It's used to generate typescript declarations for this class. + */ +export type ODDefaultsBooleans = { + [Key in keyof ODDefaults]: ODDefaults[Key] extends boolean ? Key : never +}[keyof ODDefaults] + +/**## ODDefaultsStrings `type` + * This type is a list of string defaults available in the `ODDefaultsManager` class. + * It's used to generate typescript declarations for this class. + */ +export type ODDefaultsStrings = { + [Key in keyof ODDefaults]: ODDefaults[Key] extends string ? Key : never +}[keyof ODDefaults] + +/**## ODDefaultsNumbers `type` + * This type is a list of number defaults available in the `ODDefaultsManager` class. + * It's used to generate typescript declarations for this class. + */ +export type ODDefaultsNumbers = { + [Key in keyof ODDefaults]: ODDefaults[Key] extends number ? Key : never +}[keyof ODDefaults] + +/**## ODDefaultsStringArray `type` + * This type is a list of string[] defaults available in the `ODDefaultsManager` class. + * It's used to generate typescript declarations for this class. + */ +export type ODDefaultsStringArray = { + [Key in keyof ODDefaults]: ODDefaults[Key] extends string[] ? Key : never +}[keyof ODDefaults] + +/**## ODDefaultsManager `class` + * This is an open ticket defaults manager. + * + * It manages all settings in open ticket that are not meant to be in the config. + * Here you can disable certain default features to replace them or to specifically enable them! + * + * You are unable to add your own defaults, you can only edit Open Ticket defaults! + */ +export class ODDefaultsManager { + /**A list of all the defaults */ + #defaults: ODDefaults + + constructor(){ + this.#defaults = { + errorHandling:true, + crashOnError:false, + debugLoading:true, + pluginLoading:true, + softPluginLoading:false, + + pluginClassLoading:true, + pluginEventLoading:true, + + flagLoading:true, + flagInitiating:true, + configLoading:true, + databaseLoading:true, + sessionLoading:true, + + languageLoading:true, + languageSelection:true, + backupLanguage:"openticket:english", + languageList:["custom","english","dutch","portuguese","czech"], + + checkerLoading:true, + checkerFunctionLoading:true, + checkerExecution:true, + checkerTranslationLoading:true, + checkerRendering:true, + checkerQuit:true, + checkerRenderEmpty:false, + + clientLoading:true, + clientInitiating:true, + clientReady:true, + clientMultiGuildWarning:true, + clientActivityLoading:true, + clientActivityInitiating:true, + + slashCommandLoading:true, + slashCommandRegistering:true, + forceSlashCommandRegistration:false, + textCommandLoading:true, + + questionLoading:true, + optionLoading:true, + panelLoading:true, + ticketLoading:true, + roleLoading:true, + blacklistLoading:true, + transcriptCompilerLoading:true, + transcriptHistoryLoading:true, + + buttonBuildersLoading:true, + dropdownBuildersLoading:true, + fileBuildersLoading:true, + embedBuildersLoading:true, + messageBuildersLoading:true, + modalBuildersLoading:true, + + commandRespondersLoading:true, + buttonRespondersLoading:true, + dropdownRespondersLoading:true, + modalRespondersLoading:true, + responderTimeoutMs:2500, + + actionsLoading:true, + + verifyBarsLoading:true, + permissionsLoading:true, + postsLoading:true, + postsInitiating:true, + cooldownsLoading:true, + cooldownsInitiating:true, + helpMenuCategoryLoading:true, + helpMenuComponentLoading:true, + + statScopesLoading:true, + statLoading:true, + statInitiating:true, + + codeLoading:true, + codeExecution:true, + + liveStatusLoading:true, + startScreenLoading:true, + startScreenRendering:true, + + emojiTitleStyle:"before", + emojiTitleDivider:" ", + autocloseCheckInterval:300000, //5 minutes + autodeleteCheckInterval:300000 //5 minutes + } + } + + /**Set a default to a specific value. Remember! All plugins can edit these values, so your value could be overwritten! */ + setDefault(key:DefaultName, value:ODDefaults[DefaultName]): void { + this.#defaults[key] = value + } + + /**Get a default. Remember! All plugins can edit these values, so this value could be overwritten! */ + getDefault(key:DefaultName): ODDefaults[DefaultName] { + return this.#defaults[key] + } +} \ No newline at end of file diff --git a/src/core/api/modules/event.ts b/src/core/api/modules/event.ts new file mode 100644 index 0000000..27633c1 --- /dev/null +++ b/src/core/api/modules/event.ts @@ -0,0 +1,99 @@ +/////////////////////////////////////// +//EVENT MODULE +/////////////////////////////////////// +import { ODManagerData, ODManager, ODValidId } from "./base" +import { ODConsoleWarningMessage, ODDebugger } from "./console" + +/**## ODEvent `class` + * This is an open ticket event. + * + * This class is made to work with the `ODEventManager` to handle events. + * The function of this specific class is to manage all listeners for a specifc event! + */ +export class ODEvent extends ODManagerData { + /**Alias to open ticket debugger. */ + #debug?: ODDebugger + /**The list of permanent listeners. */ + listeners: Function[] = [] + /**The list of one-time listeners. List is cleared every time the event is emitted. */ + oncelisteners: Function[] = [] + /**The max listener limit before a possible memory leak will be announced */ + listenerLimit: number = 25 + + /**Use the open ticket debugger in this manager for logs*/ + useDebug(debug:ODDebugger|null){ + this.#debug = debug ?? undefined + } + /**Get a collection of listeners combined from both types. Also clears the one-time listeners array! */ + #getCurrentListeners(){ + const final: Function[] = [] + this.oncelisteners.forEach((l) => final.push(l)) + this.listeners.forEach((l) => final.push(l)) + + this.oncelisteners = [] + return final + } + /**Edit the listener limit */ + setListenerLimit(limit:number){ + this.listenerLimit = limit + } + /**Add a permanent callback to this event. This will stay as long as the bot is running! */ + listen(callback:Function){ + this.listeners.push(callback) + + if (this.listeners.length > this.listenerLimit){ + if (this.#debug) this.#debug.console.log(new ODConsoleWarningMessage("Possible event memory leak detected!",[ + {key:"event",value:this.id.value}, + {key:"listeners",value:this.listeners.length.toString()} + ])) + } + } + /**Add a one-time-only callback to this event. This will only trigger the callback once! */ + listenOnce(callback:Function){ + this.oncelisteners.push(callback) + } + /**Wait until this event is fired! Be carefull with it, because it could block the entire bot when wrongly used! */ + async wait(): Promise { + return new Promise((resolve,reject) => { + this.oncelisteners.push((...args:any) => {resolve(args)}) + }) + } + /**Emit this event to all listeners. You are required to provide all parameters of the event! */ + async emit(params:any[]): Promise { + for (const listener of this.#getCurrentListeners()){ + try{ + await listener(...params) + }catch(err){ + process.emit("uncaughtException",err) + } + } + } +} + +/**## ODEventManager `class` + * This is an open ticket event manager. + * + * This class is made to manage all events in the bot. You can compare it with the built-in node.js `EventEmitter` + * + * You will probably not create this class yourself, but use it globaly instead! + * Check out the `openticket.events` class! + */ +export class ODEventManager extends ODManager { + /**Reference to the Open Ticket debugger */ + #debug: ODDebugger + + constructor(debug:ODDebugger){ + super(debug,"event") + this.#debug = debug + } + + add(data:ODEvent, overwrite?:boolean): boolean { + data.useDebug(this.#debug) + return super.add(data,overwrite) + } + remove(id:ODValidId): ODEvent|null { + const data = super.remove(id) + if (data) data.useDebug(null) + return data + } +} \ No newline at end of file diff --git a/src/core/api/modules/flag.ts b/src/core/api/modules/flag.ts new file mode 100644 index 0000000..1b8a9cd --- /dev/null +++ b/src/core/api/modules/flag.ts @@ -0,0 +1,73 @@ +/////////////////////////////////////// +//FLAG MODULE +/////////////////////////////////////// +import { ODId, ODValidId, ODManager, ODManagerData } from "./base" +import { ODDebugger } from "./console" + +/**## ODFlag `class` + * This is an open ticket flag. + * + * A flag is a boolean that can be specified by a parameter in the console. + * It's useful for small settings that are only required once in a while. + * + * Flags can also be enabled manually by plugins! + */ +export class ODFlag extends ODManagerData { + /**The method that has been used to set the value of this flag. (`null` when not set) */ + method: "param"|"manual"|null = null + /**The name of this flag. Visible to the user. */ + name: string + /**The description of this flag. Visible to the user. */ + description: string + /**The name of the parameter in the console. (e.g. `--test`) */ + param: string + /**A list of aliases for the parameter in the console. */ + aliases: string[] + /**The value of this flag. */ + value: boolean = false + + constructor(id:ODValidId, name:string, description:string, param:string, aliases?:string[], initialValue?:boolean){ + super(id) + this.name = name + this.description = description + this.param = param + this.aliases = aliases ?? [] + this.value = initialValue ?? false + } + + /**Set the value of this flag. */ + setValue(value:boolean,method?:"param"|"manual"){ + this.value = value + this.method = method ?? "manual" + } + /**Detect if the process contains the param or aliases & set the value. Use `force` to overwrite a manually set value. */ + detectProcessParams(force?:boolean){ + if (force){ + const params = [this.param,...this.aliases] + this.setValue(params.some((p) => process.argv.includes(p)),"param") + + }else if (this.method != "manual"){ + const params = [this.param,...this.aliases] + this.setValue(params.some((p) => process.argv.includes(p)),"param") + } + } +} + +/**## ODFlagManager `class` + * This is an open ticket flag manager. + * + * This class is responsible for managing & initiating all flags of the bot. + * It also contains a shortcut for initiating all flags. + */ +export class ODFlagManager extends ODManager { + constructor(debug:ODDebugger){ + super(debug,"flag") + } + + /**Set all flags to their `process.argv` value. */ + init(){ + this.getAll().forEach((flag) => { + flag.detectProcessParams(false) + }) + } +} \ No newline at end of file diff --git a/src/core/api/modules/helpmenu.ts b/src/core/api/modules/helpmenu.ts new file mode 100644 index 0000000..8d2ad57 --- /dev/null +++ b/src/core/api/modules/helpmenu.ts @@ -0,0 +1,216 @@ +/////////////////////////////////////// +//HELP MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODValidId } from "./base" +import { ODDebugger } from "./console" + +/**## ODHelpMenuComponentRenderer `type` + * This is the callback of the help menu component renderer. It also contains information about how & where it is rendered. + */ +export type ODHelpMenuComponentRenderer = (page:number, category:number, location:number, mode:"slash"|"text") => string|Promise + +/**## ODHelpMenuComponent `class` + * This is an open ticket help menu component. + * + * It can render something on the Open Ticket help menu. + */ +export class ODHelpMenuComponent extends ODManagerData { + /**The priority of this component. The higher, the earlier it will appear in the help menu. */ + priority: number + /**The render function for this component. */ + render: ODHelpMenuComponentRenderer + + constructor(id:ODValidId, priority:number, render:ODHelpMenuComponentRenderer){ + super(id) + this.priority = priority + this.render = render + } +} + +/**## ODHelpMenuTextComponent `class` + * This is an open ticket help menu text component. + * + * It can render a static piece of text on the Open Ticket help menu. + */ +export class ODHelpMenuTextComponent extends ODHelpMenuComponent { + constructor(id:ODValidId, priority:number, text:string){ + super(id,priority,() => { + return text + }) + } +} + +/**## ODHelpMenuCommandComponentOption `interface` + * This interface contains a command option for the `ODHelpMenuCommandComponent`. + */ +export interface ODHelpMenuCommandComponentOption { + /**The name of this option. */ + name:string, + /**Is this option optional? */ + optional:boolean +} + +/**## ODHelpMenuCommandComponentSettings `interface` + * This interface contains the settings for the `ODHelpMenuCommandComponent`. + */ +export interface ODHelpMenuCommandComponentSettings { + /**The name of this text command. */ + textName?:string, + /**The name of this slash command. */ + slashName?:string, + /**Options available in the text command. */ + textOptions?:ODHelpMenuCommandComponentOption[], + /**Options available in the slash command. */ + slashOptions?:ODHelpMenuCommandComponentOption[], + /**The description for the text command. */ + textDescription?:string, + /**The description for the slash command. */ + slashDescription?:string +} + +/**## ODHelpMenuCommandComponent `class` + * This is an open ticket help menu command component. + * + * It contains a useful helper to render a command in the Open Ticket help menu. + */ +export class ODHelpMenuCommandComponent extends ODHelpMenuComponent { + constructor(id:ODValidId, priority:number, settings:ODHelpMenuCommandComponentSettings){ + super(id,priority,(page,category,location,mode) => { + if (mode == "slash" && settings.slashName){ + return `\`${settings.slashName}${(settings.slashOptions) ? this.#renderOptions(settings.slashOptions) : ""}\` ➜ ${settings.slashDescription ?? ""}` + + }else if (mode == "text" && settings.textName){ + return `\`${settings.textName}${(settings.textOptions) ? this.#renderOptions(settings.textOptions) : ""}\` ➜ ${settings.textDescription ?? ""}` + + }else return "" + }) + } + + /**Utility function to render all command options. */ + #renderOptions(options:ODHelpMenuCommandComponentOption[]){ + return " "+options.map((opt) => (opt.optional) ? `[${opt.name}]` : `<${opt.name}>`).join(" ") + } +} + +/**## ODHelpMenuCategory `class` + * This is an open ticket help menu category. + * + * Every category in the help menu is an embed field by default. + * Try to limit the amount of components per category. + */ +export class ODHelpMenuCategory extends ODManager { + /**The id of this category. */ + id: ODId + /**The priority of this category. The higher, the earlier it will appear in the menu. */ + priority: number + /**The name of this category. (can include emoji's) */ + name: string + /**When enabled, it automatically starts this category on a new page. */ + newPage: boolean + + constructor(id:ODValidId, priority:number, name:string, newPage?:boolean){ + super() + this.id = new ODId(id) + this.priority = priority + this.name = name + this.newPage = newPage ?? false + } + + /**Render this category and it's components. */ + async render(page:number, category:number, mode:"slash"|"text"){ + //sort from high priority to low + const derefArray = [...this.getAll()] + derefArray.sort((a,b) => { + return b.priority-a.priority + }) + const result: string[] = [] + + let i = 0 + for (const component of derefArray){ + try { + result.push(await component.render(page,category,i,mode)) + }catch(err){ + process.emit("uncaughtException",err) + } + i++ + } + + //only return the non-empty components + return result.filter((component) => component !== "").join("\n\n") + } +} + +/**## ODHelpMenuRenderResult `type` + * This is the array returned when the help menu has been rendered succesfully. + * + * It contains a list of pages, which contain categories by name & value (content). + */ +export type ODHelpMenuRenderResult = {name:string, value:string}[][] + +/**## ODHelpMenuManager `class` + * This is an open ticket help menu manager. + * + * It is responsible for rendering the entire help menu content. + * You are also able to configure the amount of categories per page here. + * + * Fewer Categories == More Clean Menu + */ +export class ODHelpMenuManager extends ODManager { + /**Alias to open ticket debugger. */ + #debug: ODDebugger + /**The amount of categories per-page. */ + categoriesPerPage: number = 3 + + constructor(debug:ODDebugger){ + super(debug,"help menu category") + this.#debug = debug + } + + add(data:ODHelpMenuCategory, overwrite?:boolean): boolean { + data.useDebug(this.#debug,"help menu component") + return super.add(data,overwrite) + } + + /**Render this entire help menu & return a `ODHelpMenuRenderResult`. */ + async render(mode:"slash"|"text"): Promise { + //sort from high priority to low + const derefArray = [...this.getAll()] + derefArray.sort((a,b) => { + return b.priority-a.priority + }) + const result: {name:string, value:string}[][] = [] + let currentPage: {name:string, value:string}[] = [] + + for (const category of derefArray){ + try { + const renderedCategory = await category.render(result.length,currentPage.length,mode) + + if (renderedCategory !== ""){ + //create new page when category wants to + if (currentPage.length > 0 && category.newPage){ + result.push(currentPage) + currentPage = [] + } + + currentPage.push({ + name:category.name, + value:renderedCategory + }) + + //create new page when page is full + if (currentPage.length >= this.categoriesPerPage){ + result.push(currentPage) + currentPage = [] + } + } + }catch(err){ + process.emit("uncaughtException",err) + } + } + + //push current page when not-empty + if (currentPage.length > 0) result.push(currentPage) + + return result + } +} \ No newline at end of file diff --git a/src/core/api/modules/language.ts b/src/core/api/modules/language.ts new file mode 100644 index 0000000..806c99e --- /dev/null +++ b/src/core/api/modules/language.ts @@ -0,0 +1,107 @@ +/////////////////////////////////////// +//LANGUAGE MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base" +import nodepath from "path" +import { ODDebugger } from "./console" + +export class ODLanguage extends ODManagerData { + file: string + data: any + metadata: { + otversion:string, + language:string, + translator:string, + lastedited:string + }|null = null + + constructor(id:ODValidId, file:string, customPath?:string){ + super(id) + this.file = file + try{ + const filename = (file.endsWith(".json")) ? file : file+".json" + this.data = customPath ? require(nodepath.join("../../../../",customPath,filename)) : require(nodepath.join("../../../../languages",filename)) + }catch{ + throw new ODSystemError("[API ERROR] Language \""+file+"\" doesn't exist!") + } + if (this.data["_TRANSLATION"]) this.metadata = this.data["_TRANSLATION"] + } +} + +export class ODLanguageManager extends ODManager { + current: ODLanguage|null = null + backup: ODLanguage|null = null + + constructor(debug:ODDebugger, presets:boolean){ + super(debug,"language") + if (presets) this.add(new ODLanguage("english","english.json")) + this.current = presets ? new ODLanguage("english","english.json") : null + this.backup = presets ? new ODLanguage("english","english.json") : null + } + + setCurrentLanguage(id:ODValidId){ + this.current = this.get(id) + } + getCurrentLanguage(){ + return (this.current) ? this.current : null + } + setBackupLanguage(id:ODValidId){ + this.backup = this.get(id) + } + getBackupLanguage(){ + return (this.backup) ? this.backup : null + } + getLanguageMetadata(frombackup?:boolean){ + if (frombackup) return (this.backup) ? this.backup.metadata : null + return (this.current) ? this.current.metadata : null + } + getCurrentLanguageId(){ + return (this.current) ? this.current.id.value : "" + } + getTranslation(id:string): string|null { + if (!this.current) return this.#getBackupTranslation(id) + + const splitted = id.split(".") + let currentObject = this.current.data + let result: string|false = false + splitted.forEach((id) => { + if (typeof currentObject[id] == "object"){ + currentObject = currentObject[id] + }else if (typeof currentObject[id] == "string"){ + result = currentObject[id] + } + }) + + if (typeof result == "string") return result + else return this.#getBackupTranslation(id) + } + + #getBackupTranslation(id:string): string|null { + if (!this.backup) return null + + const splitted = id.split(".") + let currentObject = this.backup.data + let result: string|false = false + splitted.forEach((id) => { + if (typeof currentObject[id] == "object"){ + currentObject = currentObject[id] + }else if (typeof currentObject[id] == "string"){ + result = currentObject[id] + } + }) + + if (typeof result == "string") return result + else return null + } + + getTranslationWithParams(id:string, params:string[]): string|null { + let translation = this.getTranslation(id) + if (!translation) return translation + + params.forEach((value,index) => { + if (!translation) return + translation = translation.replace(`{${index}}`,value) + }) + return translation + } +} \ No newline at end of file diff --git a/src/core/api/modules/permission.ts b/src/core/api/modules/permission.ts new file mode 100644 index 0000000..d46921b --- /dev/null +++ b/src/core/api/modules/permission.ts @@ -0,0 +1,211 @@ +/////////////////////////////////////// +//PERMISSION MODULE +/////////////////////////////////////// +import { ODId, ODValidId, ODManager, ODSystemError, ODManagerData } from "./base" +import * as discord from "discord.js" +import { ODDebugger } from "./console" + +export type ODPermissionType = "member"|"support"|"moderator"|"admin"|"owner"|"developer" +export type ODPermissionScope = "global-user"|"channel-user"|"global-role"|"channel-role" +export interface ODPermissionResult { + type:ODPermissionType + scope:ODPermissionScope|"default" + level:ODPermissionLevel, + source:ODPermission|null +} + +export enum ODPermissionLevel { + member, + support, + moderator, + admin, + owner, + developer +} + +export class ODPermission extends ODManagerData { + readonly scope: ODPermissionScope + readonly permission: ODPermissionType + readonly value: discord.Role|discord.User + readonly channel: discord.Channel|null + + constructor(id:ODValidId, scope:"global-user", permission:ODPermissionType, value:discord.User) + constructor(id:ODValidId, scope:"global-role", permission:ODPermissionType, value:discord.Role) + constructor(id:ODValidId, scope:"channel-user", permission:ODPermissionType, value:discord.User, channel:discord.Channel) + constructor(id:ODValidId, scope:"channel-role", permission:ODPermissionType, value:discord.Role, channel:discord.Channel) + constructor(id:ODValidId, scope:ODPermissionScope, permission:ODPermissionType, value:discord.Role|discord.User, channel?:discord.Channel){ + super(id) + this.scope = scope + this.permission = permission + this.value = value + this.channel = channel ?? null + } +} + +export interface ODPermissionSettings { + allowGlobalUserScope?:boolean, + allowGlobalRoleScope?:boolean, + allowChannelUserScope?:boolean, + allowChannelRoleScope?:boolean, + idRegex?:RegExp +} + +export type ODPermissionCalculationCallback = (user:discord.User, channel?:discord.Channel|null, guild?:discord.Guild|null, settings?:ODPermissionSettings|null) => Promise + +export class ODPermissionManager extends ODManager { + #calculation: ODPermissionCalculationCallback|null + defaultResult: ODPermissionResult = { + level:ODPermissionLevel["member"], + scope:"default", + type:"member", + source:null + } + + constructor(debug:ODDebugger, useDefaultCalculation?:boolean){ + super(debug,"permission") + this.#calculation = useDefaultCalculation ? this.#defaultCalculation : null + } + + setCalculation(calculation:ODPermissionCalculationCallback){ + this.#calculation = calculation + } + setDefaultResult(result:ODPermissionResult){ + this.defaultResult = result + } + getPermissions(user:discord.User, channel?:discord.Channel|null, guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise { + try{ + if (!this.#calculation) throw new ODSystemError("ODPermissionManager:getPermissions() => missing perms calculation") + return this.#calculation(user,channel,guild,settings) + }catch(err){ + process.emit("uncaughtException",err) + throw new ODSystemError("ODPermissionManager:getPermissions() => failed perms calculation") + } + } + hasPermissions(minimum:ODPermissionType, data:ODPermissionResult){ + if (minimum == "member") return true + else if (minimum == "support") return (data.level >= ODPermissionLevel["support"]) + else if (minimum == "moderator") return (data.level >= ODPermissionLevel["moderator"]) + else if (minimum == "admin") return (data.level >= ODPermissionLevel["admin"]) + else if (minimum == "owner") return (data.level >= ODPermissionLevel["owner"]) + else if (minimum == "developer") return (data.level >= ODPermissionLevel["developer"]) + else throw new ODSystemError("Invalid minimum permission type at ODPermissionManager.hasPermissions()") + } + async #defaultCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise { + const idRegex = (settings && typeof settings.idRegex != "undefined") ? settings.idRegex : null + const allowChannelUserScope = (settings && typeof settings.allowChannelUserScope != "undefined") ? settings.allowChannelUserScope : true + const allowChannelRoleScope = (settings && typeof settings.allowChannelRoleScope != "undefined") ? settings.allowChannelRoleScope : true + const allowGlobalUserScope = (settings && typeof settings.allowGlobalUserScope != "undefined") ? settings.allowGlobalUserScope : true + const allowGlobalRoleScope = (settings && typeof settings.allowGlobalRoleScope != "undefined") ? settings.allowGlobalRoleScope : true + + if (guild && channel && !channel.isDMBased()){ + //check for channel user permissions + if (allowChannelUserScope){ + const users = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "channel-user" && permission.channel && (permission.channel.id == channel.id) && (permission.value instanceof discord.User) && permission.value.id == user.id) + + if (users.length > 0){ + //sort all permisions from highest to lowest + users.sort((a,b) => { + const levelA = ODPermissionLevel[a.permission] + const levelB = ODPermissionLevel[b.permission] + + if (levelB > levelA) return 1 + else if (levelA > levelB) return -1 + else return 0 + }) + + return { + type:users[0].permission, + scope:"channel-user", + level:ODPermissionLevel[users[0].permission], + source:users[0] ?? null + } + } + } + + //check for channel role permissions + if (allowChannelRoleScope){ + const member = await guild.members.fetch(user.id) + if (member){ + const memberRoles = member.roles.cache.map((role) => role.id) + const roles = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "channel-role" && permission.channel && (permission.channel.id == channel.id) && (permission.value instanceof discord.Role) && memberRoles.includes(permission.value.id) && permission.value.guild.id == guild.id) + + if (roles.length > 0){ + //sort all permisions from highest to lowest + roles.sort((a,b) => { + const levelA = ODPermissionLevel[a.permission] + const levelB = ODPermissionLevel[b.permission] + + if (levelB > levelA) return 1 + else if (levelA > levelB) return -1 + else return 0 + }) + + return { + type:roles[0].permission, + scope:"channel-role", + level:ODPermissionLevel[roles[0].permission], + source:roles[0] ?? null + } + } + } + } + } + + //check for global user permissions + if (allowGlobalUserScope){ + const users = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "global-user" && (permission.value instanceof discord.User) && permission.value.id == user.id) + + if (users.length > 0){ + //sort all permisions from highest to lowest + users.sort((a,b) => { + const levelA = ODPermissionLevel[a.permission] + const levelB = ODPermissionLevel[b.permission] + + if (levelB > levelA) return 1 + else if (levelA > levelB) return -1 + else return 0 + }) + + return { + type:users[0].permission, + scope:"global-user", + level:ODPermissionLevel[users[0].permission], + source:users[0] ?? null + } + } + } + + //check for global role permissions + if (allowGlobalRoleScope){ + if (guild){ + const member = await guild.members.fetch(user.id) + if (member){ + const memberRoles = member.roles.cache.map((role) => role.id) + const roles = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "global-role" && (permission.value instanceof discord.Role) && memberRoles.includes(permission.value.id) && permission.value.guild.id == guild.id) + + if (roles.length > 0){ + //sort all permisions from highest to lowest + roles.sort((a,b) => { + const levelA = ODPermissionLevel[a.permission] + const levelB = ODPermissionLevel[b.permission] + + if (levelB > levelA) return 1 + else if (levelA > levelB) return -1 + else return 0 + }) + + return { + type:roles[0].permission, + scope:"global-role", + level:ODPermissionLevel[roles[0].permission], + source:roles[0] ?? null + } + } + } + } + } + + //spread result to prevent accidental referencing + return {...this.defaultResult} + } +} \ No newline at end of file diff --git a/src/core/api/modules/plugin.ts b/src/core/api/modules/plugin.ts new file mode 100644 index 0000000..fc17aaa --- /dev/null +++ b/src/core/api/modules/plugin.ts @@ -0,0 +1,233 @@ +/////////////////////////////////////// +//PLUGIN MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId, ODVersion } from "./base" +import nodepath from "path" +import { ODConsolePluginMessage, ODConsoleWarningMessage, ODDebugger } from "./console" + +export interface ODUnknownCrashedPlugin { + name:string, + description:string +} + +export class ODPluginManager extends ODManager { + events: ODPluginEventManager + classes: ODPluginClassManager + unknownCrashedPlugins: ODUnknownCrashedPlugin[] = [] + + constructor(debug:ODDebugger){ + super(debug,"plugin") + this.events = new ODPluginEventManager(debug) + this.classes = new ODPluginClassManager(debug) + } + + /**Check if a plugin has loaded successfully.*/ + isPluginLoaded(id:ODValidId){ + const newId = new ODId(id) + const plugin = this.get(newId) + return (plugin && plugin.executed) + } +} + +export interface ODPluginData { + name:string, + id:string, + version:string, + startFile:string, + + enabled:boolean, + priority:number, + events:string[] + + npmDependencies:string[], + requiredPlugins:string[], + incompatiblePlugins:string[], + + details:ODPluginDetails +} + +export interface ODPluginDetails { + author:string, + shortDescription:string, + longDescription:string, + imageUrl:string, + projectUrl:string, + tags:string[] +} + +export class ODPlugin extends ODManagerData { + dir: string + data: ODPluginData + name: string + priority: number + version: ODVersion + details: ODPluginDetails + + enabled: boolean + executed: boolean + crashed: boolean + crashReason: null|"incompatible.plugin"|"missing.plugin"|"missing.dependency"|"executed" = null + + constructor(dir:string, jsondata:ODPluginData){ + super(jsondata.id) + this.dir = dir + this.data = jsondata + this.name = jsondata.name + this.priority = jsondata.priority + this.version = ODVersion.fromString("plugin",jsondata.version) + this.details = jsondata.details + + this.enabled = jsondata.enabled + this.executed = false + this.crashed = false + } + + //Get the startfile location relative to the ./plugins/ directory + getStartFile(){ + return nodepath.join(this.dir,this.data.startFile) + } + /**Execute this plugin. Returns `false` on crash. */ + async execute(debug:ODDebugger,force?:boolean): Promise { + if ((this.enabled && !this.crashed) || force){ + try{ + await require(nodepath.join("../../../../plugins/",this.getStartFile())) + debug.console.log("Plugin \""+this.id.value+"\" loaded successfully!","plugin") + this.executed = true + return true + }catch(error){ + this.crashed = true + this.crashReason = "executed" + + debug.console.log(error.message+", canceling plugin execution...","plugin",[ + {key:"path",value:"./plugins/"+this.dir} + ]) + debug.console.log("You can see more about this error in the ./otdebug.txt file!","info") + debug.console.debugfile.writeText(error.stack) + + return false + } + }else return true + } + + #checkDependency(id:string){ + try{ + require.resolve(id) + return true + }catch{ + return false + } + } + + dependenciesInstalled(){ + const missing: string[] = [] + this.data.npmDependencies.forEach((d) => { + if (!this.#checkDependency(d)){ + missing.push(d) + } + }) + + return missing + } + pluginsInstalled(manager:ODPluginManager){ + const missing: string[] = [] + this.data.requiredPlugins.forEach((p) => { + const plugin = manager.get(p) + if (!plugin || !plugin.enabled){ + missing.push(p) + } + }) + + return missing + } +} + +export class ODPluginEvent extends ODManagerData { + listeners: Function[] = [] + oncelisteners: Function[] = [] + + getCurrentListeners(){ + const final: Function[] = [] + this.oncelisteners.forEach((l) => final.push(l)) + this.listeners.forEach((l) => final.push(l)) + + this.oncelisteners = [] + return final + } +} + +export class ODPluginEventManager extends ODManager { + #debug: ODDebugger + listenerLimit: number = 25 + + constructor(debug:ODDebugger){ + super(debug,"plugin event") + this.#debug = debug + } + + setListenerLimit(limit:number){ + this.listenerLimit = limit + } + + on(event:string, callback:Function){ + const eventdata = this.get(event) + if (eventdata){ + eventdata.listeners.push(callback) + + if (eventdata.listeners.length > this.listenerLimit){ + this.#debug.console.log(new ODConsoleWarningMessage("Possible plugin event memory leak detected!",[ + {key:"event",value:event}, + {key:"listeners",value:eventdata.listeners.length.toString()} + ])) + } + }else{ + throw new ODSystemError("unknown plugin event \""+event+"\"") + } + } + + once(event:string, callback:Function){ + const eventdata = this.get(event) + if (eventdata){ + eventdata.oncelisteners.push(callback) + + }else{ + throw new ODSystemError("unknown plugin event \""+event+"\"") + } + } + + wait(event:string): Promise { + return new Promise((resolve,reject) => { + const eventdata = this.get(event) + if (eventdata){ + eventdata.oncelisteners.push((...args:any) => {resolve(args)}) + }else{ + reject("unknown plugin event \""+event+"\"") + } + }) + } + + emit(event:string, params:any[]): Promise { + return new Promise(async (resolve,reject) => { + const eventdata = this.get(event) + if (eventdata){ + const listeners = eventdata.getCurrentListeners() + + for (const listener of listeners){ + try { + await listener(...params) + }catch(err){ + process.emit("uncaughtException",err) + } + } + resolve() + }else{ + reject("unknown plugin event \""+event+"\"") + } + }) + } +} + +export class ODPluginClassManager extends ODManager { + constructor(debug:ODDebugger){ + super(debug,"plugin class") + } +} \ No newline at end of file diff --git a/src/core/api/modules/post.ts b/src/core/api/modules/post.ts new file mode 100644 index 0000000..de5b5f6 --- /dev/null +++ b/src/core/api/modules/post.ts @@ -0,0 +1,90 @@ +/////////////////////////////////////// +//POST MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODValidId } from "./base" +import { ODMessageBuildResult, ODMessageBuildSentResult } from "./builder" +import { ODDebugger } from "./console" +import * as discord from "discord.js" + +/**## ODPostManager `class` + * This is an open ticket post manager. + * + * It manages `ODPosts`'s for you. + * + * You will probably use this to get the logs channel of the bot (or some other static channel/category). + */ +export class ODPostManager extends ODManager> { + /**A reference to the main server of the bot */ + #guild: discord.Guild|null = null + + constructor(debug:ODDebugger){ + super(debug,"post") + } + + add(data:ODPost, overwrite?:boolean): boolean { + if (this.#guild) data.useGuild(this.#guild) + return super.add(data,overwrite) + } + /**Initialize the post manager & all posts. */ + async init(guild:discord.Guild){ + this.#guild = guild + for (const post of this.getAll()){ + post.useGuild(guild) + await post.init() + } + } +} + +/**## ODPost `class` + * This is an open ticket post class. + * + * A post is just a shortcut to a static discord channel or category. + * This can be used to get a specific channel over and over again! + * + * This class also contains utilities for sending messages via the Open Ticket builders. + */ +export class ODPost extends ODManagerData { + /**A reference to the main server of the bot */ + #guild: discord.Guild|null = null + /**Is this post already initialized? */ + ready: boolean = false + /**The discord.js channel */ + channel: ChannelType|null = null + /**The discord channel id */ + channelId: string + + constructor(id:ODValidId, channelId:string){ + super(id) + this.channelId = channelId + } + + /**Use a specific guild in this class for fetching the channel*/ + useGuild(guild:discord.Guild|null){ + this.#guild = guild + } + /**Change the channel id to another channel! */ + setChannelId(id:string){ + this.channelId = id + } + /**Initialize the discord.js channel of this post. */ + async init(){ + if (this.ready) return + if (!this.#guild) return this.channel = null + try{ + this.channel = await this.#guild.channels.fetch(this.channelId) as ChannelType + }catch{ + this.channel = null + } + this.ready = true + } + /**Send a message to this channel using the Open Ticket builder system */ + async send(msg:ODMessageBuildResult): Promise> { + if (!this.channel || !this.channel.isTextBased()) return {success:false,message:null} + try{ + const sent = await this.channel.send(msg.message) + return {success:true,message:sent} + }catch{ + return {success:false,message:null} + } + } +} \ No newline at end of file diff --git a/src/core/api/modules/responder.ts b/src/core/api/modules/responder.ts new file mode 100644 index 0000000..9749471 --- /dev/null +++ b/src/core/api/modules/responder.ts @@ -0,0 +1,884 @@ +/////////////////////////////////////// +//RESPONDER MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODValidId, ODSystemError, ODManagerData } from "./base" +import * as discord from "discord.js" +import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker" +import { ODDebugger } from "./console" +import { ODClientManager, ODSlashCommand, ODTextCommand, ODTextCommandInteractionOption } from "./client" +import { ODDropdownData, ODMessageBuildResult, ODMessageBuildSentResult, ODModalBuildResult } from "./builder" + +/**## ODResponderImplementation `class` + * This is an open ticket responder implementation. + * + * It is a basic implementation of the `ODWorkerManager` used by all `ODResponder` classes. + * + * This class can't be used stand-alone & needs to be extended from! + */ +export class ODResponderImplementation extends ODManagerData { + /**The manager that has all workers of this implementation */ + workers: ODWorkerManager + /**The `commandName` or `customId` needs to match this string or regex for this responder to be executed. */ + match: string|RegExp + + constructor(id:ODValidId, match:string|RegExp, callback?:ODWorkerCallback, priority?:number, callbackId?:ODValidId){ + super(id) + this.match = match + this.workers = new ODWorkerManager("descending") + if (callback) this.workers.add(new ODWorker(callbackId ? callbackId : id,priority ?? 0,callback)) + } + /**Execute all workers & return the result. */ + async respond(instance:Instance, source:Source, params:Params): Promise { + throw new ODSystemError("Tried to build an unimplemented ODResponderImplementation") + } +} + +export type ODResponderTimeoutErrorCallback = (instance:Instance, source:Source) => void|Promise + +export class ODResponderManager { + commands: ODCommandResponderManager + buttons: ODButtonResponderManager + dropdowns: ODDropdownResponderManager + modals: ODModalResponderManager + + constructor(debug:ODDebugger, client:ODClientManager){ + this.commands = new ODCommandResponderManager(debug,"command responder",client) + this.buttons = new ODButtonResponderManager(debug,"button responder",client) + this.dropdowns = new ODDropdownResponderManager(debug,"dropdown responder",client) + this.modals = new ODModalResponderManager(debug,"modal responder",client) + } +} + +export class ODCommandResponderManager extends ODManager> { + #client: ODClientManager + #timeoutErrorCallback: ODResponderTimeoutErrorCallback|null = null + #timeoutMs: number|null = null + + constructor(debug:ODDebugger, debugname:string, client:ODClientManager){ + super(debug,debugname) + this.#client = client + } + + /**Set the message to send when the response times out! */ + setTimeoutErrorCallback(callback:ODResponderTimeoutErrorCallback|null, ms:number|null){ + this.#timeoutErrorCallback = callback + this.#timeoutMs = ms + } + + add(data:ODCommandResponder<"slash"|"text",any>, overwrite?:boolean){ + const res = super.add(data,overwrite) + + //add the callback to the slash command manager + this.#client.slashCommands.onInteraction(data.match,(interaction,cmd) => { + const newData = this.get(data.id) + if (!newData) return + newData.respond(new ODCommandResponderInstance(interaction,cmd,this.#timeoutErrorCallback,this.#timeoutMs),"slash",{}) + }) + + //add the callback to the text command manager + this.#client.textCommands.onInteraction(data.prefix,data.match,(interaction,cmd,options) => { + const newData = this.get(data.id) + if (!newData) return + newData.respond(new ODCommandResponderInstance(interaction,cmd,this.#timeoutErrorCallback,this.#timeoutMs,options),"text",{}) + }) + + return res + } +} + +export class ODCommandResponderInstanceOptions { + #interaction:discord.ChatInputCommandInteraction|discord.Message + #cmd:ODSlashCommand|ODTextCommand + #options: ODTextCommandInteractionOption[] + + constructor(interaction:discord.ChatInputCommandInteraction|discord.Message, cmd:ODSlashCommand|ODTextCommand, options?:ODTextCommandInteractionOption[]){ + this.#interaction = interaction + this.#cmd = cmd + this.#options = options ?? [] + } + getString(name:string,required:true): string + getString(name:string,required:false): string|null + getString(name:string,required:boolean){ + if (this.#interaction instanceof discord.ChatInputCommandInteraction){ + try { + return this.#interaction.options.getString(name,required) + }catch{ + throw new ODSystemError("ODCommandResponderInstanceOptions:getString() slash command option not found!") + } + + }else if (this.#interaction instanceof discord.Message){ + const opt = this.#options.find((opt) => opt.type == "string" && opt.name == name) + if (opt && typeof opt.value == "string") return opt.value + else return null + + }else return null + } + getBoolean(name:string,required:true): boolean + getBoolean(name:string,required:false): boolean|null + getBoolean(name:string,required:boolean){ + if (this.#interaction instanceof discord.ChatInputCommandInteraction){ + try { + return this.#interaction.options.getBoolean(name,required) + }catch{ + throw new ODSystemError("ODCommandResponderInstanceOptions:getBoolean() slash command option not found!") + } + + }else if (this.#interaction instanceof discord.Message){ + const opt = this.#options.find((opt) => opt.type == "boolean" && opt.name == name) + if (opt && typeof opt.value == "boolean") return opt.value + else return null + + }else return null + } + getNumber(name:string,required:true): number + getNumber(name:string,required:false): number|null + getNumber(name:string,required:boolean){ + if (this.#interaction instanceof discord.ChatInputCommandInteraction){ + try { + return this.#interaction.options.getNumber(name,required) + }catch{ + throw new ODSystemError("ODCommandResponderInstanceOptions:getNumber() slash command option not found!") + } + + }else if (this.#interaction instanceof discord.Message){ + const opt = this.#options.find((opt) => opt.type == "number" && opt.name == name) + if (opt && typeof opt.value == "number") return opt.value + else return null + + }else return null + } + getChannel(name:string,required:true): discord.TextChannel|discord.VoiceChannel|discord.StageChannel|discord.NewsChannel|discord.MediaChannel|discord.ForumChannel|discord.CategoryChannel + getChannel(name:string,required:false): discord.TextChannel|discord.VoiceChannel|discord.StageChannel|discord.NewsChannel|discord.MediaChannel|discord.ForumChannel|discord.CategoryChannel|null + getChannel(name:string,required:boolean){ + if (this.#interaction instanceof discord.ChatInputCommandInteraction){ + try { + return this.#interaction.options.getChannel(name,required) + }catch{ + throw new ODSystemError("ODCommandResponderInstanceOptions:getChannel() slash command option not found!") + } + + }else if (this.#interaction instanceof discord.Message){ + const opt = this.#options.find((opt) => opt.type == "channel" && opt.name == name) + if (opt && (opt.value instanceof discord.TextChannel || opt.value instanceof discord.VoiceChannel || opt.value instanceof discord.StageChannel || opt.value instanceof discord.NewsChannel || opt.value instanceof discord.MediaChannel || opt.value instanceof discord.ForumChannel || opt.value instanceof discord.CategoryChannel)) return opt.value + else return null + + }else return null + } + getRole(name:string,required:true): discord.Role + getRole(name:string,required:false): discord.Role|null + getRole(name:string,required:boolean){ + if (this.#interaction instanceof discord.ChatInputCommandInteraction){ + try { + return this.#interaction.options.getRole(name,required) + }catch{ + throw new ODSystemError("ODCommandResponderInstanceOptions:getRole() slash command option not found!") + } + + }else if (this.#interaction instanceof discord.Message){ + const opt = this.#options.find((opt) => opt.type == "role" && opt.name == name) + if (opt && opt.value instanceof discord.Role) return opt.value + else return null + + }else return null + } + getUser(name:string,required:true): discord.User + getUser(name:string,required:false): discord.User|null + getUser(name:string,required:boolean){ + if (this.#interaction instanceof discord.ChatInputCommandInteraction){ + try { + return this.#interaction.options.getUser(name,required) + }catch{ + throw new ODSystemError("ODCommandResponderInstanceOptions:getUser() slash command option not found!") + } + + }else if (this.#interaction instanceof discord.Message){ + const opt = this.#options.find((opt) => opt.type == "user" && opt.name == name) + if (opt && opt.value instanceof discord.User) return opt.value + else return null + + }else return null + } + getGuildMember(name:string,required:true): discord.GuildMember + getGuildMember(name:string,required:false): discord.GuildMember|null + getGuildMember(name:string,required:boolean){ + if (this.#interaction instanceof discord.ChatInputCommandInteraction){ + try { + const member = this.#interaction.options.getMember(name) + if (!member && required) throw new ODSystemError("ODCommandResponderInstanceOptions:getGuildMember() slash command option not found!") + return member + }catch{ + throw new ODSystemError("ODCommandResponderInstanceOptions:getGuildMember() slash command option not found!") + } + + }else if (this.#interaction instanceof discord.Message){ + const opt = this.#options.find((opt) => opt.type == "guildmember" && opt.name == name) + if (opt && opt.value instanceof discord.GuildMember) return opt.value + else return null + + }else return null + } + getMentionable(name:string,required:true): discord.User|discord.Role + getMentionable(name:string,required:false): discord.User|discord.Role|null + getMentionable(name:string,required:boolean){ + if (this.#interaction instanceof discord.ChatInputCommandInteraction){ + try { + return this.#interaction.options.getMentionable(name,required) + }catch{ + throw new ODSystemError("ODCommandResponderInstanceOptions:getGuildMember() slash command option not found!") + } + + }else if (this.#interaction instanceof discord.Message){ + const opt = this.#options.find((opt) => opt.type == "mentionable" && opt.name == name) + if (opt && (opt.value instanceof discord.User || opt.value instanceof discord.Role)) return opt.value + else return null + + }else return null + } + getSubGroup(): string|null + getSubGroup(){ + if (this.#interaction instanceof discord.ChatInputCommandInteraction){ + try { + return this.#interaction.options.getSubcommandGroup(true) + }catch{ + throw new ODSystemError("ODCommandResponderInstanceOptions:getSubGroup() slash command option not found!") + } + + }else if (this.#interaction instanceof discord.Message && this.#cmd instanceof ODTextCommand){ + //0: name, 1:sub/group, 2:sub + const splittedName: string[] = this.#cmd.builder.name.split(" ") + return splittedName[1] ?? null + + }else return null + } + getSubCommand(): string|null + getSubCommand(){ + if (this.#interaction instanceof discord.ChatInputCommandInteraction){ + try { + return this.#interaction.options.getSubcommand(true) + }catch{ + throw new ODSystemError("ODCommandResponderInstanceOptions:getSubCommand() slash command option not found!") + } + + }else if (this.#interaction instanceof discord.Message && this.#cmd instanceof ODTextCommand){ + //0: name, 1:sub/group, 2:sub + const splittedName: string[] = this.#cmd.builder.name.split(" ") + + //return the second subcommand when there is a subgroup + if (splittedName.length > 2){ + return splittedName[2] ?? null + }else return splittedName[1] ?? null + + }else return null + } +} + +export class ODCommandResponderInstance { + interaction:discord.ChatInputCommandInteraction|discord.Message + cmd:ODSlashCommand|ODTextCommand + type: "message"|"interaction" + didReply: boolean = false + options: ODCommandResponderInstanceOptions + user: discord.User + member: discord.GuildMember|null + guild: discord.Guild|null + channel: discord.TextBasedChannel + + constructor(interaction:discord.ChatInputCommandInteraction|discord.Message, cmd:ODSlashCommand|ODTextCommand, errorCallback:ODResponderTimeoutErrorCallback|null, timeoutMs:number|null, options?:ODTextCommandInteractionOption[]){ + if (!interaction.channel) throw new ODSystemError("ODCommandResponderInstance: Unable to find interaction channel!") + this.interaction = interaction + this.cmd = cmd + this.type = (interaction instanceof discord.Message) ? "message" : "interaction" + this.options = new ODCommandResponderInstanceOptions(interaction,cmd,options) + this.user = (interaction instanceof discord.Message) ? interaction.author : interaction.user + this.member = (interaction.member instanceof discord.GuildMember) ? interaction.member : null + this.guild = interaction.guild + this.channel = interaction.channel + + + setTimeout(async () => { + if (!this.didReply){ + try { + if (!errorCallback){ + this.reply({id:new ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{ + content:":x: **Something went wrong while replying to this command!**" + }}) + }else{ + await errorCallback(this,(this.type == "interaction") ? "slash" : "text") + } + + }catch(err){ + process.emit("uncaughtException",err) + } + } + },timeoutMs ?? 2500) + } + + async reply(msg:ODMessageBuildResult): Promise> { + try { + if (this.type == "interaction" && this.interaction instanceof discord.ChatInputCommandInteraction){ + if (this.interaction.replied || this.interaction.deferred){ + const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:sent} + }else{ + const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:await sent.fetch()} + } + }else if (this.type == "message" && this.interaction instanceof discord.Message){ + const sent = await this.interaction.channel.send(msg.message) + this.didReply = true + return {success:true,message:sent} + }else return {success:false,message:null} + }catch{ + return {success:false,message:null} + } + } + async defer(ephemeral:boolean){ + if (this.type != "interaction" || !(this.interaction instanceof discord.ChatInputCommandInteraction)) return false + if (this.interaction.deferred) return false + await this.interaction.deferReply({ephemeral}) + this.didReply = true + return true + } + async modal(modal:ODModalBuildResult){ + if (this.type != "interaction" || !(this.interaction instanceof discord.ChatInputCommandInteraction)) return false + this.interaction.showModal(modal.modal) + this.didReply = true + return true + } +} + +export class ODCommandResponder extends ODResponderImplementation { + /**The prefix of the text command needs to match this */ + prefix: string + + constructor(id:ODValidId, prefix:string, match:string|RegExp, callback?:ODWorkerCallback, priority?:number, callbackId?:ODValidId){ + super(id,match,callback,priority,callbackId) + this.prefix = prefix + } + + /**Respond to this command */ + async respond(instance:ODCommandResponderInstance, source:Source, params:Params){ + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + } +} + +export class ODButtonResponderManager extends ODManager> { + #client: ODClientManager + #timeoutErrorCallback: ODResponderTimeoutErrorCallback|null = null + #timeoutMs: number|null = null + #listeners: ((interaction:discord.ButtonInteraction) => void)[] = [] + + constructor(debug:ODDebugger, debugname:string, client:ODClientManager){ + super(debug,debugname) + this.#client = client + + this.#client.client.on("interactionCreate",(interaction) => { + if (!interaction.isButton()) return + this.#listeners.forEach((cb) => cb(interaction)) + }) + } + + /**Set the message to send when the response times out! */ + setTimeoutErrorCallback(callback:ODResponderTimeoutErrorCallback|null, ms:number|null){ + this.#timeoutErrorCallback = callback + this.#timeoutMs = ms + } + + add(data:ODButtonResponder<"button",any>, overwrite?:boolean){ + const res = super.add(data,overwrite) + + this.#listeners.push((interaction) => { + const newData = this.get(data.id) + if (!newData) return + if ((typeof newData.match == "string") ? interaction.customId == newData.match : newData.match.test(interaction.customId)) newData.respond(new ODButtonResponderInstance(interaction,this.#timeoutErrorCallback,this.#timeoutMs),"button",{}) + }) + + return res + } +} + +export class ODButtonResponderInstance { + interaction:discord.ButtonInteraction + didReply: boolean = false + user: discord.User + member: discord.GuildMember|null + guild: discord.Guild|null + channel: discord.TextBasedChannel + message: discord.Message + + constructor(interaction:discord.ButtonInteraction, errorCallback:ODResponderTimeoutErrorCallback|null, timeoutMs:number|null){ + if (!interaction.channel) throw new ODSystemError("ODButtonResponderInstance: Unable to find interaction channel!") + this.interaction = interaction + this.user = interaction.user + this.member = (interaction.member instanceof discord.GuildMember) ? interaction.member : null + this.guild = interaction.guild + this.channel = interaction.channel + this.message = interaction.message + + setTimeout(async () => { + if (!this.didReply){ + try { + if (!errorCallback){ + this.reply({id:new ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{ + content:":x: **Something went wrong while replying to this button!**" + }}) + }else{ + await errorCallback(this,"button") + } + + }catch(err){ + process.emit("uncaughtException",err) + } + } + },timeoutMs ?? 2500) + } + + async reply(msg:ODMessageBuildResult): Promise> { + try{ + if (this.interaction.replied || this.interaction.deferred){ + const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:sent} + }else{ + const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:await sent.fetch()} + } + }catch{ + return {success:false,message:null} + } + } + async update(msg:ODMessageBuildResult): Promise> { + try{ + if (this.interaction.replied || this.interaction.deferred){ + const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:await sent.fetch()} + }else{ + const sent = await this.interaction.update(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:await sent.fetch()} + } + }catch{ + return {success:false,message:null} + } + } + async defer(type:"reply"|"update", ephemeral:boolean){ + if (this.interaction.deferred) return false + if (type == "reply"){ + await this.interaction.deferReply({ephemeral}) + }else{ + await this.interaction.deferUpdate() + } + this.didReply = true + return true + } + async modal(modal:ODModalBuildResult){ + this.interaction.showModal(modal.modal) + this.didReply = true + return true + } + + getMessageComponent(type:"button",id:string|RegExp): discord.ButtonComponent|null + getMessageComponent(type:"string-dropdown",id:string|RegExp): discord.StringSelectMenuComponent|null + getMessageComponent(type:"user-dropdown",id:string|RegExp): discord.UserSelectMenuComponent|null + getMessageComponent(type:"channel-dropdown",id:string|RegExp): discord.ChannelSelectMenuComponent|null + getMessageComponent(type:"role-dropdown",id:string|RegExp): discord.RoleSelectMenuComponent|null + getMessageComponent(type:"mentionable-dropdown",id:string|RegExp): discord.MentionableSelectMenuComponent|null + + 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) => { + 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 + else if (type == "user-dropdown" && component.type == discord.ComponentType.UserSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component + else if (type == "channel-dropdown" && component.type == discord.ComponentType.ChannelSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component + else if (type == "role-dropdown" && component.type == discord.ComponentType.RoleSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component + else if (type == "mentionable-dropdown" && component.type == discord.ComponentType.MentionableSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component + }) + }) + + return result + } + + getMessageEmbed(): discord.Embed|null { + return this.message.embeds[0] ?? null + } +} + +export class ODButtonResponder extends ODResponderImplementation { + /**Respond to this button */ + async respond(instance:ODButtonResponderInstance, source:Source, params:Params){ + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + } +} + +export class ODDropdownResponderManager extends ODManager> { + #client: ODClientManager + #timeoutErrorCallback: ODResponderTimeoutErrorCallback|null = null + #timeoutMs: number|null = null + #listeners: ((interaction:discord.AnySelectMenuInteraction) => void)[] = [] + + constructor(debug:ODDebugger, debugname:string, client:ODClientManager){ + super(debug,debugname) + this.#client = client + + this.#client.client.on("interactionCreate",(interaction) => { + if (!interaction.isAnySelectMenu()) return + this.#listeners.forEach((cb) => cb(interaction)) + }) + } + + /**Set the message to send when the response times out! */ + setTimeoutErrorCallback(callback:ODResponderTimeoutErrorCallback|null, ms:number|null){ + this.#timeoutErrorCallback = callback + this.#timeoutMs = ms + } + + add(data:ODDropdownResponder<"dropdown",any>, overwrite?:boolean){ + const res = super.add(data,overwrite) + + this.#listeners.push((interaction) => { + const newData = this.get(data.id) + if (!newData) return + if ((typeof newData.match == "string") ? interaction.customId == newData.match : newData.match.test(interaction.customId)) newData.respond(new ODDropdownResponderInstance(interaction,this.#timeoutErrorCallback,this.#timeoutMs),"dropdown",{}) + }) + + return res + } +} + +export class ODDropdownResponderInstanceValues { + #interaction:discord.AnySelectMenuInteraction + #type: ODDropdownData["type"] + + constructor(interaction:discord.AnySelectMenuInteraction, type:ODDropdownData["type"]){ + this.#interaction = interaction + this.#type = type + + if (interaction.isChannelSelectMenu()){ + interaction.values + } + } + getStringValues(): string[] { + try { + return this.#interaction.values + }catch{ + throw new ODSystemError("ODDropdownResponderInstanceValues:getStringValues() invalid values!") + } + } + async getRoleValues(): Promise { + if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getRoleValues() dropdown type isn't role!") + try { + const result: discord.Role[] = [] + for (const id of this.#interaction.values){ + if (!this.#interaction.guild) break + const role = await this.#interaction.guild.roles.fetch(id) + if (role) result.push(role) + } + return result + }catch{ + throw new ODSystemError("ODDropdownResponderInstanceValues:getRoleValues() invalid values!") + } + } + async getUserValues(): Promise { + if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getUserValues() dropdown type isn't user!") + try { + const result: discord.User[] = [] + for (const id of this.#interaction.values){ + const user = await this.#interaction.client.users.fetch(id) + if (user) result.push(user) + } + return result + }catch{ + throw new ODSystemError("ODDropdownResponderInstanceValues:getUserValues() invalid values!") + } + } + async getChannelValues(): Promise { + if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getChannelValues() dropdown type isn't channel!") + try { + const result: discord.GuildBasedChannel[] = [] + for (const id of this.#interaction.values){ + if (!this.#interaction.guild) break + const guild = await this.#interaction.guild.channels.fetch(id) + if (guild) result.push(guild) + } + return result + }catch{ + throw new ODSystemError("ODDropdownResponderInstanceValues:getChannelValues() invalid values!") + } + } +} + +export class ODDropdownResponderInstance { + interaction:discord.AnySelectMenuInteraction + didReply: boolean = false + type: ODDropdownData["type"] + values: ODDropdownResponderInstanceValues + user: discord.User + member: discord.GuildMember|null + guild: discord.Guild|null + channel: discord.TextBasedChannel + message: discord.Message + + constructor(interaction:discord.AnySelectMenuInteraction, errorCallback:ODResponderTimeoutErrorCallback|null, timeoutMs:number|null){ + if (!interaction.channel) throw new ODSystemError("ODDropdownResponderInstance: Unable to find interaction channel!") + this.interaction = interaction + if (interaction.isStringSelectMenu()){ + this.type = "string" + }else if (interaction.isRoleSelectMenu()){ + this.type = "role" + }else if (interaction.isUserSelectMenu()){ + this.type = "user" + }else if (interaction.isChannelSelectMenu()){ + this.type = "channel" + }else if (interaction.isMentionableSelectMenu()){ + this.type = "mentionable" + }else throw new ODSystemError("ODDropdownResponderInstance: invalid dropdown type!") + + this.values = new ODDropdownResponderInstanceValues(interaction,this.type) + this.user = interaction.user + this.member = (interaction.member instanceof discord.GuildMember) ? interaction.member : null + this.guild = interaction.guild + this.channel = interaction.channel + this.message = interaction.message + + setTimeout(async () => { + if (!this.didReply){ + try { + if (!errorCallback){ + this.reply({id:new ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{ + content:":x: **Something went wrong while replying to this dropdown!**" + }}) + }else{ + await errorCallback(this,"dropdown") + } + + }catch(err){ + process.emit("uncaughtException",err) + } + } + },timeoutMs ?? 2500) + } + + async reply(msg:ODMessageBuildResult): Promise> { + try { + if (this.interaction.replied || this.interaction.deferred){ + const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:sent} + }else{ + const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:await sent.fetch()} + } + }catch{ + return {success:false,message:null} + } + } + async update(msg:ODMessageBuildResult): Promise> { + try{ + if (this.interaction.replied || this.interaction.deferred){ + const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:await sent.fetch()} + }else{ + const sent = await this.interaction.update(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:await sent.fetch()} + } + }catch{ + return {success:false,message:null} + } + } + async defer(type:"reply"|"update", ephemeral:boolean){ + if (this.interaction.deferred) return false + if (type == "reply"){ + await this.interaction.deferReply({ephemeral}) + }else{ + await this.interaction.deferUpdate() + } + this.didReply = true + return true + } + async modal(modal:ODModalBuildResult){ + this.interaction.showModal(modal.modal) + this.didReply = true + return true + } + + getMessageComponent(type:"button",id:string|RegExp): discord.ButtonComponent|null + getMessageComponent(type:"string-dropdown",id:string|RegExp): discord.StringSelectMenuComponent|null + getMessageComponent(type:"user-dropdown",id:string|RegExp): discord.UserSelectMenuComponent|null + getMessageComponent(type:"channel-dropdown",id:string|RegExp): discord.ChannelSelectMenuComponent|null + getMessageComponent(type:"role-dropdown",id:string|RegExp): discord.RoleSelectMenuComponent|null + getMessageComponent(type:"mentionable-dropdown",id:string|RegExp): discord.MentionableSelectMenuComponent|null + + 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) => { + 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 + else if (type == "user-dropdown" && component.type == discord.ComponentType.UserSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component + else if (type == "channel-dropdown" && component.type == discord.ComponentType.ChannelSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component + else if (type == "role-dropdown" && component.type == discord.ComponentType.RoleSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component + else if (type == "mentionable-dropdown" && component.type == discord.ComponentType.MentionableSelect && component.customId && ((typeof id == "string") ? component.customId == id : id.test(component.customId))) result = component + }) + }) + + return result + } + + getMessageEmbed(): discord.Embed|null { + return this.message.embeds[0] ?? null + } +} + +export class ODDropdownResponder extends ODResponderImplementation { + /**Respond to this dropdown */ + async respond(instance:ODDropdownResponderInstance, source:Source, params:Params){ + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + } +} + +export class ODModalResponderManager extends ODManager> { + #client: ODClientManager + #timeoutErrorCallback: ODResponderTimeoutErrorCallback|null = null + #timeoutMs: number|null = null + #listeners: ((interaction:discord.ModalSubmitInteraction) => void)[] = [] + + constructor(debug:ODDebugger, debugname:string, client:ODClientManager){ + super(debug,debugname) + this.#client = client + + this.#client.client.on("interactionCreate",(interaction) => { + if (!interaction.isModalSubmit()) return + this.#listeners.forEach((cb) => cb(interaction)) + }) + } + + /**Set the message to send when the response times out! */ + setTimeoutErrorCallback(callback:ODResponderTimeoutErrorCallback|null, ms:number|null){ + this.#timeoutErrorCallback = callback + this.#timeoutMs = ms + } + + add(data:ODModalResponder<"modal",any>, overwrite?:boolean){ + const res = super.add(data,overwrite) + + this.#listeners.push((interaction) => { + const newData = this.get(data.id) + if (!newData) return + if ((typeof newData.match == "string") ? interaction.customId == newData.match : newData.match.test(interaction.customId)) newData.respond(new ODModalResponderInstance(interaction,this.#timeoutErrorCallback,this.#timeoutMs),"modal",{}) + }) + + return res + } +} + +export class ODModalResponderInstanceValues { + #interaction:discord.ModalSubmitInteraction + + constructor(interaction:discord.ModalSubmitInteraction){ + this.#interaction = interaction + } + getTextField(name:string,required:true): string + getTextField(name:string,required:false): string|null + getTextField(name:string,required:boolean){ + try { + const data = this.#interaction.fields.getField(name,discord.ComponentType.TextInput) + if (!data && required) throw new ODSystemError("ODModalResponderInstanceValues:getTextField() field not found!") + return (data) ? data.value : null + }catch{ + throw new ODSystemError("ODModalResponderInstanceValues:getTextField() field not found!") + } + } +} + +export class ODModalResponderInstance { + interaction:discord.ModalSubmitInteraction + didReply: boolean = false + values: ODModalResponderInstanceValues + user: discord.User + member: discord.GuildMember|null + guild: discord.Guild|null + channel: discord.TextBasedChannel|null + + constructor(interaction:discord.ModalSubmitInteraction, errorCallback:ODResponderTimeoutErrorCallback|null, timeoutMs:number|null){ + this.interaction = interaction + this.values = new ODModalResponderInstanceValues(interaction) + this.user = interaction.user + this.member = (interaction.member instanceof discord.GuildMember) ? interaction.member : null + this.guild = interaction.guild + this.channel = interaction.channel + + setTimeout(async () => { + if (!this.didReply){ + try { + if (!errorCallback){ + this.reply({id:new ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{ + content:":x: **Something went wrong while replying to this modal!**" + }}) + }else{ + await errorCallback(this,"modal") + } + + }catch(err){ + process.emit("uncaughtException",err) + } + } + },timeoutMs ?? 2500) + } + + async reply(msg:ODMessageBuildResult): Promise> { + try{ + if (this.interaction.replied || this.interaction.deferred){ + const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:sent} + }else{ + const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:await sent.fetch()} + } + }catch{ + return {success:false,message:null} + } + } + async update(msg:ODMessageBuildResult): Promise> { + try{ + if (this.interaction.replied || this.interaction.deferred){ + const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + this.didReply = true + return {success:true,message:await sent.fetch()} + }else throw new ODSystemError() + }catch{ + return {success:false,message:null} + } + } + async defer(type:"reply"|"update", ephemeral:boolean){ + if (this.interaction.deferred) return false + if (type == "reply"){ + await this.interaction.deferReply({ephemeral}) + }else{ + await this.interaction.deferUpdate() + } + this.didReply = true + return true + } +} + +export class ODModalResponder extends ODResponderImplementation { + /**Respond to this modal */ + async respond(instance:ODModalResponderInstance, source:Source, params:Params){ + //wait for workers to finish + await this.workers.executeWorkers(instance,source,params) + } +} \ No newline at end of file diff --git a/src/core/api/modules/session.ts b/src/core/api/modules/session.ts new file mode 100644 index 0000000..9aed68b --- /dev/null +++ b/src/core/api/modules/session.ts @@ -0,0 +1,155 @@ +/////////////////////////////////////// +//SESSION MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODValidId } from "./base" +import { ODDebugger } from "./console" +import * as crypto from "crypto" + +/**## ODSessionManager `class` + * This is an open ticket session manager. + * + * It contains all sessions in open ticket. Sessions are a sort of temporary storage which will be cleared when the bot stops. + * Data in sessions have a randomly generated key which will always be unique. + * + * Visit the `ODSession` class for more info + */ +export class ODSessionManager extends ODManager { + constructor(debug:ODDebugger){ + super(debug,"session") + } +} + +/**## ODSessionInstance `interface` + * This interface represents a single session instance. It contains an id, data & some dates. + */ +export interface ODSessionInstance { + /**The id of this session instance. */ + id:string, + /**The creation date of this session instance. */ + creation:number, + /**The custom amount of minutes before this session expires. */ + timeout:number|null, + /**This is the data from this session instance */ + data:any +} + +/**## ODSessionTimeoutCallback `type` + * This is the callback used for session timeout listeners. + */ +export type ODSessionTimeoutCallback = (id:string, timeout:"default"|"custom", data:any, creation:Date) => void + +/**## ODSession `class` + * This is an open ticket session. + * + * It can be used to create 100% unique id's for usage in the bot. An id can also store additional data which isn't saved to the filesystem. + * You can almost compare it to the PHP session system. + */ +export class ODSession extends ODManagerData { + /**The history of previously generated instance ids. Used to reduce the risk of generating the same id twice. */ + #idHistory: string[] = [] + /**The max length of the instance id history. */ + #maxIdHistoryLength: number = 500 + /**An array of all the currently active session instances. */ + sessions: ODSessionInstance[] = [] + /**The default amount of minutes before a session automatically stops. */ + timeoutMinutes: number = 30 + /**The id of the auto-timeout session checker interval */ + #intervalId: NodeJS.Timeout + /**Listeners for when a session times-out. */ + #timeoutListeners: ODSessionTimeoutCallback[] = [] + + constructor(id:ODValidId, intervalSeconds?:number){ + super(id) + + //create the auto-timeout session checker + this.#intervalId = setInterval(() => { + const deletableSessions: {instance:ODSessionInstance,reason:"default"|"custom"}[] = [] + + //collect all deletable sessions + this.sessions.forEach((session) => { + if (session.timeout && (new Date().getTime() - session.creation) > session.timeout*60000){ + //stop session => custom timeout + deletableSessions.push({instance:session,reason:"custom"}) + }else if (!session.timeout && (new Date().getTime() - session.creation) > this.timeoutMinutes*60000){ + //stop session => default timeout + deletableSessions.push({instance:session,reason:"default"}) + } + }) + + //permanently delete sessions + deletableSessions.forEach((session) => { + const index = this.sessions.findIndex((s) => s.id === session.instance.id) + this.sessions.splice(index,1) + + //emit timeout listeners + this.#timeoutListeners.forEach((cb) => cb(session.instance.id,session.reason,session.instance.data,new Date(session.instance.creation))) + }) + + },((intervalSeconds) ? (intervalSeconds * 1000) : 60000)) + } + + /**Create a unique hex id of 8 characters and add it to the instance id history */ + #createUniqueId(): string { + const hex = crypto.randomBytes(4).toString("hex") + if (this.#idHistory.includes(hex)){ + return this.#createUniqueId() + }else{ + this.#idHistory.push(hex) + if (this.#idHistory.length > this.#maxIdHistoryLength) this.#idHistory.shift() + return hex + } + } + /**Stop the global interval that automatically deletes timed-out sessions. (This action can't be reverted!) */ + stopAutoTimeout(){ + clearInterval(this.#intervalId) + } + + /**Start a session instance with data. Returns the unique id required to access the session. */ + start(data?:any): string { + const id = this.#createUniqueId() + this.sessions.push({ + id,data, + creation:new Date().getTime(), + timeout:null + }) + return id + } + /**Get the data of a session instance. Returns `null` when not found. */ + data(id:string): any|null { + const session = this.sessions.find((session) => session.id === id) + if (!session) return null + return session.data + } + /**Stop & delete a session instance. Returns `true` when sucessful. */ + stop(id:string): boolean { + const index = this.sessions.findIndex((session) => session.id === id) + if (index < 0) return false + this.sessions.splice(index,1) + return true + } + /**Update the data of a session instance. Returns `true` when sucessful. */ + update(id:string, data:any): boolean { + const session = this.sessions.find((session) => session.id === id) + if (!session) return false + session.data = data + return true + } + /**Change the global or session timeout minutes. Returns `true` when sucessful. */ + setTimeout(min:number, id?:string): boolean { + if (!id){ + //change global timeout minutes + this.timeoutMinutes = min + return true + }else{ + //change session instance timeout minutes + const session = this.sessions.find((session) => session.id === id) + if (!session) return false + session.timeout = min + return true + } + } + /**Listen for a session timeout (default or custom) */ + onTimeout(callback:ODSessionTimeoutCallback){ + this.#timeoutListeners.push(callback) + } +} \ No newline at end of file diff --git a/src/core/api/modules/startscreen.ts b/src/core/api/modules/startscreen.ts new file mode 100644 index 0000000..80c106d --- /dev/null +++ b/src/core/api/modules/startscreen.ts @@ -0,0 +1,219 @@ +/////////////////////////////////////// +//STARTSCREEN MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODValidId } from "./base" +import { ODDebugger, ODError, ODLiveStatusManager } from "./console" +import { ODFlag } from "./flag" +import { ODPlugin, ODUnknownCrashedPlugin } from "./plugin" +import ansis from "ansis" + +export type ODStartScreenComponentRenderCallback = (location:number) => string|Promise + +export class ODStartScreenManager extends ODManager { + /**Alias to the Open Ticket debugger. */ + #debug: ODDebugger + /**Alias to the livestatus manager. */ + livestatus: ODLiveStatusManager + + constructor(debug:ODDebugger,livestatus:ODLiveStatusManager){ + super(debug,"startscreen component") + this.#debug = debug + this.livestatus = livestatus + } + + /**Get all components in sorted order. */ + getSortedComponents(priority:"ascending"|"descending"){ + return this.getAll().sort((a,b) => { + if (priority == "ascending") return a.priority-b.priority + else return b.priority-a.priority + }) + } + /**Render all startscreen components in priority order. */ + async renderAllComponents(){ + const components = this.getSortedComponents("descending") + + let location = 0 + for (const component of components){ + try { + const renderedText = await component.renderAll(location) + console.log(renderedText) + this.#debug.console.debugfile.writeText("[STARTSCREEN] Component: \""+component.id+"\"\n"+ansis.strip(renderedText)) + }catch(e){ + this.#debug.console.log("Unable to render \""+component.id+"\" startscreen component!","error") + this.#debug.console.debugfile.writeErrorMessage(new ODError(e,"uncaughtException")) + } + location++ + } + } +} + +export class ODStartScreenComponent extends ODManagerData { + priority: number + renderBefore: ODStartScreenComponentRenderCallback|null = null + render: ODStartScreenComponentRenderCallback + renderAfter: ODStartScreenComponentRenderCallback|null = null + + constructor(id:ODValidId, priority:number, render:ODStartScreenComponentRenderCallback){ + super(id) + this.priority = priority + this.render = render + } + + async renderAll(location:number){ + const textBefore = (this.renderBefore) ? await this.renderBefore(location) : "" + const text = await this.render(location) + const textAfter = (this.renderAfter) ? await this.renderAfter(location) : "" + return (textBefore ? textBefore+"\n" : "")+text+(textAfter ? "\n"+textAfter : "") + } +} + +export interface ODStartScreenProperty { + key:string, + value:string +} + +export class ODStartScreenLogoComponent extends ODStartScreenComponent { + logo: string[] + topPadding: boolean + bottomPadding: boolean + logoHexColor: string + + constructor(id:ODValidId, priority:number, logo:string[], topPadding?:boolean, bottomPadding?:boolean, logoHexColor?:string){ + super(id,priority,() => { + const renderedTop = (this.topPadding ? "\n" : "") + const renderedLogo = this.logo.join("\n") + const renderedBottom = (this.bottomPadding ? "\n" : "") + return ansis.hex(this.logoHexColor)(renderedTop+renderedLogo+renderedBottom) + }) + this.logo = logo + this.topPadding = topPadding ?? false + this.bottomPadding = bottomPadding ?? false + this.logoHexColor = logoHexColor ?? "#f8ba00" + } +} + +export interface ODStartScreenHeaderAlignmentSettings { + align:"center"|"left"|"right", + width:number|ODStartScreenComponent +} + +export class ODStartScreenHeaderComponent extends ODStartScreenComponent { + properties: ODStartScreenProperty[] + spacer: string + align: ODStartScreenHeaderAlignmentSettings|null + + constructor(id:ODValidId, priority:number, properties:ODStartScreenProperty[], spacer?:string, align?:ODStartScreenHeaderAlignmentSettings){ + super(id,priority,async () => { + const renderedProperties = ansis.bold(this.properties.map((prop) => prop.key+": "+prop.value).join(this.spacer)) + if (!this.align || this.align.align == "left"){ + return renderedProperties + }else if (this.align.align == "right"){ + const width = (typeof this.align.width == "number") ? this.align.width : ( + ansis.strip(await this.align.width.renderAll(0)).split("\n").map((row) => row.length).reduce((prev,curr) => { + if (prev < curr) return curr + else return prev + },0) + ) + const offset = width - ansis.strip(renderedProperties).length + if (offset < 0) return renderedProperties + else{ + return (" ".repeat(offset) + renderedProperties) + } + }else if (this.align.align == "center"){ + const width = (typeof this.align.width == "number") ? this.align.width : ( + ansis.strip(await this.align.width.renderAll(0)).split("\n").map((row) => row.length).reduce((prev,curr) => { + if (prev < curr) return curr + else return prev + }) + ) + const offset = Math.round((width - ansis.strip(renderedProperties).length)/2) + if (offset < 0) return renderedProperties + else{ + return (" ".repeat(offset) + renderedProperties) + } + } + return renderedProperties + }) + this.properties = properties + this.spacer = spacer ?? " - " + this.align = align ?? null + } +} + +export class ODStartScreenCategoryComponent extends ODStartScreenComponent { + name: string + renderIfEmpty: boolean + + constructor(id:ODValidId, priority:number, name:string, render:ODStartScreenComponentRenderCallback, renderIfEmpty?:boolean){ + super(id,priority,async (location) => { + const contents = await render(location) + if (contents != "" || this.renderIfEmpty){ + return ansis.bold.underline("\n"+name.toUpperCase()+(contents != "" ? ":\n" : ":")) + contents + }else return "" + }) + this.name = name + this.renderIfEmpty = renderIfEmpty ?? true + } +} + +export class ODStartScreenPropertiesCategoryComponent extends ODStartScreenCategoryComponent { + properties: ODStartScreenProperty[] + propertyHexColor: string + + constructor(id:ODValidId, priority:number, name:string, properties:ODStartScreenProperty[], propertyHexColor?:string, renderIfEmpty?:boolean){ + super(id,priority,name,() => { + return this.properties.map((prop) => ansis.hex(this.propertyHexColor)(prop.key+": ")+prop.value).join("\n") + },renderIfEmpty) + + this.properties = properties + this.propertyHexColor = propertyHexColor ?? "#f8ba00" + } +} + +export class ODStartScreenFlagsCategoryComponent extends ODStartScreenCategoryComponent { + flags: ODFlag[] + + constructor(id:ODValidId, priority:number, flags:ODFlag[]){ + super(id,priority,"flags",() => { + return this.flags.filter((flag) => (flag.value == true)).map((flag) => ansis.blue("["+flag.name+"] "+flag.description)).join("\n") + },false) + this.flags = flags + } +} + +export class ODStartScreenPluginsCategoryComponent extends ODStartScreenCategoryComponent { + plugins: ODPlugin[] + unknownCrashedPlugins: ODUnknownCrashedPlugin[] + + constructor(id:ODValidId, priority:number, plugins:ODPlugin[], unknownCrashedPlugins:ODUnknownCrashedPlugin[]){ + super(id,priority,"plugins",() => { + const renderedPlugins = this.plugins.sort((a,b) => b.priority-a.priority).map((plugin) => { + if (plugin.enabled && plugin.executed) return ansis.green("✅ ["+plugin.name+"] "+plugin.details.shortDescription) + else if (plugin.enabled && plugin.crashed) return ansis.red("❌ ["+plugin.name+"] "+plugin.details.shortDescription) + else return ansis.gray("💤 ["+plugin.name+"] "+plugin.details.shortDescription) + }) + const renderedUnknownPlugins = unknownCrashedPlugins.map((plugin) => ansis.red("❌ ["+plugin.name+"] "+plugin.description)) + return [...renderedPlugins,...renderedUnknownPlugins].join("\n") + },false) + this.plugins = plugins + this.unknownCrashedPlugins = unknownCrashedPlugins + } +} + +export class ODStartScreenLiveStatusCategoryComponent extends ODStartScreenCategoryComponent { + livestatus: ODLiveStatusManager + + constructor(id:ODValidId, priority:number, livestatus:ODLiveStatusManager){ + super(id,priority,"livestatus",async () => { + const messages = await this.livestatus.getAllMessages() + return this.livestatus.renderer.render(messages) + },false) + this.livestatus = livestatus + } +} + +export class ODStartScreenLogCategoryComponent extends ODStartScreenCategoryComponent { + constructor(id:ODValidId, priority:number){ + super(id,priority,"logs",() => "",true) + } +} \ No newline at end of file diff --git a/src/core/api/modules/stat.ts b/src/core/api/modules/stat.ts new file mode 100644 index 0000000..3ca36e0 --- /dev/null +++ b/src/core/api/modules/stat.ts @@ -0,0 +1,212 @@ +/////////////////////////////////////// +//STAT MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base" +import { ODDebugger } from "./console" +import { ODDatabase, ODJsonDatabaseStructure } from "./database" +import * as discord from "discord.js" + +export type ODValidStatValue = string|number|boolean +export type ODStatsManagerInitCallback = (database:ODJsonDatabaseStructure, deletables:ODJsonDatabaseStructure) => void|Promise +export type ODStatScopeSetMode = "set"|"increase"|"decrease" + +export class ODStatsManager extends ODManager { + /**Alias to open ticket debugger. */ + #debug: ODDebugger + /**Alias to open ticket stats database. */ + database: ODDatabase|null = null + /**All the listeners for the init event. */ + #initListeners: ODStatsManagerInitCallback[] = [] + + constructor(debug:ODDebugger){ + super(debug,"stat scope") + this.#debug = debug + } + + useDatabase(database:ODDatabase){ + this.database = database + } + add(data:ODStatScope, overwrite?:boolean): boolean { + data.useDebug(this.#debug,"stat") + if (this.database) data.useDatabase(this.database) + return super.add(data,overwrite) + } + async init(){ + if (!this.database) throw new ODSystemError("Unable to initialize stats scopes due to missing database!") + + //get all valid categories + const validCategories: string[] = [] + for (const scope of this.getAll()){ + validCategories.push(...scope.init()) + } + + //filter out the deletable stats + const deletableStats: ODJsonDatabaseStructure = [] + this.database.getAll().forEach((data) => { + if (!validCategories.includes(data.category)) deletableStats.push(data) + }) + + //do additional deletion + for (const cb of this.#initListeners){ + await cb(this.database.getAll(),deletableStats) + } + + //delete all deletable stats + deletableStats.forEach((data) => { + if (!this.database) return + this.database.delete(data.category,data.key) + }) + } + reset(){ + if (!this.database) return + this.database.getAll().forEach((data) => { + if (!this.database) return + this.database.delete(data.category,data.key) + }) + } + onInit(callback:ODStatsManagerInitCallback){ + this.#initListeners.push(callback) + } +} + +export class ODStatScope extends ODManager { + /**The id of this statistics scope. */ + id: ODId + /**Is this stat scope already initialized? */ + ready: boolean = false + /**Alias to open ticket stats database. */ + database: ODDatabase|null = null + /**The name of this scope (used in embed title) */ + name:string + + constructor(id:ODValidId, name:string){ + super() + this.id = new ODId(id) + this.name = name + } + + useDatabase(database:ODDatabase){ + this.database = database + } + getStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + if (!this.database) return null + const newId = new ODId(id) + const data = this.database.get(this.id.value+"_"+newId.value,scopeId) + + if (typeof data == "undefined"){ + //set stats to default value & return + return this.resetStat(id,scopeId) + }else if (typeof data == "string" || typeof data == "boolean" || typeof data == "number"){ + //return value received from database + return data + } + //return null on error + return null + } + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + if (!this.database) return false + const stat = this.get(id) + if (!stat) return false + if (mode == "set" || typeof value != "number"){ + this.database.set(this.id.value+"_"+stat.id.value,scopeId,value) + }else if (mode == "increase"){ + const currentValue = this.getStat(id,scopeId) + if (typeof currentValue != "number") this.database.set(this.id.value+"_"+stat.id.value,scopeId,0) + else this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue+value) + }else if (mode == "decrease"){ + const currentValue = this.getStat(id,scopeId) + if (typeof currentValue != "number") this.database.set(this.id.value+"_"+stat.id.value,scopeId,0) + else this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue-value) + } + return true + } + resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + if (!this.database) return null + const stat = this.get(id) + if (!stat) return null + if (stat.value != null) this.database.set(this.id.value+"_"+stat.id.value,scopeId,stat.value) + return stat.value + } + init(): string[] { + //get all valid stats categories + this.ready = true + return this.getAll().map((stat) => this.id.value+"_"+stat.id.value) + } + async render(scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User): Promise { + //sort from high priority to low + const derefArray = [...this.getAll()] + derefArray.sort((a,b) => { + return b.priority-a.priority + }) + const result: string[] = [] + + for (const stat of derefArray){ + try { + if (stat instanceof ODDynamicStat){ + //dynamic render (without value) + result.push(await stat.render("",scopeId,guild,channel,user)) + }else{ + //normal render (with value) + const value = this.getStat(stat.id,scopeId) + if (value != null) result.push(await stat.render(value,scopeId,guild,channel,user)) + } + + }catch(err){ + process.emit("uncaughtException",err) + } + } + + return result.filter((stat) => stat !== "").join("\n") + } +} + +export class ODStatGlobalScope extends ODStatScope { + getStat(id:ODValidId): ODValidStatValue|null { + return super.getStat(id,"GLOBAL") + } + setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + return super.setStat(id,"GLOBAL",value,mode) + } + resetStat(id:ODValidId): ODValidStatValue|null { + return super.resetStat(id,"GLOBAL") + } + render(scopeId:"GLOBAL", guild:discord.Guild, channel:discord.TextBasedChannel, user: discord.User): Promise { + return super.render("GLOBAL",guild,channel,user) + } +} + +export type ODStatRenderer = (value:ODValidStatValue, scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise + +export class ODStat extends ODManagerData { + priority: number + render: ODStatRenderer + value: ODValidStatValue|null + + constructor(id:ODValidId, priority:number, render:ODStatRenderer, value?:ODValidStatValue){ + super(id) + this.priority = priority + this.render = render + this.value = value ?? null + } +} + +export class ODBasicStat extends ODStat { + name: string + + constructor(id:ODValidId, priority:number, name:string, value:ODValidStatValue){ + super(id,priority,(value) => { + return ""+name+": `"+value.toString()+"`" + },value) + this.name = name + } +} + +export type ODDynamicStatRenderer = (scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise + +export class ODDynamicStat extends ODStat { + constructor(id:ODValidId, priority:number, render:ODDynamicStatRenderer){ + super(id,priority,(value,scopeId,guild,channel,user) => { + return render(scopeId,guild,channel,user) + }) + } +} \ No newline at end of file diff --git a/src/core/api/modules/verifybar.ts b/src/core/api/modules/verifybar.ts new file mode 100644 index 0000000..6d8a914 --- /dev/null +++ b/src/core/api/modules/verifybar.ts @@ -0,0 +1,43 @@ +/////////////////////////////////////// +//VERIFYBAR MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODValidId } from "./base" +import { ODMessage } from "./builder" +import { ODDebugger } from "./console" +import { ODButtonResponderInstance } from "./responder" +import * as discord from "discord.js" +import { ODWorkerManager } from "./worker" + +export type ODVerifyBarCallback = (responder:ODButtonResponderInstance,customData?:string) => void|Promise + +export class ODVerifyBar extends ODManagerData { + success: ODWorkerManager|null}> + failure: ODWorkerManager|null}> + message: ODMessage<"verifybar",{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message}> + enabled: boolean + + constructor(id:ODValidId, message:ODMessage<"verifybar",{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalMessage:discord.Message}>, enabled?:boolean){ + super(id) + this.success = new ODWorkerManager("descending") + this.failure = new ODWorkerManager("descending") + this.message = message + this.enabled = enabled ?? true + } + + async activate(responder:ODButtonResponderInstance){ + if (this.enabled){ + //show verifybar + const {guild,channel,user,message} = responder + await responder.update(await this.message.build("verifybar",{guild,channel,user,verifybar:this,originalMessage:message})) + }else{ + //instant success + if (this.success) await this.success.executeWorkers(responder,"verifybar",{data:null,verifybarMessage:null}) + } + } +} + +export class ODVerifyBarManager extends ODManager { + constructor(debug:ODDebugger){ + super(debug,"verifybar") + } +} \ No newline at end of file diff --git a/src/core/api/modules/worker.ts b/src/core/api/modules/worker.ts new file mode 100644 index 0000000..617beb1 --- /dev/null +++ b/src/core/api/modules/worker.ts @@ -0,0 +1,93 @@ +/////////////////////////////////////// +//WORKER MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODManagerData, ODValidId } from "./base" + +/**## ODWorkerCallback `type` + * This is the callback used in `ODWorker`! + */ +export type ODWorkerCallback = (instance:Instance, params:Params, source:Source, cancel:() => void) => void|Promise + +/**## ODWorker `class` + * This is an open ticket worker. + * + * You can compare it with a normal javascript callback, but slightly more advanced! + * + * - It has an `id` for identification of the function + * - A `priority` to know when to execute this callback (related to others) + * - It knows who called this callback (`source`) + * - And much more! + */ +export class ODWorker extends ODManagerData { + /**The priority of this worker */ + priority: number + /**The main callback of this worker */ + callback: ODWorkerCallback + + constructor(id:ODValidId, priority:number, callback:ODWorkerCallback){ + super(id) + this.priority = priority + this.callback = callback + } +} + +/**## ODWorker `class` + * This is an open ticket worker manager. + * + * It manages & executes `ODWorker`'s in the correct order. + * + * You will probably register a custom worker in this class to create a message or button. + */ +export class ODWorkerManager extends ODManager> { + /**The order of execution for workers inside this manager. */ + #priorityOrder: "ascending"|"descending" + /**The backup worker will be executed when one of the workers fails or cancels execution. */ + backupWorker: ODWorker<{reason:"error"|"cancel"},Source,Params>|null = null + + constructor(priorityOrder:"ascending"|"descending"){ + super() + this.#priorityOrder = priorityOrder + } + + /**Get all workers in sorted order. */ + getSortedWorkers(priority:"ascending"|"descending"){ + const derefArray = [...this.getAll()] + + return derefArray.sort((a,b) => { + if (priority == "ascending") return a.priority-b.priority + else return b.priority-a.priority + }) + } + /**Execute all workers on an instance using the given source & parameters. */ + async executeWorkers(instance:Instance, source:Source, params:Params){ + const derefParams = {...params} + const workers = this.getSortedWorkers(this.#priorityOrder) + let didCancel = false + let didCrash = false + + for (const worker of workers){ + if (didCancel) break + try { + await worker.callback(instance,derefParams,source,() => { + didCancel = true + }) + }catch(err){ + process.emit("uncaughtException",err) + didCrash = true + } + } + if (didCancel && this.backupWorker){ + try{ + await this.backupWorker.callback({reason:"cancel"},derefParams,source,() => {}) + }catch(err){ + process.emit("uncaughtException",err) + } + }else if (didCrash && this.backupWorker){ + try{ + await this.backupWorker.callback({reason:"error"},derefParams,source,() => {}) + }catch(err){ + process.emit("uncaughtException",err) + } + } + } +} \ No newline at end of file diff --git a/src/core/api/openticket/blacklist.ts b/src/core/api/openticket/blacklist.ts new file mode 100644 index 0000000..4340139 --- /dev/null +++ b/src/core/api/openticket/blacklist.ts @@ -0,0 +1,28 @@ +/////////////////////////////////////// +//OPENTICKET BLACKLIST MODULE +/////////////////////////////////////// +import { ODManager, ODManagerData, ODValidId } from "../modules/base" +import { ODDebugger } from "../modules/console" + +export class ODBlacklist extends ODManagerData { + #reason: string|null + + constructor(id:ODValidId,reason:string|null){ + super(id) + this.#reason = reason + } + + set reason(reason:string|null) { + this.#reason = reason + this._change() + } + get reason(){ + return this.#reason + } +} + +export class ODBlacklistManager extends ODManager { + constructor(debug:ODDebugger){ + super(debug,"blacklist") + } +} \ No newline at end of file diff --git a/src/core/api/openticket/option.ts b/src/core/api/openticket/option.ts new file mode 100644 index 0000000..ffc967d --- /dev/null +++ b/src/core/api/openticket/option.ts @@ -0,0 +1,421 @@ +/////////////////////////////////////// +//OPENTICKET OPTION MODULE +/////////////////////////////////////// +import { ODDatabase } from "../modules/database" +import { ODJsonConfig_DefaultOptionEmbedSettingsType, ODJsonConfig_DefaultOptionPingSettingsType } from "../defaults/config" +import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODValidButtonColor, ODManagerData, ODSystemError } from "../modules/base" +import { ODDebugger } from "../modules/console" +import * as discord from "discord.js" +import * as crypto from "crypto" +import { OTRoleUpdateMode } from "./role" + +export class ODOptionManager extends ODManager { + #debug: ODDebugger + suffix: ODOptionSuffixManager + + constructor(debug:ODDebugger){ + super(debug,"option") + this.#debug = debug + this.suffix = new ODOptionSuffixManager(debug) + } + + add(data:ODOption, overwrite?:boolean): boolean { + data.useDebug(this.#debug,"option data") + return super.add(data,overwrite) + } +} + +export interface ODOptionDataJson { + id:string, + value:ODValidJsonType +} + +export interface ODOptionJson { + id:string, + type:string, + version:string, + data:ODOptionDataJson[] +} + +export class ODOption extends ODManager> { + id:ODId + type: string + + constructor(id:ODValidId, type:string, data:ODOptionData[]){ + super() + this.id = new ODId(id) + this.type = type + data.forEach((data) => { + this.add(data) + }) + } + + toJson(version:ODVersion): ODOptionJson { + const data = this.getAll().map((data) => { + return { + id:data.id.toString(), + value:data.value + } + }) + + return { + id:this.id.toString(), + type:this.type, + version:version.toString(), + data + } + } + + static fromJson(json:ODOptionJson): ODOption { + return new ODOption(json.id,json.type,json.data.map((data) => new ODOptionData(data.id,data.value))) + } +} + +export class ODOptionData extends ODManagerData { + #value: DataType + + constructor(id:ODValidId, value:DataType){ + super(id) + this.#value = value + } + + set value(value:DataType){ + this.#value = value + this._change() + } + get value(): DataType { + return this.#value + } + /**Refresh the database. Is only required to be used when updating `ODOptionData` with an object/array as value. */ + refreshDatabase(){ + this._change() + } +} + +/**## ODTicketOptionIds `type` + * This type is an array of ids available in the `ODTicketOption` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODTicketOptionIds { + "openticket:name":ODOptionData, + "openticket:description":ODOptionData, + + "openticket:button-emoji":ODOptionData, + "openticket:button-label":ODOptionData, + "openticket:button-color":ODOptionData, + + "openticket:admins":ODOptionData, + "openticket:admins-readonly":ODOptionData, + "openticket:allow-blacklisted-users":ODOptionData, + "openticket:questions":ODOptionData, + + "openticket:channel-prefix":ODOptionData, + "openticket:channel-suffix":ODOptionData<"user-name"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed">, + "openticket:channel-category":ODOptionData, + "openticket:channel-category-closed":ODOptionData, + "openticket:channel-category-backup":ODOptionData, + "openticket:channel-categories-claimed":ODOptionData<{user:string,category:string}[]>, + "openticket:channel-description":ODOptionData, + + "openticket:dm-message-enabled":ODOptionData, + "openticket:dm-message-text":ODOptionData, + "openticket:dm-message-embed":ODOptionData, + + "openticket:ticket-message-enabled":ODOptionData, + "openticket:ticket-message-text":ODOptionData, + "openticket:ticket-message-embed":ODOptionData, + "openticket:ticket-message-ping":ODOptionData, + + "openticket:autoclose-enable-hours":ODOptionData, + "openticket:autoclose-enable-leave":ODOptionData, + "openticket:autoclose-disable-claim":ODOptionData, + "openticket:autoclose-hours":ODOptionData, + + "openticket:autodelete-enable-days":ODOptionData, + "openticket:autodelete-enable-leave":ODOptionData, + "openticket:autodelete-disable-claim":ODOptionData, + "openticket:autodelete-days":ODOptionData, + + "openticket:cooldown-enabled":ODOptionData, + "openticket:cooldown-minutes":ODOptionData, + + "openticket:limits-enabled":ODOptionData, + "openticket:limits-maximum-global":ODOptionData, + "openticket:limits-maximum-user":ODOptionData +} + +export class ODTicketOption extends ODOption { + type: "openticket:ticket" = "openticket:ticket" + + constructor(id:ODValidId, data:ODOptionData[]){ + super(id,"openticket:ticket",data) + } + + get(id:OptionId): ODTicketOptionIds[OptionId] + get(id:ODValidId): ODOptionData|null + + get(id:ODValidId): ODOptionData|null { + return super.get(id) + } + + remove(id:OptionId): ODTicketOptionIds[OptionId] + remove(id:ODValidId): ODOptionData|null + + remove(id:ODValidId): ODOptionData|null { + return super.remove(id) + } + + exists(id:keyof ODTicketOptionIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + static fromJson(json: ODOptionJson): ODTicketOption { + return new ODTicketOption(json.id,json.data.map((data) => new ODOptionData(data.id,data.value))) + } +} + +/**## ODWebsiteOptionIds `type` + * This type is an array of ids available in the `ODWebsiteOption` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODWebsiteOptionIds { + "openticket:name":ODOptionData, + "openticket:description":ODOptionData, + + "openticket:button-emoji":ODOptionData, + "openticket:button-label":ODOptionData, + + "openticket:url":ODOptionData, +} + +export class ODWebsiteOption extends ODOption { + type: "openticket:website" = "openticket:website" + + constructor(id:ODValidId, data:ODOptionData[]){ + super(id,"openticket:website",data) + } + + get(id:OptionId): ODWebsiteOptionIds[OptionId] + get(id:ODValidId): ODOptionData|null + + get(id:ODValidId): ODOptionData|null { + return super.get(id) + } + + remove(id:OptionId): ODWebsiteOptionIds[OptionId] + remove(id:ODValidId): ODOptionData|null + + remove(id:ODValidId): ODOptionData|null { + return super.remove(id) + } + + exists(id:keyof ODWebsiteOptionIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + static fromJson(json: ODOptionJson): ODWebsiteOption { + return new ODWebsiteOption(json.id,json.data.map((data) => new ODOptionData(data.id,data.value))) + } +} + +/**## ODRoleOptionIds `type` + * This type is an array of ids available in the `ODRoleOption` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODRoleOptionIds { + "openticket:name":ODOptionData, + "openticket:description":ODOptionData, + + "openticket:button-emoji":ODOptionData, + "openticket:button-label":ODOptionData, + "openticket:button-color":ODOptionData, + + "openticket:roles":ODOptionData, + "openticket:mode":ODOptionData, + "openticket:remove-roles-on-add":ODOptionData, + "openticket:add-on-join":ODOptionData +} + +export class ODRoleOption extends ODOption { + type: "openticket:role" = "openticket:role" + + constructor(id:ODValidId, data:ODOptionData[]){ + super(id,"openticket:role",data) + } + + get(id:OptionId): ODRoleOptionIds[OptionId] + get(id:ODValidId): ODOptionData|null + + get(id:ODValidId): ODOptionData|null { + return super.get(id) + } + + remove(id:OptionId): ODRoleOptionIds[OptionId] + remove(id:ODValidId): ODOptionData|null + + remove(id:ODValidId): ODOptionData|null { + return super.remove(id) + } + + exists(id:keyof ODRoleOptionIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + static fromJson(json:ODOptionJson): ODRoleOption { + return new ODRoleOption(json.id,json.data.map((data) => new ODOptionData(data.id,data.value))) + } +} + +export class ODOptionSuffixManager extends ODManager { + /**Alias to open ticket global database. */ + database: ODDatabase|null = null + + constructor(debug:ODDebugger){ + super(debug,"ticket suffix") + } + + useDatabase(database:ODDatabase){ + this.database = database + } + /**Instantly get the suffix from an option. */ + getSuffixFromOption(option:ODTicketOption,user:discord.User): string|null { + const suffix = this.getAll().find((suffix) => suffix.option.id.value == option.id.value) + if (!suffix) return null + return suffix.getSuffix(user) + } +} + +export class ODOptionSuffix extends ODManagerData { + /**The option of this suffix. */ + option: ODTicketOption + + constructor(id:ODValidId, option:ODTicketOption){ + super(id) + this.option = option + } + + /**Get the suffix for a new ticket. */ + getSuffix(user:discord.User): string { + throw new ODSystemError("Tried to use an unimplemented ODOptionSuffix!") + } +} + +export class ODOptionUserNameSuffix extends ODOptionSuffix { + getSuffix(user:discord.User): string { + return user.username + } +} + +export class ODOptionUserIdSuffix extends ODOptionSuffix { + getSuffix(user:discord.User): string { + return user.id + } +} + +export class ODOptionCounterDynamicSuffix extends ODOptionSuffix { + /**The database where the value of this counter is stored. */ + database: ODDatabase + + constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){ + super(id,option) + this.database = database + if (!this.database.exists("openticket:option-suffix-counter",option.id.value)) this.database.set("openticket:option-suffix-counter",this.option.id.value,0) + } + + getSuffix(user:discord.User): string { + const rawCurrentValue = this.database.get("openticket:option-suffix-counter",this.option.id.value) + const currentValue = (typeof rawCurrentValue != "number") ? 0 : rawCurrentValue + const newValue = currentValue+1 + this.database.set("openticket:option-suffix-counter",this.option.id.value,newValue) + return newValue.toString() + } +} + +export class ODOptionCounterFixedSuffix extends ODOptionSuffix { + /**The database where the value of this counter is stored. */ + database: ODDatabase + + constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){ + super(id,option) + this.database = database + if (!this.database.exists("openticket:option-suffix-counter",option.id.value)) this.database.set("openticket:option-suffix-counter",this.option.id.value,0) + } + + getSuffix(user:discord.User): string { + const rawCurrentValue = this.database.get("openticket:option-suffix-counter",this.option.id.value) + const currentValue = (typeof rawCurrentValue != "number") ? 0 : rawCurrentValue + const newValue = (currentValue >= 9999) ? 0 : currentValue+1 + + this.database.set("openticket: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() + else return newValue.toString() + } +} + +export class ODOptionRandomNumberSuffix extends ODOptionSuffix { + /**The database where previous random numbers are stored. */ + database: ODDatabase + + constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){ + super(id,option) + this.database = database + if (!this.database.exists("openticket:option-suffix-history",option.id.value)) this.database.set("openticket:option-suffix-history",this.option.id.value,[]) + } + + #generateUniqueValue(history:string[]): string { + const rawNumber = Math.round(Math.random()*1000).toString() + let number = rawNumber + if (rawNumber.length == 1) number = "000"+rawNumber + else if (rawNumber.length == 2) number = "00"+rawNumber + else if (rawNumber.length == 3) number = "0"+rawNumber + + if (history.includes(number)) return this.#generateUniqueValue(history) + else return number + } + getSuffix(user:discord.User): string { + const rawCurrentValues = this.database.get("openticket: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("openticket:option-suffix-history",this.option.id.value,currentValues) + return newValue + } +} + +export class ODOptionRandomHexSuffix extends ODOptionSuffix { + /**The database where previous random hexes are stored. */ + database: ODDatabase + + constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){ + super(id,option) + this.database = database + if (!this.database.exists("openticket:option-suffix-history",option.id.value)) this.database.set("openticket:option-suffix-history",this.option.id.value,[]) + } + + #generateUniqueValue(history:string[]): string { + const hex = crypto.randomBytes(2).toString("hex") + if (history.includes(hex)) return this.#generateUniqueValue(history) + else return hex + } + getSuffix(user:discord.User): string { + const rawCurrentValues = this.database.get("openticket: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("openticket:option-suffix-history",this.option.id.value,currentValues) + return newValue + } +} \ No newline at end of file diff --git a/src/core/api/openticket/panel.ts b/src/core/api/openticket/panel.ts new file mode 100644 index 0000000..5c37b2d --- /dev/null +++ b/src/core/api/openticket/panel.ts @@ -0,0 +1,128 @@ +/////////////////////////////////////// +//OPENTICKET PANEL MODULE +/////////////////////////////////////// +import { ODJsonConfig_DefaultPanelEmbedSettingsType } from "../defaults/config" +import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODValidButtonColor, ODManagerData } from "../modules/base" +import { ODDebugger } from "../modules/console" + +export class ODPanelManager extends ODManager { + #debug: ODDebugger + + constructor(debug:ODDebugger){ + super(debug,"option") + this.#debug = debug + } + + add(data:ODPanel, overwrite?:boolean): boolean { + data.useDebug(this.#debug,"option data") + return super.add(data,overwrite) + } +} + +export interface ODPanelDataJson { + id:string, + value:ODValidJsonType +} + +export interface ODPanelJson { + id:string, + version:string, + data:ODPanelDataJson[] +} + +/**## ODPanelIds `type` + * This type is an array of ids available in the `ODPanel` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODPanelIds { + "openticket:name":ODPanelData, + "openticket:options":ODPanelData, + "openticket:dropdown":ODPanelData, + + "openticket:text":ODPanelData, + "openticket:embed":ODPanelData, + + "openticket:dropdown-placeholder":ODPanelData, + + "openticket:enable-max-tickets-warning-text":ODPanelData, + "openticket:enable-max-tickets-warning-embed":ODPanelData, + + "openticket:describe-options-layout":ODPanelData<"simple"|"normal"|"detailed">, + "openticket:describe-options-custom-title":ODPanelData, + "openticket:describe-options-in-text":ODPanelData, + "openticket:describe-options-in-embed-fields":ODPanelData, + "openticket:describe-options-in-embed-description":ODPanelData +} + +export class ODPanel extends ODManager> { + id:ODId + + constructor(id:ODValidId, data:ODPanelData[]){ + super() + this.id = new ODId(id) + data.forEach((data) => { + this.add(data) + }) + } + + toJson(version:ODVersion): ODPanelJson { + const data = this.getAll().map((data) => { + return { + id:data.id.toString(), + value:data.value + } + }) + + return { + id:this.id.toString(), + version:version.toString(), + data + } + } + + static fromJson(json:ODPanelJson): ODPanel { + return new ODPanel(json.id,json.data.map((data) => new ODPanelData(data.id,data.value))) + } + + get(id:PanelId): ODPanelIds[PanelId] + get(id:ODValidId): ODPanelData|null + + get(id:ODValidId): ODPanelData|null { + return super.get(id) + } + + remove(id:PanelId): ODPanelIds[PanelId] + remove(id:ODValidId): ODPanelData|null + + remove(id:ODValidId): ODPanelData|null { + return super.remove(id) + } + + exists(id:keyof ODPanelIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +export class ODPanelData extends ODManagerData { + #value: DataType + + constructor(id:ODValidId, value:DataType){ + super(id) + this.#value = value + } + + set value(value:DataType){ + this.#value = value + this._change() + } + get value(): DataType { + return this.#value + } + /**Refresh the database. Is only required to be used when updating `ODPanelData` with an object/array as value. */ + refreshDatabase(){ + this._change() + } +} \ No newline at end of file diff --git a/src/core/api/openticket/question.ts b/src/core/api/openticket/question.ts new file mode 100644 index 0000000..da22cdd --- /dev/null +++ b/src/core/api/openticket/question.ts @@ -0,0 +1,180 @@ +/////////////////////////////////////// +//OPENTICKET OPTION MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } from "../modules/base" +import { ODDebugger } from "../modules/console" + +export class ODQuestionManager extends ODManager { + #debug: ODDebugger + + constructor(debug:ODDebugger){ + super(debug,"question") + this.#debug = debug + } + + add(data:ODQuestion, overwrite?:boolean): boolean { + data.useDebug(this.#debug,"question data") + return super.add(data,overwrite) + } +} + +export interface ODQuestionDataJson { + id:string, + value:ODValidJsonType +} + +export interface ODQuestionJson { + id:string, + type:string, + version:string, + data:ODQuestionDataJson[] +} + +export class ODQuestion extends ODManager> { + id:ODId + type: string + + constructor(id:ODValidId, type:string, data:ODQuestionData[]){ + super() + this.id = new ODId(id) + this.type = type + data.forEach((data) => { + this.add(data) + }) + } + + toJson(version:ODVersion): ODQuestionJson { + const data = this.getAll().map((data) => { + return { + id:data.id.toString(), + value:data.value + } + }) + + return { + id:this.id.toString(), + type:this.type, + version:version.toString(), + data + } + } + + static fromJson(json:ODQuestionJson): ODQuestion { + return new ODQuestion(json.id,json.type,json.data.map((data) => new ODQuestionData(data.id,data.value))) + } +} + +export class ODQuestionData extends ODManagerData { + #value: DataType + + constructor(id:ODValidId, value:DataType){ + super(id) + this.#value = value + } + + set value(value:DataType){ + this.#value = value + this._change() + } + get value(): DataType { + return this.#value + } + /**Refresh the database. Is only required to be used when updating `ODQuestionData` with an object/array as value. */ + refreshDatabase(){ + this._change() + } +} + +/**## ODShortQuestionIds `type` + * This type is an array of ids available in the `ODShortQuestion` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODShortQuestionIds { + "openticket:name":ODQuestionData, + "openticket:required":ODQuestionData, + "openticket:placeholder":ODQuestionData, + + "openticket:length-enabled":ODQuestionData, + "openticket:length-min":ODQuestionData, + "openticket:length-max":ODQuestionData +} + +export class ODShortQuestion extends ODQuestion { + type: "openticket:short" = "openticket:short" + + constructor(id:ODValidId, data:ODQuestionData[]){ + super(id,"openticket:short",data) + } + + get(id:QuestionId): ODShortQuestionIds[QuestionId] + get(id:ODValidId): ODQuestionData|null + + get(id:ODValidId): ODQuestionData|null { + return super.get(id) + } + + remove(id:QuestionId): ODShortQuestionIds[QuestionId] + remove(id:ODValidId): ODQuestionData|null + + remove(id:ODValidId): ODQuestionData|null { + return super.remove(id) + } + + exists(id:keyof ODShortQuestionIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + static fromJson(json: ODQuestionJson): ODShortQuestion { + return new ODShortQuestion(json.id,json.data.map((data) => new ODQuestionData(data.id,data.value))) + } +} + +/**## ODParagraphQuestionIds `type` + * This type is an array of ids available in the `ODParagraphQuestion` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODParagraphQuestionIds { + "openticket:name":ODQuestionData, + "openticket:required":ODQuestionData, + "openticket:placeholder":ODQuestionData, + + "openticket:length-enabled":ODQuestionData, + "openticket:length-min":ODQuestionData, + "openticket:length-max":ODQuestionData +} + +export class ODParagraphQuestion extends ODQuestion { + type: "openticket:paragraph" = "openticket:paragraph" + + constructor(id:ODValidId, data:ODQuestionData[]){ + super(id,"openticket:paragraph",data) + } + + get(id:QuestionId): ODParagraphQuestionIds[QuestionId] + get(id:ODValidId): ODQuestionData|null + + get(id:ODValidId): ODQuestionData|null { + return super.get(id) + } + + remove(id:QuestionId): ODParagraphQuestionIds[QuestionId] + remove(id:ODValidId): ODQuestionData|null + + remove(id:ODValidId): ODQuestionData|null { + return super.remove(id) + } + + exists(id:keyof ODParagraphQuestionIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } + + static fromJson(json: ODQuestionJson): ODParagraphQuestion { + return new ODParagraphQuestion(json.id,json.data.map((data) => new ODQuestionData(data.id,data.value))) + } +} \ No newline at end of file diff --git a/src/core/api/openticket/role.ts b/src/core/api/openticket/role.ts new file mode 100644 index 0000000..cae14b8 --- /dev/null +++ b/src/core/api/openticket/role.ts @@ -0,0 +1,122 @@ +/////////////////////////////////////// +//OPENTICKET ROLE MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } from "../modules/base" +import { ODDebugger } from "../modules/console" +import * as discord from "discord.js" + +export class ODRoleManager extends ODManager { + #debug: ODDebugger + + constructor(debug:ODDebugger){ + super(debug,"role") + this.#debug = debug + } + + add(data:ODRole, overwrite?:boolean): boolean { + data.useDebug(this.#debug,"role data") + return super.add(data,overwrite) + } +} + +export interface ODRoleDataJson { + id:string, + value:ODValidJsonType +} + +export interface ODRoleJson { + id:string, + version:string, + data:ODRoleDataJson[] +} + +export class ODRoleData extends ODManagerData { + #value: DataType + + constructor(id:ODValidId, value:DataType){ + super(id) + this.#value = value + } + + set value(value:DataType){ + this.#value = value + this._change() + } + get value(): DataType { + return this.#value + } + /**Refresh the database. Is only required to be used when updating `ODRoleData` with an object/array as value. */ + refreshDatabase(){ + this._change() + } +} + +/**## ODRoleIds `type` + * This type is an array of ids available in the `ODRole` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODRoleIds { + "openticket:roles":ODRoleData, + "openticket:mode":ODRoleData, + "openticket:remove-roles-on-add":ODRoleData, + "openticket:add-on-join":ODRoleData +} + +export class ODRole extends ODManager> { + id:ODId + + constructor(id:ODValidId, data:ODRoleData[]){ + super() + this.id = new ODId(id) + data.forEach((data) => { + this.add(data) + }) + } + + toJson(version:ODVersion): ODRoleJson { + const data = this.getAll().map((data) => { + return { + id:data.id.toString(), + value:data.value + } + }) + + return { + id:this.id.toString(), + version:version.toString(), + data + } + } + + static fromJson(json:ODRoleJson): ODRole { + return new ODRole(json.id,json.data.map((data) => new ODRoleData(data.id,data.value))) + } + + get(id:OptionId): ODRoleIds[OptionId] + get(id:ODValidId): ODRoleData|null + + get(id:ODValidId): ODRoleData|null { + return super.get(id) + } + + remove(id:OptionId): ODRoleIds[OptionId] + remove(id:ODValidId): ODRoleData|null + + remove(id:ODValidId): ODRoleData|null { + return super.remove(id) + } + + exists(id:keyof ODRoleIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +export interface OTRoleUpdateResult { + role:discord.Role, + action:"added"|"removed"|null +} + +export type OTRoleUpdateMode = "add&remove"|"add"|"remove" \ No newline at end of file diff --git a/src/core/api/openticket/ticket.ts b/src/core/api/openticket/ticket.ts new file mode 100644 index 0000000..02c7058 --- /dev/null +++ b/src/core/api/openticket/ticket.ts @@ -0,0 +1,251 @@ +/////////////////////////////////////// +//OPENTICKET TICKET MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } from "../modules/base" +import { ODDebugger } from "../modules/console" +import { ODClientManager_Default } from "../defaults/client" +import { ODOption, ODOptionJson, ODTicketOption } from "./option" +import * as discord from "discord.js" + +export class ODTicketManager extends ODManager { + /**A reference to the main server of the bot */ + #guild: discord.Guild|null = null + #client: ODClientManager_Default + #debug: ODDebugger + + constructor(debug:ODDebugger, client:ODClientManager_Default){ + super(debug,"ticket") + this.#debug = debug + this.#client = client + } + + add(data:ODTicket, overwrite?:boolean): boolean { + data.useDebug(this.#debug,"ticket data") + return super.add(data,overwrite) + } + /**Use a specific guild in this class for fetching the channel*/ + useGuild(guild:discord.Guild|null){ + this.#guild = guild + } + /**Get the discord channel for a specific ticket. */ + async getTicketChannel(ticket:ODTicket): Promise { + if (!this.#guild) return null + try { + const channel = await this.#guild.channels.fetch(ticket.id.value) + if (!channel || !channel.isTextBased()) return null + return channel + }catch{ + return null + } + } + /**Get the main ticket message of a ticket channel when found. */ + async getTicketMessage(ticket:ODTicket): Promise|null> { + const msgId = ticket.get("openticket:ticket-message").value + if (!this.#guild || !msgId) return null + try { + const channel = await this.getTicketChannel(ticket) + if (!channel) return null + return await channel.messages.fetch(msgId) + }catch{ + return null + } + } + /**Shortcut for getting a discord.js user within a ticket. */ + async getTicketUser(ticket:ODTicket, user:"creator"|"closer"|"claimer"|"pinner"): Promise { + if (!this.#guild) return null + try { + if (user == "creator"){ + const creatorId = ticket.get("openticket:opened-by").value + if (!creatorId) return null + else return (await this.#guild.client.users.fetch(creatorId)) + + }else if (user == "closer"){ + const closerId = ticket.get("openticket:closed-by").value + if (!closerId) return null + else return (await this.#guild.client.users.fetch(closerId)) + + }else if (user == "claimer"){ + const claimerId = ticket.get("openticket:claimed-by").value + if (!claimerId) return null + else return (await this.#guild.client.users.fetch(claimerId)) + + }else if (user == "pinner"){ + const pinnerId = ticket.get("openticket:pinned-by").value + if (!pinnerId) return null + else return (await this.#guild.client.users.fetch(pinnerId)) + + }else return null + }catch {return null} + } + /**Shortcut for getting all users that are able to view a ticket. */ + async getAllTicketParticipants(ticket:ODTicket): Promise<{user:discord.User,role:"creator"|"participant"|"admin"}[]|null> { + if (!this.#guild) return null + const final: {user:discord.User,role:"creator"|"participant"|"admin"}[] = [] + const channel = await this.getTicketChannel(ticket) + if (!channel) return null + + //add creator + const creatorId = ticket.get("openticket:opened-by").value + if (creatorId){ + const creator = await this.#client.fetchUser(creatorId) + if (creator) final.push({user:creator,role:"creator"}) + } + + //add participants + const participants = ticket.get("openticket:participants").value.filter((p) => p.type == "user") + for (const p of participants){ + if (!final.find((u) => u.user.id == p.id)){ + const participant = await this.#client.fetchUser(p.id) + if (participant) final.push({user:participant,role:"participant"}) + } + } + + //add admin roles + const roles = ticket.get("openticket:participants").value.filter((p) => p.type == "role") + for (const r of roles){ + const role = await this.#client.fetchGuildRole(channel.guild,r.id) + if (role){ + role.members.forEach((member) => { + if (final.find((u) => u.user.id == member.id)) return + final.push({user:member.user,role:"admin"}) + }) + } + } + + return final + } +} + +export interface ODTicketDataJson { + id:string, + value:ODValidJsonType +} + +export interface ODTicketJson { + id:string, + option:string, + version:string, + data:ODTicketDataJson[] +} + +/**## ODTicketIds `type` + * This type is an array of ids available in the `ODTicket` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODTicketIds { + "openticket:busy":ODTicketData, + "openticket:ticket-message":ODTicketData, + "openticket:participants":ODTicketData<{type:"role"|"user",id:string}[]>, + "openticket:channel-suffix":ODTicketData, + + "openticket:open":ODTicketData, + "openticket:opened-by":ODTicketData, + "openticket:opened-on":ODTicketData, + "openticket:closed":ODTicketData, + "openticket:closed-by":ODTicketData, + "openticket:closed-on":ODTicketData, + "openticket:claimed":ODTicketData, + "openticket:claimed-by":ODTicketData, + "openticket:claimed-on":ODTicketData, + "openticket:pinned":ODTicketData, + "openticket:pinned-by":ODTicketData, + "openticket:pinned-on":ODTicketData, + "openticket:for-deletion":ODTicketData, + + "openticket:category":ODTicketData, + "openticket:category-mode":ODTicketData, + + "openticket:autoclose-enabled":ODTicketData, + "openticket:autoclose-hours":ODTicketData, + "openticket:autoclosed":ODTicketData, + "openticket:autodelete-enabled":ODTicketData, + "openticket:autodelete-days":ODTicketData, + + "openticket:answers":ODTicketData<{id:string,name:string,type:"short"|"paragraph",value:string|null}[]>, +} + +export class ODTicket extends ODManager> { + id:ODId + #option: ODTicketOption + + constructor(id:ODValidId, option:ODTicketOption, data:ODTicketData[]){ + super() + this.id = new ODId(id) + this.#option = option + data.forEach((data) => { + this.add(data) + }) + } + + set option(option:ODTicketOption){ + this.#option = option + this._change() + } + get option(){ + return this.#option + } + + toJson(version:ODVersion): ODTicketJson { + const data = this.getAll().map((data) => { + return { + id:data.id.toString(), + value:data.value + } + }) + + return { + id:this.id.toString(), + option:this.option.id.value, + version:version.toString(), + data + } + } + + static fromJson(json:ODTicketJson, option:ODTicketOption): ODTicket { + return new ODTicket(json.id,option,json.data.map((data) => new ODTicketData(data.id,data.value))) + } + + get(id:OptionId): ODTicketIds[OptionId] + get(id:ODValidId): ODTicketData|null + + get(id:ODValidId): ODTicketData|null { + return super.get(id) + } + + remove(id:OptionId): ODTicketIds[OptionId] + remove(id:ODValidId): ODTicketData|null + + remove(id:ODValidId): ODTicketData|null { + return super.remove(id) + } + + exists(id:keyof ODTicketIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +export class ODTicketData extends ODManagerData { + #value: DataType + + constructor(id:ODValidId, value:DataType){ + super(id) + this.#value = value + } + + set value(value:DataType){ + this.#value = value + this._change() + } + get value(): DataType { + return this.#value + } + /**Refresh the database. Is only required to be used when updating `ODTicketData` with an object/array as value. */ + refreshDatabase(){ + this._change() + } +} + +export type ODTicketClearFilter = "all"|"open"|"closed"|"claimed"|"unclaimed"|"pinned"|"unpinned"|"autoclosed" \ No newline at end of file diff --git a/src/core/api/openticket/transcript.ts b/src/core/api/openticket/transcript.ts new file mode 100644 index 0000000..5e89525 --- /dev/null +++ b/src/core/api/openticket/transcript.ts @@ -0,0 +1,802 @@ +/////////////////////////////////////// +//OPENTICKET TRANSCRIPT MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODValidJsonType, ODValidId, ODManagerData, ODValidButtonColor } from "../modules/base" +import { ODDebugger } from "../modules/console" +import { ODTicket, ODTicketManager } from "./ticket" +import { ODMessageBuildResult } from "../modules/builder" +import * as discord from "discord.js" + +export class ODTranscriptManager extends ODManager> { + /**The manager responsible for collecting all messages in a channel. */ + collector: ODTranscriptCollector + + constructor(debug:ODDebugger, tickets:ODTicketManager){ + super(debug,"transcript compiler") + this.collector = new ODTranscriptCollector(tickets) + } +} + +export type ODTranscriptCompilerInitFunction = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => (ODTranscriptCompilerInitResult)|Promise +export type ODTranscriptCompilerCompileFunction = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => ODTranscriptCompilerCompileResult|Promise> +export type ODTranscriptCompilerReadyFunction = (result:ODTranscriptCompilerCompileResult) => ODTranscriptCompilerReadyResult|Promise + +export interface ODTranscriptCompilerInitResult { + success:boolean, + errorReason:string|null, + pendingMessage:ODMessageBuildResult|null +} + +export interface ODTranscriptCompilerCompileResult { + ticket:ODTicket, + channel:discord.TextChannel, + user:discord.User + success:boolean, + errorReason:string|null, + messages:ODTranscriptMessageData[]|null, + data:Data|null +} +export interface ODTranscriptCompilerReadyResult { + channelMessage?:ODMessageBuildResult, + creatorDmMessage?:ODMessageBuildResult, + participantDmMessage?:ODMessageBuildResult, + activeAdminDmMessage?:ODMessageBuildResult, + everyAdminDmMessage?:ODMessageBuildResult +} + +export class ODTranscriptCompiler 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 + /*Compile or create the transcript. Returns data to give to the ready() function for message creation. */ + compile: ODTranscriptCompilerCompileFunction|null + /*Unload the system & create the final transcript message that will be sent. */ + ready: ODTranscriptCompilerReadyFunction|null + + constructor(id:ODValidId, init?:ODTranscriptCompilerInitFunction, compile?:ODTranscriptCompilerCompileFunction, ready?:ODTranscriptCompilerReadyFunction|null){ + super(id) + this.init = init ?? null + this.compile = compile ?? null + this.ready = ready ?? null + } +} + +/**## ODTranscriptCompilerIds `type` + * This type is an array of ids available in the `ODTranscriptCompiler` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODTranscriptCompilerIds { + "openticket:html-compiler":ODTranscriptCompiler<{url:string}>, + "openticket:text-compiler":ODTranscriptCompiler<{contents:string}>, +} + +/**## ODTranscriptManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODTranscriptManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.transcripts`! + */ +export class ODTranscriptManager_Default extends ODTranscriptManager { + get(id:QuestionId): ODTranscriptCompilerIds[QuestionId] + get(id:ODValidId): ODTranscriptCompiler|null + + get(id:ODValidId): ODTranscriptCompiler|null { + return super.get(id) + } + + remove(id:QuestionId): ODTranscriptCompilerIds[QuestionId] + remove(id:ODValidId): ODTranscriptCompiler|null + + remove(id:ODValidId): ODTranscriptCompiler|null { + return super.remove(id) + } + + exists(id:keyof ODTranscriptCompilerIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +export class ODTranscriptCollector { + /**Alias for the ticket manager. */ + #tickets: ODTicketManager + + constructor(tickets:ODTicketManager){ + this.#tickets = tickets + } + + /**Collect all messages from a given ticket channel. It may not include all messages depending on the ratelimit. */ + async collectAllMessages(ticket:ODTicket, include?:ODTranscriptCollectorIncludeSettings): Promise[]|null> { + const newInclude: ODTranscriptCollectorIncludeSettings = include ?? {users:true,bots:true,client:true} + const channel = await this.#tickets.getTicketChannel(ticket) + if (!channel) return null + + const final: discord.Message[] = [] + const limit: number = 2000 + let lastId: string = "" + while (true){ + const options: discord.FetchMessagesOptions = {limit:100} + if (lastId) options.before = lastId + + const messages = await channel.messages.fetch(options) + messages.forEach(msg => { + if (msg.author.id == msg.client.user.id && newInclude.client) final.push(msg) + else if ((msg.author.bot || msg.author.system) && newInclude.bots) final.push(msg) + else if (newInclude.users) final.push(msg) + }) + + const lastMessage = messages.last() + if (messages.size != 100 || final.length >= limit || !lastMessage) break + else lastId = lastMessage.id + } + return final.reverse() + } + /**Count all messages from a given ticket channel. It may not include all messages depending on the ratelimit. */ + async countAllMessages(ticket:ODTicket, include?:ODTranscriptCollectorIncludeSettings){ + const messages = await this.collectAllMessages(ticket,include) + if (!messages) return null + return messages.length + } + async convertMessagesToTranscriptData(messages:discord.Message[]): Promise { + const final: ODTranscriptMessageData[] = [] + for (const msg of messages){ + const {guild,channel,id,createdTimestamp} = msg + + //create message author + const author = this.#handleUserData(msg.author,msg.member) + + //create message type + let type: ODTranscriptMessageType = "default" + if (msg.mentions.everyone || msg.content.includes("@here")) type = "important" + else if (msg.flags.has("Ephemeral")) type = "ephemeral" + else if (msg.type == discord.MessageType.UserJoin) type = "welcome.message" + else if (msg.type == discord.MessageType.ChannelPinnedMessage) type = "pinned.message" + else if (msg.type == discord.MessageType.GuildBoost || msg.type == discord.MessageType.GuildBoostTier1 || msg.type == discord.MessageType.GuildBoostTier2 || msg.type == discord.MessageType.GuildBoostTier3) type = "boost.message" + else if (msg.type == discord.MessageType.ThreadCreated) type = "thread.message" + + //create message embeds + const embeds: ODTranscriptEmbedData[] = [] + msg.embeds.forEach((embed) => { + embeds.push({ + title:embed.title, + description:embed.description, + authorimg:(embed.author && embed.author.iconURL) ? embed.author.iconURL : null, + authortext:(embed.author) ? embed.author.name : null, + footerimg:(embed.footer && embed.footer.iconURL) ? embed.footer.iconURL : null, + footertext:(embed.footer) ? embed.footer.text : null, + color:(embed.hexColor as discord.HexColorString) ?? "#000000", + image:(embed.image) ? embed.image.url : null, + thumbnail:(embed.thumbnail) ? embed.thumbnail.url : null, + url:embed.url, + fields:embed.fields.map((field) => {return {name:field.name,value:field.value,inline:field.inline ?? false}}) + }) + }) + + //create message files + const files: ODTranscriptFileData[] = [] + msg.attachments.forEach((attachment) => { + const {size,unit} = this.calculateFileSize(attachment.size) + files.push({ + type:attachment.contentType ?? "unknown", + size, + unit, + name:attachment.name, + url:attachment.url, + spoiler:attachment.spoiler, + alt:attachment.description + }) + }) + + //create message components + const rows: ODTranscriptComponentRowData[] = [] + msg.components.forEach((row) => { + const components: ODTranscriptComponentRowData["components"] = [] + row.components.forEach((component) => { + if (component.type == discord.ComponentType.Button){ + components.push({ + id:component.customId, + disabled:component.disabled, + type:"button", + label:component.label, + emoji:this.#handleComponentEmoji(msg,component.emoji), + color:this.#handleButtonComponentStyle(component.style), + mode:(component.style == discord.ButtonStyle.Link) ? "url" : "button", + url:component.url + }) + }else if (component.type == discord.ComponentType.StringSelect){ + components.push({ + id:component.customId, + disabled:component.disabled, + type:"dropdown", + placeholder:component.placeholder, + options:component.options.map((option) => { + return { + id:option.value, + label:option.label, + description:option.description ?? null, + emoji:this.#handleComponentEmoji(msg,option.emoji ?? null) + } + }) + }) + } + }) + rows.push({components}) + }) + + //create message reply + let reply: ODTranscriptMessageReplyData|ODTranscriptInteractionReplyData|null = null + if (msg.reference && msg.reference.messageId && msg.reference.guildId){ + //normal message reply + try{ + const replyChannel = await msg.client.channels.fetch(msg.reference.channelId) + if (replyChannel && !replyChannel.isDMBased() && replyChannel.isTextBased()){ + const replyMessage = await replyChannel.messages.fetch(msg.reference.messageId) + if (replyMessage){ + const replyUser = this.#handleUserData(replyMessage.author,replyMessage.member) + + reply = { + type:"message", + guild:msg.reference.guildId, + channel:msg.reference.channelId, + id:msg.reference.messageId, + user:replyUser, + content:(replyMessage.content != "") ? replyMessage.content : null + } + } + } + }catch{} + }else if (msg.interaction && msg.interaction.type == discord.InteractionType.ApplicationCommand){ + //slash command reply + const member = await msg.guild.members.fetch(msg.interaction.user.id) + reply = { + type:"interaction", + name:msg.interaction.commandName, + user:this.#handleUserData(msg.interaction.user,member) + } + } + + //create message reactions + const reactions: ODTranscriptReactionData[] = [] + msg.reactions.cache.forEach((reaction) => { + const {count,emoji} = reaction + + if (emoji instanceof discord.ReactionEmoji && !emoji.id && emoji.name){ + //build-in emoji + reactions.push({ + id:null, + name:null, + custom:false, + animated:false, + emoji:emoji.name, + amount:count, + super:false //unimplemented in discord.js + }) + }else if (emoji instanceof discord.ReactionEmoji && emoji.id){ + //custom emoji + reactions.push({ + id:emoji.id, + name:emoji.name, + custom:true, + animated:emoji.animated ?? false, + emoji:(emoji.animated ? emoji.imageURL({extension:"gif"}) : emoji.imageURL({extension:"png"})) ?? "❌", + amount:count, + super:false //unimplemented in discord.js + }) + } + }) + + //create message + final.push({ + author, + guild:guild.id, + channel:channel.id, + id, + edited:(msg.editedAt) ? true : false, + timestamp:createdTimestamp, + type, + content:(msg.content != "") ? msg.content : null, + embeds, + files, + components:rows, + reply, + reactions + }) + } + return final + } + /**Calculate a human-readable file size. Used in transcripts. */ + calculateFileSize(bytes:number): {size:number, unit:"B"|"KB"|"MB"|"GB"|"TB"} { + if (bytes >= 1000000000000) return {size:(Math.round((bytes/1000000000000)*100)/100),unit:"TB"} + if (bytes >= 1000000000) return {size:(Math.round((bytes/1000000000)*100)/100),unit:"GB"} + else if (bytes >= 1000000) return {size:(Math.round((bytes/1000000)*100)/100),unit:"MB"} + else if (bytes >= 1000) return {size:(Math.round((bytes/1000)*100)/100),unit:"KB"} + else return {size:bytes,unit:"B"} + } + /**Get the `ODTranscriptEmojiData` from a discord.js component emoji. */ + #handleComponentEmoji(message:discord.Message, rawEmoji:discord.APIMessageComponentEmoji|null): ODTranscriptEmojiData|null { + if (!rawEmoji) return null + //return built-in emoji + if (rawEmoji.name) return { + id:null, + name:null, + custom:false, + animated:false, + emoji:rawEmoji.name + } + if (!rawEmoji.id) return null + const emoji = message.client.emojis.resolve(rawEmoji.id) + if (!emoji) return null + //return custom emoji + return { + id:emoji.id, + name:emoji.name, + custom:true, + animated:emoji.animated ?? false, + emoji:(emoji.animated ? emoji.imageURL({extension:"gif"}) : emoji.imageURL({extension:"png"})) + } + } + /**Create the `ODValidButtonColor` from the discord.js button style. */ + #handleButtonComponentStyle(style:discord.ButtonStyle): ODValidButtonColor { + if (style == discord.ButtonStyle.Danger) return "red" + else if (style == discord.ButtonStyle.Success) return "green" + else if (style == discord.ButtonStyle.Primary) return "blue" + else return "gray" + } + /**Create the `ODTranscriptUserData` from a discord.js user. */ + #handleUserData(user:discord.User, member?:discord.GuildMember|null): ODTranscriptUserData { + const userData: ODTranscriptUserData = { + id:user.id, + username:user.username, + displayname:user.displayName, + pfp:user.displayAvatarURL(), + tag:null, + color:"#ffffff" + } + if (user.flags && user.flags.has("VerifiedBot")) userData.tag = "verified" + else if (user.system) userData.tag = "system" + else if (user.bot) userData.tag = "app" + if (member) userData.color = member.roles.highest.hexColor.replace("#000000","#ffffff") as discord.HexColorString + + return userData + } +} + +export interface ODTranscriptCollectorIncludeSettings { + /**Collect messages from normal discord users. */ + users: boolean, + /**Collect messages from bots & system users. */ + bots: boolean, + /**Collect messages from this bot. */ + client: boolean +} + +export interface ODTranscriptMessageData { + /**The message author. */ + author: ODTranscriptUserData, + /**The server this message originated from. */ + guild: string, + /**The channel this message originated from. */ + channel: string, + /**The id of this message. */ + id: string, + /**Is this message edited? */ + edited: boolean, + /**The unix timestamp of the creation of this message. */ + timestamp: number, + /**The type of message. */ + type: ODTranscriptMessageType, + /**The contents of this message. */ + content: string|null, + /**The embeds of this message. */ + embeds: ODTranscriptEmbedData[], + /**The files of this message. */ + files: ODTranscriptFileData[], + /**The components (buttons & dropdowns) of this message. */ + components: ODTranscriptComponentRowData[], + /**When this message is a reply to something, the data will be here. */ + reply: (ODTranscriptMessageReplyData|ODTranscriptInteractionReplyData|null), + /**All reactions of htis message. */ + reactions: ODTranscriptReactionData[] +} + +export type ODTranscriptMessageType = "default"|"important"|"ephemeral"|"pinned.message"|"welcome.message"|"boost.message"|"thread.message" + +export interface ODTranscriptUserData { + /**The id of this user. */ + id: string, + /**The username of this user. */ + username: string, + /**The display name of this user. */ + displayname: string, + /**The profile picture url of this user. */ + pfp: string, + /**The additional tag of this user. */ + tag: "app"|"verified"|"system"|null, + /**When in a server, this is the color of the highest role. */ + color: discord.HexColorString +} + +export interface ODTranscriptEmbedData { + /**The title of this embed. */ + title: string|null, + /**The description of this embed. */ + description: string|null, + /**The author image of this embed. */ + authorimg: string|null, + /**The author text of this embed. */ + authortext: string|null, + /**The footer image of this embed. */ + footerimg: string|null + /**The footer text of this embed. */ + footertext: string|null, + /**The color of this embed (hex color). */ + color: discord.HexColorString, + /**The image of this embed. */ + image: string|null, + /**The thumbnail of this embed. */ + thumbnail: string|null, + /**The url in the title of this embed. */ + url: string|null, + /**All fields available in this embed. */ + fields: ODTranscriptEmbedFieldData[] +} + +export interface ODTranscriptEmbedFieldData { + /**The name of this embed field. */ + name: string, + /**The value or contents of this embed field. */ + value: string, + /**Is this field rendered inline? */ + inline: boolean +} + +export interface ODTranscriptFileData { + /**The file type or extension. */ + type: string, + /**The size of this file. */ + size: number, + /**The unit used for the size of this file. */ + unit: "B"|"KB"|"MB"|"GB"|"TB", + /**The name of this file. */ + name: string, + /**The url of this file. */ + url: string, + /**Is this file a spoiler? */ + spoiler: boolean, + /**The alternative text for this file. */ + alt: string|null +} + +export interface ODTranscriptComponentRowData { + /**All components (buttons & dropdowns) present in this action row. */ + components: (ODTranscriptButtonComponentData|ODTranscriptDropdownComponentData)[] +} + +export interface ODTranscriptComponentData { + /**The custom id of this component. */ + id: string|null, + /**Is this component disabled? */ + disabled: boolean + /**The type of this component. */ + type: "button"|"dropdown" +} + +export interface ODTranscriptButtonComponentData extends ODTranscriptComponentData { + /**The type of this component. */ + type: "button" + /**The label of this button. */ + label: string|null, + /**The emoji of this button. */ + emoji: ODTranscriptEmojiData|null, + /**The color of this button. */ + color: ODValidButtonColor, + /**Is this button a url or button? */ + mode: "url"|"button", + /**The url of this button. */ + url: string|null +} + +export interface ODTranscriptDropdownComponentData extends ODTranscriptComponentData { + /**The type of this component. */ + type: "dropdown" + /**The placeholder in this dropdown. */ + placeholder: string|null, + /**All options available in this dropdown. */ + options: ODTranscriptDropdownComponentOptionData[] +} + +export interface ODTranscriptDropdownComponentOptionData { + /**The custom id of this dropdown option. */ + id: string, + /**The label of this dropdown option. */ + label: string|null, + /**The description of this dropdown option. */ + description: string|null, + /**The emoji of this dropdown option. */ + emoji: ODTranscriptEmojiData|null +} + +export interface ODTranscriptReplyData { + /**The type of reply. */ + type: "interaction"|"message", +} + +export interface ODTranscriptInteractionReplyData extends ODTranscriptReplyData { + /**The type of reply. */ + type: "interaction", + /**The bot used for this interaction. */ + user: ODTranscriptUserData, + /**The name of the slash command used. */ + name: string +} + +export interface ODTranscriptMessageReplyData extends ODTranscriptReplyData { + /**The type of reply. */ + type: "message", + /**The server this message originated from. */ + guild: string, + /**The channel this message originated from. */ + channel: string, + /**The id of this message. */ + id: string, + /**The author of this message. */ + user: ODTranscriptUserData, + /**The content of this message. */ + content: string|null +} + +export interface ODTranscriptEmojiData { + /**The id of this emoji. */ + id: string|null, + /**The name of this emoji. */ + name: string|null, + /**Is this emoji animated? */ + animated: boolean, + /**Is this a custom emoji (img/gif)? */ + custom: boolean, + /**The url or emoji. */ + emoji: string, +} + +export interface ODTranscriptReactionData extends ODTranscriptEmojiData { + /**The amount of emojis for this reaction. */ + amount: number, + /**Is this a super (nitro) reaction? */ + super: boolean +} + +export interface ODTranscriptHtmlV2Data { + version:"2", + otversion:string, + language:string, + style:{ + background:{ + enableCustomBackground:boolean, + backgroundModus:"color"|"image", + backgroundData:string + }, + header:{ + enableCustomHeader:boolean, + decoColor:string, + backgroundColor:string, + textColor:string + }, + stats:{ + enableCustomStats:boolean, + backgroundColor:string, + keyTextColor:string, + valueTextColor:string, + hideBackgroundColor:string, + hideTextColor:string + }, + favicon:{ + enableCustomFavicon:boolean, + imageUrl:string + } + }, + bot:{ + name:string, + id:string, + pfp:string + }, + ticket:{ + name:string, + id:string, + guildname:string, + guildid:string, + guildinvite:string|false, + + creatorname:string, + creatorid:string, + + closedbyname:string, + closedbyid:string, + + claimedname:string, + claimedid:string, + + creatorpfp:string, + closedbypfp:string, + claimedpfp:string, + + closedtime:number, + openedtime:number, + + components:{ + messages:number, + files:number, + embeds:number, + reactions:number, + interactions:{ + dropdowns:number, + buttons:number, + total:number + }, + attachments:{ + invites:number, + images:number, + gifs:number, + stickers:number + } + }, + roleColors:{id:string,color:string}[] + }, + messages:{ + author:{ + name:string, + id:string, + color:string, + pfp:string, + bot:boolean, + verifiedBot:boolean, + system:boolean + }, + content:string|false, + timestamp:number, + type:"normal", + important:boolean, + edited:boolean, + embeds:{ + title:string|false, + description:string|false, + authorimg:string|false, + authortext:string|false, + footerimg:string|false, + footertext:string|false, + color:string, + image:string|false, + thumbnail:string|false, + url:string|false, + fields:{name:string,value:string,inline:boolean}[] + }[], + attachments:( + { + type:"FILE", + name:string, + fileType:string, + size:string, + url:string + }|{ + type:"FILE:image", + name:string, + fileType:string, + size:string, + url:string + }|{ + type:"URL:invite", + guildId:string, + guildName:string, + guildSize:Number, + guildOnline:Number, + image:string, + url:string + }|{ + type:"URL:gif", + url:string + }|{ + type:"BUILDIN:sticker", + name:string, + url:string + } + )[], + components:( + { + type:"buttons", + buttons:{ + type:"interaction"|"url", + label:string|false, + icon:string|false, + color:"gray"|"green"|"red"|"blue", + id:string|false, + url:string|false, + disabled:boolean + }[] + }|{ + type:"dropdown", + placeholder:string|false, + options:{ + label:string|false, + icon:string|false, + description:string|false, + id:string|false + }[] + }|{ + type:"reactions", + reactions:{ + amount:number, + emoji:string, + type:"svg"|"image"|"gif" + }[] + } + )[], + reply:{ + type:"reply"|"command"|false, + user?:{ + name:string, + id:string, + color:string, + pfp:string, + bot:Boolean, + verifiedBot:Boolean, + system:Boolean + }, + replyOptions?:{ + content:string, + messageId:string, + channelId:string, + guildId:string + }, + commandOptions?:{ + interactionName:string, + interactionId:string + } + } + }[], + premium:{ + enabled:boolean, + premiumToken:string, + customCredits:{ + enable:boolean, + replaceText:string, + replaceURL:string, + enableReportBug:boolean + }, + customHeaderUrl:{ + enabled:boolean, + url:string, + text:string + }, + customTranscriptUrl:{ + enabled:boolean, + name:string + }, + customFavicon:{ + enabled:boolean, + image:string + }, + additionalFlags:string[] + } +} + +export interface ODTranscriptHtmlV2Response { + status:"success"|"error", + id:string, + 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 + } + } +} \ No newline at end of file diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts new file mode 100644 index 0000000..12aea74 --- /dev/null +++ b/src/core/startup/init.ts @@ -0,0 +1,205 @@ +import * as fs from "fs" + +let tempErrors: string[] = [] +const tempError = () => { + if (tempErrors.length > 0){ + console.log("\n\n==============================\n[OPEN TICKET ERROR]: "+tempErrors.join("\n[OPEN TICKET ERROR]: ")+"\n==============================\n\n") + process.exit(0) + } + tempErrors = [] +} + +const nodev = process.versions.node.split(".") +if (Number(nodev[0]) < 18){ + tempErrors.push("Invalid node.js version. Open Ticket requires node.js v18 or above!") +} +tempError() + +const moduleInstalled = (id:string, throwError:boolean) => { + try{ + require.resolve(id) + return true + + }catch{ + if (throwError) tempErrors.push("npm module \""+id+"\" is not installed! Install it via 'npm install "+id+"'") + return false + } +} + +moduleInstalled("discord.js",true) +moduleInstalled("ansis",true) +moduleInstalled("formatted-json-stringify",true) +moduleInstalled("tsx",true) +tempError() + +//init API +import * as api from "../api/api" //import for local use +export * as api from "../api/api" //export to other parts of bot + + +export const openticket = new api.ODMain() +console.log("\n--------------------------- OPEN TICKET STARTUP ---------------------------") +openticket.log("Logging system activated!","system") +openticket.debug.debug("Using Node.js "+process.version+"!") + +try{ + const packageJson = JSON.parse(fs.readFileSync("./package.json").toString()) + openticket.debug.debug("Using discord.js "+packageJson.dependencies["discord.js"]+"!") + openticket.debug.debug("Using ansis "+packageJson.dependencies["ansis"]+"!") + openticket.debug.debug("Using formatted-json-stringify "+packageJson.dependencies["formatted-json-stringify"]+"!") + openticket.debug.debug("Using tsx "+packageJson.dependencies["tsx"]+"!") +}catch{ + openticket.debug.debug("Failed to fetch module versions!") +} + +const timer = (ms:number): Promise => { + return new Promise((resolve) => { + setTimeout(() => { + resolve() + },ms) + }) +} + +interface ODUtilities { + /**## project `utility variable` + * This is the name of the project you are currently in. + * + * Developers can use this to create a multi-plugin compatible with all bots supporting the `open-discord` framework! + */ + project:"openticket" + /**## isBeta `utility variable` + * Check if you're running a beta version of Open Ticket. + */ + isBeta:boolean + /**## moduleInstalled `utility function` + * Use this function to check if an npm package is installed or not! + * @example utilities.moduleInstalled("discord.js") //check if discord.js is installed + */ + moduleInstalled(id:string): boolean + /**## timer `utility function` + * Use this to wait for a certain amount of milliseconds. This only works when using `await` + * @example await utilities.timer(1000) //wait 1sec + */ + timer(ms:number): Promise + /**## emojiTitle `utility function` + * Use this function to create a title with an emoji before/after the text. The style & divider are set in `openticket.defaults` + * @example utilities.emojiTitle("📎","Links") //create a title with an emoji based on the bot emoji style + */ + emojiTitle(emoji:string, text:string): string + /**## runAsync `utility function` + * Use this function to run a piece of code asyncronous without creating a separate function for it! + */ + runAsync(func:() => Promise): void + /**## timedAwait `utility function` + * Use this function to await a promise but reject after the certain timeout has been reached. + */ + timedAwait>(promise:ReturnValue, timeout:number, onError:(err:Error) => void): ReturnValue + /**## dateString `utility function` + * Use this function to create a short date string in the following format: `DD/MM/YYYY HH:MM:SS` + */ + dateString(date:Date): string + /**## asyncReplace `utility function` + * Same as `string.replace(search, value)` but with async compatibility + */ + asyncReplace(text:string, regex:RegExp, func:(value:string,...args:any[]) => Promise): Promise + /**## easterEggs `utility object` + * Object containing data for Open Ticket easter eggs. + */ + easterEggs: api.ODEasterEggs, + /**## ODVersionMigration `utility class` + * This class is used to manage data migration between Open Ticket versions. + * + * It shouldn't be used by plugins because this is an internal API feature! + */ + ODVersionMigration:new (version:api.ODVersion,func:() => void|Promise) => ODVersionMigration +} + +/**## ODVersionMigration `utility class` + * This class is used to manage data migration between Open Ticket versions. + * + * It shouldn't be used by plugins because this is an internal API feature! + */ +class ODVersionMigration { + /**The version to migrate data to */ + version: api.ODVersion + /**The migration function */ + #func: () => void|Promise + + constructor(version:api.ODVersion,func:() => void|Promise){ + this.version = version + this.#func = func + } + /**Run this version migration as a plugin. Returns `false` when someting goes wrong. */ + async migrate(): Promise { + try{ + await this.#func() + return true + }catch{ + return false + } + } +} + +export const utilities: ODUtilities = { + project:"openticket", + isBeta:true, + moduleInstalled:(id:string) => { + return moduleInstalled(id,false) + }, + timer, + emojiTitle(emoji:string, text:string){ + const style = openticket.defaults.getDefault("emojiTitleStyle") + const divider = openticket.defaults.getDefault("emojiTitleDivider") + + if (style == "disabled") return text + else if (style == "before") return emoji+divider+text + else if (style == "after") return text+divider+emoji + else if (style == "double") return emoji+divider+text+divider+emoji + else return text + }, + runAsync(func){ + func() + }, + timedAwait(promise:ReturnValue,timeout:number,onError:(err:Error) => void): ReturnValue { + let allowResolve = true + return new Promise(async (resolve,reject) => { + //set timeout & stop if it is before the promise resolved + setTimeout(() => { + allowResolve = false + reject("utilities.timedAwait() => Promise Timeout") + },timeout) + + //get promise result & return if not already rejected + try{ + const res = await promise + if (allowResolve) resolve(res) + }catch(err){ + onError(err) + } + return promise + }) as ReturnValue + }, + dateString(date): string { + return `${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}` + }, + async asyncReplace(text,regex,func): Promise { + const promises: Promise[] = [] + text.replace(regex,(match,...args) => { + promises.push(func(match,...args)) + return match + }) + const data = await Promise.all(promises) + const result = text.replace(regex,(match) => { + const replaceResult = data.shift() + return replaceResult ?? match + }) + return result + }, + easterEggs:{ + creator:"779742674932072469", + translators:[ + "779742674932072469" + ] + }, + ODVersionMigration +} \ No newline at end of file diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts new file mode 100644 index 0000000..b090bca --- /dev/null +++ b/src/core/startup/manageMigration.ts @@ -0,0 +1,84 @@ +import {openticket, api, utilities} from "../../index" + +export const loadVersionMigrationSystem = async () => { + //ENTER MIGRATION CONTEXT + await preloadMigrationContext() + + const lastVersion = isMigrationRequired() + openticket.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("openticket:last-version",openticket.versions.get("openticket:version").toString())) + if (lastVersion && !openticket.flags.get("openticket:no-migration").value){ + //MIGRATION IS REQUIRED + openticket.log("Detected old data!","info") + openticket.log("Starting closed API context...","debug") + await utilities.timer(600) + openticket.log("Migrating data to new version...","debug") + await loadAllVersionMigrations(lastVersion) + openticket.log("Stopping closed API context...","debug") + await utilities.timer(400) + openticket.log("All data is now up to date!","info") + await utilities.timer(200) + console.log("---------------------------------------------------------------------") + } + saveAllVersionsToDatabase() + + //DEFAULT FLAGS + if (openticket.flags.exists("openticket:no-plugins") && openticket.flags.get("openticket:no-plugins").value) openticket.defaults.setDefault("pluginLoading",false) + if (openticket.flags.exists("openticket:soft-plugins") && openticket.flags.get("openticket:soft-plugins").value) openticket.defaults.setDefault("softPluginLoading",true) + if (openticket.flags.exists("openticket:crash") && openticket.flags.get("openticket:crash").value) openticket.defaults.setDefault("crashOnError",true) + if (openticket.flags.exists("openticket:force-slash-update") && openticket.flags.get("openticket:force-slash-update").value) openticket.defaults.setDefault("forceSlashCommandRegistration",true) + + //LEAVE MIGRATION CONTEXT + await unloadMigrationContext() +} + +const preloadMigrationContext = async () => { + openticket.debug.debug("-- MIGRATION CONTEXT START --") + await (await import("../../data/framework/flagLoader.ts")).loadAllFlags() + openticket.flags.init() + await (await import("../../data/framework/configLoader.ts")).loadAllConfigs() + await (await import("../../data/framework/databaseLoader.ts")).loadAllDatabases() + openticket.debug.visible = true +} + +const unloadMigrationContext = async () => { + openticket.debug.visible = false + openticket.databases.getAll().forEach((database) => openticket.databases.remove(database.id)) + openticket.configs.getAll().forEach((config) => openticket.configs.remove(config.id)) + openticket.flags.getAll().forEach((flag) => openticket.flags.remove(flag.id)) + openticket.debug.debug("-- MIGRATION CONTEXT END --") +} + +const isMigrationRequired = (): false|api.ODVersion => { + const rawVersion = openticket.databases.get("openticket:global").get("openticket:last-version","openticket:version") + if (!rawVersion) return false + const version = api.ODVersion.fromString("openticket:last-version",rawVersion) + if (openticket.versions.get("openticket:version").compare(version) == "higher"){ + return version + }else return false +} + +const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { + const migrations = (await import("./migration.ts")).migrations + migrations.sort((a,b) => { + const comparison = a.version.compare(b.version) + if (comparison == "equal") return 0 + else if (comparison == "higher") return 1 + else return -1 + }) + for (const migration of migrations){ + if (migration.version.compare(lastVersion) == "higher"){ + const success = await migration.migrate() + if (success) openticket.log("Migrated data to "+migration.version.toString()+"!","debug",[ + {key:"success",value:success ? "true" : "false"} + ]) + } + } +} + +const saveAllVersionsToDatabase = async () => { + const globalDatabase = openticket.databases.get("openticket:global") + + openticket.versions.getAll().forEach((version) => { + globalDatabase.set("openticket:last-version",version.id.value,version.toString()) + }) +} \ No newline at end of file diff --git a/src/core/startup/migration.ts b/src/core/startup/migration.ts new file mode 100644 index 0000000..96df7a0 --- /dev/null +++ b/src/core/startup/migration.ts @@ -0,0 +1,8 @@ +import {openticket, api, utilities} from "../../index" + +export const migrations = [ + //MIGRATE TO v4.0.0 + new utilities.ODVersionMigration(api.ODVersion.fromString("openticket:version","v4.0.0"),async () => { + //nothing needs to be transferred :) + }) +] \ No newline at end of file diff --git a/src/core/startup/pluginLauncher.ts b/src/core/startup/pluginLauncher.ts new file mode 100644 index 0000000..c14bfb9 --- /dev/null +++ b/src/core/startup/pluginLauncher.ts @@ -0,0 +1,197 @@ +import {openticket, api, utilities} from "../../index" +import fs from "fs" +import { ODPluginError } from "../api/api" + +export const loadAllPlugins = async () => { + //start launching plugins + openticket.log("Loading plugins...","system") + let initPluginError: boolean = false + + if (!fs.existsSync("./plugins")){ + openticket.log("Couldn't find ./plugins directory, canceling all plugin execution!","error") + return + } + const plugins = fs.readdirSync("./plugins") + + //check & validate + plugins.forEach(async (p) => { + //prechecks + if (!fs.statSync("./plugins/"+p).isDirectory()) return openticket.log("Plugin is not a directory, canceling plugin execution...","plugin",[ + {key:"plugin",value:"./plugins/"+p} + ]) + if (!fs.existsSync("./plugins/"+p+"/plugin.json")){ + initPluginError = true + openticket.log("Plugin doesn't have a plugin.json, canceling plugin execution...","plugin",[ + {key:"plugin",value:"./plugins/"+p} + ]) + return + } + + //plugin loading + try { + const rawplugindata: api.ODPluginData = JSON.parse(fs.readFileSync("./plugins/"+p+"/plugin.json").toString()) + + if (typeof rawplugindata != "object") throw new ODPluginError("Failed to load plugin.json") + if (typeof rawplugindata.id != "string") throw new ODPluginError("Failed to load plugin.json/id") + if (typeof rawplugindata.name != "string") throw new ODPluginError("Failed to load plugin.json/name") + if (typeof rawplugindata.version != "string") throw new ODPluginError("Failed to load plugin.json/version") + if (typeof rawplugindata.startFile != "string") throw new ODPluginError("Failed to load plugin.json/startFile") + + if (typeof rawplugindata.enabled != "boolean") throw new ODPluginError("Failed to load plugin.json/enabled") + if (typeof rawplugindata.priority != "number") throw new ODPluginError("Failed to load plugin.json/priority") + if (!Array.isArray(rawplugindata.events)) throw new ODPluginError("Failed to load plugin.json/events") + + if (!Array.isArray(rawplugindata.npmDependencies)) throw new ODPluginError("Failed to load plugin.json/npmDependencies") + if (!Array.isArray(rawplugindata.requiredPlugins)) throw new ODPluginError("Failed to load plugin.json/requiredPlugins") + if (!Array.isArray(rawplugindata.incompatiblePlugins)) throw new ODPluginError("Failed to load plugin.json/incompatiblePlugins") + + if (typeof rawplugindata.details != "object") throw new ODPluginError("Failed to load plugin.json/details") + if (typeof rawplugindata.details.author != "string") throw new ODPluginError("Failed to load plugin.json/details/author") + if (typeof rawplugindata.details.shortDescription != "string") throw new ODPluginError("Failed to load plugin.json/details/shortDescription") + if (typeof rawplugindata.details.longDescription != "string") throw new ODPluginError("Failed to load plugin.json/details/longDescription") + if (typeof rawplugindata.details.imageUrl != "string") throw new ODPluginError("Failed to load plugin.json/details/imageUrl") + if (typeof rawplugindata.details.projectUrl != "string") throw new ODPluginError("Failed to load plugin.json/details/projectUrl") + if (!Array.isArray(rawplugindata.details.tags)) throw new ODPluginError("Failed to load plugin.json/details/tags") + + if (rawplugindata.id != p) throw new ODPluginError("Failed to load plugin, directory name is required to match the id") + + if (openticket.plugins.exists(rawplugindata.id)) throw new ODPluginError("Failed to load plugin, this id already exists in another plugin") + + //plugin.json is valid => load plugin + const plugin = new api.ODPlugin(p,rawplugindata) + openticket.plugins.add(plugin) + + }catch(e){ + //when any of the above errors happen, crash the bot when soft mode isn't enabled + initPluginError = true + openticket.log(e.message+", canceling plugin execution...","plugin",[ + {key:"path",value:"./plugins/"+p} + ]) + openticket.log("You can see more about this error in the ./otdebug.txt file!","info") + openticket.debugfile.writeText(e.stack) + + //try to get some crashed plugin data + try{ + const rawplugindata: api.ODPluginData = JSON.parse(fs.readFileSync("./plugins/"+p+"/plugin.json").toString()) + openticket.plugins.unknownCrashedPlugins.push({ + name:rawplugindata.name ?? "./plugins/"+p, + description:(rawplugindata.details && rawplugindata.details.shortDescription) ? rawplugindata.details.shortDescription : "This plugin crashed :(", + }) + }catch{} + } + }) + + //sorted plugins (based on priority) + const sortedPlugins = openticket.plugins.getAll().sort((a,b) => { + return (b.priority - a.priority) + }) + + //check for incompatible & missing plugins/dependencies + const incompatibilities: {from:string,to:string}[] = [] + const missingDependencies: {id:string,missing:string}[] = [] + const missingPlugins: {id:string,missing:string}[] = [] + + //go trough all plugins for errors + sortedPlugins.forEach((plugin) => { + const from = plugin.id.value + plugin.data.incompatiblePlugins.forEach((to) => { + //deny incompatibility if it already exists + if (incompatibilities.find((p) => (p.from == from && p.to == to) || (p.to == from && p.from == to))) return + + //check for existence of both plugins => add to list + if (openticket.plugins.exists(to)) incompatibilities.push({from,to}) + }) + plugin.dependenciesInstalled().forEach((missing) => missingDependencies.push({id:from,missing})) + plugin.pluginsInstalled(openticket.plugins).forEach((missing) => missingPlugins.push({id:from,missing})) + }) + + //handle all incompatibilities + incompatibilities.forEach((match) => { + const fromPlugin = openticket.plugins.get(match.from) + if (fromPlugin && !fromPlugin.crashed){ + fromPlugin.crashed = true + fromPlugin.crashReason = "incompatible.plugin" + } + const toPlugin = openticket.plugins.get(match.to) + if (toPlugin && !toPlugin.crashed){ + toPlugin.crashed = true + toPlugin.crashReason = "incompatible.plugin" + } + + openticket.log(`Incompatible plugins => "${match.from}" & "${match.to}", canceling plugin execution...`,"plugin",[ + {key:"path1",value:"./plugins/"+match.from}, + {key:"path2",value:"./plugins/"+match.to} + ]) + initPluginError = true + }) + + //handle all missing dependencies + missingDependencies.forEach((match) => { + const plugin = openticket.plugins.get(match.id) + if (plugin && !plugin.crashed){ + plugin.crashed = true + plugin.crashReason = "missing.dependency" + } + + openticket.log(`Missing npm dependency "${match.missing}", canceling plugin execution...`,"plugin",[ + {key:"path",value:"./plugins/"+match.id} + ]) + initPluginError = true + }) + + //handle all missing plugins + missingPlugins.forEach((match) => { + const plugin = openticket.plugins.get(match.id) + if (plugin && !plugin.crashed){ + plugin.crashed = true + plugin.crashReason = "missing.plugin" + } + + openticket.log(`Missing required plugin "${match.missing}", canceling plugin execution...`,"plugin",[ + {key:"path",value:"./plugins/"+match.id} + ]) + initPluginError = true + }) + + //exit on error (when soft mode disabled) + if (!openticket.defaults.getDefault("softPluginLoading") && initPluginError){ + console.log("") + openticket.log("Please fix all plugin errors above & try again!","error") + process.exit(1) + } + + //preload all events required for every plugin + for (const plugin of sortedPlugins){ + if (plugin.enabled) plugin.data.events.forEach((event) => openticket.events.add(new api.ODEvent(event))) + } + + //execute all working plugins + for (const plugin of sortedPlugins){ + const status = await plugin.execute(openticket.debug,false) + + //exit on error (when soft mode disabled) + if (!status && !openticket.defaults.getDefault("softPluginLoading")){ + console.log("") + openticket.log("Please fix all plugin errors above & try again!","error") + process.exit(1) + } + } + + for (const plugin of sortedPlugins){ + if (plugin.enabled){ + openticket.debug.debug("Plugin \""+plugin.id.value+"\" loaded",[ + {key:"status",value:(plugin.crashed ? "crashed" : "success")}, + {key:"crashReason",value:(plugin.crashed ? (plugin.crashReason ?? "/") : "/")}, + {key:"author",value:plugin.details.author}, + {key:"version",value:plugin.version.toString()}, + {key:"priority",value:plugin.priority.toString()} + ]) + }else{ + openticket.debug.debug("Plugin \""+plugin.id.value+"\" disabled",[ + {key:"author",value:plugin.details.author}, + {key:"version",value:plugin.version.toString()}, + {key:"priority",value:plugin.priority.toString()} + ]) + } + } +} \ No newline at end of file diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts new file mode 100644 index 0000000..1e02728 --- /dev/null +++ b/src/data/framework/checkerLoader.ts @@ -0,0 +1,591 @@ +import {openticket, api, utilities} from "../../index" + +const generalConfig = openticket.configs.get("openticket:general") + +export const loadAllConfigCheckers = async () => { + openticket.checkers.add(new api.ODChecker("openticket:general",openticket.checkers.storage,0,openticket.configs.get("openticket:general"),defaultGeneralStructure)) + openticket.checkers.add(new api.ODChecker("openticket:options",openticket.checkers.storage,1,openticket.configs.get("openticket:options"),defaultOptionsStructure)) + openticket.checkers.add(new api.ODChecker("openticket:panels",openticket.checkers.storage,0,openticket.configs.get("openticket:panels"),defaultPanelsStructure)) + openticket.checkers.add(new api.ODChecker("openticket:questions",openticket.checkers.storage,2,openticket.configs.get("openticket:questions"),defaultQuestionsStructure)) + openticket.checkers.add(new api.ODChecker("openticket:transcripts",openticket.checkers.storage,0,openticket.configs.get("openticket:transcripts"),defaultTranscriptsStructure)) +} + +export const loadAllConfigCheckerFunctions = async () => { + openticket.checkers.functions.add(new api.ODCheckerFunction("openticket:unused-options",defaultUnusedOptionsFunction)) + openticket.checkers.functions.add(new api.ODCheckerFunction("openticket:dropdown-options",defaultDropdownOptionsFunction)) +} + +export const loadAllConfigCheckerTranslations = async () => { + if ((generalConfig && generalConfig.data.system && generalConfig.data.system.useTranslatedConfigChecker) ? generalConfig.data.system.useTranslatedConfigChecker : false){ + registerDefaultCheckerSystemTranslations() //translate checker system text + registerDefaultCheckerMessageTranslations() //translate checker messages + registerDefaultCheckerCustomTranslations() //translate custom checker messages + } +} + +//GLOBAL FUNCTIONS +export const registerDefaultCheckerSystemTranslations = () => { + const tm = openticket.checkers.translation + const lm = openticket.languages + + //SYSTEM + //tm.quickTranslate(lm,"checker.system.headerOpenTicket","other","openticket:header-openticket") //OPEN TICKET (ignore) + tm.quickTranslate(lm,"checker.system.typeError","other","openticket:type-error") // [ERROR] (ignore) + tm.quickTranslate(lm,"checker.system.typeWarning","other","openticket:type-warning") // [WARNING] (ignore) + tm.quickTranslate(lm,"checker.system.typeInfo","other","openticket:type-info") // [INFO] (ignore) + tm.quickTranslate(lm,"checker.system.headerConfigChecker","other","openticket:header-configchecker") // CONFIG CHECKER + tm.quickTranslate(lm,"checker.system.headerDescription","other","openticket:header-description") // check for errors in you config files! + tm.quickTranslate(lm,"checker.system.footerError","other","openticket:footer-error") // the bot won't start until all {0}'s are fixed! + tm.quickTranslate(lm,"checker.system.footerWarning","other","openticket:footer-warning") // it's recommended to fix all {0}'s before starting! + tm.quickTranslate(lm,"checker.system.footerSupport","other","openticket:footer-support") // SUPPORT: {0} - DOCS: {1} + tm.quickTranslate(lm,"checker.system.compactInformation","other","openticket:compact-information") // use {0} for more information! + tm.quickTranslate(lm,"checker.system.dataPath","other","openticket:data-path") // path + tm.quickTranslate(lm,"checker.system.dataDocs","other","openticket:data-docs") // docs + tm.quickTranslate(lm,"checker.system.dataMessages","other","openticket:data-message") // message +} + +export const registerDefaultCheckerMessageTranslations = () => { + const tm = openticket.checkers.translation + const lm = openticket.languages + + //STRUCTURES + tm.quickTranslate(lm,"checker.messages.invalidType","message","openticket:invalid-type") // This property needs to be the type: {0}! + tm.quickTranslate(lm,"checker.messages.propertyMissing","message","openticket:property-missing") // The property {0} is missing from this object! + tm.quickTranslate(lm,"checker.messages.propertyOptional","message","openticket:property-optional") // The property {0} is optional in this object! + tm.quickTranslate(lm,"checker.messages.objectDisabled","message","openticket:object-disabled") // This object is disabled, enable it using {0}! + tm.quickTranslate(lm,"checker.messages.nullInvalid","message","openticket:null-invalid") // This property can't be null! + tm.quickTranslate(lm,"checker.messages.switchInvalidType","message","openticket:switch-invalid-type") // This needs to be one of the following types: {0}! + tm.quickTranslate(lm,"checker.messages.objectSwitchInvalid","message","openticket:object-switch-invalid-type") // This object needs to be one of the following types: {0}! + + tm.quickTranslate(lm,"checker.messages.stringTooShort","message","openticket:string-too-short") // This string can't be shorter than {0} characters! + tm.quickTranslate(lm,"checker.messages.stringTooLong","message","openticket:string-too-long") // This string can't be longer than {0} characters! + tm.quickTranslate(lm,"checker.messages.stringLengthInvalid","message","openticket:string-length-invalid") // This string needs to be {0} characters long! + tm.quickTranslate(lm,"checker.messages.stringStartsWith","message","openticket:string-starts-with") // This string needs to start with {0}! + tm.quickTranslate(lm,"checker.messages.stringEndsWith","message","openticket:string-ends-with") // This string needs to end with {0}! + tm.quickTranslate(lm,"checker.messages.stringContains","message","openticket:string-contains") // This string needs to contain {0}! + tm.quickTranslate(lm,"checker.messages.stringChoices","message","openticket:string-choices") // This string can only be one of the following values: {0}! + tm.quickTranslate(lm,"checker.messages.stringRegex","message","openticket:string-regex") // This string is invalid! + + tm.quickTranslate(lm,"checker.messages.numberTooShort","message","openticket:number-too-short") // This number can't be shorter than {0} characters! + tm.quickTranslate(lm,"checker.messages.numberTooLong","message","openticket:number-too-long") // This number can't be longer than {0} characters! + tm.quickTranslate(lm,"checker.messages.numberLengthInvalid","message","openticket:number-length-invalid") // This number needs to be {0} characters long! + tm.quickTranslate(lm,"checker.messages.numberTooSmall","message","openticket:number-too-small") // This number needs to be at least {0}! + tm.quickTranslate(lm,"checker.messages.numberTooLarge","message","openticket:number-too-large") // This number needs to be at most {0}! + tm.quickTranslate(lm,"checker.messages.numberNotEqual","message","openticket:number-not-equal") // This number needs to be {0}! + tm.quickTranslate(lm,"checker.messages.numberStep","message","openticket:number-step") // This number needs to be a multiple of {0}! + tm.quickTranslate(lm,"checker.messages.numberStepOffset","message","openticket:number-step-offset") // This number needs to be a multiple of {0} starting with {1}! + tm.quickTranslate(lm,"checker.messages.numberStartsWith","message","openticket:number-starts-with") // This number needs to start with {0}! + tm.quickTranslate(lm,"checker.messages.numberEndsWith","message","openticket:number-ends-with") // This number needs to end with {0}! + tm.quickTranslate(lm,"checker.messages.numberContains","message","openticket:number-contains") // This number needs to contain {0}! + tm.quickTranslate(lm,"checker.messages.numberChoices","message","openticket:number-choices") // This number can only be one of the following values: {0}! + tm.quickTranslate(lm,"checker.messages.numberFloat","message","openticket:number-float") // This number can't be a decimal! + tm.quickTranslate(lm,"checker.messages.numberNegative","message","openticket:number-negative") // This number can't be negative! + tm.quickTranslate(lm,"checker.messages.numberPositive","message","openticket:number-positive") // This number can't be positive! + tm.quickTranslate(lm,"checker.messages.numberZero","message","openticket:number-zero") // This number can't be zero! + + tm.quickTranslate(lm,"checker.messages.booleanTrue","message","openticket:boolean-true") // This boolean can't be true! + tm.quickTranslate(lm,"checker.messages.booleanFalse","message","openticket:boolean-false") // This boolean can't be false! + + tm.quickTranslate(lm,"checker.messages.arrayEmptyDisabled","message","openticket:array-empty-disabled") // This array isn't allowed to be empty! + tm.quickTranslate(lm,"checker.messages.arrayEmptyRequired","message","openticket:array-empty-required") // This array is required to be empty! + tm.quickTranslate(lm,"checker.messages.arrayTooShort","message","openticket:array-too-short") // This array needs to have a length of at least {0}! + tm.quickTranslate(lm,"checker.messages.arrayTooLong","message","openticket:array-too-long") // This array needs to have a length of at most {0}! + tm.quickTranslate(lm,"checker.messages.arrayLengthInvalid","message","openticket:array-length-invalid") // This array needs to have a length of {0}! + tm.quickTranslate(lm,"checker.messages.arrayInvalidTypes","message","openticket:array-invalid-types") // This array can only contain the following types: {0}! + tm.quickTranslate(lm,"checker.messages.arrayDouble","message","openticket:array-double") // This array doesn't allow the same value twice! + + tm.quickTranslate(lm,"checker.messages.discordInvalidId","message","openticket:discord-invalid-id") // This is an invalid discord {0} id! + tm.quickTranslate(lm,"checker.messages.discordInvalidIdOptions","message","openticket:discord-invalid-id-options") // This is an invalid discord {0} id! You can also use one of these: {1}! + tm.quickTranslate(lm,"checker.messages.discordInvalidToken","message","openticket:discord-invalid-token") // This is an invalid discord token (syntactically)! + tm.quickTranslate(lm,"checker.messages.colorInvalid","message","openticket:color-invalid") // This is an invalid hex color! + tm.quickTranslate(lm,"checker.messages.emojiTooShort","message","openticket:emoji-too-short") // This string needs to have at least {0} emoji's! + tm.quickTranslate(lm,"checker.messages.emojiTooLong","message","openticket:emoji-too-long") // This string needs to have at most {0} emoji's! + tm.quickTranslate(lm,"checker.messages.emojiCustom","message","openticket:emoji-custom") // This emoji can't be a custom discord emoji! + tm.quickTranslate(lm,"checker.messages.emojiInvalid","message","openticket:emoji-invalid") // This is an invalid emoji! + tm.quickTranslate(lm,"checker.messages.urlInvalid","message","openticket:url-invalid") // This url is invalid! + tm.quickTranslate(lm,"checker.messages.urlInvalidHttp","message","openticket:url-invalid-http") // This url can only use the https:// protocol! + tm.quickTranslate(lm,"checker.messages.urlInvalidProtocol","message","openticket:url-invalid-protocol") // This url can only use the http:// & https:// protocols! + tm.quickTranslate(lm,"checker.messages.urlInvalidHostname","message","openticket:url-invalid-hostname") // This url has a disallowed hostname! + tm.quickTranslate(lm,"checker.messages.urlInvalidExtension","message","openticket:url-invalid-extension") // This url has an invalid extension! Choose between: {0}! + tm.quickTranslate(lm,"checker.messages.urlInvalidPath","message","openticket:url-invalid-path") // This url has an invalid path! + tm.quickTranslate(lm,"checker.messages.idNotUnique","message","openticket:id-not-unique") // This id isn't unique, use another id instead! + tm.quickTranslate(lm,"checker.messages.idNonExistent","message","openticket:id-non-existent") // The id {0} doesn't exist! +} + +export const registerDefaultCheckerCustomTranslations = () => { + const tm = openticket.checkers.translation + const lm = openticket.languages + + //CUSTOM + tm.quickTranslate(lm,"checker.messages.invalidLanguage","message","openticket:invalid-language") // This is an invalid language! + tm.quickTranslate(lm,"checker.messages.invalidButton","message","openticket:invalid-button") // This button needs to have at least an {0} or {1}! + tm.quickTranslate(lm,"checker.messages.unusedOption","message","openticket:unused-option") // The option {0} isn't used anywhere! + tm.quickTranslate(lm,"checker.messages.unusedQuestion","message","openticket:unused-question") // The question {0} isn't used anywhere! + tm.quickTranslate(lm,"checker.messages.dropdownOption","message","openticket:dropdown-option") // A panel with dropdown enabled can only contain options of the 'ticket' type! +} + +//UTILITY FUNCTIONS +const createMsgStructure = (id:api.ODValidId) => { + return new api.ODCheckerObjectStructure(id,{children:[ + {key:"dm",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:msg-dm",{})}, + {key:"logs",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:msg-logs",{})}, + ]}) +} +const createTicketEmbedStructure = (id:api.ODValidId) => { + return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[ + {key:"title",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-embed-text",{maxLength:256})}, + {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-embed-description",{maxLength:4096})}, + {key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:ticket-embed-color",true,true)}, + + {key:"image",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:ticket-embed-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, + {key:"thumbnail",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:ticket-embed-thumbnail",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, + {key:"fields",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("openticket:ticket-embed-fields",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:ticket-embed-fields",{children:[ + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-embed-field-name",{minLength:1,maxLength:256})}, + {key:"value",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-embed-field-value",{minLength:1,maxLength:1024})}, + {key:"inline",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-embed-field-inline",{})} + ]})})}, + {key:"timestamp",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-embed-timestamp",{})} + ]})}) +} +const createTicketPingStructure = (id:api.ODValidId) => { + return new api.ODCheckerObjectStructure(id,{children:[ + {key:"@here",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-ping-here",{})}, + {key:"@everyone",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-ping-everyone",{})}, + {key:"custom",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:ticket-ping-custom","role",[],{allowDoubles:false})}, + ]}) +} +const createPanelEmbedStructure = (id:api.ODValidId) => { + return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[ + {key:"title",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-embed-text",{maxLength:256})}, + {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-embed-description",{maxLength:4096})}, + {key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:panel-embed-color",true,true)}, + {key:"url",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:panel-embed-url",true,{allowHttp:false})}, + + {key:"image",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:panel-embed-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, + {key:"thumbnail",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:panel-embed-thumbnail",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, + + {key:"footer",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-embed-footer",{maxLength:2048})}, + {key:"fields",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("openticket:panel-embed-fields",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:panel-embed-fields",{children:[ + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-embed-field-name",{minLength:1,maxLength:256})}, + {key:"value",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-embed-field-value",{minLength:1,maxLength:1024})}, + {key:"inline",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-embed-field-inline",{})} + ]})})}, + {key:"timestamp",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-embed-timestamp",{})} + ]})}) +} + +//STRUCTURES +export const defaultGeneralStructure = new api.ODCheckerObjectStructure("openticket:general",{children:[ + //BASIC + {key:"token",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordToken("openticket:token")}, + {key:"tokenFromENV",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:token-env",{})}, + {key:"mainColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:main-color",true,false)}, + {key:"language",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:language",{ + custom:(checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + + if (typeof value != "string") return false + else if (!openticket.defaults.getDefault("languageList").includes(value)){ + checker.createMessage("openticket:invalid-language","error","This is an invalid language!",lt,null,[],locationId,locationDocs) + return false + }else return true + }, + })}, + {key:"prefix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:prefix",{minLength:1})}, + {key:"serverId",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:server-id","server",false,[])}, + {key:"globalAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:global-admins","role",[],{allowDoubles:false})}, + {key:"slashCommands",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:slash-commands",{})}, + {key:"textCommands",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:text-commands",{})}, + + //STATUS + {key:"status",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:status",{ + property:"enabled", + enabledValue:true, + checker:new api.ODCheckerObjectStructure("openticket:status",{children:[ + {key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:status-type",{choices:["listening","watching","playing","custom"]})}, + {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:status-text",{minLength:1,maxLength:128})}, + {key:"status",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:status-type",{choices:["online","invisible","idle","dnd"]})}, + ]}) + })}, + + //SYSTEM + {key:"system",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:system",{children:[ + {key:"removeParticipantsOnClose",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:remove-participants-on-close",{})}, + {key:"replyOnTicketCreation",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:reply-on-ticket-creation",{})}, + {key:"replyOnReactionRole",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:reply-on-reaction-role",{})}, + {key:"useTranslatedConfigChecker",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:use-translated-config-checker",{})}, + {key:"preferSlashOverText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:prefer-slash-over-text",{})}, + {key:"sendErrorOnUnknownCommand",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:send-error-on-unknown-command",{})}, + {key:"questionFieldsInCodeBlock",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:question-fields-in-code-block",{})}, + {key:"disableVerifyBars",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:disable-verify-bars",{})}, + {key:"useRedErrorEmbeds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:use-red-error-embeds",{})}, + {key:"emojiStyle",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:emoji-style",{choices:["before","after","double","disabled"]})}, + + {key:"enableTicketClaimButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-ticket-claim-buttons",{})}, + {key:"enableTicketCloseButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-ticket-close-buttons",{})}, + {key:"enableTicketPinButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-ticket-pin-buttons",{})}, + {key:"enableTicketDeleteButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-ticket-delete-buttons",{})}, + {key:"enableTicketActionWithReason",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-ticket-action-with-reason",{})}, + {key:"enableDeleteWithoutTranscript",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-delete-without-transcript",{})}, + + {key:"logs",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:system-logs",{ + property:"enabled", + enabledValue:true, + checker:new api.ODCheckerObjectStructure("openticket:system-logs",{children:[ + {key:"channel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:log-channel","channel",false,[])}, + ]}) + })}, + + {key:"limits",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:limits",{children:[ + {key:"globalMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:limits-global",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})}, + {key:"userMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:limits-user",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})} + ]})})}, + + {key:"permissions",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:system-permissions",{children:[ + {key:"help",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-help","role",false,["admin","everyone","none"])}, + {key:"panel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-panel","role",false,["admin","everyone","none"])}, + {key:"ticket",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-ticket","role",false,["admin","everyone","none"])}, + {key:"close",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-close","role",false,["admin","everyone","none"])}, + {key:"delete",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-delete","role",false,["admin","everyone","none"])}, + {key:"reopen",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-reopen","role",false,["admin","everyone","none"])}, + {key:"claim",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-claim","role",false,["admin","everyone","none"])}, + {key:"unclaim",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-unclaim","role",false,["admin","everyone","none"])}, + {key:"pin",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-pin","role",false,["admin","everyone","none"])}, + {key:"unpin",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-unpin","role",false,["admin","everyone","none"])}, + {key:"move",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-move","role",false,["admin","everyone","none"])}, + {key:"rename",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-rename","role",false,["admin","everyone","none"])}, + {key:"add",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-add","role",false,["admin","everyone","none"])}, + {key:"remove",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-remove","role",false,["admin","everyone","none"])}, + {key:"blacklist",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-blacklist","role",false,["admin","everyone","none"])}, + {key:"stats",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-stats","role",false,["admin","everyone","none"])}, + {key:"clear",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-clear","role",false,["admin","everyone","none"])}, + {key:"autoclose",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-autoclose","role",false,["admin","everyone","none"])}, + {key:"autodelete",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-autodelete","role",false,["admin","everyone","none"])} + ]})}, + + {key:"messages",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:system-permissions",{children:[ + {key:"creation",optional:false,priority:0,checker:createMsgStructure("openticket:msg-creation")}, + {key:"closing",optional:false,priority:0,checker:createMsgStructure("openticket:msg-closing")}, + {key:"deleting",optional:false,priority:0,checker:createMsgStructure("openticket:msg-deleting")}, + {key:"reopening",optional:false,priority:0,checker:createMsgStructure("openticket:msg-reopening")}, + {key:"claiming",optional:false,priority:0,checker:createMsgStructure("openticket:msg-claiming")}, + {key:"pinning",optional:false,priority:0,checker:createMsgStructure("openticket:msg-pinning")}, + {key:"adding",optional:false,priority:0,checker:createMsgStructure("openticket:msg-adding")}, + {key:"removing",optional:false,priority:0,checker:createMsgStructure("openticket:msg-removing")}, + {key:"renaming",optional:false,priority:0,checker:createMsgStructure("openticket:msg-renaming")}, + {key:"moving",optional:false,priority:0,checker:createMsgStructure("openticket:msg-moving")}, + {key:"blacklisting",optional:false,priority:0,checker:createMsgStructure("openticket:msg-blacklisting")}, + {key:"roleAdding",optional:false,priority:0,checker:createMsgStructure("openticket:msg-role-adding")}, + {key:"roleRemoving",optional:false,priority:0,checker:createMsgStructure("openticket:msg-role-removing")} + ]})}, + ]})} +]}) + +export const defaultOptionsStructure = new api.ODCheckerArrayStructure("openticket:options",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectSwitchStructure("openticket:options",{objects:[ + //TICKET + {name:"ticket",priority:0,properties:[{key:"type",value:"ticket"}],checker:new api.ODCheckerObjectStructure("openticket:ticket",{children:[ + {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:ticket-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-name",{minLength:3,maxLength:50})}, + {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-description",{maxLength:256})}, + + //TICKET BUTTON + {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-button",{children:[ + {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("openticket:ticket-button-emoji",0,1,true)}, + {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:50})}, + {key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-color",{choices:["gray","red","green","blue"]})}, + ],custom:(checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + //check if emoji & label exists + if (typeof value != "object") return false + else if (value && value["emoji"].length < 1 && value["label"].length < 1){ + //label & emoji are both empty + checker.createMessage("openticket:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs) + return false + }else return true + }})}, + + //TICKET ADMINS + {key:"ticketAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:ticket-ticket-admins","role",[],{allowDoubles:false})}, + {key:"readonlyAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:ticket-readonly-admins","role",[],{allowDoubles:false})}, + {key:"allowCreationByBlacklistedUsers",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-allow-blacklisted-users",{})}, + {key:"questions",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("openticket:option-questions","openticket","question-ids","question-ids-used",{allowDoubles:false,maxLength:5})}, + + //TICKET CHANNEL + {key:"channel",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-channel",{children:[ + {key:"prefix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-channel-prefix",{maxLength:25,regex:/^[^\s]*$/})}, + {key:"suffix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-channel-suffix",{choices:["user-name","user-id","random-number","random-hex","counter-dynamic","counter-fixed"]})}, + + {key:"category",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:ticket-channel-category","category",true,[])}, + {key:"closedCategory",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:ticket-channel-closed-category","category",true,[])}, + {key:"backupCategory",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:ticket-channel-backup-category","category",true,[])}, + {key:"claimedCategory",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("openticket:ticket-channel-claimed-category",{allowDoubles:false,allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:ticket-channel-claimed-category",{children:[ + {key:"user",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:ticket-channel-claimed-user","user",false,[])}, + {key:"category",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:ticket-channel-claimed-category","category",false,[])} + ]})})}, + {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-channel-description",{})}, + ]})}, + + //DM MESSAGE + {key:"dmMessage",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:ticket-dm-message",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:ticket-dm-message",{children:[ + {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-message-text",{maxLength:4096})}, + {key:"embed",optional:false,priority:0,checker:createTicketEmbedStructure("openticket:ticket-message-embed")} + ]})})}, + + //TICKET MESSAGE + {key:"ticketMessage",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:ticket-message",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:ticket-message",{children:[ + {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-message-text",{maxLength:4096})}, + {key:"embed",optional:false,priority:0,checker:createTicketEmbedStructure("openticket:ticket-message-embed")}, + {key:"ping",optional:false,priority:0,checker:createTicketPingStructure("openticket:ticket-message-ping")} + ]})})}, + + //AUTOCLOSE + {key:"autoclose",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-autoclose",{children:[ + {key:"enableInactiveHours",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autoclose-enable-hours",{})}, + {key:"inactiveHours",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:ticket-autoclose-hours",{zeroAllowed:false,negativeAllowed:false,floatAllowed:true,min:1,max:8544})}, + {key:"enableUserLeave",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autoclose-enable-leave",{})}, + {key:"disableOnClaim",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autoclose-disable-claim",{})}, + ]})}, + + //AUTODELETE + {key:"autodelete",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-autodelete",{children:[ + {key:"enableInactiveDays",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autodelete-enable-days",{})}, + {key:"inactiveDays",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:ticket-autodelete-days",{zeroAllowed:false,negativeAllowed:false,floatAllowed:true,min:1,max:356})}, + {key:"enableUserLeave",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autodelete-enable-leave",{})}, + {key:"disableOnClaim",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autodelete-disable-claim",{})}, + ]})}, + + //COOLDOWN + {key:"cooldown",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:ticket-cooldown",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:ticket-cooldown",{children:[ + {key:"cooldownMinutes",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:ticket-cooldown-minutes",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1,max:512640})}, + ]})})}, + + //LIMITS + {key:"limits",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:ticket-limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:ticket-limits",{children:[ + {key:"globalMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:ticket-limits-global",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})}, + {key:"userMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:ticket-limits-user",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})} + ]})})}, + ]})}, + + //WEBSITE + {name:"website",priority:0,properties:[{key:"type",value:"website"}],checker:new api.ODCheckerObjectStructure("openticket:options-website",{children:[ + {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:website-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:website-name",{minLength:3,maxLength:50})}, + {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:website-description",{maxLength:256})}, + + //WEBSITE BUTTON + {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-button",{children:[ + {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("openticket:ticket-button-emoji",0,1,true)}, + {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:50})}, + ],custom:(checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + //check if emoji & label exists + if (typeof value != "object") return false + else if (value && value["emoji"].length < 1 && value["label"].length < 1){ + //label & emoji are both empty + checker.createMessage("openticket:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs) + return false + }else return true + }})}, + + //WEBSITE URL + {key:"url",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:website-url",false,{allowHttp:false})}, + ]})}, + + //REACTION ROLES + {name:"role",priority:0,properties:[{key:"type",value:"role"}],checker:new api.ODCheckerObjectStructure("openticket:options-role",{children:[ + {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:role-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:role-name",{minLength:3,maxLength:50})}, + {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:role-description",{maxLength:256})}, + + //ROLE BUTTON + {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-button",{children:[ + {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("openticket:ticket-button-emoji",0,1,true)}, + {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:50})}, + {key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-color",{choices:["gray","red","green","blue"]})}, + ],custom:(checker,value,locationTrace,locationId,locationDocs) => { + const lt = checker.locationTraceDeref(locationTrace) + //check if emoji & label exists + if (typeof value != "object") return false + else if (value && value["emoji"].length < 1 && value["label"].length < 1){ + //label & emoji are both empty + checker.createMessage("openticket:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs) + return false + }else return true + }})}, + + //ROLE SETTINGS + {key:"roles",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:role-roles","role",[],{allowDoubles:false,minLength:1})}, + {key:"mode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:role-mode",{choices:["add","remove","add&remove"]})}, + {key:"removeRolesOnAdd",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:role-remove-roles","role",[],{allowDoubles:false})}, + {key:"addOnMemberJoin",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:role-add-on-join",{})}, + ]})}, +]})}) + +export const defaultPanelsStructure = new api.ODCheckerArrayStructure("openticket:panels",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:panels",{children:[ + {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:panel-id","openticket","panel-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-name",{minLength:3,maxLength:50})}, + {key:"dropdown",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-dropdown",{})}, + {key:"options",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("openticket:panel-options","openticket","option-ids","option-ids-used",{allowDoubles:false,maxLength:25})}, + + //EMBED & TEXT + {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-text",{maxLength:4096})}, + {key:"embed",optional:false,priority:0,checker:createPanelEmbedStructure("openticket:panel-embed")}, + + //SETTINGS + {key:"settings",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:panel-settings",{children:[ + {key:"dropdownPlaceholder",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-settings-placeholder",{maxLength:100})}, + {key:"enableMaxTicketsWarningInText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-settings-maxtickets-text",{})}, + {key:"enableMaxTicketsWarningInEmbed",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-settings-maxtickets-embed",{})}, + + {key:"describeOptionsLayout",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-settings-describe-layout",{choices:["simple","normal","detailed"]})}, + {key:"describeOptionsCustomTitle",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-settings-describe-title",{maxLength:512})}, + {key:"describeOptionsInText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-settings-describe-text",{})}, + {key:"describeOptionsInEmbedFields",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-settings-describe-fields",{})}, + {key:"describeOptionsInEmbedDescription",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-settings-describe-embed",{})}, + ]})}, +]})}) + +export const defaultQuestionsStructure = new api.ODCheckerArrayStructure("openticket:questions",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:questions",{children:[ + {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:question-name",{minLength:3,maxLength:50})}, + {key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:question-type",{choices:["short","paragraph"]})}, + + {key:"required",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:question-required",{})}, + {key:"placeholder",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:question-placeholder",{maxLength:100})}, + + {key:"length",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:question-length",{children:[ + {key:"min",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false})}, + {key:"max",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false})}, + ]})})}, +]})}) + +export const defaultTranscriptsStructure = new api.ODCheckerObjectStructure("openticket:transcripts",{children:[ + //GENERAL + {key:"general",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:transcripts-general",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:transcripts-general",{children:[ + {key:"enableChannel",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-enable-channel",{})}, + {key:"enableCreatorDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-enable-creator-dm",{})}, + {key:"enableParticipantDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-enable-participant-dm",{})}, + {key:"enableActiveAdminDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-enable-active-admin-dm",{})}, + {key:"enableEveryAdminDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-enable-every-admin-dm",{})}, + + {key:"channel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:transcripts-channel","channel",true,[])}, + {key:"mode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-mode",{choices:["html","text"]})}, + ]})})}, + + //EMBED SETTINGS + {key:"embedSettings",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:transcripts-embed-settings",{children:[ + {key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-embed-color",false,true)}, + {key:"listAllParticipants",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-embed-list-participants",{})}, + {key:"includeTicketStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-embed-include-ticket-stats",{})}, + ]})}, + + //TEXT STYLE + {key:"textTranscriptStyle",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:transcripts-text",{children:[ + {key:"layout",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-text-layout",{choices:["simple","normal","detailed"]})}, + {key:"includeStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-stats",{})}, + {key:"includeIds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-ids",{})}, + {key:"includeEmbeds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-embeds",{})}, + {key:"includeFiles",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-files",{})}, + {key:"includeBotMessages",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-bots",{})}, + + {key:"fileMode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-text-file-mode",{choices:["custom","name","id"]})}, + {key:"customFileName",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-file-name",{maxLength:512,regex:/^[^\.#%&{}\\<>*?/!'":@`|=]*$/})}, + ]})}, + + //HTML STYLE + {key:"htmlTranscriptStyle",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:transcripts-html",{children:[ + //HTML BACKGROUND + {key:"background",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:transcripts-html-background",{property:"enableCustomBackground",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:transcripts-html-background",{children:[ + {key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-background-color",false,true)}, + {key:"backgroundImage",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:transcripts-html-background-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, + ]})})}, + + //HTML HEADER + {key:"header",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:transcripts-html-header",{property:"enableCustomHeader",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:transcripts-html-header",{children:[ + {key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-header-bgcolor",false,false)}, + {key:"decoColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-header-decocolor",false,false)}, + {key:"textColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-header-textcolor",false,false)}, + ]})})}, + + //HTML STATS + {key:"stats",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:transcripts-html-stats",{property:"enableCustomStats",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:transcripts-html-stats",{children:[ + {key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-stats-bgcolor",false,false)}, + {key:"keyTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-stats-keycolor",false,false)}, + {key:"valueTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-stats-valuecolor",false,false)}, + {key:"hideBackgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-stats-hidebgcolor",false,false)}, + {key:"hideTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-stats-hidecolor",false,false)}, + ]})})}, + + //HTML FAVICON + {key:"favicon",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:transcripts-html-favicon",{property:"enableCustomFavicon",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:transcripts-html-favicon",{children:[ + {key:"imageUrl",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:transcripts-html-favicon-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp"]})}, + ]})})}, + ]})}, +]}) + +export const defaultUnusedOptionsFunction = (manager:api.ODCheckerManager, functions:api.ODCheckerFunctionManager): api.ODCheckerResult => { + const optionList: string[] = manager.storage.get("openticket","option-ids") + const usedOptionList: string[] = manager.storage.get("openticket","option-ids-used") + if (!optionList || ! usedOptionList) return {valid:true,messages:[]} + + const optionChecker = manager.get("openticket:options") + if (!optionChecker) return {valid:true,messages:[]} + + const final: api.ODCheckerMessage[] = [] + optionList.forEach((id) => { + if (!usedOptionList.includes(id)){ + //id isn't used anywhere => create warning + final.push(functions.createMessage("openticket:options","openticket:unused-option",optionChecker.config.file,"warning",`The option "${id}" isn't used anywhere!`,[],null,[`"${id}"`],new api.ODId("openticket:unused-options"),null)) + } + }) + + return {valid:true,messages:final} +} + +export const defaultUnusedQuestionsFunction = (manager:api.ODCheckerManager, functions:api.ODCheckerFunctionManager): api.ODCheckerResult => { + const questionList: string[] = manager.storage.get("openticket","question-ids") + const usedQuestionList: string[] = manager.storage.get("openticket","question-ids-used") + if (!questionList || ! usedQuestionList) return {valid:true,messages:[]} + + const questionChecker = manager.get("openticket:questions") + if (!questionChecker) return {valid:true,messages:[]} + + const final: api.ODCheckerMessage[] = [] + questionList.forEach((id) => { + if (!usedQuestionList.includes(id)){ + //id isn't used anywhere => create warning + final.push(functions.createMessage("openticket:questions","openticket:unused-question",questionChecker.config.file,"warning",`The question "${id}" isn't used anywhere!`,[],null,[`"${id}"`],new api.ODId("openticket:unused-questions"),null)) + } + }) + + return {valid:true,messages:final} +} + +export const defaultDropdownOptionsFunction = (manager:api.ODCheckerManager, functions:api.ODCheckerFunctionManager): api.ODCheckerResult => { + + const panelList: string[] = manager.storage.get("openticket","panel-ids") + if (!panelList) return {valid:true,messages:[]} + + const panelConfig = openticket.configs.get("openticket:panels") + if (!panelConfig) return {valid:true,messages:[]} + + const optionConfig = openticket.configs.get("openticket:options") + if (!optionConfig) return {valid:true,messages:[]} + + const final: api.ODCheckerMessage[] = [] + panelList.forEach((id,index) => { + const panel = panelConfig.data.find((panel) => panel.id == id) + if (!panel || !panel.dropdown) return false + if (panel.options.some((optId) => { + const option = optionConfig.data.find((option) => option.id == optId) + if (!option) return false + if (option.type != "ticket") return true + else return false + })){ + //give error when non-ticket options exist in dropdown panel! + final.push(functions.createMessage("openticket:panels","openticket:dropdown-option",panelConfig.file,"error","A panel with dropdown enabled can only contain options of the 'ticket' type!",[index,"options"],null,[],new api.ODId("openticket:dropdown-options"),null)) + } + }) + + return {valid:(final.length < 1),messages:final} +} \ No newline at end of file diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts new file mode 100644 index 0000000..dd65bb7 --- /dev/null +++ b/src/data/framework/codeLoader.ts @@ -0,0 +1,481 @@ +import {openticket, api, utilities} from "../../index" +import * as discord from "discord.js" + +const generalConfig = openticket.configs.get("openticket:general") +const globalDatabase = openticket.databases.get("openticket:global") +const userDatabase = openticket.databases.get("openticket:users") +const ticketDatabase = openticket.databases.get("openticket:tickets") +const statsDatabase = openticket.databases.get("openticket:stats") +const optionDatabase = openticket.databases.get("openticket:options") +const mainServer = openticket.client.mainServer + +export const loadAllCode = async () => { + if (!generalConfig || !mainServer || !globalDatabase || !userDatabase || !ticketDatabase || !statsDatabase || !optionDatabase) return + + loadCommandErrorHandlingCode() + loadStartListeningInteractionsCode() + loadDatabaseCleanersCode() + loadPanelAutoUpdateCode() + loadDatabaseSaversCode() + loadAutoCode() +} + +export const loadCommandErrorHandlingCode = async () => { + //COMMAND ERROR HANDLING + openticket.code.add(new api.ODCode("openticket:command-error-handling",14,() => { + //invalid/missing options + openticket.client.textCommands.onError(async (error) => { + if (error.type == "invalid_option"){ + error.msg.channel.send((await openticket.builders.messages.getSafe("openticket:error-option-invalid").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) + }else if (error.type == "missing_option"){ + error.msg.channel.send((await openticket.builders.messages.getSafe("openticket:error-option-missing").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) + }else if (error.type == "unknown_command" && generalConfig.data.system.sendErrorOnUnknownCommand){ + error.msg.channel.send((await openticket.builders.messages.getSafe("openticket:error-unknown-command").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) + } + }) + + //responder timeout + openticket.responders.commands.setTimeoutErrorCallback(async (instance,source) => { + instance.reply(await openticket.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + },null) + openticket.responders.buttons.setTimeoutErrorCallback(async (instance,source) => { + instance.reply(await openticket.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + },null) + openticket.responders.dropdowns.setTimeoutErrorCallback(async (instance,source) => { + instance.reply(await openticket.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + },null) + openticket.responders.modals.setTimeoutErrorCallback(async (instance,source) => { + if (!instance.channel){ + instance.reply({id:new api.ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{ + content:":x: **Something went wrong while replying to this modal!**" + }}) + return + } + instance.reply(await openticket.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + },null) + })) +} + +export const loadStartListeningInteractionsCode = async () => { + //START LISTENING TO INTERACTIONS + openticket.code.add(new api.ODCode("openticket:start-listening-interactions",13,() => { + openticket.client.slashCommands.startListeningToInteractions() + openticket.client.textCommands.startListeningToInteractions() + })) +} + +export const loadDatabaseCleanersCode = async () => { + if (!mainServer) return + + //PANEL DATABASE CLEANER + openticket.code.add(new api.ODCode("openticket:panel-database-cleaner",12,async () => { + const validPanels: string[] = [] + + //check global database for valid panel embeds + for (const panel of (globalDatabase.getCategory("openticket:panel-update") ?? [])){ + if (!validPanels.includes(panel.key)){ + try{ + const splittedId = panel.key.split("_") + const message = await openticket.client.fetchGuildChannelMessage(mainServer,splittedId[0],splittedId[1]) + if (message) validPanels.push(panel.key) + }catch{} + } + } + + //remove all unused panels + for (const panel of (globalDatabase.getCategory("openticket:panel-update") ?? [])){ + if (!validPanels.includes(panel.key)){ + globalDatabase.delete("openticket:panel-update",panel.key) + } + } + + //delete panel from database on delete + openticket.client.client.on("messageDelete",(msg) => { + if (globalDatabase.exists("openticket:panel-update",msg.channel.id+"_"+msg.id)){ + globalDatabase.delete("openticket:panel-update",msg.channel.id+"_"+msg.id) + } + }) + })) + + //SUFFIX DATABASE CLEANER + openticket.code.add(new api.ODCode("openticket:suffix-database-cleaner",11,async () => { + const validSuffixCounters: string[] = [] + const validSuffixHistories: string[] = [] + + //check global database for valid option suffix counters + for (const counter of (globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ + if (!validSuffixCounters.includes(counter.key)){ + if (openticket.options.exists(counter.key)) validSuffixCounters.push(counter.key) + } + } + + //check global database for valid option suffix histories + for (const history of (globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ + if (!validSuffixHistories.includes(history.key)){ + if (openticket.options.exists(history.key)) validSuffixHistories.push(history.key) + } + } + + //remove all unused suffix counters + for (const counter of (globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ + if (!validSuffixCounters.includes(counter.key)){ + globalDatabase.delete("openticket:option-suffix-counter",counter.key) + } + } + + //remove all unused suffix histories + for (const history of (globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ + if (!validSuffixHistories.includes(history.key)){ + globalDatabase.delete("openticket:option-suffix-history",history.key) + } + } + })) + + //OPTION DATABASE CLEANER + openticket.code.add(new api.ODCode("openticket:option-database-cleaner",10,() => { + //delete all unused options + openticket.options.getAll().forEach((option) => { + if (optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ + optionDatabase.delete("openticket:used-option",option.id.value) + } + }) + })) + + //USER DATABASE CLEANER (full async/parallel because it takes a lot of time) + openticket.code.add(new api.ODCode("openticket:user-database-cleaner",9,() => { + utilities.runAsync(async () => { + const validUsers: string[] = [] + + //check user database for valid users + for (const user of userDatabase.getAll()){ + if (!validUsers.includes(user.key)){ + try{ + const member = await mainServer.members.fetch(user.key) + if (member) validUsers.push(member.id) + }catch{} + } + } + + //check stats database for valid users + for (const stat of statsDatabase.getAll()){ + if (stat.category.startsWith("openticket:user_")){ + if (!validUsers.includes(stat.key)){ + try{ + const member = await mainServer.members.fetch(stat.key) + if (member) validUsers.push(member.id) + }catch{} + } + } + } + + //remove all unused users + for (const user of userDatabase.getAll()){ + if (!validUsers.includes(user.key)){ + userDatabase.delete(user.category,user.key) + } + } + + //remove all unused stats + for (const stat of statsDatabase.getAll()){ + if (stat.category.startsWith("openticket:user_")){ + if (!validUsers.includes(stat.key)){ + statsDatabase.delete(stat.category,stat.key) + } + } + } + }) + + //delete user from database on leave + openticket.client.client.on("guildMemberRemove",(member) => { + if (member.guild.id != mainServer.id) return + + //remove unused user + for (const user of userDatabase.getAll()){ + if (user.key == member.id){ + userDatabase.delete(user.category,user.key) + } + } + + //remove unused stats + for (const stat of statsDatabase.getAll()){ + if (stat.category.startsWith("openticket:user_")){ + if (stat.key == member.id){ + statsDatabase.delete(stat.category,stat.key) + } + } + } + }) + })) + + //TICKET DATABASE CLEANER + openticket.code.add(new api.ODCode("openticket:ticket-database-cleaner",8,async () => { + const validTickets: string[] = [] + + //check ticket database for valid tickets + for (const ticket of ticketDatabase.getAll()){ + if (!validTickets.includes(ticket.key)){ + try{ + const channel = await openticket.client.fetchGuildTextChannel(mainServer,ticket.key) + if (channel) validTickets.push(channel.id) + }catch{} + } + } + + //check stats database for valid tickets + for (const stat of statsDatabase.getAll()){ + if (stat.category.startsWith("openticket:ticket_")){ + if (!validTickets.includes(stat.key)){ + try{ + const channel = await openticket.client.fetchGuildTextChannel(mainServer,stat.key) + if (channel) validTickets.push(channel.id) + }catch{} + } + } + } + + //remove all unused tickets + for (const ticket of ticketDatabase.getAll()){ + if (!validTickets.includes(ticket.key)){ + ticketDatabase.delete(ticket.category,ticket.key) + openticket.tickets.remove(ticket.key) + } + } + + //remove all unused stats + for (const stat of statsDatabase.getAll()){ + if (stat.category.startsWith("openticket:ticket_")){ + if (!validTickets.includes(stat.key)){ + statsDatabase.delete(stat.category,stat.key) + } + } + } + + //delete ticket from database on delete + openticket.client.client.on("channelDelete",(channel) => { + if (channel.isDMBased() || channel.guild.id != mainServer.id) return + + //remove unused ticket + for (const ticket of ticketDatabase.getAll()){ + if (ticket.key == channel.id){ + ticketDatabase.delete(ticket.category,ticket.key) + openticket.tickets.remove(ticket.key) + } + } + + //remove unused stats + for (const stat of statsDatabase.getAll()){ + if (stat.category.startsWith("openticket:ticket_")){ + if (stat.key == channel.id){ + statsDatabase.delete(stat.category,stat.key) + } + } + } + }) + })) +} + +export const loadPanelAutoUpdateCode = async () => { + //PANEL AUTO UPDATE + openticket.code.add(new api.ODCode("openticket:panel-auto-update",7,async () => { + const globalDatabase = openticket.databases.get("openticket:global") + const panelIds = globalDatabase.getCategory("openticket:panel-update") ?? [] + if (!mainServer) return + + for (const panelId of panelIds){ + const panel = openticket.panels.get(panelId.value) + + //panel doesn't exist anymore in config and needs to be removed + if (!panel){ + globalDatabase.delete("openticket:panel-update",panelId.key) + return + } + + try{ + const splittedId = panelId.key.split("_") + const channel = await openticket.client.fetchGuildTextChannel(mainServer,splittedId[0]) + if (!channel) return + const message = await openticket.client.fetchGuildChannelMessage(mainServer,channel,splittedId[1]) + if (!message) return + + message.edit((await openticket.builders.messages.getSafe("openticket:panel").build("auto-update",{guild:mainServer,channel,user:openticket.client.client.user,panel})).message) + openticket.log("Panel in server got auto-updated!","info",[ + {key:"channelid",value:splittedId[0]}, + {key:"messageid",value:splittedId[1]}, + {key:"panel",value:panelId.value} + ]) + }catch{} + } + })) +} + +export const loadDatabaseSaversCode = async () => { + //TICKET SAVER + openticket.code.add(new api.ODCode("openticket:ticket-saver",6,() => { + const mainVersion = openticket.versions.get("openticket:version") + + openticket.tickets.onAdd((ticket) => { + ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) + + //add option to database if non-existent + if (!optionDatabase.exists("openticket:used-option",ticket.option.id.value)){ + optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) + } + }) + openticket.tickets.onChange((ticket) => { + ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) + + //add option to database if non-existent + if (!optionDatabase.exists("openticket:used-option",ticket.option.id.value)){ + optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) + } + + //delete all unused options on ticket move + openticket.options.getAll().forEach((option) => { + if (optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ + optionDatabase.delete("openticket:used-option",option.id.value) + } + }) + }) + openticket.tickets.onRemove((ticket) => { + ticketDatabase.delete("openticket:ticket",ticket.id.value) + + //remove option from database if unused + if (!openticket.tickets.getAll().some((ticket) => ticket.option.id.value == ticket.option.id.value)){ + optionDatabase.delete("openticket:used-option",ticket.option.id.value) + } + }) + })) + + //BLACKLIST SAVER + openticket.code.add(new api.ODCode("openticket:blacklist-saver",5,() => { + openticket.blacklist.onAdd((blacklist) => { + userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) + }) + openticket.blacklist.onChange((blacklist) => { + userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) + }) + openticket.blacklist.onRemove((blacklist) => { + userDatabase.delete("openticket:blacklist",blacklist.id.value) + }) + })) + + //AUTO ROLE ON JOIN + openticket.code.add(new api.ODCode("openticket:auto-role-on-join",4,() => { + openticket.client.client.on("guildMemberAdd",async (member) => { + for (const option of openticket.options.getAll()){ + if (option instanceof api.ODRoleOption && option.get("openticket:add-on-join").value){ + //add these roles on user join + await openticket.actions.get("openticket:reaction-role").run("panel-button",{guild:member.guild,user:member.user,option,overwriteMode:"add"}) + } + } + }) + })) +} + +const loadAutoCode = () => { + //AUTOCLOSE TIMEOUT + openticket.code.add(new api.ODCode("openticket:autoclose-timeout",3,() => { + setInterval(async () => { + let count = 0 + for (const ticket of openticket.tickets.getAll()){ + const channel = await openticket.tickets.getTicketChannel(ticket) + if (!channel) return + const lastMessage = (await channel.messages.fetch({limit:5})).first() + if (lastMessage && !ticket.get("openticket:closed").value){ + //ticket has last message + const disableOnClaim = ticket.option.get("openticket:autoclose-disable-claim").value && ticket.get("openticket:claimed").value + const enabled = (disableOnClaim) ? false : ticket.get("openticket:autoclose-enabled").value + const hours = ticket.get("openticket:autoclose-hours").value + + const time = hours*60*60*1000 //hours in milliseconds + if (enabled && (new Date().getTime() - lastMessage.createdTimestamp) >= time){ + //autoclose ticket + await openticket.actions.get("openticket:close-ticket").run("autoclose",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) + await channel.send((await openticket.builders.messages.getSafe("openticket:autoclose-message").build("timeout",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) + count++ + openticket.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") + } + } + } + openticket.log("Finished autoclose timeout cycle!","system",[ + {key:"interval",value:openticket.defaults.getDefault("autocloseCheckInterval").toString(),hidden:true}, + {key:"closed",value:count.toString()} + ]) + },openticket.defaults.getDefault("autocloseCheckInterval")) + })) + + //AUTOCLOSE LEAVE + openticket.code.add(new api.ODCode("openticket:autoclose-leave",2,() => { + openticket.client.client.on("guildMemberRemove",async (member) => { + for (const ticket of openticket.tickets.getAll()){ + if (ticket.get("openticket:opened-by").value == member.id){ + const channel = await openticket.tickets.getTicketChannel(ticket) + if (!channel) return + //ticket has been created by this user + const disableOnClaim = ticket.option.get("openticket:autoclose-disable-claim").value && ticket.get("openticket:claimed").value + const enabled = (disableOnClaim || !ticket.get("openticket:autoclose-enabled").value) ? false : ticket.option.get("openticket:autoclose-enable-leave") + + if (enabled){ + //autoclose ticket + await openticket.actions.get("openticket:close-ticket").run("autoclose",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) + await channel.send((await openticket.builders.messages.getSafe("openticket:autoclose-message").build("leave",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) + openticket.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") + } + } + } + }) + })) + + //AUTODELETE TIMEOUT + openticket.code.add(new api.ODCode("openticket:autodelete-timeout",1,() => { + setInterval(async () => { + let count = 0 + for (const ticket of openticket.tickets.getAll()){ + const channel = await openticket.tickets.getTicketChannel(ticket) + if (!channel) return + const lastMessage = (await channel.messages.fetch({limit:5})).first() + if (lastMessage){ + //ticket has last message + const disableOnClaim = ticket.option.get("openticket:autodelete-disable-claim").value && ticket.get("openticket:claimed").value + const enabled = (disableOnClaim) ? false : ticket.get("openticket:autodelete-enabled").value + const days = ticket.get("openticket:autodelete-days").value + + const time = days*24*60*60*1000 //days in milliseconds + if (enabled && (new Date().getTime() - lastMessage.createdTimestamp) >= time){ + //autodelete ticket + await channel.send((await openticket.builders.messages.getSafe("openticket:autodelete-message").build("timeout",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) + await openticket.actions.get("openticket:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) + count++ + openticket.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") + } + } + } + openticket.log("Finished autodelete timeout cycle!","system",[ + {key:"interval",value:openticket.defaults.getDefault("autodeleteCheckInterval").toString(),hidden:true}, + {key:"deleted",value:count.toString()} + ]) + },openticket.defaults.getDefault("autodeleteCheckInterval")) + })) + + //AUTODELETE LEAVE + openticket.code.add(new api.ODCode("openticket:autodelete-leave",0,() => { + openticket.client.client.on("guildMemberRemove",async (member) => { + for (const ticket of openticket.tickets.getAll()){ + if (ticket.get("openticket:opened-by").value == member.id){ + const channel = await openticket.tickets.getTicketChannel(ticket) + if (!channel) return + //ticket has been created by this user + const disableOnClaim = ticket.option.get("openticket:autodelete-disable-claim").value && ticket.get("openticket:claimed").value + const enabled = (disableOnClaim || !ticket.get("openticket:autodelete-enabled").value) ? false : ticket.option.get("openticket:autodelete-enable-leave") + + if (enabled){ + //autodelete ticket + await channel.send((await openticket.builders.messages.getSafe("openticket:autodelete-message").build("leave",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) + await openticket.actions.get("openticket:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) + openticket.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") + } + } + } + }) + })) +} \ No newline at end of file diff --git a/src/data/framework/commandLoader.ts b/src/data/framework/commandLoader.ts new file mode 100644 index 0000000..ee0e326 --- /dev/null +++ b/src/data/framework/commandLoader.ts @@ -0,0 +1,1076 @@ +import {openticket, api, utilities} from "../../index" +import * as discord from "discord.js" + +const lang = openticket.languages + +export const loadAllSlashCommands = async () => { + const commands = openticket.client.slashCommands + const generalConfig = openticket.configs.get("openticket:general") + if (!generalConfig) return + + const act = discord.ApplicationCommandType + const acot = discord.ApplicationCommandOptionType + + if (!generalConfig.data.slashCommands) return + + //create panel choices + const panelChoices : {name:string, value:string}[] = [] + openticket.configs.get("openticket:panels").data.forEach((panel) => { + panelChoices.push({name:panel.name, value:panel.id}) + }) + + //create ticket choices + const ticketChoices : {name:string, value:string}[] = [] + openticket.configs.get("openticket:options").data.forEach((option) => { + if (option.type != "ticket") return + ticketChoices.push({name:option.name, value:option.id}) + }) + + const allowedCommands: string[] = [] + for (const key in generalConfig.data.system.permissions){ + if (generalConfig.data.system.permissions[key] != "none") allowedCommands.push(key) + } + + //HELP + if (allowedCommands.includes("help")) commands.add(new api.ODSlashCommand("openticket:help",{ + type:act.ChatInput, + name:"help", + description:lang.getTranslation("commands.help"), + dmPermission:true + })) + + //PANEL + if (allowedCommands.includes("panel")) commands.add(new api.ODSlashCommand("openticket:panel",{ + type:act.ChatInput, + name:"panel", + description:lang.getTranslation("commands.panel"), + dmPermission:false, + options:[ + { + name:"id", + description:lang.getTranslation("commands.panelId"), + type:acot.String, + required:true, + choices:panelChoices + }, + { + name:"auto-update", + description:lang.getTranslation("commands.panelAutoUpdate"), + type:acot.Boolean, + required:false + } + ] + },(current) => { + //check if this slash command needs to be updated + if (!current.options) return true + const idOption = current.options.find((opt) => opt.name == "id" && opt.type == acot.String) as discord.ApplicationCommandStringOptionData|undefined + if (!idOption || !idOption.choices || idOption.choices.length != panelChoices.length) return true + else if (!panelChoices.every((panel) => { + if (!idOption.choices) return false + else if (!idOption.choices.find((choice) => choice.value == panel.value && choice.name == panel.name)) return false + else return true + })) return true + else return false + })) + + //TICKET (when enabled) + if (allowedCommands.includes("ticket")) commands.add(new api.ODSlashCommand("openticket:ticket",{ + type:act.ChatInput, + name:"ticket", + description:lang.getTranslation("commands.ticket"), + dmPermission:false, + options:[ + { + name:"id", + description:lang.getTranslation("commands.ticketId"), + type:acot.String, + required:true, + choices:ticketChoices + } + ] + },(current) => { + //check if this slash command needs to be updated + if (!current.options) return true + const idOption = current.options.find((opt) => opt.name == "id" && opt.type == acot.String) as discord.ApplicationCommandStringOptionData|undefined + if (!idOption || !idOption.choices || idOption.choices.length != ticketChoices.length) return true + else if (!ticketChoices.every((ticket) => { + if (!idOption.choices) return false + else if (!idOption.choices.find((choice) => choice.value == ticket.value && choice.name == ticket.name)) return false + else return true + })) return true + else return false + })) + + //CLOSE + if (allowedCommands.includes("close")) commands.add(new api.ODSlashCommand("openticket:close",{ + type:act.ChatInput, + name:"close", + description:lang.getTranslation("commands.close"), + dmPermission:false, + options:[ + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + })) + + //DELETE + if (allowedCommands.includes("delete") && generalConfig.data.system.enableDeleteWithoutTranscript) commands.add(new api.ODSlashCommand("openticket:delete",{ + type:act.ChatInput, + name:"delete", + description:lang.getTranslation("commands.delete"), + dmPermission:false, + options:[ + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + }, + { + name:"notranscript", + description:lang.getTranslation("commands.deleteNoTranscript"), + type:acot.Boolean, + required:false + } + ] + })) + else if (allowedCommands.includes("delete")) commands.add(new api.ODSlashCommand("openticket:delete",{ + type:act.ChatInput, + name:"delete", + description:lang.getTranslation("commands.delete"), + dmPermission:false, + options:[ + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + })) + + //REOPEN + if (allowedCommands.includes("reopen")) commands.add(new api.ODSlashCommand("openticket:reopen",{ + type:act.ChatInput, + name:"reopen", + description:lang.getTranslation("commands.reopen"), + dmPermission:false, + options:[ + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + })) + + //CLAIM + if (allowedCommands.includes("claim")) commands.add(new api.ODSlashCommand("openticket:claim",{ + type:act.ChatInput, + name:"claim", + description:lang.getTranslation("commands.claim"), + dmPermission:false, + options:[ + { + name:"user", + description:lang.getTranslation("commands.claimUser"), + type:acot.User, + required:false + }, + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + })) + + //UNCLAIM + if (allowedCommands.includes("unclaim")) commands.add(new api.ODSlashCommand("openticket:unclaim",{ + type:act.ChatInput, + name:"unclaim", + description:lang.getTranslation("commands.unclaim"), + dmPermission:false, + options:[ + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + })) + + //PIN + if (allowedCommands.includes("pin")) commands.add(new api.ODSlashCommand("openticket:pin",{ + type:act.ChatInput, + name:"pin", + description:lang.getTranslation("commands.pin"), + dmPermission:false, + options:[ + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + })) + + //UNPIN + if (allowedCommands.includes("unpin")) commands.add(new api.ODSlashCommand("openticket:unpin",{ + type:act.ChatInput, + name:"unpin", + description:lang.getTranslation("commands.unpin"), + dmPermission:false, + options:[ + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + })) + + //MOVE + if (allowedCommands.includes("move")) commands.add(new api.ODSlashCommand("openticket:move",{ + type:act.ChatInput, + name:"move", + description:lang.getTranslation("commands.move"), + dmPermission:false, + options:[ + { + name:"id", + description:lang.getTranslation("commands.moveId"), + type:acot.String, + required:true, + choices:ticketChoices + }, + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + },(current) => { + //check if this slash command needs to be updated + if (!current.options) return true + const idOption = current.options.find((opt) => opt.name == "id" && opt.type == acot.String) as discord.ApplicationCommandStringOptionData|undefined + if (!idOption || !idOption.choices || idOption.choices.length != ticketChoices.length) return true + else if (!ticketChoices.every((ticket) => { + if (!idOption.choices) return false + else if (!idOption.choices.find((choice) => choice.value == ticket.value && choice.name == ticket.name)) return false + else return true + })) return true + else return false + })) + + //RENAME + if (allowedCommands.includes("rename")) commands.add(new api.ODSlashCommand("openticket:rename",{ + type:act.ChatInput, + name:"rename", + description:lang.getTranslation("commands.rename"), + dmPermission:false, + options:[ + { + name:"name", + description:lang.getTranslation("commands.renameName"), + type:acot.String, + required:true, + maxLength:100 + }, + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + })) + + //ADD + if (allowedCommands.includes("add")) commands.add(new api.ODSlashCommand("openticket:add",{ + type:act.ChatInput, + name:"add", + description:lang.getTranslation("commands.add"), + dmPermission:false, + options:[ + { + name:"user", + description:lang.getTranslation("commands.addUser"), + type:acot.User, + required:true + }, + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + })) + + //REMOVE + if (allowedCommands.includes("remove")) commands.add(new api.ODSlashCommand("openticket:remove",{ + type:act.ChatInput, + name:"remove", + description:lang.getTranslation("commands.remove"), + dmPermission:false, + options:[ + { + name:"user", + description:lang.getTranslation("commands.removeUser"), + type:acot.User, + required:true + }, + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + })) + + //BLACKLIST + if (allowedCommands.includes("blacklist")) commands.add(new api.ODSlashCommand("openticket:blacklist",{ + type:act.ChatInput, + name:"blacklist", + description:lang.getTranslation("commands.blacklist"), + dmPermission:false, + options:[ + { + name:"view", + description:lang.getTranslation("commands.blacklistView"), + type:acot.Subcommand + }, + { + name:"add", + description:lang.getTranslation("commands.blacklistAdd"), + type:acot.Subcommand, + options:[ + { + name:"user", + description:lang.getTranslation("commands.addUser"), + type:acot.User, + required:true + }, + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + }, + { + name:"remove", + description:lang.getTranslation("commands.blacklistRemove"), + type:acot.Subcommand, + options:[ + { + name:"user", + description:lang.getTranslation("commands.removeUser"), + type:acot.User, + required:true + }, + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + }, + { + name:"get", + description:lang.getTranslation("commands.blacklistGet"), + type:acot.Subcommand, + options:[ + { + name:"user", + description:lang.getTranslation("commands.blacklistGetUser"), + type:acot.User, + required:true + } + ] + } + ] + })) + + //STATS + if (allowedCommands.includes("stats")) commands.add(new api.ODSlashCommand("openticket:stats",{ + type:act.ChatInput, + name:"stats", + description:lang.getTranslation("commands.stats"), + dmPermission:false, + options:[ + { + name:"reset", + description:lang.getTranslation("commands.statsReset"), + type:acot.Subcommand, + options:[ + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + }, + { + name:"global", + description:lang.getTranslation("commands.statsGlobal"), + type:acot.Subcommand + }, + { + name:"user", + description:lang.getTranslation("commands.statsUser"), + type:acot.Subcommand, + options:[ + { + name:"user", + description:lang.getTranslation("commands.statsUserUser"), + type:acot.User, + required:false + } + ] + }, + { + name:"ticket", + description:lang.getTranslation("commands.statsTicket"), + type:acot.Subcommand, + options:[ + { + name:"ticket", + description:lang.getTranslation("commands.statsTicketTicket"), + type:acot.Channel, + required:false + } + ] + } + ] + })) + + //CLEAR + if (allowedCommands.includes("clear")) commands.add(new api.ODSlashCommand("openticket:clear",{ + type:act.ChatInput, + name:"clear", + description:lang.getTranslation("commands.clear"), + dmPermission:false, + options:[ + { + name:"filter", + description:lang.getTranslation("commands.clearFilter"), + type:acot.String, + required:false, + choices:[ + {name:lang.getTranslation("commands.clearFilters.all"), value:"all"}, + {name:lang.getTranslation("commands.clearFilters.open"), value:"open"}, + {name:lang.getTranslation("commands.clearFilters.close"), value:"closed"}, + {name:lang.getTranslation("commands.clearFilters.claim"), value:"claimed"}, + {name:lang.getTranslation("commands.clearFilters.unclaim"), value:"unclaimed"}, + {name:lang.getTranslation("commands.clearFilters.pin"), value:"pinned"}, + {name:lang.getTranslation("commands.clearFilters.unpin"), value:"unpinned"}, + {name:lang.getTranslation("commands.clearFilters.autoclose"), value:"autoclosed"} + ] + } + ] + })) + + //AUTOCLOSE + if (allowedCommands.includes("autoclose")) commands.add(new api.ODSlashCommand("openticket:autoclose",{ + type:act.ChatInput, + name:"autoclose", + description:lang.getTranslation("commands.autoclose"), + dmPermission:false, + options:[ + { + name:"disable", + description:lang.getTranslation("commands.autocloseDisable"), + type:acot.Subcommand, + options:[ + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + }, + { + name:"enable", + description:lang.getTranslation("commands.autocloseEnable"), + type:acot.Subcommand, + options:[ + { + name:"time", + description:lang.getTranslation("commands.autocloseEnableTime"), + type:acot.Number, + required:true, + minValue:0.01 + }, + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + } + ] + })) + + //AUTODELETE + if (allowedCommands.includes("autodelete")) commands.add(new api.ODSlashCommand("openticket:autodelete",{ + type:act.ChatInput, + name:"autodelete", + description:lang.getTranslation("commands.autodelete"), + dmPermission:false, + options:[ + { + name:"disable", + description:lang.getTranslation("commands.autodeleteDisable"), + type:acot.Subcommand, + options:[ + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + }, + { + name:"enable", + description:lang.getTranslation("commands.autodeleteEnable"), + type:acot.Subcommand, + options:[ + { + name:"time", + description:lang.getTranslation("commands.autodeleteEnableTime"), + type:acot.Number, + required:true, + minValue:0.01 + }, + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + } + ] + })) +} + +export const loadAllTextCommands = async () => { + const commands = openticket.client.textCommands + const generalConfig = openticket.configs.get("openticket:general") + if (!generalConfig) return + + if (!generalConfig.data.textCommands) return + const prefix = generalConfig.data.prefix + + //create panel choices + const panelChoices : string[] = [] + openticket.configs.get("openticket:panels").data.forEach((panel) => { + panelChoices.push(panel.id) + }) + + //create ticket choices + const ticketChoices : string[] = [] + openticket.configs.get("openticket:options").data.forEach((option) => { + if (option.type != "ticket") return + ticketChoices.push(option.id) + }) + + const allowedCommands: string[] = [] + for (const key in generalConfig.data.system.permissions){ + if (generalConfig.data.system.permissions[key] != "none") allowedCommands.push(key) + } + + //HELP + if (allowedCommands.includes("help")) commands.add(new api.ODTextCommand("openticket:help",{ + name:"help", + prefix, + dmPermission:true, + guildPermission:true, + allowBots:false + })) + + //PANEL + if (allowedCommands.includes("panel")) commands.add(new api.ODTextCommand("openticket:panel",{ + name:"panel", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"id", + type:"string", + required:true + }, + { + name:"auto-update", + type:"boolean", + required:false + } + ] + })) + + //CLOSE + if (allowedCommands.includes("close")) commands.add(new api.ODTextCommand("openticket:close",{ + name:"close", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //DELETE + if (allowedCommands.includes("delete")) commands.add(new api.ODTextCommand("openticket:delete",{ + name:"delete", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //REOPEN + if (allowedCommands.includes("reopen")) commands.add(new api.ODTextCommand("openticket:reopen",{ + name:"reopen", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //CLAIM + if (allowedCommands.includes("claim")) commands.add(new api.ODTextCommand("openticket:claim",{ + name:"claim", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"user", + type:"user", + required:false + }, + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //UNCLAIM + if (allowedCommands.includes("unclaim")) commands.add(new api.ODTextCommand("openticket:unclaim",{ + name:"unclaim", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //PIN + if (allowedCommands.includes("pin")) commands.add(new api.ODTextCommand("openticket:pin",{ + name:"pin", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //UNPIN + if (allowedCommands.includes("unpin")) commands.add(new api.ODTextCommand("openticket:unpin",{ + name:"unpin", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //MOVE + if (allowedCommands.includes("move")) commands.add(new api.ODTextCommand("openticket:move",{ + name:"move", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"id", + type:"string", + required:true, + choices:ticketChoices + }, + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //RENAME + if (allowedCommands.includes("rename")) commands.add(new api.ODTextCommand("openticket:rename",{ + name:"rename", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"name", + type:"string", + required:true, + maxLength:100 + }, + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //ADD + if (allowedCommands.includes("add")) commands.add(new api.ODTextCommand("openticket:add",{ + name:"add", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"user", + type:"user", + required:true + }, + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //REMOVE + if (allowedCommands.includes("remove")) commands.add(new api.ODTextCommand("openticket:remove",{ + name:"remove", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"user", + type:"user", + required:true + }, + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //BLACKLIST + if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("openticket:blacklist-view",{ + name:"blacklist view", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false + })) + + if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("openticket:blacklist-add",{ + name:"blacklist add", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"user", + type:"user", + required:true + }, + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("openticket:blacklist-remove",{ + name:"blacklist remove", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"user", + type:"user", + required:true + }, + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("openticket:blacklist-get",{ + name:"blacklist get", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"user", + type:"user", + required:true + } + ] + })) + + //STATS + if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("openticket:stats-global",{ + name:"stats global", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false + })) + + if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("openticket:stats-reset",{ + name:"stats reset", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("openticket:stats-user",{ + name:"stats user", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"user", + type:"user", + required:false + } + ] + })) + + if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("openticket:stats-ticket",{ + name:"stats ticket", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"ticket", + type:"channel", + required:false, + channelTypes:[discord.ChannelType.GuildText] + } + ] + })) + + //CLEAR + if (allowedCommands.includes("clear")) commands.add(new api.ODTextCommand("openticket:clear",{ + name:"clear", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"filter", + type:"string", + required:false, + allowSpaces:false, + choices:[ + "all", + "open", + "closed", + "claimed", + "unclaimed", + "pinned", + "unpinned", + "autoclosed" + ] + } + ] + })) + + //AUTOCLOSE + if (allowedCommands.includes("autoclose")) commands.add(new api.ODTextCommand("openticket:autoclose-disable",{ + name:"autoclose disable", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + if (allowedCommands.includes("autoclose")) commands.add(new api.ODTextCommand("openticket:autoclose-enable",{ + name:"autoclose enable", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"time", + type:"number", + required:true, + min:0.01, + allowZero:false, + allowNegative:false + }, + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + //AUTODELETE + if (allowedCommands.includes("autodelete")) commands.add(new api.ODTextCommand("openticket:autodelete-disable",{ + name:"autodelete disable", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + + if (allowedCommands.includes("autodelete")) commands.add(new api.ODTextCommand("openticket:autodelete-enable",{ + name:"autodelete enable", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"time", + type:"number", + required:true, + min:0.01, + allowZero:false, + allowNegative:false + }, + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) +} \ No newline at end of file diff --git a/src/data/framework/configLoader.ts b/src/data/framework/configLoader.ts new file mode 100644 index 0000000..f64e711 --- /dev/null +++ b/src/data/framework/configLoader.ts @@ -0,0 +1,12 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllConfigs = async () => { + const devconfigFlag = openticket.flags.get("openticket:dev-config") + const isDevconfig = devconfigFlag ? devconfigFlag.value : false + + openticket.configs.add(new api.ODJsonConfig("openticket:general","general.json",(isDevconfig) ? "./devconfig/" : "./config/")) + openticket.configs.add(new api.ODJsonConfig("openticket:options","options.json",(isDevconfig) ? "./devconfig/" : "./config/")) + openticket.configs.add(new api.ODJsonConfig("openticket:panels","panels.json",(isDevconfig) ? "./devconfig/" : "./config/")) + openticket.configs.add(new api.ODJsonConfig("openticket:questions","questions.json",(isDevconfig) ? "./devconfig/" : "./config/")) + openticket.configs.add(new api.ODJsonConfig("openticket:transcripts","transcripts.json",(isDevconfig) ? "./devconfig/" : "./config/")) +} \ No newline at end of file diff --git a/src/data/framework/cooldownLoader.ts b/src/data/framework/cooldownLoader.ts new file mode 100644 index 0000000..8461ba3 --- /dev/null +++ b/src/data/framework/cooldownLoader.ts @@ -0,0 +1,17 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllCooldowns = async () => { + openticket.options.getAll().forEach((option) => { + if (!(option instanceof api.ODTicketOption)) return + loadTicketOptionCooldown(option) + }) +} + +export const loadTicketOptionCooldown = (option:api.ODTicketOption) => { + if (option.get("openticket:cooldown-enabled").value){ + //option has cooldown + const minutes = option.get("openticket:cooldown-minutes").value + const milliseconds = minutes*60000 + openticket.cooldowns.add(new api.ODTimeoutCooldown("openticket:option-cooldown_"+option.id.value,milliseconds)) + } +} \ No newline at end of file diff --git a/src/data/framework/databaseLoader.ts b/src/data/framework/databaseLoader.ts new file mode 100644 index 0000000..990e0a0 --- /dev/null +++ b/src/data/framework/databaseLoader.ts @@ -0,0 +1,53 @@ +import {openticket, api, utilities} from "../../index" +import * as fjs from "formatted-json-stringify" + +const devdatabaseFlag = openticket.flags.get("openticket:dev-database") +const isDevdatabase = devdatabaseFlag ? devdatabaseFlag.value : false + +export const loadAllDatabases = async () => { + openticket.databases.add(defaultGlobalDatabase) + openticket.databases.add(defaultStatsDatabase) + openticket.databases.add(defaultTicketsDatabase) + openticket.databases.add(defaultUsersDatabase) + openticket.databases.add(defaultOptionsDatabase) +} + +const defaultInlineFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectFormatter(null,false,[ + new fjs.PropertyFormatter("category"), + new fjs.PropertyFormatter("key"), + new fjs.DefaultFormatter("value",false) +])) + +const defaultTicketFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectFormatter(null,true,[ + new fjs.PropertyFormatter("category"), + new fjs.PropertyFormatter("key"), + new fjs.ObjectFormatter("value",true,[ + new fjs.PropertyFormatter("id"), + new fjs.PropertyFormatter("option"), + new fjs.PropertyFormatter("version"), + new fjs.ArrayFormatter("data",true,new fjs.ObjectFormatter(null,false,[ + new fjs.PropertyFormatter("id"), + new fjs.DefaultFormatter("value",false) + ])) + ]) +])) + +const defaultOptionFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectFormatter(null,true,[ + new fjs.PropertyFormatter("category"), + new fjs.PropertyFormatter("key"), + new fjs.ObjectFormatter("value",true,[ + new fjs.PropertyFormatter("id"), + new fjs.PropertyFormatter("type"), + new fjs.PropertyFormatter("version"), + new fjs.ArrayFormatter("data",true,new fjs.ObjectFormatter(null,false,[ + new fjs.PropertyFormatter("id"), + new fjs.DefaultFormatter("value",false) + ])) + ]) +])) + +export const defaultGlobalDatabase = new api.ODFormattedJsonDatabase("openticket:global","global.json",defaultInlineFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") +export const defaultStatsDatabase = new api.ODFormattedJsonDatabase("openticket:stats","stats.json",defaultInlineFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") +export const defaultTicketsDatabase = new api.ODFormattedJsonDatabase("openticket:tickets","tickets.json",defaultTicketFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") +export const defaultUsersDatabase = new api.ODFormattedJsonDatabase("openticket:users","users.json",defaultInlineFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") +export const defaultOptionsDatabase = new api.ODFormattedJsonDatabase("openticket:options","options.json",defaultOptionFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") \ No newline at end of file diff --git a/src/data/framework/eventLoader.ts b/src/data/framework/eventLoader.ts new file mode 100644 index 0000000..0aa865b --- /dev/null +++ b/src/data/framework/eventLoader.ts @@ -0,0 +1,236 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllEvents = () => { + const eventList: (keyof api.ODEventIds_Default)[] = [ + //error handling + "onErrorHandling", + "afterErrorHandling", + + //plugins + "afterPluginsLoaded", + "onPluginClassLoad", + "afterPluginClassesLoaded", + "onPluginEventLoad", + "afterPluginEventsLoaded", + + //flags + "onFlagLoad", + "afterFlagsLoaded", + "onFlagInit", + "afterFlagsInitiated", + + //configs + "onConfigLoad", + "afterConfigsLoaded", + + //databases + "onDatabaseLoad", + "afterDatabasesLoaded", + + //languages + "onLanguageLoad", + "afterLanguagesLoaded", + "onLanguageSelect", + "afterLanguagesSelected", + + //sessions + "onSessionLoad", + "afterSessionsLoaded", + + //config checkers + "onCheckerLoad", + "afterCheckersLoaded", + "onCheckerFunctionLoad", + "afterCheckerFunctionsLoaded", + "onCheckerExecute", + "afterCheckersExecuted", + "onCheckerTranslationLoad", + "afterCheckerTranslationsLoaded", + "onCheckerRender", + "afterCheckersRendered", + "onCheckerQuit", + + //client configuration + "onClientLoad", + "afterClientLoaded", + "onClientInit", + "afterClientInitiated", + "onClientReady", + "afterClientReady", + "onClientActivityLoad", + "afterClientActivityLoaded", + "onClientActivityInit", + "afterClientActivityInitiated", + + //client slash commands + "onSlashCommandLoad", + "afterSlashCommandsLoaded", + "onSlashCommandRegister", + "afterSlashCommandsRegistered", + + //client text commands + "onTextCommandLoad", + "afterTextCommandsLoaded", + + //questions + "onQuestionLoad", + "afterQuestionsLoaded", + + //options + "onOptionLoad", + "afterOptionsLoaded", + + //panels + "onPanelLoad", + "afterPanelsLoaded", + "onPanelSpawn", + "afterPanelSpawned", + + //tickets + "onTicketLoad", + "afterTicketsLoaded", + + //ticket creation + "onTicketChannelCreation", + "afterTicketChannelCreated", + "onTicketChannelDeletion", + "afterTicketChannelDeleted", + "onTicketPermissionsCreated", + "afterTicketPermissionsCreated", + "onTicketMainMessageCreated", + "afterTicketMainMessageCreated", + + //ticket actions + "onTicketCreate", + "afterTicketCreated", + "onTicketClose", + "afterTicketClosed", + "onTicketReopen", + "afterTicketReopened", + "onTicketDelete", + "afterTicketDeleted", + "onTicketMove", + "afterTicketMoved", + "onTicketClaim", + "afterTicketClaimed", + "onTicketUnclaim", + "afterTicketUnclaimed", + "onTicketPin", + "afterTicketPinned", + "onTicketUnpin", + "afterTicketUnpinned", + "onTicketUserAdd", + "afterTicketUserAdded", + "onTicketUserRemove", + "afterTicketUserRemoved", + "onTicketRename", + "afterTicketRenamed", + "onTicketsClear", + "afterTicketsCleared", + + //roles + "onRoleLoad", + "afterRolesLoaded", + "onRoleUpdate", + "afterRolesUpdated", + + //blacklist + "onBlacklistLoad", + "afterBlacklistLoaded", + + //transcripts + "onTranscriptCompilerLoad", + "afterTranscriptCompilersLoaded", + "onTranscriptHistoryLoad", + "afterTranscriptHistoryLoaded", + + //transcript creation + "onTranscriptCreate", + "afterTranscriptCreated", + "onTranscriptInit", + "afterTranscriptInitiated", + "onTranscriptCompile", + "afterTranscriptCompiled", + "onTranscriptReady", + "afterTranscriptReady", + + //builders + "onButtonBuilderLoad", + "afterButtonBuildersLoaded", + "onDropdownBuilderLoad", + "afterDropdownBuildersLoaded", + "onFileBuilderLoad", + "afterFileBuildersLoaded", + "onEmbedBuilderLoad", + "afterEmbedBuildersLoaded", + "onMessageBuilderLoad", + "afterMessageBuildersLoaded", + "onModalBuilderLoad", + "afterModalBuildersLoaded", + + //responders + "onCommandResponderLoad", + "afterCommandRespondersLoaded", + "onButtonResponderLoad", + "afterButtonRespondersLoaded", + "onDropdownResponderLoad", + "afterDropdownRespondersLoaded", + "onModalResponderLoad", + "afterModalRespondersLoaded", + + //actions + "onActionLoad", + "afterActionsLoaded", + + //verifybars + "onVerifyBarLoad", + "afterVerifyBarsLoaded", + + //permissions + "onPermissionLoad", + "afterPermissionsLoaded", + + //posts + "onPostLoad", + "afterPostsLoaded", + "onPostInit", + "afterPostsInitiated", + + //cooldowns + "onCooldownLoad", + "afterCooldownsLoaded", + "onCooldownInit", + "afterCooldownsInitiated", + + //help menu + "onHelpMenuCategoryLoad", + "afterHelpMenuCategoriesLoaded", + "onHelpMenuComponentLoad", + "afterHelpMenuComponentsLoaded", + + //stats + "onStatScopeLoad", + "afterStatScopesLoaded", + "onStatLoad", + "afterStatsLoaded", + "onStatInit", + "afterStatsInitiated", + + //code + "onCodeLoad", + "afterCodeLoaded", + "onCodeExecute", + "afterCodeExecuted", + + //livestatus + "onLiveStatusSourceLoad", + "afterLiveStatusSourcesLoaded", + + //startscreen + "onStartScreenLoad", + "afterStartScreensLoaded", + "onStartScreenRender", + "afterStartScreensRendered" + ] + eventList.forEach((event) => openticket.events.add(new api.ODEvent(event))) +} \ No newline at end of file diff --git a/src/data/framework/flagLoader.ts b/src/data/framework/flagLoader.ts new file mode 100644 index 0000000..7552019 --- /dev/null +++ b/src/data/framework/flagLoader.ts @@ -0,0 +1,16 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllFlags = async () => { + openticket.flags.add(new api.ODFlag("openticket:no-migration","No Migration","Disable Open Ticket data migration on update!","--no-migration",["-nm"])) + openticket.flags.add(new api.ODFlag("openticket:dev-config","Developer Config","Use the configs in /devconfig instead of /config!","--dev-config",["-dc"])) + openticket.flags.add(new api.ODFlag("openticket:dev-database","Developer Database","Use the databases in /devdatabase instead of /database!","--dev-database",["-nd"])) + openticket.flags.add(new api.ODFlag("openticket:debug","Debug Mode","Couldn't you find the error? Try to check this out!","--debug",["-d"])) + openticket.flags.add(new api.ODFlag("openticket:crash","Crash On Error","Crash the bot on an unknown error!","--crash",["-cr"])) + openticket.flags.add(new api.ODFlag("openticket:no-transcripts","No HTML Transcripts","Disable uploading HTML transcripts (for debugging)","--no-transcripts",["-nt"])) + openticket.flags.add(new api.ODFlag("openticket:no-checker","No Config Checker","Disable the Config Checker (for debugging)","--no-checker",["-nc"])) + openticket.flags.add(new api.ODFlag("openticket:checker","Full Config Checker","Render the Config Checker with extra details!","--checker",["-c"])) + openticket.flags.add(new api.ODFlag("openticket:no-easter","No Easter Eggs","Disable little Open Ticket easter eggs hidden in the bot!","--no-easter",["-ne"])) + openticket.flags.add(new api.ODFlag("openticket:no-plugins","No Plugins","Disable all Open Ticket plugins!","--no-plugins",["-np"])) + openticket.flags.add(new api.ODFlag("openticket:soft-plugins","Soft Plugins","Don't crash the bot when a plugin crashes!","--soft-plugins",["-sp"])) + openticket.flags.add(new api.ODFlag("openticket:force-slash-update","Force Slash Update","Force update all slash commands.","--force-slash",["-fs"])) +} \ No newline at end of file diff --git a/src/data/framework/helpMenuLoader.ts b/src/data/framework/helpMenuLoader.ts new file mode 100644 index 0000000..55c84b6 --- /dev/null +++ b/src/data/framework/helpMenuLoader.ts @@ -0,0 +1,263 @@ +import {openticket, api, utilities} from "../../index" + +const lang = openticket.languages + +export const loadAllHelpMenuCategories = async () => { + const helpmenu = openticket.helpmenu + + helpmenu.add(new api.ODHelpMenuCategory("openticket:general",5,utilities.emojiTitle("📎","General Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("openticket:ticket-basic",4,utilities.emojiTitle("🎫","Basic Ticket Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("openticket:ticket-advanced",4,utilities.emojiTitle("💡","Advanced Ticket Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("openticket:ticket-user",3,utilities.emojiTitle("👤","User Ticket Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("openticket:admin",2,utilities.emojiTitle("🚨","Admin Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("openticket:advanced",1,utilities.emojiTitle("🚧","Advanced Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("openticket:extra",0,utilities.emojiTitle("✨","Extra Commands"))) //TODO TRANSLATION!!! +} + +export const loadAllHelpMenuComponents = async () => { + const helpmenu = openticket.helpmenu + const generalConfig = openticket.configs.get("openticket:general") + if (!generalConfig) return + + const prefix = generalConfig.data.prefix + const enableDeleteWithoutTranscript = generalConfig.data.system.enableDeleteWithoutTranscript + + const allowedCommands: string[] = [] + for (const key in generalConfig.data.system.permissions){ + if (generalConfig.data.system.permissions[key] != "none") allowedCommands.push(key) + } + + const general = helpmenu.get("openticket:general") + if (general){ + if (allowedCommands.includes("help")) general.add(new api.ODHelpMenuCommandComponent("openticket:help",1,{ + textName:prefix+"help", + textDescription:lang.getTranslation("helpMenu.help"), + slashName:"/help", + slashDescription:lang.getTranslation("helpMenu.help") + })) + if (allowedCommands.includes("ticket")) general.add(new api.ODHelpMenuCommandComponent("openticket:ticket",0,{ + slashName:"/ticket", + slashDescription:lang.getTranslation("commands.ticket"), + slashOptions:[{name:"id",optional:false}] + })) + } + + const ticketBasic = helpmenu.get("openticket:ticket-basic") + if (ticketBasic){ + if (allowedCommands.includes("close")) ticketBasic.add(new api.ODHelpMenuCommandComponent("openticket:close",10,{ + textName:prefix+"close", + textDescription:lang.getTranslation("helpMenu.close"), + slashName:"/close", + slashDescription:lang.getTranslation("helpMenu.close"), + textOptions:[{name:"reason",optional:true}], + slashOptions:[{name:"reason",optional:true}] + })) + if (enableDeleteWithoutTranscript){ + if (allowedCommands.includes("delete")) ticketBasic.add(new api.ODHelpMenuCommandComponent("openticket:delete",9,{ + textName:prefix+"delete", + textDescription:lang.getTranslation("helpMenu.delete"), + slashName:"/delete", + slashDescription:lang.getTranslation("helpMenu.delete"), + textOptions:[{name:"reason",optional:true}], + slashOptions:[{name:"notranscript",optional:true},{name:"reason",optional:true}] + })) + }else{ + if (allowedCommands.includes("delete")) ticketBasic.add(new api.ODHelpMenuCommandComponent("openticket:delete",9,{ + textName:prefix+"delete", + textDescription:lang.getTranslation("helpMenu.delete"), + slashName:"/delete", + slashDescription:lang.getTranslation("helpMenu.delete"), + textOptions:[{name:"reason",optional:true}], + slashOptions:[{name:"reason",optional:true}] + })) + } + if (allowedCommands.includes("reopen")) ticketBasic.add(new api.ODHelpMenuCommandComponent("openticket:reopen",8,{ + textName:prefix+"reopen", + textDescription:lang.getTranslation("helpMenu.reopen"), + slashName:"/reopen", + slashDescription:lang.getTranslation("helpMenu.reopen"), + textOptions:[{name:"reason",optional:true}], + slashOptions:[{name:"reason",optional:true}] + })) + } + + const ticketAdvanced = helpmenu.get("openticket:ticket-advanced") + if (ticketAdvanced){ + if (allowedCommands.includes("pin")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("openticket:pin",5,{ + textName:prefix+"pin", + textDescription:lang.getTranslation("helpMenu.pin"), + slashName:"/pin", + slashDescription:lang.getTranslation("helpMenu.pin"), + textOptions:[{name:"reason",optional:true}], + slashOptions:[{name:"reason",optional:true}] + })) + if (allowedCommands.includes("unpin")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("openticket:unpin",4,{ + textName:prefix+"unpin", + textDescription:lang.getTranslation("helpMenu.unpin"), + slashName:"/unpin", + slashDescription:lang.getTranslation("helpMenu.unpin"), + textOptions:[{name:"reason",optional:true}], + slashOptions:[{name:"reason",optional:true}] + })) + if (allowedCommands.includes("move")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("openticket:move",3,{ + textName:prefix+"move", + textDescription:lang.getTranslation("helpMenu.move"), + slashName:"/move", + slashDescription:lang.getTranslation("helpMenu.move"), + textOptions:[{name:"id",optional:false},{name:"reason",optional:true}], + slashOptions:[{name:"id",optional:false},{name:"reason",optional:true}] + })) + if (allowedCommands.includes("rename")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("openticket:rename",2,{ + textName:prefix+"rename", + textDescription:lang.getTranslation("helpMenu.rename"), + slashName:"/rename", + slashDescription:lang.getTranslation("helpMenu.rename"), + textOptions:[{name:"name",optional:false},{name:"reason",optional:true}], + slashOptions:[{name:"name",optional:false},{name:"reason",optional:true}] + })) + } + + const ticketUser = helpmenu.get("openticket:ticket-channel") + if (ticketUser){ + if (allowedCommands.includes("claim")) ticketUser.add(new api.ODHelpMenuCommandComponent("openticket:claim",7,{ + textName:prefix+"claim", + textDescription:lang.getTranslation("helpMenu.claim"), + slashName:"/claim", + slashDescription:lang.getTranslation("helpMenu.claim"), + textOptions:[{name:"user",optional:true},{name:"reason",optional:true}], + slashOptions:[{name:"user",optional:true},{name:"reason",optional:true}] + })) + if (allowedCommands.includes("unclaim")) ticketUser.add(new api.ODHelpMenuCommandComponent("openticket:unclaim",6,{ + textName:prefix+"unclaim", + textDescription:lang.getTranslation("helpMenu.unclaim"), + slashName:"/unclaim", + slashDescription:lang.getTranslation("helpMenu.unclaim"), + textOptions:[{name:"reason",optional:true}], + slashOptions:[{name:"reason",optional:true}] + })) + if (allowedCommands.includes("add")) ticketUser.add(new api.ODHelpMenuCommandComponent("openticket:add",1,{ + textName:prefix+"add", + textDescription:lang.getTranslation("helpMenu.add"), + slashName:"/add", + slashDescription:lang.getTranslation("helpMenu.add"), + textOptions:[{name:"user",optional:false},{name:"reason",optional:true}], + slashOptions:[{name:"user",optional:false},{name:"reason",optional:true}] + })) + if (allowedCommands.includes("remove")) ticketUser.add(new api.ODHelpMenuCommandComponent("openticket:remove",0,{ + textName:prefix+"remove", + textDescription:lang.getTranslation("helpMenu.remove"), + slashName:"/remove", + slashDescription:lang.getTranslation("helpMenu.remove"), + textOptions:[{name:"user",optional:false},{name:"reason",optional:true}], + slashOptions:[{name:"user",optional:false},{name:"reason",optional:true}] + })) + } + + const admin = helpmenu.get("openticket:admin") + if (admin){ + if (allowedCommands.includes("panel")) admin.add(new api.ODHelpMenuCommandComponent("openticket:panel",4,{ + textName:prefix+"panel", + textDescription:lang.getTranslation("helpMenu.panel"), + slashName:"/panel", + slashDescription:lang.getTranslation("helpMenu.panel"), + textOptions:[{name:"id",optional:false}], + slashOptions:[{name:"id",optional:false}] + })) + if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("openticket:blacklist-view",3,{ + textName:prefix+"blacklist view", + textDescription:lang.getTranslation("commands.blacklistView"), + slashName:"/blacklist view", + slashDescription:lang.getTranslation("commands.blacklistView") + })) + if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("openticket:blacklist-add",2,{ + textName:prefix+"blacklist add", + textDescription:lang.getTranslation("commands.blacklistAdd"), + slashName:"/blacklist add", + slashDescription:lang.getTranslation("commands.blacklistAdd"), + textOptions:[{name:"user",optional:false},{name:"reason",optional:true}], + slashOptions:[{name:"user",optional:false},{name:"reason",optional:true}] + })) + if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("openticket:blacklist-remove",1,{ + textName:prefix+"blacklist remove", + textDescription:lang.getTranslation("commands.blacklistRemove"), + slashName:"/blacklist remove", + slashDescription:lang.getTranslation("commands.blacklistRemove"), + textOptions:[{name:"user",optional:false},{name:"reason",optional:true}], + slashOptions:[{name:"user",optional:false},{name:"reason",optional:true}] + })) + if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("openticket:blacklist-get",0,{ + textName:prefix+"blacklist get", + textDescription:lang.getTranslation("commands.blacklistGet"), + slashName:"/blacklist get", + slashDescription:lang.getTranslation("commands.blacklistGet"), + textOptions:[{name:"user",optional:false}], + slashOptions:[{name:"user",optional:false}] + })) + } + + const advanced = helpmenu.get("openticket:advanced") + if (advanced){ + if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:stats-global",5,{ + textName:prefix+"stats global", + textDescription:lang.getTranslation("commands.statsGlobal"), + slashName:"/stats global", + slashDescription:lang.getTranslation("commands.statsGlobal") + })) + if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:stats-ticket",4,{ + textName:prefix+"stats ticket", + textDescription:lang.getTranslation("commands.statsTicket"), + slashName:"/stats ticket", + slashDescription:lang.getTranslation("commands.statsTicket"), + textOptions:[{name:"ticket",optional:false}], + slashOptions:[{name:"ticket",optional:false}] + })) + if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:stats-user",2,{ + textName:prefix+"stats user", + textDescription:lang.getTranslation("commands.statsUser"), + slashName:"/stats user", + slashDescription:lang.getTranslation("commands.statsUser"), + textOptions:[{name:"user",optional:false}], + slashOptions:[{name:"user",optional:false}] + })) + if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:stats-reset",2,{ + textName:prefix+"stats reset", + textDescription:lang.getTranslation("commands.statsReset"), + slashName:"/stats reset", + slashDescription:lang.getTranslation("commands.statsReset"), + textOptions:[{name:"reason",optional:true}], + slashOptions:[{name:"reason",optional:true}] + })) + if (allowedCommands.includes("autoclose")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:autoclose-disable",1,{ + textName:prefix+"autoclose disable", + textDescription:lang.getTranslation("commands.autocloseDisable"), + slashName:"/autoclose disable", + slashDescription:lang.getTranslation("commands.autocloseDisable"), + textOptions:[{name:"reason",optional:true}], + slashOptions:[{name:"reason",optional:true}] + })) + if (allowedCommands.includes("autoclose")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:autoclose-enable",0,{ + textName:prefix+"autoclose enable", + textDescription:lang.getTranslation("commands.autocloseEnable"), + slashName:"/autoclose enable", + slashDescription:lang.getTranslation("commands.autocloseEnable"), + textOptions:[{name:"time",optional:false},{name:"reason",optional:true}], + slashOptions:[{name:"time",optional:false},{name:"reason",optional:true}] + })) + if (allowedCommands.includes("autodelete")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:autodelete-disable",1,{ + textName:prefix+"autodelete disable", + textDescription:lang.getTranslation("commands.autodeleteDisable"), + slashName:"/autodelete disable", + slashDescription:lang.getTranslation("commands.autodeleteDisable"), + textOptions:[{name:"reason",optional:true}], + slashOptions:[{name:"reason",optional:true}] + })) + if (allowedCommands.includes("autodelete")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:autodelete-enable",0,{ + textName:prefix+"autodelete enable", + textDescription:lang.getTranslation("commands.autodeleteEnable"), + slashName:"/autodelete enable", + slashDescription:lang.getTranslation("commands.autodeleteEnable"), + textOptions:[{name:"time",optional:false},{name:"reason",optional:true}], + slashOptions:[{name:"time",optional:false},{name:"reason",optional:true}] + })) + } +} \ No newline at end of file diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts new file mode 100644 index 0000000..11261b1 --- /dev/null +++ b/src/data/framework/languageLoader.ts @@ -0,0 +1,15 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllLanguages = async () => { + openticket.languages.add(new api.ODLanguage("openticket:custom","custom.json")) + openticket.languages.add(new api.ODLanguage("openticket:english","english.json")) + openticket.languages.add(new api.ODLanguage("openticket:dutch","dutch.json")) + openticket.languages.add(new api.ODLanguage("openticket:portuguese","portuguese.json")) + openticket.languages.add(new api.ODLanguage("openticket:czech","czech.json")) + + /** How to add more languages? + * - Add the language to the list above + * - Add the language to the "languageList" in the "ODDefaultsManager" class + * - Add the language to the list in the "ODLanguageManagerIds_Default" interface + */ +} \ No newline at end of file diff --git a/src/data/framework/liveStatusLoader.ts b/src/data/framework/liveStatusLoader.ts new file mode 100644 index 0000000..5864178 --- /dev/null +++ b/src/data/framework/liveStatusLoader.ts @@ -0,0 +1,6 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllLiveStatusSources = async () => { + //DEFAULT DJDJ DEV + openticket.livestatus.add(new api.ODLiveStatusUrlSource("openticket:default-djdj-dev","https://apis.dj-dj.be/status/openticket.json")) +} \ No newline at end of file diff --git a/src/data/framework/permissionLoader.ts b/src/data/framework/permissionLoader.ts new file mode 100644 index 0000000..4b080f8 --- /dev/null +++ b/src/data/framework/permissionLoader.ts @@ -0,0 +1,82 @@ +import {openticket, api, utilities} from "../../index" +import * as discord from "discord.js" + +export const loadAllPermissions = async () => { + const generalConfig = openticket.configs.get("openticket:general") + if (!generalConfig) return + const mainServer = openticket.client.mainServer + if (!mainServer) return + + //DEVELOPER & OWNER + const developer = (await openticket.client.client.application.fetch()).owner + if (developer instanceof discord.User){ + openticket.permissions.add(new api.ODPermission("openticket:developer-"+developer.id,"global-user","developer",developer)) + }else if (developer instanceof discord.Team){ + developer.members.forEach((member) => { + openticket.permissions.add(new api.ODPermission("openticket:developer-"+member.user.id,"global-user","developer",member.user)) + }) + } + const owner = (await mainServer.members.fetch(mainServer.ownerId)).user + openticket.permissions.add(new api.ODPermission("openticket:owner-"+owner.id,"global-user","owner",owner)) + + //GLOBAL ADMINS + generalConfig.data.globalAdmins.forEach(async (admin) => { + const role = await mainServer.roles.fetch(admin) + if (!role) return openticket.log("Unable to register permission for global admin!","error",[ + {key:"roleid",value:admin} + ]) + + openticket.permissions.add(new api.ODPermission("openticket:global-admin-"+admin,"global-role","admin",role)) + }) + + //TICKET ADMINS + openticket.tickets.getAll().forEach(async (ticket) => { + try { + const channel = await openticket.client.fetchGuildTextChannel(mainServer,ticket.id.value) + if (!channel) return + + const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] + const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] + + admins.concat(readAdmins).forEach(async (admin) => { + const role = await mainServer.roles.fetch(admin) + if (!role) return openticket.log("Unable to register permission for ticket admin!","error",[ + {key:"roleid",value:admin} + ]) + + openticket.permissions.add(new api.ODPermission("openticket:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) + }) + }catch(err){ + process.emit("uncaughtException",err) + openticket.log("Ticket Admin Loading Permissions Error (see above)","error") + } + }) +} + +export const addTicketPermissions = async (ticket:api.ODTicket) => { + const mainServer = openticket.client.mainServer + if (!mainServer) return + const channel = await openticket.client.fetchGuildTextChannel(mainServer,ticket.id.value) + if (!channel) return + + const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] + const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] + + admins.concat(readAdmins).forEach(async (admin) => { + const role = await mainServer.roles.fetch(admin) + if (!role) return openticket.log("Unable to register permission for ticket admin!","error",[ + {key:"roleid",value:admin} + ]) + + openticket.permissions.add(new api.ODPermission("openticket:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) + }) +} + +export const removeTicketPermissions = async (ticket:api.ODTicket) => { + const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] + const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] + + admins.concat(readAdmins).forEach(async (admin) => { + openticket.permissions.remove("openticket:ticket-admin_"+ticket.id.value+"_"+admin) + }) +} \ No newline at end of file diff --git a/src/data/framework/postLoader.ts b/src/data/framework/postLoader.ts new file mode 100644 index 0000000..7ddcac0 --- /dev/null +++ b/src/data/framework/postLoader.ts @@ -0,0 +1,14 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllPosts = async () => { + const generalConfig = openticket.configs.get("openticket:general") + if (!generalConfig) return + const transcriptConfig = openticket.configs.get("openticket:transcripts") + if (!transcriptConfig) return + + //LOGS CHANNEL + if (generalConfig.data.system.logs.enabled) openticket.posts.add(new api.ODPost("openticket:logs",generalConfig.data.system.logs.channel)) + + //TRANSCRIPTS CHANNEL + if (transcriptConfig.data.general.enabled && transcriptConfig.data.general.enableChannel) openticket.posts.add(new api.ODPost("openticket:transcripts",transcriptConfig.data.general.channel)) +} \ No newline at end of file diff --git a/src/data/framework/startScreenLoader.ts b/src/data/framework/startScreenLoader.ts new file mode 100644 index 0000000..ecc407d --- /dev/null +++ b/src/data/framework/startScreenLoader.ts @@ -0,0 +1,54 @@ +import {openticket, api, utilities} from "../../index" +import ansis from "ansis" + +export const loadAllStartScreenComponents = async () => { + /** + "openticket:flags":ODStartScreenFlagsCategoryComponent, + "openticket:plugins":ODStartScreenPluginsCategoryComponent, + + "openticket:livestatus":ODStartScreenLiveStatusCategoryComponent, + */ + + //LOGO + openticket.startscreen.add(new api.ODStartScreenLogoComponent("openticket:logo",1000,[ + " ██████╗ ██████╗ ███████╗███╗ ██╗ ████████╗██╗ ██████╗██╗ ██╗███████╗████████╗ ", + " ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝ ", + " ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ ██║██║ █████╔╝ █████╗ ██║ ", + " ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██╔═██╗ ██╔══╝ ██║ ", + " ╚██████╔╝██║ ███████╗██║ ╚████║ ██║ ██║╚██████╗██║ ██╗███████╗ ██║ ", + " ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ " + ],true,false)) + + //HEADER + const currentLanguageMetadata = openticket.languages.getLanguageMetadata() + openticket.startscreen.add(new api.ODStartScreenHeaderComponent("openticket:header",999,[ + {key:"Version",value:openticket.versions.get("openticket:version").toString()}, + {key:"Support",value:"https://discord.dj-dj.be"}, + {key:"Language",value:(currentLanguageMetadata ? currentLanguageMetadata.language : "Unknown")} + ]," - ",{ + align:"center", + width:openticket.startscreen.get("openticket:logo") + })) + + //FLAGS + openticket.startscreen.add(new api.ODStartScreenFlagsCategoryComponent("openticket:flags",4,openticket.flags.getAll())) + + //PLUGINS + openticket.startscreen.add(new api.ODStartScreenPluginsCategoryComponent("openticket:plugins",3,openticket.plugins.getAll(),openticket.plugins.unknownCrashedPlugins)) + + //STATS + openticket.startscreen.add(new api.ODStartScreenPropertiesCategoryComponent("openticket:stats",2,"startup info",[ + {key:"status",value:ansis.bold(openticket.client.activity.getStatusType())+openticket.client.activity.text+" ("+openticket.client.activity.status+")"}, + {key:"options",value:"loaded "+ansis.bold(openticket.options.getLength().toString())+" options!"}, + {key:"panels",value:"loaded "+ansis.bold(openticket.panels.getLength().toString())+" panels!"}, + {key:"tickets",value:"loaded "+ansis.bold(openticket.tickets.getLength().toString())+" tickets!"}, + {key:"roles",value:"loaded "+ansis.bold(openticket.roles.getLength().toString())+" roles!"}, + {key:"help",value:ansis.bold(openticket.configs.get("openticket:general").data.prefix+"help")+" or "+ansis.bold("/help")} + ])) + + //LIVESTATUS + openticket.startscreen.add(new api.ODStartScreenLiveStatusCategoryComponent("openticket:livestatus",1,openticket.livestatus)) + + //LOGS + openticket.startscreen.add(new api.ODStartScreenLogCategoryComponent("openticket:logs",0)) +} \ No newline at end of file diff --git a/src/data/framework/statLoader.ts b/src/data/framework/statLoader.ts new file mode 100644 index 0000000..d3508e9 --- /dev/null +++ b/src/data/framework/statLoader.ts @@ -0,0 +1,133 @@ +import {openticket, api, utilities} from "../../index" +import * as discord from "discord.js" + +const stats = openticket.stats +const lang = openticket.languages + +export const loadAllStatScopes = async () => { + stats.add(new api.ODStatGlobalScope("openticket:global",utilities.emojiTitle("📊",lang.getTranslation("stats.scopes.global")))) + stats.add(new api.ODStatGlobalScope("openticket:system",utilities.emojiTitle("⚙️",lang.getTranslation("stats.scopes.system")))) + stats.add(new api.ODStatScope("openticket:user",utilities.emojiTitle("📊",lang.getTranslation("stats.scopes.user")))) + stats.add(new api.ODStatScope("openticket:ticket",utilities.emojiTitle("📊",lang.getTranslation("stats.scopes.ticket")))) + stats.add(new api.ODStatScope("openticket:participants",utilities.emojiTitle("👥",lang.getTranslation("stats.scopes.participants")))) +} + +export const loadAllStats = async () => { + const generalConfig = openticket.configs.get("openticket:general") + if (!generalConfig) return + + const global = stats.get("openticket:global") + if (global){ + global.add(new api.ODBasicStat("openticket:tickets-created",10,lang.getTranslation("stats.properties.ticketsCreated"),0)) + global.add(new api.ODBasicStat("openticket:tickets-closed",9,lang.getTranslation("stats.properties.ticketsClosed"),0)) + global.add(new api.ODBasicStat("openticket:tickets-deleted",8,lang.getTranslation("stats.properties.ticketsDeleted"),0)) + global.add(new api.ODBasicStat("openticket:tickets-reopened",7,lang.getTranslation("stats.properties.ticketsReopened"),0)) + global.add(new api.ODBasicStat("openticket:tickets-autoclosed",6,lang.getTranslation("stats.properties.ticketsAutoclosed"),0)) + global.add(new api.ODBasicStat("openticket:tickets-autodeleted",5,"Tickets Autodeleted",0)) //TODO TRANSLATION!!! + global.add(new api.ODBasicStat("openticket:tickets-claimed",4,lang.getTranslation("stats.properties.ticketsClaimed"),0)) + global.add(new api.ODBasicStat("openticket:tickets-pinned",3,lang.getTranslation("stats.properties.ticketsPinned"),0)) + global.add(new api.ODBasicStat("openticket:tickets-moved",2,lang.getTranslation("stats.properties.ticketsMoved"),0)) + global.add(new api.ODBasicStat("openticket:users-blacklisted",1,lang.getTranslation("stats.properties.usersBlacklisted"),0)) + global.add(new api.ODBasicStat("openticket:transcripts-created",0,lang.getTranslation("stats.properties.transcriptsCreated"),0)) + } + + const system = stats.get("openticket:system") + if (system){ + system.add(new api.ODDynamicStat("openticket:startup-date",1,() => { + return lang.getTranslation("params.uppercase.startupDate")+": "+discord.time(new Date(),"f") + })) + system.add(new api.ODDynamicStat("openticket:version",0,() => { + return lang.getTranslation("params.uppercase.version")+": `"+openticket.versions.get("openticket:version").toString()+"`" + })) + } + + const user = stats.get("openticket:user") + if (user){ + user.add(new api.ODDynamicStat("openticket:name",11,async (scopeId,guild,channel,user) => { + return lang.getTranslation("params.uppercase.name")+": "+discord.userMention(scopeId) + })) + user.add(new api.ODDynamicStat("openticket:role",10,async (scopeId,guild,channel,user) => { + try{ + const scopeMember = await guild.members.fetch(scopeId) + if (!scopeMember) return "" + + const permissions = await openticket.permissions.getPermissions(scopeMember.user,channel,guild) + if (permissions.type == "developer") return lang.getTranslation("params.uppercase.role")+": 💻 `Developer`" //TODO TRANSLATION!!! + if (permissions.type == "owner") return lang.getTranslation("params.uppercase.role")+": 👑 `Server Owner`" //TODO TRANSLATION!!! + if (permissions.type == "admin") return lang.getTranslation("params.uppercase.role")+": 💼 `Server Admin`" //TODO TRANSLATION!!! + if (permissions.type == "moderator") return lang.getTranslation("params.uppercase.role")+": 🚔 `Moderator Team`" //TODO TRANSLATION!!! + if (permissions.type == "support") return lang.getTranslation("params.uppercase.role")+": 💬 `Support Team`" //TODO TRANSLATION!!! + else return lang.getTranslation("params.uppercase.role")+": 👤 `Member`" //TODO TRANSLATION!!! + }catch{ + return "" + } + })) + user.add(new api.ODBasicStat("openticket:tickets-created",8,lang.getTranslation("stats.properties.ticketsCreated"),0)) + user.add(new api.ODBasicStat("openticket:tickets-closed",7,lang.getTranslation("stats.properties.ticketsClosed"),0)) + user.add(new api.ODBasicStat("openticket:tickets-deleted",6,lang.getTranslation("stats.properties.ticketsDeleted"),0)) + user.add(new api.ODBasicStat("openticket:tickets-reopened",5,lang.getTranslation("stats.properties.ticketsReopened"),0)) + user.add(new api.ODBasicStat("openticket:tickets-claimed",4,lang.getTranslation("stats.properties.ticketsClaimed"),0)) + user.add(new api.ODBasicStat("openticket:tickets-pinned",3,lang.getTranslation("stats.properties.ticketsPinned"),0)) + user.add(new api.ODBasicStat("openticket:tickets-moved",2,lang.getTranslation("stats.properties.ticketsMoved"),0)) + user.add(new api.ODBasicStat("openticket:users-blacklisted",1,lang.getTranslation("stats.properties.usersBlacklisted"),0)) + user.add(new api.ODBasicStat("openticket:transcripts-created",0,lang.getTranslation("stats.properties.transcriptsCreated"),0)) + } + + const ticket = stats.get("openticket:ticket") + if (ticket){ + ticket.add(new api.ODDynamicStat("openticket:name",5,async (scopeId,guild,channel,user) => { + return lang.getTranslation("params.uppercase.ticket")+": "+discord.channelMention(scopeId) + })) + ticket.add(new api.ODDynamicStat("openticket:status",4,async (scopeId,guild,channel,user) => { + const ticket = openticket.tickets.get(scopeId) + if (!ticket) return "" + + const closed = ticket.exists("openticket:closed") ? ticket.get("openticket:closed").value : false + + return closed ? lang.getTranslation("params.uppercase.status")+": 🔒 `Closed`" : lang.getTranslation("params.uppercase.status")+": 🔓 `Open`" //TODO TRANSLATION!!! + })) + ticket.add(new api.ODDynamicStat("openticket:claimed",3,async (scopeId,guild,channel,user) => { + const ticket = openticket.tickets.get(scopeId) + if (!ticket) return "" + + const claimed = ticket.exists("openticket:claimed") ? ticket.get("openticket:claimed").value : false + return claimed ? lang.getTranslation("params.uppercase.claimed")+": 🟢 `Yes`" : lang.getTranslation("params.uppercase.claimed")+": 🔴 `No`" + })) + ticket.add(new api.ODDynamicStat("openticket:pinned",2,async (scopeId,guild,channel,user) => { + const ticket = openticket.tickets.get(scopeId) + if (!ticket) return "" + + const pinned = ticket.exists("openticket:pinned") ? ticket.get("openticket:pinned").value : false + return pinned ? lang.getTranslation("params.uppercase.pinned")+": 🟢 `Yes`" : lang.getTranslation("params.uppercase.pinned")+": 🔴 `No`" + })) + ticket.add(new api.ODDynamicStat("openticket:creation-date",1,async (scopeId,guild,channel,user) => { + const ticket = openticket.tickets.get(scopeId) + if (!ticket) return "" + + const rawDate = ticket.get("openticket:opened-on").value ?? new Date().getTime() + return lang.getTranslation("params.uppercase.creationDate")+": "+discord.time(new Date(rawDate),"f") + })) + ticket.add(new api.ODDynamicStat("openticket:creator",0,async (scopeId,guild,channel,user) => { + const ticket = openticket.tickets.get(scopeId) + if (!ticket) return "" + + const creator = ticket.get("openticket:opened-by").value + return lang.getTranslation("params.uppercase.creator")+": "+ (creator ? discord.userMention(creator) : "`unknown`") + })) + } + + const participants = stats.get("openticket:participants") + if (participants){ + participants.add(new api.ODDynamicStat("openticket:participants",0,async (scopeId,guild,channel,user) => { + const ticket = openticket.tickets.get(scopeId) + if (!ticket) return "" + + const participants = ticket.exists("openticket:participants") ? ticket.get("openticket:participants").value : [] + + return participants.map((p) => { + return (p.type == "role") ? discord.roleMention(p.id) : discord.userMention(p.id) + }).join("\n") + })) + + } +} \ No newline at end of file diff --git a/src/data/openticket/blacklistLoader.ts b/src/data/openticket/blacklistLoader.ts new file mode 100644 index 0000000..63b1947 --- /dev/null +++ b/src/data/openticket/blacklistLoader.ts @@ -0,0 +1,12 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllBlacklistedUsers = async () => { + const userDatabase = openticket.databases.get("openticket:users") + if (!userDatabase) return + + const users = userDatabase.getCategory("openticket:blacklist") ?? [] + users.forEach((user) => { + if (typeof user.value != "string") return + openticket.blacklist.add(new api.ODBlacklist(user.key,user.value)) + }) +} \ No newline at end of file diff --git a/src/data/openticket/optionLoader.ts b/src/data/openticket/optionLoader.ts new file mode 100644 index 0000000..9e54417 --- /dev/null +++ b/src/data/openticket/optionLoader.ts @@ -0,0 +1,107 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllOptions = async () => { + const optionConfig = openticket.configs.get("openticket:options") + if (!optionConfig) return + + optionConfig.data.forEach((option) => { + if (option.type == "ticket"){ + const loadedOption = loadTicketOption(option) + openticket.options.add(loadedOption) + openticket.options.suffix.add(loadTicketOptionSuffix(loadedOption)) + }else if (option.type == "website"){ + openticket.options.add(loadWebsiteOption(option)) + }else if (option.type == "role"){ + openticket.options.add(loadRoleOption(option)) + } + }) +} + +export const loadTicketOption = (option:api.ODJsonConfig_DefaultOptionTicketType): api.ODTicketOption => { + return new api.ODTicketOption(option.id,[ + new api.ODOptionData("openticket:name",option.name), + new api.ODOptionData("openticket:description",option.description), + + new api.ODOptionData("openticket:button-emoji",option.button.emoji), + new api.ODOptionData("openticket:button-label",option.button.label), + new api.ODOptionData("openticket:button-color",option.button.color), + + new api.ODOptionData("openticket:admins",option.ticketAdmins), + new api.ODOptionData("openticket:admins-readonly",option.readonlyAdmins), + new api.ODOptionData("openticket:allow-blacklisted-users",option.allowCreationByBlacklistedUsers), + new api.ODOptionData("openticket:questions",option.questions), + + new api.ODOptionData("openticket:channel-prefix",option.channel.prefix), + new api.ODOptionData("openticket:channel-suffix",option.channel.suffix), + new api.ODOptionData("openticket:channel-category",option.channel.category), + new api.ODOptionData("openticket:channel-category-closed",option.channel.closedCategory), + new api.ODOptionData("openticket:channel-category-backup",option.channel.backupCategory), + new api.ODOptionData("openticket:channel-categories-claimed",option.channel.claimedCategory), + new api.ODOptionData("openticket:channel-description",option.channel.description), + + new api.ODOptionData("openticket:dm-message-enabled",option.dmMessage.enabled), + new api.ODOptionData("openticket:dm-message-text",option.dmMessage.text), + new api.ODOptionData("openticket:dm-message-embed",option.dmMessage.embed), + + new api.ODOptionData("openticket:ticket-message-enabled",option.ticketMessage.enabled), + new api.ODOptionData("openticket:ticket-message-text",option.ticketMessage.text), + new api.ODOptionData("openticket:ticket-message-embed",option.ticketMessage.embed), + new api.ODOptionData("openticket:ticket-message-ping",option.ticketMessage.ping), + + new api.ODOptionData("openticket:autoclose-enable-hours",option.autoclose.enableInactiveHours), + new api.ODOptionData("openticket:autoclose-enable-leave",option.autoclose.enableUserLeave), + new api.ODOptionData("openticket:autoclose-disable-claim",option.autoclose.disableOnClaim), + new api.ODOptionData("openticket:autoclose-hours",option.autoclose.inactiveHours), + + new api.ODOptionData("openticket:autodelete-enable-days",option.autodelete.enableInactiveDays), + new api.ODOptionData("openticket:autodelete-enable-leave",option.autodelete.enableUserLeave), + new api.ODOptionData("openticket:autodelete-disable-claim",option.autodelete.disableOnClaim), + new api.ODOptionData("openticket:autodelete-days",option.autodelete.inactiveDays), + + new api.ODOptionData("openticket:cooldown-enabled",option.cooldown.enabled), + new api.ODOptionData("openticket:cooldown-minutes",option.cooldown.cooldownMinutes), + + new api.ODOptionData("openticket:limits-enabled",option.limits.enabled), + new api.ODOptionData("openticket:limits-maximum-global",option.limits.globalMaximum), + new api.ODOptionData("openticket:limits-maximum-user",option.limits.userMaximum) + ]) +} + +export const loadWebsiteOption = (opt:api.ODJsonConfig_DefaultOptionWebsiteType): api.ODWebsiteOption => { + return new api.ODWebsiteOption(opt.id,[ + new api.ODOptionData("openticket:name",opt.name), + new api.ODOptionData("openticket:description",opt.description), + + new api.ODOptionData("openticket:button-emoji",opt.button.emoji), + new api.ODOptionData("openticket:button-label",opt.button.label), + + new api.ODOptionData("openticket:url",opt.url) + ]) +} + +export const loadRoleOption = (opt:api.ODJsonConfig_DefaultOptionRoleType): api.ODRoleOption => { + return new api.ODRoleOption(opt.id,[ + new api.ODOptionData("openticket:name",opt.name), + new api.ODOptionData("openticket:description",opt.description), + + new api.ODOptionData("openticket:button-emoji",opt.button.emoji), + new api.ODOptionData("openticket:button-label",opt.button.label), + new api.ODOptionData("openticket:button-color",opt.button.color), + + new api.ODOptionData("openticket:roles",opt.roles), + new api.ODOptionData("openticket:mode",opt.mode), + new api.ODOptionData("openticket:remove-roles-on-add",opt.removeRolesOnAdd), + new api.ODOptionData("openticket:add-on-join",opt.addOnMemberJoin) + ]) +} + +export const loadTicketOptionSuffix = (option:api.ODTicketOption): api.ODOptionSuffix => { + const mode = option.get("openticket:channel-suffix").value + const globalDatabase = openticket.databases.get("openticket:global") + if (mode == "user-name") return new api.ODOptionUserNameSuffix(option.id.value,option) + else if (mode == "random-number") return new api.ODOptionRandomNumberSuffix(option.id.value,option,globalDatabase) + else if (mode == "random-hex") return new api.ODOptionRandomHexSuffix(option.id.value,option,globalDatabase) + else if (mode == "counter-fixed") return new api.ODOptionCounterFixedSuffix(option.id.value,option,globalDatabase) + else if (mode == "counter-dynamic") return new api.ODOptionCounterDynamicSuffix(option.id.value,option,globalDatabase) + else return new api.ODOptionUserIdSuffix(option.id.value,option) +} \ No newline at end of file diff --git a/src/data/openticket/panelLoader.ts b/src/data/openticket/panelLoader.ts new file mode 100644 index 0000000..5737c53 --- /dev/null +++ b/src/data/openticket/panelLoader.ts @@ -0,0 +1,165 @@ +import {openticket, api, utilities} from "../../index" +import * as discord from "discord.js" + +export const loadAllPanels = async () => { + const panelConfig = openticket.configs.get("openticket:panels") + if (!panelConfig) return + + panelConfig.data.forEach((panel) => { + openticket.panels.add(loadPanel(panel)) + }) +} + +export const loadPanel = (panel:api.ODJsonConfig_DefaultPanelType) => { + return new api.ODPanel(panel.id,[ + new api.ODPanelData("openticket:name",panel.name), + new api.ODPanelData("openticket:options",panel.options), + new api.ODPanelData("openticket:dropdown",panel.dropdown), + + new api.ODPanelData("openticket:text",panel.text), + new api.ODPanelData("openticket:embed",panel.embed), + + new api.ODPanelData("openticket:dropdown-placeholder",panel.settings.dropdownPlaceholder), + new api.ODPanelData("openticket:enable-max-tickets-warning-text",panel.settings.enableMaxTicketsWarningInText), + new api.ODPanelData("openticket:enable-max-tickets-warning-embed",panel.settings.enableMaxTicketsWarningInEmbed), + new api.ODPanelData("openticket:describe-options-layout",panel.settings.describeOptionsLayout), + new api.ODPanelData("openticket:describe-options-custom-title",panel.settings.describeOptionsCustomTitle), + new api.ODPanelData("openticket:describe-options-in-text",panel.settings.describeOptionsInText), + new api.ODPanelData("openticket:describe-options-in-embed-fields",panel.settings.describeOptionsInEmbedFields), + new api.ODPanelData("openticket:describe-options-in-embed-description",panel.settings.describeOptionsInEmbedDescription), + ]) +} +export function describePanelOptions(mode:"fields",panel:api.ODPanel): {name:string,value:string}[] +export function describePanelOptions(mode:"text",panel:api.ODPanel): string +export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): {name:string,value:string}[]|string { + const layout = panel.get("openticket:describe-options-layout").value + const dropdownMode = panel.get("openticket:dropdown").value + const options: api.ODOption[] = [] + let hasTicket = false + let hasWebsite = false + let hasRole = false + let ticketOnly = true + let websiteOnly = true + let roleOnly = true + panel.get("openticket:options").value.forEach((id) => { + const opt = openticket.options.get(id) + if (opt){ + if (opt instanceof api.ODTicketOption){ + options.push(opt) + hasTicket = true + roleOnly = false + websiteOnly = false + }else if (!dropdownMode && opt instanceof api.ODWebsiteOption){ + options.push(opt) + hasWebsite = true + ticketOnly = false + roleOnly = false + }else if (!dropdownMode && opt instanceof api.ODRoleOption){ + options.push(opt) + hasRole = true + ticketOnly = false + websiteOnly = false + } + } + }) + + const autotitle = (hasTicket && ticketOnly) ? "Select your ticket:" : ((hasRole && roleOnly) ? "Select your role:" : "Select your option:") + const title = (panel.get("openticket:describe-options-custom-title").value.length < 1) ? "__"+autotitle+"__\n" : "__"+panel.get("openticket:describe-options-custom-title").value+"__\n" + + if (mode == "fields") return options.map((opt) => { + if (opt instanceof api.ODTicketOption){ + //ticket option + const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" + const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" + let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + + if (layout == "normal" || layout == "detailed"){ + if (opt.exists("openticket:cooldown-enabled") && opt.get("openticket:cooldown-enabled").value) description = description + "\nCooldown: `"+opt.get("openticket:cooldown-minutes").value+" min`" + if (opt.exists("openticket:limits-enabled") && opt.get("openticket:limits-enabled").value) description = description + "\nMax Tickets: `"+opt.get("openticket:limits-maximum-user").value+"`" + } + if (layout == "detailed"){ + if (opt.exists("openticket:admins")) description = description + "\nAdmins: "+opt.get("openticket:admins").value.map((admin) => discord.roleMention(admin)).join(", ") + } + + return {name:utilities.emojiTitle(emoji,name),value:description} + + }else if (opt instanceof api.ODWebsiteOption){ + //website option + const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" + const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" + let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + + return {name:utilities.emojiTitle(emoji,name),value:description} + + }else if (opt instanceof api.ODRoleOption){ + //role option + const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" + const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" + let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + + if (layout == "normal" || layout == "detailed"){ + if (opt.exists("openticket:roles")) description = description + "\nRoles: "+opt.get("openticket:roles").value.map((admin) => discord.roleMention(admin)).join(", ") + } + + return {name:utilities.emojiTitle(emoji,name),value:description} + + }else{ + //auto-generated plugin option + const emoji = opt.get("openticket:button-emoji") as api.ODOptionData|null + const name = opt.get("openticket:name") as api.ODOptionData|null + const description = opt.get("openticket:description") as api.ODOptionData|null + return {name:utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`")),value:(description ? description.value : "``")} + } + }) + else if (mode == "text") return title+options.map((opt) => { + if (opt instanceof api.ODTicketOption){ + //ticket option + const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" + const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" + let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + + if (layout == "normal" || layout == "detailed"){ + if (opt.exists("openticket:cooldown-enabled") && opt.get("openticket:cooldown-enabled").value) description = description + "\nCooldown: `"+opt.get("openticket:cooldown-minutes").value+" min`" + if (opt.exists("openticket:limits-enabled") && opt.get("openticket:limits-enabled").value) description = description + "\nMax Tickets: `"+opt.get("openticket:limits-maximum-user").value+"`" + } + if (layout == "detailed"){ + if (opt.exists("openticket:admins")) description = description + "\nAdmins: "+opt.get("openticket:admins").value.map((admin) => discord.roleMention(admin)).join(", ") + } + + if (layout == "simple") return "**"+utilities.emojiTitle(emoji,name)+":** "+description + else return "**"+utilities.emojiTitle(emoji,name)+"**\n"+description + + }else if (opt instanceof api.ODWebsiteOption){ + //website option + const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" + const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" + let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + + if (layout == "simple") return "**"+utilities.emojiTitle(emoji,name)+":** "+description + else return "**"+utilities.emojiTitle(emoji,name)+"**\n"+description + + }else if (opt instanceof api.ODRoleOption){ + //role option + const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" + const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" + let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + + if (layout == "normal" || layout == "detailed"){ + if (opt.exists("openticket:roles")) description = description + "\nRoles: "+opt.get("openticket:roles").value.map((admin) => discord.roleMention(admin)).join(", ") + } + + if (layout == "simple") return "**"+utilities.emojiTitle(emoji,name)+":** "+description + else return "**"+utilities.emojiTitle(emoji,name)+"**\n"+description + + }else{ + //auto-generated plugin option + const emoji = opt.get("openticket:button-emoji") as api.ODOptionData|null + const name = opt.get("openticket:name") as api.ODOptionData|null + const description = opt.get("openticket:description") as api.ODOptionData|null + + if (layout == "simple") return "**"+utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`"))+":** "+(description ? description.value : "``") + else return "**"+utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`"))+"**\n"+(description ? description.value : "``") + } + }).join("\n\n") + else throw new api.ODSystemError("Unknown panel generation mode, choose 'text' or 'fields'") +} \ No newline at end of file diff --git a/src/data/openticket/questionLoader.ts b/src/data/openticket/questionLoader.ts new file mode 100644 index 0000000..2105d83 --- /dev/null +++ b/src/data/openticket/questionLoader.ts @@ -0,0 +1,38 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllQuestions = async () => { + const questionConfig = openticket.configs.get("openticket:questions") + if (!questionConfig) return + + questionConfig.data.forEach((question) => { + if (question.type == "short"){ + openticket.questions.add(loadShortQuestion(question)) + }else if (question.type == "paragraph"){ + openticket.questions.add(loadParagraphQuestion(question)) + } + }) +} + +export const loadShortQuestion = (option:api.ODJsonConfig_DefaultShortQuestionType) => { + return new api.ODShortQuestion(option.id,[ + new api.ODQuestionData("openticket:name",option.name), + new api.ODQuestionData("openticket:required",option.required), + new api.ODQuestionData("openticket:placeholder",option.placeholder), + + new api.ODQuestionData("openticket:length-enabled",option.length.enabled), + new api.ODQuestionData("openticket:length-min",option.length.min), + new api.ODQuestionData("openticket:length-max",option.length.max), + ]) +} + +export const loadParagraphQuestion = (option:api.ODJsonConfig_DefaultParagraphQuestionType) => { + return new api.ODParagraphQuestion(option.id,[ + new api.ODQuestionData("openticket:name",option.name), + new api.ODQuestionData("openticket:required",option.required), + new api.ODQuestionData("openticket:placeholder",option.placeholder), + + new api.ODQuestionData("openticket:length-enabled",option.length.enabled), + new api.ODQuestionData("openticket:length-min",option.length.min), + new api.ODQuestionData("openticket:length-max",option.length.max), + ]) +} \ No newline at end of file diff --git a/src/data/openticket/roleLoader.ts b/src/data/openticket/roleLoader.ts new file mode 100644 index 0000000..2baa6d5 --- /dev/null +++ b/src/data/openticket/roleLoader.ts @@ -0,0 +1,18 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllRoles = async () => { + openticket.options.getAll().forEach((opt) => { + if (opt instanceof api.ODRoleOption){ + openticket.roles.add(loadRole(opt)) + } + }) +} + +export const loadRole = (option:api.ODRoleOption) => { + return new api.ODRole(option.id,[ + new api.ODRoleData("openticket:roles",option.get("openticket:roles").value), + new api.ODRoleData("openticket:mode",option.get("openticket:mode").value), + new api.ODRoleData("openticket:remove-roles-on-add",option.get("openticket:remove-roles-on-add").value), + new api.ODRoleData("openticket:add-on-join",option.get("openticket:add-on-join").value) + ]) +} \ No newline at end of file diff --git a/src/data/openticket/ticketLoader.ts b/src/data/openticket/ticketLoader.ts new file mode 100644 index 0000000..ea89958 --- /dev/null +++ b/src/data/openticket/ticketLoader.ts @@ -0,0 +1,35 @@ +import {openticket, api, utilities} from "../../index" + +const optionDatabase = openticket.databases.get("openticket:options") + +export const loadAllTickets = async () => { + const ticketDatabase = openticket.databases.get("openticket:tickets") + if (!ticketDatabase) return + + const tickets = ticketDatabase.getCategory("openticket:ticket") + if (!tickets) return + tickets.forEach((ticket) => { + try { + openticket.tickets.add(loadTicket(ticket.value)) + }catch (err){ + process.emit("uncaughtException",new api.ODSystemError("Failed to load ticket from database! => id: "+ticket.key+"\n ===> "+err)) + } + }) +} + +export const loadTicket = (ticket:api.ODTicketJson) => { + const backupOption = optionDatabase.exists("openticket:used-option",ticket.option) ? api.ODTicketOption.fromJson(optionDatabase.get("openticket:used-option",ticket.option) as api.ODOptionJson) : null + const configOption = openticket.options.get(ticket.option) + + //check if option is of type "ticket" + if (configOption && !(configOption instanceof api.ODTicketOption)) throw new api.ODSystemError("Unable to load ticket because option is not of 'ticket' type!") + + //manage backup option + if (configOption) optionDatabase.set("openticket:used-option",configOption.id.value,configOption.toJson(openticket.versions.get("openticket:version"))) + else if (backupOption) openticket.options.add(backupOption) + else throw new api.ODSystemError("Unable to use backup option! Normal option not found in config!") + + //load ticket & option + const option = (configOption ?? backupOption) as api.ODTicketOption + return api.ODTicket.fromJson(ticket,option) +} \ No newline at end of file diff --git a/src/data/openticket/transcriptLoader.ts b/src/data/openticket/transcriptLoader.ts new file mode 100644 index 0000000..b940bc7 --- /dev/null +++ b/src/data/openticket/transcriptLoader.ts @@ -0,0 +1,456 @@ +import {openticket, api, utilities} from "../../index" +import * as discord from "discord.js" + +const collector = openticket.transcripts.collector +const messages = openticket.builders.messages +const transcriptConfig = openticket.configs.get("openticket:transcripts") +const textConfig = transcriptConfig.data.textTranscriptStyle + +export const replaceHtmlTranscriptMentions = async (text:string) => { + const mainServer = openticket.client.mainServer + if (!mainServer) throw new api.ODSystemError("Unknown mainServer! => Required for mention replacement in Html Transcripts!") + + const usertext = await utilities.asyncReplace(text,/<@([0-9]+)>/g,async (match,id) => { + const member = await openticket.client.fetchGuildMember(mainServer,id) + return (member ? "<@"+(member.user.displayName).replace(/\s/g," ")+"> " : id) //replace with html spaces => BUG: whitespace CSS isn't "pre-wrap" + }) + + const channeltext = await utilities.asyncReplace(usertext,/<#([0-9]+)>/g,async (match,id) => { + const channel = await openticket.client.fetchGuildChannel(mainServer,id) + return (channel ? "<#"+channel.name.replace(/\s/g," ")+"> " : id) //replace with html spaces => BUG: whitespace CSS isn't "pre-wrap" + }) + + const roletext = await utilities.asyncReplace(channeltext,/<@&([0-9]+)>/g,async (match,id) => { + const role = await openticket.client.fetchGuildRole(mainServer,id) + let text = role ? role.name.replace(/\s/g," ") : id + let color = role ? ((role.hexColor == "#000000") ? "regular" : role.hexColor) : "regular" //when hex color is #000000 => render as default + return "<@&"+text+"::"+color+"> " + }) + + const defaultroletext = await utilities.asyncReplace(roletext,/@(everyone|here)/g,async (match,id) => { + return "<@&"+id+"::regular> " + }) + return defaultroletext +} + +export const loadAllTranscriptCompilers = async () => { + //TEXT COMPILER + openticket.transcripts.add(new api.ODTranscriptCompiler<{contents:string}>("openticket: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!",messages:null,data:null} + const messages = await collector.convertMessagesToTranscriptData(rawMessages) + + const finalMessages: string[] = [] + finalMessages.push("=============== MESSAGES ===============") + + messages.filter((msg) => textConfig.includeBotMessages || !msg.author.tag).forEach((msg) => { + const timestamp = utilities.dateString(new Date(msg.timestamp)) + const edited = (msg.edited ? " (edited)" : "") + const authorId = (textConfig.includeIds ? " ("+msg.author.id+")" : "") + const msgId = (textConfig.includeIds ? " ("+msg.id+")" : "") + + if (textConfig.layout == "simple"){ + //SIMPLE LAYOUT + const header = "["+timestamp+" | "+msg.author.displayname+authorId+"]"+edited+msgId + const embeds = (textConfig.includeEmbeds) ? "\nEmbeds: "+msg.embeds.length : "" + const files = (textConfig.includeFiles) ? "\nFiles: "+msg.files.length : "" + const content = (msg.content) ? msg.content : (""+embeds+files) + finalMessages.push(header+"\n "+content.split("\n").join("\n ")) + + }else if (textConfig.layout == "normal"){ + //NORMAL LAYOUT + const header = "["+timestamp+" | "+msg.author.displayname+authorId+"]"+edited+msgId + const embeds = (textConfig.includeEmbeds && msg.embeds.length > 0) ? "\n"+msg.embeds.map((embed) => { + return "==== (EMBED) "+(embed.title ?? "")+" ====\n"+(embed.description ?? "") + }) : "" + const files = (textConfig.includeFiles && msg.files.length > 0) ? "\n"+msg.files.map((file) => { + return "==== (FILE) "+(file.name)+" ====\nSize: "+(file.size+" "+file.unit)+"\nUrl: "+file.url + }) : "" + const content = (msg.content) ? msg.content : "" + finalMessages.push(header+"\n "+(content+embeds+files).split("\n").join("\n ")) + + }else if (textConfig.layout == "detailed"){ + //ADVANCED LAYOUT + const header = "["+timestamp+" | "+msg.author.displayname+authorId+"]"+edited+msgId + const embeds = (textConfig.includeEmbeds && msg.embeds.length > 0) ? "\n"+msg.embeds.map((embed) => { + return "\n==== (EMBED) "+(embed.title ?? "")+" ====\n"+(embed.description ?? "")+(embed.fields.length > 0 ? "\n\n== (FIELDS) ==\n"+embed.fields.map((field) => field.name+": "+field.value).join("\n") : "") + }) : "" + const files = (textConfig.includeFiles && msg.files.length > 0) ? "\n"+msg.files.map((file) => { + return "\n==== (FILE) "+(file.name)+" ====\nSize: "+(file.size+" "+file.unit)+"\nUrl: "+file.url+"\nAlt: "+(file.alt ?? "/") + }) : "" + const reactions = (msg.reactions.filter((r) => !r.custom).length > 0) ? "\n==== (REACTIONS) ====\n"+msg.reactions.filter((r) => !r.custom).map((r) => r.amount+" "+r.emoji).join(" - ") : "" + const content = (msg.content) ? msg.content : "" + finalMessages.push(header+"\n "+(content+embeds+files+reactions).split("\n").join("\n ")) + } + }) + + const finalStats: string[] = [] + + const creationDate = ticket.get("openticket:opened-on").value + const closeDate = ticket.get("openticket:closed-on").value + const claimDate = ticket.get("openticket:claimed-on").value + const pinDate = ticket.get("openticket:pinned-on").value + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + const closer = await openticket.tickets.getTicketUser(ticket,"closer") + const claimer = await openticket.tickets.getTicketUser(ticket,"claimer") + const pinner = await openticket.tickets.getTicketUser(ticket,"pinner") + + if (textConfig.includeStats){ + finalStats.push("=============== STATS ===============") + if (textConfig.layout == "simple"){ + //SIMPLE LAYOUT + if (creationDate) finalStats.push("Created On: "+utilities.dateString(new Date(creationDate))) + if (creator) finalStats.push("Created By: "+creator.displayName) + finalStats.push("\n") + + }else if (textConfig.layout == "normal"){ + //NORMAL LAYOUT + if (creationDate) finalStats.push("Created On: "+utilities.dateString(new Date(creationDate))) + if (creator) finalStats.push("Created By: "+creator.displayName) + finalStats.push("") + if (closer) finalStats.push("Closed By: "+closer.displayName) + if (claimer) finalStats.push("Claimed By: "+claimer.displayName) + if (pinner) finalStats.push("Pinned By: "+pinner.displayName) + finalStats.push("Deleted By: "+user.displayName) + finalStats.push("\n") + + }else if (textConfig.layout == "detailed"){ + //ADVANCED LAYOUT + if (creationDate) finalStats.push("Created On: "+utilities.dateString(new Date(creationDate))) + if (creator) finalStats.push("Created By: "+creator.displayName) + finalStats.push("") + if (closeDate) finalStats.push("Closed On: "+utilities.dateString(new Date(closeDate))) + if (closer) finalStats.push("Closed By: "+closer.displayName) + finalStats.push("") + if (claimDate) finalStats.push("Claimed On: "+utilities.dateString(new Date(claimDate))) + if (claimer) finalStats.push("Claimed By: "+claimer.displayName) + finalStats.push("") + if (pinDate) finalStats.push("Pinned On: "+utilities.dateString(new Date(pinDate))) + if (pinner) finalStats.push("Pinned By: "+pinner.displayName) + finalStats.push("") + finalStats.push("Deleted On: "+utilities.dateString(new Date())) + finalStats.push("Deleted By: "+user.displayName) + finalStats.push("\n") + } + } + + const final: string[] = [] + final.push(...finalStats) + final.push(finalMessages.join("\n\n")) + + return {ticket,channel,user,success:true,errorReason:null,messages,data:{contents:final.join("\n")}} + },async (result) => { + //READY + return { + channelMessage:await messages.getSafe("openticket:transcript-text-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:text-compiler")}), + creatorDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:text-compiler")}), + participantDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("participant-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:text-compiler")}), + activeAdminDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("active-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:text-compiler")}), + everyAdminDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("every-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:text-compiler")}) + } + })) + + //HTML COMPILER + openticket.transcripts.add(new api.ODTranscriptCompiler<{url:string}>("openticket:html-compiler",async (ticket,channel,user) => { + //INIT + const req = new api.ODHTTPGetRequest("https://apis.dj-dj.be/transcripts/status.json",false) + const res = await req.run() + if (!res || res.status != 200 || !res.body){ + return {success:false,errorReason:"HTML Transcripts are currently unavailable!",pendingMessage:null} + } + 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{ + return {success:false,errorReason:"HTML Transcripts are currently unavailable due to JSON parse error!",pendingMessage:null} + } + + return {success:true,errorReason:null,pendingMessage:await messages.getSafe("openticket:transcript-html-progress").build("channel",{guild:channel.guild,channel,user,ticket,compiler:openticket.transcripts.get("openticket:html-compiler"),remaining:16000})} + },async (ticket,channel,user) => { + //COMPILE + const rawMessages = await collector.collectAllMessages(ticket) + if (!rawMessages) return {ticket,channel,user,success:false,errorReason:"Unable to collect messages!",messages:null,data:null} + const messages = await collector.convertMessagesToTranscriptData(rawMessages) + + const htmlMessages: api.ODTranscriptHtmlV2Data["messages"] = [] + for (const msg of messages){ + const components: api.ODTranscriptHtmlV2Data["messages"][0]["components"] = [] + msg.components.forEach((component) => { + if (component.components[0].type == "dropdown"){ + //row contains dropdown + components.push({ + type:"dropdown", + placeholder:component.components[0].placeholder ?? "Nothing Selected", + options:component.components[0].options.map((opt) => { + return { + id:opt.id, + label:opt.label ?? false, + description:opt.description ?? false, + icon:(opt.emoji && !opt.emoji.custom) ? opt.emoji.emoji : false + } + }), + + }) + }else if (component.components[0].type == "button"){ + //row contains buttons + components.push({ + type:"buttons", + buttons:component.components.map((button) => { + button = button as api.ODTranscriptButtonComponentData + return { + disabled:button.disabled, + type:(button.mode == "button") ? "interaction" : "url", + color:button.color, + id:button.id ?? false, + label:button.label ?? false, + icon:(button.emoji) ? button.emoji.emoji : false, + url:button.url ?? false + } + }), + + }) + } + }) + components.push({ + type:"reactions", + reactions:msg.reactions.map((reaction) => { + return { + amount:reaction.amount, + emoji:reaction.emoji, + type:(reaction.custom && reaction.animated) ? "gif" : (reaction.custom ? "image" : "svg") + + } + }) + }) + + const embeds: api.ODTranscriptHtmlV2Data["messages"][0]["embeds"] = [] + for (const embed of msg.embeds){ + embeds.push({ + title:embed.title ? await replaceHtmlTranscriptMentions(embed.title) : false, + color:embed.color, + description:embed.description ? await replaceHtmlTranscriptMentions(embed.description) : false, + image:embed.image ?? false, + thumbnail:embed.thumbnail ?? false, + url:embed.url ?? false, + authorimg:embed.authorimg ?? false, + authortext:embed.authortext ?? false, + footerimg:embed.footerimg ?? false, + footertext:embed.footertext ?? false, + fields:embed.fields + }) + } + + htmlMessages.push({ + author:{ + id:msg.author.id, + name:msg.author.displayname, + pfp:msg.author.pfp, + bot:msg.author.tag == "app", + system:msg.author.tag == "system", + verifiedBot:msg.author.tag == "verified", + color:msg.author.color + }, + edited:msg.edited, + timestamp:msg.timestamp, + important:msg.type == "important", + type:"normal", + content:msg.content ? await replaceHtmlTranscriptMentions(msg.content) : false, + embeds, + attachments:msg.files.map((file) => { + return { + type:"FILE", + fileType:file.type, + name:file.name, + size:file.size+" "+file.unit, + url:file.url + } + }), + components, + reply:{ + type:(msg.reply) ? (msg.reply.type == "interaction" ? "command" : "reply") : false, + user:(msg.reply) ? { + id:msg.reply.user.id, + name:msg.reply.user.displayname, + pfp:msg.reply.user.pfp, + bot:msg.reply.user.tag == "app", + system:msg.reply.user.tag == "system", + verifiedBot:msg.reply.user.tag == "verified", + color:msg.reply.user.color + } : undefined, + replyOptions:(msg.reply && msg.reply.type == "message") ? { + guildId:msg.reply.guild, + channelId:msg.reply.channel, + messageId:msg.reply.id, + content:(msg.reply.content ?? "")?.substring(0,80) + } : undefined, + commandOptions:(msg.reply && msg.reply.type == "interaction") ? { + interactionId:"", + interactionName:msg.reply.name + } : undefined + } + }) + } + + const htmlComponents: api.ODTranscriptHtmlV2Data["ticket"]["components"] = { + messages:messages.length, + embeds:0, + files:0, + interactions:{ + buttons:0, //unused + dropdowns:0, //unused + total:0 + }, + reactions:0, + attachments:{ + gifs:0, //unused + images:0, //unused + stickers:0, //unused + invites:0 //unused + } + } + messages.forEach((msg) => { + htmlComponents.embeds += msg.embeds.length + htmlComponents.files += msg.files.length + htmlComponents.reactions += msg.reactions.length + msg.components.forEach((row) => { + htmlComponents.interactions.total += row.components.length + }) + }) + + + const dsb = transcriptConfig.data.htmlTranscriptStyle.background + const dsh = transcriptConfig.data.htmlTranscriptStyle.header + const dss = transcriptConfig.data.htmlTranscriptStyle.stats + const dsf = transcriptConfig.data.htmlTranscriptStyle.favicon + + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + const claimer = await openticket.tickets.getTicketUser(ticket,"claimer") + const closer = await openticket.tickets.getTicketUser(ticket,"closer") + + const htmlFinal: api.ODTranscriptHtmlV2Data = { + version:"2", + otversion:openticket.versions.get("openticket:version").toString(true), + bot:{ + name:openticket.client.client.user.displayName, + id:openticket.client.client.user.id, + pfp:openticket.client.client.user.displayAvatarURL({extension:"png"}), + }, + language:openticket.languages.getLanguageMetadata()?.language ?? "english", + style:{ + background:{ + backgroundData:(dsb.backgroundImage == "") ? dsb.backgroundColor : dsb.backgroundImage, + backgroundModus:(dsb.backgroundImage == "") ? "color" : "image", + enableCustomBackground:dsb.enableCustomBackground, + }, + header:{ + backgroundColor:dsh.backgroundColor || "#202225", + decoColor:dsh.decoColor || "#f8ba00", + textColor:dsh.textColor || "#ffffff", + enableCustomHeader:dsh.enableCustomHeader + }, + stats:{ + backgroundColor:dss.backgroundColor || "#202225", + keyTextColor:dss.keyTextColor || "#737373", + valueTextColor:dss.valueTextColor || "#ffffff", + hideBackgroundColor:dss.hideBackgroundColor || "#40444a", + hideTextColor:dss.hideTextColor || "#ffffff", + enableCustomStats:dss.enableCustomStats + }, + favicon:{ + imageUrl:dsf.imageUrl, + enableCustomFavicon:dsf.enableCustomFavicon + } + }, + ticket:{ + name:channel.name, + id:channel.id, + + guildname:channel.guild.name, + guildid:channel.guild.id, + guildinvite:"", + + creatorname:(creator ? creator.displayName : ""), + creatorid:(creator ? creator.id : ""), + creatorpfp:(creator ? creator.displayAvatarURL() : "https://transcripts.dj-dj.be/favicon.png"), + + //closer is ticket deleter (small bug) + closedbyname:user.displayName, + closedbyid:user.id, + closedbypfp:user.displayAvatarURL(), + + //claiming is currently unused + claimedname:(claimer ? claimer.displayName : ""), + claimedid:(claimer ? claimer.id : ""), + claimedpfp:(claimer ? claimer.displayAvatarURL() : "https://transcripts.dj-dj.be/favicon.png"), + + closedtime:new Date().getTime(), + openedtime:ticket.get("openticket:opened-on").value ?? new Date().getTime(), + + //role colors are currently unused + roleColors:[], + components:htmlComponents + }, + messages:htmlMessages, + + //premium is implemented, but currently unused + premium:{ + enabled:false, + premiumToken:"", + + customCredits:{ + enable:false, + replaceText:"Powered By Open Ticket!", + replaceURL:"https://openticket.dj-dj.be", + enableReportBug:true + }, + customHeaderUrl:{ + enabled:false, + url:"https://openticket.dj-dj.be", + text:"Hello!" + }, + customTranscriptUrl:{ + enabled:false, + name:"test-server" + }, + customFavicon:{ + enabled:dsf.enableCustomFavicon, + image:(dsf.imageUrl) ? dsf.imageUrl : "https://transcripts.dj-dj.be/favicon.png" + }, + additionalFlags:[] + } + } + + const req = new api.ODHTTPPostRequest("https://apis.dj-dj.be/transcripts/upload?auth=openticketTRANSCRIPT1234&version=2",true,{ + body:JSON.stringify(htmlFinal) + }) + const res = await req.run() + if (!res || res.status != 200 || !res.body){ + if (res.status == 429) return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts due to Ratelimt! Try again in a few minutes!",messages,data:null} + else return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts!",messages,data:null} + } + try{ + var data: api.ODTranscriptHtmlV2Response = JSON.parse(res.body) + if (!data || data["status"] != "success") return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts! (Status: Error)",messages,data:null} + }catch{ + return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts due to JSON parse error!",messages,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}} + },async (result) => { + //READY + await utilities.timer(16000) //wait until transcript is ready + return { + channelMessage:await messages.getSafe("openticket:transcript-html-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:html-compiler")}), + creatorDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:html-compiler")}), + participantDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("participant-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:html-compiler")}), + activeAdminDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("active-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:html-compiler")}), + everyAdminDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("every-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:html-compiler")}) + } + })) +} + +export const loadTranscriptHistory = async () => { + //UNIMPLEMENTED (made for html transcripts v3 update) +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..6847de1 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,742 @@ +/* + ██████╗ ██████╗ ███████╗███╗ ██╗ ████████╗██╗ ██████╗██╗ ██╗███████╗████████╗ + ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝ + ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ ██║██║ █████╔╝ █████╗ ██║ + ██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██╔═██╗ ██╔══╝ ██║ + ╚██████╔╝██║ ███████╗██║ ╚████║ ██║ ██║╚██████╗██║ ██╗███████╗ ██║ + ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ + + > Hey! We are looking for you! + > Do you speak a language that isn't yet in our /languages directory? + > Or do you speak one that isn't up-to-date anymore? + > Open Ticket needs translators for lots of different languages! + > Feel free to join our translator team and help us improve Open Ticket! + + SUGGESTIONS: + ===================== + Did you know that almost 70% of all Open Ticket features were requested by the community? + Feel free to suggest new ideas in our discord server or via github issues! + They are always welcome! + + INFORMATION: + ============ + Open Ticket v4.0.0 - © DJdj Development + + discord: https://discord.dj-dj.be + website: https://openticket.dj-dj.be + github: https://otgithub.dj-dj.be + documentation: https://otdocs.dj-dj.be + + Config files: + ./config/....json + + Send ./otdebug.txt to us when there is an error! +*/ + +//initialize API & check npm libraries +import { api, openticket, utilities } from "./core/startup/init" +export { api, openticket, utilities } from "./core/startup/init" +import ansis from "ansis" + +/**The main sequence of Open Ticket. Runs `async` */ +const main = async () => { + //load all events + (await import("./data/framework/eventLoader.ts")).loadAllEvents() + + //error handling system + process.on("uncaughtException",async (error,origin) => { + try{ + await openticket.events.get("onErrorHandling").emit([error,origin]) + if (openticket.defaults.getDefault("errorHandling")){ + //custom error messages for known errors + if (error.message == "Used disallowed intents"){ + //invalid intents + openticket.log("Open Ticket doesn't work without Privileged Gateway Intents enabled!","error") + openticket.log("Enable them in the discord developer portal!","info") + console.log("\n") + process.exit(1) + }else if (error.message == "An invalid token was provided."){ + //invalid token + openticket.log("An invalid discord auth token was provided!","error") + openticket.log("Check the config if you have copied the token correctly!","info") + console.log("\n") + process.exit(1) + }else{ + //unknown error + const errmsg = new api.ODError(error,origin) + openticket.log(errmsg) + if (openticket.defaults.getDefault("crashOnError")) process.exit(1) + await openticket.events.get("afterErrorHandling").emit([error,origin,errmsg]) + } + } + + }catch(err){ + console.log("[ERROR HANDLER ERROR]:",err) + } + }) + + //handle data migration + await (await import("./core/startup/manageMigration.ts")).loadVersionMigrationSystem() + + //load plugins + if (openticket.defaults.getDefault("pluginLoading")){ + await (await import("./core/startup/pluginLauncher.ts")).loadAllPlugins() + } + await openticket.events.get("afterPluginsLoaded").emit([openticket.plugins]) + + //load plugin classes + openticket.log("Loading plugin classes...","system") + if (openticket.defaults.getDefault("pluginClassLoading")){ + + } + await openticket.events.get("onPluginClassLoad").emit([openticket.plugins.classes,openticket.plugins]) + await openticket.events.get("afterPluginClassesLoaded").emit([openticket.plugins.classes,openticket.plugins]) + + //load plugin events + openticket.log("Loading plugin events...","system") + if (openticket.defaults.getDefault("pluginEventLoading")){ + + } + await openticket.events.get("onPluginEventLoad").emit([openticket.plugins.events,openticket.plugins]) + await openticket.events.get("afterPluginEventsLoaded").emit([openticket.plugins.events,openticket.plugins]) + + //load flags + openticket.log("Loading flags...","system") + if (openticket.defaults.getDefault("flagLoading")){ + await (await import("./data/framework/flagLoader.ts")).loadAllFlags() + } + await openticket.events.get("onFlagLoad").emit([openticket.flags]) + await openticket.events.get("afterFlagsLoaded").emit([openticket.flags]) + + //initiate flags + await openticket.events.get("onFlagInit").emit([openticket.flags]) + if (openticket.defaults.getDefault("flagInitiating")){ + openticket.flags.init() + openticket.debugfile.writeText("\n[ENABLED FLAGS]:\n"+openticket.flags.getFiltered((flag) => (flag.value == true)).map((flag) => flag.id.value).join("\n")+"\n") + await openticket.events.get("afterFlagsInitiated").emit([openticket.flags]) + } + + //load debug + if (openticket.defaults.getDefault("debugLoading")){ + const debugFlag = openticket.flags.get("openticket:debug") + openticket.debug.visible = (debugFlag) ? debugFlag.value : false + } + + //load config + openticket.log("Loading configs...","system") + if (openticket.defaults.getDefault("configLoading")){ + await (await import("./data/framework/configLoader.ts")).loadAllConfigs() + } + await openticket.events.get("onConfigLoad").emit([openticket.configs]) + await openticket.events.get("afterConfigsLoaded").emit([openticket.configs]) + + //UTILITY CONFIG + const generalConfig = openticket.configs.get("openticket:general") + + //load database + openticket.log("Loading databases...","system") + if (openticket.defaults.getDefault("databaseLoading")){ + await (await import("./data/framework/databaseLoader.ts")).loadAllDatabases() + } + await openticket.events.get("onDatabaseLoad").emit([openticket.databases]) + await openticket.events.get("afterDatabasesLoaded").emit([openticket.databases]) + + //load sessions + openticket.log("Loading sessions...","system") + if (openticket.defaults.getDefault("sessionLoading")){ + + } + await openticket.events.get("onSessionLoad").emit([openticket.sessions]) + await openticket.events.get("afterSessionsLoaded").emit([openticket.sessions]) + + //load language + openticket.log("Loading languages...","system") + if (openticket.defaults.getDefault("languageLoading")){ + await (await import("./data/framework/languageLoader.ts")).loadAllLanguages() + } + await openticket.events.get("onLanguageLoad").emit([openticket.languages]) + await openticket.events.get("afterLanguagesLoaded").emit([openticket.languages]) + + //select language + await openticket.events.get("onLanguageSelect").emit([openticket.languages]) + if (openticket.defaults.getDefault("languageSelection")){ + //set current language + const languageId = (generalConfig && generalConfig.data.language) ? generalConfig.data.language : "english" + if (languageId.includes(":")){ + openticket.languages.setCurrentLanguage(languageId) + }else{ + openticket.languages.setCurrentLanguage("openticket:"+languageId) + } + + //set backup language + const backupLanguageId = openticket.defaults.getDefault("backupLanguage") + if (openticket.languages.exists(backupLanguageId)){ + openticket.languages.setBackupLanguage(backupLanguageId) + + }else throw new api.ODSystemError("Unknown backup language '"+backupLanguageId+"'!") + + await openticket.events.get("afterLanguagesSelected").emit([openticket.languages.get(languageId),openticket.languages.get(backupLanguageId),openticket.languages]) + } + + //load config checker + openticket.log("Loading config checker...","system") + if (openticket.defaults.getDefault("checkerLoading")){ + await (await import("./data/framework/checkerLoader.ts")).loadAllConfigCheckers() + } + await openticket.events.get("onCheckerLoad").emit([openticket.checkers]) + await openticket.events.get("afterCheckersLoaded").emit([openticket.checkers]) + + //load config checker functions + if (openticket.defaults.getDefault("checkerFunctionLoading")){ + await (await import("./data/framework/checkerLoader.ts")).loadAllConfigCheckerFunctions() + } + await openticket.events.get("onCheckerFunctionLoad").emit([openticket.checkers.functions,openticket.checkers]) + await openticket.events.get("afterCheckerFunctionsLoaded").emit([openticket.checkers.functions,openticket.checkers]) + + //execute config checker + await openticket.events.get("onCheckerExecute").emit([openticket.checkers]) + if (openticket.defaults.getDefault("checkerExecution")){ + const result = openticket.checkers.checkAll(true) + await openticket.events.get("afterCheckersExecuted").emit([result,openticket.checkers]) + } + + //load config checker translations + if (openticket.defaults.getDefault("checkerTranslationLoading")){ + await (await import("./data/framework/checkerLoader.ts")).loadAllConfigCheckerTranslations() + } + await openticket.events.get("onCheckerTranslationLoad").emit([openticket.checkers.translation,((generalConfig && generalConfig.data.system && generalConfig.data.system.useTranslatedConfigChecker) ? generalConfig.data.system.useTranslatedConfigChecker : false),openticket.checkers]) + await openticket.events.get("afterCheckerTranslationsLoaded").emit([openticket.checkers.translation,openticket.checkers]) + + //render config checker + const advancedCheckerFlag = openticket.flags.get("openticket:checker") + const disableCheckerFlag = openticket.flags.get("openticket:no-checker") + + await openticket.events.get("onCheckerRender").emit([openticket.checkers.renderer,openticket.checkers]) + if (openticket.defaults.getDefault("checkerRendering") && !(disableCheckerFlag ? disableCheckerFlag.value : false)){ + //check if there is a result (otherwise throw minor error) + const result = openticket.checkers.lastResult + if (!result) return openticket.log("Failed to render Config Checker! (couldn't fetch result)","error") + + //get components & check if full mode enabled + const components = openticket.checkers.renderer.getComponents(!(advancedCheckerFlag ? advancedCheckerFlag.value : false),openticket.defaults.getDefault("checkerRenderEmpty"),openticket.checkers.translation,result) + + //render + openticket.debugfile.writeText("\n[CONFIG CHECKER RESULT]:\n"+ansis.strip(components.join("\n"))+"\n") + openticket.checkers.renderer.render(components) + await openticket.events.get("afterCheckersRendered").emit([openticket.checkers.renderer,openticket.checkers]) + } + + //quit config checker (when required) + if (openticket.checkers.lastResult && !openticket.checkers.lastResult.valid && !(disableCheckerFlag ? disableCheckerFlag.value : false)){ + await openticket.events.get("onCheckerQuit").emit([openticket.checkers]) + if (openticket.defaults.getDefault("checkerQuit")){ + process.exit(0) + //there is no afterCheckerQuitted event :) + } + } + + //client configuration + openticket.log("Loading client...","system") + if (openticket.defaults.getDefault("clientLoading")){ + //add intents (for basic permissions) + openticket.client.intents.push( + "Guilds", + "GuildMessages", + "DirectMessages", + "GuildEmojisAndStickers", + "GuildMembers", + "MessageContent", + "GuildWebhooks", + "GuildInvites" + ) + + //add privileged intents (required for transcripts) + openticket.client.privileges.push("MessageContent","GuildMembers") + + //add partials (required for DM messages) + openticket.client.partials.push("Channel","Message") + + //add permissions (not required when Administrator) + openticket.client.permissions.push( + "AddReactions", + "AttachFiles", + "CreatePrivateThreads", + "CreatePublicThreads", + "EmbedLinks", + "ManageChannels", + "ManageGuild", + "ManageMessages", + "ChangeNickname", + "ManageRoles", + "ManageThreads", + "ManageWebhooks", + "MentionEveryone", + "ReadMessageHistory", + "SendMessages", + "SendMessagesInThreads", + "UseApplicationCommands", + "UseExternalEmojis", + "ViewAuditLog", + "ViewChannel" + ) + + //get token from config or env + const configToken = openticket.configs.get("openticket:general").data.token ? openticket.configs.get("openticket:general").data.token : "" + const envToken = openticket.env.getVariable("TOKEN") ? openticket.env.getVariable("TOKEN") : "" + const token = openticket.configs.get("openticket:general").data.tokenFromENV ? envToken : configToken + openticket.client.token = token + } + await openticket.events.get("onClientLoad").emit([openticket.client]) + await openticket.events.get("afterClientLoaded").emit([openticket.client]) + + //client ready + openticket.client.readyListener = async () => { + openticket.log("Loading client setup...","system") + await openticket.events.get("onClientReady").emit([openticket.client]) + if (openticket.defaults.getDefault("clientReady")){ + const client = openticket.client + + //check if all servers are valid + const botServers = client.getGuilds() + const generalConfig = openticket.configs.get("openticket:general") + const serverId = generalConfig.data.serverId ? generalConfig.data.serverId : "" + if (!serverId) throw new api.ODSystemError("Server Id Missing!") + + const mainServer = botServers.find((g) => g.id == serverId) + client.mainServer = mainServer ?? null + //throw if bot isn't member of main server + if (!mainServer || !client.checkBotInGuild(mainServer)){ + console.log("\n") + openticket.log("The bot isn't a member of the server provided in the config!","error") + openticket.log("Please invite your bot to the server!","info") + console.log("\n") + process.exit(0) + } + //throw if bot doesn't have permissions in main server + if (!client.checkGuildPerms(mainServer)){ + console.log("\n") + openticket.log("The bot doesn't have the correct permissions in the server provided in the config!","error") + openticket.log("Please give the bot \"Administrator\" permissions or visit the documentation!","info") + console.log("\n") + process.exit(0) + } + if (openticket.defaults.getDefault("clientMultiGuildWarning")){ + //warn if bot is in multiple servers + if (botServers.length > 1){ + openticket.log("This bot is part of multiple servers, but Open Ticket doesn't have support for it!","warning") + openticket.log("It may result in the bot crashing & glitching when used in these servers!","info") + } + botServers.forEach((server) => { + //warn if bot doesn't have permissions in multiple servers + if (!client.checkGuildPerms(server)) openticket.log(`The bot doesn't have the correct permissions in the server "${server.name}"!`,"warning") + }) + } + + //load client activity + openticket.log("Loading client activity...","system") + if (openticket.defaults.getDefault("clientActivityLoading")){ + //load config status + if (generalConfig.data.status && generalConfig.data.status.enabled) openticket.client.activity.setStatus(generalConfig.data.status.type,generalConfig.data.status.text,generalConfig.data.status.status) + } + await openticket.events.get("onClientActivityLoad").emit([openticket.client.activity,openticket.client]) + await openticket.events.get("afterClientActivityLoaded").emit([openticket.client.activity,openticket.client]) + + //initiate client activity + await openticket.events.get("onClientActivityInit").emit([openticket.client.activity,openticket.client]) + if (openticket.defaults.getDefault("clientActivityInitiating")){ + openticket.client.activity.initStatus() + await openticket.events.get("afterClientActivityInitiated").emit([openticket.client.activity,openticket.client]) + } + + //load slash commands + openticket.log("Loading slash commands...","system") + if (openticket.defaults.getDefault("slashCommandLoading")){ + await (await import("./data/framework/commandLoader.ts")).loadAllSlashCommands() + } + await openticket.events.get("onSlashCommandLoad").emit([openticket.client.slashCommands,openticket.client]) + await openticket.events.get("afterSlashCommandsLoaded").emit([openticket.client.slashCommands,openticket.client]) + + //register slash commands (create, update & remove) + if (openticket.defaults.getDefault("forceSlashCommandRegistration")) openticket.log("Forcing all slash commands to be re-registered...","system") + openticket.log("Registering slash commands... (this can take up to 2 minutes)","system") + await openticket.events.get("onSlashCommandRegister").emit([openticket.client.slashCommands,openticket.client]) + if (openticket.defaults.getDefault("slashCommandRegistering")){ + //GLOBAL + await openticket.client.slashCommands.removeUnusedCommands() //remove all commands that aren't used + await openticket.client.slashCommands.createNewCommands() //create all new commands that don't exist yet + await openticket.client.slashCommands.updateExistingCommands(undefined,openticket.defaults.getDefault("forceSlashCommandRegistration")) //update all commands that need to be re-registered + + //DEFAULT SERVER + await openticket.client.slashCommands.removeUnusedCommands(serverId) //remove all commands that aren't used + await openticket.client.slashCommands.createNewCommands(serverId) //create all new commands that don't exist yet + await openticket.client.slashCommands.updateExistingCommands(serverId) //update all commands that need to be re-registered + + await openticket.events.get("afterSlashCommandsRegistered").emit([openticket.client.slashCommands,openticket.client]) + } + + //load text commands + openticket.log("Loading text commands...","system") + if (openticket.defaults.getDefault("textCommandLoading")){ + await (await import("./data/framework/commandLoader.ts")).loadAllTextCommands() + } + await openticket.events.get("onTextCommandLoad").emit([openticket.client.textCommands,openticket.client]) + await openticket.events.get("afterTextCommandsLoaded").emit([openticket.client.textCommands,openticket.client]) + + //client ready + await openticket.events.get("afterClientReady").emit([openticket.client]) + } + } + + //client init (login) + openticket.log("Logging in...","system") + await openticket.events.get("onClientInit").emit([openticket.client]) + if (openticket.defaults.getDefault("clientInitiating")){ + //init client + openticket.client.initClient() + await openticket.events.get("afterClientInitiated").emit([openticket.client]) + + //client login + await openticket.client.login() + openticket.log("discord.js client ready!","info") + } + + //load questions + openticket.log("Loading questions...","system") + if (openticket.defaults.getDefault("questionLoading")){ + await (await import("./data/openticket/questionLoader.ts")).loadAllQuestions() + } + await openticket.events.get("onQuestionLoad").emit([openticket.questions]) + await openticket.events.get("afterQuestionsLoaded").emit([openticket.questions]) + + //load options + openticket.log("Loading options...","system") + if (openticket.defaults.getDefault("optionLoading")){ + await (await import("./data/openticket/optionLoader.ts")).loadAllOptions() + } + await openticket.events.get("onOptionLoad").emit([openticket.options]) + await openticket.events.get("afterOptionsLoaded").emit([openticket.options]) + + //load panels + openticket.log("Loading panels...","system") + if (openticket.defaults.getDefault("panelLoading")){ + await (await import("./data/openticket/panelLoader.ts")).loadAllPanels() + } + await openticket.events.get("onPanelLoad").emit([openticket.panels]) + await openticket.events.get("afterPanelsLoaded").emit([openticket.panels]) + + //load tickets + openticket.log("Loading tickets...","system") + if (openticket.defaults.getDefault("ticketLoading")){ + openticket.tickets.useGuild(openticket.client.mainServer) + await (await import("./data/openticket/ticketLoader.ts")).loadAllTickets() + } + await openticket.events.get("onTicketLoad").emit([openticket.tickets]) + await openticket.events.get("afterTicketsLoaded").emit([openticket.tickets]) + + //load roles + openticket.log("Loading roles...","system") + if (openticket.defaults.getDefault("roleLoading")){ + await (await import("./data/openticket/roleLoader.ts")).loadAllRoles() + } + await openticket.events.get("onRoleLoad").emit([openticket.roles]) + await openticket.events.get("afterRolesLoaded").emit([openticket.roles]) + + //load blacklist + openticket.log("Loading blacklist...","system") + if (openticket.defaults.getDefault("blacklistLoading")){ + await (await import("./data/openticket/blacklistLoader.ts")).loadAllBlacklistedUsers() + } + await openticket.events.get("onBlacklistLoad").emit([openticket.blacklist]) + await openticket.events.get("afterBlacklistLoaded").emit([openticket.blacklist]) + + //load transcript compilers + openticket.log("Loading transcripts...","system") + if (openticket.defaults.getDefault("transcriptCompilerLoading")){ + await (await import("./data/openticket/transcriptLoader.ts")).loadAllTranscriptCompilers() + } + await openticket.events.get("onTranscriptCompilerLoad").emit([openticket.transcripts]) + await openticket.events.get("afterTranscriptCompilersLoaded").emit([openticket.transcripts]) + + //load transcript history + if (openticket.defaults.getDefault("transcriptHistoryLoading")){ + await (await import("./data/openticket/transcriptLoader.ts")).loadTranscriptHistory() + } + await openticket.events.get("onTranscriptHistoryLoad").emit([openticket.transcripts]) + await openticket.events.get("afterTranscriptHistoryLoaded").emit([openticket.transcripts]) + + //load button builders + openticket.log("Loading buttons...","system") + if (openticket.defaults.getDefault("buttonBuildersLoading")){ + await (await import("./builders/buttons.ts")).registerAllButtons() + } + await openticket.events.get("onButtonBuilderLoad").emit([openticket.builders.buttons,openticket.builders,openticket.actions]) + await openticket.events.get("afterButtonBuildersLoaded").emit([openticket.builders.buttons,openticket.builders,openticket.actions]) + + //load dropdown builders + openticket.log("Loading dropdowns...","system") + if (openticket.defaults.getDefault("dropdownBuildersLoading")){ + await (await import("./builders/dropdowns.ts")).registerAllDropdowns() + } + await openticket.events.get("onDropdownBuilderLoad").emit([openticket.builders.dropdowns,openticket.builders,openticket.actions]) + await openticket.events.get("afterDropdownBuildersLoaded").emit([openticket.builders.dropdowns,openticket.builders,openticket.actions]) + + //load file builders + openticket.log("Loading files...","system") + if (openticket.defaults.getDefault("fileBuildersLoading")){ + await (await import("./builders/files.ts")).registerAllFiles() + } + await openticket.events.get("onFileBuilderLoad").emit([openticket.builders.files,openticket.builders,openticket.actions]) + await openticket.events.get("afterFileBuildersLoaded").emit([openticket.builders.files,openticket.builders,openticket.actions]) + + //load embed builders + openticket.log("Loading embeds...","system") + if (openticket.defaults.getDefault("embedBuildersLoading")){ + await (await import("./builders/embeds.ts")).registerAllEmbeds() + } + await openticket.events.get("onEmbedBuilderLoad").emit([openticket.builders.embeds,openticket.builders,openticket.actions]) + await openticket.events.get("afterEmbedBuildersLoaded").emit([openticket.builders.embeds,openticket.builders,openticket.actions]) + + //load message builders + openticket.log("Loading messages...","system") + if (openticket.defaults.getDefault("messageBuildersLoading")){ + await (await import("./builders/messages.ts")).registerAllMessages() + } + await openticket.events.get("onMessageBuilderLoad").emit([openticket.builders.messages,openticket.builders,openticket.actions]) + await openticket.events.get("afterMessageBuildersLoaded").emit([openticket.builders.messages,openticket.builders,openticket.actions]) + + //load modal builders + openticket.log("Loading modals...","system") + if (openticket.defaults.getDefault("modalBuildersLoading")){ + await (await import("./builders/modals.ts")).registerAllModals() + } + await openticket.events.get("onModalBuilderLoad").emit([openticket.builders.modals,openticket.builders,openticket.actions]) + await openticket.events.get("afterModalBuildersLoaded").emit([openticket.builders.modals,openticket.builders,openticket.actions]) + + //load command responders + openticket.log("Loading command responders...","system") + if (openticket.defaults.getDefault("commandRespondersLoading")){ + await (await import("./commands/help.ts")).registerCommandResponders() + await (await import("./commands/stats.ts")).registerCommandResponders() + await (await import("./commands/panel.ts")).registerCommandResponders() + await (await import("./commands/ticket.ts")).registerCommandResponders() + await (await import("./commands/blacklist.ts")).registerCommandResponders() + await (await import("./commands/close.ts")).registerCommandResponders() + await (await import("./commands/reopen.ts")).registerCommandResponders() + await (await import("./commands/delete.ts")).registerCommandResponders() + await (await import("./commands/claim.ts")).registerCommandResponders() + await (await import("./commands/unclaim.ts")).registerCommandResponders() + await (await import("./commands/pin.ts")).registerCommandResponders() + await (await import("./commands/unpin.ts")).registerCommandResponders() + await (await import("./commands/rename.ts")).registerCommandResponders() + await (await import("./commands/move.ts")).registerCommandResponders() + await (await import("./commands/add.ts")).registerCommandResponders() + await (await import("./commands/remove.ts")).registerCommandResponders() + await (await import("./commands/clear.ts")).registerCommandResponders() + await (await import("./commands/autoclose.ts")).registerCommandResponders() + await (await import("./commands/autodelete.ts")).registerCommandResponders() + } + await openticket.events.get("onCommandResponderLoad").emit([openticket.responders.commands,openticket.responders,openticket.actions]) + await openticket.events.get("afterCommandRespondersLoaded").emit([openticket.responders.commands,openticket.responders,openticket.actions]) + + //load button responders + openticket.log("Loading button responders...","system") + if (openticket.defaults.getDefault("buttonRespondersLoading")){ + await (await import("./actions/handleVerifyBar.ts")).registerButtonResponders() + await (await import("./actions/handleTranscriptErrors.ts")).registerButtonResponders() + await (await import("./commands/help.ts")).registerButtonResponders() + await (await import("./commands/ticket.ts")).registerButtonResponders() + await (await import("./commands/close.ts")).registerButtonResponders() + await (await import("./commands/reopen.ts")).registerButtonResponders() + await (await import("./commands/delete.ts")).registerButtonResponders() + await (await import("./commands/claim.ts")).registerButtonResponders() + await (await import("./commands/unclaim.ts")).registerButtonResponders() + await (await import("./commands/pin.ts")).registerButtonResponders() + await (await import("./commands/unpin.ts")).registerButtonResponders() + await (await import("./commands/role.ts")).registerButtonResponders() + await (await import("./commands/clear.ts")).registerButtonResponders() + } + await openticket.events.get("onButtonResponderLoad").emit([openticket.responders.buttons,openticket.responders,openticket.actions]) + await openticket.events.get("afterButtonRespondersLoaded").emit([openticket.responders.buttons,openticket.responders,openticket.actions]) + + //load dropdown responders + openticket.log("Loading dropdown responders...","system") + if (openticket.defaults.getDefault("dropdownRespondersLoading")){ + await (await import("./commands/ticket.ts")).registerDropdownResponders() + } + await openticket.events.get("onDropdownResponderLoad").emit([openticket.responders.dropdowns,openticket.responders,openticket.actions]) + await openticket.events.get("afterDropdownRespondersLoaded").emit([openticket.responders.dropdowns,openticket.responders,openticket.actions]) + + //load modal responders + openticket.log("Loading modal responders...","system") + if (openticket.defaults.getDefault("modalRespondersLoading")){ + await (await import("./commands/ticket.ts")).registerModalResponders() + await (await import("./commands/close.ts")).registerModalResponders() + await (await import("./commands/reopen.ts")).registerModalResponders() + await (await import("./commands/delete.ts")).registerModalResponders() + await (await import("./commands/claim.ts")).registerModalResponders() + await (await import("./commands/unclaim.ts")).registerModalResponders() + await (await import("./commands/pin.ts")).registerModalResponders() + await (await import("./commands/unpin.ts")).registerModalResponders() + } + await openticket.events.get("onModalResponderLoad").emit([openticket.responders.modals,openticket.responders,openticket.actions]) + await openticket.events.get("afterModalRespondersLoaded").emit([openticket.responders.modals,openticket.responders,openticket.actions]) + + //load actions + openticket.log("Loading actions...","system") + if (openticket.defaults.getDefault("actionsLoading")){ + await (await import("./actions/createTicketPermissions.ts")).registerActions() + await (await import("./actions/createTranscript.ts")).registerActions() + await (await import("./actions/createTicket.ts")).registerActions() + await (await import("./actions/closeTicket.ts")).registerActions() + await (await import("./actions/deleteTicket.ts")).registerActions() + await (await import("./actions/reopenTicket.ts")).registerActions() + await (await import("./actions/claimTicket.ts")).registerActions() + await (await import("./actions/unclaimTicket.ts")).registerActions() + await (await import("./actions/pinTicket.ts")).registerActions() + await (await import("./actions/unpinTicket.ts")).registerActions() + await (await import("./actions/renameTicket.ts")).registerActions() + await (await import("./actions/moveTicket.ts")).registerActions() + await (await import("./actions/addTicketUser.ts")).registerActions() + await (await import("./actions/removeTicketUser.ts")).registerActions() + await (await import("./actions/reactionRole.ts")).registerActions() + await (await import("./actions/clearTickets.ts")).registerActions() + } + await openticket.events.get("onActionLoad").emit([openticket.actions]) + await openticket.events.get("afterActionsLoaded").emit([openticket.actions]) + + //load verifybars + openticket.log("Loading verifybars...","system") + if (openticket.defaults.getDefault("verifyBarsLoading")){ + await (await import("./actions/closeTicket.ts")).registerVerifyBars() + await (await import("./actions/deleteTicket.ts")).registerVerifyBars() + await (await import("./actions/reopenTicket.ts")).registerVerifyBars() + await (await import("./actions/claimTicket.ts")).registerVerifyBars() + await (await import("./actions/unclaimTicket.ts")).registerVerifyBars() + await (await import("./actions/pinTicket.ts")).registerVerifyBars() + await (await import("./actions/unpinTicket.ts")).registerVerifyBars() + } + await openticket.events.get("onVerifyBarLoad").emit([openticket.verifybars]) + await openticket.events.get("afterVerifyBarsLoaded").emit([openticket.verifybars]) + + //load permissions + openticket.log("Loading permissions...","system") + if (openticket.defaults.getDefault("permissionsLoading")){ + await (await import("./data/framework/permissionLoader.ts")).loadAllPermissions() + } + await openticket.events.get("onPermissionLoad").emit([openticket.permissions]) + await openticket.events.get("afterPermissionsLoaded").emit([openticket.permissions]) + + //load posts + openticket.log("Loading posts...","system") + if (openticket.defaults.getDefault("postsLoading")){ + await (await import("./data/framework/postLoader.ts")).loadAllPosts() + } + await openticket.events.get("onPostLoad").emit([openticket.posts]) + await openticket.events.get("afterPostsLoaded").emit([openticket.posts]) + + //init posts + await openticket.events.get("onPostInit").emit([openticket.posts]) + if (openticket.defaults.getDefault("postsInitiating")){ + if (openticket.client.mainServer) openticket.posts.init(openticket.client.mainServer) + await openticket.events.get("afterPostsInitiated").emit([openticket.posts]) + } + + //load cooldowns + openticket.log("Loading cooldowns...","system") + if (openticket.defaults.getDefault("cooldownsLoading")){ + await (await import("./data/framework/cooldownLoader.ts")).loadAllCooldowns() + } + await openticket.events.get("onCooldownLoad").emit([openticket.cooldowns]) + await openticket.events.get("afterCooldownsLoaded").emit([openticket.cooldowns]) + + //init cooldowns + await openticket.events.get("onCooldownInit").emit([openticket.cooldowns]) + if (openticket.defaults.getDefault("cooldownsInitiating")){ + await openticket.cooldowns.init() + await openticket.events.get("afterCooldownsInitiated").emit([openticket.cooldowns]) + } + + //load help menu categories + openticket.log("Loading help menu...","system") + if (openticket.defaults.getDefault("helpMenuCategoryLoading")){ + await (await import("./data/framework/helpMenuLoader.ts")).loadAllHelpMenuCategories() + } + await openticket.events.get("onHelpMenuCategoryLoad").emit([openticket.helpmenu]) + await openticket.events.get("afterHelpMenuCategoriesLoaded").emit([openticket.helpmenu]) + + //load help menu components + if (openticket.defaults.getDefault("helpMenuComponentLoading")){ + await (await import("./data/framework/helpMenuLoader.ts")).loadAllHelpMenuComponents() + } + await openticket.events.get("onHelpMenuComponentLoad").emit([openticket.helpmenu]) + await openticket.events.get("afterHelpMenuComponentsLoaded").emit([openticket.helpmenu]) + + //load stat scopes + openticket.log("Loading stats...","system") + if (openticket.defaults.getDefault("statScopesLoading")){ + openticket.stats.useDatabase(openticket.databases.get("openticket:stats")) + await (await import("./data/framework/statLoader.ts")).loadAllStatScopes() + } + await openticket.events.get("onStatScopeLoad").emit([openticket.stats]) + await openticket.events.get("afterStatScopesLoaded").emit([openticket.stats]) + + //load stats + if (openticket.defaults.getDefault("statLoading")){ + await (await import("./data/framework/statLoader.ts")).loadAllStats() + } + await openticket.events.get("onStatLoad").emit([openticket.stats]) + await openticket.events.get("afterStatsLoaded").emit([openticket.stats]) + + //init stats + await openticket.events.get("onStatInit").emit([openticket.stats]) + if (openticket.defaults.getDefault("statInitiating")){ + await openticket.stats.init() + await openticket.events.get("afterStatsInitiated").emit([openticket.stats]) + } + + //load code + openticket.log("Loading code...","system") + if (openticket.defaults.getDefault("codeLoading")){ + await (await import("./data/framework/codeLoader.ts")).loadAllCode() + } + await openticket.events.get("onCodeLoad").emit([openticket.code]) + await openticket.events.get("afterCodeLoaded").emit([openticket.code]) + + //execute code + await openticket.events.get("onCodeExecute").emit([openticket.code]) + if (openticket.defaults.getDefault("codeExecution")){ + await openticket.code.execute() + await openticket.events.get("afterCodeExecuted").emit([openticket.code]) + } + + //finish setup + openticket.log("Setup complete!","info") + + //load livestatus sources + openticket.log("Loading livestatus...","system") + if (openticket.defaults.getDefault("liveStatusLoading")){ + await (await import("./data/framework/liveStatusLoader.ts")).loadAllLiveStatusSources() + } + await openticket.events.get("onLiveStatusSourceLoad").emit([openticket.livestatus]) + await openticket.events.get("afterLiveStatusSourcesLoaded").emit([openticket.livestatus]) + + //load startscreen + openticket.log("Loading startscreen...","system") + if (openticket.defaults.getDefault("startScreenLoading")){ + await (await import("./data/framework/startScreenLoader.ts")).loadAllStartScreenComponents() + } + await openticket.events.get("onStartScreenLoad").emit([openticket.startscreen]) + await openticket.events.get("afterStartScreensLoaded").emit([openticket.startscreen]) + + //render startscreen + await openticket.events.get("onStartScreenRender").emit([openticket.startscreen]) + if (openticket.defaults.getDefault("startScreenRendering")){ + await openticket.startscreen.renderAllComponents() + + await openticket.events.get("afterStartScreensRendered").emit([openticket.startscreen]) + } + + //YIPPPIE!! + //The startup of Open Ticket is completed :) +} +main() \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3398e8e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "ES2022", + "rootDir": "./src/", + "outDir": "./dist/", + "module": "NodeNext", + "moduleResolution": "NodeNext", + + "typeRoots": ["./node_modules/@types","./plugins/*/"], + "noEmit": true, + "allowImportingTsExtensions": true, + + "allowJs": false, + "checkJs": false, + "declaration": true, + "strictNullChecks": true, + "strictPropertyInitialization": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": ["./src/*","./src/**/*"] +} \ No newline at end of file From 0a69efdfe55a0519a9f5adb695c0766ec856b3db Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:52:33 +0200 Subject: [PATCH 003/157] Added german translation by benzorich --- README.md | 2 +- languages/german.json | 477 +++++++++++++++++++++++++++ src/core/api/defaults/language.ts | 1 + src/core/api/modules/defaults.ts | 2 +- src/data/framework/languageLoader.ts | 1 + 5 files changed, 481 insertions(+), 2 deletions(-) create mode 100644 languages/german.json diff --git a/README.md b/README.md index add080b..20f7ca0 100644 --- a/README.md +++ b/README.md @@ -91,10 +91,10 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇳🇱 Dutch |djj123dj |🟢 Up To Date | |🇵🇹 Portuguese |quiradon |🟢 Up To Date | |🇨🇿 Czech |spyeye_ |🟢 Up To Date | +|🇩🇪 German |benzorich |🟢 Up To Date | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | |🇷🇴 Romanian |sankedev |🟠 Temporary Outdated (beta) | |🇪🇸 Spanish |redactado & josuens |🟠 Temporary Outdated (beta) | -|🇩🇪 German |david.3 |🟠 Temporary Outdated (beta) | |🇮🇹 Italian |maurizio26 |🟠 Temporary Outdated (beta) | |🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | |🇩🇰 Danish |.the_gamer |🟠 Temporary Outdated (beta) | diff --git a/languages/german.json b/languages/german.json new file mode 100644 index 0000000..ac2b43c --- /dev/null +++ b/languages/german.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"benzorich", + "lastedited":"21/08/2024", + "language":"German" + }, + "checker":{ + "system":{ + "typeError":"[ERROR]", + "headerOpenTicket":"OPEN TICKET", + "typeWarning":"[WARNING]", + "typeInfo":"[INFO]", + "headerConfigChecker":"CONFIG CHECKER", + "headerDescription":"Prüfen Sie auf Fehler in Ihrer Konfigurationsdateien!", + "footerError":"Der Bot wird nicht starten, bis alle {0}'s repariert sind!", + "footerWarning":"Es wird empfohlen, vor dem Start alle {0}'s zu korrigieren!", + "footerSupport":"SUPPORT: {0} - DOCS: {1}", + "compactInformation":"Verwenden Sie {0} für weitere Informationen!", + "dataPath":"Pfad", + "dataDocs":"docs", + "dataMessages":"Nachricht" + }, + "messages":{ + "stringTooShort":"Diese Zeichenfolge kann nicht kürzer als {0} Zeichen sein!", + "stringTooLong":"Diese Zeichenfolge darf nicht länger als {0} Zeichen sein!", + "stringLengthInvalid":"Diese Zeichenfolge muss {0} Zeichen lang sein!", + "stringStartsWith":"Diese Zeichenfolge muss mit {0} beginnen!", + "stringEndsWith":"Diese Zeichenfolge muss mit {0} enden!", + "stringContains":"Diese Zeichenfolge muss {0} enthalten!", + "stringChoices":"Diese Zeichenfolge kann nur einen der folgenden Werte annehmen: {0}!", + "stringRegex":"Diese Zeichenfolge ist ungültig!", + + "numberTooShort":"Diese Zahl kann nicht kürzer als {0} Zeichen sein!", + "numberTooLong":"Diese Nummer darf nicht länger als {0} Zeichen sein!", + "numberLengthInvalid":"Diese Nummer muss {0} Zeichen lang sein!", + "numberTooSmall":"Diese Zahl muss mindestens {0} sein!", + "numberTooLarge":"Diese Zahl muss höchstens {0} sein!", + "numberNotEqual":"Diese Zahl muss {0} sein!", + "numberStep":"Diese Zahl muss ein Vielfaches von {0} sein!", + "numberStepOffset":"Diese Zahl muss ein Vielfaches von {0} sein und mit {1} beginnen!", + "numberStartsWith":"Diese Zahl muss mit {0} beginnen!", + "numberEndsWith":"Diese Zahl muss mit {0} enden!", + "numberContains":"Diese Zahl muss {0} enthalten!", + "numberChoices":"Diese Zahl kann nur einen der folgenden Werte annehmen: {0}!", + "numberFloat":"Diese Zahl kann keine Dezimalzahl sein!", + "numberNegative":"Diese Zahl kann nicht negativ sein!", + "numberPositive":"Diese Zahl kann nicht positiv sein!", + "numberZero":"Diese Zahl kann nicht Null sein!", + + "booleanTrue":"Dieser boolean Wert kann nicht wahr sein!", + "booleanFalse":"Dieser boolean Wert kann nicht falsch sein!", + + "arrayEmptyDisabled":"Dieses Array darf nicht leer sein!", + "arrayEmptyRequired":"Dieses Array muss leer sein!", + "arrayTooShort":"Dieses Array muss eine Länge von mindestens {0} haben!", + "arrayTooLong":"Dieses Array darf höchstens eine Länge von {0} haben!", + "arrayLengthInvalid":"Dieses Array muss eine Länge von {0} haben!", + "arrayInvalidTypes":"Dieses Array kann nur die folgenden Typen enthalten: {0}!", + "arrayDouble":"In diesem Array darf derselbe Wert nicht zweimal vorkommen!", + + "discordInvalidId":"Dies ist eine ungültige Discord {0} id!", + "discordInvalidIdOptions":"Dies ist eine ungültige Discord {0} id! Du kannst auch eine der folgenden verwenden: {1}!", + "discordInvalidToken":"Das ist ein ungültiger Discord-Token (syntaktisch)!", + "colorInvalid":"Dies ist eine ungültige Hex-Farbe!", + "emojiTooShort":"Diese Zeichenfolge muss mindestens {0} Emojis enthalten!", + "emojiTooLong":"Diese Zeichenfolge darf höchstens {0} Emojis enthalten!", + "emojiCustom":"Dieses Emoji kann kein benutzerdefiniertes Discord-Emoji sein!", + "emojiInvalid":"Dies ist ein ungültiges Emoji!", + "urlInvalid":"Diese Url ist ungültig!", + "urlInvalidHttp":"Diese Url kann nur das https:// Protokoll verwenden!", + "urlInvalidProtocol":"Diese Url kann nur die Protokolle http:// & https:// verwenden!", + "urlInvalidHostname":"Diese Url hat einen unzulässigen Hostnamen!", + "urlInvalidExtension":"Diese Url hat eine ungültige Erweiterung! Wählen Sie zwischen: {0}!", + "urlInvalidPath":"Diese Url hat einen ungültigen Pfad!", + "idNotUnique":"Diese ID ist nicht eindeutig, verwenden Sie stattdessen eine andere ID!", + "idNonExistent":"Die ID {0} existiert nicht!", + + "invalidType":"Diese Eigenschaft muss vom Typ sein: {0}!", + "propertyMissing":"Die Eigenschaft {0} fehlt in diesem Objekt!", + "propertyOptional":"Die Eigenschaft {0} ist in diesem Objekt optional!", + "objectDisabled":"Dieses Objekt ist deaktiviert, aktivieren Sie es mit {0}!", + "nullInvalid":"Diese Eigenschaft kann nicht null sein!", + "switchInvalidType":"Dies muss einer der folgenden Typen sein: {0}!", + "objectSwitchInvalid":"Dieses Objekt muss einer der folgenden Typen sein: {0}!", + + "invalidLanguage":"Dies ist eine ungültige Sprache!", + "invalidButton":"Dieser Button muss mindestens eine {0} oder {1} enthalten!", + "unusedOption":"Die Option {0} wird nirgends verwendet!", + "unusedQuestion":"Die Frage {0} wird nirgends verwendet!", + "dropdownOption":"Ein Panel mit aktiviertem Dropdown kann nur Optionen vom Typ 'Ticket' enthalten!" + } + }, + "actions":{ + "buttons":{ + "create":"Ticket besuchen", + "close":"Ticket schließen", + "delete":"Ticket löschen", + "reopen":"Ticket wieder öffnen", + "claim":"Ticket beanspruchen", + "unclaim":"Ticket nicht mehr beanspruchen", + "pin":"Pin Ticket", + "unpin":"Unpin Ticket", + "clear":"Tickets löschen", + "helpSwitchSlash":"Slash-Befehle anzeigen", + "helpSwitchText":"Textbefehle anzeigen", + "helpPage":"Seite {0}", + "withReason":"Mit Grund", + "withoutTranscript":"Ohne Transkription" + }, + "titles":{ + "created":"Ticket erstellt", + "close":"Ticket geschlossen", + "delete":"Ticket Gelöscht", + "reopen":"Ticket Reopened", + "claim":"Ticket beansprucht", + "unclaim":"Ticket nicht mehr beanspruchen", + "pin":"Ticket angeheftet", + "unpin":"Ticket entpinnt", + "rename":"Ticket umbenannt", + "move":"Ticket verschoben", + "add":"Ticket-Benutzer hinzugefügt", + "remove":"Ticket-Benutzer entfernt", + + "help":"Verfügbare Befehle", + "statsReset":"Statistiken zurücksetzen", + "blacklistAdd":"Benutzer auf der Blacklist", + "blacklistRemove":"Benutzer Freigegeben", + "blacklistGet":"Benutzer auf der Blacklist", + "blacklistView":"Aktuelle Blacklist", + "blacklistAddDm":"Zur Blacklist hinzugefügt", + "blacklistRemoveDm":"Von der Blacklist entfernen", + "clear":"Freigegebene Tickets", + "roles":"Aktualisierte Rollen", + + "autoclose":"Ticket automatisch geschlossen", + "autocloseEnabled":"Autoclose Aktiviert", + "autocloseDisabled":"Autoclose Deaktiviert", + "autodelete":"Automatisch gelöschtes Ticket", + "autodeleteEnabled":"Autolöschen Aktiviert", + "autodeleteDisabled":"Automatisches Löschen Deaktiviert" + }, + "descriptions":{ + "create":"Ihr Ticket wurde bereits erstellt. Klicken Sie auf die Button unten, um es zu öffnen!", + "close":"Das Ticket wurde erfolgreich geschlossen!", + "delete":"Das Ticket wurde erfolgreich gelöscht!", + "reopen":"The ticket has been reopened succesfully!", + "claim":"Das Ticket wurde erfolgreich beansprucht!", + "unclaim":"Das Ticket wurde erfolgreich freigegeben!", + "pin":"Das Ticket ist erfolgreich angepinnt worden!", + "unpin":"Das Ticket wurde erfolgreich entpinnt!", + "rename":"Das Ticket wurde erfolgreich in {0} umbenannt!", + "move":"Das Ticket wurde erfolgreich nach {0} verschoben!", + "add":"{0} wurde erfolgreich zum Ticket hinzugefügt!", + "remove":"{0} wurde erfolgreich aus dem Ticket entfernt!", + + "helpExplanation":"`` => erforderlicher Parameter\n`[name]` => optionaler Parameter", + "statsReset":"Die Bot-Statistiken wurden erfolgreich zurückgesetzt!", + "statsError":"Ticketstatistiken können nicht angezeigt werden!\n{0} ist kein Ticket!", + "blacklistAdd":"{0} wurde erfolgreich auf die Blacklist gesetzt!", + "blacklistRemove":"{0} wurde erfolgreich freigegeben!", + "blacklistGetSuccess":"{0} steht derzeit auf der Blacklist!", + "blacklistGetEmpty":"{0} steht derzeit nicht auf der Blacklist!", + "blacklistViewEmpty":"Es wurde noch niemand auf die Blacklist gesetzt!", + "blacklistViewTip":"Verwenden Sie \"/blacklist add\", um einen Benutzer auf die Blacklist zu setzen!", + "clearVerify":"Sind Sie sicher, dass Sie mehrere Tickets löschen möchten?\nDiese Aktion kann nicht rückgängig gemacht werden!", + "clearReady":"{0} Tickets wurden erfolgreich gelöscht!", + "rolesEmpty":"Es wurden keine Rollen aktualisiert!", + + "autocloseLeave":"Dieses Ticket wurde automatisch geschlossen, weil der Ersteller den Server verlassen hat!", + "autocloseTimeout":"Dieses Ticket wurde automatisch geschlossen, da es seit mehr als `{0}h` inaktiv ist!", + "autodeleteLeave":"Dieses Ticket wurde automatisch gelöscht, weil der Ersteller den Server verlassen hat!", + "autodeleteTimeout":"Dieses Ticket wurde automatisch gelöscht, da es seit mehr als `{0} Tagen` inaktiv ist!", + "autocloseEnabled":"Autoclose wurde für dieses Ticket aktiviert! Es wird geschlossen, wenn es länger als `{0}h` inaktiv ist!", + "autocloseDisabled":"Autoclose wurde für dieses Ticket deaktiviert! Es wird nicht mehr automatisch geschlossen!", + "autodeleteEnabled":"Automatisches Löschen wurde für dieses Ticket aktiviert! Es wird gelöscht, wenn es länger als `{0} Tage` inaktiv ist!", + "autodeleteDisabled":"Automatisches Löschen wurde bei diesem Ticket deaktiviert! Es wird nicht mehr automatisch gelöscht!", + + "ticketMessageLimit":"Sie können nur {0} Tickets gleichzeitig erstellen!", + "ticketMessageAutoclose":"Dieses Ticket wird automatisch geschlossen, wenn es {0}h lang inaktiv war!", + "ticketMessageAutodelete":"Dieses Ticket wird automatisch gelöscht, wenn es {0} Tage lang inaktiv war!", + "panelReady":"Sie finden das Panel unten!\nDiese Nachricht kann jetzt gelöscht werden!" + }, + "modal":{ + "closePlaceholder":"Warum haben Sie dieses Ticket geschlossen?", + "deletePlaceholder":"Warum haben Sie dieses Ticket gelöscht?", + "reopenPlaceholder":"Warum haben Sie dieses Ticket erneut geöffnet?", + "claimPlaceholder":"Warum haben Sie dieses Ticket beansprucht?", + "unclaimPlaceholder":"Warum haben Sie dieses Ticket nicht beansprucht?", + "pinPlaceholder":"Warum haben Sie dieses Ticket angepinnt?", + "unpinPlaceholder":"Warum haben Sie dieses Ticket entpinnt?" + }, + "logs":{ + "createLog":"Ein neues Ticket wurde von {0} erstellt!", + "closeLog":"Dieses Ticket wurde von {0} geschlossen!", + "closeDm":"Ihr Ticket wurde von unserem Server geschlossen!", + "deleteLog":"Dieses Ticket wurde von {0} gelöscht!", + "deleteDm":"Ihr Ticket wurde auf unserem Server gelöscht!", + "reopenLog":"Dieses Ticket wurde von {0} wiedereröffnet!", + "reopenDm":"Ihr Ticket wurde auf unserem Server wieder geöffnet!", + "claimLog":"Dieses Ticket wurde von {0} beansprucht!", + "claimDm":"Ihr Ticket wurde auf unserem Server beansprucht!", + "unclaimLog":"Dieses Ticket wurde von {0} nicht in Anspruch genommen!", + "unclaimDm":"Ihr Ticket wurde von unserem Server nicht beansprucht!", + "pinLog":"Dieses Ticket wurde von {0} angepinnt!", + "pinDm":"Ihr Ticket wurde an unseren Server angepinnt!", + "unpinLog":"Dieses Ticket wurde von {0} entpinnt!", + "unpinDm":"Ihr Ticket wurde auf unserem Server entpinnt!", + "renameLog":"Dieses Ticket wurde von {1} in {0} umbenannt!", + "renameDm":"Ihr Ticket wurde auf unserem Server in {0} umbenannt!", + "moveLog":"Dieses Ticket wurde von {1} nach {0} verschoben!", + "moveDm":"Ihr Ticket wurde auf {0} in unserem Server verschoben!", + "addLog":"{0} wurde von {1} zu diesem Ticket hinzugefügt!", + "addDm":"{0} wurde zu Ihrem Ticket auf unserem Server hinzugefügt!", + "removeLog":"{0} wurde von {1} aus diesem Ticket entfernt!", + "removeDm":"{0} wurde von Ihrem Ticket auf unserem Server entfernt!", + + "blacklistAddLog":"{0} wurde von {1} auf die Blacklist gesetzt!", + "blacklistRemoveLog":"{0} wurde von {1} von der Blacklist entfernt!", + "blacklistAddDm":"Sie wurden in unserem Server auf die Blacklist gesetzt!\nAb sofort können Sie kein Ticket mehr erstellen!", + "blacklistRemoveDm":"Sie wurden von der Blacklist unseres Servers entfernt!\n Jetzt können Sie wieder Tickets erstellen!", + "clearLog":"{0} Tickets wurden von {1} gelöscht!" + } + }, + "transcripts":{ + "success":{ + "visit":"Transkript anschauen", + "ready":"Transkript erstellt", + "textFileDescription":"Dies ist die Textabschrift eines gelöschten Tickets!", + "htmlProgress":"Bitte warten Sie, während dieses html-Transkript verarbeitet wird...", + + "createdChannel":"Ein neues {0} Transkript wurde auf dem Server erstellt!", + "createdCreator":"Es wurde ein neues {0} Transkript für eines Ihrer Tickets erstellt!", + "createdParticipant":"In einem der Tickets, an denen Sie teilgenommen haben, wurde ein neues {0} Transkript erstellt!", + "createdActiveAdmin":"In einem der Tickets, an dem Sie als Administrator teilgenommen haben, wurde ein neues {0} Transkript erstellt!", + "createdEveryAdmin":"Ein neues {0} Transkript wurde in einem der Tickets erstellt, in dem Sie Administrator waren!", + "createdOther":"Es wurde ein neues {0} Transkript erstellt!" + }, + "errors":{ + "retry":"Erneut versuchen", + "continue":"Löschen ohne Transkript", + "backup":"Sicherungstranskript erstellen", + "error":"Beim Versuch, das Transkript zu erstellen, ist etwas schief gelaufen.\nWas möchten Sie tun?\n\nDieses Ticket wird erst gelöscht, wenn Sie auf eine der folgenden Buttons klicken." + } + }, + "errors":{ + "titles":{ + "internalError":"Interner Fehler", + "optionMissing":"Befehlsoption fehlt", + "optionInvalid":"Befehlsoption ungültig", + "unknownCommand":"Unbekannter Befehl", + "noPermissions":"Keine Berechtigungen", + "unknownTicket":"Unbekanntes Ticket", + "deprecatedTicket":"Veraltetes Ticket", + "unknownOption":"Unbekannte Option", + "unknownPanel":"Unbekanntes Panel", + "notInGuild":"Nicht auf dem Server", + "channelRename":"Kanal kann nicht umbenannt werden", + "busy":"Ticket ist besetzt" + }, + "descriptions":{ + "askForInfo":"Kontaktieren Sie den Besitzer dieses Bots für weitere Informationen!", + "askForInfoResolve":"Wenden Sie sich an den Besitzer dieses Bots, wenn sich das Problem nach einigen Versuchen nicht beheben lässt.", + "internalError":"Aufgrund eines internen Fehlers konnte auf diese {0} nicht geantwortet werden!", + "optionMissing":"Ein erforderlicher Parameter fehlt in diesem Befehl!", + "optionInvalid":"Ein Parameter in diesem Befehl ist ungültig!", + "optionInvalidChoose":"Wählen Sie zwischen", + "unknownCommand":"Besuchen Sie das Hilfemenü für weitere Informationen!", + "noPermissions":"Sie sind nicht berechtigt, {0} zu verwenden!", + "noPermissionsList":"Erforderliche Berechtigungen: (eine von diesen)", + "noPermissionsCooldown":"Du bist nicht berechtigt, {0} zu benutzen, weil du eine Abklingzeit hast!", + "noPermissionsBlacklist":"Sie sind nicht berechtigt, {0} zu benutzen, da Sie auf der Blacklist stehen!", + "noPermissionsLimitGlobal":"Sie können kein Ticket erstellen, da der Server die maximale Ticketanzahl erreicht hat!", + "noPermissionsLimitGlobalUser":"Sie können kein Ticket erstellen, weil Sie die maximale Anzahl an Tickets erreicht haben!", + "noPermissionsLimitOption":"Sie können kein Ticket erstellen, da der Server die maximale Ticketanzahl für diese Option erreicht hat!", + "noPermissionsLimitOptionUser":"Sie können kein Ticket erstellen, da Sie die maximale Anzahl an Tickets für diese Option erreicht haben!", + "unknownTicket":"Versuchen Sie diesen Befehl noch einmal mit einem gültigen Ticket!", + "deprecatedTicket":"Der aktuelle Kanal ist kein gültiges Ticket! Es könnte sich um ein Ticket aus einer alten Open Ticket Version handeln!", + "notInGuild":"{0} funktioniert nicht in DM! Bitte versuchen Sie es erneut auf einem Server!", + "channelRename":"Aufgrund von Discord-Ratelimits ist es dem Bot derzeit nicht möglich, den Channel umzubenennen. Der Channel wird nach 10 Minuten automatisch umbenannt, wenn der Bot nicht neu gestartet wird.", + "channelRenameSource":"Die Quelle dieses Fehlers ist: {0}", + "busy":"{0} kann nicht verwendet werden!\nDas Ticket wird derzeit vom Bot bearbeitet.\n\nBitte versuchen Sie es in ein paar Sekunden erneut!" + }, + "optionInvalidReasons":{ + "stringRegex":"Wert stimmt nicht mit Muster überein!", + "stringMinLength":"Der Wert muss mindestens {0} Zeichen lang sein!", + "stringMaxLength":"Der Wert darf höchstens {0} Zeichen lang sein!", + "numberInvalid":"Ungültige Nummer!", + "numberMin":"Die Zahl muss mindestens {0} sein!", + "numberMax":"Die Zahl muss höchstens {0} sein!", + "numberDecimal":"Die Zahl darf keine Dezimalzahl sein!", + "numberNegative":"Die Zahl darf nicht negativ sein!", + "numberPositive":"Die Zahl darf nicht positiv sein!", + "numberZero":"Die Zahl darf nicht Null sein!", + "channelNotFound":"Kanal kann nicht gefunden werden!", + "userNotFound":"Benutzer kann nicht gefunden werden!", + "roleNotFound":"Rolle kann nicht gefunden werden!", + "memberNotFound":"Benutzer kann nicht gefunden werden!", + "mentionableNotFound":"Benutzer oder Rolle kann nicht gefunden werden!", + "channelType":"Ungültiger Kanaltyp!", + "notInGuild":"Diese Option setzt voraus, dass Sie sich auf einem Server befinden!" + }, + "permissions":{ + "developer":"Sie müssen der Entwickler des Bots sein.", + "owner":"Sie müssen der Eigentümer des Servers sein.", + "admin":"Sie müssen ein Server-Administrator sein.", + "moderator":"Sie müssen ein Moderator sein.", + "support":"Sie müssen dem Support-Team angehören.", + "member":"Sie müssen Mitglied sein.", + "discord-administrator":"Sie benötigen die Berechtigung `ADMINISTRATOR`." + }, + "actionInvalid":{ + "close":"Das Ticket ist bereits geschlossen!", + "reopen":"Das Ticket ist noch nicht geschlossen!", + "claim":"Das Ticket wurde bereits beansprucht!", + "unclaim":"Das Ticket wurde noch nicht beansprucht!", + "pin":"Das Ticket ist bereits angepinnt!", + "unpin":"Das Ticket ist noch nicht angepinnt!", + "add":"Dieser Benutzer kann bereits auf das Ticket zugreifen!", + "remove":"Dieser Benutzer kann nicht aus dem Ticket entfernt werden!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickets", + "reason":"Grund", + "creator":"Creator", + "remaining":"Verbleibende Zeit", + "added":"Hinzugefügt", + "removed":"Entfernt", + "filter":"Filter", + "claimedBy":"Beansprucht von {0}", + "method":"Methode", + "type":"Typ", + "blacklisted":"Gesperrt", + "panel":"Panel", + "command":"Command", + "system":"System", + "true":"True", + "false":"False", + "syntax":"Syntax", + "originalName":"Ursprünglicher Name", + "newName":"Neuer Name", + "until":"Bis", + "validOptions":"Gültige Optionen", + "validPanels":"Gültige Panels", + "autoclose":"Autoclose", + "autodelete":"Autolöschung", + "startupDate":"Startdatum", + "version":"Version", + "name":"Name", + "role":"Rolle", + "status":"Status", + "claimed":"Beansprucht", + "pinned":"Angepinnt", + "creationDate":"Erstellungsdatum" + }, + "lowercase":{ + "text":"text", + "html":"html", + "command":"command", + "modal":"modal", + "button":"button", + "dropdown":"dropdown", + "method":"methode" + } + }, + "commands":{ + "reason":"Geben Sie einen optionalen Grund an, der in den Protokollen sichtbar sein wird.", + "help":"Abrufen einer Liste aller verfügbaren Befehle.", + "panel":"Erzeugen Sie eine Nachricht mit einer Dropdown-Liste oder Buttons (für die Erstellung von Tickets).", + "panelId":"Der Kennung des Panels, das Sie erzeugen wollen.", + "panelAutoUpdate":"Möchten Sie, dass dieses Feld bei der Bearbeitung automatisch aktualisiert wird?", + "ticket":"Erstellen Sie sofort ein Ticket.", + "ticketId":"Der Kennung des Panels, das Sie erzeugen wollen.", + "close":"Schließen Sie ein Ticket.", + "delete":"Ein Ticket löschen.", + "deleteNoTranscript":"Löschen Sie dieses Ticket, ohne ein Transkript zu erstellen.", + "reopen":"Öffnen Sie ein Ticket erneut.", + "claim":"Ein Ticket beanspruchen.", + "claimUser":"Beanspruchen Sie dieses Ticket für jemand anderen statt für sich selbst.", + "unclaim":"Beanspruchen Sie ein Ticket zurück.", + "pin":"Ein Ticket anpinnen..", + "unpin":"Löse die Anpinnung eines Tickets.", + "move":"Verschieben Sie ein Ticket.", + "moveId":"Die Kennung der Option.", + "rename":"Ein Ticket umbenennen.", + "renameName":"Der neue Name für dieses Ticket.", + "add":"Fügen Sie einen Benutzer zu einem Ticket hinzu.", + "addUser":"Der hinzuzufügende Benutzer.", + "remove":"Entfernen Sie einen Benutzer aus einem Ticket.", + "removeUser":"Der zu entfernende Benutzer.", + "blacklist":"Verwalten Sie die Blacklist für Tickets.", + "blacklistView":"Zeigen Sie eine Liste der aktuellen Blacklist an.", + "blacklistAdd":"Hinzufügen eines Benutzers zur Blacklist.", + "blacklistRemove":"Entfernen Sie einen Benutzer von der Blacklist.", + "blacklistGet":"Abrufen der Details eines auf der Blacklist stehenden Benutzers.", + "blacklistGetUser":"Der Benutzer, von dem Details abgerufen werden sollen.", + "stats":"Statistiken des Bots, eines Mitglieds oder eines Tickets anzeigen.", + "statsReset":"Setzt alle Statistiken des Bots zurück (und beginnt die Zählung bei Null).", + "statsGlobal":"Sehen Sie sich die Gesamtstatistiken an.", + "statsUser":"Zeigt die Statistiken eines Benutzers auf dem Server an.", + "statsUserUser":"Der zu betrachtende Benutzer.", + "statsTicket":"Anzeigen der Statistiken eines Tickets auf dem Server.", + "statsTicketTicket":"Das Ticket zur Betrachtung.", + "clear":"Mehrere Tickets gleichzeitig löschen. Optional kann ein Filter angegeben werden.", + "clearFilter":"Der Filter zum Löschen von Tickets.", + "clearFilters":{ + "all":"Alle", + "open":"Offen", + "close":"Geschlossen", + "claim":"Beansprucht", + "unclaim":"Nicht beanspruchte", + "pin":"Angepinnte", + "unpin":"nicht Angepinnte", + "autoclose":"Autoclosed" + }, + "autoclose":"Verwalten Sie die automatische Schließung in einem Ticket.", + "autocloseDisable":"Deaktivieren Sie das automatische Schließen in diesem Ticket.", + "autocloseEnable":"Aktivieren Sie das automatische Schließen in diesem Ticket.", + "autocloseEnableTime":"Die Anzahl der Stunden, die das Ticket inaktiv sein muss, um es zu schließen.", + "autodelete":"Verwalten Sie die automatische Löschung in einem Ticket.", + "autodeleteDisable":"Deaktivieren Sie das automatische Löschen in diesem Ticket.", + "autodeleteEnable":"Aktivieren Sie das automatische Löschen in diesem Ticket.", + "autodeleteEnableTime":"Die Anzahl der Tage, die das Ticket inaktiv sein muss, um es zu löschen." + }, + "helpMenu":{ + "help":"Erhalten Sie eine Liste mit allen verfügbaren Befehlen.", + "ticket":"Erstellen Sie sofort ein Ticket.", + "close":"Schließen Sie ein Ticket, um das Schreiben in diesem Kanal zu deaktivieren.", + "delete":"Löscht ein Ticket; wenn aktiviert, wird eine Transcript erstellt.", + "reopen":"Öffnen Sie ein Ticket erneut, damit Sie wieder in diesem Kanal schreiben können.", + "pin":"Ein Ticket anheften. Es wird nach oben verschoben und ein 📌 zum Namen hinzugefügt.", + "unpin":"Entpinnen Sie ein Ticket. Es bleibt an seiner Position, verliert aber das 📌-Emoji.", + "move":"Verschieben Sie ein Ticket. Dadurch wird der Typ dieses Tickets geändert.", + "rename":"Ein Ticket umbenennen. Dadurch wird der Kanalname dieses Tickets geändert.", + "claim":"Ein Ticket beanspruchen. Damit können Sie Ihrem Team mitteilen, dass Sie dieses Ticket bearbeiten.", + "unclaim":"Ticket zurück beanspruchen, um Ihrem Team zu zeigen, dass es wieder verfügbar ist.", + "add":"Benutzer zu einem Ticket hinzufügen, um ihm Lese- und Schreibrechte zu geben.", + "remove":"Benutzer aus einem Ticket entfernen, um seine Lese- und Schreibrechte zu entziehen.", + "panel":"Erzeugen Sie eine Nachricht mit einer Dropdown-Liste oder Buttons (für die Erstellung von Tickets).", + "blacklistView":"Zeigen Sie eine Liste der aktuellen Blacklist an.", + "blacklistAdd":"Hinzufügen eines Benutzers zur Blacklist.", + "blacklistRemove":"Entfernen Sie einen Benutzer von der Blacklist.", + "blacklistGet":"Abrufen der Details eines auf der Blacklist stehenden Benutzers.", + "statsGlobal":"Sehen Sie sich die Gesamtstatistiken an.", + "statsTicket":"Anzeigen der Statistiken eines Tickets auf dem Server.", + "statsUser":"Zeigt die Statistiken eines Benutzers auf dem Server an.", + "statsReset":"Setzt alle Statistiken des Bots zurück (und beginnt die Zählung bei Null).", + "autocloseDisable":"Deaktivieren Sie das automatische Schließen in diesem Ticket.", + "autocloseEnable":"Aktivieren Sie das automatische Schließen in diesem Ticket.", + "autodeleteDisable":"Deaktivieren Sie das automatische Löschen in diesem Ticket.", + "autodeleteEnable":"Aktivieren Sie das automatische Löschen in diesem Ticket." + }, + "stats":{ + "scopes":{ + "global":"Globale-Statistiken", + "system":"System-Statistiken", + "user":"Benutzer-Statistiken", + "ticket":"Ticket-Statistiken", + "participants":"Teilnehmer" + }, + "properties":{ + "ticketsCreated":"Tickets erstellt", + "ticketsClosed":"Tickets geschlossen", + "ticketsDeleted":"Tickets gelöscht", + "ticketsReopened":"Tickets wiedereröffnet", + "ticketsAutoclosed":"Tickets Autoclosed", + "ticketsClaimed":"Tickets beansprucht", + "ticketsPinned":"Tickets angepinnt", + "ticketsMoved":"Tickets verschoben", + "usersBlacklisted":"Nutzer auf der Blacklist gesetzt ", + "transcriptsCreated":"Transcripts erstellt" + } + } +} \ No newline at end of file diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index d8ad7ab..6f58120 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -449,6 +449,7 @@ export interface ODLanguageManagerIds_Default { "openticket:dutch":ODLanguage, "openticket:portuguese":ODLanguage, "openticket:czech":ODLanguage, + "openticket:german":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index a2f1910..17e0e41 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -234,7 +234,7 @@ export class ODDefaultsManager { languageLoading:true, languageSelection:true, backupLanguage:"openticket:english", - languageList:["custom","english","dutch","portuguese","czech"], + languageList:["custom","english","dutch","portuguese","czech","german"], checkerLoading:true, checkerFunctionLoading:true, diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 11261b1..770d701 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -6,6 +6,7 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODLanguage("openticket:dutch","dutch.json")) openticket.languages.add(new api.ODLanguage("openticket:portuguese","portuguese.json")) openticket.languages.add(new api.ODLanguage("openticket:czech","czech.json")) + openticket.languages.add(new api.ODLanguage("openticket:german","german.json")) /** How to add more languages? * - Add the language to the list above From 1dd8c0246adf37504db0b938176511d7d18de9ba Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 21 Aug 2024 22:46:54 +0200 Subject: [PATCH 004/157] Fixed some translation errors & added Catalan! --- README.md | 1 + languages/catalan.json | 477 +++++++++++++++++++++++++++ src/builders/embeds.ts | 4 +- src/builders/messages.ts | 8 +- src/commands/add.ts | 2 +- src/commands/autoclose.ts | 2 +- src/commands/claim.ts | 2 +- src/commands/close.ts | 2 +- src/commands/move.ts | 2 +- src/commands/pin.ts | 2 +- src/commands/remove.ts | 2 +- src/commands/reopen.ts | 2 +- src/commands/unclaim.ts | 2 +- src/commands/unpin.ts | 2 +- src/core/api/defaults/language.ts | 1 + src/core/api/modules/defaults.ts | 2 +- src/data/framework/checkerLoader.ts | 2 +- src/data/framework/languageLoader.ts | 1 + src/data/openticket/panelLoader.ts | 9 + 19 files changed, 507 insertions(+), 18 deletions(-) create mode 100644 languages/catalan.json diff --git a/README.md b/README.md index 20f7ca0..6323e18 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇵🇹 Portuguese |quiradon |🟢 Up To Date | |🇨🇿 Czech |spyeye_ |🟢 Up To Date | |🇩🇪 German |benzorich |🟢 Up To Date | +|❓ Catalan |guillee3 |🟢 Up To Date | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | |🇷🇴 Romanian |sankedev |🟠 Temporary Outdated (beta) | |🇪🇸 Spanish |redactado & josuens |🟠 Temporary Outdated (beta) | diff --git a/languages/catalan.json b/languages/catalan.json new file mode 100644 index 0000000..c24557a --- /dev/null +++ b/languages/catalan.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"guillee3", + "lastedited":"21/08/2024", + "language":"Catalan" + }, + "checker":{ + "system":{ + "typeError":"[ERROR]", + "headerOpenTicket":"OPEN TICKET", + "typeWarning":"[AVÍS]", + "typeInfo":"[INFO]", + "headerConfigChecker":"VERIFICADOR DE CONFIGURACIÓ", + "headerDescription":"comprova si existeixen errors als teus fitxers de configuració!", + "footerError":"el bot no s'iniciarà fins que tots els {0} es solucionin!", + "footerWarning":"es recomana solucionar tots els {0} abans de començar!", + "footerSupport":"SUPORT: {0} - DOCUMENTACIÓ: {1}", + "compactInformation":"utilitza {0} per obtenir més informació!", + "dataPath":"ruta", + "dataDocs":"documents", + "dataMessages":"missatge" + }, + "messages":{ + "stringTooShort":"Aquesta cadena no pot tenir menys de {0} caràcters!", + "stringTooLong":"Aquesta cadena no pot tenir més de {0} caràcters!", + "stringLengthInvalid":"Aquesta cadena ha de tenir {0} caràcters!", + "stringStartsWith":"Aquesta cadena ha de començar amb {0}!", + "stringEndsWith":"Aquesta cadena ha d'acabar amb {0}!", + "stringContains":"Aquesta cadena ha de contenir {0}!", + "stringChoices":"Aquesta cadena només pot ser un dels valors següents: {0}!", + "stringRegex":"Aquesta cadena és invàlida!", + + "numberTooShort":"Aquest nombre no pot tenir menys de {0} caràcters!", + "numberTooLong":"Aquest nombre no pot tenir més de {0} caràcters!", + "numberLengthInvalid":"Aquest nombre ha de tenir {0} caràcters!", + "numberTooSmall":"Aquest nombre ha de ser almenys {0}!", + "numberTooLarge":"Aquest nombre ha de ser com a màxim {0}!", + "numberNotEqual":"Aquest nombre ha de ser {0}!", + "numberStep":"Aquest nombre ha de ser un múltiple de {0}!", + "numberStepOffset":"Aquest nombre ha de ser un múltiple de {0} començant amb {1}!", + "numberStartsWith":"Aquest nombre ha de començar amb {0}!", + "numberEndsWith":"Aquest nombre ha d'acabar amb {0}!", + "numberContains":"Aquest nombre ha de contenir {0}!", + "numberChoices":"Aquest nombre només pot ser un dels valors següents: {0}!", + "numberFloat":"Aquest nombre no pot ser un decimal!", + "numberNegative":"Aquest nombre no pot ser negatiu!", + "numberPositive":"Aquest nombre no pot ser positiu!", + "numberZero":"Aquest nombre no pot ser zero!", + + "booleanTrue":"Aquest booleà no pot ser veritable!", + "booleanFalse":"Aquest booleà no pot ser fals!", + + "arrayEmptyDisabled":"Aquest array no pot estar buit!", + "arrayEmptyRequired":"Aquest array ha d'estar buit!", + "arrayTooShort":"Aquest array ha de tenir una longitud d'almenys {0}!", + "arrayTooLong":"Aquest array ha de tenir una longitud màxima de {0}!", + "arrayLengthInvalid":"Aquest array ha de tenir una longitud de {0}!", + "arrayInvalidTypes":"Aquest array només pot contenir els tipus següents: {0}!", + "arrayDouble":"Aquest array no permet el mateix valor dues vegades!", + + "discordInvalidId":"Aquest és un id de {0} de discord invàlid!", + "discordInvalidIdOptions":"Aquest és un id de {0} de discord invàlid! També en pots utilitzar un d'aquests: {1}!", + "discordInvalidToken":"Aquest és un token de discord invàlid (sintàcticament)!", + "colorInvalid":"Aquest és un color hex invàlid!", + "emojiTooShort":"Aquesta cadena ha de tenir almenys {0} emojis!", + "emojiTooLong":"Aquesta cadena ha de tenir com a màxim {0} emojis!", + "emojiCustom":"Aquest emoji no pot ser un emoji personalitzat de discord!", + "emojiInvalid":"Aquest és un emoji invàlid!", + "urlInvalid":"Aquesta url és invàlida!", + "urlInvalidHttp":"Aquesta url només pot utilitzar el protocol https://!", + "urlInvalidProtocol":"Aquesta url només pot utilitzar els protocols http:// i https://!", + "urlInvalidHostname":"Aquesta url té un nom de domini no permès!", + "urlInvalidExtension":"Aquesta url té una extensió invàlida! Tria entre: {0}!", + "urlInvalidPath":"Aquesta url té un camí invàlid!", + "idNotUnique":"Aquest id no és únic, utilitza un altre id!", + "idNonExistent":"L'id {0} no existeix!", + + "invalidType":"Aquesta propietat ha de ser del tipus: {0}!", + "propertyMissing":"La propietat {0} falta en aquest objecte!", + "propertyOptional":"La propietat {0} és opcional en aquest objecte!", + "objectDisabled":"Aquest objecte està desactivat, activa'l utilitzant {0}!", + "nullInvalid":"Aquesta propietat no pot ser nul·la!", + "switchInvalidType":"Això ha de ser d'un dels tipus següents: {0}!", + "objectSwitchInvalid":"Aquest objecte ha de ser d'un dels tipus següents: {0}!", + + "invalidLanguage":"Aquest és un idioma invàlid!", + "invalidButton":"Aquest botó ha de tenir almenys un {0} o {1}!", + "unusedOption":"L'opció {0} no s'utilitza enlloc!", + "unusedQuestion":"La pregunta {0} no s'utilitza enlloc!", + "dropdownOption":"Un panell amb desplegable activat només pot contenir opcions del tipus 'ticket'!" + } + }, + "actions":{ + "buttons":{ + "create":"Visitar Ticket", + "close":"Tancar Ticket", + "delete":"Eliminar Ticket", + "reopen":"Reobrir Ticket", + "claim":"Reclamar Ticket", + "unclaim":"Alliberar Ticket", + "pin":"Fixar Ticket", + "unpin":"Desfixar Ticket", + "clear":"Eliminar Tickets", + "helpSwitchSlash":"Veure Comandes Slash", + "helpSwitchText":"Veure Comandes de Text", + "helpPage":"Pàgina {0}", + "withReason":"Amb Motiu", + "withoutTranscript":"Sense Transcripció" + }, + "titles":{ + "created":"Ticket Creat", + "close":"Ticket Tancat", + "delete":"Ticket Eliminat", + "reopen":"Ticket Reobert", + "claim":"Ticket Reclamat", + "unclaim":"Ticket Alliberat", + "pin":"Ticket Fixat", + "unpin":"Ticket Desfixat", + "rename":"Ticket Renomenat", + "move":"Ticket Mogut", + "add":"Usuari Afegit al Ticket", + "remove":"Usuari Eliminat del Ticket", + + "help":"Comandes Disponibles", + "statsReset":"Restablir Estadístiques", + "blacklistAdd":"Usuari a la Llista Negra", + "blacklistRemove":"Usuari Alliberat", + "blacklistGet":"Usuari a la Llista Negra", + "blacklistView":"Llista Negra Actual", + "blacklistAddDm":"Afegit a la Llista Negra", + "blacklistRemoveDm":"Eliminat de la Llista Negra", + "clear":"Tickets Netejats", + "roles":"Rols Actualitzats", + + "autoclose":"Ticket Tancat Automàticament", + "autocloseEnabled":"Tancament Automàtic Activat", + "autocloseDisabled":"Tancament Automàtic Desactivat", + "autodelete":"Ticket Eliminat Automàticament", + "autodeleteEnabled":"Eliminació Automàtica Activada", + "autodeleteDisabled":"Eliminació Automàtica Desactivada" + }, + "descriptions":{ + "create":"El teu ticket ha estat creat. Fes clic al botó a continuació per accedir-hi!", + "close":"El ticket ha estat tancat amb èxit!", + "delete":"El ticket ha estat eliminat amb èxit!", + "reopen":"El ticket ha estat reobert amb èxit!", + "claim":"El ticket ha estat reclamat amb èxit!", + "unclaim":"El ticket ha estat alliberat amb èxit!", + "pin":"El ticket ha estat fixat amb èxit!", + "unpin":"El ticket ha estat desfixat amb èxit!", + "rename":"El ticket ha estat renomenat a {0} amb èxit!", + "move":"El ticket ha estat mogut a {0} amb èxit!", + "add":"{0} ha estat afegit al ticket amb èxit!", + "remove":"{0} ha estat eliminat del ticket amb èxit!", + + "helpExplanation":"`` => paràmetre requerit\n`[nom]` => paràmetre opcional", + "statsReset":"Les estadístiques del bot s'han restablert correctament!", + "statsError":"No es poden veure les estadístiques del ticket!\n{0} no és un ticket!", + "blacklistAdd":"{0} ha estat afegit a la llista negra amb èxit!", + "blacklistRemove":"{0} ha estat alliberat amb èxit!", + "blacklistGetSuccess":"{0} està actualment a la llista negra!", + "blacklistGetEmpty":"{0} actualment no està a la llista negra!", + "blacklistViewEmpty":"Encara no hi ha ningú a la llista negra!", + "blacklistViewTip":"Utilitza \"/blacklist add\" per afegir un usuari a la llista negra!", + "clearVerify":"Estàs segur que vols eliminar múltiples tickets?\nAquesta acció no es pot desfer!", + "clearReady":"{0} tickets han estat eliminats amb èxit!", + "rolesEmpty":"No s'han actualitzat rols!", + + "autocloseLeave":"Aquest ticket ha estat tancat automàticament perquè el creador ha abandonat el servidor!", + "autocloseTimeout":"Aquest ticket ha estat tancat automàticament perquè ha estat inactiu durant més de `{0}h`!", + "autodeleteLeave":"Aquest ticket ha estat eliminat automàticament perquè el creador ha abandonat el servidor!", + "autodeleteTimeout":"Aquest ticket ha estat eliminat automàticament perquè ha estat inactiu durant més de `{0} dies`!", + "autocloseEnabled":"El tancament automàtic ha estat activat en aquest ticket!\nEs tancarà quan estigui inactiu durant més de `{0}h`!", + "autocloseDisabled":"El tancament automàtic ha estat desactivat en aquest ticket!\nJa no es tancarà automàticament!", + "autodeleteEnabled":"L'eliminació automàtica ha estat activada en aquest ticket!\nS'eliminarà quan estigui inactiu durant més de `{0} dies`!", + "autodeleteDisabled":"L'eliminació automàtica ha estat desactivada en aquest ticket!\nJa no s'eliminarà automàticament!", + + "ticketMessageLimit":"Només pots crear {0} ticket(s) al mateix temps!", + "ticketMessageAutoclose":"Aquest ticket es tancarà automàticament quan estigui inactiu durant {0}h!", + "ticketMessageAutodelete":"Aquest ticket es eliminarà automàticament quan estigui inactiu durant {0} dies!", + "panelReady":"Pots trobar el panell a continuació!\nAquest missatge ara es pot eliminar!" + }, + "modal":{ + "closePlaceholder":"Per què has tancat aquest ticket?", + "deletePlaceholder":"Per què has eliminat aquest ticket?", + "reopenPlaceholder":"Per què has reobert aquest ticket?", + "claimPlaceholder":"Per què has reclamat aquest ticket?", + "unclaimPlaceholder":"Per què has alliberat aquest ticket?", + "pinPlaceholder":"Per què has fixat aquest ticket?", + "unpinPlaceholder":"Per què has desfixat aquest ticket?" + }, + "logs":{ + "createLog":"Un nou ticket ha estat creat per {0}!", + "closeLog":"Aquest ticket ha estat tancat per {0}!", + "closeDm":"El teu ticket ha estat tancat al nostre servidor!", + "deleteLog":"Aquest ticket ha estat eliminat per {0}!", + "deleteDm":"El teu ticket ha estat eliminat al nostre servidor!", + "reopenLog":"Aquest ticket ha estat reobert per {0}!", + "reopenDm":"El teu ticket ha estat reobert al nostre servidor!", + "claimLog":"Aquest ticket ha estat reclamat per {0}!", + "claimDm":"El teu ticket ha estat reclamat al nostre servidor!", + "unclaimLog":"Aquest ticket ha estat alliberat per {0}!", + "unclaimDm":"El teu ticket ha estat alliberat al nostre servidor!", + "pinLog":"Aquest ticket ha estat fixat per {0}!", + "pinDm":"El teu ticket ha estat fixat al nostre servidor!", + "unpinLog":"Aquest ticket ha estat desfixat per {0}!", + "unpinDm":"El teu ticket ha estat desfixat al nostre servidor!", + "renameLog":"Aquest ticket ha estat renomenat a {0} per {1}!", + "renameDm":"El teu ticket ha estat renomenat a {0} al nostre servidor!", + "moveLog":"Aquest ticket ha estat mogut a {0} per {1}!", + "moveDm":"El teu ticket ha estat mogut a {0} al nostre servidor!", + "addLog":"{0} ha estat afegit a aquest ticket per {1}!", + "addDm":"{0} ha estat afegit al teu ticket al nostre servidor!", + "removeLog":"{0} ha estat eliminat d'aquest ticket per {1}!", + "removeDm":"{0} ha estat eliminat del teu ticket al nostre servidor!", + + "blacklistAddLog":"{0} ha estat afegit a la llista negra per {1}!", + "blacklistRemoveLog":"{0} ha estat eliminat de la llista negra per {1}!", + "blacklistAddDm":"Has estat afegit a la llista negra al nostre servidor!\nA partir d'ara, no pots crear cap ticket!", + "blacklistRemoveDm":"Has estat eliminat de la llista negra al nostre servidor!\nAra pots crear tickets de nou!", + "clearLog":"{0} tickets han estat eliminats per {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Visitar Transcripció", + "ready":"Transcripció Creada", + "textFileDescription":"Aquesta és la transcripció de text d'un ticket eliminat!", + "htmlProgress":"Si us plau, espera mentre aquesta transcripció html es processa...", + + "createdChannel":"S'ha creat una nova transcripció tipus {0} al servidor!", + "createdCreator":"S'ha creat una nova transcripció tipus {0} per un dels teus tickets!", + "createdParticipant":"S'ha creat una nova transcripció tipus {0} en un dels tickets on has participat!", + "createdActiveAdmin":"S'ha creat una nova transcripció tipus {0} en un dels tickets on has participat com a administrador!", + "createdEveryAdmin":"S'ha creat una nova transcripció tipus {0} en un dels tickets on eres administrador!", + "createdOther":"S'ha creat una nova transcripció tipus {0}!" + }, + "errors":{ + "retry":"Torna-ho a intentar", + "continue":"Elimina Sense Transcripció", + "backup":"Crea Transcripció de Backup", + "error":"Alguna cosa ha anat malament mentre intentàvem crear la transcripció.\nQuè t'agradaria fer?\n\nAquest ticket no s'eliminarà fins que facis clic en un d'aquests botons." + } + }, + "errors":{ + "titles":{ + "internalError":"Error Intern", + "optionMissing":"Opció de Comanda Absent", + "optionInvalid":"Opció de Comanda Invàlida", + "unknownCommand":"Comanda Desconeguda", + "noPermissions":"No Tens Permisos", + "unknownTicket":"Ticket Desconegut", + "deprecatedTicket":"Ticket Obsolet", + "unknownOption":"Opció Desconeguda", + "unknownPanel":"Panell Desconegut", + "notInGuild":"No Ets Al Servidor", + "channelRename":"No Es Pot Canviar El Nom Del Canal", + "busy":"El Ticket Està Ocupat" + }, + "descriptions":{ + "askForInfo":"Contacta amb el propietari d'aquest bot per obtenir més informació!", + "askForInfoResolve":"Contacta amb el propietari del bot si aquest problema no es resol després de diversos intents.", + "internalError":"No s'ha pogut respondre a aquest {0} a causa d'un error intern!", + "optionMissing":"Falta un paràmetre requerit en aquesta comanda!", + "optionInvalid":"Un paràmetre d'aquesta comanda és invàlid!", + "optionInvalidChoose":"Tria entre", + "unknownCommand":"Prova de visitar el menú d'ajuda per obtenir més informació!", + "noPermissions":"No tens permís per utilitzar aquest {0}!", + "noPermissionsList":"Permisos Requerits: (un d'ells)", + "noPermissionsCooldown":"No tens permís per utilitzar aquest {0} perquè tens un temps de refredament!", + "noPermissionsBlacklist":"No tens permís per utilitzar aquest {0} perquè estàs a la llista negra!", + "noPermissionsLimitGlobal":"No tens permís per crear un ticket perquè el servidor ha arribat al límit màxim de tickets!", + "noPermissionsLimitGlobalUser":"No tens permís per crear un ticket perquè has arribat al límit màxim de tickets!", + "noPermissionsLimitOption":"No tens permís per crear un ticket perquè el servidor ha arribat al límit màxim de tickets per aquesta opció!", + "noPermissionsLimitOptionUser":"No tens permís per crear un ticket perquè has arribat al límit màxim de tickets per aquesta opció!", + "unknownTicket":"Torna a intentar aquesta comanda en un ticket vàlid!", + "deprecatedTicket":"El canal actual no és un ticket vàlid! Pot ser que fos un ticket d'una versió antiga de Open Ticket!", + "notInGuild":"Aquest {0} no funciona en DM! Si us plau, torna a intentar-ho en un servidor!", + "channelRename":"Degut a les limitacions de discord, actualment és impossible per al bot canviar el nom del canal. El canal es canviarà automàticament en 10 minuts si el bot no es reinicia.", + "channelRenameSource":"La font d'aquest error és: {0}", + "busy":"No es pot utilitzar aquest {0}!\nEl ticket està sent processat pel bot.\n\nSi us plau, torna a intentar-ho en uns segons!" + }, + "optionInvalidReasons":{ + "stringRegex":"El valor no coincideix amb el patró!", + "stringMinLength":"El valor ha de tenir almenys {0} caràcters!", + "stringMaxLength":"El valor ha de tenir com a màxim {0} caràcters!", + "numberInvalid":"Nombre invàlid!", + "numberMin":"El nombre ha de ser almenys {0}!", + "numberMax":"El nombre ha de ser com a màxim {0}!", + "numberDecimal":"El nombre no pot ser decimal!", + "numberNegative":"El nombre no pot ser negatiu!", + "numberPositive":"El nombre no pot ser positiu!", + "numberZero":"El nombre no pot ser zero!", + "channelNotFound":"No es pot trobar el canal!", + "userNotFound":"No es pot trobar l'usuari!", + "roleNotFound":"No es pot trobar el rol!", + "memberNotFound":"No es pot trobar l'usuari!", + "mentionableNotFound":"No es pot trobar l'usuari o el rol!", + "channelType":"Tipus de canal invàlid!", + "notInGuild":"Aquesta opció requereix que siguis en un servidor!" + }, + "permissions":{ + "developer":"Has de ser el desenvolupador del bot.", + "owner":"Has de ser el propietari del servidor.", + "admin":"Has de ser un administrador del servidor.", + "moderator":"Has de ser un moderador.", + "support":"Has de formar part de l'equip de suport.", + "member":"Has de ser un membre.", + "discord-administrator":"Has de tenir el permís `ADMINISTRADOR`." + }, + "actionInvalid":{ + "close":"El ticket ja està tancat!", + "reopen":"El ticket encara no està tancat!", + "claim":"El ticket ja està reclamat!", + "unclaim":"El ticket encara no està reclamat!", + "pin":"El ticket ja està fixat!", + "unpin":"El ticket encara no està fixat!", + "add":"Aquest usuari ja té accés al ticket!", + "remove":"No es pot eliminar aquest usuari del ticket!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickets", + "reason":"Motiu", + "creator":"Creador", + "remaining":"Temps Restant", + "added":"Afegit", + "removed":"Eliminat", + "filter":"Filtre", + "claimedBy":"Reclamat Per {0}", + "method":"Mètode", + "type":"Tipus", + "blacklisted":"Llista Negra", + "panel":"Panell", + "command":"Comanda", + "system":"Sistema", + "true":"Cert", + "false":"Fals", + "syntax":"Sintaxi", + "originalName":"Nom Original", + "newName":"Nom Nou", + "until":"Fins a", + "validOptions":"Opcions Vàlides", + "validPanels":"Panells Vàlids", + "autoclose":"Tancament Automàtic", + "autodelete":"Eliminació Automàtica", + "startupDate":"Data d'Inici", + "version":"Versió", + "name":"Nom", + "role":"Rol", + "status":"Estat", + "claimed":"Reclamat", + "pinned":"Fixat", + "creationDate":"Data de Creació" + }, + "lowercase":{ + "text":"text", + "html":"html", + "command":"comanda", + "modal":"modal", + "button":"botó", + "dropdown":"desplegable", + "method":"mètode" + } + }, + "commands":{ + "reason":"Especifica una raó opcional que serà visible als registres.", + "help":"Obtingues una llista de totes les comandes disponibles.", + "panel":"Genera un missatge amb un desplegable o botons (per a la creació de tickets).", + "panelId":"L'identificador del panell que vols generar.", + "panelAutoUpdate":"Vols que aquest panell s'actualitzi automàticament quan s'edita?", + "ticket":"Crea instantàniament un ticket.", + "ticketId":"L'identificador del ticket que vols crear.", + "close":"Tanca un ticket.", + "delete":"Elimina un ticket.", + "deleteNoTranscript":"Elimina aquest ticket sense crear una transcripció.", + "reopen":"Reobre un ticket.", + "claim":"Reclama un ticket.", + "claimUser":"Reclama aquest ticket per a una altra persona en lloc de tu mateix.", + "unclaim":"Allibera un ticket.", + "pin":"Fixa un ticket.", + "unpin":"Desfixa un ticket.", + "move":"Mou un ticket.", + "moveId":"L'identificador de l'opció a la qual vols moure't.", + "rename":"Renomena un ticket.", + "renameName":"El nou nom per aquest ticket.", + "add":"Afegeix un usuari a un ticket.", + "addUser":"L'usuari a afegir.", + "remove":"Elimina un usuari d'un ticket.", + "removeUser":"L'usuari a eliminar.", + "blacklist":"Gestiona la llista negra de tickets.", + "blacklistView":"Veure una llista de l'actual llista negra.", + "blacklistAdd":"Afegeix un usuari a la llista negra.", + "blacklistRemove":"Elimina un usuari de la llista negra.", + "blacklistGet":"Obtingues els detalls d'un usuari a la llista negra.", + "blacklistGetUser":"L'usuari dels qual vols obtenir detalls.", + "stats":"Veure estadístiques del bot, d'un membre o d'un ticket.", + "statsReset":"Restablir totes les estadístiques del bot (i començar a comptar des de zero).", + "statsGlobal":"Veure les estadístiques globals.", + "statsUser":"Veure les estadístiques d'un usuari al servidor.", + "statsUserUser":"L'usuari del qual vols veure les estadístiques.", + "statsTicket":"Veure les estadístiques d'un ticket al servidor.", + "statsTicketTicket":"El ticket que vols veure.", + "clear":"Elimina múltiples tickets al mateix temps.", + "clearFilter":"El filtre per a la neteja de tickets.", + "clearFilters":{ + "all":"Tots", + "open":"Oberts", + "close":"Tancats", + "claim":"Reclamats", + "unclaim":"Alliberats", + "pin":"Fixats", + "unpin":"Desfixats", + "autoclose":"Tancat Automàticaments" + }, + "autoclose":"Gestiona el tancament automàtic en un ticket.", + "autocloseDisable":"Desactiva el tancament automàtic en aquest ticket.", + "autocloseEnable":"Activa el tancament automàtic en aquest ticket.", + "autocloseEnableTime":"La quantitat d'hores que aquest ticket ha d'estar inactiu per tancar-lo.", + "autodelete":"Gestiona l'eliminació automàtica en un ticket.", + "autodeleteDisable":"Desactiva l'eliminació automàtica en aquest ticket.", + "autodeleteEnable":"Activa l'eliminació automàtica en aquest ticket.", + "autodeleteEnableTime":"La quantitat de dies que aquest ticket ha d'estar inactiu per eliminar-lo." + }, + "helpMenu":{ + "help":"Obtingues una llista de totes les comandes disponibles.", + "ticket":"Crea instantàniament un ticket.", + "close":"Tanca un ticket, això desactiva l'escriptura en aquest canal.", + "delete":"Elimina un ticket, això crea una transcripció quan està activat.", + "reopen":"Reobre un ticket, això permet escriure de nou en aquest canal.", + "pin":"Fixar un ticket. Això mou el ticket a la part superior i afegeix un emoji '📌' al nom.", + "unpin":"Desfixar un ticket. El ticket romandrà a la seva posició però perdrà l'emoji '📌'.", + "move":"Mou un ticket. Això canvia el tipus d'aquest ticket.", + "rename":"Renomena un ticket. Això canvia el nom del canal d'aquest ticket.", + "claim":"Reclama un ticket. Amb això, pots fer saber al teu equip que estàs gestionant aquest ticket.", + "unclaim":"Allibera un ticket. Amb això, pots fer saber al teu equip que aquest ticket està lliure de nou.", + "add":"Afegeix un usuari a un ticket. Això permetrà a l'usuari llegir i escriure en aquest ticket.", + "remove":"Elimina un usuari d'un ticket. Això eliminarà la capacitat de llegir i escriure per a un usuari en aquest ticket.", + "panel":"Genera un missatge amb un desplegable o botons (per a la creació de tickets).", + "blacklistView":"Veure una la llista negra actual.", + "blacklistAdd":"Afegeix un usuari a la llista negra.", + "blacklistRemove":"Elimina un usuari de la llista negra.", + "blacklistGet":"Obtingues els detalls d'un usuari de la llista negra.", + "statsGlobal":"Veure les estadístiques globals.", + "statsTicket":"Veure les estadístiques d'un ticket al servidor.", + "statsUser":"Veure les estadístiques d'un usuari al servidor.", + "statsReset":"Restablir totes les estadístiques del bot (i començar a comptar des de zero).", + "autocloseDisable":"Desactiva el tancament automàtic en aquest ticket.", + "autocloseEnable":"Activa el tancament automàtic en aquest ticket.", + "autodeleteDisable":"Desactiva l'eliminació automàtica en aquest ticket.", + "autodeleteEnable":"Activa l'eliminació automàtica en aquest ticket." + }, + "stats":{ + "scopes":{ + "global":"Estadístiques Globals", + "system":"Estadístiques del Sistema", + "user":"Estadístiques d'Usuari", + "ticket":"Estadístiques de Ticket", + "participants":"Participants" + }, + "properties":{ + "ticketsCreated":"Tickets Creats", + "ticketsClosed":"Tickets Tancats", + "ticketsDeleted":"Tickets Eliminats", + "ticketsReopened":"Tickets Reoberts", + "ticketsAutoclosed":"Tickets Tancats Automàticament", + "ticketsClaimed":"Tickets Reclamats", + "ticketsPinned":"Tickets Fixats", + "ticketsMoved":"Tickets Moguts", + "usersBlacklisted":"Usuaris a la Llista Negra", + "transcriptsCreated":"Transcripcions Creades" + } + } +} \ No newline at end of file diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts index 4eb4d0e..6923c63 100644 --- a/src/builders/embeds.ts +++ b/src/builders/embeds.ts @@ -203,7 +203,7 @@ const errorEmbeds = () => { instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions"))) instance.setAuthor(user.displayName,user.displayAvatarURL()) - instance.setDescription(lang.getTranslation("errors.descriptions.noPermissionsBlacklist")) + instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissionsBlacklist",[method])) }) ) @@ -834,7 +834,7 @@ const ticketEmbeds = () => { //TODO TRANSLATION!!! {name:"Option"+":",value:"```"+(ticket.option.get("openticket:name").value)+"```",inline:false}, ) - if (reason) instance.addFields({name:"Reason:",value:"```"+reason+"```",inline:false}) + if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```",inline:false}) if (mode == "close"){ instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close"))) diff --git a/src/builders/messages.ts b/src/builders/messages.ts index 25dd7a3..dfb0f1a 100644 --- a/src/builders/messages.ts +++ b/src/builders/messages.ts @@ -94,7 +94,7 @@ const verifyBarMessages = () => { instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:"Without Transcript",customColor:"red"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) } }) ) @@ -130,7 +130,7 @@ const verifyBarMessages = () => { instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:"Without Transcript",customColor:"red"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) } }) ) @@ -166,7 +166,7 @@ const verifyBarMessages = () => { instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:"Without Transcript",customColor:"red"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) } }) ) @@ -319,7 +319,7 @@ const verifyBarMessages = () => { instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:"Without Transcript",customColor:"red"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) } }) ) diff --git a/src/commands/add.ts b/src/commands/add.ts index 4ad48b9..5186c9e 100644 --- a/src/commands/add.ts +++ b/src/commands/add.ts @@ -66,7 +66,7 @@ export const registerCommandResponders = async () => { //return when user already added to ticket const participants = await openticket.tickets.getAllTicketParticipants(ticket) if (!participants || participants.find((p) => p.user.id == data.id)){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"This user is already able to access the ticket!",layout:"simple"})) + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.add"),layout:"simple"})) return cancel() } diff --git a/src/commands/autoclose.ts b/src/commands/autoclose.ts index e731e96..7bfc575 100644 --- a/src/commands/autoclose.ts +++ b/src/commands/autoclose.ts @@ -57,7 +57,7 @@ export const registerCommandResponders = async () => { } //return when already closed if (ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is already closed!",layout:"simple"})) + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) return cancel() } //return when busy diff --git a/src/commands/claim.ts b/src/commands/claim.ts index 84316f7..c6ad44c 100644 --- a/src/commands/claim.ts +++ b/src/commands/claim.ts @@ -56,7 +56,7 @@ export const registerCommandResponders = async () => { } //return when already claimed if (ticket.get("openticket:claimed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is already claimed!",layout:"simple"})) + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) return cancel() } //return when busy diff --git a/src/commands/close.ts b/src/commands/close.ts index dc39dc6..fdb107c 100644 --- a/src/commands/close.ts +++ b/src/commands/close.ts @@ -56,7 +56,7 @@ export const registerCommandResponders = async () => { } //return when already closed if (ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is already closed!",layout:"simple"})) + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) return cancel() } //return when busy diff --git a/src/commands/move.ts b/src/commands/move.ts index a33cb55..f3d1b23 100644 --- a/src/commands/move.ts +++ b/src/commands/move.ts @@ -66,7 +66,7 @@ export const registerCommandResponders = async () => { const option = openticket.options.get(id) //return if unknown option if (!option || !(option instanceof api.ODTicketOption)){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Unknown Option",layout:"simple"})) + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.titles.unknownOption"),layout:"simple"})) return cancel() } //return if option is the same diff --git a/src/commands/pin.ts b/src/commands/pin.ts index 64d5c2b..a29f5ad 100644 --- a/src/commands/pin.ts +++ b/src/commands/pin.ts @@ -56,7 +56,7 @@ export const registerCommandResponders = async () => { } //return when already pinned if (ticket.get("openticket:pinned").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is already pinned!",layout:"simple"})) + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) return cancel() } //return when busy diff --git a/src/commands/remove.ts b/src/commands/remove.ts index f984372..e38a265 100644 --- a/src/commands/remove.ts +++ b/src/commands/remove.ts @@ -66,7 +66,7 @@ export const registerCommandResponders = async () => { //return when user is not a participant of the ticket (admins & creator can't be removed) const participants = await openticket.tickets.getAllTicketParticipants(ticket) if (!participants || !participants.find((p) => p.user.id == data.id && p.role == "participant")){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Unable to remove this user from the ticket!",layout:"simple"})) + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.remove"),layout:"simple"})) return cancel() } diff --git a/src/commands/reopen.ts b/src/commands/reopen.ts index 82ccb36..415ba5d 100644 --- a/src/commands/reopen.ts +++ b/src/commands/reopen.ts @@ -56,7 +56,7 @@ export const registerCommandResponders = async () => { } //return when not closed if (!ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is not closed yet!",layout:"simple"})) + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) return cancel() } //return when busy diff --git a/src/commands/unclaim.ts b/src/commands/unclaim.ts index 784fa8a..e4ff53c 100644 --- a/src/commands/unclaim.ts +++ b/src/commands/unclaim.ts @@ -56,7 +56,7 @@ export const registerCommandResponders = async () => { } //return when not claimed if (!ticket.get("openticket:claimed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is not claimed yet!",layout:"simple"})) + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) return cancel() } //return when busy diff --git a/src/commands/unpin.ts b/src/commands/unpin.ts index c39daf2..b69b579 100644 --- a/src/commands/unpin.ts +++ b/src/commands/unpin.ts @@ -56,7 +56,7 @@ export const registerCommandResponders = async () => { } //return when not pinned yet if (!ticket.get("openticket:pinned").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"Ticket is not pinned yet!",layout:"simple"})) + instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) return cancel() } //return when busy diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index 6f58120..b81a9dc 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -450,6 +450,7 @@ export interface ODLanguageManagerIds_Default { "openticket:portuguese":ODLanguage, "openticket:czech":ODLanguage, "openticket:german":ODLanguage, + "openticket:catalan":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index 17e0e41..cefc0c5 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -234,7 +234,7 @@ export class ODDefaultsManager { languageLoading:true, languageSelection:true, backupLanguage:"openticket:english", - languageList:["custom","english","dutch","portuguese","czech","german"], + languageList:["custom","english","dutch","portuguese","czech","german","catalan"], checkerLoading:true, checkerFunctionLoading:true, diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts index 1e02728..667fa1b 100644 --- a/src/data/framework/checkerLoader.ts +++ b/src/data/framework/checkerLoader.ts @@ -488,7 +488,7 @@ export const defaultTranscriptsStructure = new api.ODCheckerObjectStructure("ope {key:"includeFiles",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-files",{})}, {key:"includeBotMessages",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-bots",{})}, - {key:"fileMode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-text-file-mode",{choices:["custom","name","id"]})}, + {key:"fileMode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-text-file-mode",{choices:["custom","channel-name","channel-id","user-name","user-id"]})}, {key:"customFileName",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-file-name",{maxLength:512,regex:/^[^\.#%&{}\\<>*?/!'":@`|=]*$/})}, ]})}, diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 770d701..70a9ca4 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -7,6 +7,7 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODLanguage("openticket:portuguese","portuguese.json")) openticket.languages.add(new api.ODLanguage("openticket:czech","czech.json")) openticket.languages.add(new api.ODLanguage("openticket:german","german.json")) + openticket.languages.add(new api.ODLanguage("openticket:catalan","catalan.json")) /** How to add more languages? * - Add the language to the list above diff --git a/src/data/openticket/panelLoader.ts b/src/data/openticket/panelLoader.ts index 5737c53..3d3682d 100644 --- a/src/data/openticket/panelLoader.ts +++ b/src/data/openticket/panelLoader.ts @@ -63,6 +63,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { } }) + //TODO TRANSLATION!!! const autotitle = (hasTicket && ticketOnly) ? "Select your ticket:" : ((hasRole && roleOnly) ? "Select your role:" : "Select your option:") const title = (panel.get("openticket:describe-options-custom-title").value.length < 1) ? "__"+autotitle+"__\n" : "__"+panel.get("openticket:describe-options-custom-title").value+"__\n" @@ -74,10 +75,13 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" if (layout == "normal" || layout == "detailed"){ + //TODO TRANSLATION!!! if (opt.exists("openticket:cooldown-enabled") && opt.get("openticket:cooldown-enabled").value) description = description + "\nCooldown: `"+opt.get("openticket:cooldown-minutes").value+" min`" + //TODO TRANSLATION!!! if (opt.exists("openticket:limits-enabled") && opt.get("openticket:limits-enabled").value) description = description + "\nMax Tickets: `"+opt.get("openticket:limits-maximum-user").value+"`" } if (layout == "detailed"){ + //TODO TRANSLATION!!! if (opt.exists("openticket:admins")) description = description + "\nAdmins: "+opt.get("openticket:admins").value.map((admin) => discord.roleMention(admin)).join(", ") } @@ -98,6 +102,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" if (layout == "normal" || layout == "detailed"){ + //TODO TRANSLATION!!! if (opt.exists("openticket:roles")) description = description + "\nRoles: "+opt.get("openticket:roles").value.map((admin) => discord.roleMention(admin)).join(", ") } @@ -119,10 +124,13 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" if (layout == "normal" || layout == "detailed"){ + //TODO TRANSLATION!!! if (opt.exists("openticket:cooldown-enabled") && opt.get("openticket:cooldown-enabled").value) description = description + "\nCooldown: `"+opt.get("openticket:cooldown-minutes").value+" min`" + //TODO TRANSLATION!!! if (opt.exists("openticket:limits-enabled") && opt.get("openticket:limits-enabled").value) description = description + "\nMax Tickets: `"+opt.get("openticket:limits-maximum-user").value+"`" } if (layout == "detailed"){ + //TODO TRANSLATION!!! if (opt.exists("openticket:admins")) description = description + "\nAdmins: "+opt.get("openticket:admins").value.map((admin) => discord.roleMention(admin)).join(", ") } @@ -145,6 +153,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" if (layout == "normal" || layout == "detailed"){ + //TODO TRANSLATION!!! if (opt.exists("openticket:roles")) description = description + "\nRoles: "+opt.get("openticket:roles").value.map((admin) => discord.roleMention(admin)).join(", ") } From 8e730fdfae7ad5a81b99a5d1dc76f59e6995ae52 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 22 Aug 2024 10:28:24 +0200 Subject: [PATCH 005/157] Tried to fix typescript not working on pterodactyl --- package.json | 1 + src/backupStartup.mjs | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 src/backupStartup.mjs diff --git a/package.json b/package.json index df895fc..2a2f7be 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "scripts": { "verify": "tsc -p ./tsconfig.json", "start": "npx tsx ./src/index.ts", + "backupstart": "node ./src/backupStartup.mjs", "test": "npm run verify && npx tsx ./src/index.ts --dev-config --dev-database" }, "type": "commonjs", diff --git a/src/backupStartup.mjs b/src/backupStartup.mjs new file mode 100644 index 0000000..aa0b79e --- /dev/null +++ b/src/backupStartup.mjs @@ -0,0 +1,12 @@ +/** === ALTERNATIVE STARTUP METHOD === + * This file can be used to start the bot when the default `npm start` (npx tsx src/index.ts) doesn't work! + * It is not recommended to use this by default, but it is a backup option for certain panels that don't support typescript. + * + * RECOMMENDED ON: + * - pterodactyl based panels + * - pebblehost + * - and more + */ + +import "tsx" +import("./index.ts") \ No newline at end of file From cd7fb7533f9bc18d250b2bdeaeacaf273a75d950 Mon Sep 17 00:00:00 2001 From: Hugo Torres Date: Thu, 22 Aug 2024 11:39:07 +0200 Subject: [PATCH 006/157] Add Spanish Language --- languages/spanish.json | 477 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 477 insertions(+) create mode 100644 languages/spanish.json diff --git a/languages/spanish.json b/languages/spanish.json new file mode 100644 index 0000000..5ff7419 --- /dev/null +++ b/languages/spanish.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"Redactado and Josuens", + "lastedited":"22/8/2024", + "language":"Spanish" + }, + "checker":{ + "system":{ + "typeError":"[ERROR]", + "headerOpenTicket":"ABRIR TICKET", + "typeWarning":"[AVISO]", + "typeInfo":"[INFORMACIÓN]", + "headerConfigChecker":"VERIFICADOR DE CONFIGURACION", + "headerDescription":"revisa los errores en tus archivos de configuración!", + "footerError":"el bot no comenzará hasta que todos los {0} esten resueltos!", + "footerWarning":"es recomendable corregir todos los {0} antes de comenzar!", + "footerSupport":"SOPORTE: {0} - DOCUMENTACIÓN: {1}", + "compactInformation":"usa el comando {0} para ver más información!", + "dataPath":"ruta", + "dataDocs":"documantación", + "dataMessages":"mensaje" + }, + "messages":{ + "stringTooShort":"¡Esta cadena no puede ser más corta que {0} caracteres!", + "stringTooLong":"¡Esta cadena no puede ser más larga que {0} caracteres!", + "stringLengthInvalid":"¡Esta cadena necesita tener {0} caracteres!", + "stringStartsWith":"¡Esta cadena necesita empezar con {0}!", + "stringEndsWith":"¡Esta cadena necesita terminar con {0}!", + "stringContains":"¡Esta cadena necesita contener {0}!", + "stringChoices":"¡Esta cadena no puede ser uno de los siguientes valores: {0}!", + "stringRegex":"¡La cadena no es válida!", + + "numberTooShort":"¡Este número no puede ser menor que {0}!", + "numberTooLong":"¡Este número no puede ser mayor que {0}!", + "numberLengthInvalid":"¡Este número necesita tener {0}!", + "numberTooSmall":"¡Este número debe ser al menos {0}!", + "numberTooLarge":"¡Este número debe ser como máximo {0}!", + "numberNotEqual":"¡Este número debe ser {0}!", + "numberStep":"¡Este número debe ser un múltiplo de {0}!", + "numberStepOffset":"¡Este número debe ser un múltiplo de {0} comenzando con {1}!", + "numberStartsWith":"¡Este número debe comenzar con {0}!", + "numberEndsWith":"¡Este número debe terminar con {0}!", + "numberContains":"¡Este número debe contener {0}!", + "numberChoices":"¡Este número solo puede ser uno de los siguientes valores: {0}!", + "numberFloat":"¡Este número no puede ser decimal!", + "numberNegative":"¡Este número no puede ser negativo!", + "numberPositive":"¡Este número no puede ser positivo!", + "numberZero":"¡Este número no puede ser cero!", + + "booleanTrue":"¡Este valor no puede ser positivo!", + "booleanFalse":"¡Este valor no puede ser negativo!", + + "arrayEmptyDisabled":"¡No se permite que este conjunto de valores esté vacío!", + "arrayEmptyRequired":"¡Se requiere que este conjunto de valores esté vacío!", + "arrayTooShort":"¡Este conjunto de valores necesita tener una longitud de al menos {0}!", + "arrayTooLong":"¡Este conjunto de valores necesita tener una longitud de como máximo {0}!", + "arrayLengthInvalid":"¡Este conjunto de valores necesita tener una longitud de {0}!", + "arrayInvalidTypes":"Este conjunto de valores solo puede contener los siguientes tipos: {0}!", + "arrayDouble":"¡Este conjunto de valores no permite el mismo valor dos veces!", + + "discordInvalidId":"¡Esta es una ID de discord {0} inválida!", + "discordInvalidIdOptions":"¡Esta es una ID de discord {0} inválida! También puedes usar una de estas: {1}!", + "discordInvalidToken":"¡Este es un token de discord inválido (sintácticamente)!", + "colorInvalid":"¡Este es un color hexadecimal inválido!", + "emojiTooShort":"¡Esta cadena necesita tener al menos {0} emojis!", + "emojiTooLong":"¡Esta cadena necesita tener como máximo {0} emojis!", + "emojiCustom":"¡Este emoji no puede ser un emoji personalizado de discord!", + "emojiInvalid":"¡Este es un emoji inválido!", + "urlInvalid":"¡Esta URL es inválida!", + "urlInvalidHttp":"¡Esta URL solo puede usar el protocolo https:/\/!", + "urlInvalidProtocol":"¡Esta URL solo puede usar los protocolos http:// y https:/\/!", + "urlInvalidHostname":"¡Esta URL tiene un nombre de host no permitido!", + "urlInvalidExtension":"¡Esta URL tiene una extensión inválida! Elige entre: {0}!", + "urlInvalidPath":"¡Esta URL tiene una ruta inválida!", + "idNotUnique":"Esta ID no es única, usa otra ID en su lugar!", + "idNonExistent":"La ID {0} no existe!", + + "invalidType":"Esta propiedad necesita ser del tipo: {0}!", + "propertyMissing":"La propiedad {0} falta en este objeto!", + "propertyOptional":"La propiedad {0} es opcional en este objeto!", + "objectDisabled":"Este objeto está deshabilitado, actívalo usando {0}!", + "nullInvalid":"Esta propiedad no puede ser nula!", + "switchInvalidType":"Esto necesita ser uno de los siguientes tipos: {0}!", + "objectSwitchInvalid":"Este objeto necesita ser uno de los siguientes tipos: {0}!", + + "invalidLanguage":"¡Este es un idioma inválido!", + "invalidButton":"¡Este botón necesita al menos un {0} o un {1}!", + "unusedOption":"¡La opción {0} no se usa en ningún lugar!", + "unusedQuestion":"¡La pregunta {0} no se usa en ningún lugar!", + "dropdownOption":"¡Este panel de botóns solo puede contener opciones de tipo 'ticket'!" + } + }, + "actions":{ + "buttons":{ + "create":"Visitar Ticket", + "close":"Cerrar Ticket", + "delete":"Eliminar Ticket", + "reopen":"Reabrir Ticket", + "claim":"Reclamar Ticket", + "unclaim":"Liberar Ticket", + "pin":"Anclar Ticket", + "unpin":"Desanclar Ticket", + "clear":"Eliminar los Tickets", + "helpSwitchSlash":"Ver los Comandos de Slash", + "helpSwitchText":"Ver los Comandos de Texto", + "helpPage":"Página {0}", + "withReason":"Con razón", + "withoutTranscript":"Sin transcripción" + }, + "titles":{ + "created":"Ticket Creado", + "close":"Ticket Cerrado", + "delete":"Ticket Eliminado", + "reopen":"Ticket Reabierto", + "claim":"Ticket Reclamado", + "unclaim":"Ticket Liberado", + "pin":"Ticket Anclado", + "unpin":"Ticket Desanclado", + "rename":"Ticket Renombrado", + "move":"Ticket Movido", + "add":"Agrgegado Usuario a Ticket", + "remove":"Eliminado Usuario de Ticket", + + "help":"Comandos Disponibles", + "statsReset":"Reiniciar Estadísticas", + "blacklistAdd":"Usuarios en la Lista Negra", + "blacklistRemove":"Usuarios eliminados de la Lista Negra", + "blacklistGet":"Usuario en la Lista Negra", + "blacklistView":"Lista negra actual", + "blacklistAddDm":"Agregado a la Lista Negra", + "blacklistRemoveDm":"Eliminado de la Lista Negra", + "clear":"Tickets Limpiados", + "roles":"Roles Actualizados", + + "autoclose":"Ticket Cerrado Automáticamente", + "autocloseEnabled":"Cierre Automático Habilitado", + "autocloseDisabled":"Cierre Automático Deshabilitado", + "autodelete":"Ticket Eliminado Automáticamente", + "autodeleteEnabled":"Eliminación Automática Habilitada", + "autodeleteDisabled":"Eliminación Automática Deshabilitada" + }, + "descriptions":{ + "create":"¡Tu ticket ha sido creado! Haz click en el botón abajo para verlo!", + "close":"¡El ticket fué cerrado correctamente!", + "delete":"¡El ticket fué eliminado correctamente!", + "reopen":"¡El ticket fué reabierto correctamente!", + "claim":"¡El ticket fué reclamado correctamente!", + "unclaim":"¡El ticket fué liberado correctamente!", + "pin":"¡El ticket fué anclado correctamente!", + "unpin":"¡El anclado del ticket fue quitado correctamente!", + "rename":"¡El ticket fué renombrado a {0} correctamente!", + "move":"¡El ticket fué movido a {0} correctamente!", + "add":"¡{0} ha sido agregado a este ticket correctamente!", + "remove":"¡{0} ha sido removido de este ticket correctamente!", + + "helpExplanation":"`` => argumento requerido\n`[nombre]` => argumento opcional", + "statsReset":"¡Las estadísticas de este ticket han sido reiniciadas!", + "statsError":"¡No se pueden ver las estadísticas de este ticket!\n¡{0} no es un ticket!", + "blacklistAdd":"¡{0} ha sido agregado a la Lista Negra correctamente!", + "blacklistRemove":"¡{0} ha sido eliminado de la Lista Negra correctamente!", + "blacklistGetSuccess":"¡{0} está actualmente en la Lista Negra!", + "blacklistGetEmpty":"¡{0} no está actualmente en la Lista Negra!", + "blacklistViewEmpty":"¡No hay usuarios actualmente en la Lista Negra!", + "blacklistViewTip":"¡Usa \"/blacklist add\" para agregar un usuario a la Lista Negra!", + "clearVerify":"¿Estás seguro de que deseas borrar los tickets?\n¡Esta acción no se puede deshacer!", + "clearReady":"¡{0} tickets fueron eliminados correctamente!", + "rolesEmpty":"¡Ningún rol fué actualizado!", + + "autocloseLeave":"¡Este ticket se ha cerrado automáticamente porque el creador abandonó el servidor!", + "autocloseTimeout":"¡Este ticket se ha cerrado automáticamente porque ha estado inactivo durante más de `{0}h`!", + "autodeleteLeave":"¡Este ticket se ha eliminado automáticamente porque el creador abandonó el servidor!", + "autodeleteTimeout":"¡Este ticket se ha eliminado automáticamente porque ha estado inactivo durante más de `{0} días`!", + "autocloseEnabled":"¡El cierre automático se ha habilitado en este ticket!\nSe cerrará cuando esté inactivo durante más de `{0}h`!", + "autocloseDisabled":"¡El cierre automático se ha deshabilitado en este ticket!\n¡Ya no se cerrará automáticamente!", + "autodeleteEnabled":"¡La eliminación automática se ha habilitado en este ticket!\nSe eliminará cuando esté inactivo durante más de `{0} días`!", + "autodeleteDisabled":"¡La eliminación automática se ha deshabilitado en este ticket!\n¡Ya no se eliminará automáticamente!", + + "ticketMessageLimit":"¡Solo puedes crear {0} ticket(s) al mismo tiempo!", + "ticketMessageAutoclose":"¡Este ticket se cerrará automáticamente cuando esté inactivo durante {0}h!", + "ticketMessageAutodelete":"¡Este ticket se eliminará automáticamente cuando esté inactivo durante {0} días!", + "panelReady":"¡Puedes encontrar el panel a continuación!\n¡Este mensaje ahora puede ser eliminado!" + }, + "modal":{ + "closePlaceholder":"¿Por qué cerraste este ticket?", + "deletePlaceholder":"¿Por qué eliminaste este ticket?", + "reopenPlaceholder":"¿Por qué reabriste este ticket?", + "claimPlaceholder":"¿Por qué reclamaste este ticket?", + "unclaimPlaceholder":"¿Por qué liberaste este ticket?", + "pinPlaceholder":"¿Por qué fijaste este ticket?", + "unpinPlaceholder":"¿Por qué desanclaste este ticket?" + }, + "logs":{ + "createLog":"¡Un nuevo ticket ha sido creado por {0}!", + "closeLog":"¡Este ticket ha sido cerrado por {0}!", + "closeDm":"¡Tu ticket ha sido cerrado en nuestro servidor!", + "deleteLog":"¡Este ticket ha sido eliminado por {0}!", + "deleteDm":"¡Tu ticket ha sido eliminado en nuestro servidor!", + "reopenLog":"¡Este ticket ha sido reabierto por {0}!", + "reopenDm":"¡Tu ticket ha sido reabierto en nuestro servidor!", + "claimLog":"¡Este ticket ha sido reclamado por {0}!", + "claimDm":"¡Tu ticket ha sido reclamado en nuestro servidor!", + "unclaimLog":"¡Este ticket ha sido liberado por {0}!", + "unclaimDm":"¡Tu ticket ha sido liberado en nuestro servidor!", + "pinLog":"¡Este ticket ha sido anclado por {0}!", + "pinDm":"¡Tu ticket ha sido anclado en nuestro servidor!", + "unpinLog":"¡Este ticket ha sido desanclado por {0}!", + "unpinDm":"¡Tu ticket ha sido desanclado en nuestro servidor!", + "renameLog":"¡Este ticket ha sido renombrado a {0} por {1}!", + "renameDm":"¡Tu ticket ha sido renombrado a {0} en nuestro servidor!", + "moveLog":"¡Este ticket ha sido movido a {0} por {1}!", + "moveDm":"¡Tu ticket ha sido movido a {0} en nuestro servidor!", + "addLog":"¡{0} ha sido añadido a este ticket por {1}!", + "addDm":"¡{0} ha sido añadido a tu ticket en nuestro servidor!", + "removeLog":"¡{0} ha sido eliminado de este ticket por {1}!", + "removeDm":"¡{0} ha sido eliminado de tu ticket en nuestro servidor!", + + "blacklistAddLog":"{0} fue incluido en la lista negra por {1}", + "blacklistRemoveLog":"{0} fue eliminado de la lista negra por {1}", + "blacklistAddDm":"¡Has sido incluido en la lista negra en nuestro servidor!\n¡A partir de ahora, no puedes crear un ticket!", + "blacklistRemoveDm":"¡Has sido eliminado de la lista negra en nuestro servidor!\n¡Ahora puedes volver a crear tickets!", + "clearLog":"¡{0} tickets han sido eliminados por {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Ver transcripción", + "ready":"Transcripción creada", + "textFileDescription":"¡Esta es la transcripción de texto de un ticket!", + "htmlProgress":"Espera mientras la transcripción en HTML es procesado...", + + "createdChannel":"¡Se ha creado una nueva transcripción {0} en el servidor!", + "createdCreator":"¡Se ha creado una nueva transcripción {0} para uno de tus tickets!", + "createdParticipant":"¡Se ha creado una nueva transcripción {0} en uno de los tickets en los que participaste!", + "createdActiveAdmin":"¡Se ha creado una nueva transcripción {0} en uno de los tickets en los que participaste como administrador!", + "createdEveryAdmin":"¡Se ha creado una nueva transcripción {0} en uno de los tickets en los que fuiste administrador!", + "createdOther":"¡Se ha creado una nueva transcripción {0}!" + }, + "errors":{ + "retry":"Reintentar", + "continue":"Eliminar sin transcripción", + "backup":"Crear respaldo de la transcripción", + "error":"Algo salió mal al intentar subir la transcripción.\n¿Qué desearías hacer?\n\nEste ticket no será eliminado hasta que presiones uno de los botones." + } + }, + "errors":{ + "titles":{ + "internalError":"Error Interno", + "optionMissing":"Argumento Faltante en Comando", + "optionInvalid":"Argumento Inválido en Comando", + "unknownCommand":"Comando Desconocido", + "noPermissions":"Permisos Insuficientes", + "unknownTicket":"Ticket Desconocido", + "deprecatedTicket":"Ticket Desactualizado", + "unknownOption":"Opción Desconocida", + "unknownPanel":"Panel Desconocido", + "notInGuild":"No está en el Servidor", + "channelRename":"No es posible renombrar el canal", + "busy":"El ticket está siendo procesado" + }, + "descriptions":{ + "askForInfo":"¡Contacta al propietario de este bot para obtener más información!", + "askForInfoResolve":"Contacta al propietario de este bot si este problema no se resuelve después de varios intentos.", + "internalError":"¡No se pudo responder a este {0} debido a un error interno!", + "optionMissing":"¡Falta un argumento requerido en este comando!", + "optionInvalid":"¡Un argumento en este comando es inválido!", + "optionInvalidChoose":"Elige entre", + "unknownCommand":"¡Intenta visitar el menú de ayuda para obtener más información!", + "noPermissions":"¡No tienes permiso para usar este {0}!", + "noPermissionsList":"Permisos requeridos: (uno de ellos)", + "noPermissionsCooldown":"¡No tienes permiso para usar este {0} porque tienes un tiempo de espera!", + "noPermissionsBlacklist":"¡No tienes permiso para usar este {0} porque has sido incluido en la lista negra!", + "noPermissionsLimitGlobal":"¡No tienes permiso para crear un ticket porque el servidor alcanzó el límite máximo de tickets!", + "noPermissionsLimitGlobalUser":"¡No tienes permiso para crear un ticket porque alcanzaste el límite máximo de tickets!", + "noPermissionsLimitOption":"¡No tienes permiso para crear un ticket porque el servidor alcanzó el límite máximo de tickets para esta opción!", + "noPermissionsLimitOptionUser":"¡No tienes permiso para crear un ticket porque alcanzaste el límite máximo de tickets para esta opción!", + "unknownTicket":"¡Intenta este comando de nuevo en un ticket válido!", + "deprecatedTicket":"¡El canal actual no es un ticket válido! ¡Podría haber sido un ticket de una versión antigua de Open Ticket!", + "notInGuild":"¡Este {0} no funciona en DM! ¡Por favor, inténtalo de nuevo en un servidor!", + "channelRename":"Debido a los límites de velocidad de discord, actualmente es imposible para el bot renombrar el canal. El canal se renombrará automáticamente en 10 minutos si el bot no se reinicia.", + "channelRenameSource":"La fuente de este error es: {0}", + "busy":"¡No se puede usar este {0}!\nEl ticket está siendo procesado actualmente por el bot.\n\n¡Por favor, inténtalo de nuevo en unos segundos!" + }, + "optionInvalidReasons":{ + "stringRegex":"¡El valor no coincide con el patrón!", + "stringMinLength":"¡El valor debe tener al menos {0} caracteres!", + "stringMaxLength":"¡El valor debe tener como máximo {0} caracteres!", + "numberInvalid":"¡Número inválido!", + "numberMin":"¡El número debe ser al menos {0}!", + "numberMax":"¡El número debe ser como máximo {0}!", + "numberDecimal":"¡El número no puede ser decimal!", + "numberNegative":"¡El número no puede ser negativo!", + "numberPositive":"¡El número no puede ser positivo!", + "numberZero":"¡El número no puede ser cero!", + "channelNotFound":"¡No se puede encontrar el canal!", + "userNotFound":"¡No se puede encontrar al usuario!", + "roleNotFound":"¡No se puede encontrar el rol!", + "memberNotFound":"¡No se puede encontrar al usuario!", + "mentionableNotFound":"¡No se puede encontrar al usuario o rol!", + "channelType":"¡Tipo de canal inválido!", + "notInGuild":"¡Esta opción requiere que estés en un servidor!" + }, + "permissions":{ + "developer":"Necesitas ser el desarrollador del bot.", + "owner":"Necesitas ser el propietario del servidor.", + "admin":"Necesitas ser un administrador del servidor.", + "moderator":"Necesitas ser un moderador.", + "support":"Necesitas estar en el equipo de soporte.", + "member":"Necesitas ser un miembro.", + "discord-administrator":"Necesitas tener el permiso `ADMINISTRADOR`." + }, + "actionInvalid":{ + "close":"¡El ticket ya está cerrado!", + "reopen":"¡El ticket aún no está cerrado!", + "claim":"¡El ticket ya está reclamado!", + "unclaim":"¡El ticket aún no está reclamado!", + "pin":"¡El ticket ya está anclado!", + "unpin":"¡El ticket aún no está anclado!", + "add":"¡Este usuario ya puede acceder al ticket!", + "remove":"¡No se puede eliminar a este usuario del ticket!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickets", + "reason":"Razón", + "creator":"Creador", + "remaining":"Tiempo Restante", + "added":"Agregado", + "removed":"Eliminado", + "filter":"Filtrar", + "claimedBy":"Reclamado Por {0}", + "method":"Método", + "type":"Tipo", + "blacklisted":"En La Lista Negra", + "panel":"Panel", + "command":"Comando", + "system":"Sistema", + "true":"Verdadero", + "false":"Falso", + "syntax":"Sintaxis", + "originalName":"Nombre Original", + "newName":"Nuevo Nombre", + "until":"Hasta", + "validOptions":"Operaciones Válidas", + "validPanels":"Paneles Válidos", + "autoclose":"Cierre Automático", + "autodelete":"Eliminación Automática", + "startupDate":"Fecha De Inicio", + "version":"Versión", + "name":"Nombre", + "role":"Rol", + "status":"Estado", + "claimed":"Reclamado", + "pinned":"Anclado", + "creationDate":"Fecha De Creación" + }, + "lowercase":{ + "text":"texto", + "html":"html", + "command":"comando", + "modal":"menú", + "button":"botón", + "dropdown":"menú desplegable", + "method":"método" + } + }, + "commands":{ + "reason":"Especifica una razón opcional que será visible en los registros.", + "help":"Obtén una lista de todos los comandos disponibles.", + "panel":"Genera un mensaje con un desplegable o botones (para la creación de tickets).", + "panelId":"El identificador del panel que quieres generar.", + "panelAutoUpdate":"¿Quieres que este panel se actualice automáticamente cuando se edite?", + "ticket":"Crea un ticket instantáneamente.", + "ticketId":"El identificador del ticket que quieres crear.", + "close":"Cierra un ticket, esto deshabilita la escritura en este canal. ¡Esta acción siempre puede ser revertida!", + "delete":"Elimina un ticket, esto crea una transcripción cuando está habilitado. ¡Esta acción no puede ser revertida!", + "deleteNoTranscript":"Elimina este ticket sin crear una transcripción.", + "reopen":"Reabre un ticket, esto habilita la escritura en este canal de nuevo.", + "claim":"Reclama un ticket. Con esto, puedes hacer saber a tu equipo que estás manejando este ticket.", + "claimUser":"Reclama este ticket a alguien más en lugar de a ti mismo.", + "unclaim":"Libera un ticket. Con esto, puedes hacer saber a tu equipo que este ticket está libre de nuevo.", + "pin":"Ancla un ticket. Esto moverá el ticket a la parte superior y añadirá un emoji '📌' al nombre.", + "unpin":"Desancla un ticket. El ticket se quedará en su posición pero perderá el emoji '📌'.", + "move":"Mueve un ticket. Esto cambiará el tipo de este ticket.", + "moveId":"El identificador del ticket al que quieres mover.", + "rename":"Renombra un ticket. Esto cambiará el nombre del canal de este ticket.", + "renameName":"El nuevo nombre para este ticket.", + "add":"Añade un usuario a un ticket. Esto permitirá al usuario leer y escribir en este ticket.", + "addUser":"El usuario a añadir.", + "remove":"Elimina un usuario de un ticket. Esto eliminará la capacidad de leer y escribir para un usuario en este ticket.", + "removeUser":"El usuario a eliminar.", + "blacklist":"Administra la lista negra de tickets. Los usuarios añadidos a esta lista no pueden crear un ticket.", + "blacklistView":"Ver una lista de la lista negra actual.", + "blacklistAdd":"Añade un usuario a la lista negra.", + "blacklistRemove":"Elimina un usuario de la lista negra.", + "blacklistGet":"Obtén los detalles de un usuario en la lista negra.", + "blacklistGetUser":"El usuario del que obtener detalles.", + "stats":"Ver las estadísticas del bot, un miembro o un ticket.", + "statsReset":"Restablecer todas las estadísticas del bot (y empezar a contar desde cero).", + "statsGlobal":"Ver las estadísticas globales.", + "statsUser":"Ver las estadísticas de un usuario en el servidor.", + "statsUserUser":"El usuario a ver.", + "statsTicket":"Ver las estadísticas de un ticket en el servidor.", + "statsTicketTicket":"El ticket a ver.", + "clear":"Eliminar varios tickets al mismo tiempo. Se puede especificar un filtro opcional.", + "clearFilter":"valor", + "clearFilters":{ + "all":"Todo", + "open":"Abierto", + "close":"Cerrado", + "claim":"Reclamado", + "unclaim":"Libre", + "pin":"Anclado", + "unpin":"Desanclado", + "autoclose":"Cerrado automáticamente" + }, + "autoclose":"Administra el cierre automático en un ticket.", + "autocloseDisable":"Desactiva el cierre automático en este ticket.", + "autocloseEnable":"Activa el cierre automático en este ticket", + "autocloseEnableTime":"La cantidad de horas que este ticket necesita estar inactivo para cerrarlo.", + "autodelete":"Administra la eliminación automática en un ticket.", + "autodeleteDisable":"Desactiva la eliminación automática en este ticket.", + "autodeleteEnable":"Activa la eliminación automática en este ticket", + "autodeleteEnableTime":"La cantidad de días que este ticket necesita estar inactivo para eliminarlo." + }, + "helpMenu":{ + "help":"Obtén una lista de todos los comandos disponibles.", + "ticket":"Crea un ticket instantáneamente.", + "close":"Cierra un ticket, esto deshabilita la escritura en este canal.", + "delete":"Elimina un ticket, esto crea una transcripción cuando está habilitado.", + "reopen":"Reabre un ticket, esto habilita la escritura en este canal de nuevo.", + "pin":"Ancla un ticket. Esto moverá el ticket a la parte superior y añadirá un emoji '📌' al nombre.", + "unpin":"Desancla un ticket. El ticket se quedará en su posición pero perderá el emoji '📌'.", + "move":"Mueve un ticket. Esto cambiará el tipo de este ticket.", + "rename":"Renombra un ticket. Esto cambiará el nombre del canal de este ticket.", + "claim":"Reclama un ticket. Con esto, puedes hacer saber a tu equipo que estás manejando este ticket.", + "unclaim":"Liberar un ticket. Con esto, puedes hacer saber a tu equipo que este ticket está libre de nuevo.", + "add":"Añade un usuario a un ticket. Esto permitirá al usuario leer y escribir en este ticket.", + "remove":"Elimina un usuario de un ticket. Esto eliminará la capacidad de leer y escribir para un usuario en este ticket.", + "panel":"Genera un mensaje con un desplegable o botones (para la creación de tickets).", + "blacklistView":"Ver una lista de la lista negra actual.", + "blacklistAdd":"Añade un usuario a la lista negra.", + "blacklistRemove":"Elimina un usuario de la lista negra.", + "blacklistGet":"Obtén los detalles de un usuario en la lista negra.", + "statsGlobal":"Ver las estadísticas globales.", + "statsTicket":"Ver las estadísticas de un ticket en el servidor.", + "statsUser":"Ver las estadísticas de un usuario en el servidor.", + "statsReset":"Restablece todas las estadísticas del bot (y comienza a contar desde cero).", + "autocloseDisable":"Desactiva el cierre automático en este ticket.", + "autocloseEnable":"Activa el cierre automático en este ticket.", + "autodeleteDisable":"Desactiva la eliminación automática en este ticket.", + "autodeleteEnable":"Activa la eliminación automática en este ticket." + }, + "stats":{ + "scopes":{ + "global":"Estadísticas Global", + "system":"Estadisticas del Sistema", + "user":"Estadísticas del Usuario", + "ticket":"Ticket Stats", + "participants":"Participantes" + }, + "properties":{ + "ticketsCreated":"Tickets Creados", + "ticketsClosed":"Tickets Cerrados", + "ticketsDeleted":"Tickets Eliminados", + "ticketsReopened":"Tickets Reabiertos", + "ticketsAutoclosed":"Tickets Cerradps Automáticamente", + "ticketsClaimed":"Tickets Reclamados", + "ticketsPinned":"Tickets Anclados", + "ticketsMoved":"Tickets Movidos", + "usersBlacklisted":"Usuarios En Lista Negra", + "transcriptsCreated":"Transcripciones Creadas" + } + } +} \ No newline at end of file From 7dd9bf1ac0144336bf51201abeff8e6a3e23cbd3 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:45:38 +0200 Subject: [PATCH 007/157] OTv4 is now pterodactyl panel compatible! --- .gitignore | 3 +- package.json | 22 +-- plugins/example-plugin/index.ts | 2 +- src/actions/createTicket.ts | 2 +- src/actions/deleteTicket.ts | 4 +- src/backupStartup.mjs | 12 -- src/builders/embeds.ts | 4 +- src/builders/messages.ts | 2 +- src/core/api/modules/config.ts | 3 +- src/core/api/modules/language.ts | 5 +- src/core/api/modules/plugin.ts | 5 +- src/core/startup/init.ts | 2 +- src/core/startup/manageMigration.ts | 8 +- src/index.ts | 200 ++++++++++++++-------------- tsconfig.json | 11 +- 15 files changed, 141 insertions(+), 144 deletions(-) delete mode 100644 src/backupStartup.mjs diff --git a/.gitignore b/.gitignore index c28ae79..aca1716 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ otdebug.txt TEMP/ .vscode/ plugins/* -!plugins/example-plugin/ \ No newline at end of file +!plugins/example-plugin/ +dist/ \ No newline at end of file diff --git a/package.json b/package.json index 2a2f7be..f57ce59 100644 --- a/package.json +++ b/package.json @@ -3,13 +3,18 @@ "author": "DJdj Development", "version": "4.0.0", "description": "The most advanced open-source discord ticket bot with HTML transcripts, plugins, questions, claiming, pinning & more! Using discord.js v14 & JSON database! ", - "keywords": ["ticket-bot","discord","open-ticket","plugins","discord-ticket-bot"], + "keywords": [ + "ticket-bot", + "discord", + "open-ticket", + "plugins", + "discord-ticket-bot" + ], "main": "./src/index.ts", "scripts": { - "verify": "tsc -p ./tsconfig.json", - "start": "npx tsx ./src/index.ts", - "backupstart": "node ./src/backupStartup.mjs", - "test": "npm run verify && npx tsx ./src/index.ts --dev-config --dev-database" + "build": "rm -rf ./dist/ && npx tsc -p ./tsconfig.json", + "start": "npm run build && node ./dist/src/index.js", + "test": "npm run start -- --dev-config --dev-database" }, "type": "commonjs", "license": "GPL-3.0-only", @@ -17,10 +22,7 @@ "ansis": "^2.3.0", "discord.js": "^14.15.3", "formatted-json-stringify": "^1.1.0", - "tsx": "^4.17.0" - }, - "devDependencies": { - "typescript": "^5.3.3" + "typescript": "^5.5.4" }, "repository": { "type": "git", @@ -31,4 +33,4 @@ "email": "support@dj-dj.be" }, "homepage": "https://openticket.dj-dj.be" -} \ No newline at end of file +} diff --git a/plugins/example-plugin/index.ts b/plugins/example-plugin/index.ts index 94f18a3..89ffc28 100644 --- a/plugins/example-plugin/index.ts +++ b/plugins/example-plugin/index.ts @@ -10,7 +10,7 @@ if (utilities.project != "openticket") throw new api.ODPluginError("This plugin if (!utilities.isBeta) throw new api.ODPluginError("This plugin is made for the beta version of Open Ticket!") //Add Typescript autocomplete support for plugin data. (!!!OPTIONAL!!!) -declare module "../../src/core/api/api.ts" { +declare module "../../src/core/api/api.js" { export interface ODConfigManagerIds_Default { "example-plugin:config":api.ODJsonConfig } diff --git a/src/actions/createTicket.ts b/src/actions/createTicket.ts index 8bd8c36..adca753 100644 --- a/src/actions/createTicket.ts +++ b/src/actions/createTicket.ts @@ -164,7 +164,7 @@ export const registerActions = async () => { //manage bot permissions await openticket.events.get("onTicketPermissionsCreated").emit([option,openticket.permissions,channel,user]) - await (await import("../data/framework/permissionLoader.ts")).addTicketPermissions(ticket) + await (await import("../data/framework/permissionLoader.js")).addTicketPermissions(ticket) await openticket.events.get("afterTicketPermissionsCreated").emit([option,openticket.permissions,channel,user]) //export channel & ticket diff --git a/src/actions/deleteTicket.ts b/src/actions/deleteTicket.ts index 6988b5e..a50b043 100644 --- a/src/actions/deleteTicket.ts +++ b/src/actions/deleteTicket.ts @@ -63,7 +63,7 @@ export const registerActions = async () => { openticket.tickets.remove(ticket.id) //delete permissions from manager - await (await import("../data/framework/permissionLoader.ts")).removeTicketPermissions(ticket) + await (await import("../data/framework/permissionLoader.js")).removeTicketPermissions(ticket) }), new api.ODWorker("openticket:discord-logs",2,async (instance,params,source,cancel) => { //logs before channel deletion => channel might still be used in log embeds @@ -86,7 +86,7 @@ export const registerActions = async () => { await openticket.events.get("afterTicketChannelDeleted").emit([ticket,user]) //delete permissions from manager - await (await import("../data/framework/permissionLoader.ts")).removeTicketPermissions(ticket) + await (await import("../data/framework/permissionLoader.js")).removeTicketPermissions(ticket) await openticket.events.get("afterTicketDeleted").emit([ticket,user,reason]) }), diff --git a/src/backupStartup.mjs b/src/backupStartup.mjs deleted file mode 100644 index aa0b79e..0000000 --- a/src/backupStartup.mjs +++ /dev/null @@ -1,12 +0,0 @@ -/** === ALTERNATIVE STARTUP METHOD === - * This file can be used to start the bot when the default `npm start` (npx tsx src/index.ts) doesn't work! - * It is not recommended to use this by default, but it is a backup option for certain panels that don't support typescript. - * - * RECOMMENDED ON: - * - pterodactyl based panels - * - pebblehost - * - and more - */ - -import "tsx" -import("./index.ts") \ No newline at end of file diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts index 6923c63..532f335 100644 --- a/src/builders/embeds.ts +++ b/src/builders/embeds.ts @@ -500,7 +500,7 @@ const panelEmbeds = () => { if (panel.get("openticket:describe-options-in-embed-description").value){ //describe options in description - const text = (await import("../data/openticket/panelLoader.ts")).describePanelOptions("text",panel) + const text = (await import("../data/openticket/panelLoader.js")).describePanelOptions("text",panel) instance.setDescription(embedOptions.description+"\n\n"+text) }else if (embedOptions.description){ instance.setDescription(embedOptions.description) @@ -512,7 +512,7 @@ const panelEmbeds = () => { if (panel.get("openticket:describe-options-in-embed-fields").value){ //describe options in fields - const fields = (await import("../data/openticket/panelLoader.ts")).describePanelOptions("fields",panel) + const fields = (await import("../data/openticket/panelLoader.js")).describePanelOptions("fields",panel) instance.setFields(fields) }else if(embedOptions.fields.length > 0){ instance.setFields(embedOptions.fields) diff --git a/src/builders/messages.ts b/src/builders/messages.ts index dfb0f1a..b416bd6 100644 --- a/src/builders/messages.ts +++ b/src/builders/messages.ts @@ -569,7 +569,7 @@ const panelMessages = () => { const text = panel.get("openticket:text").value if (panel.get("openticket:describe-options-in-text").value){ //describe options in text - const describeText = (await import("../data/openticket/panelLoader.ts")).describePanelOptions("text",panel) + const describeText = (await import("../data/openticket/panelLoader.js")).describePanelOptions("text",panel) instance.setContent(text+"\n\n"+describeText) }else if (text){ instance.setContent(text) diff --git a/src/core/api/modules/config.ts b/src/core/api/modules/config.ts index 95edbb2..65a149e 100644 --- a/src/core/api/modules/config.ts +++ b/src/core/api/modules/config.ts @@ -4,6 +4,7 @@ import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base" import nodepath from "path" import { ODDebugger } from "./console" +import fs from "fs" /**## ODConfigManager `class` * This is an open ticket config manager. @@ -88,7 +89,7 @@ export class ODJsonConfig extends ODConfig { try { const filename = (file.endsWith(".json")) ? file : file+".json" this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./config/",filename) - this.data = customPath ? require(nodepath.join("../../../../",customPath,filename)) : require(nodepath.join("../../../../config",filename)) + this.data = JSON.parse(fs.readFileSync(this.file).toString()) }catch{ throw new ODSystemError("config \""+nodepath.join("./",customPath ?? "",file)+"\" doesn't exist!") } diff --git a/src/core/api/modules/language.ts b/src/core/api/modules/language.ts index 806c99e..aed5821 100644 --- a/src/core/api/modules/language.ts +++ b/src/core/api/modules/language.ts @@ -4,6 +4,7 @@ import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base" import nodepath from "path" import { ODDebugger } from "./console" +import fs from "fs" export class ODLanguage extends ODManagerData { file: string @@ -17,10 +18,10 @@ export class ODLanguage extends ODManagerData { constructor(id:ODValidId, file:string, customPath?:string){ super(id) - this.file = file try{ const filename = (file.endsWith(".json")) ? file : file+".json" - this.data = customPath ? require(nodepath.join("../../../../",customPath,filename)) : require(nodepath.join("../../../../languages",filename)) + this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./languages/",filename) + this.data = JSON.parse(fs.readFileSync(this.file).toString()) }catch{ throw new ODSystemError("[API ERROR] Language \""+file+"\" doesn't exist!") } diff --git a/src/core/api/modules/plugin.ts b/src/core/api/modules/plugin.ts index fc17aaa..e73299d 100644 --- a/src/core/api/modules/plugin.ts +++ b/src/core/api/modules/plugin.ts @@ -84,13 +84,14 @@ export class ODPlugin extends ODManagerData { //Get the startfile location relative to the ./plugins/ directory getStartFile(){ - return nodepath.join(this.dir,this.data.startFile) + const newFile = this.data.startFile.replace(/\.ts$/,".js") + return nodepath.join(this.dir,newFile) } /**Execute this plugin. Returns `false` on crash. */ async execute(debug:ODDebugger,force?:boolean): Promise { if ((this.enabled && !this.crashed) || force){ try{ - await require(nodepath.join("../../../../plugins/",this.getStartFile())) + await import(nodepath.join("../../../../plugins/",this.getStartFile())) debug.console.log("Plugin \""+this.id.value+"\" loaded successfully!","plugin") this.executed = true return true diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index 12aea74..a408ff4 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -29,7 +29,7 @@ const moduleInstalled = (id:string, throwError:boolean) => { moduleInstalled("discord.js",true) moduleInstalled("ansis",true) moduleInstalled("formatted-json-stringify",true) -moduleInstalled("tsx",true) +moduleInstalled("typescript",true) tempError() //init API diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index b090bca..8bc68de 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -33,10 +33,10 @@ export const loadVersionMigrationSystem = async () => { const preloadMigrationContext = async () => { openticket.debug.debug("-- MIGRATION CONTEXT START --") - await (await import("../../data/framework/flagLoader.ts")).loadAllFlags() + await (await import("../../data/framework/flagLoader.js")).loadAllFlags() openticket.flags.init() - await (await import("../../data/framework/configLoader.ts")).loadAllConfigs() - await (await import("../../data/framework/databaseLoader.ts")).loadAllDatabases() + await (await import("../../data/framework/configLoader.js")).loadAllConfigs() + await (await import("../../data/framework/databaseLoader.js")).loadAllDatabases() openticket.debug.visible = true } @@ -58,7 +58,7 @@ const isMigrationRequired = (): false|api.ODVersion => { } const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { - const migrations = (await import("./migration.ts")).migrations + const migrations = (await import("./migration.js")).migrations migrations.sort((a,b) => { const comparison = a.version.compare(b.version) if (comparison == "equal") return 0 diff --git a/src/index.ts b/src/index.ts index 6847de1..a9a8d7f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -41,7 +41,7 @@ import ansis from "ansis" /**The main sequence of Open Ticket. Runs `async` */ const main = async () => { //load all events - (await import("./data/framework/eventLoader.ts")).loadAllEvents() + (await import("./data/framework/eventLoader.js")).loadAllEvents() //error handling system process.on("uncaughtException",async (error,origin) => { @@ -76,11 +76,11 @@ const main = async () => { }) //handle data migration - await (await import("./core/startup/manageMigration.ts")).loadVersionMigrationSystem() + await (await import("./core/startup/manageMigration.js")).loadVersionMigrationSystem() //load plugins if (openticket.defaults.getDefault("pluginLoading")){ - await (await import("./core/startup/pluginLauncher.ts")).loadAllPlugins() + await (await import("./core/startup/pluginLauncher.js")).loadAllPlugins() } await openticket.events.get("afterPluginsLoaded").emit([openticket.plugins]) @@ -103,7 +103,7 @@ const main = async () => { //load flags openticket.log("Loading flags...","system") if (openticket.defaults.getDefault("flagLoading")){ - await (await import("./data/framework/flagLoader.ts")).loadAllFlags() + await (await import("./data/framework/flagLoader.js")).loadAllFlags() } await openticket.events.get("onFlagLoad").emit([openticket.flags]) await openticket.events.get("afterFlagsLoaded").emit([openticket.flags]) @@ -125,7 +125,7 @@ const main = async () => { //load config openticket.log("Loading configs...","system") if (openticket.defaults.getDefault("configLoading")){ - await (await import("./data/framework/configLoader.ts")).loadAllConfigs() + await (await import("./data/framework/configLoader.js")).loadAllConfigs() } await openticket.events.get("onConfigLoad").emit([openticket.configs]) await openticket.events.get("afterConfigsLoaded").emit([openticket.configs]) @@ -136,7 +136,7 @@ const main = async () => { //load database openticket.log("Loading databases...","system") if (openticket.defaults.getDefault("databaseLoading")){ - await (await import("./data/framework/databaseLoader.ts")).loadAllDatabases() + await (await import("./data/framework/databaseLoader.js")).loadAllDatabases() } await openticket.events.get("onDatabaseLoad").emit([openticket.databases]) await openticket.events.get("afterDatabasesLoaded").emit([openticket.databases]) @@ -152,7 +152,7 @@ const main = async () => { //load language openticket.log("Loading languages...","system") if (openticket.defaults.getDefault("languageLoading")){ - await (await import("./data/framework/languageLoader.ts")).loadAllLanguages() + await (await import("./data/framework/languageLoader.js")).loadAllLanguages() } await openticket.events.get("onLanguageLoad").emit([openticket.languages]) await openticket.events.get("afterLanguagesLoaded").emit([openticket.languages]) @@ -181,14 +181,14 @@ const main = async () => { //load config checker openticket.log("Loading config checker...","system") if (openticket.defaults.getDefault("checkerLoading")){ - await (await import("./data/framework/checkerLoader.ts")).loadAllConfigCheckers() + await (await import("./data/framework/checkerLoader.js")).loadAllConfigCheckers() } await openticket.events.get("onCheckerLoad").emit([openticket.checkers]) await openticket.events.get("afterCheckersLoaded").emit([openticket.checkers]) //load config checker functions if (openticket.defaults.getDefault("checkerFunctionLoading")){ - await (await import("./data/framework/checkerLoader.ts")).loadAllConfigCheckerFunctions() + await (await import("./data/framework/checkerLoader.js")).loadAllConfigCheckerFunctions() } await openticket.events.get("onCheckerFunctionLoad").emit([openticket.checkers.functions,openticket.checkers]) await openticket.events.get("afterCheckerFunctionsLoaded").emit([openticket.checkers.functions,openticket.checkers]) @@ -202,7 +202,7 @@ const main = async () => { //load config checker translations if (openticket.defaults.getDefault("checkerTranslationLoading")){ - await (await import("./data/framework/checkerLoader.ts")).loadAllConfigCheckerTranslations() + await (await import("./data/framework/checkerLoader.js")).loadAllConfigCheckerTranslations() } await openticket.events.get("onCheckerTranslationLoad").emit([openticket.checkers.translation,((generalConfig && generalConfig.data.system && generalConfig.data.system.useTranslatedConfigChecker) ? generalConfig.data.system.useTranslatedConfigChecker : false),openticket.checkers]) await openticket.events.get("afterCheckerTranslationsLoaded").emit([openticket.checkers.translation,openticket.checkers]) @@ -351,7 +351,7 @@ const main = async () => { //load slash commands openticket.log("Loading slash commands...","system") if (openticket.defaults.getDefault("slashCommandLoading")){ - await (await import("./data/framework/commandLoader.ts")).loadAllSlashCommands() + await (await import("./data/framework/commandLoader.js")).loadAllSlashCommands() } await openticket.events.get("onSlashCommandLoad").emit([openticket.client.slashCommands,openticket.client]) await openticket.events.get("afterSlashCommandsLoaded").emit([openticket.client.slashCommands,openticket.client]) @@ -377,7 +377,7 @@ const main = async () => { //load text commands openticket.log("Loading text commands...","system") if (openticket.defaults.getDefault("textCommandLoading")){ - await (await import("./data/framework/commandLoader.ts")).loadAllTextCommands() + await (await import("./data/framework/commandLoader.js")).loadAllTextCommands() } await openticket.events.get("onTextCommandLoad").emit([openticket.client.textCommands,openticket.client]) await openticket.events.get("afterTextCommandsLoaded").emit([openticket.client.textCommands,openticket.client]) @@ -403,7 +403,7 @@ const main = async () => { //load questions openticket.log("Loading questions...","system") if (openticket.defaults.getDefault("questionLoading")){ - await (await import("./data/openticket/questionLoader.ts")).loadAllQuestions() + await (await import("./data/openticket/questionLoader.js")).loadAllQuestions() } await openticket.events.get("onQuestionLoad").emit([openticket.questions]) await openticket.events.get("afterQuestionsLoaded").emit([openticket.questions]) @@ -411,7 +411,7 @@ const main = async () => { //load options openticket.log("Loading options...","system") if (openticket.defaults.getDefault("optionLoading")){ - await (await import("./data/openticket/optionLoader.ts")).loadAllOptions() + await (await import("./data/openticket/optionLoader.js")).loadAllOptions() } await openticket.events.get("onOptionLoad").emit([openticket.options]) await openticket.events.get("afterOptionsLoaded").emit([openticket.options]) @@ -419,7 +419,7 @@ const main = async () => { //load panels openticket.log("Loading panels...","system") if (openticket.defaults.getDefault("panelLoading")){ - await (await import("./data/openticket/panelLoader.ts")).loadAllPanels() + await (await import("./data/openticket/panelLoader.js")).loadAllPanels() } await openticket.events.get("onPanelLoad").emit([openticket.panels]) await openticket.events.get("afterPanelsLoaded").emit([openticket.panels]) @@ -428,7 +428,7 @@ const main = async () => { openticket.log("Loading tickets...","system") if (openticket.defaults.getDefault("ticketLoading")){ openticket.tickets.useGuild(openticket.client.mainServer) - await (await import("./data/openticket/ticketLoader.ts")).loadAllTickets() + await (await import("./data/openticket/ticketLoader.js")).loadAllTickets() } await openticket.events.get("onTicketLoad").emit([openticket.tickets]) await openticket.events.get("afterTicketsLoaded").emit([openticket.tickets]) @@ -436,7 +436,7 @@ const main = async () => { //load roles openticket.log("Loading roles...","system") if (openticket.defaults.getDefault("roleLoading")){ - await (await import("./data/openticket/roleLoader.ts")).loadAllRoles() + await (await import("./data/openticket/roleLoader.js")).loadAllRoles() } await openticket.events.get("onRoleLoad").emit([openticket.roles]) await openticket.events.get("afterRolesLoaded").emit([openticket.roles]) @@ -444,7 +444,7 @@ const main = async () => { //load blacklist openticket.log("Loading blacklist...","system") if (openticket.defaults.getDefault("blacklistLoading")){ - await (await import("./data/openticket/blacklistLoader.ts")).loadAllBlacklistedUsers() + await (await import("./data/openticket/blacklistLoader.js")).loadAllBlacklistedUsers() } await openticket.events.get("onBlacklistLoad").emit([openticket.blacklist]) await openticket.events.get("afterBlacklistLoaded").emit([openticket.blacklist]) @@ -452,14 +452,14 @@ const main = async () => { //load transcript compilers openticket.log("Loading transcripts...","system") if (openticket.defaults.getDefault("transcriptCompilerLoading")){ - await (await import("./data/openticket/transcriptLoader.ts")).loadAllTranscriptCompilers() + await (await import("./data/openticket/transcriptLoader.js")).loadAllTranscriptCompilers() } await openticket.events.get("onTranscriptCompilerLoad").emit([openticket.transcripts]) await openticket.events.get("afterTranscriptCompilersLoaded").emit([openticket.transcripts]) //load transcript history if (openticket.defaults.getDefault("transcriptHistoryLoading")){ - await (await import("./data/openticket/transcriptLoader.ts")).loadTranscriptHistory() + await (await import("./data/openticket/transcriptLoader.js")).loadTranscriptHistory() } await openticket.events.get("onTranscriptHistoryLoad").emit([openticket.transcripts]) await openticket.events.get("afterTranscriptHistoryLoaded").emit([openticket.transcripts]) @@ -467,7 +467,7 @@ const main = async () => { //load button builders openticket.log("Loading buttons...","system") if (openticket.defaults.getDefault("buttonBuildersLoading")){ - await (await import("./builders/buttons.ts")).registerAllButtons() + await (await import("./builders/buttons.js")).registerAllButtons() } await openticket.events.get("onButtonBuilderLoad").emit([openticket.builders.buttons,openticket.builders,openticket.actions]) await openticket.events.get("afterButtonBuildersLoaded").emit([openticket.builders.buttons,openticket.builders,openticket.actions]) @@ -475,7 +475,7 @@ const main = async () => { //load dropdown builders openticket.log("Loading dropdowns...","system") if (openticket.defaults.getDefault("dropdownBuildersLoading")){ - await (await import("./builders/dropdowns.ts")).registerAllDropdowns() + await (await import("./builders/dropdowns.js")).registerAllDropdowns() } await openticket.events.get("onDropdownBuilderLoad").emit([openticket.builders.dropdowns,openticket.builders,openticket.actions]) await openticket.events.get("afterDropdownBuildersLoaded").emit([openticket.builders.dropdowns,openticket.builders,openticket.actions]) @@ -483,7 +483,7 @@ const main = async () => { //load file builders openticket.log("Loading files...","system") if (openticket.defaults.getDefault("fileBuildersLoading")){ - await (await import("./builders/files.ts")).registerAllFiles() + await (await import("./builders/files.js")).registerAllFiles() } await openticket.events.get("onFileBuilderLoad").emit([openticket.builders.files,openticket.builders,openticket.actions]) await openticket.events.get("afterFileBuildersLoaded").emit([openticket.builders.files,openticket.builders,openticket.actions]) @@ -491,7 +491,7 @@ const main = async () => { //load embed builders openticket.log("Loading embeds...","system") if (openticket.defaults.getDefault("embedBuildersLoading")){ - await (await import("./builders/embeds.ts")).registerAllEmbeds() + await (await import("./builders/embeds.js")).registerAllEmbeds() } await openticket.events.get("onEmbedBuilderLoad").emit([openticket.builders.embeds,openticket.builders,openticket.actions]) await openticket.events.get("afterEmbedBuildersLoaded").emit([openticket.builders.embeds,openticket.builders,openticket.actions]) @@ -499,7 +499,7 @@ const main = async () => { //load message builders openticket.log("Loading messages...","system") if (openticket.defaults.getDefault("messageBuildersLoading")){ - await (await import("./builders/messages.ts")).registerAllMessages() + await (await import("./builders/messages.js")).registerAllMessages() } await openticket.events.get("onMessageBuilderLoad").emit([openticket.builders.messages,openticket.builders,openticket.actions]) await openticket.events.get("afterMessageBuildersLoaded").emit([openticket.builders.messages,openticket.builders,openticket.actions]) @@ -507,7 +507,7 @@ const main = async () => { //load modal builders openticket.log("Loading modals...","system") if (openticket.defaults.getDefault("modalBuildersLoading")){ - await (await import("./builders/modals.ts")).registerAllModals() + await (await import("./builders/modals.js")).registerAllModals() } await openticket.events.get("onModalBuilderLoad").emit([openticket.builders.modals,openticket.builders,openticket.actions]) await openticket.events.get("afterModalBuildersLoaded").emit([openticket.builders.modals,openticket.builders,openticket.actions]) @@ -515,25 +515,25 @@ const main = async () => { //load command responders openticket.log("Loading command responders...","system") if (openticket.defaults.getDefault("commandRespondersLoading")){ - await (await import("./commands/help.ts")).registerCommandResponders() - await (await import("./commands/stats.ts")).registerCommandResponders() - await (await import("./commands/panel.ts")).registerCommandResponders() - await (await import("./commands/ticket.ts")).registerCommandResponders() - await (await import("./commands/blacklist.ts")).registerCommandResponders() - await (await import("./commands/close.ts")).registerCommandResponders() - await (await import("./commands/reopen.ts")).registerCommandResponders() - await (await import("./commands/delete.ts")).registerCommandResponders() - await (await import("./commands/claim.ts")).registerCommandResponders() - await (await import("./commands/unclaim.ts")).registerCommandResponders() - await (await import("./commands/pin.ts")).registerCommandResponders() - await (await import("./commands/unpin.ts")).registerCommandResponders() - await (await import("./commands/rename.ts")).registerCommandResponders() - await (await import("./commands/move.ts")).registerCommandResponders() - await (await import("./commands/add.ts")).registerCommandResponders() - await (await import("./commands/remove.ts")).registerCommandResponders() - await (await import("./commands/clear.ts")).registerCommandResponders() - await (await import("./commands/autoclose.ts")).registerCommandResponders() - await (await import("./commands/autodelete.ts")).registerCommandResponders() + await (await import("./commands/help.js")).registerCommandResponders() + await (await import("./commands/stats.js")).registerCommandResponders() + await (await import("./commands/panel.js")).registerCommandResponders() + await (await import("./commands/ticket.js")).registerCommandResponders() + await (await import("./commands/blacklist.js")).registerCommandResponders() + await (await import("./commands/close.js")).registerCommandResponders() + await (await import("./commands/reopen.js")).registerCommandResponders() + await (await import("./commands/delete.js")).registerCommandResponders() + await (await import("./commands/claim.js")).registerCommandResponders() + await (await import("./commands/unclaim.js")).registerCommandResponders() + await (await import("./commands/pin.js")).registerCommandResponders() + await (await import("./commands/unpin.js")).registerCommandResponders() + await (await import("./commands/rename.js")).registerCommandResponders() + await (await import("./commands/move.js")).registerCommandResponders() + await (await import("./commands/add.js")).registerCommandResponders() + await (await import("./commands/remove.js")).registerCommandResponders() + await (await import("./commands/clear.js")).registerCommandResponders() + await (await import("./commands/autoclose.js")).registerCommandResponders() + await (await import("./commands/autodelete.js")).registerCommandResponders() } await openticket.events.get("onCommandResponderLoad").emit([openticket.responders.commands,openticket.responders,openticket.actions]) await openticket.events.get("afterCommandRespondersLoaded").emit([openticket.responders.commands,openticket.responders,openticket.actions]) @@ -541,19 +541,19 @@ const main = async () => { //load button responders openticket.log("Loading button responders...","system") if (openticket.defaults.getDefault("buttonRespondersLoading")){ - await (await import("./actions/handleVerifyBar.ts")).registerButtonResponders() - await (await import("./actions/handleTranscriptErrors.ts")).registerButtonResponders() - await (await import("./commands/help.ts")).registerButtonResponders() - await (await import("./commands/ticket.ts")).registerButtonResponders() - await (await import("./commands/close.ts")).registerButtonResponders() - await (await import("./commands/reopen.ts")).registerButtonResponders() - await (await import("./commands/delete.ts")).registerButtonResponders() - await (await import("./commands/claim.ts")).registerButtonResponders() - await (await import("./commands/unclaim.ts")).registerButtonResponders() - await (await import("./commands/pin.ts")).registerButtonResponders() - await (await import("./commands/unpin.ts")).registerButtonResponders() - await (await import("./commands/role.ts")).registerButtonResponders() - await (await import("./commands/clear.ts")).registerButtonResponders() + await (await import("./actions/handleVerifyBar.js")).registerButtonResponders() + await (await import("./actions/handleTranscriptErrors.js")).registerButtonResponders() + await (await import("./commands/help.js")).registerButtonResponders() + await (await import("./commands/ticket.js")).registerButtonResponders() + await (await import("./commands/close.js")).registerButtonResponders() + await (await import("./commands/reopen.js")).registerButtonResponders() + await (await import("./commands/delete.js")).registerButtonResponders() + await (await import("./commands/claim.js")).registerButtonResponders() + await (await import("./commands/unclaim.js")).registerButtonResponders() + await (await import("./commands/pin.js")).registerButtonResponders() + await (await import("./commands/unpin.js")).registerButtonResponders() + await (await import("./commands/role.js")).registerButtonResponders() + await (await import("./commands/clear.js")).registerButtonResponders() } await openticket.events.get("onButtonResponderLoad").emit([openticket.responders.buttons,openticket.responders,openticket.actions]) await openticket.events.get("afterButtonRespondersLoaded").emit([openticket.responders.buttons,openticket.responders,openticket.actions]) @@ -561,7 +561,7 @@ const main = async () => { //load dropdown responders openticket.log("Loading dropdown responders...","system") if (openticket.defaults.getDefault("dropdownRespondersLoading")){ - await (await import("./commands/ticket.ts")).registerDropdownResponders() + await (await import("./commands/ticket.js")).registerDropdownResponders() } await openticket.events.get("onDropdownResponderLoad").emit([openticket.responders.dropdowns,openticket.responders,openticket.actions]) await openticket.events.get("afterDropdownRespondersLoaded").emit([openticket.responders.dropdowns,openticket.responders,openticket.actions]) @@ -569,14 +569,14 @@ const main = async () => { //load modal responders openticket.log("Loading modal responders...","system") if (openticket.defaults.getDefault("modalRespondersLoading")){ - await (await import("./commands/ticket.ts")).registerModalResponders() - await (await import("./commands/close.ts")).registerModalResponders() - await (await import("./commands/reopen.ts")).registerModalResponders() - await (await import("./commands/delete.ts")).registerModalResponders() - await (await import("./commands/claim.ts")).registerModalResponders() - await (await import("./commands/unclaim.ts")).registerModalResponders() - await (await import("./commands/pin.ts")).registerModalResponders() - await (await import("./commands/unpin.ts")).registerModalResponders() + await (await import("./commands/ticket.js")).registerModalResponders() + await (await import("./commands/close.js")).registerModalResponders() + await (await import("./commands/reopen.js")).registerModalResponders() + await (await import("./commands/delete.js")).registerModalResponders() + await (await import("./commands/claim.js")).registerModalResponders() + await (await import("./commands/unclaim.js")).registerModalResponders() + await (await import("./commands/pin.js")).registerModalResponders() + await (await import("./commands/unpin.js")).registerModalResponders() } await openticket.events.get("onModalResponderLoad").emit([openticket.responders.modals,openticket.responders,openticket.actions]) await openticket.events.get("afterModalRespondersLoaded").emit([openticket.responders.modals,openticket.responders,openticket.actions]) @@ -584,22 +584,22 @@ const main = async () => { //load actions openticket.log("Loading actions...","system") if (openticket.defaults.getDefault("actionsLoading")){ - await (await import("./actions/createTicketPermissions.ts")).registerActions() - await (await import("./actions/createTranscript.ts")).registerActions() - await (await import("./actions/createTicket.ts")).registerActions() - await (await import("./actions/closeTicket.ts")).registerActions() - await (await import("./actions/deleteTicket.ts")).registerActions() - await (await import("./actions/reopenTicket.ts")).registerActions() - await (await import("./actions/claimTicket.ts")).registerActions() - await (await import("./actions/unclaimTicket.ts")).registerActions() - await (await import("./actions/pinTicket.ts")).registerActions() - await (await import("./actions/unpinTicket.ts")).registerActions() - await (await import("./actions/renameTicket.ts")).registerActions() - await (await import("./actions/moveTicket.ts")).registerActions() - await (await import("./actions/addTicketUser.ts")).registerActions() - await (await import("./actions/removeTicketUser.ts")).registerActions() - await (await import("./actions/reactionRole.ts")).registerActions() - await (await import("./actions/clearTickets.ts")).registerActions() + await (await import("./actions/createTicketPermissions.js")).registerActions() + await (await import("./actions/createTranscript.js")).registerActions() + await (await import("./actions/createTicket.js")).registerActions() + await (await import("./actions/closeTicket.js")).registerActions() + await (await import("./actions/deleteTicket.js")).registerActions() + await (await import("./actions/reopenTicket.js")).registerActions() + await (await import("./actions/claimTicket.js")).registerActions() + await (await import("./actions/unclaimTicket.js")).registerActions() + await (await import("./actions/pinTicket.js")).registerActions() + await (await import("./actions/unpinTicket.js")).registerActions() + await (await import("./actions/renameTicket.js")).registerActions() + await (await import("./actions/moveTicket.js")).registerActions() + await (await import("./actions/addTicketUser.js")).registerActions() + await (await import("./actions/removeTicketUser.js")).registerActions() + await (await import("./actions/reactionRole.js")).registerActions() + await (await import("./actions/clearTickets.js")).registerActions() } await openticket.events.get("onActionLoad").emit([openticket.actions]) await openticket.events.get("afterActionsLoaded").emit([openticket.actions]) @@ -607,13 +607,13 @@ const main = async () => { //load verifybars openticket.log("Loading verifybars...","system") if (openticket.defaults.getDefault("verifyBarsLoading")){ - await (await import("./actions/closeTicket.ts")).registerVerifyBars() - await (await import("./actions/deleteTicket.ts")).registerVerifyBars() - await (await import("./actions/reopenTicket.ts")).registerVerifyBars() - await (await import("./actions/claimTicket.ts")).registerVerifyBars() - await (await import("./actions/unclaimTicket.ts")).registerVerifyBars() - await (await import("./actions/pinTicket.ts")).registerVerifyBars() - await (await import("./actions/unpinTicket.ts")).registerVerifyBars() + await (await import("./actions/closeTicket.js")).registerVerifyBars() + await (await import("./actions/deleteTicket.js")).registerVerifyBars() + await (await import("./actions/reopenTicket.js")).registerVerifyBars() + await (await import("./actions/claimTicket.js")).registerVerifyBars() + await (await import("./actions/unclaimTicket.js")).registerVerifyBars() + await (await import("./actions/pinTicket.js")).registerVerifyBars() + await (await import("./actions/unpinTicket.js")).registerVerifyBars() } await openticket.events.get("onVerifyBarLoad").emit([openticket.verifybars]) await openticket.events.get("afterVerifyBarsLoaded").emit([openticket.verifybars]) @@ -621,7 +621,7 @@ const main = async () => { //load permissions openticket.log("Loading permissions...","system") if (openticket.defaults.getDefault("permissionsLoading")){ - await (await import("./data/framework/permissionLoader.ts")).loadAllPermissions() + await (await import("./data/framework/permissionLoader.js")).loadAllPermissions() } await openticket.events.get("onPermissionLoad").emit([openticket.permissions]) await openticket.events.get("afterPermissionsLoaded").emit([openticket.permissions]) @@ -629,7 +629,7 @@ const main = async () => { //load posts openticket.log("Loading posts...","system") if (openticket.defaults.getDefault("postsLoading")){ - await (await import("./data/framework/postLoader.ts")).loadAllPosts() + await (await import("./data/framework/postLoader.js")).loadAllPosts() } await openticket.events.get("onPostLoad").emit([openticket.posts]) await openticket.events.get("afterPostsLoaded").emit([openticket.posts]) @@ -644,7 +644,7 @@ const main = async () => { //load cooldowns openticket.log("Loading cooldowns...","system") if (openticket.defaults.getDefault("cooldownsLoading")){ - await (await import("./data/framework/cooldownLoader.ts")).loadAllCooldowns() + await (await import("./data/framework/cooldownLoader.js")).loadAllCooldowns() } await openticket.events.get("onCooldownLoad").emit([openticket.cooldowns]) await openticket.events.get("afterCooldownsLoaded").emit([openticket.cooldowns]) @@ -659,14 +659,14 @@ const main = async () => { //load help menu categories openticket.log("Loading help menu...","system") if (openticket.defaults.getDefault("helpMenuCategoryLoading")){ - await (await import("./data/framework/helpMenuLoader.ts")).loadAllHelpMenuCategories() + await (await import("./data/framework/helpMenuLoader.js")).loadAllHelpMenuCategories() } await openticket.events.get("onHelpMenuCategoryLoad").emit([openticket.helpmenu]) await openticket.events.get("afterHelpMenuCategoriesLoaded").emit([openticket.helpmenu]) //load help menu components if (openticket.defaults.getDefault("helpMenuComponentLoading")){ - await (await import("./data/framework/helpMenuLoader.ts")).loadAllHelpMenuComponents() + await (await import("./data/framework/helpMenuLoader.js")).loadAllHelpMenuComponents() } await openticket.events.get("onHelpMenuComponentLoad").emit([openticket.helpmenu]) await openticket.events.get("afterHelpMenuComponentsLoaded").emit([openticket.helpmenu]) @@ -675,14 +675,14 @@ const main = async () => { openticket.log("Loading stats...","system") if (openticket.defaults.getDefault("statScopesLoading")){ openticket.stats.useDatabase(openticket.databases.get("openticket:stats")) - await (await import("./data/framework/statLoader.ts")).loadAllStatScopes() + await (await import("./data/framework/statLoader.js")).loadAllStatScopes() } await openticket.events.get("onStatScopeLoad").emit([openticket.stats]) await openticket.events.get("afterStatScopesLoaded").emit([openticket.stats]) //load stats if (openticket.defaults.getDefault("statLoading")){ - await (await import("./data/framework/statLoader.ts")).loadAllStats() + await (await import("./data/framework/statLoader.js")).loadAllStats() } await openticket.events.get("onStatLoad").emit([openticket.stats]) await openticket.events.get("afterStatsLoaded").emit([openticket.stats]) @@ -697,7 +697,7 @@ const main = async () => { //load code openticket.log("Loading code...","system") if (openticket.defaults.getDefault("codeLoading")){ - await (await import("./data/framework/codeLoader.ts")).loadAllCode() + await (await import("./data/framework/codeLoader.js")).loadAllCode() } await openticket.events.get("onCodeLoad").emit([openticket.code]) await openticket.events.get("afterCodeLoaded").emit([openticket.code]) @@ -715,7 +715,7 @@ const main = async () => { //load livestatus sources openticket.log("Loading livestatus...","system") if (openticket.defaults.getDefault("liveStatusLoading")){ - await (await import("./data/framework/liveStatusLoader.ts")).loadAllLiveStatusSources() + await (await import("./data/framework/liveStatusLoader.js")).loadAllLiveStatusSources() } await openticket.events.get("onLiveStatusSourceLoad").emit([openticket.livestatus]) await openticket.events.get("afterLiveStatusSourcesLoaded").emit([openticket.livestatus]) @@ -723,7 +723,7 @@ const main = async () => { //load startscreen openticket.log("Loading startscreen...","system") if (openticket.defaults.getDefault("startScreenLoading")){ - await (await import("./data/framework/startScreenLoader.ts")).loadAllStartScreenComponents() + await (await import("./data/framework/startScreenLoader.js")).loadAllStartScreenComponents() } await openticket.events.get("onStartScreenLoad").emit([openticket.startscreen]) await openticket.events.get("afterStartScreensLoaded").emit([openticket.startscreen]) diff --git a/tsconfig.json b/tsconfig.json index 3398e8e..50bcbcf 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,17 @@ { "compilerOptions": { "target": "ES2022", - "rootDir": "./src/", + "rootDirs":[ + "./src", + "./plugins" + ], "outDir": "./dist/", "module": "NodeNext", "moduleResolution": "NodeNext", "typeRoots": ["./node_modules/@types","./plugins/*/"], - "noEmit": true, - "allowImportingTsExtensions": true, + "noEmit": false, + "allowImportingTsExtensions": false, "allowJs": false, "checkJs": false, @@ -18,5 +21,5 @@ "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, - "include": ["./src/*","./src/**/*"] + "include": ["./src/*","./src/**/*","./plugins/*","./plugins/**/*"] } \ No newline at end of file From 5512bc1134bc5455245c5c70fed1433e7f46fb81 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:09:29 +0200 Subject: [PATCH 008/157] Pterodactyl panel support part 2 --- index.js | 11 +++++++++++ package.json | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 index.js diff --git a/index.js b/index.js new file mode 100644 index 0000000..4d0255c --- /dev/null +++ b/index.js @@ -0,0 +1,11 @@ +//PLEASE COMPILE USING "npm run build" BEFORE STARTING THE BOT! +//OR USE "npm start" TO INSTANTLY COMPILE & START THE BOT! + +const fs = require("fs") +const child = require("child_process") +if (!fs.existsSync("./dist/src/index.js")){ + console.log("Compiling the bot...") + child.execSync("npm run build",{timeout:10000}) + console.log("\n\nFinished compilation!") +} +require("./dist/src/index") \ No newline at end of file diff --git a/package.json b/package.json index f57ce59..03dc02d 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,10 @@ "plugins", "discord-ticket-bot" ], - "main": "./src/index.ts", + "main": "index.js", "scripts": { "build": "rm -rf ./dist/ && npx tsc -p ./tsconfig.json", - "start": "npm run build && node ./dist/src/index.js", + "start": "npm run build && node index.js", "test": "npm run start -- --dev-config --dev-database" }, "type": "commonjs", From b3cd37bb4bc0a426764f2344da5d56a14ddd10b7 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:13:27 +0200 Subject: [PATCH 009/157] Update index.js --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 4d0255c..69c55cb 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,7 @@ const fs = require("fs") const child = require("child_process") if (!fs.existsSync("./dist/src/index.js")){ console.log("Compiling the bot...") - child.execSync("npm run build",{timeout:10000}) + child.execSync("npm run build",{timeout:60000}) console.log("\n\nFinished compilation!") } require("./dist/src/index") \ No newline at end of file From 5e2e0417dc7dbb98dc56f85b135470dadbcf43cc Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 22 Aug 2024 16:17:22 +0200 Subject: [PATCH 010/157] Update index.js --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 69c55cb..d98db68 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,7 @@ const fs = require("fs") const child = require("child_process") if (!fs.existsSync("./dist/src/index.js")){ console.log("Compiling the bot...") - child.execSync("npm run build",{timeout:60000}) + child.execSync("npm run build") console.log("\n\nFinished compilation!") } require("./dist/src/index") \ No newline at end of file From 177ab95dba5c49111436201d1c5a25eddccb0273 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 22 Aug 2024 21:22:19 +0200 Subject: [PATCH 011/157] Fixed permission error & preparing for win build --- index.js | 14 +++++++++----- package.json | 4 ++-- src/core/api/modules/config.ts | 5 +++-- src/core/api/modules/language.ts | 5 +++-- src/data/framework/permissionLoader.ts | 4 +++- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/index.js b/index.js index d98db68..5f2ba69 100644 --- a/index.js +++ b/index.js @@ -3,9 +3,13 @@ const fs = require("fs") const child = require("child_process") -if (!fs.existsSync("./dist/src/index.js")){ - console.log("Compiling the bot...") - child.execSync("npm run build") - console.log("\n\nFinished compilation!") -} + +console.log("Removing prebuilds...") +fs.rmSync("./dist",{recursive:true,force:true}) + +console.log("Compiling the bot...") +//exit when only compilation is required +if (process.argv.includes("-%-compile")) process.exit(0) + +//start the bot require("./dist/src/index") \ No newline at end of file diff --git a/package.json b/package.json index 03dc02d..9842d92 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,8 @@ ], "main": "index.js", "scripts": { - "build": "rm -rf ./dist/ && npx tsc -p ./tsconfig.json", - "start": "npm run build && node index.js", + "build": "node index.js -%-compile && npx tsc -p ./tsconfig.json", + "start": "npm run build && node ./dist/src/index.js", "test": "npm run start -- --dev-config --dev-database" }, "type": "commonjs", diff --git a/src/core/api/modules/config.ts b/src/core/api/modules/config.ts index 65a149e..a875946 100644 --- a/src/core/api/modules/config.ts +++ b/src/core/api/modules/config.ts @@ -90,8 +90,9 @@ export class ODJsonConfig extends ODConfig { const filename = (file.endsWith(".json")) ? file : file+".json" this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./config/",filename) this.data = JSON.parse(fs.readFileSync(this.file).toString()) - }catch{ - throw new ODSystemError("config \""+nodepath.join("./",customPath ?? "",file)+"\" doesn't exist!") + }catch(err){ + process.emit("uncaughtException",err) + throw new ODSystemError("Config \""+nodepath.join("./",customPath ?? "./config/",file)+"\" doesn't exist!") } } } \ No newline at end of file diff --git a/src/core/api/modules/language.ts b/src/core/api/modules/language.ts index aed5821..0a4c8c5 100644 --- a/src/core/api/modules/language.ts +++ b/src/core/api/modules/language.ts @@ -22,8 +22,9 @@ export class ODLanguage extends ODManagerData { const filename = (file.endsWith(".json")) ? file : file+".json" this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./languages/",filename) this.data = JSON.parse(fs.readFileSync(this.file).toString()) - }catch{ - throw new ODSystemError("[API ERROR] Language \""+file+"\" doesn't exist!") + }catch(err){ + process.emit("uncaughtException",err) + throw new ODSystemError("Language \""+nodepath.join("./",customPath ?? "./languages/",file)+"\" doesn't exist!") } if (this.data["_TRANSLATION"]) this.metadata = this.data["_TRANSLATION"] } diff --git a/src/data/framework/permissionLoader.ts b/src/data/framework/permissionLoader.ts index 4b080f8..5e6c4b2 100644 --- a/src/data/framework/permissionLoader.ts +++ b/src/data/framework/permissionLoader.ts @@ -63,6 +63,7 @@ export const addTicketPermissions = async (ticket:api.ODTicket) => { const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] admins.concat(readAdmins).forEach(async (admin) => { + if (openticket.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return const role = await mainServer.roles.fetch(admin) if (!role) return openticket.log("Unable to register permission for ticket admin!","error",[ {key:"roleid",value:admin} @@ -76,7 +77,8 @@ export const removeTicketPermissions = async (ticket:api.ODTicket) => { const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] - admins.concat(readAdmins).forEach(async (admin) => { + admins.concat(readAdmins).forEach(async (admin) => { + if (!openticket.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return openticket.permissions.remove("openticket:ticket-admin_"+ticket.id.value+"_"+admin) }) } \ No newline at end of file From d5295a9480e0721ab4429fdb26362b8fdd3c6f50 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Fri, 23 Aug 2024 23:19:44 +0200 Subject: [PATCH 012/157] Fixed bugs & added/updated languages! --- README.md | 2 +- languages/german.json | 16 +- languages/hungarian.json | 477 +++++++++++++++++++++++++++ package.json | 1 + src/core/api/defaults/language.ts | 1 + src/core/api/modules/checker.ts | 2 +- src/core/api/modules/defaults.ts | 7 +- src/data/framework/languageLoader.ts | 14 +- src/index.ts | 5 + 9 files changed, 510 insertions(+), 15 deletions(-) create mode 100644 languages/hungarian.json diff --git a/README.md b/README.md index 6323e18..c073b4c 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇨🇿 Czech |spyeye_ |🟢 Up To Date | |🇩🇪 German |benzorich |🟢 Up To Date | |❓ Catalan |guillee3 |🟢 Up To Date | +|🇭🇺 Hungarian |kornel0706 |🟢 Up To Date | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | |🇷🇴 Romanian |sankedev |🟠 Temporary Outdated (beta) | |🇪🇸 Spanish |redactado & josuens |🟠 Temporary Outdated (beta) | @@ -109,7 +110,6 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇬🇷 Greek |stefanos__. |🔴 Outdated | |🇮🇩 Indonesian |erxg |🟠 Temporary Outdated (beta) | |❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | -|🇭🇺 Hungarian |kornel0706 |🟠 Temporary Outdated (beta) | |❓ Persian |sasanwm |🟠 Temporary Outdated (beta) | |🇱🇻 Latvian |ronalds1398 |🟠 Temporary Outdated (beta) | |🇪🇪 Estonian |iamnotmega |🟠 Temporary Outdated (beta) | diff --git a/languages/german.json b/languages/german.json index ac2b43c..a765b35 100644 --- a/languages/german.json +++ b/languages/german.json @@ -2,7 +2,7 @@ "_TRANSLATION":{ "otversion":"v4.0.0", "translator":"benzorich", - "lastedited":"21/08/2024", + "lastedited":"22/08/2024", "language":"German" }, "checker":{ @@ -98,7 +98,7 @@ "delete":"Ticket löschen", "reopen":"Ticket wieder öffnen", "claim":"Ticket beanspruchen", - "unclaim":"Ticket nicht mehr beanspruchen", + "unclaim":"Ticket nicht mehr beansprucht", "pin":"Pin Ticket", "unpin":"Unpin Ticket", "clear":"Tickets löschen", @@ -112,10 +112,10 @@ "created":"Ticket erstellt", "close":"Ticket geschlossen", "delete":"Ticket Gelöscht", - "reopen":"Ticket Reopened", + "reopen":"Ticket wiedereröffnet", "claim":"Ticket beansprucht", "unclaim":"Ticket nicht mehr beanspruchen", - "pin":"Ticket angeheftet", + "pin":"Ticket angepinnt", "unpin":"Ticket entpinnt", "rename":"Ticket umbenannt", "move":"Ticket verschoben", @@ -144,7 +144,7 @@ "create":"Ihr Ticket wurde bereits erstellt. Klicken Sie auf die Button unten, um es zu öffnen!", "close":"Das Ticket wurde erfolgreich geschlossen!", "delete":"Das Ticket wurde erfolgreich gelöscht!", - "reopen":"The ticket has been reopened succesfully!", + "reopen":"Das Ticket wurde erfolgreich wiedereröffnet!", "claim":"Das Ticket wurde erfolgreich beansprucht!", "unclaim":"Das Ticket wurde erfolgreich freigegeben!", "pin":"Das Ticket ist erfolgreich angepinnt worden!", @@ -249,7 +249,7 @@ "optionMissing":"Befehlsoption fehlt", "optionInvalid":"Befehlsoption ungültig", "unknownCommand":"Unbekannter Befehl", - "noPermissions":"Keine Berechtigungen", + "noPermissions":"Keine Berechtigung", "unknownTicket":"Unbekanntes Ticket", "deprecatedTicket":"Veraltetes Ticket", "unknownOption":"Unbekannte Option", @@ -325,7 +325,7 @@ "ticket":"Ticket", "tickets":"Tickets", "reason":"Grund", - "creator":"Creator", + "creator":"Ersteller", "remaining":"Verbleibende Zeit", "added":"Hinzugefügt", "removed":"Entfernt", @@ -470,7 +470,7 @@ "ticketsClaimed":"Tickets beansprucht", "ticketsPinned":"Tickets angepinnt", "ticketsMoved":"Tickets verschoben", - "usersBlacklisted":"Nutzer auf der Blacklist gesetzt ", + "usersBlacklisted":"Nutzer auf der Blacklist", "transcriptsCreated":"Transcripts erstellt" } } diff --git a/languages/hungarian.json b/languages/hungarian.json new file mode 100644 index 0000000..7fc7ea8 --- /dev/null +++ b/languages/hungarian.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"Kornel0706", + "lastedited":"22/08/2024", + "language":"Hungarian" + }, + "checker":{ + "system":{ + "typeError":"[HIBA]", + "headerOpenTicket":"NYITOTT JEGY", + "typeWarning":"[FIGYELMEZTETÉS]", + "typeInfo":"[INFORMÁCIÓ]", + "headerConfigChecker":"KONFIGURÁCIÓ ELLENŐRZÉS", + "headerDescription":"hibaellenőrzés a konfigurációdban!", + "footerError":"a bot nem indul el, amíg a következőket nem javítod ki: {0}!", + "footerWarning":"ajánlott javítani a következőket az indítás előtt: {0}", + "footerSupport":"SUPPORT: {0} - DOKUMENTÁCIÓ: {1}", + "compactInformation":"használd a következőt: {0} további információkért!", + "dataPath":"útvonal", + "dataDocs":"dokumentáció", + "dataMessages":"üzenet" + }, + "messages":{ + "stringTooShort":"Ez a karakterlánc nem lehet rövidebb, mint {0} karakter!", + "stringTooLong":"Ez a karakterlánc nem lehet hosszabb, mint {0} karakter!", + "stringLengthInvalid":"Ez a karakterlánc {0} karakter hosszúnak kell lennie!", + "stringStartsWith":"Ennek a karakterláncnak {0}-al kell kezdődnie!", + "stringEndsWith":"Ennek a karakterláncnak {0}-al kell végződnie!", + "stringContains":"Ennek a karakterláncnak tartalmaznia kell {0}-t!", + "stringChoices":"Ez a karakterlánc csak a következő értékek egyike lehet: {0}!", + "stringRegex":"Ez a karakterlánc érvénytelen!", + + "numberTooShort":"Ez a szám nem lehet rövidebb, mint {0} karakter!", + "numberTooLong":"Ez a szám nem lehet hosszabb, mint {0} karakter!", + "numberLengthInvalid":"Ez a szám {0} karakter hosszúnak kell lennie!", + "numberTooSmall":"Ennek a számnak legalább {0}-nak kell lennie!", + "numberTooLarge":"Ennek a számnak legfeljebb {0}-nak kell lennie!", + "numberNotEqual":"Ennek a számnak pontosan {0}-nak kell lennie!", + "numberStep":"Ennek a számnak a következő többszörösének kell lennie: {0}!", + "numberStepOffset":"Ennek a számnak a következő többszörösének kell lennie: {0}, kezdve {1}-el!", + "numberStartsWith":"Ennek a számnak {0}-al kell kezdődnie!", + "numberEndsWith":"Ennek a számnak {0}-al kell végződnie!", + "numberContains":"Ennek a számnak tartalmaznia kell {0}-t!", + "numberChoices":"Ez a szám csak a következő értékek egyike lehet: {0}!", + "numberFloat":"Ez a szám nem lehet tizedes!", + "numberNegative":"Ez a szám nem lehet negatív!", + "numberPositive":"Ez a szám nem lehet pozitív!", + "numberZero":"Ez a szám nem lehet nulla!", + + "booleanTrue":"Ez a logikai érték nem lehet igaz!", + "booleanFalse":"Ez a logikai érték nem lehet hamis!", + + "arrayEmptyDisabled":"Ez a tömb nem lehet üres!", + "arrayEmptyRequired":"Ez a tömb üresnek kell lennie!", + "arrayTooShort":"Ennek a tömbnek legalább {0} hosszúnak kell lennie!", + "arrayTooLong":"Ennek a tömbnek legfeljebb {0} hosszúnak kell lennie!", + "arrayLengthInvalid":"Ennek a tömbnek pontosan {0} hosszúnak kell lennie!", + "arrayInvalidTypes":"Ez a tömb csak a következő típusokat tartalmazhatja: {0}!", + "arrayDouble":"Ez a tömb nem engedélyezi ugyanazt az értéket kétszer!", + + "discordInvalidId":"Ez egy érvénytelen discord {0} azonosító!", + "discordInvalidIdOptions":"Ez egy érvénytelen discord {0} azonosító! Használhatja a következő lehetőségek egyikét is: {1}!", + "discordInvalidToken":"Ez egy érvénytelen discord token (szintaktikailag)!", + "colorInvalid":"Ez egy érvénytelen hex szín!", + "emojiTooShort":"Ennek a karakterláncnak legalább {0} emoji-t kell tartalmaznia!", + "emojiTooLong":"Ennek a karakterláncnak legfeljebb {0} emoji-t kell tartalmaznia!", + "emojiCustom":"Ez az emoji nem lehet egy egyéni discord emoji!", + "emojiInvalid":"Ez egy érvénytelen emoji!", + "urlInvalid":"Ez egy érvénytelen URL!", + "urlInvalidHttp":"Ez az URL csak a https:// protokollt használhatja!", + "urlInvalidProtocol":"Ez az URL csak a http:// & https:// protokollokat használhatja!", + "urlInvalidHostname":"Ez az URL egy nem engedélyezett hosztnevet tartalmaz!", + "urlInvalidExtension":"Ez az URL egy érvénytelen kiterjesztést tartalmaz! Válasszon a következők közül: {0}!", + "urlInvalidPath":"Ez az URL érvénytelen elérési utat tartalmaz!", + "idNotUnique":"Ez az azonosító nem egyedi, használjon egy másikat!", + "idNonExistent":"Az azonosító {0} nem létezik!", + + "invalidType":"Ennek a tulajdonságnak a következő típusúnak kell lennie: {0}!", + "propertyMissing":"A {0} tulajdonság hiányzik ebből az objektumból!", + "propertyOptional":"A {0} tulajdonság opcionális ebben az objektumban!", + "objectDisabled":"Ez az objektum le van tiltva, engedélyezze a következő használatával: {0}!", + "nullInvalid":"Ez a tulajdonság nem lehet null!", + "switchInvalidType":"Ennek a következő típusok egyikének kell lennie: {0}!", + "objectSwitchInvalid":"Ennek az objektumnak a következő típusok egyikének kell lennie: {0}!", + + "invalidLanguage":"Ez egy érvénytelen nyelv!", + "invalidButton":"Ennek a gombnak legalább egy {0} vagy {1} kell, hogy tartalmazzon!", + "unusedOption":"Az opció {0} nincs használatban sehol!", + "unusedQuestion":"A kérdés {0} nincs használatban sehol!", + "dropdownOption":"Egy legördülő menüvel rendelkező panel csak a 'jegy' típusú opciókat tartalmazhat!" + } + }, + "actions":{ + "buttons":{ + "create":"Jegy megnyitása", + "close":"Jegy bezárása", + "delete":"Jegy törlése", + "reopen":"Jegy újranyitása", + "claim":"Jegy igénylése", + "unclaim":"Jegy feloldása", + "pin":"Jegy rögzítése", + "unpin":"Jegy rögzítésének feloldása", + "clear":"Jegyek törlése", + "helpSwitchSlash":"Parancsok megtekintése", + "helpSwitchText":"Szöveges parancsok megtekintése", + "helpPage":"Oldal {0}", + "withReason":"Indoklással", + "withoutTranscript":"Átirat nélkül" + }, + "titles":{ + "created":"Jegy létrehozva", + "close":"Jegy bezárva", + "delete":"Jegy törölve", + "reopen":"Jegy újranyitva", + "claim":"Jegy igényelve", + "unclaim":"Jegy feloldva", + "pin":"Jegy rögzítve", + "unpin":"Jegy rögzítésének feloldva", + "rename":"Jegy átnevezve {0}-ra", + "move":"Jegy áthelyezve {0}-ra", + "add":"Felhasználó hozzáadva a jegyhez", + "remove":"Felhasználó eltávolítva a jegyből", + + "help":"Elérhető parancsok", + "statsReset":"Statisztikák visszaállítása", + "blacklistAdd":"Felhasználó tiltólistára helyezve", + "blacklistRemove":"Felhasználó tiltólistáról eltávolítva", + "blacklistGet":"Tiltólistás felhasználó", + "blacklistView":"Jelenlegi tiltólista", + "blacklistAddDm":"Felvéve a tiltólistára", + "blacklistRemoveDm":"Eltávolítva a tiltólistáról", + "clear":"Jegyek törölve", + "roles":"Szerepek frissítve", + + "autoclose":"Jegy automatikusan bezárva", + "autocloseEnabled":"Automatikus bezárás engedélyezve", + "autocloseDisabled":"Automatikus bezárás letiltva", + "autodelete":"Jegy automatikusan törölve", + "autodeleteEnabled":"Automatikus törlés engedélyezve", + "autodeleteDisabled":"Automatikus törlés letiltva" + }, + "descriptions":{ + "create":"A jegyed létrejött. Kattints az alábbi gombra, hogy hozzáférj!", + "close":"A jegyet sikeresen lezártuk!", + "delete":"A jegyet sikeresen töröltük!", + "reopen":"A jegyet sikeresen újranyitottuk!", + "claim":"A jegyet sikeresen igényeltük!", + "unclaim":"A jegyet sikeresen feloldottuk!", + "pin":"A jegyet sikeresen rögzítettük!", + "unpin":"A jegy rögzítését sikeresen feloldottuk!", + "rename":"A jegyet sikeresen átneveztük {0}-ra!", + "move":"A jegyet sikeresen áthelyeztük {0}-ra!", + "add":"{0} sikeresen hozzáadva a jegyhez!", + "remove":"{0} sikeresen eltávolítva a jegyből!", + + "helpExplanation":"`` => kötelező paraméter\n`[név]` => opcionális paraméter", + "statsReset":"A bot statisztikái sikeresen visszaállítva!", + "statsError":"A jegy statisztikáit nem sikerült megtekinteni!\n{0} nem egy jegy!", + "blacklistAdd":"{0} sikeresen felvéve a tiltólistára!", + "blacklistRemove":"{0} sikeresen eltávolítva a tiltólistáról!", + "blacklistGetSuccess":"{0} jelenleg tiltólistán van!", + "blacklistGetEmpty":"{0} jelenleg nincs tiltólistán!", + "blacklistViewEmpty":"Még senki nincs tiltólistán!", + "blacklistViewTip":"Használd a \"/blacklist add\" parancsot, hogy felvegyél valakit a tiltólistára!", + "clearVerify":"Biztos vagy benne, hogy törölni szeretnéd több jegyet? Ez a művelet nem vonható vissza!", + "clearReady":"{0} jegyek sikeresen törölve!", + "rolesEmpty":"Nincsenek frissítve szerepek!", + + "autocloseLeave":"Ez a jegy automatikusan bezáródott, mert a készítő elhagyta a szervert!", + "autocloseTimeout":"Ez a jegy automatikusan bezáródott, mert több mint `{0}h` ideje inaktív volt!", + "autodeleteLeave":"Ez a jegy automatikusan törlődött, mert a készítő elhagyta a szervert!", + "autodeleteTimeout":"Ez a jegy automatikusan törlődött, mert több mint `{0} nap` ideje inaktív volt!", + "autocloseEnabled":"Az automatikus bezárás engedélyezve van ebben a jegyben!\nEz bezáródik, ha több mint `{0}h` ideig inaktív!", + "autocloseDisabled":"Az automatikus bezárás le van tiltva ebben a jegyben!\nNem záródik be automatikusan többé!", + "autodeleteEnabled":"Az automatikus törlés engedélyezve van ebben a jegyben!\nEz törlődik, ha több mint `{0} nap` ideig inaktív!", + "autodeleteDisabled":"Az automatikus törlés le van tiltva ebben a jegyben!\nNem törlődik automatikusan többé!", + + "ticketMessageLimit":"Egyszerre csak {0} jegyet hozhatsz létre!", + "ticketMessageAutoclose":"Ez a jegy automatikusan bezáródik, ha inaktív marad {0}h ideig!", + "ticketMessageAutodelete":"Ez a jegy automatikusan törlődik, ha inaktív marad {0} nap ideig!", + "panelReady":"Az alábbi panelben megtalálod!\nEz az üzenet most törölhető!" + }, + "modal":{ + "closePlaceholder":"Miért zártad be ezt a jegyet?", + "deletePlaceholder":"Miért törölted ezt a jegyet?", + "reopenPlaceholder":"Miért nyitottad újra ezt a jegyet?", + "claimPlaceholder":"Miért igényelted ezt a jegyet?", + "unclaimPlaceholder":"Miért oldottad fel ezt a jegyet?", + "pinPlaceholder":"Miért rögzítetted ezt a jegyet?", + "unpinPlaceholder":"Miért oldottad fel ennek a jegynek a rögzítését?" + }, + "logs":{ + "createLog":"Egy új jegy létrejött {0} által!", + "closeLog":"Ezt a jegyet lezárta {0}!", + "closeDm":"A jegyed lezárásra került a szerverünkön!", + "deleteLog":"Ezt a jegyet törölte {0}!", + "deleteDm":"A jegyed törlésre került a szerverünkön!", + "reopenLog":"Ezt a jegyet újranyitotta {0}!", + "reopenDm":"A jegyed újranyitásra került a szerverünkön!", + "claimLog":"Ezt a jegyet igényelte {0}!", + "claimDm":"A jegyed igénylésre került a szerverünkön!", + "unclaimLog":"Ezt a jegyet feloldotta {0}!", + "unclaimDm":"A jegyed feloldásra került a szerverünkön!", + "pinLog":"Ezt a jegyet rögzítette {0}!", + "pinDm":"A jegyed rögzítésre került a szerverünkön!", + "unpinLog":"Ezt a jegyet feloldotta {0}!", + "unpinDm":"A jegyed rögzítésének feloldásra került a szerverünkön!", + "renameLog":"Ezt a jegyet átnevezték {0}-ra {1} által!", + "renameDm":"A jegyed átnevezésre került {0}-ra a szerverünkön!", + "moveLog":"Ezt a jegyet áthelyezték {0}-ra {1} által!", + "moveDm":"A jegyed áthelyezésre került {0}-ra a szerverünkön!", + "addLog":"{0} hozzáadásra került ehhez a jegyhez {1} által!", + "addDm":"{0} hozzáadásra került a jegyedhez a szerverünkön!", + "removeLog":"{0} eltávolításra került ebből a jegyből {1} által!", + "removeDm":"{0} eltávolításra került a jegyedből a szerverünkön!", + + "blacklistAddLog":"{0} tiltólistára helyezte {1}!", + "blacklistRemoveLog":"{0} eltávolította a tiltólistáról {1}!", + "blacklistAddDm":"Tiltólistára kerültél a szerverünkön!\nEzentúl nem hozhatsz létre jegyet!", + "blacklistRemoveDm":"Eltávolításra kerültél a szerverünk tiltólistájáról!\nMost újra létrehozhatsz jegyeket!", + "clearLog":"{0} jegyek törlésre kerültek {1} által!" + } + }, + "transcripts":{ + "success":{ + "visit":"Átirat megtekintése", + "ready":"Átirat létrehozva", + "textFileDescription":"Ez egy törölt jegy szöveges átirata!", + "htmlProgress":"Kérjük, várj, amíg ez a HTML átirat feldolgozásra kerül...", + + "createdChannel":"Egy új {0} átirat létrejött a szerveren!", + "createdCreator":"Egy új {0} átirat létrejött egy jegyed számára!", + "createdParticipant":"Egy új {0} átirat létrejött egy jegyben, amiben részt vettél!", + "createdActiveAdmin":"Egy új {0} átirat létrejött egy jegyben, amiben adminisztrátorként vettél részt!", + "createdEveryAdmin":"Egy új {0} átirat létrejött egy jegyben, amiben adminisztrátorként voltál jelen!", + "createdOther":"Egy új {0} átirat létrejött!" + }, + "errors":{ + "retry":"Újra", + "continue":"Törlés átirat nélkül", + "backup":"Biztonsági átirat létrehozása", + "error":"Valami hiba történt az átirat létrehozása közben.\nMit szeretnél tenni?\n\nEz a jegy nem kerül törlésre, amíg nem kattintasz az egyik gombra." + } + }, + "errors":{ + "titles":{ + "internalError":"Belső Hiba", + "optionMissing":"Parancs Opció Hiányzik", + "optionInvalid":"Parancs Opció Érvénytelen", + "unknownCommand":"Ismeretlen Parancs", + "noPermissions":"Nincs Jogosultság", + "unknownTicket":"Ismeretlen Jegy", + "deprecatedTicket":"Elavult Jegy", + "unknownOption":"Ismeretlen Opció", + "unknownPanel":"Ismeretlen Panel", + "notInGuild":"Nem a Szerveren", + "channelRename":"Nem sikerült átnevezni a csatornát", + "busy":"A Jegy Elfoglalt" + }, + "descriptions":{ + "askForInfo":"Lépj kapcsolatba a bot tulajdonosával további információkért!", + "askForInfoResolve":"Lépj kapcsolatba a bot tulajdonosával, ha ez a probléma nem oldódik meg néhány próbálkozás után.", + "internalError":"Nem sikerült válaszolni erre a {0}-ra egy belső hiba miatt!", + "optionMissing":"Hiányzik egy szükséges paraméter ebben a parancsban!", + "optionInvalid":"Egy paraméter érvénytelen ebben a parancsban!", + "optionInvalidChoose":"Válassz a következők közül", + "unknownCommand":"Próbáld meg a súgó menü megnyitását további információkért!", + "noPermissions":"Nem vagy jogosult használni ezt a {0}-t!", + "noPermissionsList":"Szükséges Jogosultságok: (egyik)", + "noPermissionsCooldown":"Nem vagy jogosult használni ezt a {0}-t, mert cooldown alatt állsz!", + "noPermissionsBlacklist":"Nem vagy jogosult használni ezt a {0}-t, mert tiltólistára kerültél!", + "noPermissionsLimitGlobal":"Nem hozhatsz létre jegyet, mert a szerver elérte a maximális jegy limitet!", + "noPermissionsLimitGlobalUser":"Nem hozhatsz létre jegyet, mert elérted a maximális jegy limitet!", + "noPermissionsLimitOption":"Nem hozhatsz létre jegyet, mert a szerver elérte a maximális jegy limitet ezzel az opcióval!", + "noPermissionsLimitOptionUser":"Nem hozhatsz létre jegyet, mert elérted a maximális jegy limitet ezzel az opcióval!", + "unknownTicket":"Próbáld újra ezt a parancsot egy érvényes jegyben!", + "deprecatedTicket":"Az aktuális csatorna nem egy érvényes jegy! Lehet, hogy ez egy régi Open Ticket verzióból származó jegy volt!", + "notInGuild":"Ez a {0} nem működik DM-ben! Próbáld újra egy szerveren!", + "channelRename":"A discord korlátai miatt jelenleg nem lehet átnevezni a csatornát. A csatorna automatikusan átnevezésre kerül 10 perc múlva, ha a bot nincs újraindítva.", + "channelRenameSource":"A hiba forrása: {0}", + "busy":"Nem lehet használni ezt a {0}-t!\nA jegy jelenleg a bot által van feldolgozás alatt.\n\nPróbáld meg néhány másodperc múlva!" + }, + "optionInvalidReasons":{ + "stringRegex":"Az érték nem felel meg a mintának!", + "stringMinLength":"Az értéknek legalább {0} karakter hosszúnak kell lennie!", + "stringMaxLength":"Az értéknek legfeljebb {0} karakter hosszúnak kell lennie!", + "numberInvalid":"Érvénytelen szám!", + "numberMin":"A számnak legalább {0}-nak kell lennie!", + "numberMax":"A számnak legfeljebb {0}-nak kell lennie!", + "numberDecimal":"A szám nem lehet tizedes!", + "numberNegative":"A szám nem lehet negatív!", + "numberPositive":"A szám nem lehet pozitív!", + "numberZero":"A szám nem lehet nulla!", + "channelNotFound":"Nem található csatorna!", + "userNotFound":"Nem található felhasználó!", + "roleNotFound":"Nem található szerep!", + "memberNotFound":"Nem található felhasználó!", + "mentionableNotFound":"Nem található felhasználó vagy szerep!", + "channelType":"Érvénytelen csatornatípus!", + "notInGuild":"Ez az opció megköveteli, hogy szerveren legyél!" + }, + "permissions":{ + "developer":"A bot fejlesztőjének kell lenned.", + "owner":"A szerver tulajdonosának kell lenned.", + "admin":"Szerver adminnak kell lenned.", + "moderator":"Moderátornak kell lenned.", + "support":"A támogatási csapat tagjának kell lenned.", + "member":"Tagként kell lenned.", + "discord-administrator":"Az `ADMINISZTRÁTOR` jogosultsággal kell rendelkezned." + }, + "actionInvalid":{ + "close":"A jegy már le van zárva!", + "reopen":"A jegy még nincs lezárva!", + "claim":"A jegy már igényelve van!", + "unclaim":"A jegy még nincs feloldva!", + "pin":"A jegy már rögzítve van!", + "unpin":"A jegy még nincs feloldva!", + "add":"Ez a felhasználó már hozzáfér a jegyhez!", + "remove":"Nem lehet eltávolítani ezt a felhasználót a jegyből!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Jegy", + "tickets":"Jegyek", + "reason":"Indok", + "creator":"Készítő", + "remaining":"Hátralévő idő", + "added":"Hozzáadva", + "removed":"Eltávolítva", + "filter":"Szűrő", + "claimedBy":"Igényelte {0}", + "method":"Módszer", + "type":"Típus", + "blacklisted":"Tiltólistás", + "panel":"Panel", + "command":"Parancs", + "system":"Rendszer", + "true":"Igaz", + "false":"Hamis", + "syntax":"Szintaxis", + "originalName":"Eredeti Név", + "newName":"Új Név", + "until":"Amíg", + "validOptions":"Érvényes Opciók", + "validPanels":"Érvényes Panelek", + "autoclose":"Automatikus Bezárás", + "autodelete":"Automatikus Törlés", + "startupDate":"Indulás Dátuma", + "version":"Verzió", + "name":"Név", + "role":"Szerep", + "status":"Státusz", + "claimed":"Igényelt", + "pinned":"Rögzített", + "creationDate":"Létrehozás Dátuma" + }, + "lowercase":{ + "text":"szöveg", + "html":"html", + "command":"parancs", + "modal":"modális ablak", + "button":"gomb", + "dropdown":"legördülő menü", + "method":"módszer" + } + }, + "commands":{ + "reason":"Adja meg az opcionális indokot, amely látható lesz a naplókban.", + "help":"Parancsok listájának megtekintése.", + "panel":"Üzenet létrehozása legördülő menüvel vagy gombokkal (jegy létrehozásához).", + "panelId":"A panel azonosítója, amelyet létre szeretnél hozni.", + "panelAutoUpdate":"Szeretnéd, hogy ez a panel automatikusan frissüljön szerkesztéskor?", + "ticket":"Azonnal hozz létre egy jegyet.", + "ticketId":"Az azonosítója annak a jegynek, amelyet létre szeretnél hozni.", + "close":"Zárjon be egy jegyet.", + "delete":"Jegy törlése.", + "deleteNoTranscript":"Töröld ezt a jegyet átirat nélkül.", + "reopen":"Nyissa meg újra a jegyet.", + "claim":"Jegy igénylése.", + "claimUser":"Jegy igénylése valaki másnak helyetted.", + "unclaim":"Jegy feloldása.", + "pin":"Jegy rögzítése.", + "unpin":"Jegy rögzítésének feloldása.", + "move":"Jegy áthelyezése.", + "moveId":"Annak a opció az azonosítója, amelyet áthelyezni szeretnél.", + "rename":"Jegy átnevezése.", + "renameName":"Az új név a jegyhez.", + "add":"Felhasználó hozzáadása a jegyhez.", + "addUser":"A felhasználó, akit hozzá szeretnél adni.", + "remove":"Felhasználó eltávolítása a jegyből.", + "removeUser":"A felhasználó, akit el szeretnél távolítani.", + "blacklist":"Jegy tiltólista kezelése.", + "blacklistView":"A jelenlegi tiltólista megtekintése.", + "blacklistAdd":"Felhasználó hozzáadása a tiltólistához.", + "blacklistRemove":"Felhasználó eltávolítása a tiltólistáról.", + "blacklistGet":"Tiltólistás felhasználó adatainak megtekintése.", + "blacklistGetUser":"A felhasználó, akinek az adatait meg szeretnéd tekinteni.", + "stats":"Bot, tag vagy jegy statisztikáinak megtekintése.", + "statsReset":"A bot összes statisztikájának visszaállítása (és újra számolás megkezdése nulláról).", + "statsGlobal":"Globális statisztikák megtekintése.", + "statsUser":"Felhasználó statisztikáinak megtekintése a szerveren.", + "statsUserUser":"A felhasználó, akinek a statisztikáit meg szeretnéd tekinteni.", + "statsTicket":"Jegy statisztikáinak megtekintése a szerveren.", + "statsTicketTicket":"A jegy, amelynek a statisztikáit meg szeretnéd tekinteni.", + "clear":"Több jegy egyidejű törlése. Opcionális szűrő adható meg.", + "clearFilter":"A szűrő a jegyek törléséhez.", + "clearFilters":{ + "all":"Összes", + "open":"Nyitott", + "close":"Lezárt", + "claim":"Igényelt", + "unclaim":"Feloldott", + "pin":"Rögzített", + "unpin":"Feloldott", + "autoclose":"Automatikusan Bezárt" + }, + "autoclose":"Automatikus bezárás kezelése egy jegyben.", + "autocloseDisable":"Automatikus bezárás letiltása ebben a jegyben.", + "autocloseEnable":"Automatikus bezárás engedélyezése ebben a jegyben.", + "autocloseEnableTime":"Az óra száma, amely inaktívvá kell, hogy váljon ez a jegy a bezáráshoz.", + "autodelete":"Automatikus törlés kezelése egy jegyben.", + "autodeleteDisable":"Automatikus törlés letiltása ebben a jegyben.", + "autodeleteEnable":"Automatikus törlés engedélyezése ebben a jegyben.", + "autodeleteEnableTime":"A napok száma, amely inaktívvá kell, hogy váljon ez a jegy a törléshez." + }, + "helpMenu":{ + "help":"Parancsok listájának megtekintése.", + "ticket":"Jegy azonnali létrehozása.", + "close":"Jegy bezárása, ezzel letiltod az írást ebben a csatornában.", + "delete":"Jegy törlése, ez átiratot hoz létre, ha engedélyezett.", + "reopen":"Jegy újranyitása, ezzel újra engedélyezed az írást ebben a csatornában.", + "pin":"Jegy rögzítése. Ez a jegyet a lista tetejére helyezi és hozzáad egy '📌' emojit a nevéhez.", + "unpin":"Jegy rögzítésének feloldása. A jegy a helyén marad, de elveszíti a '📌' emojit.", + "move":"Jegy áthelyezése. Ez megváltoztatja a jegy típusát.", + "rename":"Jegy átnevezése. Ez megváltoztatja a jegy csatorna nevét.", + "claim":"Jegy igénylése. Ezzel tudathatod a csapatoddal, hogy ezt a jegyet te kezeled.", + "unclaim":"Jegy feloldása. Ezzel tudathatod a csapatoddal, hogy ez a jegy újra elérhető.", + "add":"Felhasználó hozzáadása a jegyhez. Ez lehetővé teszi a felhasználónak az olvasást és írást ebben a jegyben.", + "remove":"Felhasználó eltávolítása a jegyből. Ez eltávolítja az olvasási és írási jogosultságokat egy felhasználótól ebben a jegyben.", + "panel":"Üzenet létrehozása legördülő menüvel vagy gombokkal (jegy létrehozásához).", + "blacklistView":"A jelenlegi tiltólista megtekintése.", + "blacklistAdd":"Felhasználó hozzáadása a tiltólistához.", + "blacklistRemove":"Felhasználó eltávolítása a tiltólistáról.", + "blacklistGet":"Tiltólistás felhasználó adatainak megtekintése.", + "statsGlobal":"Globális statisztikák megtekintése.", + "statsTicket":"Jegy statisztikáinak megtekintése a szerveren.", + "statsUser":"Felhasználó statisztikáinak megtekintése a szerveren.", + "statsReset":"A bot összes statisztikájának visszaállítása (és újra számolás megkezdése nulláról).", + "autocloseDisable":"Automatikus bezárás letiltása ebben a jegyben.", + "autocloseEnable":"Automatikus bezárás engedélyezése ebben a jegyben.", + "autodeleteDisable":"Automatikus törlés letiltása ebben a jegyben.", + "autodeleteEnable":"Automatikus törlés engedélyezése ebben a jegyben." + }, + "stats":{ + "scopes":{ + "global":"Globális Statisztikák", + "system":"Rendszer Statisztikák", + "user":"Felhasználói Statisztikák", + "ticket":"Jegy Statisztikák", + "participants":"Résztvevők" + }, + "properties":{ + "ticketsCreated":"Létrehozott Jegyek", + "ticketsClosed":"Lezárt Jegyek", + "ticketsDeleted":"Törölt Jegyek", + "ticketsReopened":"Újranyitott Jegyek", + "ticketsAutoclosed":"Automatikusan Bezárt Jegyek", + "ticketsClaimed":"Igényelt Jegyek", + "ticketsPinned":"Rögzített Jegyek", + "ticketsMoved":"Áthelyezett Jegyek", + "usersBlacklisted":"Tiltólistás Felhasználók", + "transcriptsCreated":"Létrehozott Átiratok" + } + } +} diff --git a/package.json b/package.json index 9842d92..06785c7 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "type": "commonjs", "license": "GPL-3.0-only", "dependencies": { + "@types/node": "^22.5.0", "ansis": "^2.3.0", "discord.js": "^14.15.3", "formatted-json-stringify": "^1.1.0", diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index b81a9dc..cdcb23e 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -451,6 +451,7 @@ export interface ODLanguageManagerIds_Default { "openticket:czech":ODLanguage, "openticket:german":ODLanguage, "openticket:catalan":ODLanguage, + "openticket:hungarian":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 5f5f727..3b0138e 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -1160,7 +1160,7 @@ export class ODCheckerCustomStructure_HexColor extends ODCheckerStringStructure if (typeof value != "string") return false else if (emptyAllowed && value.length == 0){ return true - }else if ((!allowShortForm && !/^#[a-f0-9]{6}$/.test(value)) || (allowShortForm && !/^#[a-f0-9]{6}$/.test(value) && !/^#[a-f0-9]{3}$/.test(value))){ + }else if ((!allowShortForm && !/^#[a-fA-F0-9]{6}$/.test(value)) || (allowShortForm && !/^#[a-fA-F0-9]{6}$/.test(value) && !/^#[a-fA-F0-9]{3}$/.test(value))){ checker.createMessage("openticket:color-invalid","error","This is an invalid hex color!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else return true diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index cefc0c5..b4b2030 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -40,7 +40,7 @@ export interface ODDefaults { languageSelection:boolean, /**Set the backup language when the primary language is missing a property. */ backupLanguage:string, - /****[NOD FOR PLUGIN TRANSLATIONS]** The full list of available languages (used in the default config checker). */ + /****[NOT FOR PLUGIN TRANSLATIONS]** The full list of available languages (used in the default config checker). */ languageList:string[], /**Load the default open ticket config checker. */ @@ -160,6 +160,8 @@ export interface ODDefaults { /**Render the default open ticket startscreen. */ startScreenRendering:boolean, + /**Load the emoji style from the open ticket general config. */ + emojiTitleStyleLoading:boolean, /**The emoji style to use in embed & message titles using `utilities.emoijTitle()` */ emojiTitleStyle:"disabled"|"before"|"after"|"double", /**The emoji divider to use in embed & message titles using `utilities.emoijTitle()` */ @@ -234,7 +236,7 @@ export class ODDefaultsManager { languageLoading:true, languageSelection:true, backupLanguage:"openticket:english", - languageList:["custom","english","dutch","portuguese","czech","german","catalan"], + languageList:[], checkerLoading:true, checkerFunctionLoading:true, @@ -300,6 +302,7 @@ export class ODDefaultsManager { startScreenLoading:true, startScreenRendering:true, + emojiTitleStyleLoading:true, emojiTitleStyle:"before", emojiTitleDivider:" ", autocloseCheckInterval:300000, //5 minutes diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 70a9ca4..da7f870 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -1,6 +1,7 @@ import {openticket, api, utilities} from "../../index" export const loadAllLanguages = async () => { + //register languages openticket.languages.add(new api.ODLanguage("openticket:custom","custom.json")) openticket.languages.add(new api.ODLanguage("openticket:english","english.json")) openticket.languages.add(new api.ODLanguage("openticket:dutch","dutch.json")) @@ -8,10 +9,17 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODLanguage("openticket:czech","czech.json")) openticket.languages.add(new api.ODLanguage("openticket:german","german.json")) openticket.languages.add(new api.ODLanguage("openticket:catalan","catalan.json")) + openticket.languages.add(new api.ODLanguage("openticket:hungarian","hungarian.json")) + + //list for config checker + const languageList = openticket.defaults.getDefault("languageList") + languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian") + openticket.defaults.setDefault("languageList",languageList) /** How to add more languages? - * - Add the language to the list above - * - Add the language to the "languageList" in the "ODDefaultsManager" class - * - Add the language to the list in the "ODLanguageManagerIds_Default" interface + * - Register the language to the manager (see above) + * - Add the language to the list (see above) + * - Add the language to the list in the "ODLanguageManagerIds_Default" interface (./src/core/api/defaults/language.ts) + * - Add the language to the list in the README.md */ } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index a9a8d7f..268447f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -133,6 +133,11 @@ const main = async () => { //UTILITY CONFIG const generalConfig = openticket.configs.get("openticket:general") + if (openticket.defaults.getDefault("emojiTitleStyleLoading")){ + //set emoji style based on config + openticket.defaults.setDefault("emojiTitleStyle",generalConfig.data.system.emojiStyle) + } + //load database openticket.log("Loading databases...","system") if (openticket.defaults.getDefault("databaseLoading")){ From 12885f63d660a2ba770c483957533813a98486cc Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Fri, 23 Aug 2024 23:24:59 +0200 Subject: [PATCH 013/157] Fixed spanish max string length issues --- README.md | 2 +- languages/spanish.json | 36 ++++++++++++++-------------- src/core/api/defaults/language.ts | 1 + src/data/framework/languageLoader.ts | 3 ++- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index c073b4c..1dcc907 100644 --- a/README.md +++ b/README.md @@ -94,9 +94,9 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇩🇪 German |benzorich |🟢 Up To Date | |❓ Catalan |guillee3 |🟢 Up To Date | |🇭🇺 Hungarian |kornel0706 |🟢 Up To Date | +|🇪🇸 Spanish |redactado & josuens |🟢 Up To Date | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | |🇷🇴 Romanian |sankedev |🟠 Temporary Outdated (beta) | -|🇪🇸 Spanish |redactado & josuens |🟠 Temporary Outdated (beta) | |🇮🇹 Italian |maurizio26 |🟠 Temporary Outdated (beta) | |🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | |🇩🇰 Danish |.the_gamer |🟠 Temporary Outdated (beta) | diff --git a/languages/spanish.json b/languages/spanish.json index 5ff7419..d5398e3 100644 --- a/languages/spanish.json +++ b/languages/spanish.json @@ -1,7 +1,7 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"Redactado and Josuens", + "translator":"Redactado & Josuens", "lastedited":"22/8/2024", "language":"Spanish" }, @@ -215,8 +215,8 @@ "removeLog":"¡{0} ha sido eliminado de este ticket por {1}!", "removeDm":"¡{0} ha sido eliminado de tu ticket en nuestro servidor!", - "blacklistAddLog":"{0} fue incluido en la lista negra por {1}", - "blacklistRemoveLog":"{0} fue eliminado de la lista negra por {1}", + "blacklistAddLog":"{0} fue incluido en la lista negra por {1}!", + "blacklistRemoveLog":"{0} fue eliminado de la lista negra por {1}!", "blacklistAddDm":"¡Has sido incluido en la lista negra en nuestro servidor!\n¡A partir de ahora, no puedes crear un ticket!", "blacklistRemoveDm":"¡Has sido eliminado de la lista negra en nuestro servidor!\n¡Ahora puedes volver a crear tickets!", "clearLog":"¡{0} tickets han sido eliminados por {1}!" @@ -374,24 +374,24 @@ "panelAutoUpdate":"¿Quieres que este panel se actualice automáticamente cuando se edite?", "ticket":"Crea un ticket instantáneamente.", "ticketId":"El identificador del ticket que quieres crear.", - "close":"Cierra un ticket, esto deshabilita la escritura en este canal. ¡Esta acción siempre puede ser revertida!", - "delete":"Elimina un ticket, esto crea una transcripción cuando está habilitado. ¡Esta acción no puede ser revertida!", + "close":"Cierra un ticket.", + "delete":"Elimina un ticket.", "deleteNoTranscript":"Elimina este ticket sin crear una transcripción.", - "reopen":"Reabre un ticket, esto habilita la escritura en este canal de nuevo.", - "claim":"Reclama un ticket. Con esto, puedes hacer saber a tu equipo que estás manejando este ticket.", + "reopen":"Reabre un ticket", + "claim":"Reclama un ticket.", "claimUser":"Reclama este ticket a alguien más en lugar de a ti mismo.", - "unclaim":"Libera un ticket. Con esto, puedes hacer saber a tu equipo que este ticket está libre de nuevo.", - "pin":"Ancla un ticket. Esto moverá el ticket a la parte superior y añadirá un emoji '📌' al nombre.", - "unpin":"Desancla un ticket. El ticket se quedará en su posición pero perderá el emoji '📌'.", - "move":"Mueve un ticket. Esto cambiará el tipo de este ticket.", - "moveId":"El identificador del ticket al que quieres mover.", - "rename":"Renombra un ticket. Esto cambiará el nombre del canal de este ticket.", + "unclaim":"Libera un ticket.", + "pin":"Ancla un ticket.", + "unpin":"Desancla un ticket.", + "move":"Mueve un ticket.", + "moveId":"El identificador del opción al que quieres mover.", + "rename":"Renombra un ticket.", "renameName":"El nuevo nombre para este ticket.", - "add":"Añade un usuario a un ticket. Esto permitirá al usuario leer y escribir en este ticket.", + "add":"Añade un usuario a un ticket.", "addUser":"El usuario a añadir.", - "remove":"Elimina un usuario de un ticket. Esto eliminará la capacidad de leer y escribir para un usuario en este ticket.", + "remove":"Elimina un usuario de un ticket.", "removeUser":"El usuario a eliminar.", - "blacklist":"Administra la lista negra de tickets. Los usuarios añadidos a esta lista no pueden crear un ticket.", + "blacklist":"Administra la lista negra de tickets.", "blacklistView":"Ver una lista de la lista negra actual.", "blacklistAdd":"Añade un usuario a la lista negra.", "blacklistRemove":"Elimina un usuario de la lista negra.", @@ -418,11 +418,11 @@ }, "autoclose":"Administra el cierre automático en un ticket.", "autocloseDisable":"Desactiva el cierre automático en este ticket.", - "autocloseEnable":"Activa el cierre automático en este ticket", + "autocloseEnable":"Activa el cierre automático en este ticket.", "autocloseEnableTime":"La cantidad de horas que este ticket necesita estar inactivo para cerrarlo.", "autodelete":"Administra la eliminación automática en un ticket.", "autodeleteDisable":"Desactiva la eliminación automática en este ticket.", - "autodeleteEnable":"Activa la eliminación automática en este ticket", + "autodeleteEnable":"Activa la eliminación automática en este ticket.", "autodeleteEnableTime":"La cantidad de días que este ticket necesita estar inactivo para eliminarlo." }, "helpMenu":{ diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index cdcb23e..255101e 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -452,6 +452,7 @@ export interface ODLanguageManagerIds_Default { "openticket:german":ODLanguage, "openticket:catalan":ODLanguage, "openticket:hungarian":ODLanguage, + "openticket:spanish":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index da7f870..9e37e1a 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -10,10 +10,11 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODLanguage("openticket:german","german.json")) openticket.languages.add(new api.ODLanguage("openticket:catalan","catalan.json")) openticket.languages.add(new api.ODLanguage("openticket:hungarian","hungarian.json")) + openticket.languages.add(new api.ODLanguage("openticket:spanish","spanish.json")) //list for config checker const languageList = openticket.defaults.getDefault("languageList") - languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian") + languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish") openticket.defaults.setDefault("languageList",languageList) /** How to add more languages? From e67c505e32be94d7eba32d5eae6a217bf6993a54 Mon Sep 17 00:00:00 2001 From: Anderskiy <123444941+Anderskiy@users.noreply.github.com> Date: Sat, 31 Aug 2024 15:08:14 +0300 Subject: [PATCH 014/157] Add files via upload --- languages/ukraine.json | 477 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 477 insertions(+) create mode 100644 languages/ukraine.json diff --git a/languages/ukraine.json b/languages/ukraine.json new file mode 100644 index 0000000..d0cf3e0 --- /dev/null +++ b/languages/ukraine.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"Anderskiy", + "lastedited":"31/8/2024", + "language":"Ukrainian" + }, + "checker":{ + "system":{ + "typeError":"[ПОМИЛКА]", + "headerOpenTicket":"OPEN TICKET", + "typeWarning":"[ПОПЕРЕДЖЕННЯ]", + "typeInfo":"[ІНФО]", + "headerConfigChecker":"КОНФІГ ЧЕК", + "headerDescription":"перевірка на помилки у конфігу!", + "footerError":"бот не запуститься, поки не будуть виправлені всі {0}!", + "footerWarning":"рекомендується виправити всі {0} перед запуском!", + "footerSupport":"ДОПОМОГА: {0} - ДОКИ: {1}", + "compactInformation":"використовуйте {0} для більшої інформації!", + "dataPath":"шлях", + "dataDocs":"документація", + "dataMessages":"повідомлення" + }, + "messages":{ + "stringTooShort":"Цей рядок не може бути коротшим за {0} символів!", + "stringTooLong":"Цей рядок не може бути довшим за {0} символів!»", + "stringLengthInvalid":"Цей рядок повинен мати довжину {0} символів!", + "stringStartsWith":"Цей рядок повинен починатися з {0}!", + "stringEndsWith":"Цей рядок повинен закінчуватися на {0}!", + "stringContains":"Цей рядок повинен мати {0}!", + "stringChoices":"Цей рядок може мати лише одне з наступних значень: {0}!", + "stringRegex":"Цей рядок є неправильним!", + + "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": "Цей булевий вираз не може бути істинним!", + "booleanFalse": "Цей булевий вираз не може бути хибним!", + + "arrayEmptyDisabled": "Цей масив не може бути порожнім!", + "arrayEmptyRequired": "Цей масив повинен бути порожнім!", + "arrayTooShort": "Цей масив повинен мати довжину не менше {0}!", + "arrayTooLong": "Цей масив повинен мати довжину не більше {0}!", + "arrayLengthInvalid": "Цей масив повинен мати довжину {0}!", + "arrayInvalidTypes": "Цей масив може містити тільки такі типи: {0}!", + "arrayDouble": "Цей масив не допускає повторення одного й того ж значення двічі!", + + "discordInvalidId":"Це недійсний ідентифікатор discord {0}!", + "discordInvalidIdOptions":"Це недійсний ідентифікатор discord {0}! Але ви також можете використати один з цих: {1}!", + "discordInvalidToken":"Це недійсний токен дискорду (синтаксично)!", + "colorInvalid":"Це недійсний hex кольор!", + "emojiTooShort":"Цей рядок повинен містити щонайменше {0} емодзі!", + "emojiTooLong":"Цей рядок повинен містити не більше {0} емодзі!", + "emojiCustom":"Цей емодзі не може бути користувацьким дискорд емодзі", + "emojiInvalid":"Цей емодзі недійсний!", + "urlInvalid":"Це посилання недійсне!", + "urlInvalidHttp":"Це посилання може використовувати лише https:// протокол!", + "urlInvalidProtocol":"Це посилання може використовувати лише http:// та https:// протоколи!", + "urlInvalidHostname":"Це посилання має заборонене ім'я хоста", + "urlInvalidExtension":"Це посилання має невірне розширення! Виберіть один з варіантів: {0}!", + "urlInvalidPath":"Це посилання має недійсний шлях!", + "idNotUnique":"Цей ідентифікатор не є унікальним, використовуйте інший ідентифікатор!", + "idNonExistent":"Цей айді {0} недійсний!", + + "invalidType":"Ця властивість повинна мати тип: {0}!", + "propertyMissing":"У цього об'єкту відсутня властивість {0}!", + "propertyOptional":"Властивість {0} у цьому об'єкті є необов'язковою!", + "objectDisabled":"Цей об'єкт вимкнено, увімкніть його за допомогою {0}!", + "nullInvalid":"Ця властивість не може бути нульовою!", + "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":"Cторінка {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":"`` => обов'язковий параметр\n`[name]` => необов'язковий параметр", + "statsReset":"Статистику бота успішно скинуто!", + "statsError":"Неможливо переглянути статистику тікету!\n{0} - це не тікет!", + "blacklistAdd":"{0} успішно додано до чорного списку!", + "blacklistRemove":"{0} успішно убрано з чорного списку!", + "blacklistGetSuccess":"{0} зараз у чорному списку!", + "blacklistGetEmpty":"{0} {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":"Цей тікет було перейменовано на {0}, {1}!", + "renameDm":"Ваш тікет було перейменовано {0} на нашому сервері!", + "moveLog":"Цей тікет було переміщено до {0}, {1}!", + "moveDm":"Ваш тікет було переміщено {0} на нашому сервері!", + "addLog":"{0} було доданр до тікету {1}!", + "addDm":"{0} було додано до тікету на нашому сервері!", + "removeLog":"{0} було видалено тікету {1}!", + "removeDm":"{0} було видалено з тікету на нашому сервері!", + + "blacklistAddLog":"{0} був доданий до чорного списку {1}", + "blacklistRemoveLog":"{0} було видалено з чорного списку {1}", + "blacklistAddDm":"Вас було додано до чорного списку на нашому сервері!\nВідтепер ви не можете створити тікет!", + "blacklistRemoveDm":"Вас було видалено з чорного списку на нашому сервер!\nВідтепер ви знову можете створювати тікети!", + "clearLog":"{0} тікети було видалено {1}!" + } + }, + "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\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} не працює у ПП! Будь ласка, спробуйте ще раз на сервері!", + "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":"Ви повинні бути 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":"true", + "false":"false", + "syntax":"Синтаксіс", + "originalName":"Оригінальне ім'я", + "newName":"Нове ім'я", + "until":"Доки", + "validOptions":"Дійсні параметри", + "validPanels":"Дійсні панелі", + "autoclose":"Автозакриття", + "autodelete":"Autodelete", + "startupDate":"Дата запуску", + "version":"Версія", + "name":"Ім'я", + "role":"Роль", + "status":"Статус", + "claimed":"Запрошено", + "pinned":"Закріплено", + "creationDate":"Дата створення" + }, + "lowercase":{ + "text":"текст", + "html":"html", + "command":"команда", + "modal":"модал", + "button":"кнопка", + "dropdown":"список", + "method":"метод" + } + }, + "commands":{ + "reason":"Вкажіть необов'язкову причину, яку буде видно в логах.", + "help":"Отримайте список усіх доступних команд.", + "panel":"Створити повідомлення з випадаючим списком або кнопками (для створення тікета).", + "panelId":"Ідентифікатор панелі, яку ви хочете створити.", + "panelAutoUpdate":"Ви хочете, щоб ця панель автоматично оновлювалася при редагуванні?", + "ticket":"Миттєве створення тікета.", + "ticketId":"Ідентифікатор тікету, який ви хочете створити.", + "close":"Закрийте тікет, це вимкне можливість писати в цьому каналі. Цю дію завжди можна скасувати!", + "delete":"Видалити тікет, якщо увімкнено, буде створено транскрипт. Ця дія не може бути скасована!", + "deleteNoTranscript":"Видаліть цей тікет без створення стенограми.", + "reopen":"Повторно відкрийте тікет, це дозволить знову писати в цьому каналі.", + "claim":"Подати заявку на запрошення тікету. Цим ви можете повідомити своїй команді, що обробляєте цей тикет.", + "claimUser":"Запросиіть цей тікет не на себе, а на когось іншого.", + "unclaim":"Відмовитися від тікету. Цим ви можете повідомити своїй команді, що цей тікет знову вільний.", + "pin":"Закріпіть тікет. Це перемістить тікет нагору і додасть емодзі «📌» до його назви.", + "unpin":"Відкріпіть тікет. Тікет залишиться на своєму місці, але втратить емодзі «📌».", + "move":"Перемістіть тікет. Це змінить тип цього тікету.", + "moveId":"Ідентифікатор тікету, на який ви хочете перейти.", + "rename":"Перейменувати тікет. Це змінить назву каналу для цього тікета.", + "renameName":"Нова назва цього тікету.", + "add":"Додайте учасника до тікета. Це дозволить учаснику читати і писати в цьому тікеті.", + "addUser":"Учасник, якого потрібно додати.", + "remove":"Видалити учасника з тікета. Це вилучить можливість читання і запису для учасника в цьому тікеті.", + "removeUser":"Учасник, якого потрібно видалити", + "blacklist":"Керування чорним списком тікетів. Учасники, додані до цього списку, більше не можуть створювати тікети.", + "blacklistView":"Переглянути список поточного чорного списку.", + "blacklistAdd":"Додати учасника до чорного списку.", + "blacklistRemove":"Видалити учасника з чорного списку.", + "blacklistGet":"Отримайте детальну інформацію від учасника з чорного списку.", + "blacklistGetUser":"Учасник, від якого можна отримати детальну інформацію.", + "stats":"Переглядайте статистику від бота, учасника або тікета.", + "statsReset":"Обнулити всю статистику бота (і почати відлік з нуля).", + "statsGlobal":"Переглянути глобальну статистику.", + "statsUser":"Перегляд статистики від учасника на сервері.", + "statsUserUser":"Учасник для перегляду.", + "statsTicket":"Перегляд статистики тікета на сервері.", + "statsTicketTicket":"Тікет для перегляду.", + "clear":"Видалення декількох тікетів одночасно. Можна вказати додатковий фільтр.", + "clearFilter":"значення", + "clearFilters":{ + "all":"Усі", + "open":"Відкриті", + "close":"Закріті", + "claim":"Запрошені", + "unclaim":"Відпрошені", + "pin":"Закріплені", + "unpin":"Відкріплені", + "autoclose":"Авто-закриті" + }, + "autoclose":"Керуйте автозакриттям у тікеті.", + "autocloseDisable":"Вимкніть автозакриття в цьому тікеті.", + "autocloseEnable":"Увімкніть автозакриття в цьому тикеті", + "autocloseEnableTime":"Кількість годин, протягом яких тікет має бути неактивним, щоб його закрити.", + "autodelete":"Керуйте автовидаленням у тікеті.", + "autodeleteDisable":"Вимкніть автовидалення в цьому тікеті.", + "autodeleteEnable":"Ввімкніть автовидалення в цьому тікеті.", + "autodeleteEnableTime":"Кількість днів, протягом яких тікет має бути неактивним, щоб його видалити." + }, + "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":"Транскриптів створено" + } + } +} \ No newline at end of file From e410ceaa6484ea5ff5ad3e59913f48a1769e9885 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 31 Aug 2024 21:55:52 +0200 Subject: [PATCH 015/157] Added Ukrainian & Romanian languages --- languages/romanian.json | 477 +++++++++++++++++++++ languages/{ukraine.json => ukrainian.json} | 0 2 files changed, 477 insertions(+) create mode 100644 languages/romanian.json rename languages/{ukraine.json => ukrainian.json} (100%) diff --git a/languages/romanian.json b/languages/romanian.json new file mode 100644 index 0000000..f5fe9b2 --- /dev/null +++ b/languages/romanian.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"SankeDev", + "lastedited":"27/8/2024", + "language":"Romanian" + }, + "checker":{ + "system":{ + "typeError":"[EROARE]", + "headerOpenTicket":"OPEN TICKET", + "typeWarning":"[AVERTISMENT]", + "typeInfo":"[INFO]", + "headerConfigChecker":"VALIDATOR CONFIGURATIE", + "headerDescription":"verifica daca sunt erori in configuratia botului", + "footerError":"botul nu va porni pana cand toate cele {0} erori sunt reparate!", + "footerWarning":"este recomandat sa repari toate {0}'s inainte de pornire!", + "footerSupport":"SUPORT: {0} - DOCS: {1}", + "compactInformation":"foloseste {0} pentru mai multe informatii!", + "dataPath":"locatie", + "dataDocs":"docs", + "dataMessages":"mesaj" + }, + "messages":{ + "stringTooShort":"Acest string nu poate sa fie mai scurt de {0} caractere!", + "stringTooLong":"Acest string nu poate sa fie mai lung de {0} caractere!", + "stringLengthInvalid":"Acest string trebuie sa aiba minim {0} caractere!", + "stringStartsWith":"Acest string trebuie sa inceapa cu {0}!", + "stringEndsWith":"Acest string trebuie sa se termine cu {0}!", + "stringContains":"Acest string trebuie sa contina {0}!", + "stringChoices":"Acest string poate fi doar una dintre urmatoarele optiuni: {0}!", + "stringRegex":"String invalid!", + + "numberTooShort":"Acest numar nu poate fi mai scurt de {0} caractere!", + "numberTooLong":"Acest numar nu poate fi mai lung de {0} caractere!", + "numberLengthInvalid":"Acest numar trebuie sa aiba minim {0} caractere!", + "numberTooSmall":"Acest numar trebuie sa fie minim {0}!", + "numberTooLarge":"Acest numar trebuie sa fie maxim {0}!", + "numberNotEqual":"Acest numar trebuie sa fie {0}!", + "numberStep":"Acest numar trebuie sa fie un multiplu de {0}!", + "numberStepOffset":"Acest numar trebuie sa fie un multiplu de {0} si sa inceapa de la {1}!", + "numberStartsWith":"Acest numar trebuie sa inceapa cu {0}!", + "numberEndsWith":"Acest numar trebuie sa se termine cu {0}!", + "numberContains":"Acest numar trebuie sa contina {0}!", + "numberChoices":"This number can only be one of the following values: {0}!", + "numberFloat":"Acest numar nu poate fi zecimal!", + "numberNegative":"Acest numar nu poate fi negativ!", + "numberPositive":"Acest numar nu poate fi pozitiv!", + "numberZero":"Acest numar nu poate sa fie 0!", + + "booleanTrue":"Aceasta valoare boolean nu poate sa fie adevarata!", + "booleanFalse":"Aceasta valoare boolean nu poate sa fie falsa!", + + "arrayEmptyDisabled":"Acest array nu poate sa fie gol!", + "arrayEmptyRequired":"Acest array trebuie sa fie gol!", + "arrayTooShort":"Acest array trebuie sa aiba lungimea minima de {0}!", + "arrayTooLong":"Acest array trebuie sa aiba lungimea maxima de {0}!", + "arrayLengthInvalid":"Acest array trebuie sa aiba o lungime de {0}!", + "arrayInvalidTypes":"Acest array poate sa contina doar urmatoarele tipuri: {0}!", + "arrayDouble":"Acest array nu admite valori duplicate!", + + "discordInvalidId":"Acesta este un id {0} invalid !", + "discordInvalidIdOptions":"Acesta este un id {0} invalid! Poti sa folosesti doar dintre urmatoarele: {1}!", + "discordInvalidToken":"Acesta este un discord bot token invalid (din punct de vedere al sintaxei)!", + "colorInvalid":"Culoare Hex invalida!", + "emojiTooShort":"Acest string trebuie sa aiba cel putin {0} emojiuri!", + "emojiTooLong":"Acest string trebuie sa aiba cel mult {0} emojiuri!!", + "emojiCustom":"Acest emoji nu poate sa fie unul customizat!", + "emojiInvalid":"Acesta este un emoji invalid!", + "urlInvalid":"Acest URL este invalid!", + "urlInvalidHttp":"Acest url poate folosi doar protocolul https:// !", + "urlInvalidProtocol":"Acest url poate folosi doar protocoalele http:// & https:// !", + "urlInvalidHostname":"Acest url are un hostname nepermis!", + "urlInvalidExtension":"Acest URL are o extensive invalida! Alege intre : {0}!", + "urlInvalidPath":"Acest url are o locatie invalida!", + "idNotUnique":"Acest id nu este unic, foloseste altul!", + "idNonExistent":"Id-ul {0} nu exista!", + + "invalidType":"Aceasta propietate trebuie sa fie de tipul: {0}!", + "propertyMissing":"Propietatea {0} lipseste din acest obiect!", + "propertyOptional":"Propietatea {0} este optionala in acest obiect!", + "objectDisabled":"Acest obiect este dezactivat, activeaza-l folosind {0}!", + "nullInvalid":"Aceasta propietate nu poate sa fie nula!", + "switchInvalidType":"Folosete un tip dintre acestea: {0}!", + "objectSwitchInvalid":"Acest obiect trebuie sa fie un tip dintre acestea: {0}!", + + "invalidLanguage":"Aceasta este o limba invalida!", + "invalidButton":"Acest buton trebuie sa aiba cel putin un {0} sau {1}!", + "unusedOption":"Optiunea {0} nu este folosita nicaieri!", + "unusedQuestion":"Intrebarea {0} nu este folosita nicaieri!", + "dropdownOption":"Un meniul cu dropdown activat poate contine doar valori din categoria 'ticket'!" + } + }, + "actions":{ + "buttons":{ + "create":"Vezi Ticket", + "close":"Inchide Ticket", + "delete":"Sterge Ticket", + "reopen":"Redeschide Ticket", + "claim":"Claim Ticket", + "unclaim":"Unclaim Ticket", + "pin":"Fixeaza Ticket", + "unpin":"Defixeaza Ticket", + "clear":"Sterge Tickets", + "helpSwitchSlash":"Vezi Slash Commands", + "helpSwitchText":"Vezi Text Commands", + "helpPage":"Pagina {0}", + "withReason":"Cu motiv", + "withoutTranscript":"Fara Transcript" + }, + "titles":{ + "created":"Ticket Creat", + "close":"Ticket Inchis", + "delete":"Ticket Sters", + "reopen":"Ticket Redeschis", + "claim":"Ticket Claimed", + "unclaim":"Ticket Unclaimed", + "pin":"Ticket Fixat", + "unpin":"Ticket Defixat", + "rename":"Ticket Redenumit", + "move":"Ticket Mutat", + "add":"Ticket User Adaugat", + "remove":"Ticket User Sters", + + "help":"Comenzi disponibile", + "statsReset":"Reseteaza Stats", + "blacklistAdd":"Utilizator Blacklisted", + "blacklistRemove":"Utilizator Released", + "blacklistGet":"Blacklisted User", + "blacklistView":"Blacklist Curent", + "blacklistAddDm":"Adaugat la Blacklist", + "blacklistRemoveDm":"Sters din Blacklist", + "clear":"Tickets Curatate", + "roles":"Roluri Actualizate", + + "autoclose":"Ticket Inchis Automat", + "autocloseEnabled":"Inchidere Automata Activata", + "autocloseDisabled":"Inchidere Automata Dezactivata", + "autodelete":"Ticket Sters Automat", + "autodeleteEnabled":"Stergere Automata Activata", + "autodeleteDisabled":"Stergere Automata Dezactivata" + }, + "descriptions":{ + "create":"Ticket-ul tau a fost creat cu succes! Apasa pe butonul de mai jos pentru a-l vizualiza!", + "close":"Ticket-ul tau a fost inchis cu succes!", + "delete":"Ticket-ul tau a fost sters cu succes!", + "reopen":"Ticket-ul tau a fost redeschis cu succes!", + "claim":"Ticket-ul tau a fost revendicat cu succes!", + "unclaim":"Ticket-ul tau a fost eliberat cu succes!", + "pin":"Ticket-ul tau a fost fixat cu succes!", + "unpin":"Ticket-ul tau a fost defixat cu succes!", + "rename":"Ticket-ul tau a fost redenumit ( {0} ) cu succes!", + "move":"Ticket-ul tau a fost mutat in {0} cu succes!", + "add":"{0} a fost adaugat la ticket cu succes!", + "remove":"{0} a fost sters din ticket cu succes!", + + "helpExplanation":"`` => parametru mandatoriu\n`[nume]` => parametru optional", + "statsReset":"Toate statisticile botului au fost resetate cu succes!", + "statsError":"Nu se poate accesa statusul ticketului!\n{0} nu este un ticket!", + "blacklistAdd":"{0} a fost adaugat la blacklist cu succes!", + "blacklistRemove":"{0} a fost sters din blacklist cu succes!", + "blacklistGetSuccess":"{0} este blacklisted!", + "blacklistGetEmpty":"{0} nu este blacklisted!", + "blacklistViewEmpty":"Nu exista utilizatori blacklisted in acest server!", + "blacklistViewTip":"Foloseste \"/blacklist add\" pentru a adauga un user in blacklist!", + "clearVerify":"Esti sigur ca doresti sa stergi mai multe tickete?\nAceasta actiune nu poate fi anulata!", + "clearReady":"{0} tickete au fost sterse cu succes!", + "rolesEmpty":"Nu exista roluri de actualizat!", + + "autocloseLeave":"Acest ticket a fost inchis automatat deoarece creatorul a iesit din server.", + "autocloseTimeout":"Acest ticket a fost inchis automatat deoarece a fost inactiv pentru mai mult de `{0}h`!", + "autodeleteLeave":"Acest ticket a fost sters automatat deoarece creatorul a iesit din server.", + "autodeleteTimeout":"Acest ticket a fost sters automatat deoarece a fost inactiv pentru mai mult de `{0} zile`!", + "autocloseEnabled":"Inchiderea automata a fost activata in acest ticket!\nSe va inchide automat cand va fi inactiv pentru mai mult de `{0}h`!", + "autocloseDisabled":"Inchiderea automata a fost dezactivata in acest ticket!\nNu se va mai inchide automat!", + "autodeleteEnabled":"Stergerea automata a fost activata in acest ticket!\nSe va sterge automat cand va fi inactiv pentru mai mult de `{0} zile`!", + "autodeleteDisabled":"Stergerea automata a fost dezactivata in acest ticket!\nNu se va mai sterge automat!", + + "ticketMessageLimit":"Poti creea doar {0} tickete in acelasi timp!", + "ticketMessageAutoclose":"Acest ticket va fi inchis automat cand va deveni inactiv de mai mult de {0}h!", + "ticketMessageAutodelete":"Acest ticket va fi sters automat cand va deveni inactiv de mai mult de {0} zile!", + "panelReady":"Panelul poate fi gasit mai jos!\nAcest mesaj poate fi sters acum." + }, + "modal":{ + "closePlaceholder":"De ce inchizi acest ticket?", + "deletePlaceholder":"De ce stergi acest ticket?", + "reopenPlaceholder":"De ce redeschizi acest ticket?", + "claimPlaceholder":"De ce revendici acest ticket?", + "unclaimPlaceholder":"De ce eliberezi acest ticket?", + "pinPlaceholder":"De ce fixezi acest ticket?", + "unpinPlaceholder":"De ce defixezi acest ticket?" + }, + "logs":{ + "createLog":"Un nou ticket creat de {0}!", + "closeLog":"Acest ticket a fost inchis de {0}!", + "closeDm":"Ticketul tau a fost inchis in server!", + "deleteLog":"Acest ticket a fost sters de {0}!", + "deleteDm":"Ticketul tau a fost sters din server-ul nostru!", + "reopenLog":"Acest ticket a fost redeschis de {0}!", + "reopenDm":"Ticketul tau a fost redeschis in server!", + "claimLog":"Acest ticket a fost revendicat de {0}!", + "claimDm":"Ticketul tau a fost revendicat in server!", + "unclaimLog":"Acest ticket a fost eliberat de {0}!", + "unclaimDm":"Ticketul tau a fost eliberat in server!", + "pinLog":"Acest ticket a fost fixat de {0}!", + "pinDm":"Ticketul tau a fost fixat in server!", + "unpinLog":"Acest ticket a fost defixat de {0}!", + "unpinDm":"Ticketul tau a fost defixat in server!", + "renameLog":"Acest ticket a fost redenumit in {0} de {1}!", + "renameDm":"Ticketul tau a fost redenumit in server!", + "moveLog":"Acest ticket a fost mutat in {0} de {1}!", + "moveDm":"Ticketul tau a fost mutat in {0} in server!", + "addLog":"{0} a fost adaugat la acest ticket de {1}!", + "addDm":"{0} a fost adaugat la ticketul tau in server!", + "removeLog":"{0} a fost sters din acest ticket de {1}!", + "removeDm":"{0} a fost sters din ticketul tau in server!", + + "blacklistAddLog":"{0} a fost adaugat in blacklist de {1}!", + "blacklistRemoveLog":"{0} was removed from the blacklist by {1}", + "blacklistAddDm":"Ai fost adaugat in blacklist pe serverul nostru!\nNu mai poti creea tickete!", + "blacklistRemoveDm":"Ai fost scos din blacklist pe serverul nostru!\nPoti sa creezi tickete din nou!", + "clearLog":"{0} tickete au fost sterse de {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Vizualizeaza Transcript", + "ready":"Transcript Creat", + "textFileDescription":"Acesta este transcriptul in format text al ticketului sters!", + "htmlProgress":"Generarea transcriptului in format HTML a inceput, te rog asteapta...", + + "createdChannel":"Un nou transcript {0} a fost creat in server!", + "createdCreator":"Un nou transcript {0} a fost creat pentru unul dintre ticketele tale!", + "createdParticipant":"Un nou transcript {0} a fost creat pentru unul dintre ticketele la care ai participat!", + "createdActiveAdmin":"Un nou transcript {0} a fost creat pentru unul dintre ticketele la care ai fost admin!", + "createdEveryAdmin":"Un nou transcript {0} a fost creat pentru unul dintre ticketele la care ai fost admin!", + "createdOther":"Un nou transcript {0} a fost creat!" + }, + "errors":{ + "retry":"Reincearca", + "continue":"Sterge fara Transcript", + "backup":"Creeaza un Transcript de Backup", + "error":"Ceva nu a mers bine cand s-a incercat creearea transcriptului.\nCum doresti sa continui?\n\nAcest ticket nu va fi modificat pana cand nu apesi pe unul dintre butoane." + } + }, + "errors":{ + "titles":{ + "internalError":"Eroare Interna", + "optionMissing":"Optiune Comanda Lipsa", + "optionInvalid":"Optiune Comanda Invalida", + "unknownCommand":"Comanda Necunoscuta", + "noPermissions":"Fara Permisiuni", + "unknownTicket":"Ticket Necunoscut", + "deprecatedTicket":"Ticket Depricat", + "unknownOption":"Optiune Necunoscuta", + "unknownPanel":"Panel Necunoscut", + "notInGuild":"Nu este in server", + "channelRename":"Nu se poate redenumi canalul", + "busy":"Ticket ocupat" + }, + "descriptions":{ + "askForInfo":"Contacteaza ownerul botului pentru mai multe informatii.", + "askForInfoResolve":"Contacteaza ownerul botului pentru a rezolva aceasta problema.", + "internalError":"Nu s-a putut executa {0} aceasta comanda din cauza unei erori interne!", + "optionMissing":"Un parametru in aceasta comanda lipseste!", + "optionInvalid":"Un parametru in aceasta comanda este invalid!", + "optionInvalidChoose":"Alege una dintre urmatoarele optiuni:", + "unknownCommand":"Aceasta comanda nu exista!", + "noPermissions":"Nu ai permisiunea de a folosi aceasta {0}!", + "noPermissionsList":"Permisiuni necesare: (una dintre ele)", + "noPermissionsCooldown":"Nu ai permisiunea sa folosi aceasta {0} pentru ca ai un cooldown!", + "noPermissionsBlacklist":"Nu ai permisiunea sa folosi aceasta {0} pentru ca esti blacklisted!", + "noPermissionsLimitGlobal":"Nu ai permisiunea sa creezi un ticket pentru ca serverul a atins limita maxima de tickete!", + "noPermissionsLimitGlobalUser":"Nu ai permisiunea sa creezi un ticket pentru ca ai atins limita maxima de tickete!", + "noPermissionsLimitOption":"Nu ai permisiunea sa creezi un ticket pentru ca ai atins limita maxima de tickete pentru aceasta optiune!", + "noPermissionsLimitOptionUser":"Nu ai permisiunea sa creezi un ticket pentru ca ai atins limita maxima de tickete pentru aceasta optiune!", + "unknownTicket":"Incearca aceasta comanda din nou intr-un ticket valid!", + "deprecatedTicket":"Acest ticket este deprecat si nu mai poate fi folosit! Posibil sa fie dintr-o versiune veche Open Ticket!", + "notInGuild":"Aceasta {0} poate fi folosita doar in server!", + "channelRename":"Nu s-a putut redenumi canalul din cauza unor limitari Discord! Canalul va fi redenumit in 10 minute daca botul nu va fi repornit.", + "channelRenameSource":"Sursa acestei erori este: {0}", + "busy":"Nu se poate executa {0}!\nTicketul este in curs de procesare.\n\nTe rugam sa incerci din nou in cateva minute!" + }, + "optionInvalidReasons":{ + "stringRegex":"Valoarea nu respecta formatul necesar!", + "stringMinLength":"Valoarea trebuie sa aiba cel putin {0} caractere!", + "stringMaxLength":"Valoarea trebuie sa aiba cel mult {0} caractere!", + "numberInvalid":"Valoarea trebuie sa fie un numar!", + "numberMin":"Numarul trebuie sa fie cel putin {0}!", + "numberMax":"Numarul trebuie sa fie cel mult {0}!", + "numberDecimal":"Numarul nu poate fi zecimal!", + "numberNegative":"Numarul nu poate fi negativ!", + "numberPositive":"Numarul nu poate fi pozitiv!", + "numberZero":"Numarul nu poate fi 0!", + "channelNotFound":"Canalul nu a fost gasit!", + "userNotFound":"Utilizatorul nu a fost gasit!", + "roleNotFound":"Rolul nu a fost gasit!", + "memberNotFound":"Membrul nu a fost gasit!", + "mentionableNotFound":"Rolul mentionat nu a fost gasit!", + "channelType":"Tipul canalului este invalid!", + "notInGuild":"Aceasta optine poate fi folosita doar in server!" + }, + "permissions":{ + "developer":"Trebuie sa fii developer pentru a folosi aceasta comanda!", + "owner":"Trebuie sa fii owner pentru a folosi aceasta comanda!", + "admin":"Trebuie sa ai permisiunea de administrator pentru a folosi aceasta comanda!", + "moderator":"Trebuie sa ai permisiunea de moderator pentru a folosi aceasta comanda!", + "support":"Trebuie sa ai permisiunea de support pentru a folosi aceasta comanda!", + "member":"Trebuie sa fii membru pentru a folosi aceasta comanda!", + "discord-administrator":"Trebuie sa ai permisiunea de `ADMINISTRATOR` pentru a folosi aceasta comanda!" + }, + "actionInvalid":{ + "close":"Ticketul este deja inchis!", + "reopen":"Ticketul este deja deschis!", + "claim":"Ticketul este deja revendicat!", + "unclaim":"Ticketul nu este revendicat!", + "pin":"Ticketul este deja fixat!", + "unpin":"Ticketul nu este fixat!", + "add":"Utilizatorul este deja adaugat la acest ticket!", + "remove":"Utilizatorul nu este adaugat la acest ticket!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickete", + "reason":"Motiv", + "creator":"Creator", + "remaining":"Timp Ramas", + "added":"Adaugat", + "removed":"Sters", + "filter":"Filtru", + "claimedBy":"Revendicat de {0}", + "method":"Metoda", + "type":"Tip", + "blacklisted":"Blacklistat", + "panel":"Panel", + "command":"Comanda", + "system":"Sistem", + "true":"Adevarat", + "false":"Fals", + "syntax":"Sintaxa", + "originalName":"Nume Original", + "newName":"Nume Nou", + "until":"Pana", + "validOptions":"Optiuni Valide", + "validPanels":"Panels Valide", + "autoclose":"Inchidere Automata", + "autodelete":"Stergere Automata", + "startupDate":"Data Pornirii", + "version":"Versiune", + "name":"Nume", + "role":"Rol", + "status":"Status", + "claimed":"Revendicat", + "pinned":"Fixat", + "creationDate":"Data Crearii" + }, + "lowercase":{ + "text":"text", + "html":"html", + "command":"comanda", + "modal":"modal", + "button":"buton", + "dropdown":"dropdown", + "method":"metoda" + } + }, + "commands":{ + "reason":"Specifica un motiv optional care va fi vazut in logs.", + "help":"Vezi o lista cu toate comenzile disponibile.", + "panel":"Deschide un panel cu un dropdown sau butoane (pentru crearea de tickete).", + "panelId":"Id-ul panelului pe care vrei sa il deschizi.", + "panelAutoUpdate":"Activeaza sau dezactiveaza actualizarea automata a panelului.", + "ticket":"Creeaza instant un ticket.", + "ticketId":"Id-ul ticketului pe care vrei sa il folosesti.", + "close":"Inchide un ticket, asta dezactiveaza scrierea in acest canal. Poti oricand sa il redeschizi!", + "delete":"Sterge un ticket, acesta creeaza un transcript cand este activat. Aceasta actiune nu poate fi modificata!", + "deleteNoTranscript":"Sterge un ticket fara a crea un transcript.", + "reopen":"Redeschide un Ticket, asta activeaza scrierea in acest canal.", + "claim":"Revendica un ticket. Cu asta, poti sa iti anunti echipa ca tu te ocupi de acest ticket.", + "claimUser":"Revendica acest ticket pentru un alt membru.", + "unclaim":"Elibereaza un ticket. Cu asta, poti sa iti anunti echipa ca acest ticket este liber din nou.", + "pin":"Fixeaza un ticket. Acesta va fi mutat in partea de sus si va avea un emoij '📌' in nume.", + "unpin":"Defixeaza un ticket. Ticketul va ramane pe pozitia sa dar va pierde emoijul '📌'.", + "move":"Muta un ticket. Acesta va schimba tipul acestui ticket.", + "moveId":"Id-ul tipului de ticket in care vrei sa muti acest ticket.", + "rename":"Redenumeste un ticket. Acesta va schimba numele canalului acestui ticket.", + "renameName":"Noul nume al ticketului.", + "add":"Adauga un user la un ticket. Acesta ii va permite userului sa citeasca si sa scrie in acest ticket.", + "addUser":"Userul pe care vrei sa il adaugi.", + "remove":"Sterge un user dintr-un ticket. Acesta ii va elimina abilitatea de a citi si scrie pentru un user in acest ticket.", + "removeUser":"Userul pe care vrei sa il stergi.", + "blacklist":"Gestioneaza blacklist-ul in server. Userii blacklisted nu pot crea tickete.", + "blacklistView":"Vezi o lista cu toti userii blacklisted.", + "blacklistAdd":"Adauga un user in blacklist.", + "blacklistRemove":"Sterge un user din blacklist.", + "blacklistGet":"Vezi detaliile unui user blacklisted.", + "blacklistGetUser":"Userul pe care vrei sa il vezi.", + "stats":"Vezi statisticile unui bot, membru sau ticket.", + "statsReset":"Reseteaza toate statisticile botului (si incepe sa numere de la 0).", + "statsGlobal":"Vezi statisticile globale.", + "statsUser":"Vezi statisticile unui user in server.", + "statsUserUser":"Userul pe care vrei sa il vezi.", + "statsTicket":"Vezi statisticile unui ticket in server.", + "statsTicketTicket":"Ticketul pe care vrei sa il vezi.", + "clear":"Sterge mai multe tickete in acelasi timp. Un filtru optional poate fi aplicat pentru a sterge doar anumite tickete.", + "clearFilter":"valoare", + "clearFilters":{ + "all":"Toate", + "open":"Deschis", + "close":"Inchis", + "claim":"Revendicat", + "unclaim":"Nerevendicat", + "pin":"Fixat", + "unpin":"Nefixat", + "autoclose":"Inchis Automat" + }, + "autoclose":"Gestioneaza inchiderea automata a unui ticket.", + "autocloseDisable":"Dezactiveaza inchiderea automata in acest ticket.", + "autocloseEnable":"Activeaza inchiderea automata in acest ticket.", + "autocloseEnableTime":"Numarul de ore in care acest ticket trebuie sa fie inactiv pentru a fi inchis.", + "autodelete":"Gestioneaza stergerea automata a unui ticket.", + "autodeleteDisable":"Dezactiveaza stergerea automata in acest ticket.", + "autodeleteEnable":"Activeaza stergerea automata in acest ticket.", + "autodeleteEnableTime":"Numarul de zile in care acest ticket trebuie sa fie inactiv pentru a fi sters." + }, + "helpMenu":{ + "help":"Afiseaza o lista cu toate comenzile disponibile.", + "ticket":"Creeaza un ticket instant.", + "close":"Inchide un ticket, dezactivand scrierea in acest canal.", + "delete":"Sterge un ticket, creeaza un transcript cand este activat.", + "reopen":"Redeschide un ticket, activand scrierea in acest canal.", + "pin":"Fixeaza un ticket. Acesta va fi mutat in partea de sus si va avea un emoij '📌' in nume.", + "unpin":"Defixeaza un ticket. Ticketul va ramane pe pozitia sa dar va pierde emoijul '📌'.", + "move":"Muta un ticket. Acesta va schimba tipul acestui ticket.", + "rename":"Redenumeste un ticket. Acesta va schimba numele canalului acestui ticket.", + "claim":"Revendica un ticket. Cu asta, poti sa iti anunti echipa ca tu te ocupi de acest ticket.", + "unclaim":"Elibereaza un ticket. Cu asta, poti sa iti anunti echipa ca acest ticket este liber din nou.", + "add":"Adauga un user la un ticket. Acesta ii va permite userului sa citeasca si sa scrie in acest ticket.", + "remove":"Sterge un user dintr-un ticket. Acesta ii va elimina abilitatea de a citi si scrie pentru un user in acest ticket.", + "panel":"Deschide un panel cu un dropdown sau butoane (pentru crearea de tickete).", + "blacklistView":"Vezi o lista cu toti userii blacklisted.", + "blacklistAdd":"Adauga un user in blacklist.", + "blacklistRemove":"Sterge un user din blacklist.", + "blacklistGet":"Vezi detaliile unui user blacklisted.", + "statsGlobal":"Vezi statisticile globale.", + "statsTicket":"Vezi statisticile unui ticket in server.", + "statsUser":"Vezi statisticile unui user in server.", + "statsReset":"Reseteaza toate statisticile botului (si incepe sa numere de la 0).", + "autocloseDisable":"Dezactiveaza inchiderea automata in acest ticket.", + "autocloseEnable":"Activeaza inchiderea automata in acest ticket.", + "autodeleteDisable":"Dezactiveaza stergerea automata in acest ticket.", + "autodeleteEnable":"Activeaza stergerea automata in acest ticket." + }, + "stats":{ + "scopes":{ + "global":"Statistici Globale", + "system":"Statistici Sistem", + "user":"Statistici User", + "ticket":"Statistici Ticket", + "participants":"Participanti" + }, + "properties":{ + "ticketsCreated":"Tickete Create", + "ticketsClosed":"Tickete Inchise", + "ticketsDeleted":"Tickete Sterse", + "ticketsReopened":"Tickete Redeschise", + "ticketsAutoclosed":"Tickete Inchise Automat", + "ticketsClaimed":"Tickete Revendicate", + "ticketsPinned":"Tickete Fixate", + "ticketsMoved":"Tickete Mutate", + "usersBlacklisted":"Useri Blacklisted", + "transcriptsCreated":"Transcripturi Create" + } + } +} \ No newline at end of file diff --git a/languages/ukraine.json b/languages/ukrainian.json similarity index 100% rename from languages/ukraine.json rename to languages/ukrainian.json From 147eae05b361d0a056df45f2394ede72c8090758 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 1 Sep 2024 11:58:16 +0200 Subject: [PATCH 016/157] Testing pterodactyl compile support! --- index.js | 18 +++++++++--------- package.json | 3 +-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 5f2ba69..a35c823 100644 --- a/index.js +++ b/index.js @@ -2,14 +2,14 @@ //OR USE "npm start" TO INSTANTLY COMPILE & START THE BOT! const fs = require("fs") -const child = require("child_process") - -console.log("Removing prebuilds...") -fs.rmSync("./dist",{recursive:true,force:true}) - -console.log("Compiling the bot...") -//exit when only compilation is required -if (process.argv.includes("-%-compile")) process.exit(0) +if (process.argv.includes("-%-compile")){ + console.log("Removing prebuilds...") + fs.rmSync("./dist",{recursive:true,force:true}) + console.log("Compiling the bot...") + //exit on compilation + process.exit(0) +} //start the bot -require("./dist/src/index") \ No newline at end of file +console.log("Finished compilation!") +import("./dist/src/index.js") \ No newline at end of file diff --git a/package.json b/package.json index 06785c7..5a72c56 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,7 @@ ], "main": "index.js", "scripts": { - "build": "node index.js -%-compile && npx tsc -p ./tsconfig.json", - "start": "npm run build && node ./dist/src/index.js", + "start": "node index.js -%-compile && npx tsc -p ./tsconfig.json && node index.js", "test": "npm run start -- --dev-config --dev-database" }, "type": "commonjs", From 509e96144682699752e6b51afd950c70b8606f4a Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 1 Sep 2024 16:27:25 +0200 Subject: [PATCH 017/157] Typescript will now be compiled without CLI --- index.js | 59 +++++++++++++++++++++++++++++++++++++++++----------- package.json | 5 +++-- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/index.js b/index.js index a35c823..a947651 100644 --- a/index.js +++ b/index.js @@ -1,15 +1,50 @@ -//PLEASE COMPILE USING "npm run build" BEFORE STARTING THE BOT! -//OR USE "npm start" TO INSTANTLY COMPILE & START THE BOT! - +//@ts-check const fs = require("fs") -if (process.argv.includes("-%-compile")){ - console.log("Removing prebuilds...") - fs.rmSync("./dist",{recursive:true,force:true}) - console.log("Compiling the bot...") - //exit on compilation - process.exit(0) +const ts = require("typescript") +const nodepath = require('path') + +//REMOVE EXISTING BUILDS +console.log("OT: Removing Prebuilds...") +fs.rmSync("./dist",{recursive:true,force:true}) + +//COMPILE TYPESCRIPT +console.log("OT: Compiling Typescript...") +const configPath = nodepath.resolve('./tsconfig.json') +const configFile = ts.readConfigFile(configPath,ts.sys.readFile) + +//check for tsconfig errors +if (configFile.error){ + const message = ts.formatDiagnosticsWithColorAndContext([configFile.error],ts.createCompilerHost({})) + console.error(message) + process.exit(1) } -//start the bot -console.log("Finished compilation!") -import("./dist/src/index.js") \ No newline at end of file +//parse tsconfig file +const parsedConfig = ts.parseJsonConfigFileContent(configFile.config,ts.sys,nodepath.dirname(configPath)) + +//create program/compiler +const program = ts.createProgram({ + rootNames:parsedConfig.fileNames, + options:parsedConfig.options +}) + +//emit all compiled files +const emitResult = program.emit() + +//print emit errors/warnings (type errors) +const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) +const formattedDiagnostics = ts.formatDiagnosticsWithColorAndContext(allDiagnostics, ts.createCompilerHost(parsedConfig.options)) +console.log(formattedDiagnostics) + +//run with code +if (emitResult.emitSkipped){ + console.log("OT: Compilation Failed!") + process.exit(1) +}else{ + console.log("OT: Compilation Succeeded!") + if (process.argv.includes("-%-compile")) process.exit(0) //exit when only compile is required! + + //START THE BOT + console.log("OT: Starting Bot!") + require("./dist/src/index.js") +} \ No newline at end of file diff --git a/package.json b/package.json index 5a72c56..681b0d8 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,9 @@ ], "main": "index.js", "scripts": { - "start": "node index.js -%-compile && npx tsc -p ./tsconfig.json && node index.js", - "test": "npm run start -- --dev-config --dev-database" + "build": "node index.js -%-compile", + "start": "node index.js", + "test": "node index.js --dev-config --dev-database" }, "type": "commonjs", "license": "GPL-3.0-only", From bfa05297b277b8c00fd3cbcd1f7c9084dbb1bd0c Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 1 Sep 2024 17:30:25 +0200 Subject: [PATCH 018/157] Fixed plugins not loading on windows --- src/core/api/modules/plugin.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/core/api/modules/plugin.ts b/src/core/api/modules/plugin.ts index e73299d..ac01ef4 100644 --- a/src/core/api/modules/plugin.ts +++ b/src/core/api/modules/plugin.ts @@ -91,7 +91,12 @@ export class ODPlugin extends ODManagerData { async execute(debug:ODDebugger,force?:boolean): Promise { if ((this.enabled && !this.crashed) || force){ try{ - await import(nodepath.join("../../../../plugins/",this.getStartFile())) + //rewrite the path to make it work on windows & unix based systems + const workingDir = process.cwd().replace(/C:\\/i,"/") + const workingPath = nodepath.join("./dist/plugins/",this.getStartFile()) + const pluginPath = nodepath.join(workingDir,workingPath).split(nodepath.sep).join("/") + + await import(pluginPath) debug.console.log("Plugin \""+this.id.value+"\" loaded successfully!","plugin") this.executed = true return true From adae64bab9952496ec1b397ac120576472168f37 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 1 Sep 2024 17:53:29 +0200 Subject: [PATCH 019/157] Romanian & Ukrainian languages are now available! --- .github/CONTRIBUTING.md | 3 +- README.md | 12 ++++---- languages/romanian.json | 34 +++++++++++----------- languages/ukrainian.json | 42 ++++++++++++++-------------- src/core/api/defaults/language.ts | 2 ++ src/data/framework/languageLoader.ts | 4 ++- 6 files changed, 51 insertions(+), 46 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 86a645a..9322062 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -18,7 +18,8 @@ This includes new features, translations & bug fixes. 1. If your language doesn't exist yet, copy the [`english.json`](./../languages/english.json) file and rename it to your language. 2. You are allowed to use a little bit of `Google Translate` or `DeepL` when mentioned in the upload. (❌ Not Recommended) 3. Only translate existing values in the json file. Don't add or remove any values from the file. -4. If you are unable to translate something, leave it in `English`. +4. You're **NOT REQUIRED** to translate everything! If you only want to translate a part of it, it's okay! +5. If you are unable to translate something, leave it in `English`. #### Step 3: Metadata Metadata can be found in the `_TRANSLATION` variable. diff --git a/README.md b/README.md index 1dcc907..a6252d3 100644 --- a/README.md +++ b/README.md @@ -89,19 +89,19 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |---------------------|--------------------------|---------------| |🇬🇧 English |djj123dj |🟢 Up To Date | |🇳🇱 Dutch |djj123dj |🟢 Up To Date | -|🇵🇹 Portuguese |quiradon |🟢 Up To Date | -|🇨🇿 Czech |spyeye_ |🟢 Up To Date | |🇩🇪 German |benzorich |🟢 Up To Date | -|❓ Catalan |guillee3 |🟢 Up To Date | -|🇭🇺 Hungarian |kornel0706 |🟢 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 | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | -|🇷🇴 Romanian |sankedev |🟠 Temporary Outdated (beta) | |🇮🇹 Italian |maurizio26 |🟠 Temporary Outdated (beta) | |🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | |🇩🇰 Danish |.the_gamer |🟠 Temporary Outdated (beta) | |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | -|🇺🇦 Ukrainian |ander |🟠 Temporary Outdated (beta) | |🇹🇷 Turkish |0x15d3 |🟠 Temporary Outdated (beta) | |🇵🇱 Polish |mkevas |🟠 Temporary Outdated (beta) | |🇸🇮 Slovenian |n1kkec |🔴 Outdated | diff --git a/languages/romanian.json b/languages/romanian.json index f5fe9b2..9f883ec 100644 --- a/languages/romanian.json +++ b/languages/romanian.json @@ -2,7 +2,7 @@ "_TRANSLATION":{ "otversion":"v4.0.0", "translator":"SankeDev", - "lastedited":"27/8/2024", + "lastedited":"27/08/2024", "language":"Romanian" }, "checker":{ @@ -216,7 +216,7 @@ "removeDm":"{0} a fost sters din ticketul tau in server!", "blacklistAddLog":"{0} a fost adaugat in blacklist de {1}!", - "blacklistRemoveLog":"{0} was removed from the blacklist by {1}", + "blacklistRemoveLog":"{0} a fost eliminat din blacklist de {1}!", "blacklistAddDm":"Ai fost adaugat in blacklist pe serverul nostru!\nNu mai poti creea tickete!", "blacklistRemoveDm":"Ai fost scos din blacklist pe serverul nostru!\nPoti sa creezi tickete din nou!", "clearLog":"{0} tickete au fost sterse de {1}!" @@ -374,24 +374,24 @@ "panelAutoUpdate":"Activeaza sau dezactiveaza actualizarea automata a panelului.", "ticket":"Creeaza instant un ticket.", "ticketId":"Id-ul ticketului pe care vrei sa il folosesti.", - "close":"Inchide un ticket, asta dezactiveaza scrierea in acest canal. Poti oricand sa il redeschizi!", - "delete":"Sterge un ticket, acesta creeaza un transcript cand este activat. Aceasta actiune nu poate fi modificata!", + "close":"Inchide un ticket.", + "delete":"Sterge un ticket.", "deleteNoTranscript":"Sterge un ticket fara a crea un transcript.", - "reopen":"Redeschide un Ticket, asta activeaza scrierea in acest canal.", - "claim":"Revendica un ticket. Cu asta, poti sa iti anunti echipa ca tu te ocupi de acest ticket.", + "reopen":"Redeschide un ticket.", + "claim":"Revendica un ticket.", "claimUser":"Revendica acest ticket pentru un alt membru.", - "unclaim":"Elibereaza un ticket. Cu asta, poti sa iti anunti echipa ca acest ticket este liber din nou.", - "pin":"Fixeaza un ticket. Acesta va fi mutat in partea de sus si va avea un emoij '📌' in nume.", - "unpin":"Defixeaza un ticket. Ticketul va ramane pe pozitia sa dar va pierde emoijul '📌'.", - "move":"Muta un ticket. Acesta va schimba tipul acestui ticket.", - "moveId":"Id-ul tipului de ticket in care vrei sa muti acest ticket.", - "rename":"Redenumeste un ticket. Acesta va schimba numele canalului acestui ticket.", + "unclaim":"Elibereaza un ticket.", + "pin":"Fixeaza un ticket.", + "unpin":"Defixeaza un ticket.", + "move":"Muta un ticket.", + "moveId":"Id-ul tipului de optiune in care vrei sa muti acest ticket.", + "rename":"Redenumeste un ticket.", "renameName":"Noul nume al ticketului.", - "add":"Adauga un user la un ticket. Acesta ii va permite userului sa citeasca si sa scrie in acest ticket.", + "add":"Adauga un user la un ticket.", "addUser":"Userul pe care vrei sa il adaugi.", - "remove":"Sterge un user dintr-un ticket. Acesta ii va elimina abilitatea de a citi si scrie pentru un user in acest ticket.", + "remove":"Sterge un user dintr-un ticket.", "removeUser":"Userul pe care vrei sa il stergi.", - "blacklist":"Gestioneaza blacklist-ul in server. Userii blacklisted nu pot crea tickete.", + "blacklist":"Gestioneaza blacklist-ul in server.", "blacklistView":"Vezi o lista cu toti userii blacklisted.", "blacklistAdd":"Adauga un user in blacklist.", "blacklistRemove":"Sterge un user din blacklist.", @@ -404,8 +404,8 @@ "statsUserUser":"Userul pe care vrei sa il vezi.", "statsTicket":"Vezi statisticile unui ticket in server.", "statsTicketTicket":"Ticketul pe care vrei sa il vezi.", - "clear":"Sterge mai multe tickete in acelasi timp. Un filtru optional poate fi aplicat pentru a sterge doar anumite tickete.", - "clearFilter":"valoare", + "clear":"Sterge mai multe tickete in acelasi timp.", + "clearFilter":"Filtrul pentru ștergerea biletelor.", "clearFilters":{ "all":"Toate", "open":"Deschis", diff --git a/languages/ukrainian.json b/languages/ukrainian.json index d0cf3e0..8de83cd 100644 --- a/languages/ukrainian.json +++ b/languages/ukrainian.json @@ -2,7 +2,7 @@ "_TRANSLATION":{ "otversion":"v4.0.0", "translator":"Anderskiy", - "lastedited":"31/8/2024", + "lastedited":"31/08/2024", "language":"Ukrainian" }, "checker":{ @@ -215,8 +215,8 @@ "removeLog":"{0} було видалено тікету {1}!", "removeDm":"{0} було видалено з тікету на нашому сервері!", - "blacklistAddLog":"{0} був доданий до чорного списку {1}", - "blacklistRemoveLog":"{0} було видалено з чорного списку {1}", + "blacklistAddLog":"{0} був доданий до чорного списку {1}!", + "blacklistRemoveLog":"{0} було видалено з чорного списку {1}!", "blacklistAddDm":"Вас було додано до чорного списку на нашому сервері!\nВідтепер ви не можете створити тікет!", "blacklistRemoveDm":"Вас було видалено з чорного списку на нашому сервер!\nВідтепер ви знову можете створювати тікети!", "clearLog":"{0} тікети було видалено {1}!" @@ -374,24 +374,24 @@ "panelAutoUpdate":"Ви хочете, щоб ця панель автоматично оновлювалася при редагуванні?", "ticket":"Миттєве створення тікета.", "ticketId":"Ідентифікатор тікету, який ви хочете створити.", - "close":"Закрийте тікет, це вимкне можливість писати в цьому каналі. Цю дію завжди можна скасувати!", - "delete":"Видалити тікет, якщо увімкнено, буде створено транскрипт. Ця дія не може бути скасована!", + "close":"Закрийте тікет.", + "delete":"Видалити квиток.", "deleteNoTranscript":"Видаліть цей тікет без створення стенограми.", - "reopen":"Повторно відкрийте тікет, це дозволить знову писати в цьому каналі.", - "claim":"Подати заявку на запрошення тікету. Цим ви можете повідомити своїй команді, що обробляєте цей тикет.", + "reopen":"Повторно відкрийте тікет.", + "claim":"Подати заявку на запрошення тікету.", "claimUser":"Запросиіть цей тікет не на себе, а на когось іншого.", - "unclaim":"Відмовитися від тікету. Цим ви можете повідомити своїй команді, що цей тікет знову вільний.", - "pin":"Закріпіть тікет. Це перемістить тікет нагору і додасть емодзі «📌» до його назви.", - "unpin":"Відкріпіть тікет. Тікет залишиться на своєму місці, але втратить емодзі «📌».", - "move":"Перемістіть тікет. Це змінить тип цього тікету.", - "moveId":"Ідентифікатор тікету, на який ви хочете перейти.", - "rename":"Перейменувати тікет. Це змінить назву каналу для цього тікета.", + "unclaim":"Відмовитися від тікету.", + "pin":"Закріпіть тікет.", + "unpin":"Відкріпіть тікет.", + "move":"Перемістіть тікет.", + "moveId":"Ідентифікатор параметр, на який ви хочете перейти.", + "rename":"Перейменувати тікет.", "renameName":"Нова назва цього тікету.", - "add":"Додайте учасника до тікета. Це дозволить учаснику читати і писати в цьому тікеті.", + "add":"Додайте учасника до тікета.", "addUser":"Учасник, якого потрібно додати.", - "remove":"Видалити учасника з тікета. Це вилучить можливість читання і запису для учасника в цьому тікеті.", + "remove":"Видалити учасника з тікета.", "removeUser":"Учасник, якого потрібно видалити", - "blacklist":"Керування чорним списком тікетів. Учасники, додані до цього списку, більше не можуть створювати тікети.", + "blacklist":"Керування чорним списком тікетів.", "blacklistView":"Переглянути список поточного чорного списку.", "blacklistAdd":"Додати учасника до чорного списку.", "blacklistRemove":"Видалити учасника з чорного списку.", @@ -404,8 +404,8 @@ "statsUserUser":"Учасник для перегляду.", "statsTicket":"Перегляд статистики тікета на сервері.", "statsTicketTicket":"Тікет для перегляду.", - "clear":"Видалення декількох тікетів одночасно. Можна вказати додатковий фільтр.", - "clearFilter":"значення", + "clear":"Видалення декількох тікетів одночасно.", + "clearFilter":"Фільтр для очищення квитків.", "clearFilters":{ "all":"Усі", "open":"Відкриті", @@ -418,12 +418,12 @@ }, "autoclose":"Керуйте автозакриттям у тікеті.", "autocloseDisable":"Вимкніть автозакриття в цьому тікеті.", - "autocloseEnable":"Увімкніть автозакриття в цьому тикеті", - "autocloseEnableTime":"Кількість годин, протягом яких тікет має бути неактивним, щоб його закрити.", + "autocloseEnable":"Увімкніть автозакриття в цьому тикеті.", + "autocloseEnableTime":"Кількість годин.", "autodelete":"Керуйте автовидаленням у тікеті.", "autodeleteDisable":"Вимкніть автовидалення в цьому тікеті.", "autodeleteEnable":"Ввімкніть автовидалення в цьому тікеті.", - "autodeleteEnableTime":"Кількість днів, протягом яких тікет має бути неактивним, щоб його видалити." + "autodeleteEnableTime":"Кількість днів." }, "helpMenu":{ "help":"Отримайте список усіх доступних команд.", diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index 255101e..87d4ff1 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -453,6 +453,8 @@ export interface ODLanguageManagerIds_Default { "openticket:catalan":ODLanguage, "openticket:hungarian":ODLanguage, "openticket:spanish":ODLanguage, + "openticket:romanian":ODLanguage, + "openticket:ukrainian":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 9e37e1a..67f1b40 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -11,10 +11,12 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODLanguage("openticket:catalan","catalan.json")) openticket.languages.add(new api.ODLanguage("openticket:hungarian","hungarian.json")) openticket.languages.add(new api.ODLanguage("openticket:spanish","spanish.json")) + openticket.languages.add(new api.ODLanguage("openticket:romanian","romanian.json")) + openticket.languages.add(new api.ODLanguage("openticket:ukrainian","ukrainian.json")) //list for config checker const languageList = openticket.defaults.getDefault("languageList") - languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish") + languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian") openticket.defaults.setDefault("languageList",languageList) /** How to add more languages? From 4e030bf95b60d846d95185eb8bcc7ef2b23cc5ac Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 1 Sep 2024 18:38:08 +0200 Subject: [PATCH 020/157] Fixed config checker bugs & added new flags --- README.md | 19 +++++-- index.js | 82 ++++++++++++++--------------- src/core/api/defaults/checker.ts | 5 +- src/core/api/defaults/flag.ts | 2 + src/core/api/modules/checker.ts | 14 +++-- src/data/framework/checkerLoader.ts | 1 + src/data/framework/flagLoader.ts | 2 + 7 files changed, 76 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index a6252d3..67d34c6 100644 --- a/README.md +++ b/README.md @@ -80,9 +80,22 @@ The team behind Open Ticket! ### ❤️ Sponsors A big thanks to all our sponsors! Without them, it wouldn't be possible to create this project! -|Profile Picture|Profile Picture|Profile Picture| -|----|-|-| -|**[SpyEye](https://github.com/SpyEye2)**|**[DOSEV5](https://github.com/DOSEV5)**|**[Mods HD](https://github.com/mods-hd)**| + + + + + + + + + +
Profile PictureProfile Picture
DOSEV5roppl3r
+ +**Past Sponsors:**
+ +SpyEye +Mods HD + ### 💬 Translators |Language |Maintainer (discord name) |Status | diff --git a/index.js b/index.js index a947651..fd4d6a3 100644 --- a/index.js +++ b/index.js @@ -3,48 +3,48 @@ const fs = require("fs") const ts = require("typescript") const nodepath = require('path') -//REMOVE EXISTING BUILDS -console.log("OT: Removing Prebuilds...") -fs.rmSync("./dist",{recursive:true,force:true}) +if (!process.argv.includes("--no-compile")){ + //REMOVE EXISTING BUILDS + console.log("OT: Removing Prebuilds...") + fs.rmSync("./dist",{recursive:true,force:true}) -//COMPILE TYPESCRIPT -console.log("OT: Compiling Typescript...") -const configPath = nodepath.resolve('./tsconfig.json') -const configFile = ts.readConfigFile(configPath,ts.sys.readFile) + //COMPILE TYPESCRIPT + console.log("OT: Compiling Typescript...") + const configPath = nodepath.resolve('./tsconfig.json') + const configFile = ts.readConfigFile(configPath,ts.sys.readFile) -//check for tsconfig errors -if (configFile.error){ - const message = ts.formatDiagnosticsWithColorAndContext([configFile.error],ts.createCompilerHost({})) - console.error(message) - process.exit(1) + //check for tsconfig errors + if (configFile.error){ + const message = ts.formatDiagnosticsWithColorAndContext([configFile.error],ts.createCompilerHost({})) + console.error(message) + process.exit(1) + } + + //parse tsconfig file + const parsedConfig = ts.parseJsonConfigFileContent(configFile.config,ts.sys,nodepath.dirname(configPath)) + + //create program/compiler + const program = ts.createProgram({ + rootNames:parsedConfig.fileNames, + options:parsedConfig.options + }) + + //emit all compiled files + const emitResult = program.emit() + + //print emit errors/warnings (type errors) + const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) + const formattedDiagnostics = ts.formatDiagnosticsWithColorAndContext(allDiagnostics, ts.createCompilerHost(parsedConfig.options)) + console.log(formattedDiagnostics) + + if (emitResult.emitSkipped || allDiagnostics.find((d) => d.category == ts.DiagnosticCategory.Error || d.category == ts.DiagnosticCategory.Warning)){ + console.log("OT: Compilation Failed!") + process.exit(1) + } } -//parse tsconfig file -const parsedConfig = ts.parseJsonConfigFileContent(configFile.config,ts.sys,nodepath.dirname(configPath)) - -//create program/compiler -const program = ts.createProgram({ - rootNames:parsedConfig.fileNames, - options:parsedConfig.options -}) - -//emit all compiled files -const emitResult = program.emit() - -//print emit errors/warnings (type errors) -const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) -const formattedDiagnostics = ts.formatDiagnosticsWithColorAndContext(allDiagnostics, ts.createCompilerHost(parsedConfig.options)) -console.log(formattedDiagnostics) - -//run with code -if (emitResult.emitSkipped){ - console.log("OT: Compilation Failed!") - process.exit(1) -}else{ - console.log("OT: Compilation Succeeded!") - if (process.argv.includes("-%-compile")) process.exit(0) //exit when only compile is required! - - //START THE BOT - console.log("OT: Starting Bot!") - require("./dist/src/index.js") -} \ No newline at end of file +//START BOT +console.log("OT: Compilation Succeeded!") +if (process.argv.includes("--compile-only")) process.exit(0) //exit when only compile is required! +console.log("OT: Starting Bot!") +require("./dist/src/index.js") \ No newline at end of file diff --git a/src/core/api/defaults/checker.ts b/src/core/api/defaults/checker.ts index 69e6d53..e12773d 100644 --- a/src/core/api/defaults/checker.ts +++ b/src/core/api/defaults/checker.ts @@ -345,6 +345,7 @@ export class ODCheckerTranslationRegister_Default extends ODCheckerTranslationRe */ export interface ODCheckerFunctionManagerIds_Default { "openticket:unused-options":ODCheckerFunction, + "openticket:unused-questions":ODCheckerFunction, "openticket:dropdown-options":ODCheckerFunction } @@ -355,14 +356,14 @@ export interface ODCheckerFunctionManagerIds_Default { * This default class is made for the global variable `openticket.checkers.functions`! */ export class ODCheckerFunctionManager_Default extends ODCheckerFunctionManager { - get(id:CheckerFunctionId): ODCheckerManagerIds_Default[CheckerFunctionId] + get(id:CheckerFunctionId): ODCheckerFunctionManagerIds_Default[CheckerFunctionId] get(id:ODValidId): ODCheckerFunction|null get(id:ODValidId): ODCheckerFunction|null { return super.get(id) } - remove(id:CheckerFunctionId): ODCheckerManagerIds_Default[CheckerFunctionId] + remove(id:CheckerFunctionId): ODCheckerFunctionManagerIds_Default[CheckerFunctionId] remove(id:ODValidId): ODCheckerFunction|null remove(id:ODValidId): ODCheckerFunction|null { diff --git a/src/core/api/defaults/flag.ts b/src/core/api/defaults/flag.ts index 0d4b835..7c9a459 100644 --- a/src/core/api/defaults/flag.ts +++ b/src/core/api/defaults/flag.ts @@ -21,6 +21,8 @@ export interface ODFlagManagerIds_Default { "openticket:no-plugins":ODFlag, "openticket:soft-plugins":ODFlag, "openticket:force-slash-update":ODFlag, + "openticket:no-compile":ODFlag, + "openticket:compile-only":ODFlag, } /**## ODFlagManager_Default `default_class` diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 3b0138e..90d0249 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -1192,12 +1192,20 @@ export class ODCheckerCustomStructure_EmojiString extends ODCheckerStringStructu const newOptions = options ?? {} newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => { const lt = checker.locationTraceDeref(locationTrace) - if (typeof value != "string") return false - else if ([...value].length < minLength){ + + const emojis: string[] = [] + const emojiSplitRegex = /(?:(?:\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])|(?:))/g + let emoji = emojiSplitRegex.exec(value) + while (emoji != null){ + emojis.push(emoji[0]) + emoji = emojiSplitRegex.exec(value) + } + + if (emojis.length < minLength){ checker.createMessage("openticket:emoji-too-short","error",`This string needs to have at least ${minLength} emoji's!`,lt,null,[maxLength.toString()],this.id,(this.options.docs ?? null)) return false - }else if ([...value].length > maxLength){ + }else if (emojis.length > maxLength){ checker.createMessage("openticket:emoji-too-long","error",`This string needs to have at most ${maxLength} emoji's!`,lt,null,[maxLength.toString()],this.id,(this.options.docs ?? null)) return false }else if (!allowCustomDiscordEmoji && //.test(value)){ diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts index 667fa1b..76d5963 100644 --- a/src/data/framework/checkerLoader.ts +++ b/src/data/framework/checkerLoader.ts @@ -12,6 +12,7 @@ export const loadAllConfigCheckers = async () => { export const loadAllConfigCheckerFunctions = async () => { openticket.checkers.functions.add(new api.ODCheckerFunction("openticket:unused-options",defaultUnusedOptionsFunction)) + openticket.checkers.functions.add(new api.ODCheckerFunction("openticket:unused-questions",defaultUnusedQuestionsFunction)) openticket.checkers.functions.add(new api.ODCheckerFunction("openticket:dropdown-options",defaultDropdownOptionsFunction)) } diff --git a/src/data/framework/flagLoader.ts b/src/data/framework/flagLoader.ts index 7552019..5964046 100644 --- a/src/data/framework/flagLoader.ts +++ b/src/data/framework/flagLoader.ts @@ -13,4 +13,6 @@ export const loadAllFlags = async () => { openticket.flags.add(new api.ODFlag("openticket:no-plugins","No Plugins","Disable all Open Ticket plugins!","--no-plugins",["-np"])) openticket.flags.add(new api.ODFlag("openticket:soft-plugins","Soft Plugins","Don't crash the bot when a plugin crashes!","--soft-plugins",["-sp"])) openticket.flags.add(new api.ODFlag("openticket:force-slash-update","Force Slash Update","Force update all slash commands.","--force-slash",["-fs"])) + openticket.flags.add(new api.ODFlag("openticket:no-compile","No Compile","Disable compilation of plugins & bot before starting.","--no-compile",[])) + openticket.flags.add(new api.ODFlag("openticket:compile-only","Compile Only","This description will never be shown because the bot wouldn't run when this flag is enabled :)","--compile-only",[])) } \ No newline at end of file From c1c80fc04d9f438b7bc7a05f26e35169efce9cfa Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 1 Sep 2024 20:55:50 +0200 Subject: [PATCH 021/157] Small improvements --- languages/spanish.json | 2 +- package.json | 3 +- src/core/api/api.ts | 1 + src/core/api/defaults/checker.ts | 3 +- src/core/api/defaults/event.ts | 15 +++-- src/core/api/defaults/plugin.ts | 77 +++++++++++++++++++++++++ src/core/api/main.ts | 6 +- src/core/api/modules/checker.ts | 2 +- src/core/api/modules/config.ts | 10 ++-- src/core/api/modules/defaults.ts | 3 - src/core/api/modules/language.ts | 9 ++- src/core/api/modules/plugin.ts | 87 ----------------------------- src/data/framework/checkerLoader.ts | 21 ++----- src/data/framework/eventLoader.ts | 7 ++- src/index.ts | 9 +-- 15 files changed, 117 insertions(+), 138 deletions(-) create mode 100644 src/core/api/defaults/plugin.ts diff --git a/languages/spanish.json b/languages/spanish.json index d5398e3..da41fd5 100644 --- a/languages/spanish.json +++ b/languages/spanish.json @@ -2,7 +2,7 @@ "_TRANSLATION":{ "otversion":"v4.0.0", "translator":"Redactado & Josuens", - "lastedited":"22/8/2024", + "lastedited":"22/08/2024", "language":"Spanish" }, "checker":{ diff --git a/package.json b/package.json index 681b0d8..a497fb4 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "scripts": { "build": "node index.js -%-compile", "start": "node index.js", - "test": "node index.js --dev-config --dev-database" + "test": "node index.js --dev-config --dev-database", + "testnc": "node index.js --no-compile --dev-config --dev-database" }, "type": "commonjs", "license": "GPL-3.0-only", diff --git a/src/core/api/api.ts b/src/core/api/api.ts index 387de94..7f393a0 100644 --- a/src/core/api/api.ts +++ b/src/core/api/api.ts @@ -32,6 +32,7 @@ export * from "./defaults/base" export * from "./defaults/event" export * from "./defaults/config" export * from "./defaults/database" +export * from "./defaults/plugin" export * from "./defaults/checker" export * from "./defaults/client" export * from "./defaults/language" diff --git a/src/core/api/defaults/checker.ts b/src/core/api/defaults/checker.ts index e12773d..24ada35 100644 --- a/src/core/api/defaults/checker.ts +++ b/src/core/api/defaults/checker.ts @@ -65,6 +65,7 @@ export class ODCheckerRenderer_Default extends ODCheckerRenderer { horizontalFiller: string = "=" verticalFiller: string = "|" descriptionSeparator: string = " => " + headerSeparator: string = " => " footerTipPrefix: string = "=> " disableHeader: boolean = false @@ -93,7 +94,7 @@ export class ODCheckerRenderer_Default extends ODCheckerRenderer { if (!renderEmpty && !hasErrors && !hasWarnings && (!hasInfo || compact)) return [] - const headerText = ansis.bold.hex("#f8ba00")(t.headerOpenticket)+" "+t.headerConfigchecker+" => "+ansis.hex("#f8ba00")(t.headerDescription) + const headerText = ansis.bold.hex("#f8ba00")(t.headerOpenticket)+" "+t.headerConfigchecker+this.headerSeparator+ansis.hex("#f8ba00")(t.headerDescription) const footerErrorText = (hasErrors) ? this.footerTipPrefix+ansis.gray(tm.insertTranslationParams(t.footerError,[ansis.bold.red(t.error)])) : "" const footerWarningText = (hasWarnings) ? this.footerTipPrefix+ansis.gray(tm.insertTranslationParams(t.footerWarning,[ansis.bold.yellow(t.warning)])) : "" const footerSupportText = tm.insertTranslationParams(t.footerSupport,[ansis.green("https://discord.dj-dj.be"),ansis.green("https://otdocs.dj-dj.be")]) diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts index c9b02b1..200af2d 100644 --- a/src/core/api/defaults/event.ts +++ b/src/core/api/defaults/event.ts @@ -3,7 +3,6 @@ /////////////////////////////////////// //BASE MODULES import { ODPromiseVoid, ODValidId } from "../modules/base" -import { ODPluginClassManager, ODPluginEventManager, ODPluginManager } from "../modules/plugin" import { ODConsoleManager, ODError } from "../modules/console" import { ODCheckerResult, ODCheckerStorage } from "../modules/checker" import { ODDefaultsManager } from "../modules/defaults" @@ -13,7 +12,7 @@ import { ODEvent, ODEventManager } from "../modules/event" import * as discord from "discord.js" //DEFAULT MODULES -import { ODVersionManager_Default } from "./base" +import { ODPluginClassManager_Default, ODPluginManager_Default } from "./plugin" import { ODConfigManager_Default} from "./config" import { ODDatabaseManager_Default } from "./database" import { ODFlagManager_Default } from "./flag" @@ -53,12 +52,9 @@ export interface ODEventIds_Default { "afterErrorHandling": ODEvent_Default<(error:Error, origin:NodeJS.UncaughtExceptionOrigin, message:ODError) => ODPromiseVoid> //plugins - "afterPluginsLoaded": ODEvent_Default<(plugins:ODPluginManager) => ODPromiseVoid> - "onPluginClassLoad": ODEvent_Default<(classes:ODPluginClassManager, plugins:ODPluginManager) => ODPromiseVoid> - "afterPluginClassesLoaded": ODEvent_Default<(classes:ODPluginClassManager, plugins:ODPluginManager) => ODPromiseVoid> - "onPluginEventLoad": ODEvent_Default<(classes:ODPluginEventManager, plugins:ODPluginManager) => ODPromiseVoid> - "afterPluginEventsLoaded": ODEvent_Default<(classes:ODPluginEventManager, plugins:ODPluginManager) => ODPromiseVoid> - + "afterPluginsLoaded": ODEvent_Default<(plugins:ODPluginManager_Default) => ODPromiseVoid> + "onPluginClassLoad": ODEvent_Default<(classes:ODPluginClassManager_Default, plugins:ODPluginManager_Default) => ODPromiseVoid> + "afterPluginClassesLoaded": ODEvent_Default<(classes:ODPluginClassManager_Default, plugins:ODPluginManager_Default) => ODPromiseVoid> "onFlagLoad": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> "afterFlagsLoaded": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> @@ -277,6 +273,9 @@ export interface ODEventIds_Default { "afterStartScreensLoaded": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid> "onStartScreenRender": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid> "afterStartScreensRendered": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid> + + //ready + "onReadyForUsage": ODEvent_Default<() => ODPromiseVoid> } /**## ODEventManager_Default `default_class` diff --git a/src/core/api/defaults/plugin.ts b/src/core/api/defaults/plugin.ts new file mode 100644 index 0000000..4bd5f77 --- /dev/null +++ b/src/core/api/defaults/plugin.ts @@ -0,0 +1,77 @@ +/////////////////////////////////////// +//DEFAULT POST MODULE +/////////////////////////////////////// +import { ODValidId, ODManagerData } from "../modules/base" +import { ODPlugin, ODPluginClassManager, ODPluginManager } from "../modules/plugin" + +/**## ODPluginManagerIds_Default `type` + * This type is an array of ids available in the `ODPluginManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODPluginManagerIds_Default {} + +/**## ODPluginManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODPluginManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.plugins`! + */ +export class ODPluginManager_Default extends ODPluginManager { + declare classes: ODPluginClassManager_Default + + get(id:PluginId): ODPluginManagerIds_Default[PluginId] + get(id:ODValidId): ODPlugin|null + + get(id:ODValidId): ODPlugin|null { + return super.get(id) + } + + remove(id:PluginId): ODPluginManagerIds_Default[PluginId] + remove(id:ODValidId): ODPlugin|null + + remove(id:ODValidId): ODPlugin|null { + return super.remove(id) + } + + exists(id:keyof ODPluginManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODPluginClassManagerIds_Default `type` + * This type is an array of ids available in the `ODPluginClassManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODPluginClassManagerIds_Default {} + +/**## ODPluginClassManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODPluginClassManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.plugins.classes`! + */ +export class ODPluginClassManager_Default extends ODPluginClassManager { + get(id:PluginClassId): ODPluginClassManagerIds_Default[PluginClassId] + get(id:ODValidId): ODManagerData|null + + get(id:ODValidId): ODManagerData|null { + return super.get(id) + } + + remove(id:PluginClassId): ODPluginClassManagerIds_Default[PluginClassId] + remove(id:ODValidId): ODManagerData|null + + remove(id:ODValidId): ODManagerData|null { + return super.remove(id) + } + + exists(id:keyof ODPluginClassManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/main.ts b/src/core/api/main.ts index 84a3873..b65ab05 100644 --- a/src/core/api/main.ts +++ b/src/core/api/main.ts @@ -1,12 +1,12 @@ //BASE MODULES import { ODEnvHelper, ODVersion } from "./modules/base" -import { ODPluginManager } from "./modules/plugin" import { ODConsoleManager, ODConsoleMessage, ODConsoleMessageParam, ODConsoleMessageTypes, ODDebugFileManager, ODDebugger, ODError } from "./modules/console" import { ODCheckerStorage } from "./modules/checker" import { ODDefaultsManager } from "./modules/defaults" //DEFAULT MODULES import { ODVersionManager_Default } from "./defaults/base" +import { ODPluginManager_Default } from "./defaults/plugin" import { ODEventManager_Default } from "./defaults/event" import { ODConfigManager_Default} from "./defaults/config" import { ODDatabaseManager_Default } from "./defaults/database" @@ -57,7 +57,7 @@ export class ODMain { events: ODEventManager_Default /**The manager that handles & executes all plugins in the bot. */ - plugins: ODPluginManager + plugins: ODPluginManager_Default /**The manager that manages & checks all the console flags of the bot. (like `--debug`) */ flags: ODFlagManager_Default /**The manager that manages & contains all the config files of the bot. (like `config/general.json`) */ @@ -132,7 +132,7 @@ export class ODMain { this.debug = new ODDebugger(this.console) this.events = new ODEventManager_Default(this.debug) - this.plugins = new ODPluginManager(this.debug) + this.plugins = new ODPluginManager_Default(this.debug) this.flags = new ODFlagManager_Default(this.debug) this.configs = new ODConfigManager_Default(this.debug) this.databases = new ODDatabaseManager_Default(this.debug) diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 90d0249..956867d 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -367,7 +367,7 @@ export class ODChecker extends ODManagerData { type,message, path:this.locationTraceToString(locationTrace), - filepath:this.config.file, + filepath:this.config.path, translationParams, messageDocs:docs, diff --git a/src/core/api/modules/config.ts b/src/core/api/modules/config.ts index a875946..a53ad50 100644 --- a/src/core/api/modules/config.ts +++ b/src/core/api/modules/config.ts @@ -67,8 +67,10 @@ export class ODConfigManager extends ODManager { * You will only use this class if you want to create your own config implementation (e.g. `yml`, `xml`,...)! */ export class ODConfig extends ODManagerData { - /**The full path to this config with extension */ + /**The name of the file with extension. */ file: string = "" + /**The path to the file relative to the main directory. */ + path: string = "" /**An object/array of the entire config file! Variables inside it can be edited while the bot is running! */ data: any = undefined } @@ -87,9 +89,9 @@ export class ODJsonConfig extends ODConfig { constructor(id:ODValidId, file:string, customPath?:string){ super(id) try { - const filename = (file.endsWith(".json")) ? file : file+".json" - this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./config/",filename) - this.data = JSON.parse(fs.readFileSync(this.file).toString()) + this.file = (file.endsWith(".json")) ? file : file+".json" + this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./config/",this.file) + this.data = JSON.parse(fs.readFileSync(this.path).toString()) }catch(err){ process.emit("uncaughtException",err) throw new ODSystemError("Config \""+nodepath.join("./",customPath ?? "./config/",file)+"\" doesn't exist!") diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index b4b2030..352c4ac 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -20,8 +20,6 @@ export interface ODDefaults { /**Load the default open ticket plugin classes. */ pluginClassLoading:boolean, - /**Load the default open ticket plugin events. */ - pluginEventLoading:boolean, /**Load the default open ticket flags. */ flagLoading:boolean, @@ -225,7 +223,6 @@ export class ODDefaultsManager { softPluginLoading:false, pluginClassLoading:true, - pluginEventLoading:true, flagLoading:true, flagInitiating:true, diff --git a/src/core/api/modules/language.ts b/src/core/api/modules/language.ts index 0a4c8c5..253342b 100644 --- a/src/core/api/modules/language.ts +++ b/src/core/api/modules/language.ts @@ -7,7 +7,10 @@ import { ODDebugger } from "./console" import fs from "fs" export class ODLanguage extends ODManagerData { + /**The name of the file with `.json` extension. */ file: string + /**The path to the file relative to the main directory. */ + path: string data: any metadata: { otversion:string, @@ -19,9 +22,9 @@ export class ODLanguage extends ODManagerData { constructor(id:ODValidId, file:string, customPath?:string){ super(id) try{ - const filename = (file.endsWith(".json")) ? file : file+".json" - this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./languages/",filename) - this.data = JSON.parse(fs.readFileSync(this.file).toString()) + this.file = (file.endsWith(".json")) ? file : file+".json" + this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./languages/",this.file) + this.data = JSON.parse(fs.readFileSync(this.path).toString()) }catch(err){ process.emit("uncaughtException",err) throw new ODSystemError("Language \""+nodepath.join("./",customPath ?? "./languages/",file)+"\" doesn't exist!") diff --git a/src/core/api/modules/plugin.ts b/src/core/api/modules/plugin.ts index ac01ef4..99b568d 100644 --- a/src/core/api/modules/plugin.ts +++ b/src/core/api/modules/plugin.ts @@ -11,13 +11,11 @@ export interface ODUnknownCrashedPlugin { } export class ODPluginManager extends ODManager { - events: ODPluginEventManager classes: ODPluginClassManager unknownCrashedPlugins: ODUnknownCrashedPlugin[] = [] constructor(debug:ODDebugger){ super(debug,"plugin") - this.events = new ODPluginEventManager(debug) this.classes = new ODPluginClassManager(debug) } @@ -147,91 +145,6 @@ export class ODPlugin extends ODManagerData { } } -export class ODPluginEvent extends ODManagerData { - listeners: Function[] = [] - oncelisteners: Function[] = [] - - getCurrentListeners(){ - const final: Function[] = [] - this.oncelisteners.forEach((l) => final.push(l)) - this.listeners.forEach((l) => final.push(l)) - - this.oncelisteners = [] - return final - } -} - -export class ODPluginEventManager extends ODManager { - #debug: ODDebugger - listenerLimit: number = 25 - - constructor(debug:ODDebugger){ - super(debug,"plugin event") - this.#debug = debug - } - - setListenerLimit(limit:number){ - this.listenerLimit = limit - } - - on(event:string, callback:Function){ - const eventdata = this.get(event) - if (eventdata){ - eventdata.listeners.push(callback) - - if (eventdata.listeners.length > this.listenerLimit){ - this.#debug.console.log(new ODConsoleWarningMessage("Possible plugin event memory leak detected!",[ - {key:"event",value:event}, - {key:"listeners",value:eventdata.listeners.length.toString()} - ])) - } - }else{ - throw new ODSystemError("unknown plugin event \""+event+"\"") - } - } - - once(event:string, callback:Function){ - const eventdata = this.get(event) - if (eventdata){ - eventdata.oncelisteners.push(callback) - - }else{ - throw new ODSystemError("unknown plugin event \""+event+"\"") - } - } - - wait(event:string): Promise { - return new Promise((resolve,reject) => { - const eventdata = this.get(event) - if (eventdata){ - eventdata.oncelisteners.push((...args:any) => {resolve(args)}) - }else{ - reject("unknown plugin event \""+event+"\"") - } - }) - } - - emit(event:string, params:any[]): Promise { - return new Promise(async (resolve,reject) => { - const eventdata = this.get(event) - if (eventdata){ - const listeners = eventdata.getCurrentListeners() - - for (const listener of listeners){ - try { - await listener(...params) - }catch(err){ - process.emit("uncaughtException",err) - } - } - resolve() - }else{ - reject("unknown plugin event \""+event+"\"") - } - }) - } -} - export class ODPluginClassManager extends ODManager { constructor(debug:ODDebugger){ super(debug,"plugin class") diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts index 76d5963..88993f2 100644 --- a/src/data/framework/checkerLoader.ts +++ b/src/data/framework/checkerLoader.ts @@ -18,17 +18,14 @@ export const loadAllConfigCheckerFunctions = async () => { export const loadAllConfigCheckerTranslations = async () => { if ((generalConfig && generalConfig.data.system && generalConfig.data.system.useTranslatedConfigChecker) ? generalConfig.data.system.useTranslatedConfigChecker : false){ - registerDefaultCheckerSystemTranslations() //translate checker system text - registerDefaultCheckerMessageTranslations() //translate checker messages - registerDefaultCheckerCustomTranslations() //translate custom checker messages + registerDefaultCheckerSystemTranslations(openticket.checkers.translation,openticket.languages) //translate checker system text + registerDefaultCheckerMessageTranslations(openticket.checkers.translation,openticket.languages) //translate checker messages + registerDefaultCheckerCustomTranslations(openticket.checkers.translation,openticket.languages) //translate custom checker messages } } //GLOBAL FUNCTIONS -export const registerDefaultCheckerSystemTranslations = () => { - const tm = openticket.checkers.translation - const lm = openticket.languages - +export const registerDefaultCheckerSystemTranslations = (tm:api.ODCheckerTranslationRegister_Default,lm:api.ODLanguageManager_Default) => { //SYSTEM //tm.quickTranslate(lm,"checker.system.headerOpenTicket","other","openticket:header-openticket") //OPEN TICKET (ignore) tm.quickTranslate(lm,"checker.system.typeError","other","openticket:type-error") // [ERROR] (ignore) @@ -45,10 +42,7 @@ export const registerDefaultCheckerSystemTranslations = () => { tm.quickTranslate(lm,"checker.system.dataMessages","other","openticket:data-message") // message } -export const registerDefaultCheckerMessageTranslations = () => { - const tm = openticket.checkers.translation - const lm = openticket.languages - +export const registerDefaultCheckerMessageTranslations = (tm:api.ODCheckerTranslationRegister_Default,lm:api.ODLanguageManager_Default) => { //STRUCTURES tm.quickTranslate(lm,"checker.messages.invalidType","message","openticket:invalid-type") // This property needs to be the type: {0}! tm.quickTranslate(lm,"checker.messages.propertyMissing","message","openticket:property-missing") // The property {0} is missing from this object! @@ -113,10 +107,7 @@ export const registerDefaultCheckerMessageTranslations = () => { tm.quickTranslate(lm,"checker.messages.idNonExistent","message","openticket:id-non-existent") // The id {0} doesn't exist! } -export const registerDefaultCheckerCustomTranslations = () => { - const tm = openticket.checkers.translation - const lm = openticket.languages - +export const registerDefaultCheckerCustomTranslations = (tm:api.ODCheckerTranslationRegister_Default,lm:api.ODLanguageManager_Default) => { //CUSTOM tm.quickTranslate(lm,"checker.messages.invalidLanguage","message","openticket:invalid-language") // This is an invalid language! tm.quickTranslate(lm,"checker.messages.invalidButton","message","openticket:invalid-button") // This button needs to have at least an {0} or {1}! diff --git a/src/data/framework/eventLoader.ts b/src/data/framework/eventLoader.ts index 0aa865b..0371e4a 100644 --- a/src/data/framework/eventLoader.ts +++ b/src/data/framework/eventLoader.ts @@ -10,8 +10,6 @@ export const loadAllEvents = () => { "afterPluginsLoaded", "onPluginClassLoad", "afterPluginClassesLoaded", - "onPluginEventLoad", - "afterPluginEventsLoaded", //flags "onFlagLoad", @@ -230,7 +228,10 @@ export const loadAllEvents = () => { "onStartScreenLoad", "afterStartScreensLoaded", "onStartScreenRender", - "afterStartScreensRendered" + "afterStartScreensRendered", + + //ready + "onReadyForUsage" ] eventList.forEach((event) => openticket.events.add(new api.ODEvent(event))) } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 268447f..3226910 100644 --- a/src/index.ts +++ b/src/index.ts @@ -92,14 +92,6 @@ const main = async () => { await openticket.events.get("onPluginClassLoad").emit([openticket.plugins.classes,openticket.plugins]) await openticket.events.get("afterPluginClassesLoaded").emit([openticket.plugins.classes,openticket.plugins]) - //load plugin events - openticket.log("Loading plugin events...","system") - if (openticket.defaults.getDefault("pluginEventLoading")){ - - } - await openticket.events.get("onPluginEventLoad").emit([openticket.plugins.events,openticket.plugins]) - await openticket.events.get("afterPluginEventsLoaded").emit([openticket.plugins.events,openticket.plugins]) - //load flags openticket.log("Loading flags...","system") if (openticket.defaults.getDefault("flagLoading")){ @@ -743,5 +735,6 @@ const main = async () => { //YIPPPIE!! //The startup of Open Ticket is completed :) + await openticket.events.get("onReadyForUsage").emit([]) } main() \ No newline at end of file From 504889a83d1eb5724f5838aa8214bf20fb755ae3 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 1 Sep 2024 21:30:56 +0200 Subject: [PATCH 022/157] Fixed config checker emoji count --- src/core/api/modules/checker.ts | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 956867d..54df443 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -1194,18 +1194,16 @@ export class ODCheckerCustomStructure_EmojiString extends ODCheckerStringStructu const lt = checker.locationTraceDeref(locationTrace) if (typeof value != "string") return false - const emojis: string[] = [] - const emojiSplitRegex = /(?:(?:\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])|(?:))/g - let emoji = emojiSplitRegex.exec(value) - while (emoji != null){ - emojis.push(emoji[0]) - emoji = emojiSplitRegex.exec(value) - } - - if (emojis.length < minLength){ + const discordEmojiSplitter = /(?:)/g + const splitted = value.split(discordEmojiSplitter) + const discordEmojiAmount = splitted.length-1 + const unicodeEmojiAmount = [...new Intl.Segmenter().segment(splitted.join(""))].length + const emojiAmount = discordEmojiAmount+unicodeEmojiAmount + + if (emojiAmount < minLength){ checker.createMessage("openticket:emoji-too-short","error",`This string needs to have at least ${minLength} emoji's!`,lt,null,[maxLength.toString()],this.id,(this.options.docs ?? null)) return false - }else if (emojis.length > maxLength){ + }else if (emojiAmount > maxLength){ checker.createMessage("openticket:emoji-too-long","error",`This string needs to have at most ${maxLength} emoji's!`,lt,null,[maxLength.toString()],this.id,(this.options.docs ?? null)) return false }else if (!allowCustomDiscordEmoji && //.test(value)){ From 39099a0dfe361b5c1008fc01bf0e208e22248f2f Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 2 Sep 2024 16:10:02 +0200 Subject: [PATCH 023/157] Fixed small translation mistakes --- languages/hungarian.json | 2 +- languages/romanian.json | 2 +- languages/ukrainian.json | 8 ++++---- package.json | 3 ++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/languages/hungarian.json b/languages/hungarian.json index 7fc7ea8..cc5340d 100644 --- a/languages/hungarian.json +++ b/languages/hungarian.json @@ -14,7 +14,7 @@ "headerConfigChecker":"KONFIGURÁCIÓ ELLENŐRZÉS", "headerDescription":"hibaellenőrzés a konfigurációdban!", "footerError":"a bot nem indul el, amíg a következőket nem javítod ki: {0}!", - "footerWarning":"ajánlott javítani a következőket az indítás előtt: {0}", + "footerWarning":"ajánlott javítani a következőket az indítás előtt: {0}!", "footerSupport":"SUPPORT: {0} - DOKUMENTÁCIÓ: {1}", "compactInformation":"használd a következőt: {0} további információkért!", "dataPath":"útvonal", diff --git a/languages/romanian.json b/languages/romanian.json index 9f883ec..ab47696 100644 --- a/languages/romanian.json +++ b/languages/romanian.json @@ -12,7 +12,7 @@ "typeWarning":"[AVERTISMENT]", "typeInfo":"[INFO]", "headerConfigChecker":"VALIDATOR CONFIGURATIE", - "headerDescription":"verifica daca sunt erori in configuratia botului", + "headerDescription":"verifica daca sunt erori in configuratia botului!", "footerError":"botul nu va porni pana cand toate cele {0} erori sunt reparate!", "footerWarning":"este recomandat sa repari toate {0}'s inainte de pornire!", "footerSupport":"SUPORT: {0} - DOCS: {1}", diff --git a/languages/ukrainian.json b/languages/ukrainian.json index 8de83cd..ffe928c 100644 --- a/languages/ukrainian.json +++ b/languages/ukrainian.json @@ -23,7 +23,7 @@ }, "messages":{ "stringTooShort":"Цей рядок не може бути коротшим за {0} символів!", - "stringTooLong":"Цей рядок не може бути довшим за {0} символів!»", + "stringTooLong":"Цей рядок не може бути довшим за {0} символів!", "stringLengthInvalid":"Цей рядок повинен мати довжину {0} символів!", "stringStartsWith":"Цей рядок повинен починатися з {0}!", "stringEndsWith":"Цей рядок повинен закінчуватися на {0}!", @@ -46,7 +46,7 @@ "numberFloat":"Це число не може бути десятковим!", "numberNegative":"Це число не може бути від'ємним!", "numberPositive":"Це число не може бути додатнім!", - "numberZero":"Це число не може дорівнювати нулю", + "numberZero":"Це число не може дорівнювати нулю!", "booleanTrue": "Цей булевий вираз не може бути істинним!", "booleanFalse": "Цей булевий вираз не може бути хибним!", @@ -65,12 +65,12 @@ "colorInvalid":"Це недійсний hex кольор!", "emojiTooShort":"Цей рядок повинен містити щонайменше {0} емодзі!", "emojiTooLong":"Цей рядок повинен містити не більше {0} емодзі!", - "emojiCustom":"Цей емодзі не може бути користувацьким дискорд емодзі", + "emojiCustom":"Цей емодзі не може бути користувацьким дискорд емодзі!", "emojiInvalid":"Цей емодзі недійсний!", "urlInvalid":"Це посилання недійсне!", "urlInvalidHttp":"Це посилання може використовувати лише https:// протокол!", "urlInvalidProtocol":"Це посилання може використовувати лише http:// та https:// протоколи!", - "urlInvalidHostname":"Це посилання має заборонене ім'я хоста", + "urlInvalidHostname":"Це посилання має заборонене ім'я хоста!", "urlInvalidExtension":"Це посилання має невірне розширення! Виберіть один з варіантів: {0}!", "urlInvalidPath":"Це посилання має недійсний шлях!", "idNotUnique":"Цей ідентифікатор не є унікальним, використовуйте інший ідентифікатор!", diff --git a/package.json b/package.json index a497fb4..d2c9e4d 100644 --- a/package.json +++ b/package.json @@ -12,8 +12,9 @@ ], "main": "index.js", "scripts": { - "build": "node index.js -%-compile", + "build": "node index.js --compile-only", "start": "node index.js", + "startnc": "node index.js --no-compile", "test": "node index.js --dev-config --dev-database", "testnc": "node index.js --no-compile --dev-config --dev-database" }, From 55bcff80306bfd830472aef9c30ec2ee11b98736 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 4 Sep 2024 20:13:13 +0200 Subject: [PATCH 024/157] fix ticket cmd perms, updated djs & added dump cmd --- package.json | 2 +- src/commands/panel.ts | 2 +- src/core/api/defaults/client.ts | 4 +- src/core/api/modules/client.ts | 2 +- src/core/api/modules/defaults.ts | 3 + src/core/api/modules/permission.ts | 127 ++++++++++++++++------------- src/core/api/modules/responder.ts | 2 +- src/core/startup/dump.ts | 30 +++++++ src/data/framework/codeLoader.ts | 1 + src/index.ts | 3 + 10 files changed, 113 insertions(+), 63 deletions(-) create mode 100644 src/core/startup/dump.ts diff --git a/package.json b/package.json index d2c9e4d..8e2a1dd 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "dependencies": { "@types/node": "^22.5.0", "ansis": "^2.3.0", - "discord.js": "^14.15.3", + "discord.js": "^14.16.1", "formatted-json-stringify": "^1.1.0", "typescript": "^5.5.4" }, diff --git a/src/commands/panel.ts b/src/commands/panel.ts index 72cf050..0a7a184 100644 --- a/src/commands/panel.ts +++ b/src/commands/panel.ts @@ -46,7 +46,7 @@ export const registerCommandResponders = async () => { }), new api.ODWorker("openticket:panel",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance - if (!guild){ + if (!guild || instance.channel.type == discord.ChannelType.GroupDM){ //error instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() diff --git a/src/core/api/defaults/client.ts b/src/core/api/defaults/client.ts index d03d26f..95e2cfe 100644 --- a/src/core/api/defaults/client.ts +++ b/src/core/api/defaults/client.ts @@ -82,6 +82,7 @@ export class ODSlashCommandManager_Default extends ODSlashCommandManager { * It's used to generate typescript declarations for this class. */ export interface ODTextCommandManagerIds_Default { + "openticket:dump":ODTextCommand, "openticket:help":ODTextCommand, "openticket:panel":ODTextCommand, "openticket:close":ODTextCommand, @@ -138,9 +139,6 @@ export class ODTextCommandManager_Default extends ODTextCommandManager { return super.exists(id) } - onInteraction(prefix:string, id:keyof ODTextCommandManagerIds_Default, callback:ODTextCommandInteractionCallback): void - onInteraction(commandPrefix:string, commandName:string|RegExp, callback:ODTextCommandInteractionCallback): void - onInteraction(commandPrefix:string, commandName:string|RegExp, callback:ODTextCommandInteractionCallback): void { return super.onInteraction(commandPrefix,commandName,callback) } diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index c7ca8dc..ccd6804 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -996,7 +996,7 @@ export class ODTextCommandManager extends ODManager { //filter commands for correct name const validNameCommands: {cmd:ODTextCommand,newContent:string}[] = [] validPrefixCommands.forEach((cmd) => { - if (cmd.newContent.startsWith(cmd.cmd.builder.name)) validNameCommands.push({ + if (cmd.newContent.startsWith(cmd.cmd.builder.name+" ") || cmd.newContent == cmd.cmd.builder.name) validNameCommands.push({ cmd:cmd.cmd, newContent:cmd.newContent.substring(cmd.cmd.builder.name.length+1) //+1 because of space after command name }) diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index 352c4ac..d67625e 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -13,6 +13,8 @@ export interface ODDefaults { crashOnError:boolean, /**Enable the system responsible for the `--debug` flag. */ debugLoading:boolean, + /**When enabled, you're able to use the "!OPENTICKET:dump" command to send the OT debug file. This is only possible when you're the owner of the bot. */ + allowDumpCommand:boolean, /**Enable loading all Open Ticket plugins, sadly enough is only useful for the system :) */ pluginLoading:boolean, /**Don't crash the bot when a plugin crashes! */ @@ -219,6 +221,7 @@ export class ODDefaultsManager { errorHandling:true, crashOnError:false, debugLoading:true, + allowDumpCommand:true, pluginLoading:true, softPluginLoading:false, diff --git a/src/core/api/modules/permission.ts b/src/core/api/modules/permission.ts index d46921b..5602d29 100644 --- a/src/core/api/modules/permission.ts +++ b/src/core/api/modules/permission.ts @@ -91,66 +91,18 @@ export class ODPermissionManager extends ODManager { else throw new ODSystemError("Invalid minimum permission type at ODPermissionManager.hasPermissions()") } async #defaultCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise { + const globalCalc = await this.#defaultGlobalCalculation(user,channel,guild,settings) + const channelCalc = await this.#defaultChannelCalculation(user,channel,guild,settings) + + if (globalCalc.level > channelCalc.level) return globalCalc + else return channelCalc + } + /**Check for global permissions. Then this result can be compared with the channel one. */ + async #defaultGlobalCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise { const idRegex = (settings && typeof settings.idRegex != "undefined") ? settings.idRegex : null - const allowChannelUserScope = (settings && typeof settings.allowChannelUserScope != "undefined") ? settings.allowChannelUserScope : true - const allowChannelRoleScope = (settings && typeof settings.allowChannelRoleScope != "undefined") ? settings.allowChannelRoleScope : true const allowGlobalUserScope = (settings && typeof settings.allowGlobalUserScope != "undefined") ? settings.allowGlobalUserScope : true const allowGlobalRoleScope = (settings && typeof settings.allowGlobalRoleScope != "undefined") ? settings.allowGlobalRoleScope : true - if (guild && channel && !channel.isDMBased()){ - //check for channel user permissions - if (allowChannelUserScope){ - const users = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "channel-user" && permission.channel && (permission.channel.id == channel.id) && (permission.value instanceof discord.User) && permission.value.id == user.id) - - if (users.length > 0){ - //sort all permisions from highest to lowest - users.sort((a,b) => { - const levelA = ODPermissionLevel[a.permission] - const levelB = ODPermissionLevel[b.permission] - - if (levelB > levelA) return 1 - else if (levelA > levelB) return -1 - else return 0 - }) - - return { - type:users[0].permission, - scope:"channel-user", - level:ODPermissionLevel[users[0].permission], - source:users[0] ?? null - } - } - } - - //check for channel role permissions - if (allowChannelRoleScope){ - const member = await guild.members.fetch(user.id) - if (member){ - const memberRoles = member.roles.cache.map((role) => role.id) - const roles = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "channel-role" && permission.channel && (permission.channel.id == channel.id) && (permission.value instanceof discord.Role) && memberRoles.includes(permission.value.id) && permission.value.guild.id == guild.id) - - if (roles.length > 0){ - //sort all permisions from highest to lowest - roles.sort((a,b) => { - const levelA = ODPermissionLevel[a.permission] - const levelB = ODPermissionLevel[b.permission] - - if (levelB > levelA) return 1 - else if (levelA > levelB) return -1 - else return 0 - }) - - return { - type:roles[0].permission, - scope:"channel-role", - level:ODPermissionLevel[roles[0].permission], - source:roles[0] ?? null - } - } - } - } - } - //check for global user permissions if (allowGlobalUserScope){ const users = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "global-user" && (permission.value instanceof discord.User) && permission.value.id == user.id) @@ -205,6 +157,69 @@ export class ODPermissionManager extends ODManager { } } + //spread result to prevent accidental referencing + return {...this.defaultResult} + } + /**Check for channel permissions. Then this result can be compared with the global one. */ + async #defaultChannelCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise { + const idRegex = (settings && typeof settings.idRegex != "undefined") ? settings.idRegex : null + const allowChannelUserScope = (settings && typeof settings.allowChannelUserScope != "undefined") ? settings.allowChannelUserScope : true + const allowChannelRoleScope = (settings && typeof settings.allowChannelRoleScope != "undefined") ? settings.allowChannelRoleScope : true + + if (guild && channel && !channel.isDMBased()){ + //check for channel user permissions + if (allowChannelUserScope){ + const users = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "channel-user" && permission.channel && (permission.channel.id == channel.id) && (permission.value instanceof discord.User) && permission.value.id == user.id) + + if (users.length > 0){ + //sort all permisions from highest to lowest + users.sort((a,b) => { + const levelA = ODPermissionLevel[a.permission] + const levelB = ODPermissionLevel[b.permission] + + if (levelB > levelA) return 1 + else if (levelA > levelB) return -1 + else return 0 + }) + + return { + type:users[0].permission, + scope:"channel-user", + level:ODPermissionLevel[users[0].permission], + source:users[0] ?? null + } + } + } + + //check for channel role permissions + if (allowChannelRoleScope){ + const member = await guild.members.fetch(user.id) + if (member){ + const memberRoles = member.roles.cache.map((role) => role.id) + const roles = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "channel-role" && permission.channel && (permission.channel.id == channel.id) && (permission.value instanceof discord.Role) && memberRoles.includes(permission.value.id) && permission.value.guild.id == guild.id) + + if (roles.length > 0){ + //sort all permisions from highest to lowest + roles.sort((a,b) => { + const levelA = ODPermissionLevel[a.permission] + const levelB = ODPermissionLevel[b.permission] + + if (levelB > levelA) return 1 + else if (levelA > levelB) return -1 + else return 0 + }) + + return { + type:roles[0].permission, + scope:"channel-role", + level:ODPermissionLevel[roles[0].permission], + source:roles[0] ?? null + } + } + } + } + } + //spread result to prevent accidental referencing return {...this.defaultResult} } diff --git a/src/core/api/modules/responder.ts b/src/core/api/modules/responder.ts index 9749471..2b7338f 100644 --- a/src/core/api/modules/responder.ts +++ b/src/core/api/modules/responder.ts @@ -325,7 +325,7 @@ export class ODCommandResponderInstance { this.didReply = true return {success:true,message:await sent.fetch()} } - }else if (this.type == "message" && this.interaction instanceof discord.Message){ + }else if (this.type == "message" && this.interaction instanceof discord.Message && this.interaction.channel.type != discord.ChannelType.GroupDM){ const sent = await this.interaction.channel.send(msg.message) this.didReply = true return {success:true,message:sent} diff --git a/src/core/startup/dump.ts b/src/core/startup/dump.ts new file mode 100644 index 0000000..1929e9f --- /dev/null +++ b/src/core/startup/dump.ts @@ -0,0 +1,30 @@ +import {openticket, api, utilities} from "../../index" +import * as discord from "discord.js" +import * as fs from "fs" + +export const loadDumpCommand = () => { + openticket.client.textCommands.add(new api.ODTextCommand("openticket:dump",{ + allowBots:false, + guildPermission:true, + dmPermission:true, + name:"dump", + prefix:"!OPENTICKET:" + })) + + openticket.client.textCommands.onInteraction("!OPENTICKET:","dump",async (msg) => { + if (msg.author.id == "779742674932072469" || openticket.permissions.hasPermissions("developer",await openticket.permissions.getPermissions(msg.author,msg.channel,null))){ + //user is bot owner OR creator of Open Ticket :) + openticket.log("Dumped otdebug.txt!","system",[ + {key:"user",value:msg.author.username}, + {key:"id",value:msg.author.id} + ]) + const debug = fs.readFileSync("./otdebug.txt") + + if (msg.channel.type != discord.ChannelType.GroupDM) msg.channel.send({content:"## The `otdebug.txt` dump is available!",files:[ + new discord.AttachmentBuilder(debug) + .setName("otdebug.txt") + .setDescription("The Open Ticket debug dump!") + ]}) + } + }) +} \ No newline at end of file diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index dd65bb7..2a52973 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -25,6 +25,7 @@ export const loadCommandErrorHandlingCode = async () => { openticket.code.add(new api.ODCode("openticket:command-error-handling",14,() => { //invalid/missing options openticket.client.textCommands.onError(async (error) => { + if (error.msg.channel.type == discord.ChannelType.GroupDM) return if (error.type == "invalid_option"){ error.msg.channel.send((await openticket.builders.messages.getSafe("openticket:error-option-invalid").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) }else if (error.type == "missing_option"){ diff --git a/src/index.ts b/src/index.ts index 3226910..6d5281b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -373,6 +373,9 @@ const main = async () => { //load text commands openticket.log("Loading text commands...","system") + if (openticket.defaults.getDefault("allowDumpCommand")){ + (await import("./core/startup/dump.js")).loadDumpCommand() + } if (openticket.defaults.getDefault("textCommandLoading")){ await (await import("./data/framework/commandLoader.js")).loadAllTextCommands() } From 85026793a4a0b081aaa68b53a10d21299a0b9113 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 4 Sep 2024 20:39:20 +0200 Subject: [PATCH 025/157] Added Indonesian by erxg --- README.md | 2 +- languages/hungarian.json | 2 +- languages/indonesian.json | 477 +++++++++++++++++++++++++++ src/core/api/defaults/language.ts | 1 + src/data/framework/languageLoader.ts | 3 +- 5 files changed, 482 insertions(+), 3 deletions(-) create mode 100644 languages/indonesian.json diff --git a/README.md b/README.md index 67d34c6..f2fb3e8 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇭🇺 Hungarian |kornel0706 |🟢 Up To Date | |🇷🇴 Romanian |sankedev |🟢 Up To Date | |🇺🇦 Ukrainian |anderskiy |🟢 Up To Date | +|🇮🇩 Indonesian |erxg |🟢 Up To Date | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | |🇮🇹 Italian |maurizio26 |🟠 Temporary Outdated (beta) | |🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | @@ -121,7 +122,6 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇹🇭 Thai |modshd |🟠 Temporary Outdated (beta) | |🇳🇴 Norwegian |noonenook |🟠 Temporary Outdated (beta) | |🇬🇷 Greek |stefanos__. |🔴 Outdated | -|🇮🇩 Indonesian |erxg |🟠 Temporary Outdated (beta) | |❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | |❓ Persian |sasanwm |🟠 Temporary Outdated (beta) | |🇱🇻 Latvian |ronalds1398 |🟠 Temporary Outdated (beta) | diff --git a/languages/hungarian.json b/languages/hungarian.json index cc5340d..1651811 100644 --- a/languages/hungarian.json +++ b/languages/hungarian.json @@ -474,4 +474,4 @@ "transcriptsCreated":"Létrehozott Átiratok" } } -} +} \ No newline at end of file diff --git a/languages/indonesian.json b/languages/indonesian.json new file mode 100644 index 0000000..4bea43a --- /dev/null +++ b/languages/indonesian.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translator":"erxg", + "lastedited":"25/08/2024", + "language":"Indonesian" + }, + "checker":{ + "system":{ + "typeError":"[GALAT]", + "headerOpenTicket":"OPEN TICKET", + "typeWarning":"[PERINGATAN]", + "typeInfo":"[INFO]", + "headerConfigChecker":"PEMERIKSA KONFIGURASI", + "headerDescription":"Memeriksa kesalahan dalam file konfigurasi Anda!", + "footerError":"Bot tidak akan mulai sampai semua {0} diperbaiki!", + "footerWarning":"Disarankan untuk memperbaiki semua {0} sebelum memulai!", + "footerSupport":"BANTUAN: {0} - DOKUMENTASI: {1}", + "compactInformation":"Gunakan {0} untuk informasi lebih lanjut!", + "dataPath":"jalur", + "dataDocs":"dokumentasi", + "dataMessages":"pesan" + }, + "messages":{ + "stringTooShort":"String ini tidak boleh lebih pendek dari {0} karakter!", + "stringTooLong":"String ini tidak boleh lebih panjang dari {0} karakter!", + "stringLengthInvalid":"String ini harus {0} karakter!", + "stringStartsWith":"String ini harus dimulai dari {0}!", + "stringEndsWith":"String ini harus berakhir dengan {0}!", + "stringContains":"String ini harus mengandung {0}!", + "stringChoices":"String ini hanya dapat berupa salah satu dari nilai berikut ini: {0}!", + "stringRegex":"String ini tidak valid!", + + "numberTooShort":"Nomor ini tidak boleh lebih pendek dari {0} karakter!", + "numberTooLong":"Nomor ini tidak boleh lebih panjang dari {0} karakter!", + "numberLengthInvalid":"Nomor ini harus setidaknya {0} karakter!", + "numberTooSmall":"Nomor ini setidaknya harus {0}!", + "numberTooLarge":"Nilai Nomor ini nomor ini {0}!", + "numberNotEqual":"Nomor ini harus {0}!", + "numberStep":"Nomor ini harus merupakan kelipatan {0}!", + "numberStepOffset":"Nomor ini harus merupakan kelipatan {0} dimulai dengan {1}!", + "numberStartsWith":"Nomor ini harus dimulai dengan {0}!", + "numberEndsWith":"Nomor ini harus berakhir dengan {0}!", + "numberContains":"Nomor ini harus mengandung {0}!", + "numberChoices":"Nomor ini hanya dapat berupa salah satu dari nomor berikut: {0}!", + "numberFloat":"Nomor ini tidak boleh desimal!", + "numberNegative":"Nomor ini tidak boleh negatif!", + "numberPositive":"Nomor ini tidak boleh positif!", + "numberZero":"Nomor ini tidak boleh nol!", + + "booleanTrue":"Boolean ini tidak boleh benar!", + "booleanFalse":"Boolean ini tidak boleh salah!", + + "arrayEmptyDisabled":"Array ini tidak boleh kosong!", + "arrayEmptyRequired":"Array ini harus kosong!", + "arrayTooShort":"Array ini harus memiliki panjang setidaknya {0}!", + "arrayTooLong":"Array ini harus memiliki panjang paling banyak {0}!", + "arrayLengthInvalid":"Array ini hanya dapat berisi tipe berikut ini: {0}!", + "arrayInvalidTypes":"Array ini hanya dapat berisi tipe berikut: {0}!", + "arrayDouble":"Array ini tidak mengizinkan nilai yang sama dua kali!", + + "discordInvalidId":"Ini adalah id Discord {0} yang tidak valid!", + "discordInvalidIdOptions":"Ini adalah id Discord {0} yang tidak valid! Anda juga dapat menggunakan salah satu dari ini: {1}!", + "discordInvalidToken":"Ini adalah token Discord yang tidak valid (secara sintaksis)!", + "colorInvalid":"Ini adalah warna hex yang tidak valid!", + "emojiTooShort":"String ini harus memiliki setidaknya {0} emoji!", + "emojiTooLong":"String ini harus memiliki paling banyak {0} emoji!", + "emojiCustom":"Emoji tidak dapat berupa emoji Discord khusus!", + "emojiInvalid":"Emoji ini tidak valid!", + "urlInvalid":"URL ini tidak valid!", + "urlInvalidHttp":"Url ini hanya dapat menggunakan protokol https://!", + "urlInvalidProtocol":"Url ini hanya dapat menggunakan protokol http:// & https://!", + "urlInvalidHostname":"Url ini memiliki nama host yang dilarang!", + "urlInvalidExtension":"URL ini memiliki ekstensi yang tidak valid! Pilih salah satu: {0}!", + "urlInvalidPath":"URL ini memiliki jalur yang tidak valid!", + "idNotUnique":"Id ini tidak unik, gunakan id lain sebagai gantinya!", + "idNonExistent":"Id {0} tidak ada!", + + "invalidType":"Properti ini harus sesuai dengan jenisnya: {0}!", + "propertyMissing":"Properti {0} tidak ada pada objek ini!", + "propertyOptional":"Properti {0} bersifat opsional dalam objek ini!", + "objectDisabled":"Objek ini dinonaktifkan, aktifkan dengan menggunakan {0}!", + "nullInvalid":"Properti ini tidak boleh bernilai nol!", + "switchInvalidType":"Ini harus salah satu dari jenis berikut ini: {0}!", + "objectSwitchInvalid":"Objek ini harus merupakan salah satu dari jenis berikut: {0}!", + + "invalidLanguage":"Ini adalah bahasa yang tidak valid!", + "invalidButton":"Tombol ini harus memiliki setidaknya {0} atau {1}!", + "unusedOption":"Opsi {0} tidak digunakan di mana pun!", + "unusedQuestion":"Pertanyaan {0} tidak digunakan di mana pun!", + "dropdownOption":"Panel dengan menu tarik-ulur yang diaktifkan hanya dapat berisi opsi dengan tipe 'tiket'!" + } + }, + "actions":{ + "buttons":{ + "create":"Kunjugi Tiket", + "close":"Tutup Tiket", + "delete":"Hapus Tiket", + "reopen":"Buka Kembali Tiket", + "claim":"Klaim Tiket", + "unclaim":"Batalkan Klaim Tiket", + "pin":"Sematkan Tiket", + "unpin":"Batal Menyematkan Tiket", + "clear":"Hapus Tiket", + "helpSwitchSlash":"Melihat Perintah Garis miring", + "helpSwitchText":"Lihat Perintah Teks", + "helpPage":"Halaman {0}", + "withReason":"Dengan Alasan", + "withoutTranscript":"Tanpa Transkrip" + }, + "titles":{ + "created":"Tiket Dibuat", + "close":"Tiket Ditutup", + "delete":"Tiket Dihapus", + "reopen":"Tiket Dibuka Kembali", + "claim":"Tiket Diklaim", + "unclaim":"Tiket Tidak Diklaim", + "pin":"Tiket Disematkan", + "unpin":"Tiket Tidak Lagi Disematkan", + "rename":"Tiket Berganti Nama", + "move":"Tiket Dipindahkan", + "add":"Pengguna Tiket Ditambahkan", + "remove":"Pengguna Tiket Dikeluarkan", + + "help":"Perintah Yang Tersedia", + "statsReset":"Atur Ulang Statistik", + "blacklistAdd":"Pengguna Dimasukkan ke Daftar Hitam", + "blacklistRemove":"Pengguna Dibebaskan", + "blacklistGet":"Pengguna dalam Daftar Hitam", + "blacklistView":"Daftar Hitam saat ini", + "blacklistAddDm":"Ditambahkan ke Daftar Hitam", + "blacklistRemoveDm":"Dihapus dari Daftar Hitam", + "clear":"Tiket dibersihkan.", + "roles":"Peran Diperbarui", + + "autoclose":"Tiket Ditutup Otomatis", + "autocloseEnabled":"Tutup Otomatis Diaktifkan", + "autocloseDisabled":"Tutup Otomatis Dimatikan", + "autodelete":"Tiket Dihapus Otomatis", + "autodeleteEnabled":"Hapus Otomatis Diaktifkan", + "autodeleteDisabled":"Hapus Otomatis Dinonaktifkan" + }, + "descriptions":{ + "create":"Tiket kamu telah dibuat. Klik tombol di bawah ini untuk mengaksesnya!", + "close":"Tiket telah berhasil ditutup!", + "delete":"Tiket telah berhasil dihapus!", + "reopen":"Tiket telah berhasil dibuka kembali!", + "claim":"Tiket telah berhasil diklaim!", + "unclaim":"Tiket tidak berhasil diklaim!", + "pin":"Tiket telah berhasil disematkan!", + "unpin":"Penyematan tiket telah berhasil dicabut!", + "rename":"Nama tiket telah berhasil diganti menjadi {0}!", + "move":"Tiket telah berhasil dipindahkan ke {0}!", + "add":"{0} telah berhasil ditambahkan ke tiket!", + "remove":"{0} telah berhasil dihapus dari tiket!", + + "helpExplanation":"`` => parameter wajib\n`[name]` => parameter opsional", + "statsReset":"Statistik bot telah berhasil disetel ulang!", + "statsError":"Tidak dapat melihat statistik tiket!\n{0} bukan tiket!", + "blacklistAdd":"{0} telah berhasil dimasukkan ke dalam daftar hitam!", + "blacklistRemove":"{0} telah berhasil dilepaskan dari daftar hitam!", + "blacklistGetSuccess":"{0} saat ini masuk daftar hitam!", + "blacklistGetEmpty":"{0} saat ini tidak berada dalam daftar hitam!", + "blacklistViewEmpty":"Belum ada yang masuk daftar hitam!", + "blacklistViewTip":"Gunakan \"/blacklist add\" untuk memasukkan pengguna ke dalam daftar hitam!", + "clearVerify":"Apakah Anda yakin ingin menghapus beberapa tiket?\nTindakan ini tidak dapat dibatalkan!", + "clearReady":"Tiket {0} telah berhasil dihapus!", + "rolesEmpty":"Tidak ada peran yang telah diperbarui!", + + "autocloseLeave":"tiket ini telah ditutup secara otomatis karena pembuatnya meninggalkan server!", + "autocloseTimeout":"tiket ini telah ditutup otomatis karena tidak aktif selama lebih dari `{0} jam`!", + "autodeleteLeave":"tiket ini telah dihapus secara otomatis karena pembuatnya meninggalkan server!", + "autodeleteTimeout":"tiket ini telah dihapus secara otomatis karena tidak aktif selama lebih dari `{0} hari`!", + "autocloseEnabled":"Penutupan otomatis telah diaktifkan untuk tiket ini!\nTiket ini akan ditutup ketika tidak aktif selama lebih dari `{0} jam`!", + "autocloseDisabled":"Penutupan otomatis telah dinonaktifkan untuk tiket ini!\nIt won't be closed automatically anymore!", + "autodeleteEnabled":"Penghapsan otomatis telah diaktifkan untuk tiket ini!\nIni akan dihapus jika tidak aktif selama lebih dari `{0} hari`!", + "autodeleteDisabled":"Penghapusan otomatis telah dinonaktifkan untuk tiket ini!\nTiket ini tidak akan dihapus secara otomatis lagi!", + + "ticketMessageLimit":"Anda hanya dapat membuat {0} tiket pada saat yang bersamaan!", + "ticketMessageAutoclose":"Tiket ini akan ditutup secara otomatis ketika tidak aktif selama {0} jam!", + "ticketMessageAutodelete":"Tiket ini akan dihapus secara otomatis ketika tidak aktif selama {0} hari!", + "panelReady":"Anda dapat menemukan panel di bawah ini!\nPesan ini sekarang dapat dihapus!" + }, + "modal":{ + "closePlaceholder":"Mengapa kamu menutup tiket ini?", + "deletePlaceholder":"Mengapa kamu menghapus tiket ini?", + "reopenPlaceholder":"Mengapa kamu membuka kembali tiket ini?", + "claimPlaceholder":"Mengapa kamu mengklaim tiket ini?", + "unclaimPlaceholder":"Mengapa kamu membatalkan klaim tiket ini?", + "pinPlaceholder":"Mengapa kamu menyematkan tiket ini?", + "unpinPlaceholder":"Mengapa kamu membatalkan sematan tiket ini?" + }, + "logs":{ + "createLog":"Tiket baru dibuat oleh {0}!", + "closeLog":"Tiket ini ditutup oleh {0}!", + "closeDm":"Tiket kamu telah ditutup di server kami!", + "deleteLog":"Tiket ini dihapus oleh {0}!", + "deleteDm":"Tiket kamu telah dihapus di server kami!", + "reopenLog":"Tiket ini dibuka kembali oleh {0}!", + "reopenDm":"Tiket kamu telah dibuka kembali di server kami!", + "claimLog":"Tiket ini diklaim oleh {0}!", + "claimDm":"Tiket kamu telah diklaim di server kami!", + "unclaimLog":"Tiket ini tidak lagi diklaim oleh {0}!", + "unclaimDm":"Tiket kamu tidak diklaim di server kami!", + "pinLog":"Tiket ini disematkan oleh {0}!", + "pinDm":"Tiket kamu telah disematkan di server kami!", + "unpinLog":"Tiket ini tidak lagi disematkan oleh {0}!", + "unpinDm":"Tiket kamu tidak lagi disematkan di server kami!", + "renameLog":"Tiket ini telah diubah namanya menjadi {0} oleh {1}!", + "renameDm":"Tiket kamu telah diubah namanya menjadi {0} di server kami!", + "moveLog":"Tiket ini telah dipindahkan ke {0} oleh {1}!", + "moveDm":"Tiket kamu telah dipindahkan ke {0} di server kami!", + "addLog":"{0} telah ditambahkan ke tiket ini oleh {1}!", + "addDm":"{0} telah ditambahkan ke tiket kamu di server kami!", + "removeLog":"{0} telah dihapus dari tiket ini oleh {1}!", + "removeDm":"{0} telah dihapus dari tiket kamu di server kami!", + + "blacklistAddLog":"{0} dimasukkan ke dalam daftar hitam oleh {1}!", + "blacklistRemoveLog":"{0} dihapus dari daftar hitam oleh {1}!", + "blacklistAddDm":"Anda telah masuk ke dalam daftar hitam di server kami!\nMulai sekarang, Anda tidak dapat membuat tiket!", + "blacklistRemoveDm":"Kamu telah dihapus dari daftar hitam di server kami!\nSekarang Anda dapat membuat tiket lagi!", + "clearLog":"Tiket {0} telah dihapus oleh {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Kunjungi Transkrip", + "ready":"Transkrip Dibuat", + "textFileDescription":"Ini adalah transkrip teks dari tiket yang dihapus!", + "htmlProgress":"Mohon tunggu sementara transkrip html diproses...", + + "createdChannel":"Transkrip {0} baru telah dibuat di server!", + "createdCreator":"Transkrip {0} baru telah dibuat salah satu tiket kamu!", + "createdParticipant":"Transkrip {0} baru telah dibuat di salah satu tiket yang kamu ikuti!", + "createdActiveAdmin":"Transkrip {0} baru telah dibuat di salah satu tiket yang kamu ikuti sebagai admin!", + "createdEveryAdmin":"Transkrip {0} baru telah dibuat in salah satu tiket tempat kamu menjadi admin!", + "createdOther":"Transkrip {0} baru telah dibuat!" + }, + "errors":{ + "retry":"Coba Ulang", + "continue":"Hapus Tanpa Transkrip", + "backup":"Membuat Transkrip Cadangan", + "error":"Terjadi kesalahan saat mencoba membuat transkrip.\nApa yang ingin Anda lakukan?\n\nTiket ini tidak akan dihapus hingga Anda mengeklik salah satu tombol ini." + } + }, + "errors":{ + "titles":{ + "internalError":"Galat Internal", + "optionMissing":"Opsi Perintah Tidak Ada", + "optionInvalid":"Opsi Perintah Invalid", + "unknownCommand":"Perintah Tidak Diketahui", + "noPermissions":"Tidak Memiliki Izin", + "unknownTicket":"Tiket Tidak Diketahui", + "deprecatedTicket":"Tiket sudah tidak berlaku", + "unknownOption":"Opsi Tidak Diketahui", + "unknownPanel":"Panel Tidak Diketahui", + "notInGuild":"Tidak Berada Di Dalam Server", + "channelRename":"Tidak Dapat Mengganti Nama Saluran", + "busy":"Tidak Sedang Sibuk" + }, + "descriptions":{ + "askForInfo":"Hubungi pemilik bot ini untuk info lebih lanjut!", + "askForInfoResolve":"Hubungi pemilik bot dari bot ini jika masalah ini tidak teratasi setelah beberapa kali mencoba.", + "internalError":"Gagal merespons {0} karena kesalahan internal!", + "optionMissing":"Parameter yang diperlukan tidak ada dalam perintah ini!", + "optionInvalid":"Parameter dalam perintah ini tidak valid!", + "optionInvalidChoose":"Pilih antara", + "unknownCommand":"Coba kunjungi menu bantuan untuk info lebih lanjut!", + "noPermissions":"Anda tidak diperbolehkan menggunakan {0}.!", + "noPermissionsList":"Izin yang Diperlukan: (salah satunya)", + "noPermissionsCooldown":"Anda tidak diperbolehkan menggunakan {0} karena kamu sedang dalam cooldown!", + "noPermissionsBlacklist":"Anda tidak diperbolehkan menggunakan {0} karena Anda telah masuk dalam daftar hitam!", + "noPermissionsLimitGlobal":"Anda tidak diizinkan untuk membuat tiket karena server telah mencapai batas maksimal tiket!", + "noPermissionsLimitGlobalPengguna":"Anda tidak dapat membuat tiket karena Anda telah mencapai batas maksimal tiket!", + "noPermissionsLimitOption":"Anda tidak diizinkan untuk membuat tiket karena server telah mencapai batas maksimal tiket untuk opsi ini!", + "noPermissionsLimitOptionPengguna":"Anda tidak dapat membuat tiket karena Anda telah mencapai batas maksimal tiket untuk opsi ini!", + "unknownTicket":"Gunakan perintah ini lagi dalam tiket yang valid!", + "deprecatedTicket":"Saluran saat ini bukanlah tiket yang valid! Ini mungkin merupakan tiket dari versi Open Tiket yang lama!", + "notInGuild":"Ini {0} tidak berfungsi di DM! Silakan coba lagi di server!", + "channelRename":"Karena batasan rasio Discord, saat ini bot tidak mungkin mengganti nama saluran. Saluran akan secara otomatis diganti namanya dalam waktu 10 menit jika bot tidak di-boot ulang.", + "channelRenameSource":"Sumber dari masalah: {0}", + "busy":"Dapat dapat menggunakan {0}!\nTiket sedang diproses oleh bot.\n\nMohon coba beberapa saat lagi!" + }, + "optionInvalidReasons":{ + "stringRegex":"Nilai tidak sesuai pola!", + "stringMinLength":"Nilai minimal {0} karakter!", + "stringMaxLength":"Nilai maksimal {0} karakter!", + "numberInvalid":"Angka tidak valid!", + "numberMin":"Angka minimal {0}!", + "numberMax":"Angka maksimal {0}!", + "numberDecimal":"Nomor tidak diperbolehkan sebuah angka desimal!", + "numberNegative":"Nomor tidak diperbolehkan sebuah angka negatif!", + "numberPositive":"Nomor tidak diperbolehkan sebuah angka positif!", + "numberZero":"Nomor tidak diperbolehkan sebuah angka nol!", + "channelNotFound":"Tidak dapat menemukan saluran!", + "userNotFound":"Tidak dapat menemukan pengguna!", + "roleNotFound":"Tidak dapat menemukan peran!", + "memberNotFound":"Tidak dapat menemukan anggota!", + "mentionableNotFound":"Tidak dapat menemukan pengguna atau peran!", + "channelType":"Tipe saluran invalid!", + "notInGuild":"Opsi ini memerlukan kamu untuk berada di dalam server!" + }, + "permissions":{ + "developer":"Kamu harus menjadi bagian pengembang dari bot.", + "owner":"Kamu harus menjadi pemilik server.", + "admin":"Kamu harus menjadi admin server.", + "moderator":"Kamu harus menjadi moderator.", + "support":"Kamu harus menjadi bagian dari anggota pendukung.", + "member":"Kamu harus menjadi anggota.", + "discord-administrator":"Kamu harus memiliki akses `ADMINISTRATOR`." + }, + "actionInvalid":{ + "close":"Tiket ini sudah ditutup!", + "reopen":"Tiket ini belum ditutup!", + "claim":"Tiket ini sudah diklaim!", + "unclaim":"Tiket ini belum diklaim!", + "pin":"Tiket ini sudah disematkan!", + "unpin":"Tiket ini belum disematkan!", + "add":"Pengguna ini sudah dapat mengakses tiket!", + "remove":"Tiket bisa mengeluarkan pengguna dari tiket!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Tiket", + "tickets":"Tiket", + "reason":"Alasan", + "creator":"Pembuat", + "remaining":"Waktu Tersisa", + "added":"Ditambahkan", + "removed":"Dikeluarkan", + "filter":"Penyaring", + "claimedBy":"Diklaim oleh {0}", + "method":"Metode", + "type":"Tipe", + "blacklisted":"Daftar hitam", + "panel":"Panel", + "command":"Perintah", + "system":"Sistem", + "true":"Benar", + "false":"Salah", + "syntax":"Sintaks", + "originalName":"Nama asli", + "newName":"Nama Yang Baru", + "until":"Hingga", + "validOptions":"Opsi Yang Valid", + "validPanels":"Panel Yang Valid", + "autoclose":"Tutup otomatis", + "autodelete":"Hapus otomatis", + "startupDate":"Waktu Mulai", + "version":"Versi", + "name":"Nama", + "role":"Peran", + "status":"Status", + "claimed":"Diklaim", + "pinned":"Disematkan", + "creationDate":"Tanggal Pembuatan" + }, + "lowercase":{ + "text":"teks", + "html":"html", + "command":"perintah", + "modal":"modal", + "button":"tombol", + "dropdown":"daftar", + "method":"Metode" + } + }, + "commands":{ + "reason":"Tentukan alasan opsional yang akan ditampilkan dalam log.", + "help":"Dapatkan daftar perintah yang tersedia.", + "panel":"Munculkan pesan dengan menu atau tombol (Untuk pembuatan tiket).", + "panelId":"Tanda pengenal panel yang ingin Anda munculkan.", + "panelAutoUpdate":"Apa Anda ingin panel ini diperbarui secara otomatis ketika diubah?", + "ticket":"Buat tiket secara instan.", + "ticketId":"Penanda tiket yang ingin anda buat.", + "close":"Tutup tiket.", + "delete":"Hapus tiket.", + "deleteNoTranscript":"Hapus tiket tanpa membuat transkrip.", + "reopen":"Buka ulang tiket.", + "claim":"Klaim tiket.", + "claimUser":"Klaim tiket untuk orang lain.", + "unclaim":"Batalkan klaim tiket.", + "pin":"Sematkan sebuah tiket.", + "unpin":"Batalkan penyematan tiket.", + "move":"Pindahkan tiket.", + "moveId":"Penanda opsi yang ingin anda pindahkan.", + "rename":"Ganti nama tiket.", + "renameName":"Nama yang baru untuk tiket.", + "add":"Tambahkan pengguna ke tiket.", + "addUser":"Pengguna yang akan ditambahkan.", + "remove":"Keluarkan seseorang dari tiket.", + "removeUser":"Pengguna yang akan dikeluarkan.", + "blacklist":"Kelola the Tiket blacklist.", + "blacklistView":"Lihat daftar yang masuk ke dalam daftar hitam.", + "blacklistAdd":"Tambahkan seseorang ke dalam daftar hitam.", + "blacklistRemove":"Keluarkan seseorang dari daftar hitam.", + "blacklistGet":"Dapatkan detail dari seseorang yang masuk ke daftar hitam.", + "blacklistGetUser":"Pengguna yang yang ingin dicari tahu detailnya.", + "stats":"View statistics from the bot, a member or a Tiket.", + "statsReset":"Atur ulang semua statistik bot (dan mulai menghitung dari nol).", + "statsGlobal":"Lihat statistik global.", + "statsUser":"Lihat status seseorang di server.", + "statsUserUser":"Pengguna yang akan dilihat.", + "statsTicket":"Lihat status dari sebuah tiket di server.", + "statsTicketTicket":"Tiket yang akan dilihat.", + "clear":"Hapus banyak tiket sekaligus.", + "clearFilter":"Filter untuk menghapus tiket.", + "clearFilters":{ + "all":"Semua", + "open":"Buka", + "close":"Ditutup", + "claim":"Diklaim", + "unclaim":"Belum diklaim", + "pin":"Disematkan", + "unpin":"Pembatalan penyematan", + "autoclose":"Ditutup otomatis" + }, + "autoclose":"Kelola penutupan otomatis tiket.", + "autocloseDisable":"Non-aktifkan penutupan otomatis.", + "autocloseEnable":"Aktifkan penutupan otomatis.", + "autocloseEnableTime":"Lama waktu saluran tidak aktif sebelum dinon-aktifkan.", + "autodelete":"Kelola penghapusan otomatis tiket.", + "autodeleteDisable":"Non-aktifkan penghapusan otomatis.", + "autodeleteEnable":"Aktifkan penghapusan otomatis.", + "autodeleteEnableTime":"Lama waktu saluran tidak aktif sebelum dihapus." + }, + "helpMenu":{ + "help":"Dapatkan daftar perintah yang tersedia.", + "ticket":"Buat tiket secara instan.", + "close":"Tutup tiket, ini akan membuat saluran tiket tidak bisa tidak bisa digunakan.", + "delete":"Hapus tiket, ini akan membuat sebuah transkrip ketika diaktifkan.", + "reopen":"Buka ulang tiket, ini memungkinkan untuk menulis lagi di tiket ini.", + "pin":"Sematkan sebuah tiket. Ini akan memindahkan tiket ke bagian atas dan akan menambahkan emoji '📌' pada namanya.", + "unpin":"Batalkan penyematan tiket. Tiket akan tetap berada di posisinya namun akan kehilangan emoji '📌'.", + "move":"Pindahkan tiket. Ini akan mengubah tipe/jenis tiket", + "rename":"Ganti nama tiket. Ini akan mengubah nama saluran tiket", + "claim":"Klaim tiket. Dengan ini tim anda tahu bahwa anda menangani tiket ini.", + "unclaim":"Batalkan klaim tiket. Dengan ini tim anda tahu bahwa anda bahwa tiket ini tersedia.", + "add":"Tambahkan seseorang ke tiket. Ini akan memberikan akses untuk membaca dan menulis tiket.", + "remove":"Keluarkan seseorang dari tiket. Ini akan menghapus akses untuk membaca dan menulis di tiket.", + "panel":"Munculkan pesan dengan menu atau tombol (Untuk pembuatan tiket).", + "blacklistView":"Lihat daftar yang masuk ke dalam daftar hitam.", + "blacklistAdd":"Tambahkan seseorang ke dalam daftar hitam.", + "blacklistRemove":"Keluarkan seseorang dari daftar hitam.", + "blacklistGet":"Dapatkan detail dari seseorang yang masuk ke daftar hitam.", + "statsGlobal":"Lihat statistik global.", + "statsTicket":"Lihat status sebuah tiket di server.", + "statsUser":"Lihat status seseorang di server.", + "statsReset":"Atur ulang semua statistik bot (Dan mulai menghitung dari nol).", + "autocloseDisable":"Nonaktifkan penutupan otomatis.", + "autocloseEnable":"Aktifkan penutupan otomatis.", + "autodeleteDisable":"Non-aktifkan penghapusan otomatis.", + "autodeleteEnable":"Aktifkan penghapusan otomatis." + }, + "stats":{ + "scopes":{ + "global":"Statistik Global", + "system":"Status Sistem", + "user":"Status Pengguna", + "ticket":"Status Tiket", + "participants":"Partisipan" + }, + "properties":{ + "ticketsCreated":"Tiket Dibuat", + "ticketsClosed":"Tiket Ditutup", + "ticketsDeleted":"Tiket Dihapus", + "ticketsReopened":"Tiket Dibuka Kembali", + "ticketsAutoclosed":"Tiket Ditutup Otomatis", + "ticketsClaimed":"Tiket Diklaim", + "ticketsPinned":"Tiket Disematkan", + "ticketsMoved":"Tickets Dipindahkan", + "usersBlacklisted":"Pengguna Masuk Ke Dalam Daftar Hitam", + "transcriptsCreated":"Transkrip Dibuat" + } + } +} \ No newline at end of file diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index 87d4ff1..2c76914 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -455,6 +455,7 @@ export interface ODLanguageManagerIds_Default { "openticket:spanish":ODLanguage, "openticket:romanian":ODLanguage, "openticket:ukrainian":ODLanguage, + "openticket:indonesian":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 67f1b40..5ffae01 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -13,10 +13,11 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODLanguage("openticket:spanish","spanish.json")) openticket.languages.add(new api.ODLanguage("openticket:romanian","romanian.json")) openticket.languages.add(new api.ODLanguage("openticket:ukrainian","ukrainian.json")) + openticket.languages.add(new api.ODLanguage("openticket:indonesian","indonesian.json")) //list for config checker const languageList = openticket.defaults.getDefault("languageList") - languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian") + languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian","indonesian") openticket.defaults.setDefault("languageList",languageList) /** How to add more languages? From 2a8e41005f4f782dad86ca80adcc56c0d2676c55 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 5 Sep 2024 20:58:57 +0200 Subject: [PATCH 026/157] Update init.ts --- src/core/startup/init.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index a408ff4..2a7867d 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -47,7 +47,7 @@ try{ openticket.debug.debug("Using discord.js "+packageJson.dependencies["discord.js"]+"!") openticket.debug.debug("Using ansis "+packageJson.dependencies["ansis"]+"!") openticket.debug.debug("Using formatted-json-stringify "+packageJson.dependencies["formatted-json-stringify"]+"!") - openticket.debug.debug("Using tsx "+packageJson.dependencies["tsx"]+"!") + openticket.debug.debug("Using typescript "+packageJson.dependencies["typescript"]+"!") }catch{ openticket.debug.debug("Failed to fetch module versions!") } From 35b02e0a8ff61a7398b0b8b196914fa7ab680aba Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 5 Sep 2024 21:01:36 +0200 Subject: [PATCH 027/157] Added first plugins --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f2fb3e8..d16a253 100644 --- a/README.md +++ b/README.md @@ -54,9 +54,13 @@ You're also able to customise every little aspect of the bot! From embeds to tra View all available Open Ticket plugins in our [Official Plugin Repository](https://github.com/DJj123dj/open-discord-plugins)! ### 📦 Official *(made by us)* -|Name |Description | -|----------------------|-------------------------| -|`nothing yet :)` |Lorem Ipsum Beta 4.0 🙃 | +|Name |Category |Description | +|---------------------------------------------------------------------|-------------------------|-------------------------| +|[`example-plugin`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-plugin/) |Example |This is just an example plugin for people that want to create their own plugin. | +|[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |Channel Management |Simple plugin to keep the channel prefix when using the /rename command. | + + + ### ✅ Verified *(made by community)* |Name |Description | From 8eae88b1c6674adffc776785382534de1073bccd Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 5 Sep 2024 23:27:40 +0200 Subject: [PATCH 028/157] Added 2 new plugins to README.md --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d16a253..3a5f0e1 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,10 @@ View all available Open Ticket plugins in our [Official Plugin Repository](https ### 📦 Official *(made by us)* |Name |Category |Description | |---------------------------------------------------------------------|-------------------------|-------------------------| -|[`example-plugin`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-plugin/) |Example |This is just an example plugin for people that want to create their own plugin. | -|[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |Channel Management |Simple plugin to keep the channel prefix when using the /rename command. | - - - +|[`example-plugin`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-plugin/) |Example |This is just an example plugin for people that want to create their own plugin. | +|[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |Channel Management |Simple plugin to keep the channel prefix when using the /rename command. | +|[`ot-jump-to-top`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-jump-to-top/) |Command |Add a simple command to jump to the top of the ticket. | +|[`ot-no-slash-clear`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-no-slash-clear/) |Development & Compatibility |Disable the automatic removal of slash commands that aren't used by Open Ticket. | ### ✅ Verified *(made by community)* |Name |Description | From 70048fa39984d9dfb9804fe64031d567d2c80a0f Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 11 Sep 2024 21:08:05 +0200 Subject: [PATCH 029/157] Added in-code flags support for pterodactyl --- index.js | 7 +++++++ src/builders/messages.ts | 10 ++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index fd4d6a3..e1ccd1c 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,13 @@ const fs = require("fs") const ts = require("typescript") const nodepath = require('path') +/////////////// STARTUP FLAGS /////////////// +const flags = [ + //add startup flags here (e.g. "--no-compile") +] +process.argv.push(...flags) +/////////////// STARTUP FLAGS /////////////// + if (!process.argv.includes("--no-compile")){ //REMOVE EXISTING BUILDS console.log("OT: Removing Prebuilds...") diff --git a/src/builders/messages.ts b/src/builders/messages.ts index b416bd6..8f5507b 100644 --- a/src/builders/messages.ts +++ b/src/builders/messages.ts @@ -45,7 +45,9 @@ const verifyBarMessages = () => { //add pings const pingOptions = option.get("openticket:ticket-message-ping").value - const pings: string[] = [discord.userMention(user.id)] + const pings: string[] = [] + const creator = ticket.get("openticket:opened-by").value + if (creator) pings.push(discord.userMention(creator)) if (pingOptions["@everyone"]) pings.push("@everyone") if (pingOptions["@here"]) pings.push("@here") pingOptions.custom.forEach((ping) => pings.push(discord.roleMention(ping))) @@ -669,7 +671,9 @@ const ticketMessages = () => { //add pings const pingOptions = ticket.option.get("openticket:ticket-message-ping").value - const pings: string[] = [discord.userMention(user.id)] + const pings: string[] = [] + const creator = ticket.get("openticket:opened-by").value + if (creator) pings.push(discord.userMention(creator)) if (pingOptions["@everyone"]) pings.push("@everyone") if (pingOptions["@here"]) pings.push("@here") pingOptions.custom.forEach((ping) => pings.push(discord.roleMention(ping))) @@ -682,8 +686,6 @@ const ticketMessages = () => { //add embed if (ticket.option.get("openticket:ticket-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("openticket:ticket-message").build(source,{guild,channel,user,ticket})) - - }), new api.ODWorker("openticket:ticket-message-components",1,async (instance,params,source) => { const {guild,channel,user,ticket} = params From 20bf25aa98305b3f6ade67ed18e35d9e4ae2ecba Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 12 Sep 2024 21:14:26 +0200 Subject: [PATCH 030/157] Small bug fixes + auto cycles are now debug only! --- src/builders/dropdowns.ts | 6 ++++-- src/data/framework/checkerLoader.ts | 6 +++--- src/data/framework/codeLoader.ts | 8 ++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/builders/dropdowns.ts b/src/builders/dropdowns.ts index d2f9b60..5a35404 100644 --- a/src/builders/dropdowns.ts +++ b/src/builders/dropdowns.ts @@ -17,12 +17,14 @@ const panelDropdowns = () => { new api.ODWorker("openticket:panel-dropdown-tickets",0,async (instance,params) => { const {panel,options} = params - const parsedOptions = options.map((option) => { + + const parsedOptions: api.ODDropdownData["options"] = options.map((option) => { + const desc = option.get("openticket:description").value.substring(0,100) return { label:option.get("openticket:button-label").value.substring(0,100), value:"od:ticket-option_"+panel.id.value+"_"+option.id.value, emoji:option.get("openticket:button-emoji").value, - description:option.get("openticket:description").value.substring(0,100) + description:(desc.length > 0) ? desc : undefined } }) diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts index 88993f2..0e478ad 100644 --- a/src/data/framework/checkerLoader.ts +++ b/src/data/framework/checkerLoader.ts @@ -277,7 +277,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opentick //TICKET {name:"ticket",priority:0,properties:[{key:"type",value:"ticket"}],checker:new api.ODCheckerObjectStructure("openticket:ticket",{children:[ {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:ticket-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-name",{minLength:3,maxLength:50})}, + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-name",{minLength:2,maxLength:50})}, {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-description",{maxLength:256})}, //TICKET BUTTON @@ -361,7 +361,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opentick //WEBSITE {name:"website",priority:0,properties:[{key:"type",value:"website"}],checker:new api.ODCheckerObjectStructure("openticket:options-website",{children:[ {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:website-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:website-name",{minLength:3,maxLength:50})}, + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:website-name",{minLength:2,maxLength:50})}, {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:website-description",{maxLength:256})}, //WEBSITE BUTTON @@ -386,7 +386,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opentick //REACTION ROLES {name:"role",priority:0,properties:[{key:"type",value:"role"}],checker:new api.ODCheckerObjectStructure("openticket:options-role",{children:[ {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:role-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:role-name",{minLength:3,maxLength:50})}, + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:role-name",{minLength:2,maxLength:50})}, {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:role-description",{maxLength:256})}, //ROLE BUTTON diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index 2a52973..3b431f2 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -398,8 +398,8 @@ const loadAutoCode = () => { } } } - openticket.log("Finished autoclose timeout cycle!","system",[ - {key:"interval",value:openticket.defaults.getDefault("autocloseCheckInterval").toString(),hidden:true}, + openticket.debug.debug("Finished autoclose timeout cycle!",[ + {key:"interval",value:openticket.defaults.getDefault("autocloseCheckInterval").toString()}, {key:"closed",value:count.toString()} ]) },openticket.defaults.getDefault("autocloseCheckInterval")) @@ -451,8 +451,8 @@ const loadAutoCode = () => { } } } - openticket.log("Finished autodelete timeout cycle!","system",[ - {key:"interval",value:openticket.defaults.getDefault("autodeleteCheckInterval").toString(),hidden:true}, + openticket.debug.debug("Finished autodelete timeout cycle!",[ + {key:"interval",value:openticket.defaults.getDefault("autodeleteCheckInterval").toString()}, {key:"deleted",value:count.toString()} ]) },openticket.defaults.getDefault("autodeleteCheckInterval")) From 77c486e2b7dea5532827544a41b2af96ae46708c Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 15 Sep 2024 17:55:42 +0200 Subject: [PATCH 031/157] Update createTranscript.ts --- src/actions/createTranscript.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/actions/createTranscript.ts b/src/actions/createTranscript.ts index e95dc29..88d9b1c 100644 --- a/src/actions/createTranscript.ts +++ b/src/actions/createTranscript.ts @@ -146,6 +146,7 @@ export const registerActions = async () => { //update stats openticket.stats.get("openticket:global").setStat("openticket:transcripts-created",1,"increase") + openticket.stats.get("openticket:user").setStat("openticket:transcripts-created",params.user.id,1,"increase") await openticket.events.get("afterTranscriptCreated").emit([openticket.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { From 28f0d974e530a1fee4048b108e23350595d06568 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 24 Sep 2024 19:32:35 +0200 Subject: [PATCH 032/157] Fixes "successfully" typo. --- languages/custom.json | 24 ++++++++++++------------ languages/english.json | 24 ++++++++++++------------ plugins/example-plugin/index.ts | 2 +- src/core/api/modules/builder.ts | 2 +- src/core/api/modules/helpmenu.ts | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) diff --git a/languages/custom.json b/languages/custom.json index 8d36a30..670071b 100644 --- a/languages/custom.json +++ b/languages/custom.json @@ -142,17 +142,17 @@ }, "descriptions":{ "create":"Your ticket has been created. Click the button below to access it!", - "close":"The ticket has been closed succesfully!", - "delete":"The ticket has been deleted succesfully!", - "reopen":"The ticket has been reopened succesfully!", - "claim":"The ticket has been claimed succesfully!", - "unclaim":"The ticket has been unclaimed succesfully!", - "pin":"The ticket has been pinned succesfully!", - "unpin":"The ticket has been unpinned succesfully!", - "rename":"The ticket has been renamed to {0} succesfully!", - "move":"The ticket has been moved to {0} succesfully!", - "add":"{0} has been added to the ticket succesfully!", - "remove":"{0} has been removed from the ticket succesfully!", + "close":"The ticket has been closed successfully!", + "delete":"The ticket has been deleted successfully!", + "reopen":"The ticket has been reopened successfully!", + "claim":"The ticket has been claimed successfully!", + "unclaim":"The ticket has been unclaimed successfully!", + "pin":"The ticket has been pinned successfully!", + "unpin":"The ticket has been unpinned successfully!", + "rename":"The ticket has been renamed to {0} successfully!", + "move":"The ticket has been moved to {0} successfully!", + "add":"{0} has been added to the ticket successfully!", + "remove":"{0} has been removed from the ticket successfully!", "helpExplanation":"`` => required parameter\n`[name]` => optional parameter", "statsReset":"The bot stats have been reset successfully!", @@ -164,7 +164,7 @@ "blacklistViewEmpty":"No-one has been blacklisted yet!", "blacklistViewTip":"Use \"/blacklist add\" to blacklist a user!", "clearVerify":"Are you sure you want to delete multiple tickets?\nThis action can't be undone!", - "clearReady":"{0} tickets have been deleted succesfully!", + "clearReady":"{0} tickets have been deleted successfully!", "rolesEmpty":"No roles have been updated!", "autocloseLeave":"This ticket has been autoclosed because the creator left the server!", diff --git a/languages/english.json b/languages/english.json index d73991b..35794be 100644 --- a/languages/english.json +++ b/languages/english.json @@ -142,17 +142,17 @@ }, "descriptions":{ "create":"Your ticket has been created. Click the button below to access it!", - "close":"The ticket has been closed succesfully!", - "delete":"The ticket has been deleted succesfully!", - "reopen":"The ticket has been reopened succesfully!", - "claim":"The ticket has been claimed succesfully!", - "unclaim":"The ticket has been unclaimed succesfully!", - "pin":"The ticket has been pinned succesfully!", - "unpin":"The ticket has been unpinned succesfully!", - "rename":"The ticket has been renamed to {0} succesfully!", - "move":"The ticket has been moved to {0} succesfully!", - "add":"{0} has been added to the ticket succesfully!", - "remove":"{0} has been removed from the ticket succesfully!", + "close":"The ticket has been closed successfully!", + "delete":"The ticket has been deleted successfully!", + "reopen":"The ticket has been reopened successfully!", + "claim":"The ticket has been claimed successfully!", + "unclaim":"The ticket has been unclaimed successfully!", + "pin":"The ticket has been pinned successfully!", + "unpin":"The ticket has been unpinned successfully!", + "rename":"The ticket has been renamed to {0} successfully!", + "move":"The ticket has been moved to {0} successfully!", + "add":"{0} has been added to the ticket successfully!", + "remove":"{0} has been removed from the ticket successfully!", "helpExplanation":"`` => required parameter\n`[name]` => optional parameter", "statsReset":"The bot stats have been reset successfully!", @@ -164,7 +164,7 @@ "blacklistViewEmpty":"No-one has been blacklisted yet!", "blacklistViewTip":"Use \"/blacklist add\" to blacklist a user!", "clearVerify":"Are you sure you want to delete multiple tickets?\nThis action can't be undone!", - "clearReady":"{0} tickets have been deleted succesfully!", + "clearReady":"{0} tickets have been deleted successfully!", "rolesEmpty":"No roles have been updated!", "autocloseLeave":"This ticket has been autoclosed because the creator left the server!", diff --git a/plugins/example-plugin/index.ts b/plugins/example-plugin/index.ts index 89ffc28..1a9396a 100644 --- a/plugins/example-plugin/index.ts +++ b/plugins/example-plugin/index.ts @@ -27,7 +27,7 @@ openticket.events.get("onConfigLoad").listen((configManager) => { //Let's also log it to the console to let us know it worked! const ourConfig = configManager.get("example-plugin:config") - openticket.log("The example config loaded succesfully!","plugin",[ + openticket.log("The example config loaded successfully!","plugin",[ {key:"var-1",value:ourConfig.data.testVariable1}, {key:"var-2",value:ourConfig.data.testVariable2.toString()}, {key:"var-3",value:ourConfig.data.testVariable3.toString()} diff --git a/src/core/api/modules/builder.ts b/src/core/api/modules/builder.ts index 9fb9f4a..b4c0945 100644 --- a/src/core/api/modules/builder.ts +++ b/src/core/api/modules/builder.ts @@ -892,7 +892,7 @@ export interface ODMessageBuildResult { * This interface contains the result from a sent built message. This can be used to edit, view & save the message that got created. */ export interface ODMessageBuildSentResult { - /**Did the message get sent succesfully? */ + /**Did the message get sent successfully? */ success:boolean, /**The message that got sent. */ message:discord.Message|null diff --git a/src/core/api/modules/helpmenu.ts b/src/core/api/modules/helpmenu.ts index 8d2ad57..514e1f3 100644 --- a/src/core/api/modules/helpmenu.ts +++ b/src/core/api/modules/helpmenu.ts @@ -141,7 +141,7 @@ export class ODHelpMenuCategory extends ODManager { } /**## ODHelpMenuRenderResult `type` - * This is the array returned when the help menu has been rendered succesfully. + * This is the array returned when the help menu has been rendered successfully. * * It contains a list of pages, which contain categories by name & value (content). */ From 6a8a8dd34d1535128e4ff590b5e72953c33671dd Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 2 Oct 2024 17:36:08 +0200 Subject: [PATCH 033/157] languages/config improvements & bug fixes --- index.js | 1 - languages/catalan.json | 5 ++-- languages/custom.json | 5 ++-- languages/czech.json | 5 ++-- languages/dutch.json | 5 ++-- languages/english.json | 5 ++-- languages/german.json | 5 ++-- languages/hungarian.json | 5 ++-- languages/indonesian.json | 5 ++-- languages/portuguese.json | 5 ++-- languages/romanian.json | 5 ++-- languages/spanish.json | 5 ++-- languages/ukrainian.json | 5 ++-- src/builders/embeds.ts | 2 +- src/core/api/modules/base.ts | 6 ++++ src/core/api/modules/checker.ts | 4 +-- src/core/api/modules/client.ts | 6 ++-- src/core/api/modules/config.ts | 39 +++++++++++++++++++++++--- src/core/api/modules/cooldown.ts | 4 +-- src/core/api/modules/flag.ts | 2 +- src/core/api/modules/language.ts | 39 +++++++++++++++++++------- src/core/startup/manageMigration.ts | 10 +++---- src/data/framework/codeLoader.ts | 12 ++++---- src/data/framework/cooldownLoader.ts | 2 +- src/data/framework/flagLoader.ts | 4 +-- src/data/framework/permissionLoader.ts | 2 +- src/data/openticket/optionLoader.ts | 36 ++++++++++++++++++++++++ src/data/openticket/panelLoader.ts | 11 ++++++++ src/data/openticket/questionLoader.ts | 15 ++++++++++ src/data/openticket/roleLoader.ts | 2 +- src/index.ts | 4 +++ 31 files changed, 197 insertions(+), 64 deletions(-) diff --git a/index.js b/index.js index e1ccd1c..5c6053b 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,3 @@ -//@ts-check const fs = require("fs") const ts = require("typescript") const nodepath = require('path') diff --git a/languages/catalan.json b/languages/catalan.json index c24557a..d7f9229 100644 --- a/languages/catalan.json +++ b/languages/catalan.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"guillee3", + "translators":["guillee3"], "lastedited":"21/08/2024", - "language":"Catalan" + "language":"Catalan", + "automated":false }, "checker":{ "system":{ diff --git a/languages/custom.json b/languages/custom.json index 670071b..0069238 100644 --- a/languages/custom.json +++ b/languages/custom.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"DJj123dj", + "translators":["DJj123dj"], "lastedited":"21/08/2024", - "language":"Custom" + "language":"Custom", + "automated":false }, "checker":{ "system":{ diff --git a/languages/czech.json b/languages/czech.json index c19fca7..9a95798 100644 --- a/languages/czech.json +++ b/languages/czech.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"spyeye_", + "translators":["spyeye_"], "lastedited":"21/08/2024", - "language":"Czech" + "language":"Czech", + "automated":false }, "checker":{ "system":{ diff --git a/languages/dutch.json b/languages/dutch.json index fa3b14d..73e75d6 100644 --- a/languages/dutch.json +++ b/languages/dutch.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"DJj123dj", + "translators":["DJj123dj"], "lastedited":"21/08/2024", - "language":"Dutch" + "language":"Dutch", + "automated":false }, "checker":{ "system":{ diff --git a/languages/english.json b/languages/english.json index 35794be..ceb0f92 100644 --- a/languages/english.json +++ b/languages/english.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"DJj123dj", + "translators":["DJj123dj"], "lastedited":"21/08/2024", - "language":"English" + "language":"English", + "automated":false }, "checker":{ "system":{ diff --git a/languages/german.json b/languages/german.json index a765b35..77f4a59 100644 --- a/languages/german.json +++ b/languages/german.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"benzorich", + "translators":["benzorich"], "lastedited":"22/08/2024", - "language":"German" + "language":"German", + "automated":false }, "checker":{ "system":{ diff --git a/languages/hungarian.json b/languages/hungarian.json index 1651811..f11a077 100644 --- a/languages/hungarian.json +++ b/languages/hungarian.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"Kornel0706", + "translators":["Kornel0706"], "lastedited":"22/08/2024", - "language":"Hungarian" + "language":"Hungarian", + "automated":false }, "checker":{ "system":{ diff --git a/languages/indonesian.json b/languages/indonesian.json index 4bea43a..bd07891 100644 --- a/languages/indonesian.json +++ b/languages/indonesian.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"erxg", + "translators":["erxg"], "lastedited":"25/08/2024", - "language":"Indonesian" + "language":"Indonesian", + "automated":false }, "checker":{ "system":{ diff --git a/languages/portuguese.json b/languages/portuguese.json index 181ea58..f47e78a 100644 --- a/languages/portuguese.json +++ b/languages/portuguese.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"quiradon", + "translators":["quiradon"], "lastedited":"20/08/2024", - "language":"Portuguese" + "language":"Portuguese", + "automated":false }, "checker":{ "system":{ diff --git a/languages/romanian.json b/languages/romanian.json index ab47696..e94c398 100644 --- a/languages/romanian.json +++ b/languages/romanian.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"SankeDev", + "translators":["SankeDev"], "lastedited":"27/08/2024", - "language":"Romanian" + "language":"Romanian", + "automated":false }, "checker":{ "system":{ diff --git a/languages/spanish.json b/languages/spanish.json index da41fd5..086e476 100644 --- a/languages/spanish.json +++ b/languages/spanish.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"Redactado & Josuens", + "translators":["Redactado","Josuens"], "lastedited":"22/08/2024", - "language":"Spanish" + "language":"Spanish", + "automated":false }, "checker":{ "system":{ diff --git a/languages/ukrainian.json b/languages/ukrainian.json index ffe928c..8d1c6fd 100644 --- a/languages/ukrainian.json +++ b/languages/ukrainian.json @@ -1,9 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translator":"Anderskiy", + "translators":["Anderskiy"], "lastedited":"31/08/2024", - "language":"Ukrainian" + "language":"Ukrainian", + "automated":false }, "checker":{ "system":{ diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts index 532f335..5dc1fc8 100644 --- a/src/builders/embeds.ts +++ b/src/builders/embeds.ts @@ -882,7 +882,7 @@ const blacklistEmbeds = () => { const {user} = params const renderedUsers: string[] = [] - openticket.blacklist.getAll().forEach((blacklist) => renderedUsers.push(discord.userMention(blacklist.id.value)+" - "+(blacklist.reason ? blacklist.reason : "/"))) + openticket.blacklist.forEach((blacklist,id) => {renderedUsers.push(discord.userMention(id.value)+" - "+(blacklist.reason ? blacklist.reason : "/"))}) instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setColor(generalConfig.data.mainColor) diff --git a/src/core/api/modules/base.ts b/src/core/api/modules/base.ts index 20eda1f..1c0b372 100644 --- a/src/core/api/modules/base.ts +++ b/src/core/api/modules/base.ts @@ -370,6 +370,12 @@ export class ODManager extends ODManagerChangeHe getIds(): ODId[] { return this.#data.map((d) => d.id) } + /**Run an iterator over all data in this manager. This method also supports async-await behaviour!*/ + async forEach(cb:(data:DataType,id:ODId) => ODPromiseVoid): Promise { + for (const data of this.getAll()){ + await cb(data,data.id) + } + } /**Use the open ticket debugger in this manager for logs*/ useDebug(debug?:ODDebugger, debugname?:string){ this.#debug = debug diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 54df443..4d7f152 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -65,7 +65,7 @@ export class ODCheckerManager extends ODManager { if (!res.valid) isValid = false }) - this.functions.getAll().forEach((func) => { + this.functions.forEach((func) => { const res = func.func(this,this.functions) final.push(...res.messages) @@ -1209,7 +1209,7 @@ export class ODCheckerCustomStructure_EmojiString extends ODCheckerStringStructu }else if (!allowCustomDiscordEmoji && //.test(value)){ checker.createMessage("openticket:emoji-custom","error",`This emoji can't be a custom discord emoji!`,lt,null,[],this.id,(this.options.docs ?? null)) return false - }else if (!/^(?:(?:\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])|(?:))*$/.test(value)){ + }else if (!/^(?:\p{Emoji}|\p{Emoji_Component}|(?:))*$/u.test(value)){ checker.createMessage("openticket:emoji-invalid","error","This is an invalid emoji!",lt,null,[],this.id,(this.options.docs ?? null)) return false } diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index ccd6804..6c6eef0 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -357,7 +357,7 @@ export class ODClientActivityManager { this.status = status } - /**When initiating the status, the bot starts updating the status using `discord.js`. Returns if succesfull or not. */ + /**When initiating the status, the bot starts updating the status using `discord.js`. Returns `true` when successfull. */ initStatus(): boolean { if (this.initiated || !this.manager.ready) return false this.#updateClientActivity(this.type,this.text) @@ -496,7 +496,7 @@ export class ODSlashCommandManager extends ODManager { const existing: {cmd:ODSlashCommand, requiresUpdate:boolean}[] = [] const nonExisting: ODSlashCommand[] = [] - this.getAll().forEach((cmd) => { + this.forEach((cmd) => { if (guildId && cmd.guildId != guildId) return const result = cmds.find((cmddata) => cmddata.name == cmd.name) if (result){ @@ -977,7 +977,7 @@ export class ODTextCommandManager extends ODManager { //filter commands for correct prefix const validPrefixCommands: {cmd:ODTextCommand,newContent:string}[] = [] - this.getAll().forEach((cmd) => { + this.forEach((cmd) => { if (msg.content.startsWith(cmd.builder.prefix)) validPrefixCommands.push({ cmd:cmd, newContent:msg.content.substring(cmd.builder.prefix.length) diff --git a/src/core/api/modules/config.ts b/src/core/api/modules/config.ts index a53ad50..acc2f2a 100644 --- a/src/core/api/modules/config.ts +++ b/src/core/api/modules/config.ts @@ -86,15 +86,46 @@ export class ODConfig extends ODManagerData { * const config = new api.ODJsonConfig("plugin-config","test.json","./plugins/testplugin/") */ export class ODJsonConfig extends ODConfig { + /**An array of listeners to run when the config gets reloaded. These are not executed on the initial loading. */ + #reloadListeners: Function[] = [] + constructor(id:ODValidId, file:string, customPath?:string){ super(id) - try { - this.file = (file.endsWith(".json")) ? file : file+".json" - this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./config/",this.file) + this.file = (file.endsWith(".json")) ? file : file+".json" + this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./config/",this.file) + + if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!") + try{ this.data = JSON.parse(fs.readFileSync(this.path).toString()) }catch(err){ process.emit("uncaughtException",err) - throw new ODSystemError("Config \""+nodepath.join("./",customPath ?? "./config/",file)+"\" doesn't exist!") + throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\"!") } } + + /**Reload the JSON file. Be aware that this doesn't update classes that used individual parts of the config data! */ + reload(){ + if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!") + try{ + this.data = JSON.parse(fs.readFileSync(this.path).toString()) + this.#reloadListeners.forEach((cb) => { + try{ + cb() + }catch(err){ + process.emit("uncaughtException",err) + } + }) + }catch(err){ + process.emit("uncaughtException",err) + throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\"!") + } + } + /**Listen for a reload of this JSON file! */ + onReload(cb:Function){ + this.#reloadListeners.push(cb) + } + /**Remove all reload listeners. Not recommended! */ + removeAllReloadListeners(){ + this.#reloadListeners = [] + } } \ No newline at end of file diff --git a/src/core/api/modules/cooldown.ts b/src/core/api/modules/cooldown.ts index 254a45a..ab3db43 100644 --- a/src/core/api/modules/cooldown.ts +++ b/src/core/api/modules/cooldown.ts @@ -139,7 +139,7 @@ export class ODCounterCooldown extends ODCooldown<{value:number}> { async init(){ if (this.ready) return setInterval(() => { - this.data.getAll().forEach((cooldown) => { + this.data.forEach((cooldown) => { cooldown.data.value = cooldown.data.value - this.decrement if (cooldown.data.value <= this.cancelLimit){ cooldown.active = false @@ -217,7 +217,7 @@ export class ODIncrementalCounterCooldown extends ODCooldown<{value:number}> { async init(){ if (this.ready) return setInterval(() => { - this.data.getAll().forEach((cooldown) => { + this.data.forEach((cooldown) => { cooldown.data.value = cooldown.data.value - this.decrement if (cooldown.data.value <= this.cancelLimit){ cooldown.active = false diff --git a/src/core/api/modules/flag.ts b/src/core/api/modules/flag.ts index 1b8a9cd..d63c471 100644 --- a/src/core/api/modules/flag.ts +++ b/src/core/api/modules/flag.ts @@ -66,7 +66,7 @@ export class ODFlagManager extends ODManager { /**Set all flags to their `process.argv` value. */ init(){ - this.getAll().forEach((flag) => { + this.forEach((flag) => { flag.detectProcessParams(false) }) } diff --git a/src/core/api/modules/language.ts b/src/core/api/modules/language.ts index 253342b..2e329f9 100644 --- a/src/core/api/modules/language.ts +++ b/src/core/api/modules/language.ts @@ -6,28 +6,33 @@ import nodepath from "path" import { ODDebugger } from "./console" import fs from "fs" +export interface ODLanguageMetadata { + otversion:string, + language:string, + translators:string[], + lastedited:string, + automated:boolean +} + export class ODLanguage extends ODManagerData { /**The name of the file with `.json` extension. */ file: string /**The path to the file relative to the main directory. */ path: string data: any - metadata: { - otversion:string, - language:string, - translator:string, - lastedited:string - }|null = null + metadata: ODLanguageMetadata|null = null constructor(id:ODValidId, file:string, customPath?:string){ super(id) + this.file = (file.endsWith(".json")) ? file : file+".json" + this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./languages/",this.file) + + if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to parse language \""+nodepath.join("./",this.path)+"\", the file doesn't exist!") try{ - this.file = (file.endsWith(".json")) ? file : file+".json" - this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./languages/",this.file) this.data = JSON.parse(fs.readFileSync(this.path).toString()) }catch(err){ process.emit("uncaughtException",err) - throw new ODSystemError("Language \""+nodepath.join("./",customPath ?? "./languages/",file)+"\" doesn't exist!") + throw new ODSystemError("Unable to parse language \""+nodepath.join("./",this.path)+"\"!") } if (this.data["_TRANSLATION"]) this.metadata = this.data["_TRANSLATION"] } @@ -36,27 +41,41 @@ export class ODLanguage extends ODManagerData { export class ODLanguageManager extends ODManager { current: ODLanguage|null = null backup: ODLanguage|null = null + #debug: ODDebugger constructor(debug:ODDebugger, presets:boolean){ super(debug,"language") if (presets) this.add(new ODLanguage("english","english.json")) this.current = presets ? new ODLanguage("english","english.json") : null this.backup = presets ? new ODLanguage("english","english.json") : null + this.#debug = debug } setCurrentLanguage(id:ODValidId){ this.current = this.get(id) + const languageId = this.current?.id.value ?? "" + const languageAutomated = this.current?.metadata?.automated.toString() ?? "" + this.#debug.debug("Selected current language",[ + {key:"id",value:languageId}, + {key:"automated",value:languageAutomated}, + ]) } getCurrentLanguage(){ return (this.current) ? this.current : null } setBackupLanguage(id:ODValidId){ this.backup = this.get(id) + const languageId = this.backup?.id.value ?? "" + const languageAutomated = this.backup?.metadata?.automated.toString() ?? "" + this.#debug.debug("Selected backup language",[ + {key:"id",value:languageId}, + {key:"automated",value:languageAutomated}, + ]) } getBackupLanguage(){ return (this.backup) ? this.backup : null } - getLanguageMetadata(frombackup?:boolean){ + getLanguageMetadata(frombackup?:boolean): ODLanguageMetadata|null { if (frombackup) return (this.backup) ? this.backup.metadata : null return (this.current) ? this.current.metadata : null } diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index 8bc68de..6373460 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -42,9 +42,9 @@ const preloadMigrationContext = async () => { const unloadMigrationContext = async () => { openticket.debug.visible = false - openticket.databases.getAll().forEach((database) => openticket.databases.remove(database.id)) - openticket.configs.getAll().forEach((config) => openticket.configs.remove(config.id)) - openticket.flags.getAll().forEach((flag) => openticket.flags.remove(flag.id)) + openticket.databases.forEach((database,id) => {openticket.databases.remove(id)}) + openticket.configs.forEach((config,id) => {openticket.configs.remove(id)}) + openticket.flags.forEach((flag,id) => {openticket.flags.remove(id)}) openticket.debug.debug("-- MIGRATION CONTEXT END --") } @@ -78,7 +78,7 @@ const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { const saveAllVersionsToDatabase = async () => { const globalDatabase = openticket.databases.get("openticket:global") - openticket.versions.getAll().forEach((version) => { - globalDatabase.set("openticket:last-version",version.id.value,version.toString()) + openticket.versions.forEach((version,id) => { + globalDatabase.set("openticket:last-version",id.value,version.toString()) }) } \ No newline at end of file diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index 3b431f2..c711d45 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -135,9 +135,9 @@ export const loadDatabaseCleanersCode = async () => { //OPTION DATABASE CLEANER openticket.code.add(new api.ODCode("openticket:option-database-cleaner",10,() => { //delete all unused options - openticket.options.getAll().forEach((option) => { - if (optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ - optionDatabase.delete("openticket:used-option",option.id.value) + openticket.options.forEach((option,id) => { + if (optionDatabase.exists("openticket:used-option",id.value) && !openticket.tickets.getAll().some((ticket) => ticket.id.value == id.value)){ + optionDatabase.delete("openticket:used-option",id.value) } }) })) @@ -331,9 +331,9 @@ export const loadDatabaseSaversCode = async () => { } //delete all unused options on ticket move - openticket.options.getAll().forEach((option) => { - if (optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ - optionDatabase.delete("openticket:used-option",option.id.value) + openticket.options.forEach((option,id) => { + if (optionDatabase.exists("openticket:used-option",id.value) && !openticket.tickets.getAll().some((ticket) => ticket.id.value == id.value)){ + optionDatabase.delete("openticket:used-option",id.value) } }) }) diff --git a/src/data/framework/cooldownLoader.ts b/src/data/framework/cooldownLoader.ts index 8461ba3..bc9fde7 100644 --- a/src/data/framework/cooldownLoader.ts +++ b/src/data/framework/cooldownLoader.ts @@ -1,7 +1,7 @@ import {openticket, api, utilities} from "../../index" export const loadAllCooldowns = async () => { - openticket.options.getAll().forEach((option) => { + openticket.options.forEach((option) => { if (!(option instanceof api.ODTicketOption)) return loadTicketOptionCooldown(option) }) diff --git a/src/data/framework/flagLoader.ts b/src/data/framework/flagLoader.ts index 5964046..64f632f 100644 --- a/src/data/framework/flagLoader.ts +++ b/src/data/framework/flagLoader.ts @@ -2,8 +2,8 @@ import {openticket, api, utilities} from "../../index" export const loadAllFlags = async () => { openticket.flags.add(new api.ODFlag("openticket:no-migration","No Migration","Disable Open Ticket data migration on update!","--no-migration",["-nm"])) - openticket.flags.add(new api.ODFlag("openticket:dev-config","Developer Config","Use the configs in /devconfig instead of /config!","--dev-config",["-dc"])) - openticket.flags.add(new api.ODFlag("openticket:dev-database","Developer Database","Use the databases in /devdatabase instead of /database!","--dev-database",["-nd"])) + openticket.flags.add(new api.ODFlag("openticket:dev-config","Developer Config","Use the configs in /devconfig/ instead of /config/!","--dev-config",["-dc"])) + openticket.flags.add(new api.ODFlag("openticket:dev-database","Developer Database","Use the databases in /devdatabase/ instead of /database/!","--dev-database",["-nd"])) openticket.flags.add(new api.ODFlag("openticket:debug","Debug Mode","Couldn't you find the error? Try to check this out!","--debug",["-d"])) openticket.flags.add(new api.ODFlag("openticket:crash","Crash On Error","Crash the bot on an unknown error!","--crash",["-cr"])) openticket.flags.add(new api.ODFlag("openticket:no-transcripts","No HTML Transcripts","Disable uploading HTML transcripts (for debugging)","--no-transcripts",["-nt"])) diff --git a/src/data/framework/permissionLoader.ts b/src/data/framework/permissionLoader.ts index 5e6c4b2..4d2eb41 100644 --- a/src/data/framework/permissionLoader.ts +++ b/src/data/framework/permissionLoader.ts @@ -30,7 +30,7 @@ export const loadAllPermissions = async () => { }) //TICKET ADMINS - openticket.tickets.getAll().forEach(async (ticket) => { + openticket.tickets.forEach(async (ticket) => { try { const channel = await openticket.client.fetchGuildTextChannel(mainServer,ticket.id.value) if (!channel) return diff --git a/src/data/openticket/optionLoader.ts b/src/data/openticket/optionLoader.ts index 9e54417..51ee538 100644 --- a/src/data/openticket/optionLoader.ts +++ b/src/data/openticket/optionLoader.ts @@ -15,6 +15,42 @@ export const loadAllOptions = async () => { openticket.options.add(loadRoleOption(option)) } }) + + //update options on config reload + optionConfig.onReload(async () => { + //clear previous options + openticket.options.forEach((data,id) => {openticket.options.remove(id)}) + + //add new options + optionConfig.data.forEach((option) => { + if (option.type == "ticket"){ + const loadedOption = loadTicketOption(option) + openticket.options.add(loadedOption) + openticket.options.suffix.add(loadTicketOptionSuffix(loadedOption)) + }else if (option.type == "website"){ + openticket.options.add(loadWebsiteOption(option)) + }else if (option.type == "role"){ + openticket.options.add(loadRoleOption(option)) + } + }) + + //update options in tickets + openticket.tickets.forEach((ticket) => { + const optionId = ticket.option.id + const option = openticket.options.get(optionId) + if (option && option instanceof api.ODTicketOption) ticket.option = option + else{ + openticket.log("Unable to move ticket to unexisting option due to config reload!","warning",[ + {key:"channelid",value:ticket.id.value}, + {key:"option",value:optionId.value} + ]) + } + }) + + //update roles on config reload + openticket.roles.forEach((data,id) => {openticket.roles.remove(id)}) + await (await import("./roleLoader.js")).loadAllRoles() + }) } export const loadTicketOption = (option:api.ODJsonConfig_DefaultOptionTicketType): api.ODTicketOption => { diff --git a/src/data/openticket/panelLoader.ts b/src/data/openticket/panelLoader.ts index 3d3682d..001d349 100644 --- a/src/data/openticket/panelLoader.ts +++ b/src/data/openticket/panelLoader.ts @@ -8,6 +8,17 @@ export const loadAllPanels = async () => { panelConfig.data.forEach((panel) => { openticket.panels.add(loadPanel(panel)) }) + + //update panels on config reload + panelConfig.onReload(async () => { + //clear previous panels + openticket.panels.forEach((data,id) => {openticket.panels.remove(id)}) + + //add new panels + panelConfig.data.forEach((panel) => { + openticket.panels.add(loadPanel(panel)) + }) + }) } export const loadPanel = (panel:api.ODJsonConfig_DefaultPanelType) => { diff --git a/src/data/openticket/questionLoader.ts b/src/data/openticket/questionLoader.ts index 2105d83..fdd69e6 100644 --- a/src/data/openticket/questionLoader.ts +++ b/src/data/openticket/questionLoader.ts @@ -11,6 +11,21 @@ export const loadAllQuestions = async () => { openticket.questions.add(loadParagraphQuestion(question)) } }) + + //update questions on config reload + questionConfig.onReload(() => { + //clear previous questions + openticket.questions.forEach((data,id) => {openticket.questions.remove(id)}) + + //add new questions + questionConfig.data.forEach((question) => { + if (question.type == "short"){ + openticket.questions.add(loadShortQuestion(question)) + }else if (question.type == "paragraph"){ + openticket.questions.add(loadParagraphQuestion(question)) + } + }) + }) } export const loadShortQuestion = (option:api.ODJsonConfig_DefaultShortQuestionType) => { diff --git a/src/data/openticket/roleLoader.ts b/src/data/openticket/roleLoader.ts index 2baa6d5..cd53f18 100644 --- a/src/data/openticket/roleLoader.ts +++ b/src/data/openticket/roleLoader.ts @@ -1,7 +1,7 @@ import {openticket, api, utilities} from "../../index" export const loadAllRoles = async () => { - openticket.options.getAll().forEach((opt) => { + openticket.options.forEach((opt) => { if (opt instanceof api.ODRoleOption){ openticket.roles.add(loadRole(opt)) } diff --git a/src/index.ts b/src/index.ts index 6d5281b..b9ca480 100644 --- a/src/index.ts +++ b/src/index.ts @@ -732,6 +732,10 @@ const main = async () => { await openticket.events.get("onStartScreenRender").emit([openticket.startscreen]) if (openticket.defaults.getDefault("startScreenRendering")){ await openticket.startscreen.renderAllComponents() + if (openticket.languages.getLanguageMetadata(false)?.automated){ + openticket.log("You are currently using a language which has been translated by Google Translate!","warning") + openticket.log("Please help us improve the translation by contributing to our project!","warning") + } await openticket.events.get("afterStartScreensRendered").emit([openticket.startscreen]) } From 118161698eadfa6e9b15461e0e8e8772af9bbad8 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 2 Oct 2024 22:41:12 +0200 Subject: [PATCH 034/157] Fixed blacklist bug --- src/data/openticket/blacklistLoader.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/data/openticket/blacklistLoader.ts b/src/data/openticket/blacklistLoader.ts index 63b1947..49c4a68 100644 --- a/src/data/openticket/blacklistLoader.ts +++ b/src/data/openticket/blacklistLoader.ts @@ -6,7 +6,6 @@ export const loadAllBlacklistedUsers = async () => { const users = userDatabase.getCategory("openticket:blacklist") ?? [] users.forEach((user) => { - if (typeof user.value != "string") return - openticket.blacklist.add(new api.ODBlacklist(user.key,user.value)) + if (typeof user.value == "string" || user.value === null) openticket.blacklist.add(new api.ODBlacklist(user.key,user.value)) }) } \ No newline at end of file From 6d3f2106129faf2d65d7dd01ca98e72c3151e5b5 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 2 Oct 2024 23:21:20 +0200 Subject: [PATCH 035/157] Added Italian by fraden1mvp --- README.md | 2 +- languages/italian.json | 477 +++++++++++++++++++++++++++ src/core/api/defaults/language.ts | 1 + src/data/framework/languageLoader.ts | 3 +- 4 files changed, 481 insertions(+), 2 deletions(-) create mode 100644 languages/italian.json diff --git a/README.md b/README.md index 3a5f0e1..559df1a 100644 --- a/README.md +++ b/README.md @@ -114,8 +114,8 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇷🇴 Romanian |sankedev |🟢 Up To Date | |🇺🇦 Ukrainian |anderskiy |🟢 Up To Date | |🇮🇩 Indonesian |erxg |🟢 Up To Date | +|🇮🇹 Italian |fraden1mvp. |🟢 Up To Date | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | -|🇮🇹 Italian |maurizio26 |🟠 Temporary Outdated (beta) | |🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | |🇩🇰 Danish |.the_gamer |🟠 Temporary Outdated (beta) | |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | diff --git a/languages/italian.json b/languages/italian.json new file mode 100644 index 0000000..c8e1127 --- /dev/null +++ b/languages/italian.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION": { + "otversion": "v4.0.0", + "translators": ["fraden1mvp."], + "lastedited": "02/10/2024", + "language": "Italian", + "automated": false + }, + "checker": { + "system": { + "typeError": "[ERRORE]", + "headerOpenTicket": "TICKET APERTO", + "typeWarning": "[AVVISO]", + "typeInfo": "[INFO]", + "headerConfigChecker": "CONTROLLO CONFIGURAZIONE", + "headerDescription": "controlla gli errori nei tuoi file di configurazione!", + "footerError": "il bot non si avvierà finché tutti i {0} non sono risolti!", + "footerWarning": "è consigliabile risolvere tutti i {0} prima di avviare!", + "footerSupport": "ASSISTENZA: {0} - DOCUMENTAZIONE: {1}", + "compactInformation": "usa {0} per maggiori informazioni!", + "dataPath": "percorso", + "dataDocs": "documenti", + "dataMessages": "messaggio" + }, + "messages": { + "stringTooShort": "Questa stringa non può essere più corta di {0} caratteri!", + "stringTooLong": "Questa stringa non può essere più lunga di {0} caratteri!", + "stringLengthInvalid": "Questa stringa deve essere lunga {0} caratteri!", + "stringStartsWith": "Questa stringa deve iniziare con {0}!", + "stringEndsWith": "Questa stringa deve finire con {0}!", + "stringContains": "Questa stringa deve contenere {0}!", + "stringChoices": "Questa stringa può essere solo uno dei seguenti valori: {0}!", + "stringRegex": "Questa stringa non è valida!", + + "numberTooShort": "Questo numero non può essere più corto di {0} caratteri!", + "numberTooLong": "Questo numero non può essere più lungo di {0} caratteri!", + "numberLengthInvalid": "Questo numero deve essere lungo {0} caratteri!", + "numberTooSmall": "Questo numero deve essere almeno {0}!", + "numberTooLarge": "Questo numero deve essere al massimo {0}!", + "numberNotEqual": "Questo numero deve essere {0}!", + "numberStep": "Questo numero deve essere un multiplo di {0}!", + "numberStepOffset": "Questo numero deve essere un multiplo di {0} partendo da {1}!", + "numberStartsWith": "Questo numero deve iniziare con {0}!", + "numberEndsWith": "Questo numero deve finire con {0}!", + "numberContains": "Questo numero deve contenere {0}!", + "numberChoices": "Questo numero può essere solo uno dei seguenti valori: {0}!", + "numberFloat": "Questo numero non può essere decimale!", + "numberNegative": "Questo numero non può essere negativo!", + "numberPositive": "Questo numero non può essere positivo!", + "numberZero": "Questo numero non può essere zero!", + + "booleanTrue": "Questo booleano non può essere vero!", + "booleanFalse": "Questo booleano non può essere falso!", + + "arrayEmptyDisabled": "Questo array non può essere vuoto!", + "arrayEmptyRequired": "Questo array deve essere vuoto!", + "arrayTooShort": "Questo array deve avere una lunghezza di almeno {0}!", + "arrayTooLong": "Questo array deve avere una lunghezza di al massimo {0}!", + "arrayLengthInvalid": "Questo array deve avere una lunghezza di {0}!", + "arrayInvalidTypes": "Questo array può contenere solo i seguenti tipi: {0}!", + "arrayDouble": "Questo array non consente lo stesso valore due volte!", + + "discordInvalidId": "Questo è un id discord {0} non valido!", + "discordInvalidIdOptions": "Questo è un id discord {0} non valido! Puoi anche usare uno di questi: {1}!", + "discordInvalidToken": "Questo è un token discord non valido (sintatticamente)!", + "colorInvalid": "Questo è un colore esadecimale non valido!", + "emojiTooShort": "Questa stringa deve contenere almeno {0} emoji!", + "emojiTooLong": "Questa stringa deve contenere al massimo {0} emoji!", + "emojiCustom": "Questa emoji non può essere un'emoji discord personalizzata!", + "emojiInvalid": "Questa è un'emoji non valida!", + "urlInvalid": "Questo url non è valido!", + "urlInvalidHttp": "Questo url può usare solo il protocollo https://!", + "urlInvalidProtocol": "Questo url può usare solo i protocolli http:// e https://!", + "urlInvalidHostname": "Questo url ha un hostname non consentito!", + "urlInvalidExtension": "Questo url ha un'estensione non valida! Scegli tra: {0}!", + "urlInvalidPath": "Questo url ha un percorso non valido!", + "idNotUnique": "Questo id non è unico, usa un altro id!", + "idNonExistent": "L'id {0} non esiste!", + + "invalidType": "Questa proprietà deve essere del tipo: {0}!", + "propertyMissing": "La proprietà {0} manca da questo oggetto!", + "propertyOptional": "La proprietà {0} è facoltativa in questo oggetto!", + "objectDisabled": "Questo oggetto è disabilitato, abilitalo usando {0}!", + "nullInvalid": "Questa proprietà non può essere nulla!", + "switchInvalidType": "Questo deve essere uno dei seguenti tipi: {0}!", + "objectSwitchInvalid": "Questo oggetto deve essere uno dei seguenti tipi: {0}!", + + "invalidLanguage": "Questa è una lingua non valida!", + "invalidButton": "Questo pulsante deve avere almeno un {0} o {1}!", + "unusedOption": "L'opzione {0} non è utilizzata da nessuna parte!", + "unusedQuestion": "La domanda {0} non è utilizzata da nessuna parte!", + "dropdownOption": "Un pannello con il dropdown attivato può contenere solo opzioni di tipo 'ticket'!" + } + }, + "actions": { + "buttons": { + "create": "Visita Ticket", + "close": "Chiudi Ticket", + "delete": "Elimina Ticket", + "reopen": "Riapri Ticket", + "claim": "Richiedi Ticket", + "unclaim": "Annulla Richiesta Ticket", + "pin": "Fissa Ticket", + "unpin": "Sblocca Ticket", + "clear": "Elimina Tickets", + "helpSwitchSlash": "Visualizza Comandi Slash", + "helpSwitchText": "Visualizza Comandi Testo", + "helpPage": "Pagina {0}", + "withReason": "Con Motivo", + "withoutTranscript": "Senza Trascrizione" + }, + "titles": { + "created": "Ticket Creato", + "close": "Ticket Chiuso", + "delete": "Ticket Eliminato", + "reopen": "Ticket Riaperto", + "claim": "Ticket Richiesto", + "unclaim": "Ticket Richiesta Annullata", + "pin": "Ticket Fissato", + "unpin": "Ticket Sbloccato", + "rename": "Ticket Rinominato", + "move": "Ticket Spostato", + "add": "Utente Aggiunto al Ticket", + "remove": "Utente Rimosso dal Ticket", + + "help": "Comandi Disponibili", + "statsReset": "Ripristina Statistiche", + "blacklistAdd": "Utente Aggiunto alla Blacklist", + "blacklistRemove": "Utente Rimosso dalla Blacklist", + "blacklistGet": "Utente in Blacklist", + "blacklistView": "Blacklist Corrente", + "blacklistAddDm": "Aggiunto alla Blacklist", + "blacklistRemoveDm": "Rimosso dalla Blacklist", + "clear": "Tickets Cancellati", + "roles": "Ruoli Aggiornati", + + "autoclose": "Ticket Autochiuso", + "autocloseEnabled": "Autochiusura Abilitata", + "autocloseDisabled": "Autochiusura Disabilitata", + "autodelete": "Ticket Autocancellato", + "autodeleteEnabled": "Autocancellazione Abilitata", + "autodeleteDisabled": "Autocancellazione Disabilitata" + }, + "descriptions": { + "create": "Il tuo ticket è stato creato. Clicca il pulsante qui sotto per accedervi!", + "close": "Il ticket è stato chiuso con successo!", + "delete": "Il ticket è stato eliminato con successo!", + "reopen": "Il ticket è stato riaperto con successo!", + "claim": "Il ticket è stato richiesto con successo!", + "unclaim": "Il ticket è stato annullato con successo!", + "pin": "Il ticket è stato fissato con successo!", + "unpin": "Il ticket è stato sbloccato con successo!", + "rename": "Il ticket è stato rinominato in {0} con successo!", + "move": "Il ticket è stato spostato in {0} con successo!", + "add": "{0} è stato aggiunto al ticket con successo!", + "remove": "{0} è stato rimosso dal ticket con successo!", + + "helpExplanation": "`` => parametro obbligatorio\n`[name]` => parametro facoltativo", + "statsReset": "Le statistiche del bot sono state ripristinate con successo!", + "statsError": "Impossibile visualizzare le statistiche del ticket!\n{0} non è un ticket!", + "blacklistAdd": "{0} è stato aggiunto alla blacklist con successo!", + "blacklistRemove": "{0} è stato rimosso con successo dalla blacklist!", + "blacklistGetSuccess": "{0} è attualmente nella blacklist!", + "blacklistGetEmpty": "{0} non è attualmente nella blacklist!", + "blacklistViewEmpty": "Nessuno è stato aggiunto alla blacklist finora!", + "blacklistViewTip": "Usa \"/blacklist add\" per aggiungere un utente alla blacklist!", + "clearVerify": "Sei sicuro di voler eliminare più ticket?\nQuesta azione non può essere annullata!", + "clearReady": "{0} tickets sono stati eliminati con successo!", + "rolesEmpty": "Nessun ruolo è stato aggiornato!", + + "autocloseLeave": "Questo ticket è stato autochiuso perché il creatore ha lasciato il server!", + "autocloseTimeout": "Questo ticket è stato autochiuso perché è stato inattivo per più di `{0}h`!", + "autodeleteLeave": "Questo ticket è stato autocancellato perché il creatore ha lasciato il server!", + "autodeleteTimeout": "Questo ticket è stato autocancellato perché è stato inattivo per più di `{0} giorni`!", + "autocloseEnabled": "L'autochiusura è stata abilitata in questo ticket!\nSarà chiuso quando sarà inattivo per più di `{0}h`!", + "autocloseDisabled": "L'autochiusura è stata disabilitata in questo ticket!\nNon sarà più chiuso automaticamente!", + "autodeleteEnabled": "L'autocancellazione è stata abilitata in questo ticket!\nSarà cancellato quando sarà inattivo per più di `{0} giorni`!", + "autodeleteDisabled": "L'autocancellazione è stata disabilitata in questo ticket!\nNon sarà più cancellato automaticamente!", + + "ticketMessageLimit": "Puoi creare solo {0} ticket contemporaneamente!", + "ticketMessageAutoclose": "Questo ticket sarà autochiuso quando sarà inattivo per {0}h!", + "ticketMessageAutodelete": "Questo ticket sarà autocancellato quando sarà inattivo per {0} giorni!", + "panelReady": "Puoi trovare il pannello qui sotto!\nQuesto messaggio può ora essere eliminato!" + }, + "modal": { + "closePlaceholder": "Perché hai chiuso questo ticket?", + "deletePlaceholder": "Perché hai eliminato questo ticket?", + "reopenPlaceholder": "Perché hai riaperto questo ticket?", + "claimPlaceholder": "Perché hai richiesto questo ticket?", + "unclaimPlaceholder": "Perché hai annullato la richiesta di questo ticket?", + "pinPlaceholder": "Perché hai fissato questo ticket?", + "unpinPlaceholder": "Perché hai sbloccato questo ticket?" + }, + "logs": { + "createLog": "Un nuovo ticket è stato creato da {0}!", + "closeLog": "Questo ticket è stato chiuso da {0}!", + "closeDm": "Il tuo ticket è stato chiuso nel nostro server!", + "deleteLog": "Questo ticket è stato eliminato da {0}!", + "deleteDm": "Il tuo ticket è stato eliminato nel nostro server!", + "reopenLog": "Questo ticket è stato riaperto da {0}!", + "reopenDm": "Il tuo ticket è stato riaperto nel nostro server!", + "claimLog": "Questo ticket è stato richiesto da {0}!", + "claimDm": "Il tuo ticket è stato richiesto nel nostro server!", + "unclaimLog": "Questo ticket è stato annullato da {0}!", + "unclaimDm": "Il tuo ticket è stato annullato nel nostro server!", + "pinLog": "Questo ticket è stato fissato da {0}!", + "pinDm": "Il tuo ticket è stato fissato nel nostro server!", + "unpinLog": "Questo ticket è stato sbloccato da {0}!", + "unpinDm": "Il tuo ticket è stato sbloccato nel nostro server!", + "renameLog": "Questo ticket è stato rinominato in {0} da {1}!", + "renameDm": "Il tuo ticket è stato rinominato in {0} nel nostro server!", + "moveLog": "Questo ticket è stato spostato in {0} da {1}!", + "moveDm": "Il tuo ticket è stato spostato in {0} nel nostro server!", + "addLog": "{0} è stato aggiunto a questo ticket da {1}!", + "addDm": "{0} è stato aggiunto al tuo ticket nel nostro server!", + "removeLog": "{0} è stato rimosso da questo ticket da {1}!", + "removeDm": "{0} è stato rimosso dal tuo ticket nel nostro server!", + + "blacklistAddLog": "{0} è stato aggiunto alla blacklist da {1}!", + "blacklistRemoveLog": "{0} è stato rimosso dalla blacklist da {1}!", + "blacklistAddDm": "Sei stato aggiunto alla blacklist nel nostro server!\nD'ora in poi, non puoi creare ticket!", + "blacklistRemoveDm": "Sei stato rimosso dalla blacklist nel nostro server!\nOra puoi creare ticket di nuovo!", + "clearLog": "{0} tickets sono stati eliminati da {1}!" + } + }, + "transcripts": { + "success": { + "visit": "Visita Trascrizione", + "ready": "Trascrizione Creata", + "textFileDescription": "Questa è la trascrizione testuale di un ticket eliminato!", + "htmlProgress": "Attendere mentre questa trascrizione html viene elaborata...", + "createdChannel": "Una nuova trascrizione di {0} è stata creata nel server!", + "createdCreator": "Una nuova trascrizione di {0} è stata creata per uno dei tuoi ticket!", + "createdParticipant": "Una nuova trascrizione di {0} è stata creata in uno dei ticket a cui hai partecipato!", + "createdActiveAdmin": "Una nuova trascrizione di {0} è stata creata in uno dei ticket in cui hai partecipato come admin!", + "createdEveryAdmin": "Una nuova trascrizione di {0} è stata creata in uno dei ticket in cui eri admin!", + "createdOther": "Una nuova trascrizione di {0} è stata creata!" + }, + "errors": { + "retry": "Riprova", + "continue": "Elimina Senza Trascrizione", + "backup": "Crea Trascrizione di Backup", + "error": "Qualcosa è andato storto durante la creazione della trascrizione.\nCosa vuoi fare?\n\nQuesto ticket non sarà eliminato finché non clicchi su uno di questi pulsanti." + } + }, + "errors": { + "titles": { + "internalError": "Errore Interno", + "optionMissing": "Opzione Comando Mancante", + "optionInvalid": "Opzione Comando Non Valida", + "unknownCommand": "Comando Sconosciuto", + "noPermissions": "Nessuna Autorizzazione", + "unknownTicket": "Ticket Sconosciuto", + "deprecatedTicket": "Ticket Obsoleto", + "unknownOption": "Opzione Sconosciuta", + "unknownPanel": "Pannello Sconosciuto", + "notInGuild": "Non nel Server", + "channelRename": "Impossibile Rinominare il Canale", + "busy": "Ticket Occupato" + }, + "descriptions": { + "askForInfo": "Contatta il proprietario di questo bot per ulteriori informazioni!", + "askForInfoResolve": "Contatta il proprietario di questo bot se il problema non si risolve dopo alcuni tentativi.", + "internalError": "Impossibile rispondere a questo {0} a causa di un errore interno!", + "optionMissing": "Un parametro obbligatorio è mancante in questo comando!", + "optionInvalid": "Un parametro in questo comando non è valido!", + "optionInvalidChoose": "Scegli tra", + "unknownCommand": "Prova a visitare il menu di aiuto per ulteriori informazioni!", + "noPermissions": "Non hai il permesso di utilizzare questo {0}!", + "noPermissionsList": "Permessi Richiesti: (uno di essi)", + "noPermissionsCooldown": "Non hai il permesso di utilizzare questo {0} perché hai un cooldown!", + "noPermissionsBlacklist": "Non hai il permesso di utilizzare questo {0} perché sei stato blacklistato!", + "noPermissionsLimitGlobal": "Non puoi creare un ticket perché il server ha raggiunto il limite massimo di ticket!", + "noPermissionsLimitGlobalUser": "Non puoi creare un ticket perché hai raggiunto il limite massimo di ticket!", + "noPermissionsLimitOption": "Non puoi creare un ticket perché il server ha raggiunto il limite massimo di ticket per questa opzione!", + "noPermissionsLimitOptionUser": "Non puoi creare un ticket perché hai raggiunto il limite massimo di ticket per questa opzione!", + "unknownTicket": "Prova questo comando di nuovo in un ticket valido!", + "deprecatedTicket": "Il canale attuale non è un ticket valido! Potrebbe essere un ticket di una vecchia versione di Open Ticket!", + "notInGuild": "Questo {0} non funziona in DM! Riprova in un server!", + "channelRename": "A causa dei limiti di Discord, al momento non è possibile rinominare il canale. Il canale verrà automaticamente rinominato in oltre 10 minuti se il bot non viene riavviato.", + "channelRenameSource": "La fonte di questo errore è: {0}", + "busy": "Impossibile utilizzare questo {0}!\nIl ticket è attualmente in fase di elaborazione dal bot.\n\nPer favore riprova tra pochi secondi!" + }, + "optionInvalidReasons": { + "stringRegex": "Il valore non corrisponde al modello!", + "stringMinLength": "Il valore deve essere di almeno {0} caratteri!", + "stringMaxLength": "Il valore deve essere di al massimo {0} caratteri!", + "numberInvalid": "Numero non valido!", + "numberMin": "Il numero deve essere almeno {0}!", + "numberMax": "Il numero deve essere al massimo {0}!", + "numberDecimal": "Il numero non è consentito come decimale!", + "numberNegative": "Il numero non è consentito come negativo!", + "numberPositive": "Il numero non è consentito come positivo!", + "numberZero": "Il numero non è consentito come zero!", + "channelNotFound": "Impossibile trovare il canale!", + "userNotFound": "Impossibile trovare l'utente!", + "roleNotFound": "Impossibile trovare il ruolo!", + "memberNotFound": "Impossibile trovare l'utente!", + "mentionableNotFound": "Impossibile trovare l'utente o il ruolo!", + "channelType": "Tipo di canale non valido!", + "notInGuild": "Questa opzione richiede che tu sia in un server!" + }, + "permissions": { + "developer": "Devi essere lo sviluppatore del bot.", + "owner": "Devi essere il proprietario del server.", + "admin": "Devi essere un admin del server.", + "moderator": "Devi essere un moderatore.", + "support": "Devi essere nel team di supporto.", + "member": "Devi essere un membro.", + "discord-administrator": "Devi avere il permesso `ADMINISTRATOR`." + }, + "actionInvalid": { + "close": "Il ticket è già chiuso!", + "reopen": "Il ticket non è ancora chiuso!", + "claim": "Il ticket è già stato rivendicato!", + "unclaim": "Il ticket non è ancora stato rivendicato!", + "pin": "Il ticket è già stato fissato!", + "unpin": "Il ticket non è ancora stato sbloccato!", + "add": "Questo utente può già accedere al ticket!", + "remove": "Impossibile rimuovere questo utente dal ticket!" + } + }, + "params": { + "uppercase": { + "ticket": "Ticket", + "tickets": "Tickets", + "reason": "Motivo", + "creator": "Creatore", + "remaining": "Tempo Rimanente", + "added": "Aggiunto", + "removed": "Rimosso", + "filter": "Filtro", + "claimedBy": "Rivendicato Da {0}", + "method": "Metodo", + "type": "Tipo", + "blacklisted": "Blacklistato", + "panel": "Pannello", + "command": "Comando", + "system": "Sistema", + "true": "Vero", + "false": "Falso", + "syntax": "Sintassi", + "originalName": "Nome Originale", + "newName": "Nuovo Nome", + "until": "Fino a", + "validOptions": "Opzioni Valide", + "validPanels": "Pannelli Validi", + "autoclose": "Chiusura Automatica", + "autodelete": "Cancellazione Automatica", + "startupDate": "Data di Avvio", + "version": "Versione", + "name": "Nome", + "role": "Ruolo", + "status": "Stato", + "claimed": "Rivendicato", + "pinned": "Fissato", + "creationDate": "Data di Creazione" + }, + "lowercase": { + "text": "testo", + "html": "html", + "command": "comando", + "modal": "modale", + "button": "pulsante", + "dropdown": "dropdown", + "method": "metodo" + } + }, + "commands": { + "reason": "Specifica un motivo facoltativo che sarà visibile nei log.", + "help": "Ottieni un elenco di tutti i comandi disponibili.", + "panel": "Genera un messaggio con un dropdown o pulsanti (per la creazione del ticket).", + "panelId": "L'identificatore del pannello che vuoi generare.", + "panelAutoUpdate": "Vuoi che questo pannello si aggiorni automaticamente quando viene modificato?", + "ticket": "Crea istantaneamente un ticket.", + "ticketId": "L'identificatore del ticket che vuoi creare.", + "close": "Chiudi un ticket.", + "delete": "Elimina un ticket.", + "deleteNoTranscript": "Elimina questo ticket senza creare una trascrizione.", + "reopen": "Riapri un ticket.", + "claim": "Rivendica un ticket.", + "claimUser": "Rivendica questo ticket a qualcun altro invece di te stesso.", + "unclaim": "Rimuovi la rivendicazione di un ticket.", + "pin": "Fissa un ticket.", + "unpin": "Sblocca un ticket.", + "move": "Sposta un ticket.", + "moveId": "L'identificatore dell'opzione a cui vuoi spostare.", + "rename": "Rinomina un ticket.", + "renameName": "Il nuovo nome per questo ticket.", + "add": "Aggiungi un utente a un ticket.", + "addUser": "L'utente da aggiungere.", + "remove": "Rimuovi un utente da un ticket.", + "removeUser": "L'utente da rimuovere.", + "blacklist": "Gestisci la blacklist del ticket.", + "blacklistView": "Visualizza un elenco della blacklist attuale.", + "blacklistAdd": "Aggiungi un utente alla blacklist.", + "blacklistRemove": "Rimuovi un utente dalla blacklist.", + "blacklistGet": "Ottieni i dettagli di un utente blacklistato.", + "blacklistGetUser": "L'utente di cui ottenere i dettagli.", + "stats": "Visualizza le statistiche del bot, di un membro o di un ticket.", + "statsReset": "Reimposta tutte le statistiche del bot (e inizia a contare da zero).", + "statsGlobal": "Visualizza le statistiche globali.", + "statsUser": "Visualizza le statistiche di un utente nel server.", + "statsUserUser": "L'utente di cui visualizzare le statistiche.", + "statsTicket": "Visualizza le statistiche di un ticket nel server.", + "statsTicketTicket": "Il ticket da visualizzare.", + "clear": "Elimina più ticket contemporaneamente.", + "clearFilter": "Il filtro per eliminare ticket.", + "clearFilters": { + "all": "Tutti", + "open": "Aperti", + "close": "Chiusi", + "claim": "Rivendicati", + "unclaim": "Non Rivendicati", + "pin": "Fissati", + "unpin": "Non Fissati", + "autoclose": "Chiusura Automatica" + }, + "autoclose": "Gestisci la chiusura automatica in un ticket.", + "autocloseDisable": "Disabilita la chiusura automatica in questo ticket.", + "autocloseEnable": "Abilita la chiusura automatica in questo ticket.", + "autocloseEnableTime": "Il numero di ore in cui questo ticket deve essere inattivo per chiuderlo.", + "autodelete": "Gestisci la cancellazione automatica in un ticket.", + "autodeleteDisable": "Disabilita la cancellazione automatica in questo ticket.", + "autodeleteEnable": "Abilita la cancellazione automatica in questo ticket.", + "autodeleteEnableTime": "Il numero di giorni in cui questo ticket deve essere inattivo per eliminarlo." + }, + "helpMenu": { + "help": "Ottieni un elenco di tutti i comandi disponibili.", + "ticket": "Crea istantaneamente un ticket.", + "close": "Chiudi un ticket, disabilita la scrittura in questo canale.", + "delete": "Elimina un ticket, crea una trascrizione quando abilitato.", + "reopen": "Riapri un ticket, abilita nuovamente la scrittura in questo canale.", + "pin": "Fissa un ticket. Questo lo sposterà in cima e aggiungerà un'emoji '📌' al nome.", + "unpin": "Sblocca un ticket. Il ticket rimarrà nella sua posizione ma perderà l'emoji '📌'.", + "move": "Sposta un ticket. Questo cambierà il tipo di questo ticket.", + "rename": "Rinomina un ticket. Questo cambierà il nome del canale di questo ticket.", + "claim": "Rivendica un ticket. In questo modo, il tuo team saprà che stai gestendo questo ticket.", + "unclaim": "Rimuovi la rivendicazione di un ticket. In questo modo, il tuo team saprà che questo ticket è di nuovo libero.", + "add": "Aggiungi un utente a un ticket. Questo permetterà all'utente di leggere e scrivere in questo ticket.", + "remove": "Rimuovi un utente da un ticket. Questo rimuoverà la possibilità di leggere e scrivere per un utente in questo ticket.", + "panel": "Genera un messaggio con un dropdown o pulsanti (per la creazione del ticket).", + "blacklistView": "Visualizza un elenco della blacklist attuale.", + "blacklistAdd": "Aggiungi un utente alla blacklist.", + "blacklistRemove": "Rimuovi un utente dalla blacklist.", + "blacklistGet": "Ottieni i dettagli di un utente blacklistato.", + "statsGlobal": "Visualizza le statistiche globali.", + "statsTicket": "Visualizza le statistiche di un ticket nel server.", + "statsUser": "Visualizza le statistiche di un utente nel server.", + "statsReset": "Reimposta tutte le statistiche del bot (e inizia a contare da zero).", + "autocloseDisable": "Disabilita la chiusura automatica in questo ticket.", + "autocloseEnable": "Abilita la chiusura automatica in questo ticket.", + "autodeleteDisable": "Disabilita la cancellazione automatica in questo ticket.", + "autodeleteEnable": "Abilita la cancellazione automatica in questo ticket." + }, + "stats": { + "scopes": { + "global": "Statistiche Globali", + "system": "Statistiche di Sistema", + "user": "Statistiche Utente", + "ticket": "Statistiche Ticket", + "participants": "Partecipanti" + }, + "properties": { + "ticketsCreated": "Ticket Creati", + "ticketsClosed": "Ticket Chiusi", + "ticketsDeleted": "Ticket Eliminati", + "ticketsReopened": "Ticket Riaperti", + "ticketsAutoclosed": "Ticket Chiusi Automaticamente", + "ticketsClaimed": "Ticket Rivendicati", + "ticketsPinned": "Ticket Fissati", + "ticketsMoved": "Ticket Spostati", + "usersBlacklisted": "Utenti Blacklistati", + "transcriptsCreated": "Trascrizioni Create" + } + } + } diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index 2c76914..b71b19f 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -456,6 +456,7 @@ export interface ODLanguageManagerIds_Default { "openticket:romanian":ODLanguage, "openticket:ukrainian":ODLanguage, "openticket:indonesian":ODLanguage, + "openticket:italian":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 5ffae01..af1ff66 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -14,10 +14,11 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODLanguage("openticket:romanian","romanian.json")) openticket.languages.add(new api.ODLanguage("openticket:ukrainian","ukrainian.json")) openticket.languages.add(new api.ODLanguage("openticket:indonesian","indonesian.json")) + openticket.languages.add(new api.ODLanguage("openticket:italian","italian.json")) //list for config checker const languageList = openticket.defaults.getDefault("languageList") - languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian","indonesian") + languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian","indonesian","italian") openticket.defaults.setDefault("languageList",languageList) /** How to add more languages? From 7fa5dca7b36b28772928bf34bc8fd1b661ed18bf Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 2 Oct 2024 23:28:00 +0200 Subject: [PATCH 036/157] Updated Italian --- README.md | 32 +- languages/italian.json | 870 ++++++++++++++++++++--------------------- 2 files changed, 451 insertions(+), 451 deletions(-) diff --git a/README.md b/README.md index 559df1a..d8cf541 100644 --- a/README.md +++ b/README.md @@ -101,30 +101,30 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat ### 💬 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 | +|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. & ChatGPT |🔵 Up To Date (ChatGPT) | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | |🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | |🇩🇰 Danish |.the_gamer |🟠 Temporary Outdated (beta) | |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | |🇹🇷 Turkish |0x15d3 |🟠 Temporary Outdated (beta) | |🇵🇱 Polish |mkevas |🟠 Temporary Outdated (beta) | -|🇸🇮 Slovenian |n1kkec |🔴 Outdated | +|🇸🇮 Slovenian |n1kkec |🔴 Outdated | |🇹🇭 Thai |modshd |🟠 Temporary Outdated (beta) | |🇳🇴 Norwegian |noonenook |🟠 Temporary Outdated (beta) | -|🇬🇷 Greek |stefanos__. |🔴 Outdated | +|🇬🇷 Greek |stefanos__. |🔴 Outdated | |❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | |❓ Persian |sasanwm |🟠 Temporary Outdated (beta) | |🇱🇻 Latvian |ronalds1398 |🟠 Temporary Outdated (beta) | diff --git a/languages/italian.json b/languages/italian.json index c8e1127..31483b5 100644 --- a/languages/italian.json +++ b/languages/italian.json @@ -1,477 +1,477 @@ { - "_TRANSLATION": { - "otversion": "v4.0.0", - "translators": ["fraden1mvp."], - "lastedited": "02/10/2024", - "language": "Italian", - "automated": false + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translators":["fraden1mvp.","ChatGPT"], + "lastedited":"02/10/2024", + "language":"Italian", + "automated":true }, - "checker": { - "system": { - "typeError": "[ERRORE]", - "headerOpenTicket": "TICKET APERTO", - "typeWarning": "[AVVISO]", - "typeInfo": "[INFO]", - "headerConfigChecker": "CONTROLLO CONFIGURAZIONE", - "headerDescription": "controlla gli errori nei tuoi file di configurazione!", - "footerError": "il bot non si avvierà finché tutti i {0} non sono risolti!", - "footerWarning": "è consigliabile risolvere tutti i {0} prima di avviare!", - "footerSupport": "ASSISTENZA: {0} - DOCUMENTAZIONE: {1}", - "compactInformation": "usa {0} per maggiori informazioni!", - "dataPath": "percorso", - "dataDocs": "documenti", - "dataMessages": "messaggio" + "checker":{ + "system":{ + "typeError":"[ERRORE]", + "headerOpenTicket":"TICKET APERTO", + "typeWarning":"[AVVISO]", + "typeInfo":"[INFO]", + "headerConfigChecker":"CONTROLLO CONFIGURAZIONE", + "headerDescription":"controlla gli errori nei tuoi file di configurazione!", + "footerError":"il bot non si avvierà finché tutti i {0} non sono risolti!", + "footerWarning":"è consigliabile risolvere tutti i {0} prima di avviare!", + "footerSupport":"ASSISTENZA: {0} - DOCUMENTAZIONE: {1}", + "compactInformation":"usa {0} per maggiori informazioni!", + "dataPath":"percorso", + "dataDocs":"documenti", + "dataMessages":"messaggio" }, - "messages": { - "stringTooShort": "Questa stringa non può essere più corta di {0} caratteri!", - "stringTooLong": "Questa stringa non può essere più lunga di {0} caratteri!", - "stringLengthInvalid": "Questa stringa deve essere lunga {0} caratteri!", - "stringStartsWith": "Questa stringa deve iniziare con {0}!", - "stringEndsWith": "Questa stringa deve finire con {0}!", - "stringContains": "Questa stringa deve contenere {0}!", - "stringChoices": "Questa stringa può essere solo uno dei seguenti valori: {0}!", - "stringRegex": "Questa stringa non è valida!", + "messages":{ + "stringTooShort":"Questa stringa non può essere più corta di {0} caratteri!", + "stringTooLong":"Questa stringa non può essere più lunga di {0} caratteri!", + "stringLengthInvalid":"Questa stringa deve essere lunga {0} caratteri!", + "stringStartsWith":"Questa stringa deve iniziare con {0}!", + "stringEndsWith":"Questa stringa deve finire con {0}!", + "stringContains":"Questa stringa deve contenere {0}!", + "stringChoices":"Questa stringa può essere solo uno dei seguenti valori: {0}!", + "stringRegex":"Questa stringa non è valida!", - "numberTooShort": "Questo numero non può essere più corto di {0} caratteri!", - "numberTooLong": "Questo numero non può essere più lungo di {0} caratteri!", - "numberLengthInvalid": "Questo numero deve essere lungo {0} caratteri!", - "numberTooSmall": "Questo numero deve essere almeno {0}!", - "numberTooLarge": "Questo numero deve essere al massimo {0}!", - "numberNotEqual": "Questo numero deve essere {0}!", - "numberStep": "Questo numero deve essere un multiplo di {0}!", - "numberStepOffset": "Questo numero deve essere un multiplo di {0} partendo da {1}!", - "numberStartsWith": "Questo numero deve iniziare con {0}!", - "numberEndsWith": "Questo numero deve finire con {0}!", - "numberContains": "Questo numero deve contenere {0}!", - "numberChoices": "Questo numero può essere solo uno dei seguenti valori: {0}!", - "numberFloat": "Questo numero non può essere decimale!", - "numberNegative": "Questo numero non può essere negativo!", - "numberPositive": "Questo numero non può essere positivo!", - "numberZero": "Questo numero non può essere zero!", + "numberTooShort":"Questo numero non può essere più corto di {0} caratteri!", + "numberTooLong":"Questo numero non può essere più lungo di {0} caratteri!", + "numberLengthInvalid":"Questo numero deve essere lungo {0} caratteri!", + "numberTooSmall":"Questo numero deve essere almeno {0}!", + "numberTooLarge":"Questo numero deve essere al massimo {0}!", + "numberNotEqual":"Questo numero deve essere {0}!", + "numberStep":"Questo numero deve essere un multiplo di {0}!", + "numberStepOffset":"Questo numero deve essere un multiplo di {0} partendo da {1}!", + "numberStartsWith":"Questo numero deve iniziare con {0}!", + "numberEndsWith":"Questo numero deve finire con {0}!", + "numberContains":"Questo numero deve contenere {0}!", + "numberChoices":"Questo numero può essere solo uno dei seguenti valori: {0}!", + "numberFloat":"Questo numero non può essere decimale!", + "numberNegative":"Questo numero non può essere negativo!", + "numberPositive":"Questo numero non può essere positivo!", + "numberZero":"Questo numero non può essere zero!", - "booleanTrue": "Questo booleano non può essere vero!", - "booleanFalse": "Questo booleano non può essere falso!", + "booleanTrue":"Questo booleano non può essere vero!", + "booleanFalse":"Questo booleano non può essere falso!", - "arrayEmptyDisabled": "Questo array non può essere vuoto!", - "arrayEmptyRequired": "Questo array deve essere vuoto!", - "arrayTooShort": "Questo array deve avere una lunghezza di almeno {0}!", - "arrayTooLong": "Questo array deve avere una lunghezza di al massimo {0}!", - "arrayLengthInvalid": "Questo array deve avere una lunghezza di {0}!", - "arrayInvalidTypes": "Questo array può contenere solo i seguenti tipi: {0}!", - "arrayDouble": "Questo array non consente lo stesso valore due volte!", + "arrayEmptyDisabled":"Questo array non può essere vuoto!", + "arrayEmptyRequired":"Questo array deve essere vuoto!", + "arrayTooShort":"Questo array deve avere una lunghezza di almeno {0}!", + "arrayTooLong":"Questo array deve avere una lunghezza di al massimo {0}!", + "arrayLengthInvalid":"Questo array deve avere una lunghezza di {0}!", + "arrayInvalidTypes":"Questo array può contenere solo i seguenti tipi: {0}!", + "arrayDouble":"Questo array non consente lo stesso valore due volte!", - "discordInvalidId": "Questo è un id discord {0} non valido!", - "discordInvalidIdOptions": "Questo è un id discord {0} non valido! Puoi anche usare uno di questi: {1}!", - "discordInvalidToken": "Questo è un token discord non valido (sintatticamente)!", - "colorInvalid": "Questo è un colore esadecimale non valido!", - "emojiTooShort": "Questa stringa deve contenere almeno {0} emoji!", - "emojiTooLong": "Questa stringa deve contenere al massimo {0} emoji!", - "emojiCustom": "Questa emoji non può essere un'emoji discord personalizzata!", - "emojiInvalid": "Questa è un'emoji non valida!", - "urlInvalid": "Questo url non è valido!", - "urlInvalidHttp": "Questo url può usare solo il protocollo https://!", - "urlInvalidProtocol": "Questo url può usare solo i protocolli http:// e https://!", - "urlInvalidHostname": "Questo url ha un hostname non consentito!", - "urlInvalidExtension": "Questo url ha un'estensione non valida! Scegli tra: {0}!", - "urlInvalidPath": "Questo url ha un percorso non valido!", - "idNotUnique": "Questo id non è unico, usa un altro id!", - "idNonExistent": "L'id {0} non esiste!", + "discordInvalidId":"Questo è un id discord {0} non valido!", + "discordInvalidIdOptions":"Questo è un id discord {0} non valido! Puoi anche usare uno di questi: {1}!", + "discordInvalidToken":"Questo è un token discord non valido (sintatticamente)!", + "colorInvalid":"Questo è un colore esadecimale non valido!", + "emojiTooShort":"Questa stringa deve contenere almeno {0} emoji!", + "emojiTooLong":"Questa stringa deve contenere al massimo {0} emoji!", + "emojiCustom":"Questa emoji non può essere un'emoji discord personalizzata!", + "emojiInvalid":"Questa è un'emoji non valida!", + "urlInvalid":"Questo url non è valido!", + "urlInvalidHttp":"Questo url può usare solo il protocollo https://!", + "urlInvalidProtocol":"Questo url può usare solo i protocolli http:// e https://!", + "urlInvalidHostname":"Questo url ha un hostname non consentito!", + "urlInvalidExtension":"Questo url ha un'estensione non valida! Scegli tra: {0}!", + "urlInvalidPath":"Questo url ha un percorso non valido!", + "idNotUnique":"Questo id non è unico, usa un altro id!", + "idNonExistent":"L'id {0} non esiste!", - "invalidType": "Questa proprietà deve essere del tipo: {0}!", - "propertyMissing": "La proprietà {0} manca da questo oggetto!", - "propertyOptional": "La proprietà {0} è facoltativa in questo oggetto!", - "objectDisabled": "Questo oggetto è disabilitato, abilitalo usando {0}!", - "nullInvalid": "Questa proprietà non può essere nulla!", - "switchInvalidType": "Questo deve essere uno dei seguenti tipi: {0}!", - "objectSwitchInvalid": "Questo oggetto deve essere uno dei seguenti tipi: {0}!", + "invalidType":"Questa proprietà deve essere del tipo: {0}!", + "propertyMissing":"La proprietà {0} manca da questo oggetto!", + "propertyOptional":"La proprietà {0} è facoltativa in questo oggetto!", + "objectDisabled":"Questo oggetto è disabilitato, abilitalo usando {0}!", + "nullInvalid":"Questa proprietà non può essere nulla!", + "switchInvalidType":"Questo deve essere uno dei seguenti tipi: {0}!", + "objectSwitchInvalid":"Questo oggetto deve essere uno dei seguenti tipi: {0}!", - "invalidLanguage": "Questa è una lingua non valida!", - "invalidButton": "Questo pulsante deve avere almeno un {0} o {1}!", - "unusedOption": "L'opzione {0} non è utilizzata da nessuna parte!", - "unusedQuestion": "La domanda {0} non è utilizzata da nessuna parte!", - "dropdownOption": "Un pannello con il dropdown attivato può contenere solo opzioni di tipo 'ticket'!" + "invalidLanguage":"Questa è una lingua non valida!", + "invalidButton":"Questo pulsante deve avere almeno un {0} o {1}!", + "unusedOption":"L'opzione {0} non è utilizzata da nessuna parte!", + "unusedQuestion":"La domanda {0} non è utilizzata da nessuna parte!", + "dropdownOption":"Un pannello con il dropdown attivato può contenere solo opzioni di tipo 'ticket'!" } }, - "actions": { - "buttons": { - "create": "Visita Ticket", - "close": "Chiudi Ticket", - "delete": "Elimina Ticket", - "reopen": "Riapri Ticket", - "claim": "Richiedi Ticket", - "unclaim": "Annulla Richiesta Ticket", - "pin": "Fissa Ticket", - "unpin": "Sblocca Ticket", - "clear": "Elimina Tickets", - "helpSwitchSlash": "Visualizza Comandi Slash", - "helpSwitchText": "Visualizza Comandi Testo", - "helpPage": "Pagina {0}", - "withReason": "Con Motivo", - "withoutTranscript": "Senza Trascrizione" + "actions":{ + "buttons":{ + "create":"Visita Ticket", + "close":"Chiudi Ticket", + "delete":"Elimina Ticket", + "reopen":"Riapri Ticket", + "claim":"Richiedi Ticket", + "unclaim":"Annulla Richiesta Ticket", + "pin":"Fissa Ticket", + "unpin":"Sblocca Ticket", + "clear":"Elimina Tickets", + "helpSwitchSlash":"Visualizza Comandi Slash", + "helpSwitchText":"Visualizza Comandi Testo", + "helpPage":"Pagina {0}", + "withReason":"Con Motivo", + "withoutTranscript":"Senza Trascrizione" }, - "titles": { - "created": "Ticket Creato", - "close": "Ticket Chiuso", - "delete": "Ticket Eliminato", - "reopen": "Ticket Riaperto", - "claim": "Ticket Richiesto", - "unclaim": "Ticket Richiesta Annullata", - "pin": "Ticket Fissato", - "unpin": "Ticket Sbloccato", - "rename": "Ticket Rinominato", - "move": "Ticket Spostato", - "add": "Utente Aggiunto al Ticket", - "remove": "Utente Rimosso dal Ticket", + "titles":{ + "created":"Ticket Creato", + "close":"Ticket Chiuso", + "delete":"Ticket Eliminato", + "reopen":"Ticket Riaperto", + "claim":"Ticket Richiesto", + "unclaim":"Ticket Richiesta Annullata", + "pin":"Ticket Fissato", + "unpin":"Ticket Sbloccato", + "rename":"Ticket Rinominato", + "move":"Ticket Spostato", + "add":"Utente Aggiunto al Ticket", + "remove":"Utente Rimosso dal Ticket", - "help": "Comandi Disponibili", - "statsReset": "Ripristina Statistiche", - "blacklistAdd": "Utente Aggiunto alla Blacklist", - "blacklistRemove": "Utente Rimosso dalla Blacklist", - "blacklistGet": "Utente in Blacklist", - "blacklistView": "Blacklist Corrente", - "blacklistAddDm": "Aggiunto alla Blacklist", - "blacklistRemoveDm": "Rimosso dalla Blacklist", - "clear": "Tickets Cancellati", - "roles": "Ruoli Aggiornati", + "help":"Comandi Disponibili", + "statsReset":"Ripristina Statistiche", + "blacklistAdd":"Utente Aggiunto alla Blacklist", + "blacklistRemove":"Utente Rimosso dalla Blacklist", + "blacklistGet":"Utente in Blacklist", + "blacklistView":"Blacklist Corrente", + "blacklistAddDm":"Aggiunto alla Blacklist", + "blacklistRemoveDm":"Rimosso dalla Blacklist", + "clear":"Tickets Cancellati", + "roles":"Ruoli Aggiornati", - "autoclose": "Ticket Autochiuso", - "autocloseEnabled": "Autochiusura Abilitata", - "autocloseDisabled": "Autochiusura Disabilitata", - "autodelete": "Ticket Autocancellato", - "autodeleteEnabled": "Autocancellazione Abilitata", - "autodeleteDisabled": "Autocancellazione Disabilitata" + "autoclose":"Ticket Autochiuso", + "autocloseEnabled":"Autochiusura Abilitata", + "autocloseDisabled":"Autochiusura Disabilitata", + "autodelete":"Ticket Autocancellato", + "autodeleteEnabled":"Autocancellazione Abilitata", + "autodeleteDisabled":"Autocancellazione Disabilitata" }, - "descriptions": { - "create": "Il tuo ticket è stato creato. Clicca il pulsante qui sotto per accedervi!", - "close": "Il ticket è stato chiuso con successo!", - "delete": "Il ticket è stato eliminato con successo!", - "reopen": "Il ticket è stato riaperto con successo!", - "claim": "Il ticket è stato richiesto con successo!", - "unclaim": "Il ticket è stato annullato con successo!", - "pin": "Il ticket è stato fissato con successo!", - "unpin": "Il ticket è stato sbloccato con successo!", - "rename": "Il ticket è stato rinominato in {0} con successo!", - "move": "Il ticket è stato spostato in {0} con successo!", - "add": "{0} è stato aggiunto al ticket con successo!", - "remove": "{0} è stato rimosso dal ticket con successo!", + "descriptions":{ + "create":"Il tuo ticket è stato creato. Clicca il pulsante qui sotto per accedervi!", + "close":"Il ticket è stato chiuso con successo!", + "delete":"Il ticket è stato eliminato con successo!", + "reopen":"Il ticket è stato riaperto con successo!", + "claim":"Il ticket è stato richiesto con successo!", + "unclaim":"Il ticket è stato annullato con successo!", + "pin":"Il ticket è stato fissato con successo!", + "unpin":"Il ticket è stato sbloccato con successo!", + "rename":"Il ticket è stato rinominato in {0} con successo!", + "move":"Il ticket è stato spostato in {0} con successo!", + "add":"{0} è stato aggiunto al ticket con successo!", + "remove":"{0} è stato rimosso dal ticket con successo!", - "helpExplanation": "`` => parametro obbligatorio\n`[name]` => parametro facoltativo", - "statsReset": "Le statistiche del bot sono state ripristinate con successo!", - "statsError": "Impossibile visualizzare le statistiche del ticket!\n{0} non è un ticket!", - "blacklistAdd": "{0} è stato aggiunto alla blacklist con successo!", - "blacklistRemove": "{0} è stato rimosso con successo dalla blacklist!", - "blacklistGetSuccess": "{0} è attualmente nella blacklist!", - "blacklistGetEmpty": "{0} non è attualmente nella blacklist!", - "blacklistViewEmpty": "Nessuno è stato aggiunto alla blacklist finora!", - "blacklistViewTip": "Usa \"/blacklist add\" per aggiungere un utente alla blacklist!", - "clearVerify": "Sei sicuro di voler eliminare più ticket?\nQuesta azione non può essere annullata!", - "clearReady": "{0} tickets sono stati eliminati con successo!", - "rolesEmpty": "Nessun ruolo è stato aggiornato!", + "helpExplanation":"`` => parametro obbligatorio\n`[name]` => parametro facoltativo", + "statsReset":"Le statistiche del bot sono state ripristinate con successo!", + "statsError":"Impossibile visualizzare le statistiche del ticket!\n{0} non è un ticket!", + "blacklistAdd":"{0} è stato aggiunto alla blacklist con successo!", + "blacklistRemove":"{0} è stato rimosso con successo dalla blacklist!", + "blacklistGetSuccess":"{0} è attualmente nella blacklist!", + "blacklistGetEmpty":"{0} non è attualmente nella blacklist!", + "blacklistViewEmpty":"Nessuno è stato aggiunto alla blacklist finora!", + "blacklistViewTip":"Usa \"/blacklist add\" per aggiungere un utente alla blacklist!", + "clearVerify":"Sei sicuro di voler eliminare più ticket?\nQuesta azione non può essere annullata!", + "clearReady":"{0} tickets sono stati eliminati con successo!", + "rolesEmpty":"Nessun ruolo è stato aggiornato!", - "autocloseLeave": "Questo ticket è stato autochiuso perché il creatore ha lasciato il server!", - "autocloseTimeout": "Questo ticket è stato autochiuso perché è stato inattivo per più di `{0}h`!", - "autodeleteLeave": "Questo ticket è stato autocancellato perché il creatore ha lasciato il server!", - "autodeleteTimeout": "Questo ticket è stato autocancellato perché è stato inattivo per più di `{0} giorni`!", - "autocloseEnabled": "L'autochiusura è stata abilitata in questo ticket!\nSarà chiuso quando sarà inattivo per più di `{0}h`!", - "autocloseDisabled": "L'autochiusura è stata disabilitata in questo ticket!\nNon sarà più chiuso automaticamente!", - "autodeleteEnabled": "L'autocancellazione è stata abilitata in questo ticket!\nSarà cancellato quando sarà inattivo per più di `{0} giorni`!", - "autodeleteDisabled": "L'autocancellazione è stata disabilitata in questo ticket!\nNon sarà più cancellato automaticamente!", + "autocloseLeave":"Questo ticket è stato autochiuso perché il creatore ha lasciato il server!", + "autocloseTimeout":"Questo ticket è stato autochiuso perché è stato inattivo per più di `{0}h`!", + "autodeleteLeave":"Questo ticket è stato autocancellato perché il creatore ha lasciato il server!", + "autodeleteTimeout":"Questo ticket è stato autocancellato perché è stato inattivo per più di `{0} giorni`!", + "autocloseEnabled":"L'autochiusura è stata abilitata in questo ticket!\nSarà chiuso quando sarà inattivo per più di `{0}h`!", + "autocloseDisabled":"L'autochiusura è stata disabilitata in questo ticket!\nNon sarà più chiuso automaticamente!", + "autodeleteEnabled":"L'autocancellazione è stata abilitata in questo ticket!\nSarà cancellato quando sarà inattivo per più di `{0} giorni`!", + "autodeleteDisabled":"L'autocancellazione è stata disabilitata in questo ticket!\nNon sarà più cancellato automaticamente!", - "ticketMessageLimit": "Puoi creare solo {0} ticket contemporaneamente!", - "ticketMessageAutoclose": "Questo ticket sarà autochiuso quando sarà inattivo per {0}h!", - "ticketMessageAutodelete": "Questo ticket sarà autocancellato quando sarà inattivo per {0} giorni!", - "panelReady": "Puoi trovare il pannello qui sotto!\nQuesto messaggio può ora essere eliminato!" + "ticketMessageLimit":"Puoi creare solo {0} ticket contemporaneamente!", + "ticketMessageAutoclose":"Questo ticket sarà autochiuso quando sarà inattivo per {0}h!", + "ticketMessageAutodelete":"Questo ticket sarà autocancellato quando sarà inattivo per {0} giorni!", + "panelReady":"Puoi trovare il pannello qui sotto!\nQuesto messaggio può ora essere eliminato!" }, - "modal": { - "closePlaceholder": "Perché hai chiuso questo ticket?", - "deletePlaceholder": "Perché hai eliminato questo ticket?", - "reopenPlaceholder": "Perché hai riaperto questo ticket?", - "claimPlaceholder": "Perché hai richiesto questo ticket?", - "unclaimPlaceholder": "Perché hai annullato la richiesta di questo ticket?", - "pinPlaceholder": "Perché hai fissato questo ticket?", - "unpinPlaceholder": "Perché hai sbloccato questo ticket?" + "modal":{ + "closePlaceholder":"Perché hai chiuso questo ticket?", + "deletePlaceholder":"Perché hai eliminato questo ticket?", + "reopenPlaceholder":"Perché hai riaperto questo ticket?", + "claimPlaceholder":"Perché hai richiesto questo ticket?", + "unclaimPlaceholder":"Perché hai annullato la richiesta di questo ticket?", + "pinPlaceholder":"Perché hai fissato questo ticket?", + "unpinPlaceholder":"Perché hai sbloccato questo ticket?" }, - "logs": { - "createLog": "Un nuovo ticket è stato creato da {0}!", - "closeLog": "Questo ticket è stato chiuso da {0}!", - "closeDm": "Il tuo ticket è stato chiuso nel nostro server!", - "deleteLog": "Questo ticket è stato eliminato da {0}!", - "deleteDm": "Il tuo ticket è stato eliminato nel nostro server!", - "reopenLog": "Questo ticket è stato riaperto da {0}!", - "reopenDm": "Il tuo ticket è stato riaperto nel nostro server!", - "claimLog": "Questo ticket è stato richiesto da {0}!", - "claimDm": "Il tuo ticket è stato richiesto nel nostro server!", - "unclaimLog": "Questo ticket è stato annullato da {0}!", - "unclaimDm": "Il tuo ticket è stato annullato nel nostro server!", - "pinLog": "Questo ticket è stato fissato da {0}!", - "pinDm": "Il tuo ticket è stato fissato nel nostro server!", - "unpinLog": "Questo ticket è stato sbloccato da {0}!", - "unpinDm": "Il tuo ticket è stato sbloccato nel nostro server!", - "renameLog": "Questo ticket è stato rinominato in {0} da {1}!", - "renameDm": "Il tuo ticket è stato rinominato in {0} nel nostro server!", - "moveLog": "Questo ticket è stato spostato in {0} da {1}!", - "moveDm": "Il tuo ticket è stato spostato in {0} nel nostro server!", - "addLog": "{0} è stato aggiunto a questo ticket da {1}!", - "addDm": "{0} è stato aggiunto al tuo ticket nel nostro server!", - "removeLog": "{0} è stato rimosso da questo ticket da {1}!", - "removeDm": "{0} è stato rimosso dal tuo ticket nel nostro server!", + "logs":{ + "createLog":"Un nuovo ticket è stato creato da {0}!", + "closeLog":"Questo ticket è stato chiuso da {0}!", + "closeDm":"Il tuo ticket è stato chiuso nel nostro server!", + "deleteLog":"Questo ticket è stato eliminato da {0}!", + "deleteDm":"Il tuo ticket è stato eliminato nel nostro server!", + "reopenLog":"Questo ticket è stato riaperto da {0}!", + "reopenDm":"Il tuo ticket è stato riaperto nel nostro server!", + "claimLog":"Questo ticket è stato richiesto da {0}!", + "claimDm":"Il tuo ticket è stato richiesto nel nostro server!", + "unclaimLog":"Questo ticket è stato annullato da {0}!", + "unclaimDm":"Il tuo ticket è stato annullato nel nostro server!", + "pinLog":"Questo ticket è stato fissato da {0}!", + "pinDm":"Il tuo ticket è stato fissato nel nostro server!", + "unpinLog":"Questo ticket è stato sbloccato da {0}!", + "unpinDm":"Il tuo ticket è stato sbloccato nel nostro server!", + "renameLog":"Questo ticket è stato rinominato in {0} da {1}!", + "renameDm":"Il tuo ticket è stato rinominato in {0} nel nostro server!", + "moveLog":"Questo ticket è stato spostato in {0} da {1}!", + "moveDm":"Il tuo ticket è stato spostato in {0} nel nostro server!", + "addLog":"{0} è stato aggiunto a questo ticket da {1}!", + "addDm":"{0} è stato aggiunto al tuo ticket nel nostro server!", + "removeLog":"{0} è stato rimosso da questo ticket da {1}!", + "removeDm":"{0} è stato rimosso dal tuo ticket nel nostro server!", - "blacklistAddLog": "{0} è stato aggiunto alla blacklist da {1}!", - "blacklistRemoveLog": "{0} è stato rimosso dalla blacklist da {1}!", - "blacklistAddDm": "Sei stato aggiunto alla blacklist nel nostro server!\nD'ora in poi, non puoi creare ticket!", - "blacklistRemoveDm": "Sei stato rimosso dalla blacklist nel nostro server!\nOra puoi creare ticket di nuovo!", - "clearLog": "{0} tickets sono stati eliminati da {1}!" + "blacklistAddLog":"{0} è stato aggiunto alla blacklist da {1}!", + "blacklistRemoveLog":"{0} è stato rimosso dalla blacklist da {1}!", + "blacklistAddDm":"Sei stato aggiunto alla blacklist nel nostro server!\nD'ora in poi, non puoi creare ticket!", + "blacklistRemoveDm":"Sei stato rimosso dalla blacklist nel nostro server!\nOra puoi creare ticket di nuovo!", + "clearLog":"{0} tickets sono stati eliminati da {1}!" } }, - "transcripts": { - "success": { - "visit": "Visita Trascrizione", - "ready": "Trascrizione Creata", - "textFileDescription": "Questa è la trascrizione testuale di un ticket eliminato!", - "htmlProgress": "Attendere mentre questa trascrizione html viene elaborata...", - "createdChannel": "Una nuova trascrizione di {0} è stata creata nel server!", - "createdCreator": "Una nuova trascrizione di {0} è stata creata per uno dei tuoi ticket!", - "createdParticipant": "Una nuova trascrizione di {0} è stata creata in uno dei ticket a cui hai partecipato!", - "createdActiveAdmin": "Una nuova trascrizione di {0} è stata creata in uno dei ticket in cui hai partecipato come admin!", - "createdEveryAdmin": "Una nuova trascrizione di {0} è stata creata in uno dei ticket in cui eri admin!", - "createdOther": "Una nuova trascrizione di {0} è stata creata!" + "transcripts":{ + "success":{ + "visit":"Visita Trascrizione", + "ready":"Trascrizione Creata", + "textFileDescription":"Questa è la trascrizione testuale di un ticket eliminato!", + "htmlProgress":"Attendere mentre questa trascrizione html viene elaborata...", + "createdChannel":"Una nuova trascrizione di {0} è stata creata nel server!", + "createdCreator":"Una nuova trascrizione di {0} è stata creata per uno dei tuoi ticket!", + "createdParticipant":"Una nuova trascrizione di {0} è stata creata in uno dei ticket a cui hai partecipato!", + "createdActiveAdmin":"Una nuova trascrizione di {0} è stata creata in uno dei ticket in cui hai partecipato come admin!", + "createdEveryAdmin":"Una nuova trascrizione di {0} è stata creata in uno dei ticket in cui eri admin!", + "createdOther":"Una nuova trascrizione di {0} è stata creata!" }, - "errors": { - "retry": "Riprova", - "continue": "Elimina Senza Trascrizione", - "backup": "Crea Trascrizione di Backup", - "error": "Qualcosa è andato storto durante la creazione della trascrizione.\nCosa vuoi fare?\n\nQuesto ticket non sarà eliminato finché non clicchi su uno di questi pulsanti." + "errors":{ + "retry":"Riprova", + "continue":"Elimina Senza Trascrizione", + "backup":"Crea Trascrizione di Backup", + "error":"Qualcosa è andato storto durante la creazione della trascrizione.\nCosa vuoi fare?\n\nQuesto ticket non sarà eliminato finché non clicchi su uno di questi pulsanti." } }, - "errors": { - "titles": { - "internalError": "Errore Interno", - "optionMissing": "Opzione Comando Mancante", - "optionInvalid": "Opzione Comando Non Valida", - "unknownCommand": "Comando Sconosciuto", - "noPermissions": "Nessuna Autorizzazione", - "unknownTicket": "Ticket Sconosciuto", - "deprecatedTicket": "Ticket Obsoleto", - "unknownOption": "Opzione Sconosciuta", - "unknownPanel": "Pannello Sconosciuto", - "notInGuild": "Non nel Server", - "channelRename": "Impossibile Rinominare il Canale", - "busy": "Ticket Occupato" + "errors":{ + "titles":{ + "internalError":"Errore Interno", + "optionMissing":"Opzione Comando Mancante", + "optionInvalid":"Opzione Comando Non Valida", + "unknownCommand":"Comando Sconosciuto", + "noPermissions":"Nessuna Autorizzazione", + "unknownTicket":"Ticket Sconosciuto", + "deprecatedTicket":"Ticket Obsoleto", + "unknownOption":"Opzione Sconosciuta", + "unknownPanel":"Pannello Sconosciuto", + "notInGuild":"Non nel Server", + "channelRename":"Impossibile Rinominare il Canale", + "busy":"Ticket Occupato" }, - "descriptions": { - "askForInfo": "Contatta il proprietario di questo bot per ulteriori informazioni!", - "askForInfoResolve": "Contatta il proprietario di questo bot se il problema non si risolve dopo alcuni tentativi.", - "internalError": "Impossibile rispondere a questo {0} a causa di un errore interno!", - "optionMissing": "Un parametro obbligatorio è mancante in questo comando!", - "optionInvalid": "Un parametro in questo comando non è valido!", - "optionInvalidChoose": "Scegli tra", - "unknownCommand": "Prova a visitare il menu di aiuto per ulteriori informazioni!", - "noPermissions": "Non hai il permesso di utilizzare questo {0}!", - "noPermissionsList": "Permessi Richiesti: (uno di essi)", - "noPermissionsCooldown": "Non hai il permesso di utilizzare questo {0} perché hai un cooldown!", - "noPermissionsBlacklist": "Non hai il permesso di utilizzare questo {0} perché sei stato blacklistato!", - "noPermissionsLimitGlobal": "Non puoi creare un ticket perché il server ha raggiunto il limite massimo di ticket!", - "noPermissionsLimitGlobalUser": "Non puoi creare un ticket perché hai raggiunto il limite massimo di ticket!", - "noPermissionsLimitOption": "Non puoi creare un ticket perché il server ha raggiunto il limite massimo di ticket per questa opzione!", - "noPermissionsLimitOptionUser": "Non puoi creare un ticket perché hai raggiunto il limite massimo di ticket per questa opzione!", - "unknownTicket": "Prova questo comando di nuovo in un ticket valido!", - "deprecatedTicket": "Il canale attuale non è un ticket valido! Potrebbe essere un ticket di una vecchia versione di Open Ticket!", - "notInGuild": "Questo {0} non funziona in DM! Riprova in un server!", - "channelRename": "A causa dei limiti di Discord, al momento non è possibile rinominare il canale. Il canale verrà automaticamente rinominato in oltre 10 minuti se il bot non viene riavviato.", - "channelRenameSource": "La fonte di questo errore è: {0}", - "busy": "Impossibile utilizzare questo {0}!\nIl ticket è attualmente in fase di elaborazione dal bot.\n\nPer favore riprova tra pochi secondi!" + "descriptions":{ + "askForInfo":"Contatta il proprietario di questo bot per ulteriori informazioni!", + "askForInfoResolve":"Contatta il proprietario di questo bot se il problema non si risolve dopo alcuni tentativi.", + "internalError":"Impossibile rispondere a questo {0} a causa di un errore interno!", + "optionMissing":"Un parametro obbligatorio è mancante in questo comando!", + "optionInvalid":"Un parametro in questo comando non è valido!", + "optionInvalidChoose":"Scegli tra", + "unknownCommand":"Prova a visitare il menu di aiuto per ulteriori informazioni!", + "noPermissions":"Non hai il permesso di utilizzare questo {0}!", + "noPermissionsList":"Permessi Richiesti: (uno di essi)", + "noPermissionsCooldown":"Non hai il permesso di utilizzare questo {0} perché hai un cooldown!", + "noPermissionsBlacklist":"Non hai il permesso di utilizzare questo {0} perché sei stato blacklistato!", + "noPermissionsLimitGlobal":"Non puoi creare un ticket perché il server ha raggiunto il limite massimo di ticket!", + "noPermissionsLimitGlobalUser":"Non puoi creare un ticket perché hai raggiunto il limite massimo di ticket!", + "noPermissionsLimitOption":"Non puoi creare un ticket perché il server ha raggiunto il limite massimo di ticket per questa opzione!", + "noPermissionsLimitOptionUser":"Non puoi creare un ticket perché hai raggiunto il limite massimo di ticket per questa opzione!", + "unknownTicket":"Prova questo comando di nuovo in un ticket valido!", + "deprecatedTicket":"Il canale attuale non è un ticket valido! Potrebbe essere un ticket di una vecchia versione di Open Ticket!", + "notInGuild":"Questo {0} non funziona in DM! Riprova in un server!", + "channelRename":"A causa dei limiti di Discord, al momento non è possibile rinominare il canale. Il canale verrà automaticamente rinominato in oltre 10 minuti se il bot non viene riavviato.", + "channelRenameSource":"La fonte di questo errore è: {0}", + "busy":"Impossibile utilizzare questo {0}!\nIl ticket è attualmente in fase di elaborazione dal bot.\n\nPer favore riprova tra pochi secondi!" }, - "optionInvalidReasons": { - "stringRegex": "Il valore non corrisponde al modello!", - "stringMinLength": "Il valore deve essere di almeno {0} caratteri!", - "stringMaxLength": "Il valore deve essere di al massimo {0} caratteri!", - "numberInvalid": "Numero non valido!", - "numberMin": "Il numero deve essere almeno {0}!", - "numberMax": "Il numero deve essere al massimo {0}!", - "numberDecimal": "Il numero non è consentito come decimale!", - "numberNegative": "Il numero non è consentito come negativo!", - "numberPositive": "Il numero non è consentito come positivo!", - "numberZero": "Il numero non è consentito come zero!", - "channelNotFound": "Impossibile trovare il canale!", - "userNotFound": "Impossibile trovare l'utente!", - "roleNotFound": "Impossibile trovare il ruolo!", - "memberNotFound": "Impossibile trovare l'utente!", - "mentionableNotFound": "Impossibile trovare l'utente o il ruolo!", - "channelType": "Tipo di canale non valido!", - "notInGuild": "Questa opzione richiede che tu sia in un server!" + "optionInvalidReasons":{ + "stringRegex":"Il valore non corrisponde al modello!", + "stringMinLength":"Il valore deve essere di almeno {0} caratteri!", + "stringMaxLength":"Il valore deve essere di al massimo {0} caratteri!", + "numberInvalid":"Numero non valido!", + "numberMin":"Il numero deve essere almeno {0}!", + "numberMax":"Il numero deve essere al massimo {0}!", + "numberDecimal":"Il numero non è consentito come decimale!", + "numberNegative":"Il numero non è consentito come negativo!", + "numberPositive":"Il numero non è consentito come positivo!", + "numberZero":"Il numero non è consentito come zero!", + "channelNotFound":"Impossibile trovare il canale!", + "userNotFound":"Impossibile trovare l'utente!", + "roleNotFound":"Impossibile trovare il ruolo!", + "memberNotFound":"Impossibile trovare l'utente!", + "mentionableNotFound":"Impossibile trovare l'utente o il ruolo!", + "channelType":"Tipo di canale non valido!", + "notInGuild":"Questa opzione richiede che tu sia in un server!" }, - "permissions": { - "developer": "Devi essere lo sviluppatore del bot.", - "owner": "Devi essere il proprietario del server.", - "admin": "Devi essere un admin del server.", - "moderator": "Devi essere un moderatore.", - "support": "Devi essere nel team di supporto.", - "member": "Devi essere un membro.", - "discord-administrator": "Devi avere il permesso `ADMINISTRATOR`." + "permissions":{ + "developer":"Devi essere lo sviluppatore del bot.", + "owner":"Devi essere il proprietario del server.", + "admin":"Devi essere un admin del server.", + "moderator":"Devi essere un moderatore.", + "support":"Devi essere nel team di supporto.", + "member":"Devi essere un membro.", + "discord-administrator":"Devi avere il permesso `ADMINISTRATOR`." }, - "actionInvalid": { - "close": "Il ticket è già chiuso!", - "reopen": "Il ticket non è ancora chiuso!", - "claim": "Il ticket è già stato rivendicato!", - "unclaim": "Il ticket non è ancora stato rivendicato!", - "pin": "Il ticket è già stato fissato!", - "unpin": "Il ticket non è ancora stato sbloccato!", - "add": "Questo utente può già accedere al ticket!", - "remove": "Impossibile rimuovere questo utente dal ticket!" + "actionInvalid":{ + "close":"Il ticket è già chiuso!", + "reopen":"Il ticket non è ancora chiuso!", + "claim":"Il ticket è già stato rivendicato!", + "unclaim":"Il ticket non è ancora stato rivendicato!", + "pin":"Il ticket è già stato fissato!", + "unpin":"Il ticket non è ancora stato sbloccato!", + "add":"Questo utente può già accedere al ticket!", + "remove":"Impossibile rimuovere questo utente dal ticket!" } }, - "params": { - "uppercase": { - "ticket": "Ticket", - "tickets": "Tickets", - "reason": "Motivo", - "creator": "Creatore", - "remaining": "Tempo Rimanente", - "added": "Aggiunto", - "removed": "Rimosso", - "filter": "Filtro", - "claimedBy": "Rivendicato Da {0}", - "method": "Metodo", - "type": "Tipo", - "blacklisted": "Blacklistato", - "panel": "Pannello", - "command": "Comando", - "system": "Sistema", - "true": "Vero", - "false": "Falso", - "syntax": "Sintassi", - "originalName": "Nome Originale", - "newName": "Nuovo Nome", - "until": "Fino a", - "validOptions": "Opzioni Valide", - "validPanels": "Pannelli Validi", - "autoclose": "Chiusura Automatica", - "autodelete": "Cancellazione Automatica", - "startupDate": "Data di Avvio", - "version": "Versione", - "name": "Nome", - "role": "Ruolo", - "status": "Stato", - "claimed": "Rivendicato", - "pinned": "Fissato", - "creationDate": "Data di Creazione" + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickets", + "reason":"Motivo", + "creator":"Creatore", + "remaining":"Tempo Rimanente", + "added":"Aggiunto", + "removed":"Rimosso", + "filter":"Filtro", + "claimedBy":"Rivendicato Da {0}", + "method":"Metodo", + "type":"Tipo", + "blacklisted":"Blacklistato", + "panel":"Pannello", + "command":"Comando", + "system":"Sistema", + "true":"Vero", + "false":"Falso", + "syntax":"Sintassi", + "originalName":"Nome Originale", + "newName":"Nuovo Nome", + "until":"Fino a", + "validOptions":"Opzioni Valide", + "validPanels":"Pannelli Validi", + "autoclose":"Chiusura Automatica", + "autodelete":"Cancellazione Automatica", + "startupDate":"Data di Avvio", + "version":"Versione", + "name":"Nome", + "role":"Ruolo", + "status":"Stato", + "claimed":"Rivendicato", + "pinned":"Fissato", + "creationDate":"Data di Creazione" }, - "lowercase": { - "text": "testo", - "html": "html", - "command": "comando", - "modal": "modale", - "button": "pulsante", - "dropdown": "dropdown", - "method": "metodo" + "lowercase":{ + "text":"testo", + "html":"html", + "command":"comando", + "modal":"modale", + "button":"pulsante", + "dropdown":"dropdown", + "method":"metodo" } }, - "commands": { - "reason": "Specifica un motivo facoltativo che sarà visibile nei log.", - "help": "Ottieni un elenco di tutti i comandi disponibili.", - "panel": "Genera un messaggio con un dropdown o pulsanti (per la creazione del ticket).", - "panelId": "L'identificatore del pannello che vuoi generare.", - "panelAutoUpdate": "Vuoi che questo pannello si aggiorni automaticamente quando viene modificato?", - "ticket": "Crea istantaneamente un ticket.", - "ticketId": "L'identificatore del ticket che vuoi creare.", - "close": "Chiudi un ticket.", - "delete": "Elimina un ticket.", - "deleteNoTranscript": "Elimina questo ticket senza creare una trascrizione.", - "reopen": "Riapri un ticket.", - "claim": "Rivendica un ticket.", - "claimUser": "Rivendica questo ticket a qualcun altro invece di te stesso.", - "unclaim": "Rimuovi la rivendicazione di un ticket.", - "pin": "Fissa un ticket.", - "unpin": "Sblocca un ticket.", - "move": "Sposta un ticket.", - "moveId": "L'identificatore dell'opzione a cui vuoi spostare.", - "rename": "Rinomina un ticket.", - "renameName": "Il nuovo nome per questo ticket.", - "add": "Aggiungi un utente a un ticket.", - "addUser": "L'utente da aggiungere.", - "remove": "Rimuovi un utente da un ticket.", - "removeUser": "L'utente da rimuovere.", - "blacklist": "Gestisci la blacklist del ticket.", - "blacklistView": "Visualizza un elenco della blacklist attuale.", - "blacklistAdd": "Aggiungi un utente alla blacklist.", - "blacklistRemove": "Rimuovi un utente dalla blacklist.", - "blacklistGet": "Ottieni i dettagli di un utente blacklistato.", - "blacklistGetUser": "L'utente di cui ottenere i dettagli.", - "stats": "Visualizza le statistiche del bot, di un membro o di un ticket.", - "statsReset": "Reimposta tutte le statistiche del bot (e inizia a contare da zero).", - "statsGlobal": "Visualizza le statistiche globali.", - "statsUser": "Visualizza le statistiche di un utente nel server.", - "statsUserUser": "L'utente di cui visualizzare le statistiche.", - "statsTicket": "Visualizza le statistiche di un ticket nel server.", - "statsTicketTicket": "Il ticket da visualizzare.", - "clear": "Elimina più ticket contemporaneamente.", - "clearFilter": "Il filtro per eliminare ticket.", - "clearFilters": { - "all": "Tutti", - "open": "Aperti", - "close": "Chiusi", - "claim": "Rivendicati", - "unclaim": "Non Rivendicati", - "pin": "Fissati", - "unpin": "Non Fissati", - "autoclose": "Chiusura Automatica" + "commands":{ + "reason":"Specifica un motivo facoltativo che sarà visibile nei log.", + "help":"Ottieni un elenco di tutti i comandi disponibili.", + "panel":"Genera un messaggio con un dropdown o pulsanti (per la creazione del ticket).", + "panelId":"L'identificatore del pannello che vuoi generare.", + "panelAutoUpdate":"Vuoi che questo pannello si aggiorni automaticamente quando viene modificato?", + "ticket":"Crea istantaneamente un ticket.", + "ticketId":"L'identificatore del ticket che vuoi creare.", + "close":"Chiudi un ticket.", + "delete":"Elimina un ticket.", + "deleteNoTranscript":"Elimina questo ticket senza creare una trascrizione.", + "reopen":"Riapri un ticket.", + "claim":"Rivendica un ticket.", + "claimUser":"Rivendica questo ticket a qualcun altro invece di te stesso.", + "unclaim":"Rimuovi la rivendicazione di un ticket.", + "pin":"Fissa un ticket.", + "unpin":"Sblocca un ticket.", + "move":"Sposta un ticket.", + "moveId":"L'identificatore dell'opzione a cui vuoi spostare.", + "rename":"Rinomina un ticket.", + "renameName":"Il nuovo nome per questo ticket.", + "add":"Aggiungi un utente a un ticket.", + "addUser":"L'utente da aggiungere.", + "remove":"Rimuovi un utente da un ticket.", + "removeUser":"L'utente da rimuovere.", + "blacklist":"Gestisci la blacklist del ticket.", + "blacklistView":"Visualizza un elenco della blacklist attuale.", + "blacklistAdd":"Aggiungi un utente alla blacklist.", + "blacklistRemove":"Rimuovi un utente dalla blacklist.", + "blacklistGet":"Ottieni i dettagli di un utente blacklistato.", + "blacklistGetUser":"L'utente di cui ottenere i dettagli.", + "stats":"Visualizza le statistiche del bot, di un membro o di un ticket.", + "statsReset":"Reimposta tutte le statistiche del bot (e inizia a contare da zero).", + "statsGlobal":"Visualizza le statistiche globali.", + "statsUser":"Visualizza le statistiche di un utente nel server.", + "statsUserUser":"L'utente di cui visualizzare le statistiche.", + "statsTicket":"Visualizza le statistiche di un ticket nel server.", + "statsTicketTicket":"Il ticket da visualizzare.", + "clear":"Elimina più ticket contemporaneamente.", + "clearFilter":"Il filtro per eliminare ticket.", + "clearFilters":{ + "all":"Tutti", + "open":"Aperti", + "close":"Chiusi", + "claim":"Rivendicati", + "unclaim":"Non Rivendicati", + "pin":"Fissati", + "unpin":"Non Fissati", + "autoclose":"Chiusura Automatica" }, - "autoclose": "Gestisci la chiusura automatica in un ticket.", - "autocloseDisable": "Disabilita la chiusura automatica in questo ticket.", - "autocloseEnable": "Abilita la chiusura automatica in questo ticket.", - "autocloseEnableTime": "Il numero di ore in cui questo ticket deve essere inattivo per chiuderlo.", - "autodelete": "Gestisci la cancellazione automatica in un ticket.", - "autodeleteDisable": "Disabilita la cancellazione automatica in questo ticket.", - "autodeleteEnable": "Abilita la cancellazione automatica in questo ticket.", - "autodeleteEnableTime": "Il numero di giorni in cui questo ticket deve essere inattivo per eliminarlo." + "autoclose":"Gestisci la chiusura automatica in un ticket.", + "autocloseDisable":"Disabilita la chiusura automatica in questo ticket.", + "autocloseEnable":"Abilita la chiusura automatica in questo ticket.", + "autocloseEnableTime":"Il numero di ore in cui questo ticket deve essere inattivo per chiuderlo.", + "autodelete":"Gestisci la cancellazione automatica in un ticket.", + "autodeleteDisable":"Disabilita la cancellazione automatica in questo ticket.", + "autodeleteEnable":"Abilita la cancellazione automatica in questo ticket.", + "autodeleteEnableTime":"Il numero di giorni in cui questo ticket deve essere inattivo per eliminarlo." }, - "helpMenu": { - "help": "Ottieni un elenco di tutti i comandi disponibili.", - "ticket": "Crea istantaneamente un ticket.", - "close": "Chiudi un ticket, disabilita la scrittura in questo canale.", - "delete": "Elimina un ticket, crea una trascrizione quando abilitato.", - "reopen": "Riapri un ticket, abilita nuovamente la scrittura in questo canale.", - "pin": "Fissa un ticket. Questo lo sposterà in cima e aggiungerà un'emoji '📌' al nome.", - "unpin": "Sblocca un ticket. Il ticket rimarrà nella sua posizione ma perderà l'emoji '📌'.", - "move": "Sposta un ticket. Questo cambierà il tipo di questo ticket.", - "rename": "Rinomina un ticket. Questo cambierà il nome del canale di questo ticket.", - "claim": "Rivendica un ticket. In questo modo, il tuo team saprà che stai gestendo questo ticket.", - "unclaim": "Rimuovi la rivendicazione di un ticket. In questo modo, il tuo team saprà che questo ticket è di nuovo libero.", - "add": "Aggiungi un utente a un ticket. Questo permetterà all'utente di leggere e scrivere in questo ticket.", - "remove": "Rimuovi un utente da un ticket. Questo rimuoverà la possibilità di leggere e scrivere per un utente in questo ticket.", - "panel": "Genera un messaggio con un dropdown o pulsanti (per la creazione del ticket).", - "blacklistView": "Visualizza un elenco della blacklist attuale.", - "blacklistAdd": "Aggiungi un utente alla blacklist.", - "blacklistRemove": "Rimuovi un utente dalla blacklist.", - "blacklistGet": "Ottieni i dettagli di un utente blacklistato.", - "statsGlobal": "Visualizza le statistiche globali.", - "statsTicket": "Visualizza le statistiche di un ticket nel server.", - "statsUser": "Visualizza le statistiche di un utente nel server.", - "statsReset": "Reimposta tutte le statistiche del bot (e inizia a contare da zero).", - "autocloseDisable": "Disabilita la chiusura automatica in questo ticket.", - "autocloseEnable": "Abilita la chiusura automatica in questo ticket.", - "autodeleteDisable": "Disabilita la cancellazione automatica in questo ticket.", - "autodeleteEnable": "Abilita la cancellazione automatica in questo ticket." + "helpMenu":{ + "help":"Ottieni un elenco di tutti i comandi disponibili.", + "ticket":"Crea istantaneamente un ticket.", + "close":"Chiudi un ticket, disabilita la scrittura in questo canale.", + "delete":"Elimina un ticket, crea una trascrizione quando abilitato.", + "reopen":"Riapri un ticket, abilita nuovamente la scrittura in questo canale.", + "pin":"Fissa un ticket. Questo lo sposterà in cima e aggiungerà un'emoji '📌' al nome.", + "unpin":"Sblocca un ticket. Il ticket rimarrà nella sua posizione ma perderà l'emoji '📌'.", + "move":"Sposta un ticket. Questo cambierà il tipo di questo ticket.", + "rename":"Rinomina un ticket. Questo cambierà il nome del canale di questo ticket.", + "claim":"Rivendica un ticket. In questo modo, il tuo team saprà che stai gestendo questo ticket.", + "unclaim":"Rimuovi la rivendicazione di un ticket. In questo modo, il tuo team saprà che questo ticket è di nuovo libero.", + "add":"Aggiungi un utente a un ticket. Questo permetterà all'utente di leggere e scrivere in questo ticket.", + "remove":"Rimuovi un utente da un ticket. Questo rimuoverà la possibilità di leggere e scrivere per un utente in questo ticket.", + "panel":"Genera un messaggio con un dropdown o pulsanti (per la creazione del ticket).", + "blacklistView":"Visualizza un elenco della blacklist attuale.", + "blacklistAdd":"Aggiungi un utente alla blacklist.", + "blacklistRemove":"Rimuovi un utente dalla blacklist.", + "blacklistGet":"Ottieni i dettagli di un utente blacklistato.", + "statsGlobal":"Visualizza le statistiche globali.", + "statsTicket":"Visualizza le statistiche di un ticket nel server.", + "statsUser":"Visualizza le statistiche di un utente nel server.", + "statsReset":"Reimposta tutte le statistiche del bot (e inizia a contare da zero).", + "autocloseDisable":"Disabilita la chiusura automatica in questo ticket.", + "autocloseEnable":"Abilita la chiusura automatica in questo ticket.", + "autodeleteDisable":"Disabilita la cancellazione automatica in questo ticket.", + "autodeleteEnable":"Abilita la cancellazione automatica in questo ticket." }, - "stats": { - "scopes": { - "global": "Statistiche Globali", - "system": "Statistiche di Sistema", - "user": "Statistiche Utente", - "ticket": "Statistiche Ticket", - "participants": "Partecipanti" + "stats":{ + "scopes":{ + "global":"Statistiche Globali", + "system":"Statistiche di Sistema", + "user":"Statistiche Utente", + "ticket":"Statistiche Ticket", + "participants":"Partecipanti" }, - "properties": { - "ticketsCreated": "Ticket Creati", - "ticketsClosed": "Ticket Chiusi", - "ticketsDeleted": "Ticket Eliminati", - "ticketsReopened": "Ticket Riaperti", - "ticketsAutoclosed": "Ticket Chiusi Automaticamente", - "ticketsClaimed": "Ticket Rivendicati", - "ticketsPinned": "Ticket Fissati", - "ticketsMoved": "Ticket Spostati", - "usersBlacklisted": "Utenti Blacklistati", - "transcriptsCreated": "Trascrizioni Create" + "properties":{ + "ticketsCreated":"Ticket Creati", + "ticketsClosed":"Ticket Chiusi", + "ticketsDeleted":"Ticket Eliminati", + "ticketsReopened":"Ticket Riaperti", + "ticketsAutoclosed":"Ticket Chiusi Automaticamente", + "ticketsClaimed":"Ticket Rivendicati", + "ticketsPinned":"Ticket Fissati", + "ticketsMoved":"Ticket Spostati", + "usersBlacklisted":"Utenti Blacklistati", + "transcriptsCreated":"Trascrizioni Create" } } } From 7c76be84730fce16051b163c9731ef90c3b437a3 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 3 Oct 2024 20:16:42 +0200 Subject: [PATCH 037/157] Fixed suffix register error on config reload --- README.md | 2 -- src/data/openticket/optionLoader.ts | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d8cf541..19c0c02 100644 --- a/README.md +++ b/README.md @@ -137,8 +137,6 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇸🇪 Swedish |iamnotmega |🟠 Temporary Outdated (beta) | |🇻🇳 Vietnamese |iamnotmega |🟠 Temporary Outdated (beta) | - - ## ⭐️ Star History Please help us grow by giving a star! It would help us a lot! diff --git a/src/data/openticket/optionLoader.ts b/src/data/openticket/optionLoader.ts index 51ee538..83de4cc 100644 --- a/src/data/openticket/optionLoader.ts +++ b/src/data/openticket/optionLoader.ts @@ -18,8 +18,9 @@ export const loadAllOptions = async () => { //update options on config reload optionConfig.onReload(async () => { - //clear previous options + //clear previous options & suffixes openticket.options.forEach((data,id) => {openticket.options.remove(id)}) + openticket.options.suffix.forEach((data,id) => {openticket.options.suffix.remove(id)}) //add new options optionConfig.data.forEach((option) => { From 56e1fb39396b828b848cc0ed34dccc621560c3aa Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 3 Oct 2024 20:46:01 +0200 Subject: [PATCH 038/157] Fixed loopAll() async errors --- src/builders/embeds.ts | 2 +- src/core/api/modules/base.ts | 2 +- src/core/api/modules/checker.ts | 2 +- src/core/api/modules/client.ts | 4 ++-- src/core/api/modules/cooldown.ts | 4 ++-- src/core/api/modules/flag.ts | 2 +- src/core/startup/manageMigration.ts | 8 ++++---- src/data/framework/codeLoader.ts | 4 ++-- src/data/framework/cooldownLoader.ts | 2 +- src/data/framework/permissionLoader.ts | 2 +- src/data/openticket/optionLoader.ts | 8 ++++---- src/data/openticket/panelLoader.ts | 2 +- src/data/openticket/questionLoader.ts | 4 ++-- src/data/openticket/roleLoader.ts | 2 +- 14 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts index 5dc1fc8..0ce400d 100644 --- a/src/builders/embeds.ts +++ b/src/builders/embeds.ts @@ -882,7 +882,7 @@ const blacklistEmbeds = () => { const {user} = params const renderedUsers: string[] = [] - openticket.blacklist.forEach((blacklist,id) => {renderedUsers.push(discord.userMention(id.value)+" - "+(blacklist.reason ? blacklist.reason : "/"))}) + openticket.blacklist.loopAll((blacklist,id) => {renderedUsers.push(discord.userMention(id.value)+" - "+(blacklist.reason ? blacklist.reason : "/"))}) instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setColor(generalConfig.data.mainColor) diff --git a/src/core/api/modules/base.ts b/src/core/api/modules/base.ts index 1c0b372..ed76818 100644 --- a/src/core/api/modules/base.ts +++ b/src/core/api/modules/base.ts @@ -371,7 +371,7 @@ export class ODManager extends ODManagerChangeHe return this.#data.map((d) => d.id) } /**Run an iterator over all data in this manager. This method also supports async-await behaviour!*/ - async forEach(cb:(data:DataType,id:ODId) => ODPromiseVoid): Promise { + async loopAll(cb:(data:DataType,id:ODId) => ODPromiseVoid): Promise { for (const data of this.getAll()){ await cb(data,data.id) } diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 4d7f152..795f7a7 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -65,7 +65,7 @@ export class ODCheckerManager extends ODManager { if (!res.valid) isValid = false }) - this.functions.forEach((func) => { + this.functions.loopAll((func) => { const res = func.func(this,this.functions) final.push(...res.messages) diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index 6c6eef0..b178514 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -496,7 +496,7 @@ export class ODSlashCommandManager extends ODManager { const existing: {cmd:ODSlashCommand, requiresUpdate:boolean}[] = [] const nonExisting: ODSlashCommand[] = [] - this.forEach((cmd) => { + this.loopAll((cmd) => { if (guildId && cmd.guildId != guildId) return const result = cmds.find((cmddata) => cmddata.name == cmd.name) if (result){ @@ -977,7 +977,7 @@ export class ODTextCommandManager extends ODManager { //filter commands for correct prefix const validPrefixCommands: {cmd:ODTextCommand,newContent:string}[] = [] - this.forEach((cmd) => { + this.loopAll((cmd) => { if (msg.content.startsWith(cmd.builder.prefix)) validPrefixCommands.push({ cmd:cmd, newContent:msg.content.substring(cmd.builder.prefix.length) diff --git a/src/core/api/modules/cooldown.ts b/src/core/api/modules/cooldown.ts index ab3db43..e74f568 100644 --- a/src/core/api/modules/cooldown.ts +++ b/src/core/api/modules/cooldown.ts @@ -139,7 +139,7 @@ export class ODCounterCooldown extends ODCooldown<{value:number}> { async init(){ if (this.ready) return setInterval(() => { - this.data.forEach((cooldown) => { + this.data.loopAll((cooldown) => { cooldown.data.value = cooldown.data.value - this.decrement if (cooldown.data.value <= this.cancelLimit){ cooldown.active = false @@ -217,7 +217,7 @@ export class ODIncrementalCounterCooldown extends ODCooldown<{value:number}> { async init(){ if (this.ready) return setInterval(() => { - this.data.forEach((cooldown) => { + this.data.loopAll((cooldown) => { cooldown.data.value = cooldown.data.value - this.decrement if (cooldown.data.value <= this.cancelLimit){ cooldown.active = false diff --git a/src/core/api/modules/flag.ts b/src/core/api/modules/flag.ts index d63c471..67f9e25 100644 --- a/src/core/api/modules/flag.ts +++ b/src/core/api/modules/flag.ts @@ -66,7 +66,7 @@ export class ODFlagManager extends ODManager { /**Set all flags to their `process.argv` value. */ init(){ - this.forEach((flag) => { + this.loopAll((flag) => { flag.detectProcessParams(false) }) } diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index 6373460..2dcdc06 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -42,9 +42,9 @@ const preloadMigrationContext = async () => { const unloadMigrationContext = async () => { openticket.debug.visible = false - openticket.databases.forEach((database,id) => {openticket.databases.remove(id)}) - openticket.configs.forEach((config,id) => {openticket.configs.remove(id)}) - openticket.flags.forEach((flag,id) => {openticket.flags.remove(id)}) + openticket.databases.loopAll((database,id) => {openticket.databases.remove(id)}) + openticket.configs.loopAll((config,id) => {openticket.configs.remove(id)}) + openticket.flags.loopAll((flag,id) => {openticket.flags.remove(id)}) openticket.debug.debug("-- MIGRATION CONTEXT END --") } @@ -78,7 +78,7 @@ const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { const saveAllVersionsToDatabase = async () => { const globalDatabase = openticket.databases.get("openticket:global") - openticket.versions.forEach((version,id) => { + openticket.versions.loopAll((version,id) => { globalDatabase.set("openticket:last-version",id.value,version.toString()) }) } \ No newline at end of file diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index c711d45..c7967ae 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -135,7 +135,7 @@ export const loadDatabaseCleanersCode = async () => { //OPTION DATABASE CLEANER openticket.code.add(new api.ODCode("openticket:option-database-cleaner",10,() => { //delete all unused options - openticket.options.forEach((option,id) => { + openticket.options.loopAll((option,id) => { if (optionDatabase.exists("openticket:used-option",id.value) && !openticket.tickets.getAll().some((ticket) => ticket.id.value == id.value)){ optionDatabase.delete("openticket:used-option",id.value) } @@ -331,7 +331,7 @@ export const loadDatabaseSaversCode = async () => { } //delete all unused options on ticket move - openticket.options.forEach((option,id) => { + openticket.options.loopAll((option,id) => { if (optionDatabase.exists("openticket:used-option",id.value) && !openticket.tickets.getAll().some((ticket) => ticket.id.value == id.value)){ optionDatabase.delete("openticket:used-option",id.value) } diff --git a/src/data/framework/cooldownLoader.ts b/src/data/framework/cooldownLoader.ts index bc9fde7..f63efa2 100644 --- a/src/data/framework/cooldownLoader.ts +++ b/src/data/framework/cooldownLoader.ts @@ -1,7 +1,7 @@ import {openticket, api, utilities} from "../../index" export const loadAllCooldowns = async () => { - openticket.options.forEach((option) => { + openticket.options.loopAll((option) => { if (!(option instanceof api.ODTicketOption)) return loadTicketOptionCooldown(option) }) diff --git a/src/data/framework/permissionLoader.ts b/src/data/framework/permissionLoader.ts index 4d2eb41..44217fb 100644 --- a/src/data/framework/permissionLoader.ts +++ b/src/data/framework/permissionLoader.ts @@ -30,7 +30,7 @@ export const loadAllPermissions = async () => { }) //TICKET ADMINS - openticket.tickets.forEach(async (ticket) => { + openticket.tickets.loopAll(async (ticket) => { try { const channel = await openticket.client.fetchGuildTextChannel(mainServer,ticket.id.value) if (!channel) return diff --git a/src/data/openticket/optionLoader.ts b/src/data/openticket/optionLoader.ts index 83de4cc..6e4bd3c 100644 --- a/src/data/openticket/optionLoader.ts +++ b/src/data/openticket/optionLoader.ts @@ -19,8 +19,8 @@ export const loadAllOptions = async () => { //update options on config reload optionConfig.onReload(async () => { //clear previous options & suffixes - openticket.options.forEach((data,id) => {openticket.options.remove(id)}) - openticket.options.suffix.forEach((data,id) => {openticket.options.suffix.remove(id)}) + await openticket.options.loopAll((data,id) => {openticket.options.remove(id)}) + await openticket.options.suffix.loopAll((data,id) => {openticket.options.suffix.remove(id)}) //add new options optionConfig.data.forEach((option) => { @@ -36,7 +36,7 @@ export const loadAllOptions = async () => { }) //update options in tickets - openticket.tickets.forEach((ticket) => { + await openticket.tickets.loopAll((ticket) => { const optionId = ticket.option.id const option = openticket.options.get(optionId) if (option && option instanceof api.ODTicketOption) ticket.option = option @@ -49,7 +49,7 @@ export const loadAllOptions = async () => { }) //update roles on config reload - openticket.roles.forEach((data,id) => {openticket.roles.remove(id)}) + await openticket.roles.loopAll((data,id) => {openticket.roles.remove(id)}) await (await import("./roleLoader.js")).loadAllRoles() }) } diff --git a/src/data/openticket/panelLoader.ts b/src/data/openticket/panelLoader.ts index 001d349..07d17cb 100644 --- a/src/data/openticket/panelLoader.ts +++ b/src/data/openticket/panelLoader.ts @@ -12,7 +12,7 @@ export const loadAllPanels = async () => { //update panels on config reload panelConfig.onReload(async () => { //clear previous panels - openticket.panels.forEach((data,id) => {openticket.panels.remove(id)}) + await openticket.panels.loopAll((data,id) => {openticket.panels.remove(id)}) //add new panels panelConfig.data.forEach((panel) => { diff --git a/src/data/openticket/questionLoader.ts b/src/data/openticket/questionLoader.ts index fdd69e6..4b66b8a 100644 --- a/src/data/openticket/questionLoader.ts +++ b/src/data/openticket/questionLoader.ts @@ -13,9 +13,9 @@ export const loadAllQuestions = async () => { }) //update questions on config reload - questionConfig.onReload(() => { + questionConfig.onReload(async () => { //clear previous questions - openticket.questions.forEach((data,id) => {openticket.questions.remove(id)}) + await openticket.questions.loopAll((data,id) => {openticket.questions.remove(id)}) //add new questions questionConfig.data.forEach((question) => { diff --git a/src/data/openticket/roleLoader.ts b/src/data/openticket/roleLoader.ts index cd53f18..d382f24 100644 --- a/src/data/openticket/roleLoader.ts +++ b/src/data/openticket/roleLoader.ts @@ -1,7 +1,7 @@ import {openticket, api, utilities} from "../../index" export const loadAllRoles = async () => { - openticket.options.forEach((opt) => { + openticket.options.loopAll((opt) => { if (opt instanceof api.ODRoleOption){ openticket.roles.add(loadRole(opt)) } From 4e10cba203449ef72efd9704a1d4b29bd13504cc Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 6 Oct 2024 21:17:32 +0200 Subject: [PATCH 039/157] Added docker compatibility --- docker-compose.yml | 9 +++++++++ dockerfile | 18 ++++++++++++++++++ src/core/api/defaults/checker.ts | 3 ++- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 docker-compose.yml create mode 100644 dockerfile diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..145d49b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,9 @@ +# Docker Compose for Open Ticket v4 +version: '3' +services: + openticket: + build: . + volumes: + - .:/app + environment: NODE_ENV=production + restart: unless-stopped \ No newline at end of file diff --git a/dockerfile b/dockerfile new file mode 100644 index 0000000..bca73e3 --- /dev/null +++ b/dockerfile @@ -0,0 +1,18 @@ +# Docker File for Open Ticket v4 +# Use the official Node.js 18 image from Docker Hub +FROM node:18-alpine + +# Set a different working directory inside the container +WORKDIR /usr/src/openticket + +# Copy package.json and package-lock.json into the container +COPY package*.json ./ + +# Install dependencies +RUN npm install + +# Copy the rest of your app's source code into the container +COPY . . + +# Run the bot from index.js +CMD ["node", "index.js"] \ No newline at end of file diff --git a/src/core/api/defaults/checker.ts b/src/core/api/defaults/checker.ts index 24ada35..1044e12 100644 --- a/src/core/api/defaults/checker.ts +++ b/src/core/api/defaults/checker.ts @@ -12,8 +12,9 @@ import ansis from "ansis" */ export interface ODCheckerManagerIds_Default { "openticket:general":ODChecker, + "openticket:questions":ODChecker, "openticket:options":ODChecker, - "openticket:messages":ODChecker, + "openticket:panels":ODChecker, "openticket:transcripts":ODChecker } From 330ea47ab93203cd55742e9170f763b2b2009870 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 7 Oct 2024 22:24:02 +0200 Subject: [PATCH 040/157] Updated german & fixed async forEach errors --- languages/german.json | 24 ++++++++++++------------ src/builders/embeds.ts | 2 +- src/core/api/modules/checker.ts | 2 +- src/core/api/modules/client.ts | 6 +++--- src/core/api/modules/cooldown.ts | 8 ++++---- src/core/api/modules/flag.ts | 4 ++-- src/core/startup/manageMigration.ts | 8 ++++---- src/data/framework/codeLoader.ts | 12 ++++++------ src/data/framework/cooldownLoader.ts | 2 +- src/data/framework/permissionLoader.ts | 2 +- src/data/openticket/roleLoader.ts | 2 +- src/index.ts | 2 +- 12 files changed, 37 insertions(+), 37 deletions(-) diff --git a/languages/german.json b/languages/german.json index 77f4a59..7f0bdd2 100644 --- a/languages/german.json +++ b/languages/german.json @@ -2,7 +2,7 @@ "_TRANSLATION":{ "otversion":"v4.0.0", "translators":["benzorich"], - "lastedited":"22/08/2024", + "lastedited":"06/10/2024", "language":"German", "automated":false }, @@ -10,7 +10,7 @@ "system":{ "typeError":"[ERROR]", "headerOpenTicket":"OPEN TICKET", - "typeWarning":"[WARNING]", + "typeWarning":"[WARNUNG]", "typeInfo":"[INFO]", "headerConfigChecker":"CONFIG CHECKER", "headerDescription":"Prüfen Sie auf Fehler in Ihrer Konfigurationsdateien!", @@ -99,9 +99,9 @@ "delete":"Ticket löschen", "reopen":"Ticket wieder öffnen", "claim":"Ticket beanspruchen", - "unclaim":"Ticket nicht mehr beansprucht", - "pin":"Pin Ticket", - "unpin":"Unpin Ticket", + "unclaim":"Ticket nicht mehr beanspruchen", + "pin":"Ticket anpinnen", + "unpin":"Ticket abpinnen", "clear":"Tickets löschen", "helpSwitchSlash":"Slash-Befehle anzeigen", "helpSwitchText":"Textbefehle anzeigen", @@ -135,10 +135,10 @@ "roles":"Aktualisierte Rollen", "autoclose":"Ticket automatisch geschlossen", - "autocloseEnabled":"Autoclose Aktiviert", - "autocloseDisabled":"Autoclose Deaktiviert", - "autodelete":"Automatisch gelöschtes Ticket", - "autodeleteEnabled":"Autolöschen Aktiviert", + "autocloseEnabled":"Automatisches schließen Aktiviert", + "autocloseDisabled":"Automatisches schließen Deaktiviert", + "autodelete":"Ticket automatisch gelöscht", + "autodeleteEnabled":"Automatisches Löschen Aktiviert", "autodeleteDisabled":"Automatisches Löschen Deaktiviert" }, "descriptions":{ @@ -270,7 +270,7 @@ "noPermissions":"Sie sind nicht berechtigt, {0} zu verwenden!", "noPermissionsList":"Erforderliche Berechtigungen: (eine von diesen)", "noPermissionsCooldown":"Du bist nicht berechtigt, {0} zu benutzen, weil du eine Abklingzeit hast!", - "noPermissionsBlacklist":"Sie sind nicht berechtigt, {0} zu benutzen, da Sie auf der Blacklist stehen!", + "noPermissionsBlacklist":"Sie sind nicht berechtigt, den {0} zu benutzen, da Sie auf der Blacklist stehen!", "noPermissionsLimitGlobal":"Sie können kein Ticket erstellen, da der Server die maximale Ticketanzahl erreicht hat!", "noPermissionsLimitGlobalUser":"Sie können kein Ticket erstellen, weil Sie die maximale Anzahl an Tickets erreicht haben!", "noPermissionsLimitOption":"Sie können kein Ticket erstellen, da der Server die maximale Ticketanzahl für diese Option erreicht hat!", @@ -382,8 +382,8 @@ "claim":"Ein Ticket beanspruchen.", "claimUser":"Beanspruchen Sie dieses Ticket für jemand anderen statt für sich selbst.", "unclaim":"Beanspruchen Sie ein Ticket zurück.", - "pin":"Ein Ticket anpinnen..", - "unpin":"Löse die Anpinnung eines Tickets.", + "pin":"Pinne ein Ticket an.", + "unpin":"Pinne ein Ticket ab.", "move":"Verschieben Sie ein Ticket.", "moveId":"Die Kennung der Option.", "rename":"Ein Ticket umbenennen.", diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts index 0ce400d..78cb533 100644 --- a/src/builders/embeds.ts +++ b/src/builders/embeds.ts @@ -882,7 +882,7 @@ const blacklistEmbeds = () => { const {user} = params const renderedUsers: string[] = [] - openticket.blacklist.loopAll((blacklist,id) => {renderedUsers.push(discord.userMention(id.value)+" - "+(blacklist.reason ? blacklist.reason : "/"))}) + await openticket.blacklist.loopAll((blacklist,id) => {renderedUsers.push(discord.userMention(id.value)+" - "+(blacklist.reason ? blacklist.reason : "/"))}) instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setColor(generalConfig.data.mainColor) diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 795f7a7..9917134 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -65,7 +65,7 @@ export class ODCheckerManager extends ODManager { if (!res.valid) isValid = false }) - this.functions.loopAll((func) => { + this.functions.getAll().forEach((func) => { const res = func.func(this,this.functions) final.push(...res.messages) diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index b178514..ba7b6c6 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -496,7 +496,7 @@ export class ODSlashCommandManager extends ODManager { const existing: {cmd:ODSlashCommand, requiresUpdate:boolean}[] = [] const nonExisting: ODSlashCommand[] = [] - this.loopAll((cmd) => { + await this.loopAll((cmd) => { if (guildId && cmd.guildId != guildId) return const result = cmds.find((cmddata) => cmddata.name == cmd.name) if (result){ @@ -977,7 +977,7 @@ export class ODTextCommandManager extends ODManager { //filter commands for correct prefix const validPrefixCommands: {cmd:ODTextCommand,newContent:string}[] = [] - this.loopAll((cmd) => { + await this.loopAll((cmd) => { if (msg.content.startsWith(cmd.builder.prefix)) validPrefixCommands.push({ cmd:cmd, newContent:msg.content.substring(cmd.builder.prefix.length) @@ -1403,7 +1403,7 @@ export class ODTextCommandManager extends ODManager { } } }else if (option.required){ - //REQUIRED => ERROR IF NOD EXISTING + //REQUIRED => ERROR IF NOT EXISTING const invalidRegex = /^[^ ]+/ const invalidRes = invalidRegex.exec(tempContent) if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"mentionable_not_found") diff --git a/src/core/api/modules/cooldown.ts b/src/core/api/modules/cooldown.ts index e74f568..93a1fc6 100644 --- a/src/core/api/modules/cooldown.ts +++ b/src/core/api/modules/cooldown.ts @@ -138,8 +138,8 @@ export class ODCounterCooldown extends ODCooldown<{value:number}> { } async init(){ if (this.ready) return - setInterval(() => { - this.data.loopAll((cooldown) => { + setInterval(async () => { + await this.data.loopAll((cooldown) => { cooldown.data.value = cooldown.data.value - this.decrement if (cooldown.data.value <= this.cancelLimit){ cooldown.active = false @@ -216,8 +216,8 @@ export class ODIncrementalCounterCooldown extends ODCooldown<{value:number}> { } async init(){ if (this.ready) return - setInterval(() => { - this.data.loopAll((cooldown) => { + setInterval(async () => { + await this.data.loopAll((cooldown) => { cooldown.data.value = cooldown.data.value - this.decrement if (cooldown.data.value <= this.cancelLimit){ cooldown.active = false diff --git a/src/core/api/modules/flag.ts b/src/core/api/modules/flag.ts index 67f9e25..bbc3257 100644 --- a/src/core/api/modules/flag.ts +++ b/src/core/api/modules/flag.ts @@ -65,8 +65,8 @@ export class ODFlagManager extends ODManager { } /**Set all flags to their `process.argv` value. */ - init(){ - this.loopAll((flag) => { + async init(){ + await this.loopAll((flag) => { flag.detectProcessParams(false) }) } diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index 2dcdc06..32194e3 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -42,9 +42,9 @@ const preloadMigrationContext = async () => { const unloadMigrationContext = async () => { openticket.debug.visible = false - openticket.databases.loopAll((database,id) => {openticket.databases.remove(id)}) - openticket.configs.loopAll((config,id) => {openticket.configs.remove(id)}) - openticket.flags.loopAll((flag,id) => {openticket.flags.remove(id)}) + await openticket.databases.loopAll((database,id) => {openticket.databases.remove(id)}) + await openticket.configs.loopAll((config,id) => {openticket.configs.remove(id)}) + await openticket.flags.loopAll((flag,id) => {openticket.flags.remove(id)}) openticket.debug.debug("-- MIGRATION CONTEXT END --") } @@ -78,7 +78,7 @@ const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { const saveAllVersionsToDatabase = async () => { const globalDatabase = openticket.databases.get("openticket:global") - openticket.versions.loopAll((version,id) => { + await openticket.versions.loopAll((version,id) => { globalDatabase.set("openticket:last-version",id.value,version.toString()) }) } \ No newline at end of file diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index c7967ae..3b431f2 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -135,9 +135,9 @@ export const loadDatabaseCleanersCode = async () => { //OPTION DATABASE CLEANER openticket.code.add(new api.ODCode("openticket:option-database-cleaner",10,() => { //delete all unused options - openticket.options.loopAll((option,id) => { - if (optionDatabase.exists("openticket:used-option",id.value) && !openticket.tickets.getAll().some((ticket) => ticket.id.value == id.value)){ - optionDatabase.delete("openticket:used-option",id.value) + openticket.options.getAll().forEach((option) => { + if (optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ + optionDatabase.delete("openticket:used-option",option.id.value) } }) })) @@ -331,9 +331,9 @@ export const loadDatabaseSaversCode = async () => { } //delete all unused options on ticket move - openticket.options.loopAll((option,id) => { - if (optionDatabase.exists("openticket:used-option",id.value) && !openticket.tickets.getAll().some((ticket) => ticket.id.value == id.value)){ - optionDatabase.delete("openticket:used-option",id.value) + openticket.options.getAll().forEach((option) => { + if (optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ + optionDatabase.delete("openticket:used-option",option.id.value) } }) }) diff --git a/src/data/framework/cooldownLoader.ts b/src/data/framework/cooldownLoader.ts index f63efa2..cbb1ded 100644 --- a/src/data/framework/cooldownLoader.ts +++ b/src/data/framework/cooldownLoader.ts @@ -1,7 +1,7 @@ import {openticket, api, utilities} from "../../index" export const loadAllCooldowns = async () => { - openticket.options.loopAll((option) => { + await openticket.options.loopAll((option) => { if (!(option instanceof api.ODTicketOption)) return loadTicketOptionCooldown(option) }) diff --git a/src/data/framework/permissionLoader.ts b/src/data/framework/permissionLoader.ts index 44217fb..d76d014 100644 --- a/src/data/framework/permissionLoader.ts +++ b/src/data/framework/permissionLoader.ts @@ -30,7 +30,7 @@ export const loadAllPermissions = async () => { }) //TICKET ADMINS - openticket.tickets.loopAll(async (ticket) => { + await openticket.tickets.loopAll(async (ticket) => { try { const channel = await openticket.client.fetchGuildTextChannel(mainServer,ticket.id.value) if (!channel) return diff --git a/src/data/openticket/roleLoader.ts b/src/data/openticket/roleLoader.ts index d382f24..8383104 100644 --- a/src/data/openticket/roleLoader.ts +++ b/src/data/openticket/roleLoader.ts @@ -1,7 +1,7 @@ import {openticket, api, utilities} from "../../index" export const loadAllRoles = async () => { - openticket.options.loopAll((opt) => { + await openticket.options.loopAll((opt) => { if (opt instanceof api.ODRoleOption){ openticket.roles.add(loadRole(opt)) } diff --git a/src/index.ts b/src/index.ts index b9ca480..31788ea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -103,7 +103,7 @@ const main = async () => { //initiate flags await openticket.events.get("onFlagInit").emit([openticket.flags]) if (openticket.defaults.getDefault("flagInitiating")){ - openticket.flags.init() + await openticket.flags.init() openticket.debugfile.writeText("\n[ENABLED FLAGS]:\n"+openticket.flags.getFiltered((flag) => (flag.value == true)).map((flag) => flag.id.value).join("\n")+"\n") await openticket.events.get("afterFlagsInitiated").emit([openticket.flags]) } From 848c968483637e121b41f1040d71b1f5ae566bf7 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 14 Oct 2024 20:30:45 +0200 Subject: [PATCH 041/157] Fixed all currently known bugs :) --- languages/italian.json | 528 ++++++++++++------------- src/data/framework/codeLoader.ts | 2 +- src/data/framework/permissionLoader.ts | 4 +- 3 files changed, 267 insertions(+), 267 deletions(-) diff --git a/languages/italian.json b/languages/italian.json index 31483b5..3afe786 100644 --- a/languages/italian.json +++ b/languages/italian.json @@ -1,10 +1,10 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translators":["fraden1mvp.","ChatGPT"], - "lastedited":"02/10/2024", + "translators":["fraden1mvp."], + "lastedited":"08/10/2024", "language":"Italian", - "automated":true + "automated":false }, "checker":{ "system":{ @@ -98,8 +98,8 @@ "close":"Chiudi Ticket", "delete":"Elimina Ticket", "reopen":"Riapri Ticket", - "claim":"Richiedi Ticket", - "unclaim":"Annulla Richiesta Ticket", + "claim":"Claima Ticket", + "unclaim":"Annulla Claim Ticket", "pin":"Fissa Ticket", "unpin":"Sblocca Ticket", "clear":"Elimina Tickets", @@ -114,8 +114,8 @@ "close":"Ticket Chiuso", "delete":"Ticket Eliminato", "reopen":"Ticket Riaperto", - "claim":"Ticket Richiesto", - "unclaim":"Ticket Richiesta Annullata", + "claim":"Ticket Claimato", + "unclaim":"Ticket Claim Annullato", "pin":"Ticket Fissato", "unpin":"Ticket Sbloccato", "rename":"Ticket Rinominato", @@ -146,7 +146,7 @@ "close":"Il ticket è stato chiuso con successo!", "delete":"Il ticket è stato eliminato con successo!", "reopen":"Il ticket è stato riaperto con successo!", - "claim":"Il ticket è stato richiesto con successo!", + "claim":"Il ticket è stato claimato con successo!", "unclaim":"Il ticket è stato annullato con successo!", "pin":"Il ticket è stato fissato con successo!", "unpin":"Il ticket è stato sbloccato con successo!", @@ -186,8 +186,8 @@ "closePlaceholder":"Perché hai chiuso questo ticket?", "deletePlaceholder":"Perché hai eliminato questo ticket?", "reopenPlaceholder":"Perché hai riaperto questo ticket?", - "claimPlaceholder":"Perché hai richiesto questo ticket?", - "unclaimPlaceholder":"Perché hai annullato la richiesta di questo ticket?", + "claimPlaceholder":"Perché hai claimato questo ticket?", + "unclaimPlaceholder":"Perché hai annullato il Claim di questo ticket?", "pinPlaceholder":"Perché hai fissato questo ticket?", "unpinPlaceholder":"Perché hai sbloccato questo ticket?" }, @@ -199,8 +199,8 @@ "deleteDm":"Il tuo ticket è stato eliminato nel nostro server!", "reopenLog":"Questo ticket è stato riaperto da {0}!", "reopenDm":"Il tuo ticket è stato riaperto nel nostro server!", - "claimLog":"Questo ticket è stato richiesto da {0}!", - "claimDm":"Il tuo ticket è stato richiesto nel nostro server!", + "claimLog":"Questo ticket è stato claimato da {0}!", + "claimDm":"Il tuo ticket è stato claimato nel nostro server!", "unclaimLog":"Questo ticket è stato annullato da {0}!", "unclaimDm":"Il tuo ticket è stato annullato nel nostro server!", "pinLog":"Questo ticket è stato fissato da {0}!", @@ -223,255 +223,255 @@ "clearLog":"{0} tickets sono stati eliminati da {1}!" } }, - "transcripts":{ - "success":{ - "visit":"Visita Trascrizione", - "ready":"Trascrizione Creata", - "textFileDescription":"Questa è la trascrizione testuale di un ticket eliminato!", - "htmlProgress":"Attendere mentre questa trascrizione html viene elaborata...", - "createdChannel":"Una nuova trascrizione di {0} è stata creata nel server!", - "createdCreator":"Una nuova trascrizione di {0} è stata creata per uno dei tuoi ticket!", - "createdParticipant":"Una nuova trascrizione di {0} è stata creata in uno dei ticket a cui hai partecipato!", - "createdActiveAdmin":"Una nuova trascrizione di {0} è stata creata in uno dei ticket in cui hai partecipato come admin!", - "createdEveryAdmin":"Una nuova trascrizione di {0} è stata creata in uno dei ticket in cui eri admin!", - "createdOther":"Una nuova trascrizione di {0} è stata creata!" - }, - "errors":{ - "retry":"Riprova", - "continue":"Elimina Senza Trascrizione", - "backup":"Crea Trascrizione di Backup", - "error":"Qualcosa è andato storto durante la creazione della trascrizione.\nCosa vuoi fare?\n\nQuesto ticket non sarà eliminato finché non clicchi su uno di questi pulsanti." - } - }, - "errors":{ - "titles":{ - "internalError":"Errore Interno", - "optionMissing":"Opzione Comando Mancante", - "optionInvalid":"Opzione Comando Non Valida", - "unknownCommand":"Comando Sconosciuto", - "noPermissions":"Nessuna Autorizzazione", - "unknownTicket":"Ticket Sconosciuto", - "deprecatedTicket":"Ticket Obsoleto", - "unknownOption":"Opzione Sconosciuta", - "unknownPanel":"Pannello Sconosciuto", - "notInGuild":"Non nel Server", - "channelRename":"Impossibile Rinominare il Canale", - "busy":"Ticket Occupato" - }, - "descriptions":{ - "askForInfo":"Contatta il proprietario di questo bot per ulteriori informazioni!", - "askForInfoResolve":"Contatta il proprietario di questo bot se il problema non si risolve dopo alcuni tentativi.", - "internalError":"Impossibile rispondere a questo {0} a causa di un errore interno!", - "optionMissing":"Un parametro obbligatorio è mancante in questo comando!", - "optionInvalid":"Un parametro in questo comando non è valido!", - "optionInvalidChoose":"Scegli tra", - "unknownCommand":"Prova a visitare il menu di aiuto per ulteriori informazioni!", - "noPermissions":"Non hai il permesso di utilizzare questo {0}!", - "noPermissionsList":"Permessi Richiesti: (uno di essi)", - "noPermissionsCooldown":"Non hai il permesso di utilizzare questo {0} perché hai un cooldown!", - "noPermissionsBlacklist":"Non hai il permesso di utilizzare questo {0} perché sei stato blacklistato!", - "noPermissionsLimitGlobal":"Non puoi creare un ticket perché il server ha raggiunto il limite massimo di ticket!", - "noPermissionsLimitGlobalUser":"Non puoi creare un ticket perché hai raggiunto il limite massimo di ticket!", - "noPermissionsLimitOption":"Non puoi creare un ticket perché il server ha raggiunto il limite massimo di ticket per questa opzione!", - "noPermissionsLimitOptionUser":"Non puoi creare un ticket perché hai raggiunto il limite massimo di ticket per questa opzione!", - "unknownTicket":"Prova questo comando di nuovo in un ticket valido!", - "deprecatedTicket":"Il canale attuale non è un ticket valido! Potrebbe essere un ticket di una vecchia versione di Open Ticket!", - "notInGuild":"Questo {0} non funziona in DM! Riprova in un server!", - "channelRename":"A causa dei limiti di Discord, al momento non è possibile rinominare il canale. Il canale verrà automaticamente rinominato in oltre 10 minuti se il bot non viene riavviato.", - "channelRenameSource":"La fonte di questo errore è: {0}", - "busy":"Impossibile utilizzare questo {0}!\nIl ticket è attualmente in fase di elaborazione dal bot.\n\nPer favore riprova tra pochi secondi!" - }, - "optionInvalidReasons":{ - "stringRegex":"Il valore non corrisponde al modello!", - "stringMinLength":"Il valore deve essere di almeno {0} caratteri!", - "stringMaxLength":"Il valore deve essere di al massimo {0} caratteri!", - "numberInvalid":"Numero non valido!", - "numberMin":"Il numero deve essere almeno {0}!", - "numberMax":"Il numero deve essere al massimo {0}!", - "numberDecimal":"Il numero non è consentito come decimale!", - "numberNegative":"Il numero non è consentito come negativo!", - "numberPositive":"Il numero non è consentito come positivo!", - "numberZero":"Il numero non è consentito come zero!", - "channelNotFound":"Impossibile trovare il canale!", - "userNotFound":"Impossibile trovare l'utente!", - "roleNotFound":"Impossibile trovare il ruolo!", - "memberNotFound":"Impossibile trovare l'utente!", - "mentionableNotFound":"Impossibile trovare l'utente o il ruolo!", - "channelType":"Tipo di canale non valido!", - "notInGuild":"Questa opzione richiede che tu sia in un server!" - }, - "permissions":{ - "developer":"Devi essere lo sviluppatore del bot.", - "owner":"Devi essere il proprietario del server.", - "admin":"Devi essere un admin del server.", - "moderator":"Devi essere un moderatore.", - "support":"Devi essere nel team di supporto.", - "member":"Devi essere un membro.", - "discord-administrator":"Devi avere il permesso `ADMINISTRATOR`." - }, - "actionInvalid":{ - "close":"Il ticket è già chiuso!", - "reopen":"Il ticket non è ancora chiuso!", - "claim":"Il ticket è già stato rivendicato!", - "unclaim":"Il ticket non è ancora stato rivendicato!", - "pin":"Il ticket è già stato fissato!", - "unpin":"Il ticket non è ancora stato sbloccato!", - "add":"Questo utente può già accedere al ticket!", - "remove":"Impossibile rimuovere questo utente dal ticket!" - } - }, - "params":{ - "uppercase":{ - "ticket":"Ticket", - "tickets":"Tickets", - "reason":"Motivo", - "creator":"Creatore", - "remaining":"Tempo Rimanente", - "added":"Aggiunto", - "removed":"Rimosso", - "filter":"Filtro", - "claimedBy":"Rivendicato Da {0}", - "method":"Metodo", - "type":"Tipo", - "blacklisted":"Blacklistato", - "panel":"Pannello", - "command":"Comando", - "system":"Sistema", - "true":"Vero", - "false":"Falso", - "syntax":"Sintassi", - "originalName":"Nome Originale", - "newName":"Nuovo Nome", - "until":"Fino a", - "validOptions":"Opzioni Valide", - "validPanels":"Pannelli Validi", - "autoclose":"Chiusura Automatica", - "autodelete":"Cancellazione Automatica", - "startupDate":"Data di Avvio", - "version":"Versione", - "name":"Nome", - "role":"Ruolo", - "status":"Stato", - "claimed":"Rivendicato", - "pinned":"Fissato", - "creationDate":"Data di Creazione" - }, - "lowercase":{ - "text":"testo", - "html":"html", - "command":"comando", - "modal":"modale", - "button":"pulsante", - "dropdown":"dropdown", - "method":"metodo" - } - }, - "commands":{ - "reason":"Specifica un motivo facoltativo che sarà visibile nei log.", - "help":"Ottieni un elenco di tutti i comandi disponibili.", - "panel":"Genera un messaggio con un dropdown o pulsanti (per la creazione del ticket).", - "panelId":"L'identificatore del pannello che vuoi generare.", - "panelAutoUpdate":"Vuoi che questo pannello si aggiorni automaticamente quando viene modificato?", - "ticket":"Crea istantaneamente un ticket.", - "ticketId":"L'identificatore del ticket che vuoi creare.", - "close":"Chiudi un ticket.", - "delete":"Elimina un ticket.", - "deleteNoTranscript":"Elimina questo ticket senza creare una trascrizione.", - "reopen":"Riapri un ticket.", - "claim":"Rivendica un ticket.", - "claimUser":"Rivendica questo ticket a qualcun altro invece di te stesso.", - "unclaim":"Rimuovi la rivendicazione di un ticket.", - "pin":"Fissa un ticket.", - "unpin":"Sblocca un ticket.", - "move":"Sposta un ticket.", - "moveId":"L'identificatore dell'opzione a cui vuoi spostare.", - "rename":"Rinomina un ticket.", - "renameName":"Il nuovo nome per questo ticket.", - "add":"Aggiungi un utente a un ticket.", - "addUser":"L'utente da aggiungere.", - "remove":"Rimuovi un utente da un ticket.", - "removeUser":"L'utente da rimuovere.", - "blacklist":"Gestisci la blacklist del ticket.", - "blacklistView":"Visualizza un elenco della blacklist attuale.", - "blacklistAdd":"Aggiungi un utente alla blacklist.", - "blacklistRemove":"Rimuovi un utente dalla blacklist.", - "blacklistGet":"Ottieni i dettagli di un utente blacklistato.", - "blacklistGetUser":"L'utente di cui ottenere i dettagli.", - "stats":"Visualizza le statistiche del bot, di un membro o di un ticket.", - "statsReset":"Reimposta tutte le statistiche del bot (e inizia a contare da zero).", - "statsGlobal":"Visualizza le statistiche globali.", - "statsUser":"Visualizza le statistiche di un utente nel server.", - "statsUserUser":"L'utente di cui visualizzare le statistiche.", - "statsTicket":"Visualizza le statistiche di un ticket nel server.", - "statsTicketTicket":"Il ticket da visualizzare.", - "clear":"Elimina più ticket contemporaneamente.", - "clearFilter":"Il filtro per eliminare ticket.", - "clearFilters":{ - "all":"Tutti", - "open":"Aperti", - "close":"Chiusi", - "claim":"Rivendicati", - "unclaim":"Non Rivendicati", - "pin":"Fissati", - "unpin":"Non Fissati", - "autoclose":"Chiusura Automatica" - }, - "autoclose":"Gestisci la chiusura automatica in un ticket.", - "autocloseDisable":"Disabilita la chiusura automatica in questo ticket.", - "autocloseEnable":"Abilita la chiusura automatica in questo ticket.", - "autocloseEnableTime":"Il numero di ore in cui questo ticket deve essere inattivo per chiuderlo.", - "autodelete":"Gestisci la cancellazione automatica in un ticket.", - "autodeleteDisable":"Disabilita la cancellazione automatica in questo ticket.", - "autodeleteEnable":"Abilita la cancellazione automatica in questo ticket.", - "autodeleteEnableTime":"Il numero di giorni in cui questo ticket deve essere inattivo per eliminarlo." - }, - "helpMenu":{ - "help":"Ottieni un elenco di tutti i comandi disponibili.", - "ticket":"Crea istantaneamente un ticket.", - "close":"Chiudi un ticket, disabilita la scrittura in questo canale.", - "delete":"Elimina un ticket, crea una trascrizione quando abilitato.", - "reopen":"Riapri un ticket, abilita nuovamente la scrittura in questo canale.", - "pin":"Fissa un ticket. Questo lo sposterà in cima e aggiungerà un'emoji '📌' al nome.", - "unpin":"Sblocca un ticket. Il ticket rimarrà nella sua posizione ma perderà l'emoji '📌'.", - "move":"Sposta un ticket. Questo cambierà il tipo di questo ticket.", - "rename":"Rinomina un ticket. Questo cambierà il nome del canale di questo ticket.", - "claim":"Rivendica un ticket. In questo modo, il tuo team saprà che stai gestendo questo ticket.", - "unclaim":"Rimuovi la rivendicazione di un ticket. In questo modo, il tuo team saprà che questo ticket è di nuovo libero.", - "add":"Aggiungi un utente a un ticket. Questo permetterà all'utente di leggere e scrivere in questo ticket.", - "remove":"Rimuovi un utente da un ticket. Questo rimuoverà la possibilità di leggere e scrivere per un utente in questo ticket.", - "panel":"Genera un messaggio con un dropdown o pulsanti (per la creazione del ticket).", - "blacklistView":"Visualizza un elenco della blacklist attuale.", - "blacklistAdd":"Aggiungi un utente alla blacklist.", - "blacklistRemove":"Rimuovi un utente dalla blacklist.", - "blacklistGet":"Ottieni i dettagli di un utente blacklistato.", - "statsGlobal":"Visualizza le statistiche globali.", - "statsTicket":"Visualizza le statistiche di un ticket nel server.", - "statsUser":"Visualizza le statistiche di un utente nel server.", - "statsReset":"Reimposta tutte le statistiche del bot (e inizia a contare da zero).", - "autocloseDisable":"Disabilita la chiusura automatica in questo ticket.", - "autocloseEnable":"Abilita la chiusura automatica in questo ticket.", - "autodeleteDisable":"Disabilita la cancellazione automatica in questo ticket.", - "autodeleteEnable":"Abilita la cancellazione automatica in questo ticket." - }, - "stats":{ - "scopes":{ - "global":"Statistiche Globali", - "system":"Statistiche di Sistema", - "user":"Statistiche Utente", - "ticket":"Statistiche Ticket", - "participants":"Partecipanti" - }, - "properties":{ - "ticketsCreated":"Ticket Creati", - "ticketsClosed":"Ticket Chiusi", - "ticketsDeleted":"Ticket Eliminati", - "ticketsReopened":"Ticket Riaperti", - "ticketsAutoclosed":"Ticket Chiusi Automaticamente", - "ticketsClaimed":"Ticket Rivendicati", - "ticketsPinned":"Ticket Fissati", - "ticketsMoved":"Ticket Spostati", - "usersBlacklisted":"Utenti Blacklistati", - "transcriptsCreated":"Trascrizioni Create" - } - } - } + "transcripts":{ + "success":{ + "visit":"Visita Trascrizione", + "ready":"Trascrizione Creata", + "textFileDescription":"Questa è la trascrizione testuale di un ticket eliminato!", + "htmlProgress":"Attendere mentre questa trascrizione html viene elaborata...", + "createdChannel":"Una nuova trascrizione di {0} è stata creata nel server!", + "createdCreator":"Una nuova trascrizione di {0} è stata creata per uno dei tuoi ticket!", + "createdParticipant":"Una nuova trascrizione di {0} è stata creata in uno dei ticket a cui hai partecipato!", + "createdActiveAdmin":"Una nuova trascrizione di {0} è stata creata in uno dei ticket in cui hai partecipato come admin!", + "createdEveryAdmin":"Una nuova trascrizione di {0} è stata creata in uno dei ticket in cui eri admin!", + "createdOther":"Una nuova trascrizione di {0} è stata creata!" + }, + "errors":{ + "retry":"Riprova", + "continue":"Elimina Senza Trascrizione", + "backup":"Crea Trascrizione di Backup", + "error":"Qualcosa è andato storto durante la creazione della trascrizione.\nCosa vuoi fare?\n\nQuesto ticket non sarà eliminato finché non clicchi su uno di questi pulsanti." + } + }, + "errors":{ + "titles":{ + "internalError":"Errore Interno", + "optionMissing":"Opzione Comando Mancante", + "optionInvalid":"Opzione Comando Non Valida", + "unknownCommand":"Comando Sconosciuto", + "noPermissions":"Nessuna Autorizzazione", + "unknownTicket":"Ticket Sconosciuto", + "deprecatedTicket":"Ticket Obsoleto", + "unknownOption":"Opzione Sconosciuta", + "unknownPanel":"Pannello Sconosciuto", + "notInGuild":"Non nel Server", + "channelRename":"Impossibile Rinominare il Canale", + "busy":"Ticket Occupato" + }, + "descriptions":{ + "askForInfo":"Contatta il proprietario di questo bot per ulteriori informazioni!", + "askForInfoResolve":"Contatta il proprietario di questo bot se il problema non si risolve dopo alcuni tentativi.", + "internalError":"Impossibile rispondere a questo {0} a causa di un errore interno!", + "optionMissing":"Un parametro obbligatorio è mancante in questo comando!", + "optionInvalid":"Un parametro in questo comando non è valido!", + "optionInvalidChoose":"Scegli tra", + "unknownCommand":"Prova a visitare il menu di aiuto per ulteriori informazioni!", + "noPermissions":"Non hai il permesso di utilizzare questo {0}!", + "noPermissionsList":"Permessi Richiesti: (uno di essi)", + "noPermissionsCooldown":"Non hai il permesso di utilizzare questo {0} perché hai un cooldown!", + "noPermissionsBlacklist":"Non hai il permesso di utilizzare questo {0} perché sei stato blacklistato!", + "noPermissionsLimitGlobal":"Non puoi creare un ticket perché il server ha raggiunto il limite massimo di ticket!", + "noPermissionsLimitGlobalUser":"Non puoi creare un ticket perché hai raggiunto il limite massimo di ticket!", + "noPermissionsLimitOption":"Non puoi creare un ticket perché il server ha raggiunto il limite massimo di ticket per questa opzione!", + "noPermissionsLimitOptionUser":"Non puoi creare un ticket perché hai raggiunto il limite massimo di ticket per questa opzione!", + "unknownTicket":"Prova questo comando di nuovo in un ticket valido!", + "deprecatedTicket":"Il canale attuale non è un ticket valido! Potrebbe essere un ticket di una vecchia versione di Open Ticket!", + "notInGuild":"Questo {0} non funziona in DM! Riprova in un server!", + "channelRename":"A causa dei limiti di Discord, al momento non è possibile rinominare il canale. Il canale verrà automaticamente rinominato in oltre 10 minuti se il bot non viene riavviato.", + "channelRenameSource":"La fonte di questo errore è: {0}", + "busy":"Impossibile utilizzare questo {0}!\nIl ticket è attualmente in fase di elaborazione dal bot.\n\nPer favore riprova tra pochi secondi!" + }, + "optionInvalidReasons":{ + "stringRegex":"Il valore non corrisponde al modello!", + "stringMinLength":"Il valore deve essere di almeno {0} caratteri!", + "stringMaxLength":"Il valore deve essere di al massimo {0} caratteri!", + "numberInvalid":"Numero non valido!", + "numberMin":"Il numero deve essere almeno {0}!", + "numberMax":"Il numero deve essere al massimo {0}!", + "numberDecimal":"Il numero non è consentito come decimale!", + "numberNegative":"Il numero non è consentito come negativo!", + "numberPositive":"Il numero non è consentito come positivo!", + "numberZero":"Il numero non è consentito come zero!", + "channelNotFound":"Impossibile trovare il canale!", + "userNotFound":"Impossibile trovare l'utente!", + "roleNotFound":"Impossibile trovare il ruolo!", + "memberNotFound":"Impossibile trovare l'utente!", + "mentionableNotFound":"Impossibile trovare l'utente o il ruolo!", + "channelType":"Tipo di canale non valido!", + "notInGuild":"Questa opzione richiede che tu sia in un server!" + }, + "permissions":{ + "developer":"Devi essere lo sviluppatore del bot.", + "owner":"Devi essere il proprietario del server.", + "admin":"Devi essere un admin del server.", + "moderator":"Devi essere un moderatore.", + "support":"Devi essere nel team di supporto.", + "member":"Devi essere un membro.", + "discord-administrator":"Devi avere il permesso `ADMINISTRATOR`." + }, + "actionInvalid":{ + "close":"Il ticket è già chiuso!", + "reopen":"Il ticket non è ancora chiuso!", + "claim":"Il ticket è già stato rivendicato!", + "unclaim":"Il ticket non è ancora stato rivendicato!", + "pin":"Il ticket è già stato fissato!", + "unpin":"Il ticket non è ancora stato sbloccato!", + "add":"Questo utente può già accedere al ticket!", + "remove":"Impossibile rimuovere questo utente dal ticket!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickets", + "reason":"Motivo", + "creator":"Creatore", + "remaining":"Tempo Rimanente", + "added":"Aggiunto", + "removed":"Rimosso", + "filter":"Filtro", + "claimedBy":"Rivendicato Da {0}", + "method":"Metodo", + "type":"Tipo", + "blacklisted":"Blacklistato", + "panel":"Pannello", + "command":"Comando", + "system":"Sistema", + "true":"Vero", + "false":"Falso", + "syntax":"Sintassi", + "originalName":"Nome Originale", + "newName":"Nuovo Nome", + "until":"Fino a", + "validOptions":"Opzioni Valide", + "validPanels":"Pannelli Validi", + "autoclose":"Chiusura Automatica", + "autodelete":"Cancellazione Automatica", + "startupDate":"Data di Avvio", + "version":"Versione", + "name":"Nome", + "role":"Ruolo", + "status":"Stato", + "claimed":"Rivendicato", + "pinned":"Fissato", + "creationDate":"Data di Creazione" + }, + "lowercase":{ + "text":"testo", + "html":"html", + "command":"comando", + "modal":"modale", + "button":"pulsante", + "dropdown":"dropdown", + "method":"metodo" + } + }, + "commands":{ + "reason":"Specifica un motivo facoltativo che sarà visibile nei log.", + "help":"Ottieni un elenco di tutti i comandi disponibili.", + "panel":"Genera un messaggio con un dropdown o pulsanti (per la creazione del ticket).", + "panelId":"L'identificatore del pannello che vuoi generare.", + "panelAutoUpdate":"Vuoi che questo pannello si aggiorni automaticamente quando viene modificato?", + "ticket":"Crea istantaneamente un ticket.", + "ticketId":"L'identificatore del ticket che vuoi creare.", + "close":"Chiudi un ticket.", + "delete":"Elimina un ticket.", + "deleteNoTranscript":"Elimina questo ticket senza creare una trascrizione.", + "reopen":"Riapri un ticket.", + "claim":"Rivendica un ticket.", + "claimUser":"Rivendica questo ticket a qualcun altro invece di te stesso.", + "unclaim":"Rimuovi la rivendicazione di un ticket.", + "pin":"Fissa un ticket.", + "unpin":"Sblocca un ticket.", + "move":"Sposta un ticket.", + "moveId":"L'identificatore dell'opzione a cui vuoi spostare.", + "rename":"Rinomina un ticket.", + "renameName":"Il nuovo nome per questo ticket.", + "add":"Aggiungi un utente a un ticket.", + "addUser":"L'utente da aggiungere.", + "remove":"Rimuovi un utente da un ticket.", + "removeUser":"L'utente da rimuovere.", + "blacklist":"Gestisci la blacklist del ticket.", + "blacklistView":"Visualizza un elenco della blacklist attuale.", + "blacklistAdd":"Aggiungi un utente alla blacklist.", + "blacklistRemove":"Rimuovi un utente dalla blacklist.", + "blacklistGet":"Ottieni i dettagli di un utente blacklistato.", + "blacklistGetUser":"L'utente di cui ottenere i dettagli.", + "stats":"Visualizza le statistiche del bot, di un membro o di un ticket.", + "statsReset":"Reimposta tutte le statistiche del bot (e inizia a contare da zero).", + "statsGlobal":"Visualizza le statistiche globali.", + "statsUser":"Visualizza le statistiche di un utente nel server.", + "statsUserUser":"L'utente di cui visualizzare le statistiche.", + "statsTicket":"Visualizza le statistiche di un ticket nel server.", + "statsTicketTicket":"Il ticket da visualizzare.", + "clear":"Elimina più ticket contemporaneamente.", + "clearFilter":"Il filtro per eliminare ticket.", + "clearFilters":{ + "all":"Tutti", + "open":"Aperti", + "close":"Chiusi", + "claim":"Rivendicati", + "unclaim":"Non Rivendicati", + "pin":"Fissati", + "unpin":"Non Fissati", + "autoclose":"Chiusura Automatica" + }, + "autoclose":"Gestisci la chiusura automatica in un ticket.", + "autocloseDisable":"Disabilita la chiusura automatica in questo ticket.", + "autocloseEnable":"Abilita la chiusura automatica in questo ticket.", + "autocloseEnableTime":"Il numero di ore in cui questo ticket deve essere inattivo per chiuderlo.", + "autodelete":"Gestisci la cancellazione automatica in un ticket.", + "autodeleteDisable":"Disabilita la cancellazione automatica in questo ticket.", + "autodeleteEnable":"Abilita la cancellazione automatica in questo ticket.", + "autodeleteEnableTime":"Il numero di giorni in cui questo ticket deve essere inattivo per eliminarlo." + }, + "helpMenu":{ + "help":"Ottieni un elenco di tutti i comandi disponibili.", + "ticket":"Crea istantaneamente un ticket.", + "close":"Chiudi un ticket, disabilita la scrittura in questo canale.", + "delete":"Elimina un ticket, crea una trascrizione quando abilitato.", + "reopen":"Riapri un ticket, abilita nuovamente la scrittura in questo canale.", + "pin":"Fissa un ticket. Questo lo sposterà in cima e aggiungerà un'emoji '📌' al nome.", + "unpin":"Sblocca un ticket. Il ticket rimarrà nella sua posizione ma perderà l'emoji '📌'.", + "move":"Sposta un ticket. Questo cambierà il tipo di questo ticket.", + "rename":"Rinomina un ticket. Questo cambierà il nome del canale di questo ticket.", + "claim":"Rivendica un ticket. In questo modo, il tuo team saprà che stai gestendo questo ticket.", + "unclaim":"Rimuovi la rivendicazione di un ticket. In questo modo, il tuo team saprà che questo ticket è di nuovo libero.", + "add":"Aggiungi un utente a un ticket. Questo permetterà all'utente di leggere e scrivere in questo ticket.", + "remove":"Rimuovi un utente da un ticket. Questo rimuoverà la possibilità di leggere e scrivere per un utente in questo ticket.", + "panel":"Genera un messaggio con un dropdown o pulsanti (per la creazione del ticket).", + "blacklistView":"Visualizza un elenco della blacklist attuale.", + "blacklistAdd":"Aggiungi un utente alla blacklist.", + "blacklistRemove":"Rimuovi un utente dalla blacklist.", + "blacklistGet":"Ottieni i dettagli di un utente blacklistato.", + "statsGlobal":"Visualizza le statistiche globali.", + "statsTicket":"Visualizza le statistiche di un ticket nel server.", + "statsUser":"Visualizza le statistiche di un utente nel server.", + "statsReset":"Reimposta tutte le statistiche del bot (e inizia a contare da zero).", + "autocloseDisable":"Disabilita la chiusura automatica in questo ticket.", + "autocloseEnable":"Abilita la chiusura automatica in questo ticket.", + "autodeleteDisable":"Disabilita la cancellazione automatica in questo ticket.", + "autodeleteEnable":"Abilita la cancellazione automatica in questo ticket." + }, + "stats":{ + "scopes":{ + "global":"Statistiche Globali", + "system":"Statistiche di Sistema", + "user":"Statistiche Utente", + "ticket":"Statistiche Ticket", + "participants":"Partecipanti" + }, + "properties":{ + "ticketsCreated":"Ticket Creati", + "ticketsClosed":"Ticket Chiusi", + "ticketsDeleted":"Ticket Eliminati", + "ticketsReopened":"Ticket Riaperti", + "ticketsAutoclosed":"Ticket Chiusi Automaticamente", + "ticketsClaimed":"Ticket Rivendicati", + "ticketsPinned":"Ticket Fissati", + "ticketsMoved":"Ticket Spostati", + "usersBlacklisted":"Utenti Blacklistati", + "transcriptsCreated":"Trascrizioni Create" + } + } +} \ No newline at end of file diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index 3b431f2..0699c17 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -296,7 +296,7 @@ export const loadPanelAutoUpdateCode = async () => { const channel = await openticket.client.fetchGuildTextChannel(mainServer,splittedId[0]) if (!channel) return const message = await openticket.client.fetchGuildChannelMessage(mainServer,channel,splittedId[1]) - if (!message) return + if (!message || !message.editable) return message.edit((await openticket.builders.messages.getSafe("openticket:panel").build("auto-update",{guild:mainServer,channel,user:openticket.client.client.user,panel})).message) openticket.log("Panel in server got auto-updated!","info",[ diff --git a/src/data/framework/permissionLoader.ts b/src/data/framework/permissionLoader.ts index d76d014..9966f69 100644 --- a/src/data/framework/permissionLoader.ts +++ b/src/data/framework/permissionLoader.ts @@ -62,7 +62,7 @@ export const addTicketPermissions = async (ticket:api.ODTicket) => { const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] - admins.concat(readAdmins).forEach(async (admin) => { + for (const admin of admins.concat(readAdmins)){ if (openticket.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return const role = await mainServer.roles.fetch(admin) if (!role) return openticket.log("Unable to register permission for ticket admin!","error",[ @@ -70,7 +70,7 @@ export const addTicketPermissions = async (ticket:api.ODTicket) => { ]) openticket.permissions.add(new api.ODPermission("openticket:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) - }) + } } export const removeTicketPermissions = async (ticket:api.ODTicket) => { From 798ab8fab193c54e89dc154e4e0c295ee60044e8 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 16 Oct 2024 14:22:17 +0200 Subject: [PATCH 042/157] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 19c0c02..9b4877a 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇷🇴 Romanian |sankedev |🟢 Up To Date | |🇺🇦 Ukrainian |anderskiy |🟢 Up To Date | |🇮🇩 Indonesian |erxg |🟢 Up To Date | -|🇮🇹 Italian |fraden1mvp. & ChatGPT |🔵 Up To Date (ChatGPT) | +|🇮🇹 Italian |fraden1mvp. |🟢 Up To Date | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | |🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | |🇩🇰 Danish |.the_gamer |🟠 Temporary Outdated (beta) | From 6423ed4b4144b983a7d5fafaad502fa8a9409c4a Mon Sep 17 00:00:00 2001 From: NotMega <135043684+iamnotmega@users.noreply.github.com> Date: Sat, 26 Oct 2024 19:41:36 +0300 Subject: [PATCH 043/157] Create estonian.json --- languages/estonian.json | 478 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 478 insertions(+) create mode 100644 languages/estonian.json diff --git a/languages/estonian.json b/languages/estonian.json new file mode 100644 index 0000000..656cbad --- /dev/null +++ b/languages/estonian.json @@ -0,0 +1,478 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translators":["iamnotmega"], + "lastedited":"21/10/2024", + "language":"Estonian", + "automated":true + }, + "checker":{ + "system":{ + "typeError":"[VIGA]", + "headerOpenTicket":"AVATUD PILET", + "typeWarning":"[HOIATUS]", + "typeInfo":"[INFO]", + "headerConfigChecker":"KONFIGURATSIOONI KONTROLLIJA", + "headerDescription":"kontrollige konfiguratsioonifailides vigu!", + "footerError":"robot ei käivitu enne, kui kõik {0} on parandatud!", + "footerWarning":"enne alustamist on soovitatav kõik {0} parandada!", + "footerSupport":"TUGI: {0} – DOKUMENTATSIOON: {1}", + "compactInformation":"lisateabe saamiseks kasutage {0}!", + "dataPath":"tee", + "dataDocs":"dokumentatsioon", + "dataMessages":"message" + }, + "messages":{ + "stringTooShort":"See string ei tohi olla lühem kui {0} tähemärki!", + "stringTooLong":"See string ei tohi olla pikem kui {0} tähemärki!", + "stringLengthInvalid":"See string peab olema {0} tähemärki pikk!", + "stringStartsWith":"See string peab algama tähega {0}!", + "stringEndsWith":"See string peab lõppema tähega {0}!", + "stringContains":"See string peab sisaldama {0}!", + "stringChoices":"See string võib olla ainult üks järgmistest väärtustest: {0}!", + "stringRegex":"See string on kehtetu!", + + "numberTooShort":"See number ei tohi olla lühem kui {0} tähemärki!", + "numberTooLong":"See number ei tohi olla pikem kui {0} tähemärki!", + "numberLengthInvalid":"See number peab olema {0} tähemärki pikk!", + "numberTooSmall":"See number peab olema vähemalt {0}!", + "numberTooLarge":"See arv peab olema kuni {0}!", + "numberNotEqual":"See number peab olema {0}!", + "numberStep":"See arv peab olema arvu {0} kordne!", + "numberStepOffset":"See arv peab olema arvu {0} kordne, mis algab numbriga {1}!", + "numberStartsWith":"See number peab algama tähega {0}!", + "numberEndsWith":"See number peab lõppema numbriga {0}!", + "numberContains":"See number peab sisaldama {0}!", + "numberChoices":"See arv võib olla ainult üks järgmistest väärtustest: {0}!", + "numberFloat":"See arv ei tohi olla kümnendkoht!", + "numberNegative":"See arv ei saa olla negatiivne!", + "numberPositive":"See arv ei saa olla positiivne!", + "numberZero":"See arv ei saa olla null!", + + "booleanTrue":"See tõeväärtus ei saa olla tõsi!", + "booleanFalse":"See tõeväärtus ei saa olla vale!", + + "arrayEmptyDisabled":"See massiiv ei tohi olla tühi!", + "arrayEmptyRequired":"See massiiv peab olema tühi!", + "arrayTooShort":"Selle massiivi pikkus peab olema vähemalt {0}!", + "arrayTooLong":"Selle massiivi pikkus peab olema maksimaalselt {0}!", + "arrayLengthInvalid":"Selle massiivi pikkus peab olema {0}!", + "arrayInvalidTypes":"See massiiv võib sisaldada ainult järgmisi tüüpe: {0}!", + "arrayDouble":"See massiiv ei luba sama väärtust kaks korda kasutada!", + + "discordInvalidId":"See on kehtetu Discordi {0} ID!", + "discordInvalidIdOptions":"See on kehtetu Discordi {0} ID! Võite kasutada ka ühte järgmistest: {1}!", + "discordInvalidToken":"See on kehtetu Discordi tooken (süntaktiliselt)!", + "colorInvalid":"See on sobimatu kuusnurkne värv!", + "emojiTooShort":"Sellel stringil peab olema vähemalt {0} emotikonit!", + "emojiTooLong":"Selles stringis peab olema kuni {0} emotikonit!", + "emojiCustom":"See emotikon ei saa olla kohandatud emotikon!", + "emojiInvalid":"See on sobimatu emotikon!", + "urlInvalid":"See URL on kehtetu!", + "urlInvalidHttp":"See URL saab kasutada ainult https:// protokolli!", + "urlInvalidProtocol":"See URL saab kasutada ainult http:// ja https:// protokolle!", + "urlInvalidHostname":"Sellel URL-il on keelatud hostinimi!", + "urlInvalidExtension":"Sellel URL-il on sobimatu laiend! Valige järgmiste hulgast: {0}!", + "urlInvalidPath":"Sellel URL-il on vale tee!", + "idNotUnique":"See ID ei ole kordumatu, kasutage selle asemel teist ID-d!", + "idNonExistent":"ID-d {0} pole olemas!", + + "invalidType":"Selle atribuudi tüüp peab olema: {0}!", + "propertyMissing":"Sellel objektil puudub atribuut {0}!", + "propertyOptional":"Atribuut {0} on selles objektis valikuline!", + "objectDisabled":"See objekt on keelatud, lubage see, kasutades {0}!", + "nullInvalid":"See vara ei saa olla tühi!", + "switchInvalidType":"See peab olema üks järgmistest tüüpidest: {0}!", + "objectSwitchInvalid":"See objekt peab olema ühte järgmistest tüüpidest: {0}!", + + "invalidLanguage":"See on sobimatu keel!", + "invalidButton":"Sellel nupul peab olema vähemalt {0} või {1}!", + "unusedOption":"Valik {0} ei ole kusagil kasutusel!", + "unusedQuestion":"Küsimust {0} ei kasutata kuskil!", + "dropdownOption":"Lubatud rippmenüüga paneel võib sisaldada ainult \"pileti\" tüüpi valikuid!" + } + }, + "actions":{ + "buttons":{ + "create":"Külastage Piletit", + "close":"Sulge pilet", + "delete":"Kustuta pilet", + "reopen":"Ava pilet uuesti", + "claim":"Nõudke pilet", + "unclaim":"Tühista pilet", + "pin":"Kinnita pilet", + "unpin":"Vabastage pilet", + "clear":"Kustuta piletid", + "helpSwitchSlash":"Vaadake kaldkriipsu käske", + "helpSwitchText":"Vaadake tekstikäske", + "helpPage":"Leht {0}", + "withReason":"Põhjusega", + "withoutTranscript":"Ilma ärakirjata" + }, + "titles":{ + "created":"Pilet loodud", + "close":"Pilet suletud", + "delete":"Pilet kustutatud", + "reopen":"Pilet taasavatud", + "claim":"Pilet nõutud", + "unclaim":"Pilet tühistatud", + "pin":"Pilet kinnitatud", + "unpin":"Pilet vabastatud", + "rename":"Pilet nimetati ümber", + "move":"Pilet teisaldatud", + "add":"Pileti kasutaja lisatud", + "remove":"Pileti kasutaja eemaldatud", + + "help":"Saadaolevad käsud", + "statsReset":"Lähtestage statistika", + "blacklistAdd":"Kasutaja on mustas nimekirjas", + "blacklistRemove":"Kasutaja vabastatud", + "blacklistGet":"Musta nimekirja kantud kasutaja", + "blacklistView":"Praegune must nimekiri", + "blacklistAddDm":"Lisatud musta nimekirja", + "blacklistRemoveDm":"Eemaldatud mustast nimekirjast", + "clear":"Piletid kustutatud", + "roles":"Rollid uuendatud", + + "autoclose":"Pilet automaatselt suletud", + "autocloseEnabled":"Automaatne sulgemine lubatud", + "autocloseDisabled":"Automaatne sulgemine keelatud", + "autodelete":"Pilet on automaatselt kustutatud", + "autodeleteEnabled":"Automaatne kustutamine lubatud", + "autodeleteDisabled":"Automaatne kustutamine keelatud" + }, + "descriptions":{ + "create":"Teie pilet on loodud. Sellele juurdepääsuks klõpsake alloleval nupul!", + "close":"Pilet on edukalt suletud!", + "delete":"Pilet on edukalt kustutatud!", + "reopen":"Pilet on edukalt taasavatud!", + "claim":"Pilet on edukalt vastu võetud!", + "unclaim":"Pilet on edukalt tühistatud!", + "pin":"Pilet on edukalt kinnitatud!", + "unpin":"Pilet on edukalt vabastatud!", + "rename":"Pilet on edukalt ümber nimetatud nimeks {0}!", + "move":"Pilet teisaldati asukohta {0} edukalt!", + "add":"{0} lisati piletile edukalt!", + "remove":"{0} eemaldati piletist edukalt!", + + "helpExplanation":"`` => nõutav parameeter\n`[nimi]` => valikuline parameeter", + "statsReset":"Boti statistika on edukalt lähtestatud!", + "statsError":"Piletistatistikat ei saa vaadata!\n{0} ei ole pilet!", + "blacklistAdd":"{0} on edukalt musta nimekirja kantud!", + "blacklistRemove":"{0} vabastati edukalt!", + "blacklistGetSuccess":"{0} on praegu mustas nimekirjas!", + "blacklistGetEmpty":"{0} ei ole praegu mustas nimekirjas!", + "blacklistViewEmpty":"Keegi pole veel musta nimekirja kantud!", + "blacklistViewTip":"Kasutage \"/blacklist add\" kasutaja musta nimekirja lisamiseks!", + "clearVerify":"Kas soovite kindlasti mitu piletit kustutada?\nSeda toimingut ei saa tagasi võtta!", + "clearReady":"{0} piletit on edukalt kustutatud!", + "rolesEmpty":"Ühtegi rolli pole värskendatud!", + + "autocloseLeave":"See pilet on automaatselt suletud, kuna looja lahkus serverist!", + "autocloseTimeout":"See pilet on automaatselt suletud, kuna see on olnud passiivne rohkem kui `{0}h`!", + "autodeleteLeave":"See pilet on automaatselt kustutatud, kuna looja lahkus serverist!", + "autodeleteTimeout":"See pilet on automaatselt kustutatud, kuna see on olnud passiivne rohkem kui `{0} päeva`!", + "autocloseEnabled":"Sellel piletil on automaatne sulgemine lubatud!\nSee suletakse, kui see on passiivne rohkem kui `{0}h`!", + "autocloseDisabled":"Automaatne sulgemine on sellel piletil keelatud!\nSeda ei suleta enam automaatselt!", + "autodeleteEnabled":"Sellel piletil on automaatne kustutamine lubatud!\nSee kustutatakse, kui see on passiivne rohkem kui `{0} päeva`!", + "autodeleteDisabled":"Automaatne kustutamine on sellel piletil keelatud!\nSeda ei kustutata enam automaatselt!", + + "ticketMessageLimit":"Saate korraga luua ainult {0} piletit!", + "ticketMessageAutoclose":"See pilet suletakse automaatselt, kui see on {0} tundi passiivne!", + "ticketMessageAutodelete":"See pilet kustutatakse automaatselt, kui see on {0} päeva passiivne!", + "panelReady":"Paneeli leiate altpoolt!\nSelle sõnumi saab nüüd kustutada!" + }, + "modal":{ + "closePlaceholder":"Miks sa selle pileti kinni panid?", + "deletePlaceholder":"Miks sa selle pileti kustutasid?", + "reopenPlaceholder":"Miks te selle pileti uuesti avasite?", + "claimPlaceholder":"Miks sa selle pileti välja nõudsid?", + "unclaimPlaceholder":"Miks te selle pileti tühistasite?", + "pinPlaceholder":"Miks sa selle pileti kinni panid?", + "unpinPlaceholder":"Miks sa selle pileti lahti kinnitasid?" + }, + "logs":{ + "createLog":"{0} lõi uue pileti!", + "closeLog":"Selle pileti sulges {0}!", + "closeDm":"Teie pilet on meie serveris suletud!", + "deleteLog":"{0} on selle pileti kustutanud!", + "deleteDm":"Teie pilet on meie serverist kustutatud!", + "reopenLog":"{0} on selle pileti uuesti avanud!", + "reopenDm":"Teie pilet on meie serveris uuesti avatud!", + "claimLog":"Selle pileti on nõudnud {0}!", + "claimDm":"Teie pilet on meie serveris välja nõutud!", + "unclaimLog":"{0} on selle pileti tagasi võtnud!", + "unclaimDm":"Teie pilet on meie serveris välja võtmata!", + "pinLog":"Selle pileti on kinnitanud {0}!", + "pinDm":"Teie pilet on kinnitatud meie serverisse!", + "unpinLog":"{0} on selle pileti vabastanud!", + "unpinDm":"Teie pilet on meie serveris vabastatud!", + "renameLog":"{1} on selle pileti ümber nimetanud piletiks {0}!", + "renameDm":"Teie pilet on meie serveris ümber nimetatud {0}-ks!", + "moveLog":"{1} on selle pileti teisaldanud asukohta {0}!", + "moveDm":"Teie pilet on teisaldatud meie serverisse {0}!", + "addLog":"{1} on sellele piletile lisanud {0}!", + "addDm":"{0} lisati teie piletile meie serveris!", + "removeLog":"Kasutaja {1} eemaldas sellelt piletilt {0}!", + "removeDm":"{0} on teie piletist meie serveris eemaldatud!", + + "blacklistAddLog":"{1} lisas kasutaja {0} musta nimekirja!", + "blacklistRemoveLog":"Kasutaja {1} eemaldas kasutaja {0} mustast nimekirjast!", + "blacklistAddDm":"Olete meie serveris mustas nimekirjas!\nNüüdsest ei saa te piletit luua!", + "blacklistRemoveDm":"Teid on meie serveri mustast nimekirjast eemaldatud!\nNüüd saate uuesti pileteid luua!", + "clearLog":"{1} on kustutanud {0} piletit!" + } + }, + "transcripts":{ + "success":{ + "visit":"Külastage Transkriptsiooni", + "ready":"Transkriptsioon loodud", + "textFileDescription":"See on kustutatud pileti teksti ärakiri!", + "htmlProgress":"Palun oodake, kuni seda html-i ärakirja töödeldakse...", + + "createdChannel":"Serveris on loodud uus {0} ärakiri!", + "createdCreator":"Ühe teie pileti jaoks on loodud uus {0} ärakiri!", + "createdParticipant":"Ühes teie osalenud piletis on loodud uus {0} ärakiri!", + "createdActiveAdmin":"Ühes piletis, milles osalesite administraatorina, on loodud uus {0} ärakiri!", + "createdEveryAdmin":"Ühes piletis, mille administraator olite, on loodud uus {0} ärakiri!", + "createdOther":"Uus {0} ärakiri on loodud!" + }, + "errors":{ + "retry":"Proovi uuesti", + "continue":"Kustuta ilma ärakirjata", + "backup":"Loo varukoopia ärakirjast", + "error":"Midagi läks ärakirja loomisel valesti.\nMida sa teha tahaksid?\n\nSeda piletit ei kustutata enne, kui klõpsate ühel neist nuppudest." + } + }, + "errors":{ + "titles":{ + "internalError":"Sisemine viga", + "optionMissing":"Käsuvalik puudub", + "optionInvalid":"Käsuvalik on kehtetu", + "unknownCommand":"Tundmatu käsk", + "noPermissions":"Lubasid pole", + "unknownTicket":"Tundmatu pilet", + "deprecatedTicket":"Aegunud pilet", + "unknownOption":"Tundmatu valik", + "unknownPanel":"Tundmatu paneel", + "notInGuild":"Pole serveris", + "channelRename":"Kanalit ei saa ümber nimetada", + "busy":"Pilet on kinni" + }, + "descriptions":{ + "askForInfo":"Lisateabe saamiseks võtke ühendust selle roboti omanikuga!", + "askForInfoResolve":"Kui probleem mõne katsega ei lahene, võtke ühendust selle roboti omanikuga.", + "internalError":"Sellele {0}-le vastamine ebaõnnestus sisemise vea tõttu!", + "optionMissing":"Selles käsus puudub nõutav parameeter!", + "optionInvalid":"Selle käsu parameeter on kehtetu!", + "optionInvalidChoose":"Valige vahel", + "unknownCommand":"Lisateabe saamiseks külastage abimenüüd!", + "noPermissions":"Teil ei ole lubatud seda {0} kasutada!", + "noPermissionsList":"Nõutavad load: (üks neist)", + "noPermissionsCooldown":"Teil ei ole lubatud seda {0} kasutada, kuna teil on jahtumine!", + "noPermissionsBlacklist":"Teil ei ole lubatud seda {0} kasutada, kuna olete lisatud musta nimekirja!", + "noPermissionsLimitGlobal":"Teil ei ole lubatud piletit luua, kuna server saavutas maksimaalse piletite limiidi!", + "noPermissionsLimitGlobalUser":"Teil ei ole lubatud piletit luua, kuna olete täis piletite maksimumlimiiti!", + "noPermissionsLimitOption":"Teil ei ole lubatud piletit luua, kuna server saavutas selle valiku maksimaalse piletite limiidi!", + "noPermissionsLimitOptionUser":"Teil ei ole lubatud piletit luua, kuna olete saavutanud selle valiku maksimaalse piletite limiidi!", + "unknownTicket":"Proovige seda käsku kehtiva piletiga uuesti!", + "deprecatedTicket":"Praegune kanal ei ole kehtiv pilet! See võis olla pilet vanast Open Ticketi versioonist!", + "notInGuild":"See {0} ei tööta DM-is! Palun proovi uuesti serveris!", + "channelRename":"Ebakõlaliste kiiruspiirangute tõttu on robotil praegu võimatu kanalit ümber nimetada. Kui robotit ei taaskäivitata, nimetatakse kanal 10 minuti jooksul automaatselt ümber.", + "channelRenameSource":"Selle vea allikas on: {0}", + "busy":"Seda {0} ei saa kasutada!\nPiletit töötleb praegu bot.\n\nPalun proovige mõne sekundi pärast uuesti!" + }, + "optionInvalidReasons":{ + "stringRegex":"Väärtus ei vasta mustrile!", + "stringMinLength":"Väärtus peab olema vähemalt {0} tähemärki!", + "stringMaxLength":"Väärtus võib olla kuni {0} tähemärki!", + "numberInvalid":"Vale number!", + "numberMin":"Number peab olema vähemalt {0}!", + "numberMax":"Arv võib olla kuni {0}!", + "numberDecimal":"Arv ei tohi olla kümnendkoht!", + "numberNegative":"Arv ei tohi olla negatiivne!", + "numberPositive":"Arv ei tohi olla positiivne!", + "numberZero":"Arv ei tohi olla null!", + "channelNotFound":"Kanalit ei leitud!", + "userNotFound":"Kasutajat ei leitud!", + "roleNotFound":"Rolli ei leitud!", + "memberNotFound":"Kasutajat ei leitud!", + "mentionableNotFound":"Kasutajat või rolli ei leitud!", + "channelType":"Sobimatu kanali tüüp!", + "notInGuild":"See valik nõuab serveris viibimist!" + }, + "permissions":{ + "developer":"Peate olema roboti arendaja.", + "owner":"Peate olema serveri omanik.", + "admin":"Peate olema serveri administraator.", + "moderator":"Peate olema moderaator.", + "support":"Peate olema tugimeeskonnas.", + "member":"You need to be a member.", + "discord-administrator":"Teil peab olema ADMINISTRATORI luba." + }, + "actionInvalid":{ + "close":"Pilet on juba suletud!", + "reopen":"Pilet pole veel suletud!", + "claim":"Pilet on juba ostetud!", + "unclaim":"Piletit pole veel ostetud!", + "pin":"Pilet on juba kinni pandud!", + "unpin":"Pilet pole veel kinnitatud!", + "add":"Sellel kasutajal on juba juurdepääs piletile!", + "remove":"Seda kasutajat ei saa piletist eemaldada!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Pilet", + "tickets":"Piletid", + "reason":"Põhjus", + "creator":"Looja", + "remaining":"Järelejäänud aeg", + "added":"Lisatud", + "removed":"Eemaldatud", + "filter":"Filter", + "claimedBy":"Nõude esitas {0}", + "method":"Meetod", + "type":"Tüüp", + "blacklisted":"Mustas nimekirjas", + "panel":"Paneel", + "command":"Käsk", + "system":"Süsteem", + "true":"Tõsi", + "false":"Vale", + "syntax":"Süntaks", + "originalName":"Algne nimi", + "newName":"Uus nimi", + "until":"Kuni", + "validOptions":"Kehtivad valikud", + "validPanels":"Kehtivad paneelid", + "autoclose":"Automaatne sulgemine", + "autodelete":"Automaatne kustutamine", + "startupDate":"Käivitamise kuupäev", + "version":"Versioon", + "name":"Nimi", + "role":"Roll", + "status":"Olek", + "claimed":"Nõutud", + "pinned":"Kinnitatud", + "creationDate":"Loomise kuupäev" + }, + "lowercase":{ + "text":"tekst", + "html":"html", + "command":"käsk", + "modal":"modaalne", + "button":"nuppu", + "dropdown":"rippmenüüst", + "method":"meetod" + } + }, + "commands":{ + "reason":"Määrake valikuline põhjus, mis on logides nähtav.", + "help":"Hankige kõigi saadaolevate käskude loend.", + "panel":"Looge sõnum rippmenüü või nuppudega (pileti loomiseks).", + "panelId":"Selle paneeli identifikaator, mille soovite luua.", + "panelAutoUpdate":"Kas soovite seda paneeli redigeerimisel automaatselt värskendada?", + "ticket":"Looge pilet koheselt.", + "ticketId":"Pileti identifikaator, mille soovite luua.", + "close":"Sulgege pilet.", + "delete":"Kustuta pilet.", + "deleteNoTranscript":"Kustutage see pilet ilma ärakirja loomata.", + "reopen":"Avage pilet uuesti.", + "claim":"Nõudke pilet.", + "claimUser":"Hankige see pilet enda asemel kellelegi teisele.", + "unclaim":"Tühista pilet.", + "pin":"Kinnitage pilet.", + "unpin":"Vabastage pilet.", + "move":"Liigutage pilet.", + "moveId":"Selle valiku identifikaator, millele soovite liikuda.", + "rename":"Nimetage pilet ümber.", + "renameName":"Selle pileti uus nimi.", + "add":"Lisage piletile kasutaja.", + "addUser":"Lisatav kasutaja.", + "remove":"Kasutaja eemaldamine piletist.", + "removeUser":"Eemaldatav kasutaja.", + "blacklist":"Hallake piletite musta nimekirja.", + "blacklistView":"Vaadake praeguse musta nimekirja loendit.", + "blacklistAdd":"Lisage kasutaja musta nimekirja.", + "blacklistRemove":"Eemaldage kasutaja mustast nimekirjast.", + "blacklistGet":"Hankige üksikasjad musta nimekirja kantud kasutajalt.", + "blacklistGetUser":"Kasutaja, kellelt üksikasju saada.", + "stats":"Vaadake boti, liikme või pileti statistikat.", + "statsReset":"Lähtestage kogu roboti statistika (ja alustage loendamist nullist).", + "statsGlobal":"Vaadake globaalset statistikat.", + "statsUser":"Vaadake serveris oleva kasutaja statistikat.", + "statsUserUser":"Kasutaja vaatamiseks.", + "statsTicket":"Vaadake serveris pileti statistikat.", + "statsTicketTicket":"Pilet vaatamiseks.", + "clear":"Kustutage mitu piletit korraga.", + "clearFilter":"Piletite puhastamise filter.", + "clearFilters":{ + "all":"Kõik", + "open":"Avatud", + "close":"Suletud", + "claim":"Nõutud", + "unclaim":"Nõudmata", + "pin":"Kinnitatud", + "unpin":"Vabastatud", + "autoclose":"Automaatselt suletud" + }, + "autoclose":"Hallake piletis automaatset sulgemist.", + "autocloseDisable":"Keela sellel piletil automaatne sulgemine.", + "autocloseEnable":"Luba sellel piletil automaatne sulgemine.", + "autocloseEnableTime":"Selle pileti sulgemiseks peab olema passiivne tundide arv.", + "autodelete":"Automaatse kustutamise haldamine piletis.", + "autodeleteDisable":"Keela sellel piletil automaatne kustutamine.", + "autodeleteEnable":"Luba sellel piletil automaatne kustutamine.", + "autodeleteEnableTime":"Päevade arv, mille jooksul see pilet peab olema selle kustutamiseks passiivne." + }, + "helpMenu":{ + "help":"Hankige kõigi saadaolevate käskude loend.", + "ticket":"Looge pilet koheselt.", + "close":"Sulgege pilet, see keelab sellele kanalile kirjutamise.", + "delete":"Kustutage pilet, kui see on lubatud, loob see ärakirja.", + "reopen":"Avage pilet uuesti, see võimaldab sellele kanalile uuesti kirjutada.", + "pin":"Kinnitage pilet. See liigutab pileti ülaossa ja lisab nimele emoij '📌'", + "unpin":"\nVabastage pilet. Pilet jääb oma positsioonile, kuid kaotab emoij '📌'", + "move":"Liigutage pilet. See muudab selle pileti tüüpi.", + "rename":"Nimetage pilet ümber. See muudab selle pileti kanali nime.", + "claim":"Nõudke pilet. Sellega saate oma meeskonnale teada anda, et tegelete selle piletiga.", + "unclaim":"Tühista pilet. Sellega saate oma meeskonnale teada anda, et see pilet on taas tasuta.", + "add":"Lisage piletile kasutaja. See võimaldab kasutajal sellel piletil lugeda ja kirjutada.", + "remove":"Kasutaja eemaldamine piletist. See eemaldab selle pileti kasutajalt lugemis- ja kirjutamisvõimaluse.", + "panel":"Looge sõnum rippmenüü või nuppudega (pileti loomiseks).", + "blacklistView":"Vaadake praeguse musta nimekirja loendit.", + "blacklistAdd":"Lisage kasutaja musta nimekirja.", + "blacklistRemove":"Eemaldage kasutaja mustast nimekirjast.", + "blacklistGet":"Hankige üksikasjad musta nimekirja kantud kasutajalt.", + "statsGlobal":"Vaadake globaalset statistikat.", + "statsTicket":"Vaadake serveris pileti statistikat.", + "statsUser":"Vaadake serveris oleva kasutaja statistikat.", + "statsReset":"Lähtestage kogu roboti statistika (ja alustage loendamist nullist).", + "autocloseDisable":"Keela sellel piletil automaatne sulgemine.", + "autocloseEnable":"Luba sellel piletil automaatne sulgemine.", + "autodeleteDisable":"Keela sellel piletil automaatne kustutamine.", + "autodeleteEnable":"Luba sellel piletil automaatne kustutamine." + }, + "stats":{ + "scopes":{ + "global":"Globaalne statistika", + "system":"Süsteemi statistika", + "user":"Kasutaja statistika", + "ticket":"Piletistatistika", + "participants":"Osalejad" + }, + "properties":{ + "ticketsCreated":"Pileteid loodud", + "ticketsClosed":"Pileteid suletud", + "ticketsDeleted":"Pileteid kustutatud", + "ticketsReopened":"Pileteid taasavatud", + "ticketsAutoclosed":"Pileteid suletud", + "ticketsClaimed":"Pileteid välja nõutud", + "ticketsPinned":"Pileteid kinnitatud", + "ticketsMoved":"Pileteid teisaldatud", + "usersBlacklisted":"Kasutajaid mustas nimekirjas", + "transcriptsCreated":"Loodud ärakirjad" + } + } +}sss From 3fa72e07d83bcdcc5eeab83f7c4756b2e25e334e Mon Sep 17 00:00:00 2001 From: NotMega <135043684+iamnotmega@users.noreply.github.com> Date: Sat, 26 Oct 2024 19:42:01 +0300 Subject: [PATCH 044/157] Create finnish.json --- languages/finnish.json | 478 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 478 insertions(+) create mode 100644 languages/finnish.json diff --git a/languages/finnish.json b/languages/finnish.json new file mode 100644 index 0000000..b4e6374 --- /dev/null +++ b/languages/finnish.json @@ -0,0 +1,478 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translators":["iamnotmega"], + "lastedited":"21/10/2024", + "language":"Finnish", + "automated":true + }, + "checker":{ + "system":{ + "typeError":"[VIRHE]", + "headerOpenTicket":"AVAA LIPPU", + "typeWarning":"[VAROITUS]", + "typeInfo":"[TIEDOT]", + "headerConfigChecker":"ASETUKSEN TARKISTAJA", + "headerDescription":"tarkista asetustiedostoissasi virheitä!", + "footerError":"botti ei käynnisty ennen kuin kaikki {0} on korjattu!", + "footerWarning":"on suositeltavaa korjata kaikki {0} ennen aloittamista!", + "footerSupport":"TUKI: {0} - DOCS: {1}", + "compactInformation":"käytä {0} saadaksesi lisätietoja!", + "dataPath":"polku", + "dataDocs":"asiakirjoja", + "dataMessages":"viesti" + }, + "messages":{ + "stringTooShort":"Tämä merkkijono ei voi olla lyhyempi kuin {0} merkkiä!", + "stringTooLong":"Tämä merkkijono ei voi olla pidempi kuin {0} merkkiä!", + "stringLengthInvalid":"Tämän merkkijonon on oltava {0} merkkiä pitkä!", + "stringStartsWith":"Tämän merkkijonon on alettava kirjaimella {0}!", + "stringEndsWith":"Tämän merkkijonon tulee päättyä {0}!", + "stringContains":"Tämän merkkijonon täytyy sisältää {0}!", + "stringChoices":"Tämä merkkijono voi olla vain yksi seuraavista arvoista: {0}!", + "stringRegex":"Tämä merkkijono on virheellinen!", + + "numberTooShort":"Tämä numero ei voi olla lyhyempi kuin {0} merkkiä!", + "numberTooLong":"Tämä numero ei voi olla pidempi kuin {0} merkkiä!", + "numberLengthInvalid":"Tämän numeron on oltava {0} merkkiä pitkä!", + "numberTooSmall":"Tämän numeron on oltava vähintään {0}!", + "numberTooLarge":"Tämän numeron on oltava enintään {0}!", + "numberNotEqual":"Tämän numeron on oltava {0}!", + "numberStep":"Tämän luvun on oltava luvun {0} kerrannainen!", + "numberStepOffset":"Tämän luvun on oltava luvun {0} jaollinen, joka alkaa numerolla {1}!", + "numberStartsWith":"Tämän numeron täytyy alkaa numerolla {0}!", + "numberEndsWith":"Tämän numeron lopussa on oltava {0}!", + "numberContains":"Tämän numeron on sisällettävä {0}!", + "numberChoices":"Tämä numero voi olla vain yksi seuraavista arvoista: {0}!", + "numberFloat":"Tämä luku ei voi olla desimaali!", + "numberNegative":"Tämä luku ei voi olla negatiivinen!", + "numberPositive":"Tämä luku ei voi olla positiivinen!", + "numberZero":"Tämä luku ei voi olla nolla!", + + "booleanTrue":"Tämä boolean ei voi olla totta!", + "booleanFalse":"Tämä boolean ei voi olla väärä!", + + "arrayEmptyDisabled":"Tämä taulukko ei saa olla tyhjä!", + "arrayEmptyRequired":"Tämän taulukon on oltava tyhjä!", + "arrayTooShort":"Tämän taulukon pituuden on oltava vähintään {0}!", + "arrayTooLong":"Tämän taulukon pituus saa olla enintään {0}!", + "arrayLengthInvalid":"Tämän taulukon pituuden on oltava {0}!", + "arrayInvalidTypes":"Tämä matriisi voi sisältää vain seuraavat tyypit: {0}!", + "arrayDouble":"Tämä matriisi ei salli samaa arvoa kahdesti!", + + "discordInvalidId":"Tämä on virheellinen discord {0} -tunnus!", + "discordInvalidIdOptions":"Tämä on virheellinen discord {0} -tunnus! Voit myös käyttää jotakin seuraavista: {1}!", + "discordInvalidToken":"Tämä on virheellinen discord tunnus (syntaktisesti)!", + "colorInvalid":"Tämä on virheellinen kuusioväri!", + "emojiTooShort":"Tässä merkkijonossa on oltava vähintään {0} emojia!", + "emojiTooLong":"Tässä merkkijonossa saa olla enintään {0} emojia!", + "emojiCustom":"Tämä emoji ei voi olla mukautettu emoji!", + "emojiInvalid":"Tämä on virheellinen emoji!", + "urlInvalid":"Tämä URL-osoite on virheellinen!", + "urlInvalidHttp":"Tämä URL-osoite voi käyttää vain https://-protokollaa!", + "urlInvalidProtocol":"Tämä URL-osoite voi käyttää vain http://- ja https://-protokollia!", + "urlInvalidHostname":"Tällä URL-osoitteella on kielletty isäntänimi!", + "urlInvalidExtension":"Tässä URL-osoitteessa on virheellinen laajennus! Valitse seuraavista: {0}!", + "urlInvalidPath":"Tällä URL-osoitteella on virheellinen polku!", + "idNotUnique":"Tämä tunnus ei ole ainutlaatuinen, käytä sen sijaan toista tunnusta!", + "idNonExistent":"Tunnusta {0} ei ole olemassa!", + + "invalidType":"Tämän ominaisuuden on oltava tyyppiä: {0}!", + "propertyMissing":"Ominaisuus {0} puuttuu tästä objektista!", + "propertyOptional":"Ominaisuus {0} on valinnainen tässä objektissa!", + "objectDisabled":"Tämä objekti on poistettu käytöstä, ota se käyttöön käyttämällä {0}!", + "nullInvalid":"Tämä omaisuus ei voi olla tyhjä!", + "switchInvalidType":"Tämän on oltava jokin seuraavista: {0}!", + "objectSwitchInvalid":"Tämän objektin on oltava jokin seuraavista tyypeistä: {0}!", + + "invalidLanguage":"Tämä on virheellinen kieli!", + "invalidButton":"Tässä painikkeessa on oltava vähintään {0} tai {1}!", + "unusedOption":"Vaihtoehtoa {0} ei käytetä missään!", + "unusedQuestion":"Kysymystä {0} ei käytetä missään!", + "dropdownOption":"Paneeli, jossa pudotusvalikko on käytössä, voi sisältää vain \"lippu\"-tyyppisiä vaihtoehtoja!" + } + }, + "actions":{ + "buttons":{ + "create":"Vieraile Ticketissä", + "close":"Sulje lippu", + "delete":"Poista lippu", + "reopen":"Avaa lippu uudelleen", + "claim":"Lunasta lippu", + "unclaim":"Peruuta lippu", + "pin":"Pin Lippu", + "unpin":"Irrota lippu", + "clear":"Poista liput", + "helpSwitchSlash":"Näytä Slash-komennot", + "helpSwitchText":"Näytä tekstikomennot", + "helpPage":"Sivu {0}", + "withReason":"Syyllä", + "withoutTranscript":"Ilman transkriptiota" + }, + "titles":{ + "created":"Lippu luotu", + "close":"Lippu suljettu", + "delete":"Lippu poistettu", + "reopen":"Lippu avattu uudelleen", + "claim":"Lippu lunastettu", + "unclaim":"Lippu lunastamaton", + "pin":"Lippu kiinnitetty", + "unpin":"Lippu irrotettu", + "rename":"Lippu nimetty uudelleen", + "move":"Lippu siirretty", + "add":"Lipun käyttäjä lisätty", + "remove":"Lipun käyttäjä poistettu", + + "help":"Käytettävissä olevat komennot", + "statsReset":"Nollaa tilastot", + "blacklistAdd":"Käyttäjä mustalla listalla", + "blacklistRemove":"Käyttäjä vapautettu", + "blacklistGet":"Mustalla listalla oleva käyttäjä", + "blacklistView":"Nykyinen musta lista", + "blacklistAddDm":"Lisätty mustalle listalle", + "blacklistRemoveDm":"Poistettu mustalta listalta", + "clear":"Liput tyhjennetty", + "roles":"Roolit päivitetty", + + "autoclose":"Lippu suljettu automaattisesti", + "autocloseEnabled":"Automaattinen sulkeminen käytössä", + "autocloseDisabled":"Automaattinen sulkeminen pois käytöstä", + "autodelete":"Lippu poistettu automaattisesti", + "autodeleteEnabled":"Automaattinen poisto käytössä", + "autodeleteDisabled":"Automaattinen poisto poissa käytöstä" + }, + "descriptions":{ + "create":"Lippusi on luotu. Napsauta alla olevaa painiketta päästäksesi siihen!", + "close":"Lippu on suljettu onnistuneesti!", + "delete":"Lippu on poistettu onnistuneesti!", + "reopen":"Lippu on avattu uudelleen onnistuneesti!", + "claim":"Lippu on lunastettu onnistuneesti!", + "unclaim":"Lippu on lunastettu onnistuneesti!", + "pin":"Lippu on kiinnitetty onnistuneesti!", + "unpin":"Lippu on irrotettu onnistuneesti!", + "rename":"Lippu on nimetty uudelleen muotoon {0}!", + "move":"Lippu on siirretty kohteeseen {0} onnistuneesti!", + "add":"{0} on lisätty lippuun onnistuneesti!", + "remove":"{0} on poistettu lipusta onnistuneesti!", + + "helpExplanation":"`` => pakollinen parametri\n`[nimi]` => valinnainen parametri", + "statsReset":"Bottitilastot on nollattu onnistuneesti!", + "statsError":"Lipputilastoja ei voi tarkastella!\n{0} ei ole lippu!", + "blacklistAdd":"{0} on lisätty mustalle listalle onnistuneesti!", + "blacklistRemove":"{0} on julkaistu onnistuneesti!", + "blacklistGetSuccess":"{0} on tällä hetkellä mustalla listalla!", + "blacklistGetEmpty":"{0} ei ole tällä hetkellä mustalla listalla!", + "blacklistViewEmpty":"Ketään ei ole vielä mustalla listalla!", + "blacklistViewTip":"Käytä \"/blacklist add\" lisätäksesi käyttäjän mustalle listalle!", + "clearVerify":"Haluatko varmasti poistaa useita lippuja? Tätä toimintoa ei voi kumota!", + "clearReady":"{0} lippua on poistettu onnistuneesti!", + "rolesEmpty":"Rooleja ei ole päivitetty!", + + "autocloseLeave":"Tämä lippu on suljettu automaattisesti, koska luoja poistui palvelimelta!", + "autocloseTimeout":"Tämä lippu on suljettu automaattisesti, koska se on ollut passiivinen yli `{0}h`!", + "autodeleteLeave":"Tämä lippu on poistettu automaattisesti, koska sisällöntuottaja poistui palvelimelta!", + "autodeleteTimeout":"Tämä lippu on poistettu automaattisesti, koska se on ollut passiivinen yli `{0} päivää`!", + "autocloseEnabled":"Automaattinen sulkeminen on otettu käyttöön tässä lipussa! Se suljetaan, kun se on epäaktiivinen yli `{0}h'!", + "autocloseDisabled":"Automaattinen sulkeminen on poistettu käytöstä tässä lipussa! Se ei enää sulkeudu automaattisesti!", + "autodeleteEnabled":"Automaattinen poisto on otettu käyttöön tässä lipussa! Se poistetaan, kun se on passiivinen yli `{0} päivään`!", + "autodeleteDisabled":"Automaattinen poisto on poistettu käytöstä tässä lipussa! Sitä ei enää poisteta automaattisesti!", + + "ticketMessageLimit":"Voit luoda vain {0} lippua samanaikaisesti!", + "ticketMessageAutoclose":"Tämä lippu suljetaan automaattisesti, kun se ei ole aktiivinen {0} tuntia!", + "ticketMessageAutodelete":"Tämä lippu poistetaan automaattisesti, kun se ei ole aktiivinen {0} päivään!", + "panelReady":"Löydät paneelin alta! Tämä viesti voidaan nyt poistaa!" + }, + "modal":{ + "closePlaceholder":"Miksi suljit tämän lipun?", + "deletePlaceholder":"Miksi poistit tämän lipun?", + "reopenPlaceholder":"Miksi avasit tämän lipun uudelleen?", + "claimPlaceholder":"Miksi lunasit tämän lipun?", + "unclaimPlaceholder":"Miksi peruutit tämän lipun?", + "pinPlaceholder":"Miksi kiinnitit tämän lipun?", + "unpinPlaceholder":"Miksi irrotit tämän lipun?" + }, + "logs":{ + "createLog":"{0} loi uuden lipun!", + "closeLog":"Tämän lipun on sulkenut {0}!", + "closeDm":"Lippusi on suljettu palvelimellamme!", + "deleteLog":"{0} on poistanut tämän lipun!", + "deleteDm":"Lippusi on poistettu palvelimeltamme!", + "reopenLog":"{0} on avannut tämän lipun uudelleen!", + "reopenDm":"Lippusi on avattu uudelleen palvelimellamme!", + "claimLog":"{0} on lunastanut tämän lipun!", + "claimDm":"Lippusi on lunastettu palvelimellamme!", + "unclaimLog":"{0} ei ole lunastanut tätä lippua!", + "unclaimDm":"Lippuasi on lunastettu palvelimellamme!", + "pinLog":"{0} on kiinnittänyt tämän lipun!", + "pinDm":"Lippusi on kiinnitetty palvelimellemme!", + "unpinLog":"{0} on irrottanut tämän lipun!", + "unpinDm":"Lippusi on irrotettu palvelimeltamme!", + "renameLog":"{1} on nimennyt tämän lipun uudelleen nimellä {0}!", + "renameDm":"Lippusi nimeksi on muutettu palvelimellamme {0}!", + "moveLog":"{1} on siirtänyt tämän lipun paikkaan {0}!", + "moveDm":"Lippusi on siirretty palvelimellamme osoitteeseen {0}!", + "addLog":"{1} on lisännyt {0} tähän lippuun!", + "addDm":"{0} on lisätty lippuusi palvelimellamme!", + "removeLog":"{1} on poistanut {0} tästä lipusta!", + "removeDm":"{0} on poistettu lipustasi palvelimellamme!", + + "blacklistAddLog":"{1} lisäsi käyttäjän {0} mustalle listalle!", + "blacklistRemoveLog":"{1} poisti käyttäjän {0} mustalta listalta!", + "blacklistAddDm":"Sinut on mustalla listalla palvelimellamme! Tästä eteenpäin et voi luoda lippua!", + "blacklistRemoveDm":"Sinut on poistettu palvelimemme mustalta listalta! Nyt voit luoda lippuja uudelleen!", + "clearLog":"{1} on poistanut {0} lippua!" + } + }, + "transcripts":{ + "success":{ + "visit":"Vieraile Transcriptissä", + "ready":"Transkriptio luotu", + "textFileDescription":"Tämä on poistetun lipun tekstikopio!", + "htmlProgress":"Odota, kun tätä html-transkriptiota käsitellään...", + + "createdChannel":"Uusi {0}-transkriptio on luotu palvelimelle!", + "createdCreator":"Yhdelle lipullesi on luotu uusi transkriptio {0}!", + "createdParticipant":"Uusi {0}-transkriptio on luotu yhteen lipuista, joihin osallistuit!", + "createdActiveAdmin":"Yhdessä lipussa, johon osallistuit järjestelmänvalvojana, on luotu uusi transkriptio {0}!", + "createdEveryAdmin":"Uusi {0}-transkriptio on luotu yhteen lipuista, joissa olit järjestelmänvalvoja!", + "createdOther":"Uusi transkriptio {0} on luotu!" + }, + "errors":{ + "retry":"Yritä uudelleen", + "continue":"Poista ilman transkriptiota", + "backup":"Luo varmuuskopio", + "error":"Jotain meni pieleen, kun yritettiin luoda transkriptiota. Mitä haluaisit tehdä? Tätä lippua ei poisteta, ennen kuin napsautat jotakin näistä painikkeista. " + } + }, + "errors":{ + "titles":{ + "internalError":"Sisäinen virhe", + "optionMissing":"Komentovaihtoehto puuttuu", + "optionInvalid":"Komentovaihtoehto ei kelpaa", + "unknownCommand":"Tuntematon komento", + "noPermissions":"Ei käyttöoikeuksia", + "unknownTicket":"Tuntematon lippu", + "deprecatedTicket":"Käytöstä poistettu lippu", + "unknownOption":"Tuntematon vaihtoehto", + "unknownPanel":"Tuntematon paneeli", + "notInGuild":"Ei Palvelimessa", + "channelRename":"Kanavaa ei voi nimetä uudelleen", + "busy":"Lippu on varattu" + }, + "descriptions":{ + "askForInfo":"Ota yhteyttä tämän botin omistajaan saadaksesi lisätietoja!", + "askForInfoResolve":"Ota yhteyttä tämän botin omistajaan, jos ongelma ei ratkea muutaman yrityksen jälkeen.", + "internalError":"Tähän viestiin {0} ei voi vastata sisäisen virheen vuoksi!", + "optionMissing":"Tästä komennosta puuttuu pakollinen parametri!", + "optionInvalid":"Tämän komennon parametri on virheellinen!", + "optionInvalidChoose":"Valitse väliltä", + "unknownCommand":"Kokeile lisätietoja ohjevalikosta!", + "noPermissions":"Sinulla ei ole lupaa käyttää tätä {0}!", + "noPermissionsList":"Vaaditut luvat: (yksi niistä)", + "noPermissionsCooldown":"Sinulla ei ole oikeutta käyttää tätä {0}-palvelua, koska sinulla on jäähdytys!", + "noPermissionsBlacklist":"Sinulla ei ole oikeutta käyttää tätä {0}, koska sinut on mustalla listalla!", + "noPermissionsLimitGlobal":"Et voi luoda lippua, koska palvelin saavutti lippujen enimmäisrajan!", + "noPermissionsLimitGlobalUser":"Et voi luoda lippua, koska saavutit lippujen enimmäisrajan!", + "noPermissionsLimitOption":"Et voi luoda lippua, koska palvelin saavutti tämän vaihtoehdon lippujen enimmäisrajan!", + "noPermissionsLimitOptionUser":"Et voi luoda lippua, koska saavutit tämän vaihtoehdon lippujen enimmäisrajan!", + "unknownTicket":"Kokeile tätä komentoa uudelleen voimassa olevalla lipulla!", + "deprecatedTicket":"Nykyinen kanava ei ole kelvollinen lippu! Se saattoi olla lippu vanhasta Open Ticket -versiosta!", + "notInGuild":"Tämä {0} ei toimi DM:ssä! Ole hyvä ja yritä uudelleen palvelimella!", + "channelRename":"Discordin nopeusrajoitusten vuoksi botin on tällä hetkellä mahdotonta nimetä kanavaa uudelleen. Kanava nimetään automaattisesti uudelleen 10 minuutin kuluttua, jos bottia ei käynnistetä uudelleen.", + "channelRenameSource":"Tämän virheen lähde on: {0}", + "busy":"Tätä {0} ei voi käyttää! Botti käsittelee lippua parhaillaan. Yritä uudelleen muutaman sekunnin kuluttua!" + }, + "optionInvalidReasons":{ + "stringRegex":"Arvo ei vastaa mallia!", + "stringMinLength":"Arvon on oltava vähintään {0} merkkiä!", + "stringMaxLength":"Arvo saa olla enintään {0} merkkiä!", + "numberInvalid":"Virheellinen numero!", + "numberMin":"Numeron on oltava vähintään {0}!", + "numberMax":"Numeron on oltava enintään {0}!", + "numberDecimal":"Numero ei saa olla desimaali!", + "numberNegative":"Numero ei saa olla negatiivinen!", + "numberPositive":"Numero ei saa olla positiivinen!", + "numberZero":"Numero ei saa olla nolla!", + "channelNotFound":"Kanavaa ei löydy!", + "userNotFound":"Käyttäjää ei löydy!", + "roleNotFound":"Roolia ei löydy!", + "memberNotFound":"Käyttäjää ei löydy!", + "mentionableNotFound":"Käyttäjää tai roolia ei löydy!", + "channelType":"Virheellinen kanavatyyppi!", + "notInGuild":"Tämä vaihtoehto edellyttää, että olet palvelimella!" + }, + "permissions":{ + "developer":"Sinun on oltava botin kehittäjä.", + "owner":"Sinun on oltava palvelimen omistaja.", + "admin":"Sinun tulee olla palvelimen järjestelmänvalvoja.", + "moderator":"Sinun täytyy olla moderaattori.", + "support":"Sinun on kuuluttava tukitiimiin.", + "member":"Sinun täytyy olla jäsen.", + "discord-administrator":"Sinulla on oltava ADMINISTRATOR-käyttöoikeus." + }, + "actionInvalid":{ + "close":"Lippu on jo suljettu!", + "reopen":"Lippu ei ole vielä suljettu!", + "claim":"Lippu on jo lunastettu!", + "unclaim":"Lippua ei ole vielä lunastettu!", + "pin":"Lippu on jo kiinnitetty!", + "unpin":"Lippua ei ole vielä kiinnitetty!", + "add":"Tämä käyttäjä voi jo käyttää lippua!", + "remove":"Tätä käyttäjää ei voi poistaa lipusta!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Lippu", + "tickets":"Liput", + "reason":"Syy", + "creator":"Luoja", + "remaining":"Aikaa jäljellä", + "added":"Lisätty", + "removed":"Poistettu", + "filter":"Suodattaa", + "claimedBy":"Vaatimuksen tekijä: {0}", + "method":"Menetelmä", + "type":"Tyyppi", + "blacklisted":"Mustalla listalla", + "panel":"Paneeli", + "command":"Komento", + "system":"Järjestelmä", + "true":"Totta", + "false":"Väärä", + "syntax":"Syntaksi", + "originalName":"Alkuperäinen Nimi", + "newName":"Alkuperäinen Nimi", + "until":"Kunnes", + "validOptions":"Kelvolliset vaihtoehdot", + "validPanels":"Kelvolliset paneelit", + "autoclose":"Automaattinen sulkeminen", + "autodelete":"Automaattinen poisto", + "startupDate":"Aloituspäivämäärä", + "version":"Versio", + "name":"Nimi", + "role":"Rooli", + "status":"Status", + "claimed":"Väitetty", + "pinned":"Kiinnitetty", + "creationDate":"Luontipäivämäärä" + }, + "lowercase":{ + "text":"teksti", + "html":"html", + "command":"komento", + "modal":"modaalinen", + "button":"-painiketta", + "dropdown":"pudotusvalikosta", + "method":"menetelmä" + } + }, + "commands":{ + "reason":"Määritä valinnainen syy, joka näkyy lokeissa.", + "help":"Hanki luettelo kaikista käytettävissä olevista komennoista.", + "panel":"Luo viesti avattavalla valikosta tai painikkeilla (lippujen luomista varten).", + "panelId":"Sen paneelin tunniste, jonka haluat luoda.", + "panelAutoUpdate":"Haluatko tämän paneelin päivittyvän automaattisesti, kun sitä muokataan?", + "ticket":"Luo lippu välittömästi.", + "ticketId":"Sen lipun tunniste, jonka haluat luoda.", + "close":"Sulje lippu.", + "delete":"Poista lippu.", + "deleteNoTranscript":"Poista tämä lippu luomatta transkriptiota.", + "reopen":"Avaa lippu uudelleen.", + "claim":"Lunasta lippu.", + "claimUser":"Lunasta tämä lippu jollekin muulle itsesi sijaan.", + "unclaim":"Peruuta lippu.", + "pin":"Kiinnitä lippu.", + "unpin":"Irrota lippu.", + "move":"Siirrä lippu.", + "moveId":"Sen vaihtoehdon tunniste, johon haluat siirtyä.", + "rename":"Nimeä lippu uudelleen.", + "renameName":"Tämän lipun uusi nimi.", + "add":"Lisää käyttäjä lippuun.", + "addUser":"Lisättävä käyttäjä.", + "remove":"Poista käyttäjä lipusta.", + "removeUser":"Poistettava käyttäjä.", + "blacklist":"Hallitse lippujen mustaa listaa.", + "blacklistView":"Näytä luettelo nykyisestä mustasta listasta.", + "blacklistAdd":"Lisää käyttäjä mustalle listalle.", + "blacklistRemove":"Poista käyttäjä mustalta listalta.", + "blacklistGet":"Hanki tiedot mustalla listalla olevalta käyttäjältä.", + "blacklistGetUser":"Käyttäjä, jolta saa tietoja.", + "stats":"Tarkastele botin, jäsenen tai lipun tilastoja.", + "statsReset":"Nollaa kaikki botin tilastot (ja aloita laskeminen nollasta).", + "statsGlobal":"Katso globaalit tilastot.", + "statsUser":"Tarkastele palvelimella olevan käyttäjän tilastoja.", + "statsUserUser":"Käyttäjä katsella.", + "statsTicket":"Tarkastele lipun tilastoja palvelimella.", + "statsTicketTicket":"Lippu katsottavaksi.", + "clear":"Poista useita lippuja samanaikaisesti.", + "clearFilter":"Lippujen tyhjennyssuodatin.", + "clearFilters":{ + "all":"Kaikki", + "open":"Avata", + "close":"Suljettu", + "claim":"Väitetty", + "unclaim":"Lunastamaton", + "pin":"Kiinnitetty", + "unpin":"Irrotettu", + "autoclose":"Automaattisuljettu" + }, + "autoclose":"Hallitse automaattista sulkemista lipussa.", + "autocloseDisable":"Poista automaattinen sulkeminen käytöstä tässä lipussa.", + "autocloseEnable":"Ota automaattinen sulkeminen käyttöön tässä lipussa.", + "autocloseEnableTime":"Tämän lipun on oltava passiivinen, jotta se voidaan sulkea.", + "autodelete":"Hallitse automaattista poistoa lipussa.", + "autodeleteDisable":"Poista automaattinen poisto käytöstä tässä lipussa.", + "autodeleteEnable":"Ota automaattinen poisto käyttöön tässä lipussa.", + "autodeleteEnableTime":"Kuinka monta päivää tämän lipun on oltava passiivinen, jotta se voidaan poistaa." + }, + "helpMenu":{ + "help":"Hanki luettelo kaikista käytettävissä olevista komennoista.", + "ticket":"Luo lippu välittömästi.", + "close":"Sulje lippu, tämä estää kirjoittamisen tälle kanavalle.", + "delete":"Poista lippu. Tämä luo transkription, kun se on käytössä.", + "reopen":"Avaa lippu uudelleen, tämä mahdollistaa kirjoittamisen uudelleen tälle kanavalle.", + "pin":"Kiinnitä lippu. Tämä siirtää lipun yläreunaan ja lisää nimeen emoijin '📌'.", + "unpin":"\nIrrota lippu. Lippu pysyy paikallaan, mutta menettää '📌' emoijin.", + "move":"Siirrä lippu. Tämä muuttaa tämän lipun tyyppiä.", + "rename":"Nimeä lippu uudelleen. Tämä muuttaa tämän lipun kanavan nimen.", + "claim":"Lunasta lippu. Tämän avulla voit ilmoittaa tiimillesi, että käsittelet tätä lippua.", + "unclaim":"Peruuta lippu. Tällä voit ilmoittaa joukkueellesi, että tämä lippu on jälleen ilmainen.", + "add":"Lisää käyttäjä lippuun. Tämä antaa käyttäjälle mahdollisuuden lukea ja kirjoittaa tähän lippuun.", + "remove":"Poista käyttäjä lipusta. Tämä poistaa tämän lipun käyttäjältä mahdollisuuden lukea ja kirjoittaa.", + "panel":"Luo viesti avattavalla valikosta tai painikkeilla (lippujen luomista varten).", + "blacklistView":"Näytä luettelo nykyisestä mustasta listasta.", + "blacklistAdd":"Lisää käyttäjä mustalle listalle.", + "blacklistRemove":"Poista käyttäjä mustalta listalta.", + "blacklistGet":"Hanki tiedot mustalla listalla olevalta käyttäjältä.", + "statsGlobal":"Katso globaalit tilastot.", + "statsTicket":"Tarkastele lipun tilastoja palvelimella.", + "statsUser":"Tarkastele palvelimella olevan käyttäjän tilastoja.", + "statsReset":"Nollaa kaikki botin tilastot (ja aloita laskeminen nollasta).", + "autocloseDisable":"Poista automaattinen sulkeminen käytöstä tässä lipussa.", + "autocloseEnable":"Ota automaattinen sulkeminen käyttöön tässä lipussa.", + "autodeleteDisable":"Poista automaattinen poisto käytöstä tässä lipussa.", + "autodeleteEnable":"Ota automaattinen poisto käyttöön tässä lipussa." + }, + "stats":{ + "scopes":{ + "global":"Globaalit tilastot", + "system":"Järjestelmätilastot", + "user":"Käyttäjätilastot", + "ticket":"Lipputilastot", + "participants":"Osallistujat" + }, + "properties":{ + "ticketsCreated":"Liput luotu", + "ticketsClosed":"Liput suljettu", + "ticketsDeleted":"Liput poistettu", + "ticketsReopened":"Liput avattu uudelleen", + "ticketsAutoclosed":"Liput automaattisesti suljettu", + "ticketsClaimed":"Liput lunastettu", + "ticketsPinned":"Liput kiinni", + "ticketsMoved":"Liput siirretty", + "usersBlacklisted":"Käyttäjät mustalla listalla", + "transcriptsCreated":"Transkriptiot luotu" + } + } +} From 3ddb03a569d67895d66467d1412078e865d11e6a Mon Sep 17 00:00:00 2001 From: NotMega <135043684+iamnotmega@users.noreply.github.com> Date: Sat, 26 Oct 2024 19:45:17 +0300 Subject: [PATCH 045/157] Update estonian.json --- languages/estonian.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/estonian.json b/languages/estonian.json index 656cbad..f10e729 100644 --- a/languages/estonian.json +++ b/languages/estonian.json @@ -475,4 +475,4 @@ "transcriptsCreated":"Loodud ärakirjad" } } -}sss +} From 3469e61065f738118b728e2ccb3d042039d9edb4 Mon Sep 17 00:00:00 2001 From: NotMega <135043684+iamnotmega@users.noreply.github.com> Date: Sat, 26 Oct 2024 19:45:34 +0300 Subject: [PATCH 046/157] Update finnish.json From 970807d144d243d7b06b6167ae1e235674308e18 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 28 Oct 2024 12:29:33 +0100 Subject: [PATCH 047/157] Added 2 new languages + small ODMain improvements --- README.md | 4 ++-- languages/estonian.json | 2 +- languages/finnish.json | 2 +- src/core/api/defaults/language.ts | 2 ++ src/core/api/main.ts | 5 +++++ src/core/api/modules/client.ts | 13 +++++++------ src/data/framework/languageLoader.ts | 4 +++- src/data/framework/statLoader.ts | 2 +- src/index.ts | 1 + 9 files changed, 23 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 9b4877a..1f291af 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,8 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇺🇦 Ukrainian |anderskiy |🟢 Up To Date | |🇮🇩 Indonesian |erxg |🟢 Up To Date | |🇮🇹 Italian |fraden1mvp. |🟢 Up To Date | +|🇪🇪 Estonian |iamnotmega |🔵 Up To Date (ChatGPT) | +|🇫🇮 Finnish |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | |🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | |🇩🇰 Danish |.the_gamer |🟠 Temporary Outdated (beta) | @@ -128,12 +130,10 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | |❓ Persian |sasanwm |🟠 Temporary Outdated (beta) | |🇱🇻 Latvian |ronalds1398 |🟠 Temporary Outdated (beta) | -|🇪🇪 Estonian |iamnotmega |🟠 Temporary Outdated (beta) | |🇯🇵 Japanese |iamnotmega |🟠 Temporary Outdated (beta) | |🇰🇷 Korean |iamnotmega |🟠 Temporary Outdated (beta) | |🇨🇳 Simplified Chinese |iamnotmega |🟠 Temporary Outdated (beta) | |🇨🇳 Traditional Chinese|iamnotmega |🟠 Temporary Outdated (beta) | -|🇫🇮 Finnish |iamnotmega |🟠 Temporary Outdated (beta) | |🇸🇪 Swedish |iamnotmega |🟠 Temporary Outdated (beta) | |🇻🇳 Vietnamese |iamnotmega |🟠 Temporary Outdated (beta) | diff --git a/languages/estonian.json b/languages/estonian.json index f10e729..1e09634 100644 --- a/languages/estonian.json +++ b/languages/estonian.json @@ -1,7 +1,7 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translators":["iamnotmega"], + "translators":["iamnotmega","ChatGPT"], "lastedited":"21/10/2024", "language":"Estonian", "automated":true diff --git a/languages/finnish.json b/languages/finnish.json index b4e6374..d789e38 100644 --- a/languages/finnish.json +++ b/languages/finnish.json @@ -1,7 +1,7 @@ { "_TRANSLATION":{ "otversion":"v4.0.0", - "translators":["iamnotmega"], + "translators":["iamnotmega","ChatGPT"], "lastedited":"21/10/2024", "language":"Finnish", "automated":true diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index b71b19f..63015be 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -457,6 +457,8 @@ export interface ODLanguageManagerIds_Default { "openticket:ukrainian":ODLanguage, "openticket:indonesian":ODLanguage, "openticket:italian":ODLanguage, + "openticket:estonian":ODLanguage, + "openticket:finnish":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/core/api/main.ts b/src/core/api/main.ts index b65ab05..5860bd9 100644 --- a/src/core/api/main.ts +++ b/src/core/api/main.ts @@ -47,6 +47,11 @@ export class ODMain { /**The manager that handles all versions in the bot. */ versions: ODVersionManager_Default + /**The timestamp that the (node.js) process of the bot started. */ + processStartupDate: Date = new Date() + /**The timestamp that the bot finished loading and is ready for usage. */ + readyStartupDate: Date|null = null + /**The manager responsible for the debug file. (`otdebug.txt`) */ debugfile: ODDebugFileManager /**The manager responsible for the console system. (logs, errors, etc) */ diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index ba7b6c6..0753a9a 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -34,13 +34,13 @@ export class ODClientManager { /**Alias to open ticket debugger. */ #debug: ODDebugger - /**List of required bot intents. Add intents to this list using the `onClientConfiguration` event. */ + /**List of required bot intents. Add intents to this list using the `onClientLoad` event. */ intents: ODClientIntents[] = [] - /**List of required bot privileged intents. Add intents to this list using the `onClientConfiguration` event. */ + /**List of required bot privileged intents. Add intents to this list using the `onClientLoad` event. */ privileges: ODClientPriviligedIntents[] = [] - /**List of required bot partials. Add intents to this list using the `onClientConfiguration` event. **❌ Only use when neccessery!** */ + /**List of required bot partials. Add intents to this list using the `onClientLoad` event. **❌ Only use when neccessery!** */ partials: ODClientPartials[] = [] - /**List of required bot permissions. Add permissions to this list using the `onClientConfiguration` event. */ + /**List of required bot permissions. Add permissions to this list using the `onClientLoad` event. */ permissions: ODClientPermissions[] = [] /**The bot token, empty by default. */ token: string = "" @@ -340,7 +340,7 @@ export class ODClientActivityManager { /**The timer responsible for refreshing the status. Stop it using `clearInterval(interval)` */ interval?: NodeJS.Timeout - /**status refresh interval in seconds*/ + /**status refresh interval in seconds (5 minutes by default)*/ refreshInterval: number = 600 /**Is the status already initiated? */ initiated: boolean = false @@ -351,10 +351,11 @@ export class ODClientActivityManager { } /**Update the status. When already initiated, it can take up to 10min to see the updated status in discord. */ - setStatus(type:ODClientActivityType,text:string,status:ODClientActivityStatus){ + setStatus(type:ODClientActivityType, text:string, status:ODClientActivityStatus, forceUpdate?:boolean){ this.type = type this.text = text this.status = status + if (forceUpdate) this.#updateClientActivity(this.type,this.text) } /**When initiating the status, the bot starts updating the status using `discord.js`. Returns `true` when successfull. */ diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index af1ff66..be93ff9 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -15,10 +15,12 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODLanguage("openticket:ukrainian","ukrainian.json")) openticket.languages.add(new api.ODLanguage("openticket:indonesian","indonesian.json")) openticket.languages.add(new api.ODLanguage("openticket:italian","italian.json")) + openticket.languages.add(new api.ODLanguage("openticket:estonian","estonian.json")) + openticket.languages.add(new api.ODLanguage("openticket:finnish","finnish.json")) //list for config checker const languageList = openticket.defaults.getDefault("languageList") - languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian","indonesian","italian") + languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian","indonesian","italian","estonian","finnish") openticket.defaults.setDefault("languageList",languageList) /** How to add more languages? diff --git a/src/data/framework/statLoader.ts b/src/data/framework/statLoader.ts index d3508e9..d75074a 100644 --- a/src/data/framework/statLoader.ts +++ b/src/data/framework/statLoader.ts @@ -34,7 +34,7 @@ export const loadAllStats = async () => { const system = stats.get("openticket:system") if (system){ system.add(new api.ODDynamicStat("openticket:startup-date",1,() => { - return lang.getTranslation("params.uppercase.startupDate")+": "+discord.time(new Date(),"f") + return lang.getTranslation("params.uppercase.startupDate")+": "+discord.time(openticket.processStartupDate,"f") })) system.add(new api.ODDynamicStat("openticket:version",0,() => { return lang.getTranslation("params.uppercase.version")+": `"+openticket.versions.get("openticket:version").toString()+"`" diff --git a/src/index.ts b/src/index.ts index 31788ea..a59a48c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -742,6 +742,7 @@ const main = async () => { //YIPPPIE!! //The startup of Open Ticket is completed :) + openticket.readyStartupDate = new Date() await openticket.events.get("onReadyForUsage").emit([]) } main() \ No newline at end of file From 319bbe318d83ec8ca9db47462d73fc166073cdc2 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:52:14 +0100 Subject: [PATCH 048/157] Added previews + plugins to README.md --- README.md | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 1f291af..d6b8e81 100644 --- a/README.md +++ b/README.md @@ -48,23 +48,29 @@ You're also able to customise every little aspect of the bot! From embeds to tra > Open Ticket Plugins ## 📸 Preview -*Previews are not available yet in the beta release!* +Ticket Message +Ticket Stats Message +Example Panel 1 +Example Panel 2 ## 🧩 Plugins View all available Open Ticket plugins in our [Official Plugin Repository](https://github.com/DJj123dj/open-discord-plugins)! -### 📦 Official *(made by us)* -|Name |Category |Description | -|---------------------------------------------------------------------|-------------------------|-------------------------| +### 📦 Official *(made by DJdj Development)* +|Name |Category |Description | +|---------------------------------------------------------------------|----------------------------|-------------------------| |[`example-plugin`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-plugin/) |Example |This is just an example plugin for people that want to create their own plugin. | -|[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |Channel Management |Simple plugin to keep the channel prefix when using the /rename command. | +|[`example-command`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-command/) |Example |Sample custom command using the Open Discord system. | |[`ot-jump-to-top`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-jump-to-top/) |Command |Add a simple command to jump to the top of the ticket. | -|[`ot-no-slash-clear`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-no-slash-clear/) |Development & Compatibility |Disable the automatic removal of slash commands that aren't used by Open Ticket. | +|[`ot-kill-switch`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-kill-switch/) |Command |Temporarily disable the ticket system using a kill switch. | +|[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |Channel Management |Simple plugin to keep the channel prefix when using the /rename command. | +|[`ot-no-slash-clear`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-no-slash-clear/) |Development |Disable the automatic removal of slash commands that aren't used by Open Ticket. | +|[`ot-better-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-better-status/) |Client Activity |An advanced status plugin to rotate between states. It also allows for the use of variables. | ### ✅ Verified *(made by community)* -|Name |Description | -|----------------------|-------------------------| -|`nothing yet :)` |Lorem Ipsum Beta 4.0 🙃 | +|Name |Author |Category |Description | +|---------------------------------------------------------------------|----------------------------|----------------------------|-------------------------| +|[`ot-config-reload`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-config-reload/) |guillee.3 |Config |This plugin adds a new command that allows reloading the Open Ticket config files without the need for a restart. | ## 🛠️ Contributors ### 🖥️ Team @@ -85,11 +91,9 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat - -
Profile Picture Profile Picture
DOSEV5 roppl3r
@@ -98,6 +102,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat SpyEye Mods HD +DOSEV5 ### 💬 Translators @@ -123,10 +128,8 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | |🇹🇷 Turkish |0x15d3 |🟠 Temporary Outdated (beta) | |🇵🇱 Polish |mkevas |🟠 Temporary Outdated (beta) | -|🇸🇮 Slovenian |n1kkec |🔴 Outdated | |🇹🇭 Thai |modshd |🟠 Temporary Outdated (beta) | |🇳🇴 Norwegian |noonenook |🟠 Temporary Outdated (beta) | -|🇬🇷 Greek |stefanos__. |🔴 Outdated | |❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | |❓ Persian |sasanwm |🟠 Temporary Outdated (beta) | |🇱🇻 Latvian |ronalds1398 |🟠 Temporary Outdated (beta) | @@ -136,6 +139,8 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇨🇳 Traditional Chinese|iamnotmega |🟠 Temporary Outdated (beta) | |🇸🇪 Swedish |iamnotmega |🟠 Temporary Outdated (beta) | |🇻🇳 Vietnamese |iamnotmega |🟠 Temporary Outdated (beta) | +|🇸🇮 Slovenian |n1kkec |🔴 Outdated | +|🇬🇷 Greek |stefanos__. |🔴 Outdated | ## ⭐️ Star History Please help us grow by giving a star! It would help us a lot! From 4022ae49c285e62d4153146fbc8f122c9f46e603 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 6 Nov 2024 20:59:00 +0100 Subject: [PATCH 049/157] Major bug fixes + updated contributing guidelines --- .github/CONTRIBUTING.md | 56 +++++++++++++++++-------- src/commands/autoclose.ts | 16 +++++++ src/commands/autodelete.ts | 16 +++++++ src/core/api/modules/database.ts | 9 +++- src/data/framework/checkerLoader.ts | 20 ++++++++- src/data/openticket/transcriptLoader.ts | 25 +++++++++-- src/index.ts | 4 ++ 7 files changed, 123 insertions(+), 23 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 9322062..ab24c6a 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -16,19 +16,20 @@ This includes new features, translations & bug fixes. #### Step 2: Translation 1. If your language doesn't exist yet, copy the [`english.json`](./../languages/english.json) file and rename it to your language. -2. You are allowed to use a little bit of `Google Translate` or `DeepL` when mentioned in the upload. (❌ Not Recommended) +2. **(❌ Not Recommended)** You are allowed to use `Google Translate` or `DeepL`, but only when you say it in the pull request and enable the `"automated"` boolean. 3. Only translate existing values in the json file. Don't add or remove any values from the file. 4. You're **NOT REQUIRED** to translate everything! If you only want to translate a part of it, it's okay! 5. If you are unable to translate something, leave it in `English`. #### Step 3: Metadata Metadata can be found in the `_TRANSLATION` variable. -|Value |Notes | -|-------------|-------------------------------------------------------------------------------------------------| -|`otversion` |The Open Ticket version of this translation. Don't edit this! | -|`translator` |The translator discord username. When improving existing translation, add your name to the list. | -|`lastedited` |The last edited date in the `DD/MM/YYYY` format. | -|`language` |The full name of the language with capital letter. | +|Value |Notes | +|--------------|-------------------------------------------------------------------------------------------------| +|`otversion` |The Open Ticket version of this translation. **❌ DON'T EDIT!** | +|`translators` |The discord usernames from the translators. Add your name to the list when you've contributed. | +|`lastedited` |The last edited date in the `DD/MM/YYYY` format. | +|`language` |The full name of the language with capital letter. | +|`automated` |Enable this boolean when this translation has been made using ChatGPT, Google Translate, ... | > #### ✅ You are also allowed to add your username to the [`README.md`](./../README.md) translator list! @@ -46,20 +47,41 @@ Translators get some rewards for translating Open Ticket! - ✅ Credits in the changelog! - ✅ Credits in the documentation! - ✅ Credits in the translation JSON file! -- ✅ A special role in our [discord server](https://discord.dj-dj.be)! +- ✅ A special role in our [Discord server](https://discord.dj-dj.be)! -### 🧩 Plugins (temporary) -Currently plugins can only be added to the list via our [discord server](https://discord.dj-dj.be)! +### 🧩 Plugins +#### Step 1: Creating Plugins +The documentation for creating plugins will be ready soon!
+In the meantime, you can already look at existing plugins or try it at your own! -### 📦 Features (temporary) -Currently features can only be suggested in our [discord server](https://discord.dj-dj.be)! +#### Step 2: Uploading Plugins +Create a pull request in the [**`open-discord-plugins`**](https://odplugins.dj-dj.be/) repository or contact DJj123dj in our [Discord server](https://discord.dj-dj.be)! -### 🕷️ Bug Fixes (temporary) -Currently bug fixes can only be reported in the following ways: -- Create an issue in the repository! -- Create a ticket in our [discord server](https://discord.dj-dj.be)! +### 📦 Features +Feature requests are required to be made in one of the following ways: +- ✅ In our [Discord server](https://discord.dj-dj.be) +- ✅ Create an issue on GitHub +- ✅ Message DJj123dj in DM on Discord +- ✅ Email to support@dj-dj.be -#### Please try to always include the `otdebug.txt` file! +> **We won't accept pull requests for features. Only for bugs, small fixes, translation and plugins!** + +### 🕷️ Bug Fixes +You are able to report bugs in one of the following ways: +- ✅ In our [Discord server](https://discord.dj-dj.be) +- ✅ Create an issue on GitHub +- ✅ Message DJj123dj in DM on Discord +- ✅ Email to support@dj-dj.be + +📌 **If you want, you can also create a pull request to fix the bug yourself :)** + +#### 🔴 Security Vulnerabilities +If you've found a bug which could affect the **SECURITY OF THE BOT** or may be potentially dangerous to the users of the bot, +you are **REQUIRED to send the bug privately via one of the following methods:** +- 🔴 Message DJj123dj in DM on Discord +- 🔴 Email to support@dj-dj.be + +> ### Please try to always include the `otdebug.txt` file! --- Open Ticket Logo diff --git a/src/commands/autoclose.ts b/src/commands/autoclose.ts index 7bfc575..aa57fc8 100644 --- a/src/commands/autoclose.ts +++ b/src/commands/autoclose.ts @@ -82,6 +82,22 @@ export const registerCommandResponders = async () => { ticket.get("openticket:autoclose-hours").value = time await instance.reply(await openticket.builders.messages.getSafe("openticket:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time})) } + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on autoclose "+scope+"!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { const scope = instance.options.getSubCommand() diff --git a/src/commands/autodelete.ts b/src/commands/autodelete.ts index 4744804..6ee1f9d 100644 --- a/src/commands/autodelete.ts +++ b/src/commands/autodelete.ts @@ -77,6 +77,22 @@ export const registerCommandResponders = async () => { ticket.get("openticket:autodelete-days").value = time await instance.reply(await openticket.builders.messages.getSafe("openticket:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time})) } + + //update ticket message + const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + if (ticketMessage){ + try{ + ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + }catch(e){ + openticket.log("Unable to edit ticket message on autodelete "+scope+"!","error",[ + {key:"channel",value:"#"+channel.name}, + {key:"channelid",value:channel.id,hidden:true}, + {key:"messageid",value:ticketMessage.id}, + {key:"option",value:ticket.option.id.value} + ]) + openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + } + } }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { const scope = instance.options.getSubCommand() diff --git a/src/core/api/modules/database.ts b/src/core/api/modules/database.ts index 15047b5..e25eb2d 100644 --- a/src/core/api/modules/database.ts +++ b/src/core/api/modules/database.ts @@ -1,7 +1,7 @@ /////////////////////////////////////// //DATABASE MODULE /////////////////////////////////////// -import { ODId, ODManager, ODManagerData, ODValidId, ODValidJsonType } from "./base" +import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId, ODValidJsonType } from "./base" import fs from "fs" import nodepath from "path" import { ODDebugger } from "./console" @@ -203,7 +203,12 @@ export class ODJsonDatabase extends ODDatabase { /**Read parsed data from the json file */ getData: (): ODJsonDatabaseStructure => { if (fs.existsSync(this.file)){ - return JSON.parse(fs.readFileSync(this.file).toString()) + try{ + return JSON.parse(fs.readFileSync(this.file).toString()) + }catch(err){ + process.emit("uncaughtException",err) + throw new ODSystemError("Unable to read database "+this.file+"! getData() read error. (see error above)") + } }else{ fs.writeFileSync(this.file,"[]") return [] diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts index 0e478ad..5097f27 100644 --- a/src/data/framework/checkerLoader.ts +++ b/src/data/framework/checkerLoader.ts @@ -114,6 +114,9 @@ export const registerDefaultCheckerCustomTranslations = (tm:api.ODCheckerTransla tm.quickTranslate(lm,"checker.messages.unusedOption","message","openticket:unused-option") // The option {0} isn't used anywhere! tm.quickTranslate(lm,"checker.messages.unusedQuestion","message","openticket:unused-question") // The question {0} isn't used anywhere! tm.quickTranslate(lm,"checker.messages.dropdownOption","message","openticket:dropdown-option") // A panel with dropdown enabled can only contain options of the 'ticket' type! + + //TODO TRANSLATION!!! + //tm.quickTranslate(lm,"checker.messages.TODO","message","openticket:invalid-version") // The version specified in your config is invalid! Make sure you have updated it to the latest version! } //UTILITY FUNCTIONS @@ -168,6 +171,21 @@ const createPanelEmbedStructure = (id:api.ODValidId) => { //STRUCTURES export const defaultGeneralStructure = new api.ODCheckerObjectStructure("openticket:general",{children:[ + //STATUS + {key:"_INFO",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:info",{children:[ + {key:"support",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:info-support",{choices:["https://otdocs.dj-dj.be"]})}, + {key:"discord",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:info-discord",{choices:["https://discord.dj-dj.be"]})}, + {key:"version",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:info-version",{custom(checker,value,locationTrace,locationId,locationDocs) { + const lt = checker.locationTraceDeref(locationTrace) + + if (typeof value != "string") return false + else if (value != "open-ticket-"+openticket.versions.get("openticket:version").toString()){ + checker.createMessage("openticket:invalid-version","warning","The version specified in your config is invalid! Make sure you have updated it to the latest version!",lt,null,[],locationId,locationDocs) + return false + }else return true + },})}, + ]})}, + //BASIC {key:"token",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordToken("openticket:token")}, {key:"tokenFromENV",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:token-env",{})}, @@ -439,7 +457,7 @@ export const defaultPanelsStructure = new api.ODCheckerArrayStructure("openticke export const defaultQuestionsStructure = new api.ODCheckerArrayStructure("openticket:questions",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:questions",{children:[ {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:question-name",{minLength:3,maxLength:50})}, + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:question-name",{minLength:3,maxLength:45})}, {key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:question-type",{choices:["short","paragraph"]})}, {key:"required",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:question-required",{})}, diff --git a/src/data/openticket/transcriptLoader.ts b/src/data/openticket/transcriptLoader.ts index b940bc7..36c3419 100644 --- a/src/data/openticket/transcriptLoader.ts +++ b/src/data/openticket/transcriptLoader.ts @@ -5,6 +5,7 @@ const collector = openticket.transcripts.collector const messages = openticket.builders.messages const transcriptConfig = openticket.configs.get("openticket:transcripts") const textConfig = transcriptConfig.data.textTranscriptStyle +const htmlVersion = Buffer.from("b3BlbnRpY2tldFRSQU5TQ1JJUFQxMjM0","base64").toString("utf8") export const replaceHtmlTranscriptMentions = async (text:string) => { const mainServer = openticket.client.mainServer @@ -34,6 +35,14 @@ export const replaceHtmlTranscriptMentions = async (text:string) => { } 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) + }) + } + } + //TEXT COMPILER openticket.transcripts.add(new api.ODTranscriptCompiler<{contents:string}>("openticket:text-compiler",undefined,async (ticket,channel,user) => { //COMPILE @@ -42,6 +51,7 @@ export const loadAllTranscriptCompilers = async () => { const messages = await collector.convertMessagesToTranscriptData(rawMessages) const finalMessages: string[] = [] + //TODO TRANSLATION!!! finalMessages.push("=============== MESSAGES ===============") messages.filter((msg) => textConfig.includeBotMessages || !msg.author.tag).forEach((msg) => { @@ -53,8 +63,10 @@ export const loadAllTranscriptCompilers = async () => { if (textConfig.layout == "simple"){ //SIMPLE LAYOUT const header = "["+timestamp+" | "+msg.author.displayname+authorId+"]"+edited+msgId + //TODO TRANSLATION!!! const embeds = (textConfig.includeEmbeds) ? "\nEmbeds: "+msg.embeds.length : "" const files = (textConfig.includeFiles) ? "\nFiles: "+msg.files.length : "" + //TODO TRANSLATION!!! const content = (msg.content) ? msg.content : (""+embeds+files) finalMessages.push(header+"\n "+content.split("\n").join("\n ")) @@ -62,9 +74,11 @@ export const loadAllTranscriptCompilers = async () => { //NORMAL LAYOUT const header = "["+timestamp+" | "+msg.author.displayname+authorId+"]"+edited+msgId const embeds = (textConfig.includeEmbeds && msg.embeds.length > 0) ? "\n"+msg.embeds.map((embed) => { + //TODO TRANSLATION!!! return "==== (EMBED) "+(embed.title ?? "")+" ====\n"+(embed.description ?? "") }) : "" const files = (textConfig.includeFiles && msg.files.length > 0) ? "\n"+msg.files.map((file) => { + //TODO TRANSLATION!!! return "==== (FILE) "+(file.name)+" ====\nSize: "+(file.size+" "+file.unit)+"\nUrl: "+file.url }) : "" const content = (msg.content) ? msg.content : "" @@ -74,11 +88,14 @@ export const loadAllTranscriptCompilers = async () => { //ADVANCED LAYOUT const header = "["+timestamp+" | "+msg.author.displayname+authorId+"]"+edited+msgId const embeds = (textConfig.includeEmbeds && msg.embeds.length > 0) ? "\n"+msg.embeds.map((embed) => { + //TODO TRANSLATION!!! return "\n==== (EMBED) "+(embed.title ?? "")+" ====\n"+(embed.description ?? "")+(embed.fields.length > 0 ? "\n\n== (FIELDS) ==\n"+embed.fields.map((field) => field.name+": "+field.value).join("\n") : "") }) : "" const files = (textConfig.includeFiles && msg.files.length > 0) ? "\n"+msg.files.map((file) => { + //TODO TRANSLATION!!! return "\n==== (FILE) "+(file.name)+" ====\nSize: "+(file.size+" "+file.unit)+"\nUrl: "+file.url+"\nAlt: "+(file.alt ?? "/") }) : "" + //TODO TRANSLATION!!! const reactions = (msg.reactions.filter((r) => !r.custom).length > 0) ? "\n==== (REACTIONS) ====\n"+msg.reactions.filter((r) => !r.custom).map((r) => r.amount+" "+r.emoji).join(" - ") : "" const content = (msg.content) ? msg.content : "" finalMessages.push(header+"\n "+(content+embeds+files+reactions).split("\n").join("\n ")) @@ -97,15 +114,18 @@ export const loadAllTranscriptCompilers = async () => { const pinner = await openticket.tickets.getTicketUser(ticket,"pinner") if (textConfig.includeStats){ + //TODO TRANSLATION!!! finalStats.push("=============== STATS ===============") if (textConfig.layout == "simple"){ //SIMPLE LAYOUT + //TODO TRANSLATION!!! if (creationDate) finalStats.push("Created On: "+utilities.dateString(new Date(creationDate))) if (creator) finalStats.push("Created By: "+creator.displayName) finalStats.push("\n") }else if (textConfig.layout == "normal"){ //NORMAL LAYOUT + //TODO TRANSLATION!!! if (creationDate) finalStats.push("Created On: "+utilities.dateString(new Date(creationDate))) if (creator) finalStats.push("Created By: "+creator.displayName) finalStats.push("") @@ -117,6 +137,7 @@ export const loadAllTranscriptCompilers = async () => { }else if (textConfig.layout == "detailed"){ //ADVANCED LAYOUT + //TODO TRANSLATION!!! if (creationDate) finalStats.push("Created On: "+utilities.dateString(new Date(creationDate))) if (creator) finalStats.push("Created By: "+creator.displayName) finalStats.push("") @@ -421,9 +442,7 @@ export const loadAllTranscriptCompilers = async () => { } } - const req = new api.ODHTTPPostRequest("https://apis.dj-dj.be/transcripts/upload?auth=openticketTRANSCRIPT1234&version=2",true,{ - body:JSON.stringify(htmlFinal) - }) + const req = new ODHTTPHtmlPostRequest("apis.dj-dj.be",htmlFinal) const res = await req.run() if (!res || res.status != 200 || !res.body){ if (res.status == 429) return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts due to Ratelimt! Try again in a few minutes!",messages,data:null} diff --git a/src/index.ts b/src/index.ts index a59a48c..b4f30e5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -220,6 +220,10 @@ const main = async () => { //render openticket.debugfile.writeText("\n[CONFIG CHECKER RESULT]:\n"+ansis.strip(components.join("\n"))+"\n") openticket.checkers.renderer.render(components) + + //wait 5 seconds when there are warnings (not for errors & info) + if (result.messages.length > 0 && result.messages.every((message) => message.type != "error")) await utilities.timer(5000) + await openticket.events.get("afterCheckersRendered").emit([openticket.checkers.renderer,openticket.checkers]) } From 92aa42fc7c8b587080123087f18968adec251109 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 11 Nov 2024 21:27:53 +0100 Subject: [PATCH 050/157] ticket creator bug fix + added danish translation --- README.md | 2 +- languages/danish.json | 478 +++++++++++++++++++++++++++ languages/estonian.json | 2 +- languages/finnish.json | 2 +- languages/italian.json | 1 + src/actions/closeTicket.ts | 2 +- src/actions/reopenTicket.ts | 2 +- src/core/api/defaults/language.ts | 1 + src/data/framework/languageLoader.ts | 3 +- 9 files changed, 487 insertions(+), 6 deletions(-) create mode 100644 languages/danish.json diff --git a/README.md b/README.md index d6b8e81..97e56e0 100644 --- a/README.md +++ b/README.md @@ -120,11 +120,11 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇺🇦 Ukrainian |anderskiy |🟢 Up To Date | |🇮🇩 Indonesian |erxg |🟢 Up To Date | |🇮🇹 Italian |fraden1mvp. |🟢 Up To Date | +|🇩🇰 Danish |the_gamer |🟢 Up To Date | |🇪🇪 Estonian |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇮 Finnish |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | |🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | -|🇩🇰 Danish |.the_gamer |🟠 Temporary Outdated (beta) | |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | |🇹🇷 Turkish |0x15d3 |🟠 Temporary Outdated (beta) | |🇵🇱 Polish |mkevas |🟠 Temporary Outdated (beta) | diff --git a/languages/danish.json b/languages/danish.json new file mode 100644 index 0000000..8a52c88 --- /dev/null +++ b/languages/danish.json @@ -0,0 +1,478 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translators":["the_gamer"], + "lastedited":"26/09/2024", + "language":"Danish", + "automated":false + }, + "checker": { + "system": { + "typeError": "[FEJL]", + "headerOpenTicket": "ÅBEN TICKET", + "typeWarning": "[ADVARSEL]", + "typeInfo": "[INFO]", + "headerConfigChecker": "CONFIG CHECKER", + "headerDescription": "tjek efter fejl i din config!", + "footerError": "botten vil ikke fikse før alle {0}'s are fixed!", + "footerWarning": "it's recommended to fix all {0}'s before starting!", + "footerSupport": "SUPPORT: {0} - DOCS: {1}", + "compactInformation": "brug {0} for mere information!", + "dataPath": "path", + "dataDocs": "docs", + "dataMessages": "besked" + }, + "messages": { + "stringTooShort": "Denne linje kan ikke være kortere end {0} karaktere!", + "stringTooLong": "Denne linke kan ikke være længere end {0} karaktere!", + "stringLengthInvalid": "Denne linje skal være {0} karaktere lang!", + "stringStartsWith": "Denne linje skal starte med {0}!", + "stringEndsWith": "Denne linje skal ende med {0}!", + "stringContains": "Denne tekst skal indeholde {0}!", + "stringChoices": "Denne tekst kan kun være en af følgende værdier: {0}!", + "stringRegex": "Denne tekst er ugyldig!", + + "numberTooShort": "Dette nummer kan ikke være kortere end {0} tegn!", + "numberTooLong": "Dette nummer kan ikke være længere end {0} tegn!", + "numberLengthInvalid": "Dette nummer skal være {0} tegn langt!", + "numberTooSmall": "Dette nummer skal være mindst {0}!", + "numberTooLarge": "Dette nummer skal være højst {0}!", + "numberNotEqual": "Dette nummer skal være {0}!", + "numberStep": "Dette nummer skal være et multiplum af {0}!", + "numberStepOffset": "Dette nummer skal være et multiplum af {0}, startende med {1}!", + "numberStartsWith": "Dette nummer skal starte med {0}!", + "numberEndsWith": "Dette nummer skal ende med {0}!", + "numberContains": "Dette nummer skal indeholde {0}!", + "numberChoices": "Dette nummer kan kun være en af følgende værdier: {0}!", + "numberFloat": "Dette nummer kan ikke være et decimaltal!", + "numberNegative": "Dette nummer kan ikke være negativt!", + "numberPositive": "Dette nummer kan ikke være positivt!", + "numberZero": "Dette nummer kan ikke være nul!", + + "booleanTrue": "Denne boolean kan ikke være sand!", + "booleanFalse": "Denne boolean kan ikke være falsk!", + + "arrayEmptyDisabled": "Dette array må ikke være tomt!", + "arrayEmptyRequired": "Dette array skal være tomt!", + "arrayTooShort": "Dette array skal have en længde på mindst {0}!", + "arrayTooLong": "Dette array skal have en længde på højst {0}!", + "arrayLengthInvalid": "Dette array skal have en længde på {0}!", + "arrayInvalidTypes": "Dette array kan kun indeholde følgende typer: {0}!", + "arrayDouble": "Dette array tillader ikke den samme værdi to gange!", + + "discordInvalidId": "Dette er et ugyldigt Discord {0} id!", + "discordInvalidIdOptions": "Dette er et ugyldigt Discord {0} id! Du kan også bruge en af disse: {1}!", + "discordInvalidToken": "Dette er et ugyldigt Discord token (syntaktisk)!", + "colorInvalid": "Dette er en ugyldig hex-farve!", + "emojiTooShort": "Denne tekst skal have mindst {0} emojis!", + "emojiTooLong": "Denne tekst skal have højst {0} emojis!", + "emojiCustom": "Denne emoji kan ikke være en brugerdefineret Discord-emoji!", + "emojiInvalid": "Dette er en ugyldig emoji!", + "urlInvalid": "Denne URL er ugyldig!", + "urlInvalidHttp": "Denne URL kan kun bruge https:// protokollen!", + "urlInvalidProtocol": "Denne URL kan kun bruge http:// & https:// protokoller!", + "urlInvalidHostname": "Denne URL har et ikke-tilladt hostname!", + "urlInvalidExtension": "Denne URL har en ugyldig filendelse! Vælg mellem: {0}!", + "urlInvalidPath": "Denne URL har en ugyldig sti!", + "idNotUnique": "Dette id er ikke unikt, brug et andet id i stedet!", + "idNonExistent": "Id'et {0} eksisterer ikke!", + + "invalidType": "Denne egenskab skal være typen: {0}!", + "propertyMissing": "Egenskaben {0} mangler i dette objekt!", + "propertyOptional": "Egenskaben {0} er valgfri i dette objekt!", + "objectDisabled": "Dette objekt er deaktiveret, aktiver det ved at bruge {0}!", + "nullInvalid": "Denne egenskab kan ikke være null!", + "switchInvalidType": "Dette skal være en af følgende typer: {0}!", + "objectSwitchInvalid": "Dette objekt skal være en af følgende typer: {0}!", + + "invalidLanguage": "Dette er et ugyldigt sprog!", + "invalidButton": "Denne knap skal have mindst en {0} eller {1}!", + "unusedOption": "Muligheden {0} bruges ikke nogen steder!", + "unusedQuestion": "Spørgsmålet {0} bruges ikke nogen steder!", + "dropdownOption": "Et panel med dropdown aktiveret kan kun indeholde muligheder af typen 'ticket'!" + } + }, + "actions": { + "buttons": { + "create": "Opret Ticket", + "close": "Luk Ticket", + "delete": "Slet Ticket", + "reopen": "Genåbn Ticket", + "claim": "Tag Ticket", + "unclaim": "Fraskriv Ticket", + "pin": "Fastgør Ticket", + "unpin": "Fjern Fastgørelse af Ticket", + "clear": "Slet Tickets", + "helpSwitchSlash": "Vis Slash Kommandoer", + "helpSwitchText": "Vis Tekst Kommandoer", + "helpPage": "Side {0}", + "withReason": "Med Årsag", + "withoutTranscript": "Uden Transkript" + }, + "titles": { + "created": "Ticket Oprettet", + "close": "Ticket Lukket", + "delete": "Ticket Slettet", + "reopen": "Ticket Genåbnet", + "claim": "Ticket Taget", + "unclaim": "Ticket Fraskrevet", + "pin": "Ticket Fastgjort", + "unpin": "Ticket Fjernet fra Fastgørelse", + "rename": "Ticket Omdøbt", + "move": "Ticket Flyttet", + "add": "Bruger Tilføjet til Ticket", + "remove": "Bruger Fjernet fra Ticket", + + "help": "Tilgængelige Kommandoer", + "statsReset": "Nulstil Statistik", + "blacklistAdd": "Bruger Blacklistet", + "blacklistRemove": "Bruger Fjernet fra Blacklist", + "blacklistGet": "Blacklistet Bruger", + "blacklistView": "Nuværende Blacklist", + "blacklistAddDm": "Tilføjet til Blacklist", + "blacklistRemoveDm": "Fjernet fra Blacklist", + "clear": "Tickets Renset", + "roles": "Roller Opdateret", + + "autoclose": "Ticket Autolukket", + "autocloseEnabled": "Autolukning Aktiveret", + "autocloseDisabled": "Autolukning Deaktiveret", + "autodelete": "Ticket Autoslettet", + "autodeleteEnabled": "Autosletning Aktiveret", + "autodeleteDisabled": "Autosletning Deaktiveret" + }, + "descriptions": { + "create": "Din ticket er blevet oprettet. Klik på knappen nedenfor for at få adgang til den!", + "close": "ticket er blevet lukket succesfuldt!", + "delete": "ticket er blevet slettet succesfuldt!", + "reopen": "ticket er blevet genåbnet succesfuldt!", + "claim": "ticket er blevet taget succesfuldt!", + "unclaim": "ticket er blevet fraskrevet succesfuldt!", + "pin": "ticket er blevet fastgjort succesfuldt!", + "unpin": "ticket er blevet fjernet fra fastgørelse succesfuldt!", + "rename": "ticket er blevet omdøbt til {0} succesfuldt!", + "move": "ticket er blevet flyttet til {0} succesfuldt!", + "add": "{0} er blevet tilføjet til ticketten succesfuldt!", + "remove": "{0} er blevet fjernet fra ticketten succesfuldt!", + + "helpExplanation": "`` => påkrævet parameter\n`[name]` => valgfri parameter", + "statsReset": "Bot-statistikken er blevet nulstillet succesfuldt!", + "statsError": "Kan ikke vise ticketstatistik!\n{0} er ikke en ticket!", + "blacklistAdd": "{0} er blevet blacklistet succesfuldt!", + "blacklistRemove": "{0} er blevet frigivet succesfuldt!", + "blacklistGetSuccess": "{0} er i øjeblikket blacklistet!", + "blacklistGetEmpty": "{0} er i øjeblikket ikke blacklistet!", + "blacklistViewEmpty": "Ingen har endnu været blacklistet!", + "blacklistViewTip": "Brug \"/blacklist add\" for at blacklist en bruger!", + "clearVerify": "Er du sikker på, at du vil slette flere tickets?\nDenne handling kan ikke fortrydes!", + "clearReady": "{0} tickets er blevet slettet succesfuldt!", + "rolesEmpty": "Ingen roller er blevet opdateret!", + + "autocloseLeave": "Denne ticket er blevet autolukket, fordi skaberen forlod serveren!", + "autocloseTimeout": "Denne ticket er blevet autolukket, fordi den har været inaktiv i mere end `{0}h`!", + "autodeleteLeave": "Denne ticket er blevet autoslettet, fordi skaberen forlod serveren!", + "autodeleteTimeout": "Denne ticket er blevet autoslettet, fordi den har været inaktiv i mere end `{0} dage`!", + "autocloseEnabled": "Autolukning er blevet aktiveret i denne ticket!\nDen vil blive lukket, når den er inaktiv i mere end `{0}h`!", + "autocloseDisabled": "Autolukning er blevet deaktiveret i denne ticket!\nDen vil ikke blive lukket automatisk længere!", + "autodeleteEnabled": "Autosletning er blevet aktiveret i denne ticket!\nDen vil blive slettet, når den er inaktiv i mere end `{0} dage`!", + "autodeleteDisabled": "Autosletning er blevet deaktiveret i denne ticket!\nDen vil ikke blive slettet automatisk længere!", + + "ticketMessageLimit": "Du kan kun oprette {0} ticket(ter) ad gangen!", + "ticketMessageAutoclose": "Denne ticket vil blive autolukket, når den er inaktiv i {0}h!", + "ticketMessageAutodelete": "Denne ticket vil blive autoslettet, når den er inaktiv i {0} dage!", + "panelReady": "Du kan finde panelet nedenfor!\nDenne besked kan nu slettes!" + }, + "modal": { + "closePlaceholder": "Hvorfor lukkede du denne ticket?", + "deletePlaceholder": "Hvorfor slettede du denne ticket?", + "reopenPlaceholder": "Hvorfor genåbnede du denne ticket?", + "claimPlaceholder": "Hvorfor tog du denne ticket?", + "unclaimPlaceholder": "Hvorfor fraskrev du denne ticket?", + "pinPlaceholder": "Hvorfor fastgjorde du denne ticket?", + "unpinPlaceholder": "Hvorfor fjernede du fastgørelsen af denne ticket?" + }, + "logs": { + "createLog": "En ny ticket er blevet oprettet af {0}!", + "closeLog": "Denne ticket er blevet lukket af {0}!", + "closeDm": "Din ticket er blevet lukket på vores server!", + "deleteLog": "Denne ticket er blevet slettet af {0}!", + "deleteDm": "Din ticket er blevet slettet på vores server!", + "reopenLog": "Denne ticket er blevet genåbnet af {0}!", + "reopenDm": "Din ticket er blevet genåbnet på vores server!", + "claimLog": "Denne ticket er blevet taget af {0}!", + "claimDm": "Din ticket er blevet taget på vores server!", + "unclaimLog": "Denne ticket er blevet fraskrevet af {0}!", + "unclaimDm": "Din ticket er blevet fraskrevet på vores server!", + "pinLog": "Denne ticket er blevet fastgjort af {0}!", + "pinDm": "Din ticket er blevet fastgjort på vores server!", + "unpinLog": "Denne ticket er blevet fjernet fra fastgørelse af {0}!", + "unpinDm": "Din ticket er blevet fjernet fra fastgørelse på vores server!", + "renameLog": "Denne ticket er blevet omdøbt til {0} af {1}!", + "renameDm": "Din ticket er blevet omdøbt til {0} på vores server!", + "moveLog": "Denne ticket er blevet flyttet til {0} af {1}!", + "moveDm": "Din ticket er blevet flyttet til {0} på vores server!", + "addLog": "{0} er blevet tilføjet til denne ticket af {1}!", + "addDm": "{0} er blevet tilføjet til din ticket på vores server!", + "removeLog": "{0} er blevet fjernet fra denne ticket af {1}!", + "removeDm": "{0} er blevet fjernet fra din ticket på vores server!", + + "blacklistAddLog": "{0} er blevet blacklistet af {1}!", + "blacklistRemoveLog": "{0} er blevet fjernet fra blacklisten af {1}!", + "blacklistAddDm": "Du er blevet blacklistet på vores server!\nFra nu af kan du ikke oprette en ticket!", + "blacklistRemoveDm": "Du er blevet fjernet fra blacklisten på vores server!\nNu kan du igen oprette ticketter!", + "clearLog": "{0} ticketter er blevet slettet af {1}!" + } + }, + "transcripts": { + "success": { + "visit": "Besøg Transkript", + "ready": "Transkript Oprettet", + "textFileDescription": "Dette er teksttranskriptet af en slettet billet!", + "htmlProgress": "Vent venligst mens dette HTML-transkript bliver behandlet...", + + "createdChannel": "Et nyt {0} transkript er blevet oprettet på serveren!", + "createdCreator": "Et nyt {0} transkript er blevet oprettet for en af dine billetter!", + "createdParticipant": "Et nyt {0} transkript er blevet oprettet i en af de billetter, du deltog i!", + "createdActiveAdmin": "Et nyt {0} transkript er blevet oprettet i en af de billetter, hvor du deltog som administrator!", + "createdEveryAdmin": "Et nyt {0} transkript er blevet oprettet i en af de billetter, hvor du var administrator!", + "createdOther": "Et nyt {0} transkript er blevet oprettet!" + }, + "errors": { + "retry": "Prøv igen", + "continue": "Slet uden transkript", + "backup": "Opret backup-transkript", + "error": "Noget gik galt, da vi forsøgte at oprette transkriptet.\nHvad vil du gerne gøre?\n\nDenne ticket bliver ikke slettet, før du klikker på en af disse knapper." + } + }, + "errors": { + "titles": { + "internalError": "Intern fejl", + "optionMissing": "Kommandoindstilling mangler", + "optionInvalid": "Ugyldig kommandoindstilling", + "unknownCommand": "Ukendt kommando", + "noPermissions": "Ingen tilladelser", + "unknownTicket": "Ukendt ticket", + "deprecatedTicket": "Forældet ticket", + "unknownOption": "Ukendt indstilling", + "unknownPanel": "Ukendt panel", + "notInGuild": "Ikke på server", + "channelRename": "Kan ikke omdøbe kanalen", + "busy": "Ticket er optaget" + }, + "descriptions": { + "askForInfo": "Kontakt ejeren af denne bot for mere info!", + "askForInfoResolve": "Kontakt ejeren af denne bot, hvis problemet ikke løses efter et par forsøg.", + "internalError": "Kunne ikke svare på denne {0} på grund af en intern fejl!", + "optionMissing": "Der mangler en påkrævet parameter i denne kommando!", + "optionInvalid": "En parameter i denne kommando er ugyldig!", + "optionInvalidChoose": "Vælg mellem", + "unknownCommand": "Prøv at besøge hjælpe-menuen for mere info!", + "noPermissions": "Du har ikke tilladelse til at bruge denne {0}!", + "noPermissionsList": "Påkrævede tilladelser: (en af dem)", + "noPermissionsCooldown": "Du har ikke tilladelse til at bruge denne {0}, fordi du har en nedkølingsperiode!", + "noPermissionsBlacklist": "Du har ikke tilladelse til at bruge denne {0}, fordi du er blevet sortlistet!", + "noPermissionsLimitGlobal": "Du har ikke tilladelse til at oprette en ticket, fordi serveren har nået det maksimale antal tickets!", + "noPermissionsLimitGlobalUser": "Du har ikke tilladelse til at oprette en ticket, fordi du har nået det maksimale antal tickets!", + "noPermissionsLimitOption": "Du har ikke tilladelse til at oprette en ticket, fordi serveren har nået det maksimale antal tickets for denne indstilling!", + "noPermissionsLimitOptionUser": "Du har ikke tilladelse til at oprette en ticket, fordi du har nået det maksimale antal tickets for denne indstilling!", + "unknownTicket": "Prøv denne kommando igen i en gyldig ticket!", + "deprecatedTicket": "Den aktuelle kanal er ikke en gyldig ticket! Det kan være en ticket fra en ældre version af Open Ticket!", + "notInGuild": "Denne {0} virker ikke i DM! Prøv igen på en server!", + "channelRename": "På grund af Discord-ratelimits er det i øjeblikket umuligt for botten at omdøbe kanalen. Kanalen vil automatisk blive omdøbt inden for 10 minutter, hvis botten ikke genstartes.", + "channelRenameSource": "Kilden til denne fejl er: {0}", + "busy": "Kan ikke bruge denne {0}!\nTicketen bliver i øjeblikket behandlet af botten.\n\nPrøv igen om et par sekunder!" + }, + "optionInvalidReasons": { + "stringRegex": "Værdien matcher ikke mønsteret!", + "stringMinLength": "Værdien skal være mindst {0} tegn!", + "stringMaxLength": "Værdien skal være højst {0} tegn!", + "numberInvalid": "Ugyldigt tal!", + "numberMin": "Tallet skal være mindst {0}!", + "numberMax": "Tallet skal være højst {0}!", + "numberDecimal": "Tallet må ikke være et decimaltal!", + "numberNegative": "Tallet må ikke være negativt!", + "numberPositive": "Tallet må ikke være positivt!", + "numberZero": "Tallet må ikke være nul!", + "channelNotFound": "Kan ikke finde kanalen!", + "userNotFound": "Kan ikke finde brugeren!", + "roleNotFound": "Kan ikke finde rollen!", + "memberNotFound": "Kan ikke finde brugeren!", + "mentionableNotFound": "Kan ikke finde brugeren eller rollen!", + "channelType": "Ugyldig kanaltype!", + "notInGuild": "Denne mulighed kræver, at du er på en server!" + }, + "permissions": { + "developer": "Du skal være udvikler af botten.", + "owner": "Du skal være serverejer.", + "admin": "Du skal være serveradministrator.", + "moderator": "Du skal være moderator.", + "support": "Du skal være en del af supportteamet.", + "member": "Du skal være medlem.", + "discord-administrator": "Du skal have `ADMINISTRATOR` tilladelsen." + }, + "actionInvalid": { + "close": "Ticket er allerede lukket!", + "reopen": "Ticket er ikke lukket endnu!", + "claim": "Ticket er allerede gjort krav på!", + "unclaim": "Ticket er ikke gjort krav på endnu!", + "pin": "Ticket er allerede fastgjort!", + "unpin": "Ticket er ikke fastgjort endnu!", + "add": "Denne bruger har allerede adgang til ticketen!", + "remove": "Kan ikke fjerne denne bruger fra ticketen!" + } + }, + "params": { + "uppercase": { + "ticket": "Ticket", + "tickets": "Tickets", + "reason": "Årsag", + "creator": "Skaber", + "remaining": "Tid tilbage", + "added": "Tilføjet", + "removed": "Fjernet", + "filter": "Filter", + "claimedBy": "Gjort krav på af {0}", + "method": "Metode", + "type": "Type", + "blacklisted": "Sortlistet", + "panel": "Panel", + "command": "Kommando", + "system": "System", + "true": "Sand", + "false": "Falsk", + "syntax": "Syntaks", + "originalName": "Originalt navn", + "newName": "Nyt navn", + "until": "Indtil", + "validOptions": "Gyldige indstillinger", + "validPanels": "Gyldige paneler", + "autoclose": "Auto-lukning", + "autodelete": "Auto-sletning", + "startupDate": "Startdato", + "version": "Version", + "name": "Navn", + "role": "Rolle", + "status": "Status", + "claimed": "Gjort krav på", + "pinned": "Fastgjort", + "creationDate": "Oprettelsesdato" + }, + "lowercase": { + "text": "tekst", + "html": "html", + "command": "kommando", + "modal": "modal", + "button": "knap", + "dropdown": "dropdown", + "method": "metode" + } + }, + "commands": { + "reason": "Angiv en valgfri årsag, der vil være synlig i loggene.", + "help": "Få en liste over alle tilgængelige kommandoer.", + "panel": "Opret en besked med en dropdown eller knapper (til ticket-oprettelse).", + "panelId": "Identifikatoren for panelet, som du vil oprette.", + "panelAutoUpdate": "Vil du have, at dette panel automatisk opdateres, når det redigeres?", + "ticket": "Opret en ticket med det samme.", + "ticketId": "Identifikatoren for ticketen, som du vil oprette.", + "close": "Luk en ticket.", + "delete": "Slet en ticket.", + "deleteNoTranscript": "Slet denne ticket uden at oprette et transkript.", + "reopen": "Genåbn en ticket.", + "claim": "Gør krav på en ticket.", + "claimUser": "Gør krav på denne ticket til en anden bruger i stedet for dig selv.", + "unclaim": "Afstå fra krav på en ticket.", + "pin": "Fastgør en ticket.", + "unpin": "Frigør en fastgjort ticket.", + "move": "Flyt en ticket.", + "moveId": "Identifikatoren for den indstilling, du vil flytte til.", + "rename": "Omdøb en ticket.", + "renameName": "Det nye navn for denne ticket.", + "add": "Tilføj en bruger til en ticket.", + "addUser": "Brugeren, der skal tilføjes.", + "remove": "Fjern en bruger fra en ticket.", + "removeUser": "Brugeren, der skal fjernes.", + "blacklist": "Administrer ticket-blacklisten.", + "blacklistView": "Se en liste over den nuværende blacklist.", + "blacklistAdd": "Tilføj en bruger til blacklisten.", + "blacklistRemove": "Fjern en bruger fra blacklisten.", + "blacklistGet": "Få detaljer fra en sortlistet bruger.", + "blacklistGetUser": "Brugeren at få detaljer fra.", + "stats": "Se statistik fra botten, en bruger eller en ticket.", + "statsReset": "Nulstil al statistik for botten (og start tælling fra nul).", + "statsGlobal": "Se de globale statistikker.", + "statsUser": "Se statistik fra en bruger på serveren.", + "statsUserUser": "Brugeren, der skal vises.", + "statsTicket": "Se statistik for en ticket på serveren.", + "statsTicketTicket": "Ticketen, der skal vises.", + "clear": "Slet flere tickets på samme tid.", + "clearFilter": "Filteret til at rydde tickets.", + "clearFilters": { + "all": "Alle", + "open": "Åbne", + "close": "Lukkede", + "claim": "Gjort krav på", + "unclaim": "Ikke gjort krav på", + "pin": "Fastgjort", + "unpin": "Ikke fastgjort", + "autoclose": "Auto-lukket" + }, + "autoclose": "Administrer auto-lukning i en ticket.", + "autocloseDisable": "Deaktiver auto-lukning i denne ticket.", + "autocloseEnable": "Aktiver auto-lukning i denne ticket.", + "autocloseEnableTime": "Antal timer, denne ticket skal være inaktiv for at lukke den.", + "autodelete": "Administrer auto-sletning i en ticket.", + "autodeleteDisable": "Deaktiver auto-sletning i denne ticket.", + "autodeleteEnable": "Aktiver auto-sletning i denne ticket.", + "autodeleteEnableTime": "Antal dage, denne ticket skal være inaktiv for at slette den." + }, + "helpMenu": { + "help": "Få en liste over alle de tilgængelige kommandoer.", + "ticket": "Opret en ticket med det samme.", + "close": "Luk en ticket, dette deaktiverer skrivning i denne kanal.", + "delete": "Slet en ticket, dette opretter et transkript, når det er aktiveret.", + "reopen": "Genåbn en ticket, dette aktiverer skrivning i denne kanal igen.", + "pin": "Fastgør en ticket. Dette vil flytte ticketen til toppen og tilføje en '📌' emoji til navnet.", + "unpin": "Frigør en ticket. Ticketen forbliver på sin position, men mister '📌' emoji.", + "move": "Flyt en ticket. Dette vil ændre typen af denne ticket.", + "rename": "Omdøb en ticket. Dette vil ændre kanalnavnet på denne ticket.", + "claim": "Gør krav på en ticket. Med dette kan du lade dit team vide, at du håndterer denne ticket.", + "unclaim": "Afstå fra krav på en ticket. Med dette kan du lade dit team vide, at denne ticket er fri igen.", + "add": "Tilføj en bruger til en ticket. Dette vil give brugeren mulighed for at læse og skrive i denne ticket.", + "remove": "Fjern en bruger fra en ticket. Dette vil fjerne muligheden for at læse og skrive for en bruger i denne ticket.", + "panel": "Opret en besked med en dropdown eller knapper (til ticket-oprettelse).", + "blacklistView": "Se en liste over den nuværende blacklist.", + "blacklistAdd": "Tilføj en bruger til blacklisten.", + "blacklistRemove": "Fjern en bruger fra blacklisten.", + "blacklistGet": "Få detaljerne fra en sortlistet bruger.", + "statsGlobal": "Se de globale statistikker.", + "statsTicket": "Se statistikken for en ticket på serveren.", + "statsUser": "Se statistikken fra en bruger på serveren.", + "statsReset": "Nulstil al statistik for botten (og start tælling fra nul).", + "autocloseDisable": "Deaktiver auto-lukning i denne ticket.", + "autocloseEnable": "Aktiver auto-lukning i denne ticket.", + "autodeleteDisable": "Deaktiver auto-sletning i denne ticket.", + "autodeleteEnable": "Aktiver auto-sletning i denne ticket." + }, + "stats": { + "scopes": { + "global": "Globale Statistikker", + "system": "Systemstatistikker", + "user": "Brugerstatistikker", + "ticket": "Ticketstatistikker", + "participants": "Deltagere" + }, + "properties": { + "ticketsCreated": "Oprettede Tickets", + "ticketsClosed": "Lukkede Tickets", + "ticketsDeleted": "Slettede Tickets", + "ticketsReopened": "Genåbnede Tickets", + "ticketsAutoclosed": "Auto-lukkede Tickets", + "ticketsClaimed": "Gjorte krav på Tickets", + "ticketsPinned": "Fastgjorte Tickets", + "ticketsMoved": "Flyttede Tickets", + "usersBlacklisted": "Sortlistede Brugere", + "transcriptsCreated": "Oprettede Transkripter" + } + } +} \ No newline at end of file diff --git a/languages/estonian.json b/languages/estonian.json index 1e09634..8d882c5 100644 --- a/languages/estonian.json +++ b/languages/estonian.json @@ -475,4 +475,4 @@ "transcriptsCreated":"Loodud ärakirjad" } } -} +} \ No newline at end of file diff --git a/languages/finnish.json b/languages/finnish.json index d789e38..ee1cf6d 100644 --- a/languages/finnish.json +++ b/languages/finnish.json @@ -475,4 +475,4 @@ "transcriptsCreated":"Transkriptiot luotu" } } -} +} \ No newline at end of file diff --git a/languages/italian.json b/languages/italian.json index 3afe786..da810cb 100644 --- a/languages/italian.json +++ b/languages/italian.json @@ -229,6 +229,7 @@ "ready":"Trascrizione Creata", "textFileDescription":"Questa è la trascrizione testuale di un ticket eliminato!", "htmlProgress":"Attendere mentre questa trascrizione html viene elaborata...", + "createdChannel":"Una nuova trascrizione di {0} è stata creata nel server!", "createdCreator":"Una nuova trascrizione di {0} è stata creata per uno dei tuoi ticket!", "createdParticipant":"Una nuova trascrizione di {0} è stata creata in uno dei ticket a cui hai partecipato!", diff --git a/src/actions/closeTicket.ts b/src/actions/closeTicket.ts index ded141e..4e87dcd 100644 --- a/src/actions/closeTicket.ts +++ b/src/actions/closeTicket.ts @@ -87,7 +87,7 @@ export const registerActions = async () => { if (participant.type == "user"){ permissions.push({ type:discord.OverwriteType.Member, - id:user.id, + id:participant.id, allow:["ViewChannel","ReadMessageHistory"], deny:["SendMessages","AddReactions","AttachFiles","SendPolls"] }) diff --git a/src/actions/reopenTicket.ts b/src/actions/reopenTicket.ts index 77bd5ab..4d992b6 100644 --- a/src/actions/reopenTicket.ts +++ b/src/actions/reopenTicket.ts @@ -120,7 +120,7 @@ export const registerActions = async () => { if (participant.type == "user"){ permissions.push({ type:discord.OverwriteType.Member, - id:user.id, + id:participant.id, allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory"], deny:[] }) diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index 63015be..86d7d36 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -459,6 +459,7 @@ export interface ODLanguageManagerIds_Default { "openticket:italian":ODLanguage, "openticket:estonian":ODLanguage, "openticket:finnish":ODLanguage, + "openticket:danish":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index be93ff9..f25fd03 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -17,10 +17,11 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODLanguage("openticket:italian","italian.json")) openticket.languages.add(new api.ODLanguage("openticket:estonian","estonian.json")) openticket.languages.add(new api.ODLanguage("openticket:finnish","finnish.json")) + openticket.languages.add(new api.ODLanguage("openticket:danish","danish.json")) //list for config checker const languageList = openticket.defaults.getDefault("languageList") - languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian","indonesian","italian","estonian","finnish") + languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian","indonesian","italian","estonian","finnish","danish") openticket.defaults.setDefault("languageList",languageList) /** How to add more languages? From 5a4b45aa3f357b9e3c6dca9d60fe647f6f8ffe40 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 14 Nov 2024 17:50:06 +0100 Subject: [PATCH 051/157] Added Thai Translation (by ModsHD) --- README.md | 4 +- languages/thai.json | 478 +++++++++++++++++++++++++++ src/core/api/defaults/language.ts | 1 + src/data/framework/languageLoader.ts | 3 +- 4 files changed, 483 insertions(+), 3 deletions(-) create mode 100644 languages/thai.json diff --git a/README.md b/README.md index 97e56e0..f239086 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇮🇩 Indonesian |erxg |🟢 Up To Date | |🇮🇹 Italian |fraden1mvp. |🟢 Up To Date | |🇩🇰 Danish |the_gamer |🟢 Up To Date | +|🇹🇭 Thai |modshd |🟢 Up To Date | |🇪🇪 Estonian |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇮 Finnish |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | @@ -128,7 +129,6 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | |🇹🇷 Turkish |0x15d3 |🟠 Temporary Outdated (beta) | |🇵🇱 Polish |mkevas |🟠 Temporary Outdated (beta) | -|🇹🇭 Thai |modshd |🟠 Temporary Outdated (beta) | |🇳🇴 Norwegian |noonenook |🟠 Temporary Outdated (beta) | |❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | |❓ Persian |sasanwm |🟠 Temporary Outdated (beta) | @@ -140,7 +140,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇸🇪 Swedish |iamnotmega |🟠 Temporary Outdated (beta) | |🇻🇳 Vietnamese |iamnotmega |🟠 Temporary Outdated (beta) | |🇸🇮 Slovenian |n1kkec |🔴 Outdated | -|🇬🇷 Greek |stefanos__. |🔴 Outdated | +|🇬🇷 Greek |stefanos |🔴 Outdated | ## ⭐️ Star History Please help us grow by giving a star! It would help us a lot! diff --git a/languages/thai.json b/languages/thai.json new file mode 100644 index 0000000..fa3dace --- /dev/null +++ b/languages/thai.json @@ -0,0 +1,478 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translators":["modshd"], + "lastedited":"13/11/2024", + "language":"Thai", + "automated":false + }, + "checker":{ + "system":{ + "typeError": "[ข้อผิดพลาด]", + "headerOpenTicket": "เปิดห้องติดต่อ", + "typeWarning": "[คำเตือน]", + "typeInfo": "[ข้อมูล]", + "headerConfigChecker": "ตัวตรวจสอบการตั้งค่า", + "headerDescription": "ตรวจสอบข้อผิดพลาดในไฟล์การตั้งค่าของคุณ", + "footerError": "บอทจะไม่เริ่มจนกว่าจะแก้ไขข้อผิดพลาดทั้งหมดใน {0}", + "footerWarning": "แนะนำให้แก้ไขข้อผิดพลาดทั้งหมดใน {0} ก่อนเริ่มใช้งาน", + "footerSupport": "สนับสนุน: {0} - เอกสาร: {1}", + "compactInformation": "ใช้ {0} เพื่อข้อมูลเพิ่มเติม", + "dataPath": "ทีอยู่", + "dataDocs": "เอกสารช่วยเหลือ", + "dataMessages": "ข้อความ" + }, + "messages":{ + "stringTooShort": "ข้อความนี้สั้นเกินไปไม่สามารถน้อยกว่า {0} ตัวอักษรได้", + "stringTooLong": "ข้อความนี้ยาวเกินไปไม่สามารถมากกว่า {0} ตัวอักษรได้", + "stringLengthInvalid": "ข้อความนี้ต้องมีความยาว {0} ตัวอักษร", + "stringStartsWith": "ข้อความนี้ต้องเริ่มต้นด้วย {0}", + "stringEndsWith": "ข้อความนี้ต้องลงท้ายด้วย {0}", + "stringContains": "ข้อความนี้ต้องประกอบด้วย {0}", + "stringChoices": "ข้อความนี้สามารถเป็นค่าใดค่าหนึ่งจากตัวเลือกต่อไปนี้: {0}", + "stringRegex": "ข้อความนี้ไม่ถูกต้อง", + + "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} discord ที่ไม่ถูกต้อง", + "discordInvalidIdOptions": "นี่คือรหัสไอดี {0} discord ที่ไม่ถูกต้อง คุณสามารถใช้ตัวเลือกเหล่านี้: {1}", + "discordInvalidToken": "นี่คือโทเค็น discord ที่ไม่ถูกต้อง (จากด้านไวยากรณ์)", + "colorInvalid": "นี่คือสี hex ที่ไม่ถูกต้อง", + "emojiTooShort": "ข้อความนี้ต้องมีอีโมจิอย่างน้อย {0} ตัว", + "emojiTooLong": "ข้อความนี้ต้องมีอีโมจิไม่เกิน {0} ตัว", + "emojiCustom": "อีโมจินี้ไม่สามารถเป็นอีโมจิแบบกำหนดเองของ discord ได้", + "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": "แผงที่เปิดใช้งานตัวเลือกแบบเลื่อนลงสามารถประกอบด้วยตัวเลือกประเภท 'ticket' เท่านั้น" + } + }, + "actions":{ + "buttons":{ + "create": "สร้างห้องติดต่อ", + "close": "ปิดห้องติดต่อ", + "delete": "ลบห้องติดต่อ", + "reopen": "เปิดห้องติดต่อใหม่อีกครั้ง", + "claim": "รับห้องติดต่อ", + "unclaim": "ยกเลิกการรับห้องติดต่อ", + "pin": "ปักหมุดห้องติดต่อ", + "unpin": "ยกเลิกการปักหมุดห้องติดต่อ", + "clear": "ลบห้องติดต่อทั้งหมด", + "helpSwitchSlash": "ดูคำสั่งแบบ Slash", + "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": "`` => สิ่งที่ต้องการ\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": "ห้องติดต่อนี้ถูกเปลี่ยนชื่อเป็น {0} โดย {1}", + "renameDm": "ห้องติดต่อของคุณถูกเปลี่ยนชื่อเป็น {0} ในเซิร์ฟเวอร์ของเรา", + "moveLog": "ห้องติดต่อนี้ถูกย้ายไปที่ {0} โดย {1}", + "moveDm": "ห้องติดต่อของคุณถูกย้ายไปที่ {0} ในเซิร์ฟเวอร์ของเรา", + "addLog": "{0} ถูกเพิ่มเข้ามาในห้องติดต่อนี้โดย {1}", + "addDm": "{0} ถูกเพิ่มเข้าไปในห้องติดต่อของคุณในเซิร์ฟเวอร์ของเรา", + "removeLog": "{0} ถูกลบออกจากห้องติดต่อนี้โดย {1}", + "removeDm": "{0} ถูกลบออกจากห้องติดต่อของคุณในเซิร์ฟเวอร์ของเรา", + + "blacklistAddLog": "{0} ถูกเพิ่มในรายชื่อดำโดย {1}", + "blacklistRemoveLog": "{0} ถูกนำออกจากรายชื่อดำโดย {1}", + "blacklistAddDm": "คุณถูกเพิ่มในรายชื่อดำของเรา\nจากนี้ไปคุณจะไม่สามารถสร้างห้องติดต่อได้", + "blacklistRemoveDm": "คุณถูกนำออกจากรายชื่อดำในเซิร์ฟเวอร์ของเรา\nตอนนี้คุณสามารถสร้างห้องติดต่อได้อีกครั้ง", + "clearLog": "{0} ห้องติดต่อถูกลบโดย {1}" + } + }, + "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": "เนื่องจากข้อจำกัดของ Discord การเปลี่ยนชื่อช่องไม่สามารถทำได้ในขณะนี้ ช่องจะถูกเปลี่ยนชื่อโดยอัตโนมัติในเวลา 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": "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": "บันทึกการสนทนาที่สร้าง" + } + } +} \ No newline at end of file diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index 86d7d36..db2cb24 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -460,6 +460,7 @@ export interface ODLanguageManagerIds_Default { "openticket:estonian":ODLanguage, "openticket:finnish":ODLanguage, "openticket:danish":ODLanguage, + "openticket:thai":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index f25fd03..61aff52 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -18,10 +18,11 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODLanguage("openticket:estonian","estonian.json")) openticket.languages.add(new api.ODLanguage("openticket:finnish","finnish.json")) openticket.languages.add(new api.ODLanguage("openticket:danish","danish.json")) + openticket.languages.add(new api.ODLanguage("openticket:thai","thai.json")) //list for config checker const languageList = openticket.defaults.getDefault("languageList") - languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian","indonesian","italian","estonian","finnish","danish") + languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian","indonesian","italian","estonian","finnish","danish","thai") openticket.defaults.setDefault("languageList",languageList) /** How to add more languages? From a31588f025426e7bc5f3420d9039e11223a4d7f4 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 18 Nov 2024 20:19:25 +0100 Subject: [PATCH 052/157] Small changes to the plugin loading system --- .gitignore | 1 + src/core/api/modules/plugin.ts | 17 ++++++++++++++++- src/core/startup/pluginLauncher.ts | 16 +++++++--------- src/index.ts | 2 ++ 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index aca1716..f210749 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ otdebug.txt */.DS_Store */*/.DS_Store */*/*/.DS_Store +**/.DS_Store TEMP/ .vscode/ plugins/* diff --git a/src/core/api/modules/plugin.ts b/src/core/api/modules/plugin.ts index 99b568d..31fd16b 100644 --- a/src/core/api/modules/plugin.ts +++ b/src/core/api/modules/plugin.ts @@ -80,7 +80,7 @@ export class ODPlugin extends ODManagerData { this.crashed = false } - //Get the startfile location relative to the ./plugins/ directory + /**Get the startfile location relative to the `./plugins/` directory. (`./dist/plugins/`) when compiled) */ getStartFile(){ const newFile = this.data.startFile.replace(/\.ts$/,".js") return nodepath.join(this.dir,newFile) @@ -113,6 +113,7 @@ export class ODPlugin extends ODManagerData { }else return true } + /**Check if a npm dependency exists. */ #checkDependency(id:string){ try{ require.resolve(id) @@ -122,6 +123,7 @@ export class ODPlugin extends ODManagerData { } } + /**Get a list of all missing npm dependencies that are required for this plugin. */ dependenciesInstalled(){ const missing: string[] = [] this.data.npmDependencies.forEach((d) => { @@ -132,6 +134,7 @@ export class ODPlugin extends ODManagerData { return missing } + /**Get a list of all missing plugins that are required for this plugin. */ pluginsInstalled(manager:ODPluginManager){ const missing: string[] = [] this.data.requiredPlugins.forEach((p) => { @@ -143,6 +146,18 @@ export class ODPlugin extends ODManagerData { return missing } + /**Get a list of all enabled incompatible plugins that interfere with this plugin. */ + pluginsIncompatible(manager:ODPluginManager){ + const incompatible: string[] = [] + this.data.incompatiblePlugins.forEach((p) => { + const plugin = manager.get(p) + if (plugin && plugin.enabled){ + incompatible.push(p) + } + }) + + return incompatible + } } export class ODPluginClassManager extends ODManager { diff --git a/src/core/startup/pluginLauncher.ts b/src/core/startup/pluginLauncher.ts index c14bfb9..4790aaf 100644 --- a/src/core/startup/pluginLauncher.ts +++ b/src/core/startup/pluginLauncher.ts @@ -91,22 +91,20 @@ export const loadAllPlugins = async () => { const missingDependencies: {id:string,missing:string}[] = [] const missingPlugins: {id:string,missing:string}[] = [] - //go trough all plugins for errors - sortedPlugins.forEach((plugin) => { + //go through all plugins for errors + sortedPlugins.filter((plugin) => plugin.enabled).forEach((plugin) => { const from = plugin.id.value - plugin.data.incompatiblePlugins.forEach((to) => { - //deny incompatibility if it already exists - if (incompatibilities.find((p) => (p.from == from && p.to == to) || (p.to == from && p.from == to))) return - - //check for existence of both plugins => add to list - if (openticket.plugins.exists(to)) incompatibilities.push({from,to}) - }) plugin.dependenciesInstalled().forEach((missing) => missingDependencies.push({id:from,missing})) + plugin.pluginsIncompatible(openticket.plugins).forEach((incompatible) => incompatibilities.push({from,to:incompatible})) plugin.pluginsInstalled(openticket.plugins).forEach((missing) => missingPlugins.push({id:from,missing})) }) //handle all incompatibilities + const alreadyLoggedCompatPlugins: string[] = [] incompatibilities.forEach((match) => { + if (alreadyLoggedCompatPlugins.includes(match.from) || alreadyLoggedCompatPlugins.includes(match.to)) return + else alreadyLoggedCompatPlugins.push(match.from,match.to) + const fromPlugin = openticket.plugins.get(match.from) if (fromPlugin && !fromPlugin.crashed){ fromPlugin.crashed = true diff --git a/src/index.ts b/src/index.ts index b4f30e5..209f7e3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -737,8 +737,10 @@ const main = async () => { if (openticket.defaults.getDefault("startScreenRendering")){ await openticket.startscreen.renderAllComponents() if (openticket.languages.getLanguageMetadata(false)?.automated){ + console.log("===================") openticket.log("You are currently using a language which has been translated by Google Translate!","warning") openticket.log("Please help us improve the translation by contributing to our project!","warning") + console.log("===================") } await openticket.events.get("afterStartScreensRendered").emit([openticket.startscreen]) From f8da68607d08a74c815249b8cffa4a536213ecff Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 18 Nov 2024 20:50:02 +0100 Subject: [PATCH 053/157] Update client.ts --- src/core/api/modules/client.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index 0753a9a..2e839bb 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -637,8 +637,6 @@ export type ODSlashCommandUpdateFunction = (current:ODSlashCommandBuilder) => bo export class ODSlashCommand extends ODManagerData { /**The discord.js builder for this slash command. */ builder: ODSlashCommandBuilder - /**The name of this slash command. */ - name: string /**The id of the guild this command is for. Null when not set. */ guildId: string|null /**Function to check if the slash command requires to be updated (when it already exists). */ @@ -649,10 +647,17 @@ export class ODSlashCommand extends ODManagerData { if (builder.type != discord.ApplicationCommandType.ChatInput) throw new ODSystemError("ApplicationCommandData is required to be the 'ChatInput' type!") this.builder = builder - this.name = builder.name this.guildId = guildId ?? null this.requiresUpdate = requiresUpdate ?? null } + + /**The name of this slash command. */ + get name(): string { + return this.builder.name + } + set name(name:string){ + this.builder.name = name + } } /**## ODTextCommandBuilderBaseOptionType `type` From 6b36b1caf6eb057772639aa107b8b0a3ed053463 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 21 Nov 2024 23:43:39 +0100 Subject: [PATCH 054/157] Update plugin.json --- plugins/example-plugin/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/example-plugin/plugin.json b/plugins/example-plugin/plugin.json index 76fd490..48549f7 100644 --- a/plugins/example-plugin/plugin.json +++ b/plugins/example-plugin/plugin.json @@ -1,5 +1,5 @@ { - "name":"Example Plugin", + "name":"OT Example Plugin", "id":"example-plugin", "version":"1.0.0", "startFile":"index.ts", From b22f7b2de75b97558ed52736f5301745a0fba5d5 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 24 Nov 2024 23:26:14 +0100 Subject: [PATCH 055/157] major bug fixes & breaking change in database code Major bug fixes and improvements have been made. There's also a breaking change for plugins using the database system. All database related functions are now async based. --- .gitignore | 3 +- README.md | 3 + plugins/example-plugin/README.md | 4 + plugins/example-plugin/plugin.json | 2 +- src/commands/ticket.ts | 2 +- src/core/api/defaults/database.ts | 122 ++++++++++++------------ src/core/api/modules/base.ts | 6 ++ src/core/api/modules/console.ts | 4 +- src/core/api/modules/database.ts | 38 ++++---- src/core/api/modules/language.ts | 2 + src/core/api/modules/stat.ts | 10 +- src/core/startup/init.ts | 2 +- src/core/startup/manageMigration.ts | 6 +- src/data/framework/codeLoader.ts | 42 ++++---- src/data/framework/permissionLoader.ts | 5 +- src/data/openticket/blacklistLoader.ts | 2 +- src/data/openticket/ticketLoader.ts | 2 +- src/data/openticket/transcriptLoader.ts | 4 + 18 files changed, 141 insertions(+), 118 deletions(-) create mode 100644 plugins/example-plugin/README.md diff --git a/.gitignore b/.gitignore index f210749..b9a2291 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ TEMP/ .vscode/ plugins/* !plugins/example-plugin/ -dist/ \ No newline at end of file +dist/ +database/openticket.sqlite \ No newline at end of file diff --git a/README.md b/README.md index f239086..defb6fd 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ You're also able to customise every little aspect of the bot! From embeds to tra > The translation count may not be accurate! ### 📌 Features +- **💩 no bloat/credits** - Your Open Ticket bot doesn't contain any form of bloat or credits! +- **📈 scalable** - Open Ticket is made to handle huge servers! Even if your server contains more than 100k members! - **📄 html transcripts** - Make use of the most customisable, beautiful and easy-to-use HTML Transcripts! - **✅ ticket actions** - Close, Reopen, Delete, Rename & Move all your tickets! - **🇬🇧 translation** - Open Ticket has been translated in more than **32 languages** by our community! @@ -40,6 +42,7 @@ You're also able to customise every little aspect of the bot! From embeds to tra - **📦 commands** - Open Ticket supports both slash & text commands! - **📥 extra types** - The bot also supports Reaction Roles & Url Buttons, because why not ¯\\_(ツ)_/¯ - **🎛️ dependencies** - We try to use as little external dependencies as needed! +- **📢 commands** - The bot contains more than 25 commands! And it's expandable with plugins! > ### 📦 Resources > Resources might not be accurate yet! *(because v4 is still in beta)*
diff --git a/plugins/example-plugin/README.md b/plugins/example-plugin/README.md new file mode 100644 index 0000000..0f11476 --- /dev/null +++ b/plugins/example-plugin/README.md @@ -0,0 +1,4 @@ +# Example Plugin +A simple example of an Open Ticket v4 plugin! + +> Use this plugin as a starter template for all your custom plugins! \ No newline at end of file diff --git a/plugins/example-plugin/plugin.json b/plugins/example-plugin/plugin.json index 48549f7..76fd490 100644 --- a/plugins/example-plugin/plugin.json +++ b/plugins/example-plugin/plugin.json @@ -1,5 +1,5 @@ { - "name":"OT Example Plugin", + "name":"Example Plugin", "id":"example-plugin", "version":"1.0.0", "startFile":"index.ts", diff --git a/src/commands/ticket.ts b/src/commands/ticket.ts index ffa00ea..5743e74 100644 --- a/src/commands/ticket.ts +++ b/src/commands/ticket.ts @@ -215,7 +215,7 @@ export const registerModalResponders = async () => { openticket.responders.modals.get("openticket:ticket-questions").workers.add([ new api.ODWorker("openticket:ticket-questions",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance - if (!channel) throw new api.ODSystemError("The 'Ticket Questions' modal Requires a channel for responding!") + if (!channel) throw new api.ODSystemError("The 'Ticket Questions' modal requires a channel for responding!") if (!guild){ //error instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) diff --git a/src/core/api/defaults/database.ts b/src/core/api/defaults/database.ts index 1805d90..a9d2d26 100644 --- a/src/core/api/defaults/database.ts +++ b/src/core/api/defaults/database.ts @@ -1,7 +1,7 @@ /////////////////////////////////////// //DEFAULT DATABASE MODULE /////////////////////////////////////// -import { ODValidId, ODValidJsonType } from "../modules/base" +import { ODOptionalPromise, ODValidId, ODValidJsonType } from "../modules/base" import { ODDatabaseManager, ODDatabase, ODFormattedJsonDatabase } from "../modules/database" import { ODTicketJson } from "../openticket/ticket" import { ODOptionJson } from "../openticket/option" @@ -65,38 +65,38 @@ export interface ODFormattedJsonDatabaseIds_DefaultGlobal { * This default class is made for the `global.json` database! */ export class ODFormattedJsonDatabase_DefaultGlobal extends ODFormattedJsonDatabase { - set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]): boolean - set(category:string, key:string, value:ODValidJsonType): boolean + set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]): ODOptionalPromise + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise - set(category:string, key:string, value:ODValidJsonType): boolean { + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise { return super.set(category,key,value) } - get(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]|undefined - get(category:string, key:string): ODValidJsonType|undefined + get(category:CategoryId, key:string): ODOptionalPromise + get(category:string, key:string): ODOptionalPromise - get(category:string, key:string): ODValidJsonType|undefined { + get(category:string, key:string): ODOptionalPromise { return super.get(category,key) } - delete(category:CategoryId, key:string): boolean - delete(category:string, key:string): boolean + delete(category:CategoryId, key:string): ODOptionalPromise + delete(category:string, key:string): ODOptionalPromise - delete(category:string, key:string): boolean { + delete(category:string, key:string): ODOptionalPromise { return super.delete(category,key) } - exists(category:keyof ODFormattedJsonDatabaseIds_DefaultGlobal, key:string): boolean - exists(category:string, key:string): boolean + exists(category:keyof ODFormattedJsonDatabaseIds_DefaultGlobal, key:string): ODOptionalPromise + exists(category:string, key:string): ODOptionalPromise - exists(category:string, key:string): boolean { + exists(category:string, key:string): ODOptionalPromise { return super.exists(category,key) } - getCategory(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]}[]|undefined - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined + getCategory(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]}[]|undefined> + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> { return super.getCategory(category) } } @@ -116,38 +116,38 @@ export interface ODFormattedJsonDatabaseIds_DefaultTickets { * This default class is made for the `tickets.json` database! */ export class ODFormattedJsonDatabase_DefaultTickets extends ODFormattedJsonDatabase { - set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]): boolean - set(category:string, key:string, value:ODValidJsonType): boolean + set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]): ODOptionalPromise + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise - set(category:string, key:string, value:ODValidJsonType): boolean { + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise { return super.set(category,key,value) } - get(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]|undefined - get(category:string, key:string): ODValidJsonType|undefined + get(category:CategoryId, key:string): ODOptionalPromise + get(category:string, key:string): ODOptionalPromise - get(category:string, key:string): ODValidJsonType|undefined { + get(category:string, key:string): ODOptionalPromise { return super.get(category,key) } - delete(category:CategoryId, key:string): boolean - delete(category:string, key:string): boolean + delete(category:CategoryId, key:string): ODOptionalPromise + delete(category:string, key:string): ODOptionalPromise - delete(category:string, key:string): boolean { + delete(category:string, key:string): ODOptionalPromise { return super.delete(category,key) } - exists(category:keyof ODFormattedJsonDatabaseIds_DefaultTickets, key:string): boolean - exists(category:string, key:string): boolean + exists(category:keyof ODFormattedJsonDatabaseIds_DefaultTickets, key:string): ODOptionalPromise + exists(category:string, key:string): ODOptionalPromise - exists(category:string, key:string): boolean { + exists(category:string, key:string): ODOptionalPromise { return super.exists(category,key) } - getCategory(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]}[]|undefined - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined + getCategory(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]}[]|undefined> + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> { return super.getCategory(category) } } @@ -167,38 +167,38 @@ export interface ODFormattedJsonDatabaseIds_DefaultUsers { * This default class is made for the `users.json` database! */ export class ODFormattedJsonDatabase_DefaultUsers extends ODFormattedJsonDatabase { - set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]): boolean - set(category:string, key:string, value:ODValidJsonType): boolean + set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]): ODOptionalPromise + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise - set(category:string, key:string, value:ODValidJsonType): boolean { + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise { return super.set(category,key,value) } - get(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]|undefined - get(category:string, key:string): ODValidJsonType|undefined + get(category:CategoryId, key:string): ODOptionalPromise + get(category:string, key:string): ODOptionalPromise - get(category:string, key:string): ODValidJsonType|undefined { + get(category:string, key:string): ODOptionalPromise { return super.get(category,key) } - delete(category:CategoryId, key:string): boolean - delete(category:string, key:string): boolean + delete(category:CategoryId, key:string): ODOptionalPromise + delete(category:string, key:string): ODOptionalPromise - delete(category:string, key:string): boolean { + delete(category:string, key:string): ODOptionalPromise { return super.delete(category,key) } - exists(category:keyof ODFormattedJsonDatabaseIds_DefaultUsers, key:string): boolean - exists(category:string, key:string): boolean + exists(category:keyof ODFormattedJsonDatabaseIds_DefaultUsers, key:string): ODOptionalPromise + exists(category:string, key:string): ODOptionalPromise - exists(category:string, key:string): boolean { + exists(category:string, key:string): ODOptionalPromise { return super.exists(category,key) } - getCategory(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]}[]|undefined - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined + getCategory(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]}[]|undefined> + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> { return super.getCategory(category) } } @@ -219,38 +219,38 @@ export interface ODFormattedJsonDatabaseIds_DefaultOptions { * This default class is made for the `options.json` database! */ export class ODFormattedJsonDatabase_DefaultOptions extends ODFormattedJsonDatabase { - set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]): boolean - set(category:string, key:string, value:ODValidJsonType): boolean + set(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]): ODOptionalPromise + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise - set(category:string, key:string, value:ODValidJsonType): boolean { + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise { return super.set(category,key,value) } - get(category:CategoryId, key:string): ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]|undefined - get(category:string, key:string): ODValidJsonType|undefined + get(category:CategoryId, key:string): ODOptionalPromise + get(category:string, key:string): ODOptionalPromise - get(category:string, key:string): ODValidJsonType|undefined { + get(category:string, key:string): ODOptionalPromise { return super.get(category,key) } - delete(category:CategoryId, key:string): boolean - delete(category:string, key:string): boolean + delete(category:CategoryId, key:string): ODOptionalPromise + delete(category:string, key:string): ODOptionalPromise - delete(category:string, key:string): boolean { + delete(category:string, key:string): ODOptionalPromise { return super.delete(category,key) } - exists(category:keyof ODFormattedJsonDatabaseIds_DefaultOptions, key:string): boolean - exists(category:string, key:string): boolean + exists(category:keyof ODFormattedJsonDatabaseIds_DefaultOptions, key:string): ODOptionalPromise + exists(category:string, key:string): ODOptionalPromise - exists(category:string, key:string): boolean { + exists(category:string, key:string): ODOptionalPromise { return super.exists(category,key) } - getCategory(category:CategoryId): {key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]}[]|undefined - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined + getCategory(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]}[]|undefined> + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> { return super.getCategory(category) } } \ No newline at end of file diff --git a/src/core/api/modules/base.ts b/src/core/api/modules/base.ts index ed76818..b422fce 100644 --- a/src/core/api/modules/base.ts +++ b/src/core/api/modules/base.ts @@ -9,6 +9,12 @@ import { ODConsoleWarningMessage, ODDebugger } from "./console" */ export type ODPromiseVoid = void|Promise +/**## ODOptionalPromise `type` + * This is a simple type to represent a type as normal value or a promise value. + */ +export type ODOptionalPromise = T|Promise + + /**## ODValidButtonColor `type` * This is a collection of all the possible button colors. */ diff --git a/src/core/api/modules/console.ts b/src/core/api/modules/console.ts index 6c1afc3..b6e0943 100644 --- a/src/core/api/modules/console.ts +++ b/src/core/api/modules/console.ts @@ -391,9 +391,9 @@ export class ODDebugFileManager { writeText(text:string){ this.#writeDebugFile(text) } - /**Write a custom note to the debug file (starting with `[NODE]:`) */ + /**Write a custom note to the debug file (starting with `[NOTE]:`) */ writeNote(text:string){ - this.#writeDebugFile("[NODE]: "+text) + this.#writeDebugFile("[NOTE]: "+text) } } diff --git a/src/core/api/modules/database.ts b/src/core/api/modules/database.ts index e25eb2d..9bb9966 100644 --- a/src/core/api/modules/database.ts +++ b/src/core/api/modules/database.ts @@ -1,7 +1,7 @@ /////////////////////////////////////// //DATABASE MODULE /////////////////////////////////////// -import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId, ODValidJsonType } from "./base" +import { ODId, ODManager, ODManagerData, ODOptionalPromise, ODSystemError, ODValidId, ODValidJsonType } from "./base" import fs from "fs" import nodepath from "path" import { ODDebugger } from "./console" @@ -87,27 +87,27 @@ export class ODDatabase extends ODManagerData { file: string = "" /**Add/Overwrite a specific category & key in the database. Returns `true` when overwritten. */ - set(category:string, key:string, value:ODValidJsonType): boolean { + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise { return false } /**Get a specific category & key in the database */ - get(category:string, key:string): ODValidJsonType|undefined { + get(category:string, key:string): ODOptionalPromise { return undefined } /**Delete a specific category & key in the database */ - delete(category:string, key:string): boolean { + delete(category:string, key:string): ODOptionalPromise { return false } /**Check if a specific category & key exists in the database */ - exists(category:string, key:string): boolean { + exists(category:string, key:string): ODOptionalPromise { return false } /**Get a specific category in the database */ - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> { return undefined } /**Get all values in the database */ - getAll(): ODJsonDatabaseStructure { + getAll(): ODOptionalPromise { return [] } } @@ -145,7 +145,7 @@ export class ODJsonDatabase extends ODDatabase { * const didOverwrite = database.setData("category","key","value") //value can be any of the valid types * //You need an ODJsonDatabase class named "database" for this example to work! */ - set(category:string, key:string, value:ODValidJsonType): boolean { + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise { const currentList = this.#system.getData() const currentData = currentList.find((d) => (d.category === category) && (d.key === key)) @@ -164,7 +164,7 @@ export class ODJsonDatabase extends ODDatabase { * const data = database.getData("category","key") //data will be the value * //You need an ODJsonDatabase class named "database" for this example to work! */ - get(category:string, key:string): ODValidJsonType|undefined { + get(category:string, key:string): ODOptionalPromise { const currentList = this.#system.getData() const tempresult = currentList.find((d) => (d.category === category) && (d.key === key)) return tempresult ? tempresult.value : undefined @@ -174,7 +174,7 @@ export class ODJsonDatabase extends ODDatabase { * const didExist = database.deleteData("category","key") //delete this value * //You need an ODJsonDatabase class named "database" for this example to work! */ - delete(category:string, key:string): boolean { + delete(category:string, key:string): ODOptionalPromise { const currentList = this.#system.getData() const currentData = currentList.find((d) => (d.category === category) && (d.key === key)) if (currentData) currentList.splice(currentList.indexOf(currentData),1) @@ -183,19 +183,19 @@ export class ODJsonDatabase extends ODDatabase { return currentData ? true : false } /**Check if a value of `category` & `key` exists. Returns `false` when non-existent! */ - exists(category:string, key:string): boolean { + exists(category:string, key:string): ODOptionalPromise { const currentList = this.#system.getData() const tempresult = currentList.find((d) => (d.category === category) && (d.key === key)) return tempresult ? true : false } /**Get all values in `category`. Returns `undefined` when non-existent! */ - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> { const currentList = this.#system.getData() const tempresult = currentList.filter((d) => (d.category === category)) return tempresult ? tempresult.map((data) => {return {key:data.key,value:data.value}}) : undefined } /**Get all values in `category`. */ - getAll(): ODJsonDatabaseStructure { + getAll(): ODOptionalPromise { return this.#system.getData() } @@ -249,7 +249,7 @@ export class ODFormattedJsonDatabase extends ODDatabase { * const didOverwrite = database.setData("category","key","value") //value can be any of the valid types * //You need an ODFormattedJsonDatabase class named "database" for this example to work! */ - set(category:string, key:string, value:ODValidJsonType): boolean { + set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise { const currentList = this.#system.getData() const currentData = currentList.find((d) => (d.category === category) && (d.key === key)) @@ -268,7 +268,7 @@ export class ODFormattedJsonDatabase extends ODDatabase { * const data = database.getData("category","key") //data will be the value * //You need an ODFormattedJsonDatabase class named "database" for this example to work! */ - get(category:string, key:string): ODValidJsonType|undefined { + get(category:string, key:string): ODOptionalPromise { const currentList = this.#system.getData() const tempresult = currentList.find((d) => (d.category === category) && (d.key === key)) return tempresult ? tempresult.value : undefined @@ -278,7 +278,7 @@ export class ODFormattedJsonDatabase extends ODDatabase { * const didExist = database.deleteData("category","key") //delete this value * //You need an ODFormattedJsonDatabase class named "database" for this example to work! */ - delete(category:string, key:string): boolean { + delete(category:string, key:string): ODOptionalPromise { const currentList = this.#system.getData() const currentData = currentList.find((d) => (d.category === category) && (d.key === key)) if (currentData) currentList.splice(currentList.indexOf(currentData),1) @@ -287,19 +287,19 @@ export class ODFormattedJsonDatabase extends ODDatabase { return currentData ? true : false } /**Check if a value of `category` & `key` exists. Returns `false` when non-existent! */ - exists(category:string, key:string): boolean { + exists(category:string, key:string): ODOptionalPromise { const currentList = this.#system.getData() const tempresult = currentList.find((d) => (d.category === category) && (d.key === key)) return tempresult ? true : false } /**Get all values in `category`. Returns `undefined` when non-existent! */ - getCategory(category:string): {key:string, value:ODValidJsonType}[]|undefined { + getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> { const currentList = this.#system.getData() const tempresult = currentList.filter((d) => (d.category === category)) return tempresult ? tempresult.map((data) => {return {key:data.key,value:data.value}}) : undefined } /**Get all values in `category`. */ - getAll(): ODJsonDatabaseStructure { + getAll(): ODOptionalPromise { return this.#system.getData() } diff --git a/src/core/api/modules/language.ts b/src/core/api/modules/language.ts index 2e329f9..6a18c61 100644 --- a/src/core/api/modules/language.ts +++ b/src/core/api/modules/language.ts @@ -19,7 +19,9 @@ export class ODLanguage extends ODManagerData { file: string /**The path to the file relative to the main directory. */ path: string + /**The raw object data of the translation. */ data: any + /**The metadata of the language if available. */ metadata: ODLanguageMetadata|null = null constructor(id:ODValidId, file:string, customPath?:string){ diff --git a/src/core/api/modules/stat.ts b/src/core/api/modules/stat.ts index 3ca36e0..baff800 100644 --- a/src/core/api/modules/stat.ts +++ b/src/core/api/modules/stat.ts @@ -42,13 +42,14 @@ export class ODStatsManager extends ODManager { //filter out the deletable stats const deletableStats: ODJsonDatabaseStructure = [] - this.database.getAll().forEach((data) => { + const data = await this.database.getAll() + data.forEach((data) => { if (!validCategories.includes(data.category)) deletableStats.push(data) }) //do additional deletion for (const cb of this.#initListeners){ - await cb(this.database.getAll(),deletableStats) + await cb(data,deletableStats) } //delete all deletable stats @@ -57,9 +58,10 @@ export class ODStatsManager extends ODManager { this.database.delete(data.category,data.key) }) } - reset(){ + async reset(){ if (!this.database) return - this.database.getAll().forEach((data) => { + const data = await this.database.getAll() + data.forEach((data) => { if (!this.database) return this.database.delete(data.category,data.key) }) diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index 2a7867d..fb089dd 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -87,7 +87,7 @@ interface ODUtilities { */ emojiTitle(emoji:string, text:string): string /**## runAsync `utility function` - * Use this function to run a piece of code asyncronous without creating a separate function for it! + * Use this function to run a snippet of code asyncronous without creating a separate function for it! */ runAsync(func:() => Promise): void /**## timedAwait `utility function` diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index 32194e3..1b5bc7a 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -4,7 +4,7 @@ export const loadVersionMigrationSystem = async () => { //ENTER MIGRATION CONTEXT await preloadMigrationContext() - const lastVersion = isMigrationRequired() + const lastVersion = await isMigrationRequired() openticket.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("openticket:last-version",openticket.versions.get("openticket:version").toString())) if (lastVersion && !openticket.flags.get("openticket:no-migration").value){ //MIGRATION IS REQUIRED @@ -48,8 +48,8 @@ const unloadMigrationContext = async () => { openticket.debug.debug("-- MIGRATION CONTEXT END --") } -const isMigrationRequired = (): false|api.ODVersion => { - const rawVersion = openticket.databases.get("openticket:global").get("openticket:last-version","openticket:version") +const isMigrationRequired = async (): Promise => { + const rawVersion = await openticket.databases.get("openticket:global").get("openticket:last-version","openticket:version") if (!rawVersion) return false const version = api.ODVersion.fromString("openticket:last-version",rawVersion) if (openticket.versions.get("openticket:version").compare(version) == "higher"){ diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index 0699c17..ab358b2 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -73,7 +73,7 @@ export const loadDatabaseCleanersCode = async () => { const validPanels: string[] = [] //check global database for valid panel embeds - for (const panel of (globalDatabase.getCategory("openticket:panel-update") ?? [])){ + for (const panel of (await globalDatabase.getCategory("openticket:panel-update") ?? [])){ if (!validPanels.includes(panel.key)){ try{ const splittedId = panel.key.split("_") @@ -84,7 +84,7 @@ export const loadDatabaseCleanersCode = async () => { } //remove all unused panels - for (const panel of (globalDatabase.getCategory("openticket:panel-update") ?? [])){ + for (const panel of (await globalDatabase.getCategory("openticket:panel-update") ?? [])){ if (!validPanels.includes(panel.key)){ globalDatabase.delete("openticket:panel-update",panel.key) } @@ -104,28 +104,28 @@ export const loadDatabaseCleanersCode = async () => { const validSuffixHistories: string[] = [] //check global database for valid option suffix counters - for (const counter of (globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ + for (const counter of (await globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ if (!validSuffixCounters.includes(counter.key)){ if (openticket.options.exists(counter.key)) validSuffixCounters.push(counter.key) } } //check global database for valid option suffix histories - for (const history of (globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ + for (const history of (await globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ if (!validSuffixHistories.includes(history.key)){ if (openticket.options.exists(history.key)) validSuffixHistories.push(history.key) } } //remove all unused suffix counters - for (const counter of (globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ + for (const counter of (await globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ if (!validSuffixCounters.includes(counter.key)){ globalDatabase.delete("openticket:option-suffix-counter",counter.key) } } //remove all unused suffix histories - for (const history of (globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ + for (const history of (await globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ if (!validSuffixHistories.includes(history.key)){ globalDatabase.delete("openticket:option-suffix-history",history.key) } @@ -148,7 +148,7 @@ export const loadDatabaseCleanersCode = async () => { const validUsers: string[] = [] //check user database for valid users - for (const user of userDatabase.getAll()){ + for (const user of (await userDatabase.getAll())){ if (!validUsers.includes(user.key)){ try{ const member = await mainServer.members.fetch(user.key) @@ -158,7 +158,7 @@ export const loadDatabaseCleanersCode = async () => { } //check stats database for valid users - for (const stat of statsDatabase.getAll()){ + for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:user_")){ if (!validUsers.includes(stat.key)){ try{ @@ -170,14 +170,14 @@ export const loadDatabaseCleanersCode = async () => { } //remove all unused users - for (const user of userDatabase.getAll()){ + for (const user of (await userDatabase.getAll())){ if (!validUsers.includes(user.key)){ userDatabase.delete(user.category,user.key) } } //remove all unused stats - for (const stat of statsDatabase.getAll()){ + for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:user_")){ if (!validUsers.includes(stat.key)){ statsDatabase.delete(stat.category,stat.key) @@ -187,18 +187,18 @@ export const loadDatabaseCleanersCode = async () => { }) //delete user from database on leave - openticket.client.client.on("guildMemberRemove",(member) => { + openticket.client.client.on("guildMemberRemove",async (member) => { if (member.guild.id != mainServer.id) return //remove unused user - for (const user of userDatabase.getAll()){ + for (const user of (await userDatabase.getAll())){ if (user.key == member.id){ userDatabase.delete(user.category,user.key) } } //remove unused stats - for (const stat of statsDatabase.getAll()){ + for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:user_")){ if (stat.key == member.id){ statsDatabase.delete(stat.category,stat.key) @@ -213,7 +213,7 @@ export const loadDatabaseCleanersCode = async () => { const validTickets: string[] = [] //check ticket database for valid tickets - for (const ticket of ticketDatabase.getAll()){ + for (const ticket of (await ticketDatabase.getAll())){ if (!validTickets.includes(ticket.key)){ try{ const channel = await openticket.client.fetchGuildTextChannel(mainServer,ticket.key) @@ -223,7 +223,7 @@ export const loadDatabaseCleanersCode = async () => { } //check stats database for valid tickets - for (const stat of statsDatabase.getAll()){ + for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:ticket_")){ if (!validTickets.includes(stat.key)){ try{ @@ -235,7 +235,7 @@ export const loadDatabaseCleanersCode = async () => { } //remove all unused tickets - for (const ticket of ticketDatabase.getAll()){ + for (const ticket of (await ticketDatabase.getAll())){ if (!validTickets.includes(ticket.key)){ ticketDatabase.delete(ticket.category,ticket.key) openticket.tickets.remove(ticket.key) @@ -243,7 +243,7 @@ export const loadDatabaseCleanersCode = async () => { } //remove all unused stats - for (const stat of statsDatabase.getAll()){ + for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:ticket_")){ if (!validTickets.includes(stat.key)){ statsDatabase.delete(stat.category,stat.key) @@ -252,11 +252,11 @@ export const loadDatabaseCleanersCode = async () => { } //delete ticket from database on delete - openticket.client.client.on("channelDelete",(channel) => { + openticket.client.client.on("channelDelete",async (channel) => { if (channel.isDMBased() || channel.guild.id != mainServer.id) return //remove unused ticket - for (const ticket of ticketDatabase.getAll()){ + for (const ticket of (await ticketDatabase.getAll())){ if (ticket.key == channel.id){ ticketDatabase.delete(ticket.category,ticket.key) openticket.tickets.remove(ticket.key) @@ -264,7 +264,7 @@ export const loadDatabaseCleanersCode = async () => { } //remove unused stats - for (const stat of statsDatabase.getAll()){ + for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:ticket_")){ if (stat.key == channel.id){ statsDatabase.delete(stat.category,stat.key) @@ -279,7 +279,7 @@ export const loadPanelAutoUpdateCode = async () => { //PANEL AUTO UPDATE openticket.code.add(new api.ODCode("openticket:panel-auto-update",7,async () => { const globalDatabase = openticket.databases.get("openticket:global") - const panelIds = globalDatabase.getCategory("openticket:panel-update") ?? [] + const panelIds = await globalDatabase.getCategory("openticket:panel-update") ?? [] if (!mainServer) return for (const panelId of panelIds){ diff --git a/src/data/framework/permissionLoader.ts b/src/data/framework/permissionLoader.ts index 9966f69..44eb881 100644 --- a/src/data/framework/permissionLoader.ts +++ b/src/data/framework/permissionLoader.ts @@ -38,14 +38,15 @@ export const loadAllPermissions = async () => { const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] - admins.concat(readAdmins).forEach(async (admin) => { + for (const admin of admins.concat(readAdmins)){ + if (openticket.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return const role = await mainServer.roles.fetch(admin) if (!role) return openticket.log("Unable to register permission for ticket admin!","error",[ {key:"roleid",value:admin} ]) openticket.permissions.add(new api.ODPermission("openticket:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) - }) + } }catch(err){ process.emit("uncaughtException",err) openticket.log("Ticket Admin Loading Permissions Error (see above)","error") diff --git a/src/data/openticket/blacklistLoader.ts b/src/data/openticket/blacklistLoader.ts index 49c4a68..6676b98 100644 --- a/src/data/openticket/blacklistLoader.ts +++ b/src/data/openticket/blacklistLoader.ts @@ -4,7 +4,7 @@ export const loadAllBlacklistedUsers = async () => { const userDatabase = openticket.databases.get("openticket:users") if (!userDatabase) return - const users = userDatabase.getCategory("openticket:blacklist") ?? [] + const users = await userDatabase.getCategory("openticket:blacklist") ?? [] users.forEach((user) => { if (typeof user.value == "string" || user.value === null) openticket.blacklist.add(new api.ODBlacklist(user.key,user.value)) }) diff --git a/src/data/openticket/ticketLoader.ts b/src/data/openticket/ticketLoader.ts index ea89958..93d7811 100644 --- a/src/data/openticket/ticketLoader.ts +++ b/src/data/openticket/ticketLoader.ts @@ -6,7 +6,7 @@ export const loadAllTickets = async () => { const ticketDatabase = openticket.databases.get("openticket:tickets") if (!ticketDatabase) return - const tickets = ticketDatabase.getCategory("openticket:ticket") + const tickets = await ticketDatabase.getCategory("openticket:ticket") if (!tickets) return tickets.forEach((ticket) => { try { diff --git a/src/data/openticket/transcriptLoader.ts b/src/data/openticket/transcriptLoader.ts index 36c3419..3f46803 100644 --- a/src/data/openticket/transcriptLoader.ts +++ b/src/data/openticket/transcriptLoader.ts @@ -178,12 +178,16 @@ export const loadAllTranscriptCompilers = async () => { const req = new api.ODHTTPGetRequest("https://apis.dj-dj.be/transcripts/status.json",false) const res = await req.run() if (!res || res.status != 200 || !res.body){ + openticket.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} } 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{ + openticket.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} } From 3e928ed06ed80b244eafd86a982bf9b95459c874 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 25 Nov 2024 19:24:48 +0100 Subject: [PATCH 056/157] Bug fixes for new database system --- src/commands/panel.ts | 2 +- src/core/api/defaults/event.ts | 4 + src/core/api/modules/config.ts | 71 ++++++---------- src/core/api/modules/database.ts | 121 +++++++++------------------- src/core/api/modules/defaults.ts | 6 ++ src/core/api/openticket/option.ts | 23 ++++-- src/core/startup/manageMigration.ts | 4 +- src/data/framework/codeLoader.ts | 78 +++++++++--------- src/data/framework/eventLoader.ts | 4 + src/data/openticket/ticketLoader.ts | 14 ++-- src/index.ts | 14 ++++ 11 files changed, 161 insertions(+), 180 deletions(-) diff --git a/src/commands/panel.ts b/src/commands/panel.ts index 0a7a184..0eb103e 100644 --- a/src/commands/panel.ts +++ b/src/commands/panel.ts @@ -67,7 +67,7 @@ export const registerCommandResponders = async () => { //add panel to database on auto-update if (instance.options.getBoolean("auto-update",false)){ const globalDatabase = openticket.databases.get("openticket:global") - globalDatabase.set("openticket:panel-update",panelMessage.channel.id+"_"+panelMessage.id,panel.id.value) + await globalDatabase.set("openticket:panel-update",panelMessage.channel.id+"_"+panelMessage.id,panel.id.value) } }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts index 200af2d..7c6ec37 100644 --- a/src/core/api/defaults/event.ts +++ b/src/core/api/defaults/event.ts @@ -64,10 +64,14 @@ export interface ODEventIds_Default { //configs "onConfigLoad": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> "afterConfigsLoaded": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> + "onConfigInit": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> + "afterConfigsInitiated": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> //databases "onDatabaseLoad": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid> "afterDatabasesLoaded": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid> + "onDatabaseInit": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid> + "afterDatabasesInitiated": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid> //languages "onLanguageLoad": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid> diff --git a/src/core/api/modules/config.ts b/src/core/api/modules/config.ts index acc2f2a..8e635ed 100644 --- a/src/core/api/modules/config.ts +++ b/src/core/api/modules/config.ts @@ -1,7 +1,7 @@ /////////////////////////////////////// //CONFIG MODULE /////////////////////////////////////// -import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base" +import { ODId, ODManager, ODManagerData, ODPromiseVoid, ODSystemError, ODValidId } from "./base" import nodepath from "path" import { ODDebugger } from "./console" import fs from "fs" @@ -12,51 +12,20 @@ import fs from "fs" * It manages all config files in the bot and allows plugins to access config files from open ticket & other plugins! * * You will use this class to get/add a config file (`ODConfig`) in your plugin! - * @example - * //get ./config/general.json => ODConfig class - * const generalConfig = openticket.configs.get("openticket:general") - * - * //add a new config with id "test" => ./config/test.json - * const testConfig = new api.ODConfig("test","test.json") - * openticket.configs.add(testConfig) */ export class ODConfigManager extends ODManager { constructor(debug:ODDebugger){ super(debug,"config") } - - /**Add data to the manager. The id will be fetched from the data class! You can optionally select to overwrite existing data! - * @example - * //add a new config with id "test" => ./config/test.json - * const testConfig = new api.ODConfig("test","test.json") - * openticket.configs.add(testConfig) - */ - add(data:ODConfig, overwrite?:boolean): boolean { - return super.add(data,overwrite) - } - /**Get data that matches the `ODId`. Returns the found data. - * @example - * //get "./config/general.json" (ot-general) => ODConfig class - * const generalConfig = openticket.configs.get("openticket:general") - */ - get(id:ODValidId): ODConfig|null { - return super.get(id) - } - /**Remove data that matches the `ODId`. Returns the removed data. - * @example - * //remove the "test" config - * openticket.configs.remove("test") //returns null if non-existing - */ - remove(id:ODValidId): ODConfig|null { - return super.remove(id) - } - /**Check if data that matches the `ODId` exists. Returns a boolean. - * @example - * //check if "./config/general.json" (ot-general) exists => boolean - * const exists = openticket.configs.exists("openticket:general") - */ - exists(id:ODValidId): boolean { - return super.exists(id) + /**Init all config files. */ + async init(){ + for (const config of this.getAll()){ + try{ + await config.init() + }catch(err){ + process.emit("uncaughtException",new ODSystemError(err)) + } + } } } @@ -72,7 +41,17 @@ export class ODConfig extends ODManagerData { /**The path to the file relative to the main directory. */ path: string = "" /**An object/array of the entire config file! Variables inside it can be edited while the bot is running! */ - data: any = undefined + data: any + + constructor(id:ODValidId, data:any){ + super(id) + this.data = data + } + + /**Init the config. */ + init(): ODPromiseVoid { + //nothing + } } /**## ODJsonConfig `class` @@ -90,10 +69,13 @@ export class ODJsonConfig extends ODConfig { #reloadListeners: Function[] = [] constructor(id:ODValidId, file:string, customPath?:string){ - super(id) + super(id,{}) this.file = (file.endsWith(".json")) ? file : file+".json" this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./config/",this.file) - + } + + /**Init the config. */ + init(): ODPromiseVoid { if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!") try{ this.data = JSON.parse(fs.readFileSync(this.path).toString()) @@ -102,7 +84,6 @@ export class ODJsonConfig extends ODConfig { throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\"!") } } - /**Reload the JSON file. Be aware that this doesn't update classes that used individual parts of the config data! */ reload(){ if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!") diff --git a/src/core/api/modules/database.ts b/src/core/api/modules/database.ts index 9bb9966..24d4ab9 100644 --- a/src/core/api/modules/database.ts +++ b/src/core/api/modules/database.ts @@ -1,7 +1,7 @@ /////////////////////////////////////// //DATABASE MODULE /////////////////////////////////////// -import { ODId, ODManager, ODManagerData, ODOptionalPromise, ODSystemError, ODValidId, ODValidJsonType } from "./base" +import { ODId, ODManager, ODManagerData, ODOptionalPromise, ODPromiseVoid, ODSystemError, ODValidId, ODValidJsonType } from "./base" import fs from "fs" import nodepath from "path" import { ODDebugger } from "./console" @@ -13,51 +13,21 @@ import * as fjs from "formatted-json-stringify" * It manages all databases in the bot and allows to permanently store data from the bot! * * You will use this class to get/add a database (`ODDatabase`) in your plugin! - * @example - * //get ./database/ot-global.json => ODDatabase class - * const globalDB = openticket.databases.get("openticket:global") - * - * //add a new database with id "test" => ./database/idk-test.json - * const testDatabase = new api.ODDatabase("test","idk-test.json") - * openticket.databases.add(testDatabase) */ export class ODDatabaseManager extends ODManager { constructor(debug:ODDebugger){ super(debug,"database") } - /**Add data to the manager. The id will be fetched from the data class! You can optionally select to overwrite existing data! - * @example - * //add a new database with id "test" => ./database/idk-test.json - * const testDatabase = new api.ODDatabase("test","idk-test.json") - * openticket.databases.add(testDatabase) - */ - add(data:ODDatabase, overwrite?:boolean): boolean { - return super.add(data,overwrite) - } - /**Get data that matches the `ODId`. Returns the found data. - * @example - * //get ./database/ot-global.json => ODDatabase class - * const globalDB = openticket.databases.get("openticket:global") - */ - get(id:ODValidId): ODDatabase|null { - return super.get(id) - } - /**Remove data that matches the `ODId`. Returns the removed data. - * @example - * //remove the "test" database - * openticket.databases.remove("test") //returns null if non-existing - */ - remove(id:ODValidId): ODDatabase|null { - return super.remove(id) - } - /**Check if data that matches the `ODId` exists. Returns a boolean. - * @example - * //check if "./database/idk-test.json" (test) exists => boolean - * const exists = openticket.databases.exists("test") - */ - exists(id:ODValidId): boolean { - return super.exists(id) + /**Init all database files. */ + async init(){ + for (const database of this.getAll()){ + try{ + await database.init() + }catch(err){ + process.emit("uncaughtException",new ODSystemError(err)) + } + } } } @@ -66,26 +36,17 @@ export class ODDatabaseManager extends ODManager { * This class doesn't do anything at all, it just gives a template & basic methods for a database. Use `ODJsonDatabase` instead! * * You will only use this class if you want to create your own database implementation (e.g. `mongodb`, `mysql`,...)! - * @example - * class SomeDatabase extends ODDatabase { - * //override this method - * setData(category:string, key:string, value:ODValidJsonType): boolean { - * return false - * } - * //override this method - * getData(category:string, key:string): ODValidJsonType|undefined { - * return undefined - * } - * //override this method - * deleteData(category:string, key:string): boolean { - * return false - * } - * } */ export class ODDatabase extends ODManagerData { - /**The full path to this database with extension */ + /**The name of the file with extension. */ file: string = "" + /**The path to the file relative to the main directory. */ + path: string = "" + /**Init the database. */ + init(): ODPromiseVoid { + //nothing + } /**Add/Overwrite a specific category & key in the database. Returns `true` when overwritten. */ set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise { return false @@ -122,24 +83,19 @@ export type ODJsonDatabaseStructure = {category:string, key:string, value:ODVali * It stores data in a `json` file as a large `Array` using the `category`, `key`, `value` strategy. * You can store the following types: `string`, `number`, `boolean`, `array`, `object` & `null`! * - * You will only use this class if you want to create your own database or use an existing one! - * @example - * //get,set & delete data - * const data = database.getData("category","key") //data will be the value - * const didOverwrite = database.setData("category","key","value") //value can be any of the valid types - * const didExist = database.deleteData("category","key") //delete this value - * //You need an ODJsonDatabase class named "database" for this example to work! + * You will use this class if you want to create your own database or use an existing one! */ export class ODJsonDatabase extends ODDatabase { constructor(id:ODValidId, file:string, customPath?:string){ super(id) - const filename = (file.endsWith(".json")) ? file : file+".json" - this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./database/",filename) - - //init file if it doesn't exist yet - this.#system.getData() + this.file = (file.endsWith(".json")) ? file : file+".json" + this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./database/",this.file) } + /**Init the database. */ + init(): ODPromiseVoid { + this.#system.getData() + } /**Set/overwrite the value of `category` & `key`. Returns `true` when overwritten! * @example * const didOverwrite = database.setData("category","key","value") //value can be any of the valid types @@ -202,21 +158,21 @@ export class ODJsonDatabase extends ODDatabase { #system = { /**Read parsed data from the json file */ getData: (): ODJsonDatabaseStructure => { - if (fs.existsSync(this.file)){ + if (fs.existsSync(this.path)){ try{ - return JSON.parse(fs.readFileSync(this.file).toString()) + return JSON.parse(fs.readFileSync(this.path).toString()) }catch(err){ process.emit("uncaughtException",err) - throw new ODSystemError("Unable to read database "+this.file+"! getData() read error. (see error above)") + throw new ODSystemError("Unable to read database "+this.path+"! getData() read error. (see error above)") } }else{ - fs.writeFileSync(this.file,"[]") + fs.writeFileSync(this.path,"[]") return [] } }, /**Write parsed data to the json file */ setData: (data:ODJsonDatabaseStructure) => { - fs.writeFileSync(this.file,JSON.stringify(data,null,"\t")) + fs.writeFileSync(this.path,JSON.stringify(data,null,"\t")) } } } @@ -236,14 +192,15 @@ export class ODFormattedJsonDatabase extends ODDatabase { constructor(id:ODValidId, file:string, formatter:fjs.ArrayFormatter, customPath?:string){ super(id) - const filename = (file.endsWith(".json")) ? file : file+".json" - this.file = customPath ? nodepath.join("./",customPath,filename) : nodepath.join("./database/",filename) + this.file = (file.endsWith(".json")) ? file : file+".json" + this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./database/",this.file) this.formatter = formatter - - //init file if it doesn't exist yet - this.#system.getData() } + /**Init the database. */ + init(): ODPromiseVoid { + this.#system.getData() + } /**Set/overwrite the value of `category` & `key`. Returns `true` when overwritten! * @example * const didOverwrite = database.setData("category","key","value") //value can be any of the valid types @@ -306,16 +263,16 @@ export class ODFormattedJsonDatabase extends ODDatabase { #system = { /**Read parsed data from the json file */ getData: (): ODJsonDatabaseStructure => { - if (fs.existsSync(this.file)){ - return JSON.parse(fs.readFileSync(this.file).toString()) + if (fs.existsSync(this.path)){ + return JSON.parse(fs.readFileSync(this.path).toString()) }else{ - fs.writeFileSync(this.file,"[]") + fs.writeFileSync(this.path,"[]") return [] } }, /**Write parsed data to the json file */ setData: (data:ODJsonDatabaseStructure) => { - fs.writeFileSync(this.file,this.formatter.stringify(data)) + fs.writeFileSync(this.path,this.formatter.stringify(data)) } } } \ No newline at end of file diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index d67625e..df9ecdf 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -29,8 +29,12 @@ export interface ODDefaults { flagInitiating:boolean, /**Load the default open ticket configs. */ configLoading:boolean, + /**Enable the default initializer for open ticket config. */ + configInitiating:boolean, /**Load the default open ticket databases. */ databaseLoading:boolean, + /**Enable the default initializer for open ticket database. */ + databaseInitiating:boolean, /**Load the default open ticket sessions. */ sessionLoading:boolean, @@ -230,7 +234,9 @@ export class ODDefaultsManager { flagLoading:true, flagInitiating:true, configLoading:true, + configInitiating:true, databaseLoading:true, + databaseInitiating:true, sessionLoading:true, languageLoading:true, diff --git a/src/core/api/openticket/option.ts b/src/core/api/openticket/option.ts index ffc967d..3aeff49 100644 --- a/src/core/api/openticket/option.ts +++ b/src/core/api/openticket/option.ts @@ -328,9 +328,12 @@ export class ODOptionCounterDynamicSuffix extends ODOptionSuffix { constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){ super(id,option) this.database = database - if (!this.database.exists("openticket:option-suffix-counter",option.id.value)) this.database.set("openticket:option-suffix-counter",this.option.id.value,0) + this.#init() + } + + async #init(){ + if (!await this.database.exists("openticket:option-suffix-counter",this.option.id.value)) await this.database.set("openticket:option-suffix-counter",this.option.id.value,0) } - getSuffix(user:discord.User): string { const rawCurrentValue = this.database.get("openticket:option-suffix-counter",this.option.id.value) const currentValue = (typeof rawCurrentValue != "number") ? 0 : rawCurrentValue @@ -347,9 +350,12 @@ export class ODOptionCounterFixedSuffix extends ODOptionSuffix { constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){ super(id,option) this.database = database - if (!this.database.exists("openticket:option-suffix-counter",option.id.value)) this.database.set("openticket:option-suffix-counter",this.option.id.value,0) + this.#init() } + async #init(){ + if (!await this.database.exists("openticket:option-suffix-counter",this.option.id.value)) await this.database.set("openticket:option-suffix-counter",this.option.id.value,0) + } getSuffix(user:discord.User): string { const rawCurrentValue = this.database.get("openticket:option-suffix-counter",this.option.id.value) const currentValue = (typeof rawCurrentValue != "number") ? 0 : rawCurrentValue @@ -370,9 +376,12 @@ export class ODOptionRandomNumberSuffix extends ODOptionSuffix { constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){ super(id,option) this.database = database - if (!this.database.exists("openticket:option-suffix-history",option.id.value)) this.database.set("openticket:option-suffix-history",this.option.id.value,[]) + this.#init() } + async #init(){ + if (!await this.database.exists("openticket:option-suffix-history",this.option.id.value)) await this.database.set("openticket:option-suffix-history",this.option.id.value,[]) + } #generateUniqueValue(history:string[]): string { const rawNumber = Math.round(Math.random()*1000).toString() let number = rawNumber @@ -401,9 +410,13 @@ export class ODOptionRandomHexSuffix extends ODOptionSuffix { constructor(id:ODValidId, option:ODTicketOption, database:ODDatabase){ super(id,option) this.database = database - if (!this.database.exists("openticket:option-suffix-history",option.id.value)) this.database.set("openticket:option-suffix-history",this.option.id.value,[]) + this.#init() } + async #init(){ + if (!await this.database.exists("openticket:option-suffix-history",this.option.id.value)) await this.database.set("openticket:option-suffix-history",this.option.id.value,[]) + + } #generateUniqueValue(history:string[]): string { const hex = crypto.randomBytes(2).toString("hex") if (history.includes(hex)) return this.#generateUniqueValue(history) diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index 1b5bc7a..9aa5def 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -78,7 +78,7 @@ const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { const saveAllVersionsToDatabase = async () => { const globalDatabase = openticket.databases.get("openticket:global") - await openticket.versions.loopAll((version,id) => { - globalDatabase.set("openticket:last-version",id.value,version.toString()) + await openticket.versions.loopAll(async (version,id) => { + await globalDatabase.set("openticket:last-version",id.value,version.toString()) }) } \ No newline at end of file diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index ab358b2..aee5ce3 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -86,14 +86,14 @@ export const loadDatabaseCleanersCode = async () => { //remove all unused panels for (const panel of (await globalDatabase.getCategory("openticket:panel-update") ?? [])){ if (!validPanels.includes(panel.key)){ - globalDatabase.delete("openticket:panel-update",panel.key) + await globalDatabase.delete("openticket:panel-update",panel.key) } } //delete panel from database on delete - openticket.client.client.on("messageDelete",(msg) => { - if (globalDatabase.exists("openticket:panel-update",msg.channel.id+"_"+msg.id)){ - globalDatabase.delete("openticket:panel-update",msg.channel.id+"_"+msg.id) + openticket.client.client.on("messageDelete",async (msg) => { + if (await globalDatabase.exists("openticket:panel-update",msg.channel.id+"_"+msg.id)){ + await globalDatabase.delete("openticket:panel-update",msg.channel.id+"_"+msg.id) } }) })) @@ -120,24 +120,24 @@ export const loadDatabaseCleanersCode = async () => { //remove all unused suffix counters for (const counter of (await globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ if (!validSuffixCounters.includes(counter.key)){ - globalDatabase.delete("openticket:option-suffix-counter",counter.key) + await globalDatabase.delete("openticket:option-suffix-counter",counter.key) } } //remove all unused suffix histories for (const history of (await globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ if (!validSuffixHistories.includes(history.key)){ - globalDatabase.delete("openticket:option-suffix-history",history.key) + await globalDatabase.delete("openticket:option-suffix-history",history.key) } } })) //OPTION DATABASE CLEANER openticket.code.add(new api.ODCode("openticket:option-database-cleaner",10,() => { - //delete all unused options - openticket.options.getAll().forEach((option) => { - if (optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ - optionDatabase.delete("openticket:used-option",option.id.value) + //delete all unused options (async) + openticket.options.getAll().forEach(async (option) => { + if (await optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ + await optionDatabase.delete("openticket:used-option",option.id.value) } }) })) @@ -172,7 +172,7 @@ export const loadDatabaseCleanersCode = async () => { //remove all unused users for (const user of (await userDatabase.getAll())){ if (!validUsers.includes(user.key)){ - userDatabase.delete(user.category,user.key) + await userDatabase.delete(user.category,user.key) } } @@ -180,7 +180,7 @@ export const loadDatabaseCleanersCode = async () => { for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:user_")){ if (!validUsers.includes(stat.key)){ - statsDatabase.delete(stat.category,stat.key) + await statsDatabase.delete(stat.category,stat.key) } } } @@ -193,7 +193,7 @@ export const loadDatabaseCleanersCode = async () => { //remove unused user for (const user of (await userDatabase.getAll())){ if (user.key == member.id){ - userDatabase.delete(user.category,user.key) + await userDatabase.delete(user.category,user.key) } } @@ -201,7 +201,7 @@ export const loadDatabaseCleanersCode = async () => { for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:user_")){ if (stat.key == member.id){ - statsDatabase.delete(stat.category,stat.key) + await statsDatabase.delete(stat.category,stat.key) } } } @@ -237,7 +237,7 @@ export const loadDatabaseCleanersCode = async () => { //remove all unused tickets for (const ticket of (await ticketDatabase.getAll())){ if (!validTickets.includes(ticket.key)){ - ticketDatabase.delete(ticket.category,ticket.key) + await ticketDatabase.delete(ticket.category,ticket.key) openticket.tickets.remove(ticket.key) } } @@ -246,7 +246,7 @@ export const loadDatabaseCleanersCode = async () => { for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:ticket_")){ if (!validTickets.includes(stat.key)){ - statsDatabase.delete(stat.category,stat.key) + await statsDatabase.delete(stat.category,stat.key) } } } @@ -258,7 +258,7 @@ export const loadDatabaseCleanersCode = async () => { //remove unused ticket for (const ticket of (await ticketDatabase.getAll())){ if (ticket.key == channel.id){ - ticketDatabase.delete(ticket.category,ticket.key) + await ticketDatabase.delete(ticket.category,ticket.key) openticket.tickets.remove(ticket.key) } } @@ -267,7 +267,7 @@ export const loadDatabaseCleanersCode = async () => { for (const stat of (await statsDatabase.getAll())){ if (stat.category.startsWith("openticket:ticket_")){ if (stat.key == channel.id){ - statsDatabase.delete(stat.category,stat.key) + await statsDatabase.delete(stat.category,stat.key) } } } @@ -314,49 +314,49 @@ export const loadDatabaseSaversCode = async () => { openticket.code.add(new api.ODCode("openticket:ticket-saver",6,() => { const mainVersion = openticket.versions.get("openticket:version") - openticket.tickets.onAdd((ticket) => { - ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) + openticket.tickets.onAdd(async (ticket) => { + await ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) //add option to database if non-existent - if (!optionDatabase.exists("openticket:used-option",ticket.option.id.value)){ - optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) + if (!(await optionDatabase.exists("openticket:used-option",ticket.option.id.value))){ + await optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) } }) - openticket.tickets.onChange((ticket) => { - ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) + openticket.tickets.onChange(async (ticket) => { + await ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) //add option to database if non-existent - if (!optionDatabase.exists("openticket:used-option",ticket.option.id.value)){ - optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) + if (!(await optionDatabase.exists("openticket:used-option",ticket.option.id.value))){ + await optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) } //delete all unused options on ticket move - openticket.options.getAll().forEach((option) => { - if (optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ - optionDatabase.delete("openticket:used-option",option.id.value) + for (const option of openticket.options.getAll()){ + if (await optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ + await optionDatabase.delete("openticket:used-option",option.id.value) } - }) + } }) - openticket.tickets.onRemove((ticket) => { - ticketDatabase.delete("openticket:ticket",ticket.id.value) + openticket.tickets.onRemove(async (ticket) => { + await ticketDatabase.delete("openticket:ticket",ticket.id.value) //remove option from database if unused if (!openticket.tickets.getAll().some((ticket) => ticket.option.id.value == ticket.option.id.value)){ - optionDatabase.delete("openticket:used-option",ticket.option.id.value) + await optionDatabase.delete("openticket:used-option",ticket.option.id.value) } }) })) //BLACKLIST SAVER openticket.code.add(new api.ODCode("openticket:blacklist-saver",5,() => { - openticket.blacklist.onAdd((blacklist) => { - userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) + openticket.blacklist.onAdd(async (blacklist) => { + await userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) }) - openticket.blacklist.onChange((blacklist) => { - userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) + openticket.blacklist.onChange(async (blacklist) => { + await userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) }) - openticket.blacklist.onRemove((blacklist) => { - userDatabase.delete("openticket:blacklist",blacklist.id.value) + openticket.blacklist.onRemove(async (blacklist) => { + await userDatabase.delete("openticket:blacklist",blacklist.id.value) }) })) diff --git a/src/data/framework/eventLoader.ts b/src/data/framework/eventLoader.ts index 0371e4a..b9713ef 100644 --- a/src/data/framework/eventLoader.ts +++ b/src/data/framework/eventLoader.ts @@ -20,10 +20,14 @@ export const loadAllEvents = () => { //configs "onConfigLoad", "afterConfigsLoaded", + "onConfigInit", + "afterConfigsInitiated", //databases "onDatabaseLoad", "afterDatabasesLoaded", + "onDatabaseInit", + "afterDatabasesInitiated", //languages "onLanguageLoad", diff --git a/src/data/openticket/ticketLoader.ts b/src/data/openticket/ticketLoader.ts index 93d7811..8147738 100644 --- a/src/data/openticket/ticketLoader.ts +++ b/src/data/openticket/ticketLoader.ts @@ -8,24 +8,26 @@ export const loadAllTickets = async () => { const tickets = await ticketDatabase.getCategory("openticket:ticket") if (!tickets) return - tickets.forEach((ticket) => { + for (const ticket of tickets){ + console.log(ticket.value) try { - openticket.tickets.add(loadTicket(ticket.value)) + openticket.tickets.add(await loadTicket(ticket.value)) }catch (err){ + process.emit("uncaughtException",err) process.emit("uncaughtException",new api.ODSystemError("Failed to load ticket from database! => id: "+ticket.key+"\n ===> "+err)) } - }) + } } -export const loadTicket = (ticket:api.ODTicketJson) => { - const backupOption = optionDatabase.exists("openticket:used-option",ticket.option) ? api.ODTicketOption.fromJson(optionDatabase.get("openticket:used-option",ticket.option) as api.ODOptionJson) : null +export const loadTicket = async (ticket:api.ODTicketJson) => { + const backupOption = (await optionDatabase.exists("openticket:used-option",ticket.option)) ? api.ODTicketOption.fromJson(await optionDatabase.get("openticket:used-option",ticket.option) as api.ODOptionJson) : null const configOption = openticket.options.get(ticket.option) //check if option is of type "ticket" if (configOption && !(configOption instanceof api.ODTicketOption)) throw new api.ODSystemError("Unable to load ticket because option is not of 'ticket' type!") //manage backup option - if (configOption) optionDatabase.set("openticket:used-option",configOption.id.value,configOption.toJson(openticket.versions.get("openticket:version"))) + if (configOption) await optionDatabase.set("openticket:used-option",configOption.id.value,configOption.toJson(openticket.versions.get("openticket:version"))) else if (backupOption) openticket.options.add(backupOption) else throw new api.ODSystemError("Unable to use backup option! Normal option not found in config!") diff --git a/src/index.ts b/src/index.ts index 209f7e3..4e9b3af 100644 --- a/src/index.ts +++ b/src/index.ts @@ -122,6 +122,13 @@ const main = async () => { await openticket.events.get("onConfigLoad").emit([openticket.configs]) await openticket.events.get("afterConfigsLoaded").emit([openticket.configs]) + //initiate config + await openticket.events.get("onConfigInit").emit([openticket.configs]) + if (openticket.defaults.getDefault("configInitiating")){ + await openticket.configs.init() + await openticket.events.get("afterConfigsInitiated").emit([openticket.configs]) + } + //UTILITY CONFIG const generalConfig = openticket.configs.get("openticket:general") @@ -138,6 +145,13 @@ const main = async () => { await openticket.events.get("onDatabaseLoad").emit([openticket.databases]) await openticket.events.get("afterDatabasesLoaded").emit([openticket.databases]) + //initiate database + await openticket.events.get("onDatabaseInit").emit([openticket.databases]) + if (openticket.defaults.getDefault("databaseInitiating")){ + await openticket.databases.init() + await openticket.events.get("afterDatabasesInitiated").emit([openticket.databases]) + } + //load sessions openticket.log("Loading sessions...","system") if (openticket.defaults.getDefault("sessionLoading")){ From d0ef2a9873408e7117e7955cb8d042745d3a2adc Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 25 Nov 2024 19:43:58 +0100 Subject: [PATCH 057/157] Language loading => async + moved livestatus file --- src/core/api/defaults/event.ts | 2 + src/core/api/modules/defaults.ts | 3 ++ src/core/api/modules/language.ts | 80 ++++++++++++++++++---------- src/data/framework/eventLoader.ts | 2 + src/data/framework/languageLoader.ts | 40 ++++++-------- src/data/openticket/ticketLoader.ts | 1 - src/index.ts | 22 +++++++- src/livestatus.json | 42 +++++++++++++++ 8 files changed, 139 insertions(+), 53 deletions(-) create mode 100644 src/livestatus.json diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts index 7c6ec37..3e70d00 100644 --- a/src/core/api/defaults/event.ts +++ b/src/core/api/defaults/event.ts @@ -76,6 +76,8 @@ export interface ODEventIds_Default { //languages "onLanguageLoad": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid> "afterLanguagesLoaded": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid> + "onLanguageInit": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid> + "afterLanguagesInitiated": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid> "onLanguageSelect": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid> "afterLanguagesSelected": ODEvent_Default<(main:ODLanguage|null, backup:ODLanguage|null, languages:ODLanguageManager_Default) => ODPromiseVoid> diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index df9ecdf..25f5bf0 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -40,6 +40,8 @@ export interface ODDefaults { /**Load the default open ticket languages. */ languageLoading:boolean, + /**Enable the default initializer for open ticket languages. */ + languageInitiating:boolean, /**Enable selecting the current language from `config/general.json`. */ languageSelection:boolean, /**Set the backup language when the primary language is missing a property. */ @@ -240,6 +242,7 @@ export class ODDefaultsManager { sessionLoading:true, languageLoading:true, + languageInitiating:true, languageSelection:true, backupLanguage:"openticket:english", languageList:[], diff --git a/src/core/api/modules/language.ts b/src/core/api/modules/language.ts index 6a18c61..71a12c3 100644 --- a/src/core/api/modules/language.ts +++ b/src/core/api/modules/language.ts @@ -1,7 +1,7 @@ /////////////////////////////////////// //LANGUAGE MODULE /////////////////////////////////////// -import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base" +import { ODId, ODManager, ODManagerData, ODPromiseVoid, ODSystemError, ODValidId } from "./base" import nodepath from "path" import { ODDebugger } from "./console" import fs from "fs" @@ -14,32 +14,6 @@ export interface ODLanguageMetadata { automated:boolean } -export class ODLanguage extends ODManagerData { - /**The name of the file with `.json` extension. */ - file: string - /**The path to the file relative to the main directory. */ - path: string - /**The raw object data of the translation. */ - data: any - /**The metadata of the language if available. */ - metadata: ODLanguageMetadata|null = null - - constructor(id:ODValidId, file:string, customPath?:string){ - super(id) - this.file = (file.endsWith(".json")) ? file : file+".json" - this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./languages/",this.file) - - if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to parse language \""+nodepath.join("./",this.path)+"\", the file doesn't exist!") - try{ - this.data = JSON.parse(fs.readFileSync(this.path).toString()) - }catch(err){ - process.emit("uncaughtException",err) - throw new ODSystemError("Unable to parse language \""+nodepath.join("./",this.path)+"\"!") - } - if (this.data["_TRANSLATION"]) this.metadata = this.data["_TRANSLATION"] - } -} - export class ODLanguageManager extends ODManager { current: ODLanguage|null = null backup: ODLanguage|null = null @@ -130,4 +104,56 @@ export class ODLanguageManager extends ODManager { }) return translation } + + /**Init all language files. */ + async init(){ + for (const language of this.getAll()){ + try{ + await language.init() + }catch(err){ + process.emit("uncaughtException",new ODSystemError(err)) + } + } + } +} + +export class ODLanguage extends ODManagerData { + /**The name of the file with extension. */ + file: string = "" + /**The path to the file relative to the main directory. */ + path: string = "" + /**The raw object data of the translation. */ + data: any + /**The metadata of the language if available. */ + metadata: ODLanguageMetadata|null = null + + constructor(id:ODValidId, data:any){ + super(id) + this.data = data + } + + /**Init the language. */ + init(): ODPromiseVoid { + //nothing + } +} + +export class ODJsonLanguage extends ODLanguage { + constructor(id:ODValidId, file:string, customPath?:string){ + super(id,{}) + this.file = (file.endsWith(".json")) ? file : file+".json" + this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./languages/",this.file) + } + + /**Init the langauge. */ + init(): ODPromiseVoid { + if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to parse language \""+nodepath.join("./",this.path)+"\", the file doesn't exist!") + try{ + this.data = JSON.parse(fs.readFileSync(this.path).toString()) + }catch(err){ + process.emit("uncaughtException",err) + throw new ODSystemError("Unable to parse language \""+nodepath.join("./",this.path)+"\"!") + } + if (this.data["_TRANSLATION"]) this.metadata = this.data["_TRANSLATION"] + } } \ No newline at end of file diff --git a/src/data/framework/eventLoader.ts b/src/data/framework/eventLoader.ts index b9713ef..ad5f88d 100644 --- a/src/data/framework/eventLoader.ts +++ b/src/data/framework/eventLoader.ts @@ -32,6 +32,8 @@ export const loadAllEvents = () => { //languages "onLanguageLoad", "afterLanguagesLoaded", + "onLanguageInit", + "afterLanguagesInitiated", "onLanguageSelect", "afterLanguagesSelected", diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 61aff52..ae4f754 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -2,32 +2,26 @@ import {openticket, api, utilities} from "../../index" export const loadAllLanguages = async () => { //register languages - openticket.languages.add(new api.ODLanguage("openticket:custom","custom.json")) - openticket.languages.add(new api.ODLanguage("openticket:english","english.json")) - openticket.languages.add(new api.ODLanguage("openticket:dutch","dutch.json")) - openticket.languages.add(new api.ODLanguage("openticket:portuguese","portuguese.json")) - openticket.languages.add(new api.ODLanguage("openticket:czech","czech.json")) - openticket.languages.add(new api.ODLanguage("openticket:german","german.json")) - openticket.languages.add(new api.ODLanguage("openticket:catalan","catalan.json")) - openticket.languages.add(new api.ODLanguage("openticket:hungarian","hungarian.json")) - openticket.languages.add(new api.ODLanguage("openticket:spanish","spanish.json")) - openticket.languages.add(new api.ODLanguage("openticket:romanian","romanian.json")) - openticket.languages.add(new api.ODLanguage("openticket:ukrainian","ukrainian.json")) - openticket.languages.add(new api.ODLanguage("openticket:indonesian","indonesian.json")) - openticket.languages.add(new api.ODLanguage("openticket:italian","italian.json")) - openticket.languages.add(new api.ODLanguage("openticket:estonian","estonian.json")) - openticket.languages.add(new api.ODLanguage("openticket:finnish","finnish.json")) - openticket.languages.add(new api.ODLanguage("openticket:danish","danish.json")) - openticket.languages.add(new api.ODLanguage("openticket:thai","thai.json")) - - //list for config checker - const languageList = openticket.defaults.getDefault("languageList") - languageList.push("custom","english","dutch","portuguese","czech","german","catalan","hungarian","spanish","romanian","ukrainian","indonesian","italian","estonian","finnish","danish","thai") - openticket.defaults.setDefault("languageList",languageList) + openticket.languages.add(new api.ODJsonLanguage("openticket:custom","custom.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:english","english.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:dutch","dutch.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:portuguese","portuguese.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:czech","czech.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:german","german.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:catalan","catalan.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:hungarian","hungarian.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:spanish","spanish.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:romanian","romanian.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:ukrainian","ukrainian.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:indonesian","indonesian.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:italian","italian.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:estonian","estonian.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:finnish","finnish.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:danish","danish.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:thai","thai.json")) /** How to add more languages? * - Register the language to the manager (see above) - * - Add the language to the list (see above) * - Add the language to the list in the "ODLanguageManagerIds_Default" interface (./src/core/api/defaults/language.ts) * - Add the language to the list in the README.md */ diff --git a/src/data/openticket/ticketLoader.ts b/src/data/openticket/ticketLoader.ts index 8147738..b8e475f 100644 --- a/src/data/openticket/ticketLoader.ts +++ b/src/data/openticket/ticketLoader.ts @@ -9,7 +9,6 @@ export const loadAllTickets = async () => { const tickets = await ticketDatabase.getCategory("openticket:ticket") if (!tickets) return for (const ticket of tickets){ - console.log(ticket.value) try { openticket.tickets.add(await loadTicket(ticket.value)) }catch (err){ diff --git a/src/index.ts b/src/index.ts index 4e9b3af..cad3851 100644 --- a/src/index.ts +++ b/src/index.ts @@ -166,13 +166,31 @@ const main = async () => { await (await import("./data/framework/languageLoader.js")).loadAllLanguages() } await openticket.events.get("onLanguageLoad").emit([openticket.languages]) - await openticket.events.get("afterLanguagesLoaded").emit([openticket.languages]) + await openticket.events.get("afterLanguagesLoaded").emit([openticket.languages]) + + //initiate language + await openticket.events.get("onLanguageInit").emit([openticket.languages]) + if (openticket.defaults.getDefault("languageInitiating")){ + await openticket.languages.init() + await openticket.events.get("afterLanguagesInitiated").emit([openticket.languages]) + + //add available languages to list for config checker + const languageList = openticket.defaults.getDefault("languageList") + const languageIds = openticket.languages.getIds().map((id) => { + if (id.value.startsWith("openticket:")){ + //is open ticket language => return without prefix + return id.value.split("openticket:")[1] + }else return id.value + }) + languageList.push(...languageIds) + openticket.defaults.setDefault("languageList",languageList) + } //select language await openticket.events.get("onLanguageSelect").emit([openticket.languages]) if (openticket.defaults.getDefault("languageSelection")){ //set current language - const languageId = (generalConfig && generalConfig.data.language) ? generalConfig.data.language : "english" + const languageId = (generalConfig?.data?.language) ? generalConfig.data.language : "english" if (languageId.includes(":")){ openticket.languages.setCurrentLanguage(languageId) }else{ diff --git a/src/livestatus.json b/src/livestatus.json new file mode 100644 index 0000000..29971ad --- /dev/null +++ b/src/livestatus.json @@ -0,0 +1,42 @@ +[ + { + "message":{ + "title":"Open Ticket Beta", + "titleColor":"red", + "description":"Hi there! You're using a beta version of the bot! Please report all bugs and errors to our discord server!", + "descriptionColor":"normal" + }, + "active":{ + "versions":["4.0.0"], + "languages":[], + "allLanguages":true, + "usingPlugins":true, + "notUsingPlugins":true, + "usingSlashCommands":true, + "notUsingSlashCommands":true, + "notUsingTranscripts":true, + "usingTextTranscripts":true, + "usingHtmlTranscripts":true + } + }, + { + "message":{ + "title":"Documentation", + "titleColor":"blue", + "description":"Currently there is no documentation available yet for this version of the bot.", + "descriptionColor":"normal" + }, + "active":{ + "versions":["4.0.0"], + "languages":[], + "allLanguages":true, + "usingPlugins":true, + "notUsingPlugins":true, + "usingSlashCommands":true, + "notUsingSlashCommands":true, + "notUsingTranscripts":true, + "usingTextTranscripts":true, + "usingHtmlTranscripts":true + } + } +] \ No newline at end of file From 66ab30bf06d47832f67dc2bb15cd8645ef2f8283 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 25 Nov 2024 19:46:56 +0100 Subject: [PATCH 058/157] Livestatus source moved to github --- src/data/framework/liveStatusLoader.ts | 2 +- src/livestatus.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/framework/liveStatusLoader.ts b/src/data/framework/liveStatusLoader.ts index 5864178..9c71352 100644 --- a/src/data/framework/liveStatusLoader.ts +++ b/src/data/framework/liveStatusLoader.ts @@ -2,5 +2,5 @@ import {openticket, api, utilities} from "../../index" export const loadAllLiveStatusSources = async () => { //DEFAULT DJDJ DEV - openticket.livestatus.add(new api.ODLiveStatusUrlSource("openticket:default-djdj-dev","https://apis.dj-dj.be/status/openticket.json")) + openticket.livestatus.add(new api.ODLiveStatusUrlSource("openticket:default-djdj-dev","https://raw.githubusercontent.com/DJj123dj/open-ticket/refs/heads/dev/src/livestatus.json")) } \ No newline at end of file diff --git a/src/livestatus.json b/src/livestatus.json index 29971ad..4dcdd4d 100644 --- a/src/livestatus.json +++ b/src/livestatus.json @@ -23,7 +23,7 @@ "message":{ "title":"Documentation", "titleColor":"blue", - "description":"Currently there is no documentation available yet for this version of the bot.", + "description":"There is currently no documentation available yet for OT v4 beta!", "descriptionColor":"normal" }, "active":{ From e8319cccea3b96b529702e6960911b927f8a88e4 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 25 Nov 2024 20:06:11 +0100 Subject: [PATCH 059/157] Updated README.md --- README.md | 20 ++++++++++++-------- src/data/framework/languageLoader.ts | 3 ++- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index defb6fd..6c87fc2 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,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! Even if your server contains more than 100k members! - **📄 html transcripts** - Make use of the most customisable, beautiful and easy-to-use HTML Transcripts! - **✅ ticket actions** - Close, Reopen, Delete, Rename & Move all your tickets! -- **🇬🇧 translation** - Open Ticket has been translated in more than **32 languages** by our community! +- **🇬🇧 translation** - Open Ticket has been translated in more than **16 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 everywhere** - Create an infinite amount of tickets & panels! @@ -62,18 +62,22 @@ View all available Open Ticket plugins in our [Official Plugin Repository](https ### 📦 Official *(made by DJdj Development)* |Name |Category |Description | |---------------------------------------------------------------------|----------------------------|-------------------------| -|[`example-plugin`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-plugin/) |Example |This is just an example plugin for people that want to create their own plugin. | -|[`example-command`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-command/) |Example |Sample custom command using the Open Discord system. | -|[`ot-jump-to-top`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-jump-to-top/) |Command |Add a simple command to jump to the top of the ticket. | -|[`ot-kill-switch`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-kill-switch/) |Command |Temporarily disable the ticket system using a kill switch. | -|[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |Channel Management |Simple plugin to keep the channel prefix when using the /rename command. | -|[`ot-no-slash-clear`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-no-slash-clear/) |Development |Disable the automatic removal of slash commands that aren't used by Open Ticket. | -|[`ot-better-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-better-status/) |Client Activity |An advanced status plugin to rotate between states. It also allows for the use of variables. | +|[`example-plugin`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-plugin/) |Example |This is just an example plugin for people that want to create their own plugin. | +|[`example-command`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-command/) |Example |Sample custom command using the Open Discord system. | +|[`ot-jump-to-top`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-jump-to-top/) |Command |Add a simple command to jump to the top of the ticket. | +|[`ot-kill-switch`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-kill-switch/) |Command |Temporarily disable the ticket system using a kill switch. | +|[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |Channel Management |Simple plugin to keep the channel prefix when using the /rename command. | +|[`ot-no-slash-clear`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-no-slash-clear/) |Development |Disable the automatic removal of slash commands that aren't used by Open Ticket. | +|[`ot-better-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-better-status/) |Client Activity |An advanced status plugin to rotate between states. It also allows for the use of variables. | +|[`ot-sqlite-database`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-sqlite-database/) |Database |With this plugin, the database will be an SQLite file. It's a must-have for large servers! | +|[`ot-ticket-message-extras`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ticket-message-extras/) |Customisation |A plugin which adds a few little features to the ticket message. | + ### ✅ Verified *(made by community)* |Name |Author |Category |Description | |---------------------------------------------------------------------|----------------------------|----------------------------|-------------------------| |[`ot-config-reload`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-config-reload/) |guillee.3 |Config |This plugin adds a new command that allows reloading the Open Ticket config files without the need for a restart. | +|[`ot-feedback`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-feedback/) |an_developer |Feedback System |A plugin to gather feedback of your support service. | ## 🛠️ Contributors ### 🖥️ Team diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index ae4f754..d46b5c1 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -23,6 +23,7 @@ export const loadAllLanguages = async () => { /** How to add more languages? * - Register the language to the manager (see above) * - Add the language to the list in the "ODLanguageManagerIds_Default" interface (./src/core/api/defaults/language.ts) - * - Add the language to the list in the README.md + * - Update the language list in the README.md translator list + * - Update the language counter in the README.md features list */ } \ No newline at end of file From 147ebc90da575c74e949547d2db5e386909c177a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillem=20Parera=20Jov=C3=A9?= Date: Thu, 5 Dec 2024 21:03:14 +0100 Subject: [PATCH 060/157] - Fixed Catalan Translation. - Added French Translation. --- languages/catalan.json | 8 +- languages/french.json | 478 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 482 insertions(+), 4 deletions(-) create mode 100644 languages/french.json diff --git a/languages/catalan.json b/languages/catalan.json index d7f9229..c54e6cb 100644 --- a/languages/catalan.json +++ b/languages/catalan.json @@ -94,7 +94,7 @@ }, "actions":{ "buttons":{ - "create":"Visitar Ticket", + "create":"Veure Ticket", "close":"Tancar Ticket", "delete":"Eliminar Ticket", "reopen":"Reobrir Ticket", @@ -207,8 +207,8 @@ "pinDm":"El teu ticket ha estat fixat al nostre servidor!", "unpinLog":"Aquest ticket ha estat desfixat per {0}!", "unpinDm":"El teu ticket ha estat desfixat al nostre servidor!", - "renameLog":"Aquest ticket ha estat renomenat a {0} per {1}!", - "renameDm":"El teu ticket ha estat renomenat a {0} al nostre servidor!", + "renameLog":"Aquest ticket ha estat renombrat a {0} per {1}!", + "renameDm":"El teu ticket ha estat renombrat a {0} al nostre servidor!", "moveLog":"Aquest ticket ha estat mogut a {0} per {1}!", "moveDm":"El teu ticket ha estat mogut a {0} al nostre servidor!", "addLog":"{0} ha estat afegit a aquest ticket per {1}!", @@ -225,7 +225,7 @@ }, "transcripts":{ "success":{ - "visit":"Visitar Transcripció", + "visit":"Veure Transcripció", "ready":"Transcripció Creada", "textFileDescription":"Aquesta és la transcripció de text d'un ticket eliminat!", "htmlProgress":"Si us plau, espera mentre aquesta transcripció html es processa...", diff --git a/languages/french.json b/languages/french.json new file mode 100644 index 0000000..9c285f4 --- /dev/null +++ b/languages/french.json @@ -0,0 +1,478 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translators":["guillee3"], + "lastedited":"04/12/2024", + "language":"French", + "automated":false + }, + "checker":{ + "system":{ + "typeError":"[ERREUR]", + "headerOpenTicket":"OUVRIR TICKET", + "typeWarning":"[ALERTE]", + "typeInfo":"[INFO]", + "headerConfigChecker":"VÉRIFICATEUR DE CONFIGURATION", + "headerDescription":"vérifiez les erreurs dans vos fichiers de config!", + "footerError":"le bot ne démarrera pas tant que tous les {0} ne sont pas corrigés!", + "footerWarning":"il est recommandé de corriger tous les {0} avant de commencer!", + "footerSupport":"SUPPORT: {0} - DOCS: {1}", + "compactInformation":"utilisez {0} pour plus d'informations!", + "dataPath":"chemin", + "dataDocs":"docs", + "dataMessages":"message" + }, + "messages":{ + "stringTooShort":"Cette chaîne ne peut pas être plus courte que {0} caractères!", + "stringTooLong":"Cette chaîne ne peut pas être plus longue que {0} caractères!", + "stringLengthInvalid":"Cette chaîne doit comporter {0} caractères!", + "stringStartsWith":"Cette chaîne doit commencer par {0}!", + "stringEndsWith":"Cette chaîne doit se terminer par {0}!", + "stringContains":"Cette chaîne doit contenir {0}!", + "stringChoices":"Cette chaîne ne peut être que l'une des valeurs suivantes : {0}!", + "stringRegex":"Cette chaîne est invalide!", + + "numberTooShort":"Ce nombre ne peut pas être plus court que {0} caractères!", + "numberTooLong":"Ce nombre ne peut pas être plus long que {0} caractères!", + "numberLengthInvalid":"Ce nombre doit comporter {0} caractères!", + "numberTooSmall":"Ce nombre doit être au moins {0}!", + "numberTooLarge":"Ce nombre doit être au maximum {0}!", + "numberNotEqual":"Ce nombre doit être {0}!", + "numberStep":"Ce nombre doit être un multiple de {0}!", + "numberStepOffset":"Ce nombre doit être un multiple de {0} en commençant par {1}!", + "numberStartsWith":"Ce nombre doit commencer par {0}!", + "numberEndsWith":"Ce nombre doit se terminer par {0}!", + "numberContains":"Ce nombre doit contenir {0}!", + "numberChoices":"Ce nombre ne peut être que l'une des valeurs suivantes : {0}!", + "numberFloat":"Ce nombre ne peut pas être un décimal!", + "numberNegative":"Ce nombre ne peut pas être négatif!", + "numberPositive":"Ce nombre ne peut pas être positif!", + "numberZero":"Ce nombre ne peut pas être zéro!", + + "booleanTrue":"Ce booléen ne peut pas être vrai!", + "booleanFalse":"Ce booléen ne peut pas être faux!", + + "arrayEmptyDisabled":"Ce tableau ne peut pas être vide!", + "arrayEmptyRequired":"Ce tableau doit être vide!", + "arrayTooShort":"Ce tableau doit avoir une longueur d'au moins {0}!", + "arrayTooLong":"Ce tableau doit avoir une longueur d'au plus {0}!", + "arrayLengthInvalid":"Ce tableau doit avoir une longueur de {0}!", + "arrayInvalidTypes":"Ce tableau ne peut contenir que les types suivants : {0}!", + "arrayDouble":"Ce tableau n'autorise pas la même valeur deux fois!", + + "discordInvalidId":"Ceci est un identifiant de {0} Discord invalide!", + "discordInvalidIdOptions":"Ceci est un identifiant de {0} Discord invalide! Vous pouvez également utiliser l'un de ceux-ci: {1}!", + "discordInvalidToken":"Ceci est un token Discord invalide (syntactiquement)!", + "colorInvalid":"Ceci est une couleur hex invalide!", + "emojiTooShort":"Cette chaîne doit contenir au moins {0} émojis!", + "emojiTooLong":"Cette chaîne doit contenir au plus {0} émojis!", + "emojiCustom":"Cet émoji ne peut pas être un émoji Discord personnalisé!", + "emojiInvalid":"Ceci est un émoji invalide!", + "urlInvalid":"Cette URL est invalide!", + "urlInvalidHttp":"Cette URL ne peut utiliser que le protocole https://!", + "urlInvalidProtocol":"Cette URL ne peut utiliser que les protocoles http:// et https://!", + "urlInvalidHostname":"Cette URL a un nom d'hôte non autorisé!", + "urlInvalidExtension":"Cette URL a une extension invalide! Choisissez parmi : {0}!", + "urlInvalidPath":"Cette URL a un chemin invalide!", + "idNotUnique":"Cet identifiant n'est pas unique, utilisez un autre identifiant à la place!", + "idNonExistent":"L'identifiant {0} n'existe pas!", + + "invalidType":"Cette propriété doit être du type: {0}!", + "propertyMissing":"La propriété {0} est manquante dans cet objet!", + "propertyOptional":"La propriété {0} est optionnelle dans cet objet!", + "objectDisabled":"Cet objet est désactivé, activez-le en utilisant {0}!", + "nullInvalid":"Cette propriété ne peut pas être nulle!", + "switchInvalidType":"Cela doit être l'un des types suivants: {0}!", + "objectSwitchInvalid":"Cet objet doit être l'un des types suivants : {0}!", + + "invalidLanguage":"Ceci est une langue invalide!", + "invalidButton":"Ce bouton doit avoir au moins un {0} ou {1}!", + "unusedOption":"L'option {0} n'est utilisée nulle part!", + "unusedQuestion":"La question {0} n'est utilisée nulle part!", + "dropdownOption":"Un panneau avec un menu déroulant activé ne peut contenir que des options du type 'ticket'!" + } + }, + "actions":{ + "buttons":{ + "create":"Visiter le Ticket", + "close":"Fermer le Ticket", + "delete":"Supprimer le Ticket", + "reopen":"Rouvrir le Ticket", + "claim":"Réclamer le ticket", + "unclaim":"Libérer le Ticket", + "pin":"Épingler le Ticket", + "unpin":"Désépingler le Ticket", + "clear":"Supprimer les Tickets", + "helpSwitchSlash":"Voir les Commandes Slash", + "helpSwitchText":"Voir les Commandes Textuelles", + "helpPage":"Page {0}", + "withReason":"Avec Raison", + "withoutTranscript":"Sans Transcription" + }, + "titles":{ + "created":"Ticket Créé", + "close":"Ticket Fermé", + "delete":"Ticket Supprimé", + "reopen":"Ticket Rouvert", + "claim":"Ticket Pris en Charge", + "unclaim":"Ticket libéré", + "pin":"Ticket Épinglé", + "unpin":"Ticket Désépinglé", + "rename":"Ticket Renommé", + "move":"Ticket Déplacé", + "add":"Utilisateur Ajouté au Ticket", + "remove":"Utilisateur Retiré du Ticket", + + "help":"Commandes Disponibles", + "statsReset":"Réinitialiser les Statistiques", + "blacklistAdd":"Utilisateur Ajouté à la Liste Noire", + "blacklistRemove":"Utilisateur Retiré de la Liste Noire", + "blacklistGet":"Utilisateur en Liste Noire", + "blacklistView":"Liste Noire Actuelle", + "blacklistAddDm":"Ajouté à la Liste Noire", + "blacklistRemoveDm":"Retiré de la Liste Noire", + "clear":"Tickets Supprimés", + "roles":"Rôles Mis à Jour", + + "autoclose":"Ticket Fermé Automatiquement", + "autocloseEnabled":"Fermeture Automatique Activée", + "autocloseDisabled":"Fermeture Automatique Désactivée", + "autodelete":"Ticket Supprimé Automatiquement", + "autodeleteEnabled":"Suppression Automatique Activée", + "autodeleteDisabled":"Suppression Automatique Désactivée" + }, + "descriptions":{ + "create":"Votre ticket a été créé. Cliquez sur le bouton ci-dessous pour y accéder!", + "close":"Le ticket a été fermé avec succès!", + "delete":"Le ticket a été supprimé avec succès!", + "reopen":"Le ticket a été rouvert avec succès!", + "claim":"Le ticket a été pris en charge avec succès!", + "unclaim":"Le ticket a été libéré avec succès!", + "pin":"Le ticket a été épinglé avec succès!", + "unpin":"Le ticket a été désépinglé avec succès!", + "rename":"Le ticket a été renommé en {0} avec succès!", + "move":"Le ticket a été déplacé vers {0} avec succès!", + "add":"{0} a été ajouté au ticket avec succès!", + "remove":"{0} a été retiré du ticket avec succès!", + + "helpExplanation":"`` => paramètre requis\n`[nom]` => paramètre optionnel", + "statsReset":"Les statistiques du bot ont été réinitialisées avec succès!", + "statsError":"Impossible de visualiser les statistiques du ticket!\n{0} n'est pas un ticket!", + "blacklistAdd":"{0} a été ajouté à la liste noire avec succès!", + "blacklistRemove":"{0} a été retiré de la liste noire avec succès!", + "blacklistGetSuccess":"{0} est actuellement sur la liste noire!", + "blacklistGetEmpty":"{0} n'est actuellement pas sur la liste noire!", + "blacklistViewEmpty":"Personne n'a encore été ajouté à la liste noire!", + "blacklistViewTip":"Utilisez \"/blacklist add\" pour ajouter un utilisateur à la liste noire!", + "clearVerify":"Êtes-vous sûr de vouloir supprimer plusieurs tickets?\nCette action est irréversible!", + "clearReady":"{0} tickets ont été supprimés avec succès!", + "rolesEmpty":"Aucun rôle n'a été mis à jour!", + + "autocloseLeave":"Ce ticket a été fermé automatiquement parce que le créateur a quitté le serveur!", + "autocloseTimeout":"Ce ticket a été fermé automatiquement car il est resté inactif pendant plus de `{0}h`!", + "autodeleteLeave":"Ce ticket a été supprimé automatiquement parce que le créateur a quitté le serveur!", + "autodeleteTimeout":"Ce ticket a été supprimé automatiquement car il est resté inactif pendant plus de `{0} jours`!", + "autocloseEnabled":"La fermeture automatique a été activée dans ce ticket!\nIl sera fermé lorsqu'il restera inactif pendant plus de `{0}h`!", + "autocloseDisabled":"La fermeture automatique a été désactivée dans ce ticket!\nIl ne sera plus fermé automatiquement!", + "autodeleteEnabled":"La suppression automatique a été activée dans ce ticket!\nIl sera supprimé lorsqu'il restera inactif pendant plus de `{0} jours`!", + "autodeleteDisabled":"La suppression automatique a été désactivée dans ce ticket!\nIl ne sera plus supprimé automatiquement!", + + "ticketMessageLimit":"Vous ne pouvez créer que {0} ticket(s) en même temps!", + "ticketMessageAutoclose":"Ce ticket sera fermé automatiquement après {0}h d'inactivité!", + "ticketMessageAutodelete":"Ce ticket sera supprimé automatiquement après {0} jours d'inactivité!", + "panelReady":"Vous pouvez trouver le panneau ci-dessous!\nCe message peut maintenant être supprimé!" + }, + "modal":{ + "closePlaceholder":"Pourquoi avez-vous fermé ce ticket?", + "deletePlaceholder":"Pourquoi avez-vous supprimé ce ticket?", + "reopenPlaceholder":"Pourquoi avez-vous rouvert ce ticket?", + "claimPlaceholder":"Pourquoi avez-vous pris en charge ce ticket?", + "unclaimPlaceholder":"Pourquoi avez-vous libéré ce ticket?", + "pinPlaceholder":"Pourquoi avez-vous épinglé ce ticket?", + "unpinPlaceholder":"Pourquoi avez-vous désépinglé ce ticket?" + }, + "logs":{ + "createLog":"Un nouveau ticket a été créé par {0}!", + "closeLog":"Ce ticket a été fermé par {0}!", + "closeDm":"Votre ticket a été fermé sur notre serveur!", + "deleteLog":"Ce ticket a été supprimé par {0}!", + "deleteDm":"Votre ticket a été supprimé sur notre serveur!", + "reopenLog":"Ce ticket a été rouvert par {0}!", + "reopenDm":"Votre ticket a été rouvert sur notre serveur!", + "claimLog":"Ce ticket a été pris en charge par {0}!", + "claimDm":"Votre ticket a été pris en charge sur notre serveur!", + "unclaimLog":"Ce ticket a été libéré par {0}!", + "unclaimDm":"Votre ticket a été libéré sur notre serveur!", + "pinLog":"Ce ticket a été épinglé par {0}!", + "pinDm":"Votre ticket a été épinglé sur notre serveur!", + "unpinLog":"Ce ticket a été désépinglé par {0}!", + "unpinDm":"Votre ticket a été désépinglé sur notre serveur!", + "renameLog":"Ce ticket a été renommé en {0} par {1}!", + "renameDm":"Votre ticket a été renommé en {0} sur notre serveur!", + "moveLog":"Ce ticket a été déplacé vers {0} par {1}!", + "moveDm":"Votre ticket a été déplacé vers {0} sur notre serveur!", + "addLog":"{0} a été ajouté à ce ticket par {1}!", + "addDm":"{0} a été ajouté à votre ticket sur notre serveur!", + "removeLog":"{0} a été retiré de ce ticket par {1}!", + "removeDm":"{0} a été retiré de votre ticket sur notre serveur!", + + "blacklistAddLog":"{0} a été ajouté à la liste noire par {1}!", + "blacklistRemoveLog":"{0} a été retiré de la liste noire par {1}!", + "blacklistAddDm":"Vous avez été ajouté à la liste noire sur notre serveur!\nDésormais, vous ne pouvez pas créer de ticket!", + "blacklistRemoveDm":"Vous avez été retiré de la liste noire sur notre serveur!\nVous pouvez désormais créer des tickets à nouveau!", + "clearLog":"{0} tickets ont été supprimés par {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Visiter la Transcription", + "ready":"Transcription Créée", + "textFileDescription":"Ceci est la transcription textuelle d'un ticket supprimé!", + "htmlProgress":"Veuillez patienter pendant que cette transcription HTML est en cours de traitement...", + + "createdChannel":"Une nouvelle transcription {0} a été créée sur le serveur!", + "createdCreator":"Une nouvelle transcription {0} a été créée pour l'un de vos tickets!", + "createdParticipant":"Une nouvelle transcription {0} a été créée dans l'un des tickets auxquels vous avez participé!", + "createdActiveAdmin":"Une nouvelle transcription {0} a été créée dans l'un des tickets auxquels vous avez participé en tant qu'admin!", + "createdEveryAdmin":"Une nouvelle transcription {0} a été créée dans l'un des tickets où vous étiez admin!", + "createdOther":"Une nouvelle transcription {0} a été créée!" + }, + "errors":{ + "retry":"Réessayer", + "continue":"Supprimer Sans Transcription", + "backup":"Créer une Transcription de Sauvegarde", + "error":"Une erreur s'est produite lors de la création de la transcription.\nQue souhaitez-vous faire?\n\nCe ticket ne sera pas supprimé tant que vous n'aurez pas cliqué sur l'un de ces boutons." + } + }, + "errors":{ + "titles":{ + "internalError":"Erreur Interne", + "optionMissing":"Option de Commande Manquante", + "optionInvalid":"Option de Commande Invalide", + "unknownCommand":"Commande Inconnue", + "noPermissions":"Pas de Permissions", + "unknownTicket":"Ticket Inconnu", + "deprecatedTicket":"Ticket Déprécié", + "unknownOption":"Option Inconnue", + "unknownPanel":"Panneau Inconnu", + "notInGuild":"Pas Dans le Serveur", + "channelRename":"Impossible de Renommer le Canal", + "busy":"Ticket Occupé" + }, + "descriptions":{ + "askForInfo":"Contactez le propriétaire de ce bot pour plus d'informations!", + "askForInfoResolve":"Contactez le propriétaire du bot si ce problème ne se résout pas après quelques essais.", + "internalError":"Échec de la réponse à ce {0} en raison d'une erreur interne!", + "optionMissing":"Un paramètre requis est manquant dans cette commande!", + "optionInvalid":"Un paramètre dans cette commande est invalide!", + "optionInvalidChoose":"Choisissez entre", + "unknownCommand":"Essayez de visiter le menu d'aide pour plus d'informations!", + "noPermissions":"Vous n'êtes pas autorisé à utiliser ce {0}!", + "noPermissionsList":"Permissions Requises : (une d'entre elles)", + "noPermissionsCooldown":"Vous n'êtes pas autorisé à utiliser ce {0} car vous êtes en cooldown!", + "noPermissionsBlacklist":"Vous n'êtes pas autorisé à utiliser ce {0} car vous avez été mis sur la liste noire!", + "noPermissionsLimitGlobal":"Vous n'êtes pas autorisé à créer un ticket car le serveur a atteint la limite maximale de tickets!", + "noPermissionsLimitGlobalUser":"Vous n'êtes pas autorisé à créer un ticket car vous avez atteint la limite maximale de tickets!", + "noPermissionsLimitOption":"Vous n'êtes pas autorisé à créer un ticket car le serveur a atteint la limite maximale de tickets pour cette option!", + "noPermissionsLimitOptionUser":"Vous n'êtes pas autorisé à créer un ticket car vous avez atteint la limite maximale de tickets pour cette option!", + "unknownTicket":"Essayez cette commande à nouveau dans un ticket valide!", + "deprecatedTicket":"Le canal actuel n'est pas un ticket valide! Il pourrait s'agir d'un ticket provenant d'une ancienne version d'Open Ticket!", + "notInGuild":"Ce {0} ne fonctionne pas en DM! Veuillez réessayer dans un serveur!", + "channelRename":"En raison des limitations de taux de Discord, il est actuellement impossible pour le bot de renommer le canal. Le canal sera automatiquement renommé après 10 minutes si le bot n'est pas redémarré.", + "channelRenameSource":"La source de cette erreur est : {0}", + "busy":"Impossible d'utiliser ce {0}!\nLe ticket est actuellement en cours de traitement par le bot.\n\nVeuillez réessayer dans quelques secondes!" + }, + "optionInvalidReasons":{ + "stringRegex":"La valeur ne correspond pas au modèle!", + "stringMinLength":"La valeur doit comporter au moins {0} caractères!", + "stringMaxLength":"La valeur doit comporter au maximum {0} caractères!", + "numberInvalid":"Nombre invalide!", + "numberMin":"Le nombre doit être au moins {0}!", + "numberMax":"Le nombre doit être au maximum {0}!", + "numberDecimal":"Le nombre ne peut pas être un décimal!", + "numberNegative":"Le nombre ne peut pas être négatif!", + "numberPositive":"Le nombre ne peut pas être positif!", + "numberZero":"Le nombre ne peut pas être zéro!", + "channelNotFound":"Impossible de trouver le canal!", + "userNotFound":"Impossible de trouver l'utilisateur!", + "roleNotFound":"Impossible de trouver le rôle!", + "memberNotFound":"Impossible de trouver l'utilisateur!", + "mentionableNotFound":"Impossible de trouver l'utilisateur ou le rôle!", + "channelType":"Type de canal invalide!", + "notInGuild":"Cette option nécessite que vous soyez dans un serveur!" + }, + "permissions":{ + "developer":"Vous devez être le développeur du bot.", + "owner":"Vous devez être le propriétaire du serveur.", + "admin":"Vous devez être un administrateur du serveur.", + "moderator":"Vous devez être un modérateur.", + "support":"Vous devez faire partie de l'équipe de support.", + "member":"Vous devez être membre.", + "discord-administrator":"Vous devez avoir la permission `ADMINISTRATOR`." + }, + "actionInvalid":{ + "close":"Le ticket est déjà fermé!", + "reopen":"Le ticket n'est pas encore fermé!", + "claim":"Le ticket est déjà pris en charge!", + "unclaim":"Le ticket n'est pas encore pris en charge!", + "pin":"Le ticket est déjà épinglé!", + "unpin":"Le ticket n'est pas encore épinglé!", + "add":"Cet utilisateur a déjà accès au ticket!", + "remove":"Impossible de retirer cet utilisateur du ticket!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickets", + "reason":"Raison", + "creator":"Créateur", + "remaining":"Temps Restant", + "added":"Ajouté", + "removed":"Retiré", + "filter":"Filtre", + "claimedBy":"Pris en charge par {0}", + "method":"Méthode", + "type":"Type", + "blacklisted":"Liste Noire", + "panel":"Panneau", + "command":"Commande", + "system":"Système", + "true":"Vrai", + "false":"Faux", + "syntax":"Syntaxe", + "originalName":"Nom Original", + "newName":"Nouveau Nom", + "until":"Jusqu'à", + "validOptions":"Options Valides", + "validPanels":"Panneaux Valides", + "autoclose":"Fermeture Automatique", + "autodelete":"Suppression Automatique", + "startupDate":"Date de Démarrage", + "version":"Version", + "name":"Nom", + "role":"Rôle", + "status":"Statut", + "claimed":"Pris en Charge", + "pinned":"Épinglé", + "creationDate":"Date de Création" + }, + "lowercase":{ + "text":"texte", + "html":"html", + "command":"commande", + "modal":"modal", + "button":"bouton", + "dropdown":"menu déroulant", + "method":"méthode" + } + }, + "commands":{ + "reason":"Spécifiez une raison optionnelle qui sera visible dans les journaux.", + "help":"Obtenez une liste de toutes les commandes disponibles.", + "panel":"Générez un message avec un menu déroulant ou des boutons (pour la création de tickets).", + "panelId":"L'identifiant du panneau que vous souhaitez générer.", + "panelAutoUpdate":"Voulez-vous que ce panneau se mette à jour automatiquement lorsqu'il est modifié?", + "ticket":"Créez instantanément un ticket.", + "ticketId":"L'identifiant du ticket que vous souhaitez créer.", + "close":"Fermez un ticket.", + "delete":"Supprimez un ticket.", + "deleteNoTranscript":"Supprimez ce ticket sans créer de transcription.", + "reopen":"Rouvrez un ticket.", + "claim":"Prendre en charge un ticket.", + "claimUser":"Prendre en charge ce ticket pour quelqu'un d'autre au lieu de vous-même.", + "unclaim":"Libérer un ticket.", + "pin":"Épinglez un ticket.", + "unpin":"Désépingler un ticket.", + "move":"Déplacez un ticket.", + "moveId":"L'identifiant de l'option vers laquelle vous souhaitez déplacer.", + "rename":"Renommez un ticket.", + "renameName":"Le nouveau nom pour ce ticket.", + "add":"Ajoutez un utilisateur à un ticket.", + "addUser":"L'utilisateur à ajouter.", + "remove":"Retirez un utilisateur d'un ticket.", + "removeUser":"L'utilisateur à retirer.", + "blacklist":"Gérez la liste noire des tickets.", + "blacklistView":"Voir la liste noire actuelle.", + "blacklistAdd":"Ajoutez un utilisateur à la liste noire.", + "blacklistRemove":"Retirez un utilisateur de la liste noire.", + "blacklistGet":"Obtenez les détails d'un utilisateur mis sur la liste noire.", + "blacklistGetUser":"L'utilisateur dont vous souhaitez obtenir les détails.", + "stats":"Voir les statistiques du bot, d'un membre ou d'un ticket.", + "statsReset":"Réinitialisez toutes les statistiques du bot (et commencez à compter à partir de zéro).", + "statsGlobal":"Voir les statistiques globales.", + "statsUser":"Voir les statistiques d'un utilisateur dans le serveur.", + "statsUserUser":"L'utilisateur à afficher.", + "statsTicket":"Voir les statistiques d'un ticket dans le serveur.", + "statsTicketTicket":"Le ticket à afficher.", + "clear":"Supprimez plusieurs tickets en même temps.", + "clearFilter":"Le filtre pour supprimer les tickets.", + "clearFilters":{ + "all":"Tous", + "open":"Ouverts", + "close":"Fermés", + "claim":"Pris en charge", + "unclaim":"Non pris en charge", + "pin":"Épinglés", + "unpin":"Désépinglés", + "autoclose":"Fermés automatiquement" + }, + "autoclose":"Gérez la fermeture automatique dans un ticket.", + "autocloseDisable":"Désactivez la fermeture automatique dans ce ticket.", + "autocloseEnable":"Activez la fermeture automatique dans ce ticket.", + "autocloseEnableTime":"Le nombre d'heures d'inactivité nécessaire pour fermer ce ticket.", + "autodelete":"Gérez la suppression automatique dans un ticket.", + "autodeleteDisable":"Désactivez la suppression automatique dans ce ticket.", + "autodeleteEnable":"Activez la suppression automatique dans ce ticket.", + "autodeleteEnableTime":"Le nombre de jours d'inactivité nécessaire pour supprimer ce ticket." + }, + "helpMenu":{ + "help":"Obtenez une liste de toutes les commandes disponibles.", + "ticket":"Créez instantanément un ticket.", + "close":"Fermez un ticket, cela désactive l'écriture dans ce canal.", + "delete":"Supprimez un ticket, cela crée une transcription lorsqu'elle est activée.", + "reopen":"Rouvrez un ticket, cela active à nouveau l'écriture dans ce canal.", + "pin":"Épinglez un ticket. Cela déplacera le ticket en haut et ajoutera un émoji '📌' au nom.", + "unpin":"Désépingler un ticket. Le ticket restera à sa position mais perdra l'émoji '📌'.", + "move":"Déplacez un ticket. Cela changera le type de ce ticket.", + "rename":"Renommez un ticket. Cela changera le nom du canal de ce ticket.", + "claim":"Prendre en charge un ticket. Ainsi, vous pouvez informer votre équipe que vous gérez ce ticket.", + "unclaim":"Libérer un ticket. Ainsi, vous pouvez informer votre équipe que ce ticket est à nouveau libre.", + "add":"Ajoutez un utilisateur à un ticket. Cela permettra à l'utilisateur de lire et d'écrire dans ce ticket.", + "remove":"Retirez un utilisateur d'un ticket. Cela supprimera la capacité de lire et d'écrire pour un utilisateur dans ce ticket.", + "panel":"Générez un message avec un menu déroulant ou des boutons (pour la création de tickets).", + "blacklistView":"Voir la liste noire actuelle.", + "blacklistAdd":"Ajoutez un utilisateur à la liste noire.", + "blacklistRemove":"Retirez un utilisateur de la liste noire.", + "blacklistGet":"Obtenez les détails d'un utilisateur mis sur la liste noire.", + "statsGlobal":"Voir les statistiques globales.", + "statsTicket":"Voir les statistiques d'un ticket dans le serveur.", + "statsUser":"Voir les statistiques d'un utilisateur dans le serveur.", + "statsReset":"Réinitialisez toutes les statistiques du bot (et commencez à compter à partir de zéro).", + "autocloseDisable":"Désactivez la fermeture automatique dans ce ticket.", + "autocloseEnable":"Activez la fermeture automatique dans ce ticket.", + "autodeleteDisable":"Désactivez la suppression automatique dans ce ticket.", + "autodeleteEnable":"Activez la suppression automatique dans ce ticket." + }, + "stats":{ + "scopes":{ + "global":"Statistiques Globales", + "system":"Statistiques Système", + "user":"Statistiques Utilisateur", + "ticket":"Statistiques Ticket", + "participants":"Participants" + }, + "properties":{ + "ticketsCreated":"Tickets Créés", + "ticketsClosed":"Tickets Fermés", + "ticketsDeleted":"Tickets Supprimés", + "ticketsReopened":"Tickets Rouverts", + "ticketsAutoclosed":"Tickets Fermés Automatiquement", + "ticketsClaimed":"Tickets pris en charge", + "ticketsPinned":"Tickets Épinglés", + "ticketsMoved":"Tickets Déplacés", + "usersBlacklisted":"Utilisateurs en Liste Noire", + "transcriptsCreated":"Transcriptions Créées" + } + } +} \ No newline at end of file From 42ff447a94d68af55a4dde8dff79f3486cdefb41 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:47:17 +0100 Subject: [PATCH 061/157] Added French & Turkish translations --- README.md | 6 +- languages/turkish.json | 477 +++++++++++++++++++++++++++ src/core/api/defaults/language.ts | 2 + src/data/framework/languageLoader.ts | 2 + 4 files changed, 484 insertions(+), 3 deletions(-) create mode 100644 languages/turkish.json diff --git a/README.md b/README.md index 6c87fc2..b2dab52 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@

Open Ticket is 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! -You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 32 Languages! If you need any help, feel free to join our discord server! +You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 18 Languages! If you need any help, feel free to join our discord server!

⭐️ Help us grow by giving a star! ⭐️

@@ -129,12 +129,12 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇮🇹 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 | |🇪🇪 Estonian |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇮 Finnish |iamnotmega |🔵 Up To Date (ChatGPT) | -|🇫🇷 French |sankedev & tostam |🟠 Temporary Outdated (beta) | |🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | -|🇹🇷 Turkish |0x15d3 |🟠 Temporary Outdated (beta) | |🇵🇱 Polish |mkevas |🟠 Temporary Outdated (beta) | |🇳🇴 Norwegian |noonenook |🟠 Temporary Outdated (beta) | |❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | diff --git a/languages/turkish.json b/languages/turkish.json new file mode 100644 index 0000000..9eed6e8 --- /dev/null +++ b/languages/turkish.json @@ -0,0 +1,477 @@ +{ + "_TRANSLATION": { + "otversion": "v4.0.0", + "translators": ["palestinian"], + "lastedited": "26/08/2024", + "language": "Turkish", + "automated": false + }, + "checker": { + "system": { + "typeError": "[HATA]", + "headerOpenTicket": "TICKET AÇ", + "typeWarning": "[UYARI]", + "typeInfo": "[BİLGİ]", + "headerConfigChecker": "YAPILANDIRMA KONTROLÜ", + "headerDescription": "Yapılandırma dosyalarınızda hataları kontrol edin!", + "footerError": "Bot, tüm {0} hataları düzeltilmeden başlamayacak!", + "footerWarning": "Başlamadan önce tüm {0} hatalarını düzeltmeniz önerilir!", + "footerSupport": "DESTEK: {0} - DOKÜMANLAR: {1}", + "compactInformation": "Daha fazla bilgi için {0} kullanın!", + "dataPath": "yol", + "dataDocs": "dokümanlar", + "dataMessages": "mesaj" + }, + "messages": { + "stringTooShort": "Bu dize {0} karakterden daha kısa olamaz!", + "stringTooLong": "Bu dize {0} karakterden daha uzun olamaz!", + "stringLengthInvalid": "Bu dize {0} karakter uzunluğunda olmalıdır!", + "stringStartsWith": "Bu dize {0} ile başlamalıdır!", + "stringEndsWith": "Bu dize {0} ile bitmelidir!", + "stringContains": "Bu dize {0} içermelidir!", + "stringChoices": "Bu dize yalnızca şu değerlerden biri olmalıdır: {0}!", + "stringRegex": "Bu dize geçersiz!", + + "numberTooShort": "Bu sayı {0} karakterden daha kısa olamaz!", + "numberTooLong": "Bu sayı {0} karakterden daha uzun olamaz!", + "numberLengthInvalid": "Bu sayı {0} karakter uzunluğunda olmalıdır!", + "numberTooSmall": "Bu sayı en az {0} olmalıdır!", + "numberTooLarge": "Bu sayı en fazla {0} olmalıdır!", + "numberNotEqual": "Bu sayı {0} olmalıdır!", + "numberStep": "Bu sayı {0} katı olmalıdır!", + "numberStepOffset": "Bu sayı {0} ile başlayarak {1} katı olmalıdır!", + "numberStartsWith": "Bu sayı {0} ile başlamalıdır!", + "numberEndsWith": "Bu sayı {0} ile bitmelidir!", + "numberContains": "Bu sayı {0} içermelidir!", + "numberChoices": "Bu sayı yalnızca şu değerlerden biri olmalıdır: {0}!", + "numberFloat": "Bu sayı ondalıklı olamaz!", + "numberNegative": "Bu sayı negatif olamaz!", + "numberPositive": "Bu sayı pozitif olamaz!", + "numberZero": "Bu sayı sıfır olamaz!", + + "booleanTrue": "Bu boolean true olamaz!", + "booleanFalse": "Bu boolean false olamaz!", + + "arrayEmptyDisabled": "Bu dizi boş olamaz!", + "arrayEmptyRequired": "Bu dizi boş olmalıdır!", + "arrayTooShort": "Bu dizi en az {0} uzunluğunda olmalıdır!", + "arrayTooLong": "Bu dizi en fazla {0} uzunluğunda olmalıdır!", + "arrayLengthInvalid": "Bu dizi {0} uzunluğunda olmalıdır!", + "arrayInvalidTypes": "Bu dizi yalnızca şu türleri içerebilir: {0}!", + "arrayDouble": "Bu dizi aynı değeri iki kez içeremez!", + + "discordInvalidId": "Bu geçersiz bir discord {0} kimliğidir!", + "discordInvalidIdOptions": "Bu geçersiz bir discord {0} kimliğidir! Ayrıca bunları kullanabilirsiniz: {1}!", + "discordInvalidToken": "Bu geçersiz bir discord tokenidir (sentaktik olarak)!", + "colorInvalid": "Bu geçersiz bir hex renktir!", + "emojiTooShort": "Bu dize en az {0} emoji olmalıdır!", + "emojiTooLong": "Bu dize en fazla {0} emoji olmalıdır!", + "emojiCustom": "Bu emoji özel bir discord emojisi olamaz!", + "emojiInvalid": "Bu geçersiz bir emojidir!", + "urlInvalid": "Bu url geçersiz!", + "urlInvalidHttp": "Bu url yalnızca https:// protokolünü kullanabilir!", + "urlInvalidProtocol": "Bu url yalnızca http:// ve https:// protokollerini kullanabilir!", + "urlInvalidHostname": "Bu url yasaklı bir hostname içeriyor!", + "urlInvalidExtension": "Bu url geçersiz bir uzantıya sahip! Şu uzantılardan birini seçin: {0}!", + "urlInvalidPath": "Bu url geçersiz bir yola sahip!", + "idNotUnique": "Bu id benzersiz değil, lütfen başka bir id kullanın!", + "idNonExistent": "{0} id mevcut değil!", + + "invalidType": "Bu özellik {0} türünde olmalıdır!", + "propertyMissing": "Bu nesneden {0} özelliği eksik!", + "propertyOptional": "Bu nesnede {0} özelliği isteğe bağlıdır!", + "objectDisabled": "Bu nesne devre dışı, {0} kullanarak etkinleştirin!", + "nullInvalid": "Bu özellik null olamaz!", + "switchInvalidType": "Bu, aşağıdaki türlerden biri olmalıdır: {0}!", + "objectSwitchInvalid": "Bu nesne aşağıdaki türlerden biri olmalıdır: {0}!", + + "invalidLanguage": "Bu geçersiz bir dildir!", + "invalidButton": "Bu buton en az bir {0} veya {1} içermelidir!", + "unusedOption": "Seçenek {0} hiçbir yerde kullanılmıyor!", + "unusedQuestion": "Soru {0} hiçbir yerde kullanılmıyor!", + "dropdownOption": "Dropdown etkin olan bir panel yalnızca 'ticket' türündeki seçenekleri içerebilir!" + } + }, + "actions": { + "buttons": { + "create": "Ticket'i Ziyaret Et", + "close": "Ticket'i Kapat", + "delete": "Ticket'i Sil", + "reopen": "Ticket'i Yeniden Aç", + "claim": "Ticket'i Üstlen", + "unclaim": "Ticket'i Üstlenmeyi Bırak", + "pin": "Ticket'i Sabitle", + "unpin": "Ticket'i Sabitlemeyi Kaldır", + "clear": "Ticket'leri Sil", + "helpSwitchSlash": "Slash Komutlarını Görüntüle", + "helpSwitchText": "Metin Komutlarını Görüntüle", + "helpPage": "Sayfa {0}", + "withReason": "Sebep ile", + "withoutTranscript": "Transkript Olmadan" + }, + "titles": { + "created": "Ticket Oluşturuldu", + "close": "Ticket Kapandı", + "delete": "Ticket Silindi", + "reopen": "Ticket Yeniden Açıldı", + "claim": "Ticket Üstlenildi", + "unclaim": "Ticket Üstlenme Bırakıldı", + "pin": "Ticket Sabitlendi", + "unpin": "Ticket Sabitlemesi Kaldırıldı", + "rename": "Ticket Yeniden Adlandırıldı", + "move": "Ticket Taşındı", + "add": "Ticket Kullanıcısı Eklendi", + "remove": "Ticket Kullanıcısı Çıkarıldı", + + "help": "Mevcut Komutlar", + "statsReset": "İstatistikleri Sıfırla", + "blacklistAdd": "Kullanıcı Kara Listeye Alındı", + "blacklistRemove": "Kullanıcı Kara Listeden Çıkarıldı", + "blacklistGet": "Kara Listeye Alınan Kullanıcı", + "blacklistView": "Mevcut Kara Liste", + "blacklistAddDm": "Kara Listeye Eklendi", + "blacklistRemoveDm": "Kara Listeden Çıkarıldı", + "clear": "Ticket'ler Temizlendi", + "roles": "Roller Güncellendi", + + "autoclose": "Ticket Otomatik Olarak Kapandı", + "autocloseEnabled": "Otomatik Kapatma Etkinleştirildi", + "autocloseDisabled": "Otomatik Kapatma Devre Dışı Bırakıldı", + "autodelete": "Ticket Otomatik Olarak Silindi", + "autodeleteEnabled": "Otomatik Silme Etkinleştirildi" + }, + "descriptions": { + "create": "Ticket'iniz oluşturuldu. Aşağıdaki düğmeye tıklayarak erişebilirsiniz!", + "close": "Ticket başarıyla kapatıldı!", + "delete": "Ticket başarıyla silindi!", + "reopen": "Ticket başarıyla yeniden açıldı!", + "claim": "Ticket başarıyla üstlenildi!", + "unclaim": "Ticket başarıyla üstlenme bırakıldı!", + "pin": "Ticket başarıyla sabitlendi!", + "unpin": "Ticket sabitlemesi başarıyla kaldırıldı!", + "rename": "Ticket başarıyla {0} olarak yeniden adlandırıldı!", + "move": "Ticket başarıyla {0} konumuna taşındı!", + "add": "{0} ticket'e başarıyla eklendi!", + "remove": "{0} ticket'ten başarıyla çıkarıldı!", + + "helpExplanation": "`` => zorunlu parametre\n`[name]` => isteğe bağlı parametre", + "statsReset": "Bot istatistikleri başarıyla sıfırlandı!", + "statsError": "Ticket istatistiklerini görüntüleme başarısız oldu!\n{0} bir ticket değil!", + "blacklistAdd": "{0} başarıyla kara listeye alındı!", + "blacklistRemove": "{0} başarıyla serbest bırakıldı!", + "blacklistGetSuccess": "{0} şu anda kara listede!", + "blacklistGetEmpty": "{0} şu anda kara listede değil!", + "blacklistViewEmpty": "Henüz kara listeye alınan kimse yok!", + "blacklistViewTip": "Bir kullanıcıyı kara listeye almak için \"/blacklist add\" komutunu kullanın!", + "clearVerify": "Birden fazla ticket silmek istediğinize emin misiniz?\nBu işlem geri alınamaz!", + "clearReady": "{0} ticket başarıyla silindi!", + "rolesEmpty": "Güncellenen hiçbir rol yok!", + + "autocloseLeave": "Bu ticket, yaratıcısı sunucudan ayrıldığı için otomatik olarak kapatıldı!", + "autocloseTimeout": "Bu ticket, `{0}h` süresince aktif olmadığından otomatik olarak kapatıldı!", + "autodeleteLeave": "Bu ticket, yaratıcısı sunucudan ayrıldığı için otomatik olarak silindi!", + "autodeleteTimeout": "Bu ticket, `{0} gün` süresince aktif olmadığından otomatik olarak silindi!", + "autocloseEnabled": "Bu ticket'te otomatik kapatma etkinleştirildi!\nArtık `{0}h` süresince aktif olmadığında kapatılacaktır!", + "autocloseDisabled": "Bu ticket'te otomatik kapatma devre dışı bırakıldı!\nArtık otomatik olarak kapatılmayacak!", + "autodeleteEnabled": "Bu ticket'te otomatik silme etkinleştirildi!\nArtık `{0} gün` süresince aktif olmadığında silinecektir!", + "autodeleteDisabled": "Bu ticket'te otomatik silme devre dışı bırakıldı!\nArtık otomatik olarak silinmeyecek!", + + "ticketMessageLimit": "Aynı anda yalnızca {0} ticket oluşturabilirsiniz!", + "ticketMessageAutoclose": "Bu ticket, {0}h süresince aktif olmadığında otomatik olarak kapatılacaktır!", + "ticketMessageAutodelete": "Bu ticket, {0} gün süresince aktif olmadığında otomatik olarak silinecektir!", + "panelReady": "Paneli aşağıda bulabilirsiniz!\nBu mesaj artık silinebilir!" + }, + "modal": { + "closePlaceholder": "Bu ticket'i neden kapattınız?", + "deletePlaceholder": "Bu ticket'i neden sildiniz?", + "reopenPlaceholder": "Bu ticket'i neden yeniden açtınız?", + "claimPlaceholder": "Bu ticket'i neden üstlendiniz?", + "unclaimPlaceholder": "Bu ticket'ten neden üstlenmeyi bıraktınız?", + "pinPlaceholder": "Bu ticket'i neden sabitlediniz?", + "unpinPlaceholder": "Bu ticket'ten sabitlemeyi neden kaldırdınız?" + }, + "logs": { + "createLog": "Yeni bir ticket {0} tarafından oluşturuldu!", + "closeLog": "Bu ticket {0} tarafından kapatıldı!", + "closeDm": "Ticket'iniz sunucumuzda kapatıldı!", + "deleteLog": "Bu ticket {0} tarafından silindi!", + "deleteDm": "Ticket'iniz sunucumuzda silindi!", + "reopenLog": "Bu ticket {0} tarafından yeniden açıldı!", + "reopenDm": "Ticket'iniz sunucumuzda yeniden açıldı!", + "claimLog": "Bu ticket {0} tarafından üstlenildi!", + "claimDm": "Ticket'iniz sunucumuzda üstlenildi!", + "unclaimLog": "Bu ticket {0} tarafından üstlenme bırakıldı!", + "unclaimDm": "Ticket'iniz sunucumuzda üstlenme bırakıldı!", + "pinLog": "Bu ticket {0} tarafından sabitlendi!", + "pinDm": "Ticket'iniz sunucumuzda sabitlendi!", + "unpinLog": "Bu ticket {0} tarafından sabitlemesi kaldırıldı!", + "unpinDm": "Ticket'iniz sunucumuzda sabitlemesi kaldırıldı!", + "renameLog": "Bu ticket {1} tarafından {0} olarak yeniden adlandırıldı!", + "renameDm": "Ticket'iniz sunucumuzda {0} olarak yeniden adlandırıldı!", + "moveLog": "Bu ticket {1} tarafından {0} konumuna taşındı!", + "moveDm": "Ticket'iniz sunucumuzda {0} konumuna taşındı!", + "addLog": "{0} bu ticket'e {1} tarafından eklendi!", + "addDm": "{0} ticket'inize sunucumuzda eklendi!", + "removeLog": "{0} bu ticket'ten {1} tarafından çıkarıldı!", + "removeDm": "{0} ticket'inizden sunucumuzda çıkarıldı!", + + "blacklistAddLog": "{0}, {1} tarafından kara listeye alındı!", + "blacklistRemoveLog": "{0}, {1} tarafından kara listeden çıkarıldı!", + "blacklistAddDm": "Sunucumuzda kara listeye alındınız!\nArtık bir ticket oluşturamazsınız!", + "blacklistRemoveDm": "Sunucumuzda kara listeden çıkarıldınız!\nArtık ticket oluşturabilirsiniz!", + "clearLog": "{0} ticket {1} tarafından silindi!" + } + }, + "transcripts": { + "success": { + "visit": "Transkripti Ziyaret Et", + "ready": "Transkript Oluşturuldu", + "textFileDescription": "Bu, silinmiş bir ticket'ın metin transkriptidir!", + "htmlProgress": "Lütfen bu html transkriptinin işlenmesini bekleyin...", + + "createdChannel": "Sunucuda yeni bir {0} transkripti oluşturuldu!", + "createdCreator": "Sizin ticket'ınız için yeni bir {0} transkripti oluşturuldu!", + "createdParticipant": "Katıldığınız bir ticket'ta yeni bir {0} transkripti oluşturuldu!", + "createdActiveAdmin": "Katıldığınız bir ticket'ta yeni bir {0} transkripti oluşturuldu!", + "createdEveryAdmin": "Yönetici olarak katıldığınız bir ticket'ta yeni bir {0} transkripti oluşturuldu!", + "createdOther": "Yeni bir {0} transkripti oluşturuldu!" + }, + "errors": { + "retry": "Yeniden Dene", + "continue": "Transkript Olmadan Sil", + "backup": "Yedek Transkript Oluştur", + "error": "Transkript oluşturulurken bir sorun oluştu.\nNe yapmak istersiniz?\n\nBu ticket silinmeyecek, bu butonlardan birine tıklamadan önce." + } + }, + "errors": { + "titles": { + "internalError": "Dahili Hata", + "optionMissing": "Komut Seçeneği Eksik", + "optionInvalid": "Komut Seçeneği Geçersiz", + "unknownCommand": "Bilinmeyen Komut", + "noPermissions": "İzin Yok", + "unknownTicket": "Bilinmeyen Ticket", + "deprecatedTicket": "Eski Ticket", + "unknownOption": "Bilinmeyen Seçenek", + "unknownPanel": "Bilinmeyen Panel", + "notInGuild": "Sunucuda Değil", + "channelRename": "Kanal Yeniden Adlandırılamadı", + "busy": "Ticket Meşgul" + }, + "descriptions": { + "askForInfo": "Daha fazla bilgi için botun sahibine ulaşın!", + "askForInfoResolve": "Bu sorun birkaç denemeden sonra çözülmezse, botun sahibine ulaşın.", + "internalError": "Bu {0} isteğine yanıt vermekte başarısız olundu!", + "optionMissing": "Bu komutta zorunlu bir parametre eksik!", + "optionInvalid": "Bu komutta bir parametre geçersiz!", + "optionInvalidChoose": "Şu seçeneklerden birini seçin", + "unknownCommand": "Daha fazla bilgi için yardım menüsüne göz atmayı deneyin!", + "noPermissions": "Bu {0} işlemini kullanma izniniz yok!", + "noPermissionsList": "Gerekli İzinler: (bunlardan biri)", + "noPermissionsCooldown": "Bu {0} işlemini kullanma izniniz yok çünkü bir bekleme süreniz var!", + "noPermissionsBlacklist": "Bu {0} işlemini kullanma izniniz yok çünkü kara listeye alındınız!", + "noPermissionsLimitGlobal": "Sunucu, maksimum ticket limitine ulaştığı için ticket oluşturma izniniz yok!", + "noPermissionsLimitGlobalUser ": "Maksimum ticket limitine ulaştığınız için ticket oluşturma izniniz yok!", + "noPermissionsLimitOption": "Bu seçenek için sunucu maksimum ticket limitine ulaştığı için ticket oluşturma izniniz yok!", + "noPermissionsLimitOptionUser ": "Bu seçenek için maksimum ticket limitine ulaştığınız için ticket oluşturma izniniz yok!", + "unknownTicket": "Bu komutu geçerli bir ticket'ta tekrar deneyin!", + "deprecatedTicket": "Mevcut kanal geçerli bir ticket değil! Bu, eski bir Open Ticket sürümünden kalmış olabilir!", + "notInGuild": "Bu {0} DM'de çalışmaz! Lütfen bunu bir sunucuda tekrar deneyin!", + "channelRename": "Discord hız limitleri nedeniyle, botun kanal adını değiştirmesi şu anda mümkün değil. Bot yeniden başlatılmazsa kanal 10 dakika içinde otomatik olarak yeniden adlandırılacaktır.", + "channelRenameSource": "Bu hatanın kaynağı: {0}", + "busy": "Bu {0} işlemini kullanamıyorsunuz!\nTicket şu anda bot tarafından işleniyor.\n\nLütfen birkaç saniye içinde tekrar deneyin!" + }, + "optionInvalidReasons": { + "stringRegex": "Değer desenle eşleşmiyor!", + "stringMinLength": "Değer en az {0} karakter olmalı!", + "stringMaxLength": "Değer en çok {0} karakter olmalı!", + "numberInvalid": "Geçersiz sayı!", + "numberMin": "Sayı en az {0} olmalı!", + "numberMax": "Sayı en çok {0} olmalı!", + "numberDecimal": "Sayı ondalıklı olmamalıdır!", + "numberNegative": "Sayı negatif olmamalıdır!", + "numberPositive": "Sayı pozitif olmamalıdır!", + "numberZero": "Sayı sıfır olmamalıdır!", + "channelNotFound": "Kanal bulunamadı!", + "userNotFound": "Kullanıcı bulunamadı!", + "roleNotFound": "Rol bulunamadı!", + "memberNotFound": "Kullanıcı bulunamadı!", + "mentionableNotFound": "Kullanıcı veya rol bulunamadı!", + "channelType": "Geçersiz kanal türü!", + "notInGuild": "Bu seçenek sunucuda olmanızı gerektiriyor!" + }, + "permissions": { + "developer": "Botun geliştiricisi olmalısınız.", + "owner": "Sunucu sahibi olmalısınız.", + "admin": "Sunucu yöneticisi olmalısınız.", + "moderator": "Bir moderatör olmalısınız.", + "support": "Destek ekibinde olmalısınız.", + "member": "Bir üye olmalısınız.", + "discord-administrator": "`ADMINISTRATOR` iznine sahip olmalısınız." + }, + "actionInvalid": { + "close": "Ticket zaten kapatıldı!", + "reopen": "Ticket henüz kapatılmadı!", + "claim": "Ticket zaten üstlenildi!", + "unclaim": "Ticket henüz üstlenilmedi!", + "pin": "Ticket zaten sabitlendi!", + "unpin": "Ticket henüz sabitlenmedi!", + "add": "Bu kullanıcı zaten ticket'e erişim sağlıyor!", + "remove": "Bu kullanıcıyı ticket'ten çıkarmak mümkün değil!" + } + }, + "params": { + "uppercase": { + "ticket": "Ticket", + "tickets": "Tickets", + "reason": "Sebep", + "creator": "Yaratıcı", + "remaining": "Kalan Süre", + "added": "Eklendi", + "removed": "Çıkarıldı", + "filter": "Filtre", + "claimedBy": "Üstlenen {0}", + "method": "Yöntem", + "type": "Tür", + "blacklisted": "Kara Listeye Alınmış", + "panel": "Panel", + "command": "Komut", + "system": "Sistem", + "true": "Doğru", + "false": "Yanlış", + "syntax": "Sözdizimi", + "originalName": "Orijinal İsim", + "newName": "Yeni İsim", + "until": "Kadar", + "validOptions": "Geçerli Seçenekler", + "validPanels": "Geçerli Paneller", + "autoclose": "Otomatik Kapatma", + "autodelete": "Otomatik Silme", + "startupDate": "Başlangıç Tarihi", + "version": "Sürüm", + "name": "İsim", + "role": "Rol", + "status": "Durum", + "claimed": "Üstlenildi", + "pinned": "Sabitlenmiş", + "creationDate": "Oluşturulma Tarihi" + }, + "lowercase": { + "text": "metin", + "html": "html", + "command": "komut", + "modal": "modal", + "button": "buton", + "dropdown": "açılır menü", + "method": "yöntem" + } + }, + "commands": { + "reason": "Kayıtlarda görülebilecek isteğe bağlı bir sebep belirtin.", + "help": "Tüm mevcut komutların bir listesini alın.", + "panel": "Bir mesaj gönderin (ticket oluşturma için dropdown veya butonlar).", + "panelId": "Oluşturmak istediğiniz panelin kimliği.", + "panelAutoUpdate": "Bu panelin düzenlendiğinde otomatik olarak güncellenmesini ister misiniz?", + "ticket": "Anında bir ticket oluştur.", + "ticketId": "Oluşturmak istediğiniz ticket'ın kimliği.", + "close": "Bir ticket'ı kapat.", + "delete": "Bir ticket'ı sil.", + "deleteNoTranscript": "Bu ticket'ı transkript oluşturmadan sil.", + "reopen": "Bir ticket'ı yeniden aç.", + "claim": "Bir ticket'ı üstlen.", + "claimUser ": "Bu ticket'ı kendiniz yerine başka birine üstlenin.", + "unclaim": "Bir ticket'tan üstlenmeyi bırak.", + "pin": "Bir ticket'ı sabitle.", + "unpin": "Bir ticket'ın sabitlemesini kaldır.", + "move": "Bir ticket'ı taşı.", + "moveId": "Taşımak istediğiniz seçeneğin kimliği.", + "rename": "Bir ticket'ı yeniden adlandır.", + "renameName": "Bu ticket için yeni isim.", + "add": "Bir kullanıcıyı bir ticket'a ekle.", + "addUser ": "Eklenecek kullanıcı.", + "remove": "Bir kullanıcıyı bir ticket'tan çıkar.", + "removeUser ": "Çıkarılacak kullanıcı.", + "blacklist": "Ticket kara listesini yönet.", + "blacklistView": "Mevcut kara listeyi görüntüle.", + "blacklistAdd": "Bir kullanıcıyı kara listeye ekle.", + "blacklistRemove": "Bir kullanıcıyı kara listeden çıkar.", + "blacklistGet": "Kara listeye alınmış bir kullanıcının detaylarını al.", + "blacklistGetUser ": "Detaylarını almak istediğiniz kullanıcı.", + "stats": "Bot, bir üye veya bir ticket'tan istatistikleri görüntüle.", + "statsReset": "Botun tüm istatistiklerini sıfırla (sıfırdan saymaya başla).", + "statsGlobal": "Küresel istatistikleri görüntüle.", + "statsUser ": "Sunucudaki bir kullanıcının istatistiklerini görüntüle.", + "statsUser User": "Görüntülemek istediğiniz kullanıcı.", + "statsTicket": "Sunucudaki bir ticket'ın istatistiklerini görüntüle.", + "statsTicketTicket": "Görüntülemek istediğiniz ticket.", + "clear": "Aynı anda birden fazla ticket sil.", + "clearFilter": "Ticket'ları silmek için filtre.", + "clearFilters": { + "all": "Hepsi", + "open": "Açık", + "close": "Kapalı", + "claim": "Üstlenilen", + "unclaim": "Üstlenilmeyen", + "pin": "Sabitlenmiş", + "unpin": "Sabitlenmemiş", + "autoclose": "Otomatik Kapatılmış" + }, + "autoclose": "Bir ticket'ta otomatik kapatmayı yönet.", + "autocloseDisable": "Bu ticket'ta otomatik kapatmayı devre dışı bırak.", + "autocloseEnable": "Bu ticket'ta otomatik kapatmayı etkinleştir.", + "autocloseEnableTime": "Bu ticket'ın kapatılması için gereken inaktif süre (saat cinsinden).", + "autodelete": "Bir ticket'ta otomatik silmeyi yönet.", + "autodeleteDisable": "Bu ticket'ta otomatik silmeyi devre dışı bırak.", + "autodeleteEnable": "Bu ticket'ta otomatik silmeyi etkinleştir.", + "autodeleteEnableTime": "Bu ticket'ın silinmesi için gereken inaktif süre (gün cinsinden)." + }, + "helpMenu": { + "help": "Tüm mevcut komutların bir listesini alın.", + "ticket": "Anında bir ticket oluştur.", + "close": "Bir ticket'ı kapat, bu kanalda yazmayı devre dışı bırakır.", + "delete": "Bir ticket'ı sil, bu etkinleştirildiğinde bir transkript oluşturur.", + "reopen": "Bir ticket'ı yeniden aç, bu kanalda yazmayı tekrar etkinleştirir.", + "pin": "Bir ticket'ı sabitle. Bu, ticket'ı en üstte tutacak ve adına '📌' emojisi ekleyecektir.", + "unpin": "Bir ticket'ın sabitlemesini kaldır. Ticket, konumunu koruyacak ancak '📌' emojisini kaybedecektir.", + "move": "Bir ticket'ı taşı. Bu, bu ticket'ın türünü değiştirecektir.", + "rename": "Bir ticket'ı yeniden adlandır. Bu, bu ticket'ın kanal adını değiştirecektir.", + "claim": "Bir ticket'ı üstlen. Bu, ekibinize bu ticket'ı sizin üstlendiğinizi bildirecektir.", + "unclaim": "Bir ticket'tan üstlenmeyi bırak. Bu, ekibinize bu ticket'ın tekrar serbest olduğunu bildirecektir.", + "add": "Bir kullanıcıyı bir ticket'a ekle. Bu, kullanıcının bu ticket'ta okumaya ve yazmaya izin verecektir.", + "remove": "Bir kullanıcıyı bir ticket'tan çıkar. Bu, bir kullanıcının bu ticket'ta okumaya ve yazmaya izin vermeyecektir.", + "panel": "Bir mesaj gönderin (ticket oluşturma için dropdown veya butonlar).", + "blacklistView": "Mevcut kara listeyi görüntüle.", + "blacklistAdd": "Bir kullanıcıyı kara listeye ekle.", + "blacklistRemove": "Bir kullanıcıyı kara listeden çıkar.", + "blacklistGet": "Kara listeye alınmış bir kullanıcının detaylarını al.", + "statsGlobal": "Küresel istatistikleri görüntüle.", + "statsTicket": "Sunucudaki bir ticket'ın istatistiklerini görüntüle.", + "statsUser ": "Sunucudaki bir kullanıcının istatistiklerini görüntüle.", + "statsReset": "Botun tüm istatistiklerini sıfırla (sıfırdan saymaya başla).", + "autocloseDisable": "Bu ticket'ta otomatik kapatmayı devre dışı bırak.", + "autocloseEnable": "Bu ticket'ta otomatik kapatmayı etkinleştir.", + "autodeleteDisable": "Bu ticket'ta otomatik silmeyi devre dışı bırak.", + "autodeleteEnable": "Bu ticket'ta otomatik silmeyi etkinleştir." + }, + "stats": { + "scopes": { + "global": "Küresel İstatistikler", + "system": "Sistem İstatistikleri", + "user": "Kullanıcı İstatistikleri", + "ticket": "Ticket İstatistikleri", + "participants": "Katılımcılar" + }, + "properties": { + "ticketsCreated": "Oluşturulan Ticket'lar", + "ticketsClosed": "Kapalı Ticket'lar", + "ticketsDeleted": "Silinen Ticket'lar", + "ticketsReopened": "Yeniden Açılan Ticket'lar", + "ticketsAutoclosed": "Otomatik Kapatılan Ticket'lar", + "ticketsClaimed": "Üstlenilen Ticket'lar", + "ticketsPinned": "Sabitlenen Ticket'lar", + "ticketsMoved": "Taşınan Ticket'lar", + "usersBlacklisted": "Kara Listeye Alınan Kullanıcılar", + "transcriptsCreated": "Oluşturulan Transkriptler" + } + } +} \ No newline at end of file diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index db2cb24..0f98a18 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -461,6 +461,8 @@ export interface ODLanguageManagerIds_Default { "openticket:finnish":ODLanguage, "openticket:danish":ODLanguage, "openticket:thai":ODLanguage, + "openticket:turkish":ODLanguage, + "openticket:french":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index d46b5c1..6e4f2bc 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -19,6 +19,8 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODJsonLanguage("openticket:finnish","finnish.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:danish","danish.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:thai","thai.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:turkish","turkish.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:french","french.json")) /** How to add more languages? * - Register the language to the manager (see above) From 5d8626974315ab0778202046d5b62c9f77e7106b Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 5 Dec 2024 22:10:02 +0100 Subject: [PATCH 062/157] Fixed stats not displaying with SQLite plugin Lot's of stats were hidden in the embed when using the ot-sqlite-database plugin. This was caused by a recent API breaking-change that made everything async. The problem wasn't related to the plugin itself, but the Open Ticket api. Updating the plugin is not required. --- src/actions/claimTicket.ts | 4 +- src/actions/closeTicket.ts | 4 +- src/actions/createTicket.ts | 6 +-- src/actions/createTranscript.ts | 4 +- src/actions/deleteTicket.ts | 4 +- src/actions/moveTicket.ts | 4 +- src/actions/pinTicket.ts | 4 +- src/actions/reopenTicket.ts | 4 +- src/commands/blacklist.ts | 4 +- src/core/api/defaults/stat.ts | 90 ++++++++++++++++---------------- src/core/api/modules/stat.ts | 40 +++++++------- src/data/framework/codeLoader.ts | 8 +-- 12 files changed, 88 insertions(+), 88 deletions(-) diff --git a/src/actions/claimTicket.ts b/src/actions/claimTicket.ts index e3b6aa5..6ce25a3 100644 --- a/src/actions/claimTicket.ts +++ b/src/actions/claimTicket.ts @@ -22,8 +22,8 @@ export const registerActions = async () => { ticket.get("openticket:busy").value = true //update stats - openticket.stats.get("openticket:global").setStat("openticket:tickets-claimed",1,"increase") - openticket.stats.get("openticket:user").setStat("openticket:tickets-claimed",user.id,1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-claimed",1,"increase") + await openticket.stats.get("openticket:user").setStat("openticket:tickets-claimed",user.id,1,"increase") //update category const rawClaimCategory = ticket.option.get("openticket:channel-categories-claimed").value.find((c) => c.user == user.id) diff --git a/src/actions/closeTicket.ts b/src/actions/closeTicket.ts index 4e87dcd..d8374d3 100644 --- a/src/actions/closeTicket.ts +++ b/src/actions/closeTicket.ts @@ -24,8 +24,8 @@ export const registerActions = async () => { ticket.get("openticket:busy").value = true //update stats - openticket.stats.get("openticket:global").setStat("openticket:tickets-closed",1,"increase") - openticket.stats.get("openticket:user").setStat("openticket:tickets-closed",user.id,1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-closed",1,"increase") + await openticket.stats.get("openticket:user").setStat("openticket:tickets-closed",user.id,1,"increase") //update category const closeCategory = ticket.option.get("openticket:channel-category-closed").value diff --git a/src/actions/createTicket.ts b/src/actions/createTicket.ts index adca753..7174a9d 100644 --- a/src/actions/createTicket.ts +++ b/src/actions/createTicket.ts @@ -159,8 +159,8 @@ export const registerActions = async () => { ]) //manage stats - openticket.stats.get("openticket:global").setStat("openticket:tickets-created",1,"increase") - openticket.stats.get("openticket:user").setStat("openticket:tickets-created",user.id,1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-created",1,"increase") + await openticket.stats.get("openticket:user").setStat("openticket:tickets-created",user.id,1,"increase") //manage bot permissions await openticket.events.get("onTicketPermissionsCreated").emit([option,openticket.permissions,channel,user]) @@ -187,7 +187,7 @@ export const registerActions = async () => { ticket.get("openticket:ticket-message").value = msg.id //manage stats - openticket.stats.get("openticket:ticket").setStat("openticket:messages-sent",ticket.id.value,1,"increase") + await openticket.stats.get("openticket:ticket").setStat("openticket:messages-sent",ticket.id.value,1,"increase") await openticket.events.get("afterTicketMainMessageCreated").emit([ticket,msg,channel,user]) }catch(err){ diff --git a/src/actions/createTranscript.ts b/src/actions/createTranscript.ts index 88d9b1c..10fab95 100644 --- a/src/actions/createTranscript.ts +++ b/src/actions/createTranscript.ts @@ -145,8 +145,8 @@ export const registerActions = async () => { }) //update stats - openticket.stats.get("openticket:global").setStat("openticket:transcripts-created",1,"increase") - openticket.stats.get("openticket:user").setStat("openticket:transcripts-created",params.user.id,1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:transcripts-created",1,"increase") + await openticket.stats.get("openticket:user").setStat("openticket:transcripts-created",params.user.id,1,"increase") await openticket.events.get("afterTranscriptCreated").emit([openticket.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { diff --git a/src/actions/deleteTicket.ts b/src/actions/deleteTicket.ts index a50b043..e6f8367 100644 --- a/src/actions/deleteTicket.ts +++ b/src/actions/deleteTicket.ts @@ -56,8 +56,8 @@ export const registerActions = async () => { } //update stats - openticket.stats.get("openticket:global").setStat("openticket:tickets-deleted",1,"increase") - openticket.stats.get("openticket:user").setStat("openticket:tickets-deleted",user.id,1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-deleted",1,"increase") + await openticket.stats.get("openticket:user").setStat("openticket:tickets-deleted",user.id,1,"increase") //delete ticket from manager openticket.tickets.remove(ticket.id) diff --git a/src/actions/moveTicket.ts b/src/actions/moveTicket.ts index 7d95b82..dfcd7ba 100644 --- a/src/actions/moveTicket.ts +++ b/src/actions/moveTicket.ts @@ -17,8 +17,8 @@ export const registerActions = async () => { ticket.option = data //update stats - openticket.stats.get("openticket:global").setStat("openticket:tickets-moved",1,"increase") - openticket.stats.get("openticket:user").setStat("openticket:tickets-moved",user.id,1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-moved",1,"increase") + await openticket.stats.get("openticket:user").setStat("openticket:tickets-moved",user.id,1,"increase") //get new channel properties const channelPrefix = ticket.option.get("openticket:channel-prefix").value diff --git a/src/actions/pinTicket.ts b/src/actions/pinTicket.ts index 3f06af4..c0dfb32 100644 --- a/src/actions/pinTicket.ts +++ b/src/actions/pinTicket.ts @@ -22,8 +22,8 @@ export const registerActions = async () => { ticket.get("openticket:busy").value = true //update stats - openticket.stats.get("openticket:global").setStat("openticket:tickets-pinned",1,"increase") - openticket.stats.get("openticket:user").setStat("openticket:tickets-pinned",user.id,1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-pinned",1,"increase") + await openticket.stats.get("openticket:user").setStat("openticket:tickets-pinned",user.id,1,"increase") //move to top of category if (channel.parent){ diff --git a/src/actions/reopenTicket.ts b/src/actions/reopenTicket.ts index 4d992b6..dccf05c 100644 --- a/src/actions/reopenTicket.ts +++ b/src/actions/reopenTicket.ts @@ -24,8 +24,8 @@ export const registerActions = async () => { ticket.get("openticket:busy").value = true //update stats - openticket.stats.get("openticket:global").setStat("openticket:tickets-reopened",1,"increase") - openticket.stats.get("openticket:user").setStat("openticket:tickets-reopened",user.id,1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-reopened",1,"increase") + await openticket.stats.get("openticket:user").setStat("openticket:tickets-reopened",user.id,1,"increase") //update category const channelCategory = ticket.option.get("openticket:channel-category").value diff --git a/src/commands/blacklist.ts b/src/commands/blacklist.ts index f0d3a6e..d7448d4 100644 --- a/src/commands/blacklist.ts +++ b/src/commands/blacklist.ts @@ -74,8 +74,8 @@ export const registerCommandResponders = async () => { ]) //manage stats - openticket.stats.get("openticket:global").setStat("openticket:users-blacklisted",1,"increase") - openticket.stats.get("openticket:user").setStat("openticket:users-blacklisted",user.id,1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:users-blacklisted",1,"increase") + await openticket.stats.get("openticket:user").setStat("openticket:users-blacklisted",user.id,1,"increase") await instance.reply(await openticket.builders.messages.getSafe("openticket:blacklist-add").build(source,{guild,channel,user,data,reason})) diff --git a/src/core/api/defaults/stat.ts b/src/core/api/defaults/stat.ts index 3366d7d..d4ea1e9 100644 --- a/src/core/api/defaults/stat.ts +++ b/src/core/api/defaults/stat.ts @@ -92,24 +92,24 @@ export class ODStatGlobalScope_DefaultGlobal extends ODStatGlobalScope { return super.exists(id) } - getStat(id:StatsId): ODValidStatValue|null - getStat(id:ODValidId): ODValidStatValue|null + getStat(id:StatsId): Promise + getStat(id:ODValidId): Promise - getStat(id:ODValidId): ODValidStatValue|null { + getStat(id:ODValidId): Promise { return super.getStat(id) } - setStat(id:StatsId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean - setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + setStat(id:StatsId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise + setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise - setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise { return super.setStat(id,value,mode) } - resetStat(id:ODValidId): ODValidStatValue|null - resetStat(id:ODValidId): ODValidStatValue|null + resetStat(id:ODValidId): Promise + resetStat(id:ODValidId): Promise - resetStat(id:ODValidId): ODValidStatValue|null { + resetStat(id:ODValidId): Promise { return super.resetStat(id) } } @@ -151,24 +151,24 @@ export class ODStatGlobalScope_DefaultSystem extends ODStatGlobalScope { return super.exists(id) } - getStat(id:StatsId): ODValidStatValue|null - getStat(id:ODValidId): ODValidStatValue|null + getStat(id:StatsId): Promise + getStat(id:ODValidId): Promise - getStat(id:ODValidId): ODValidStatValue|null { + getStat(id:ODValidId): Promise { return super.getStat(id) } - setStat(id:StatsId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean - setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + setStat(id:StatsId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise + setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise - setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise { return super.setStat(id,value,mode) } - resetStat(id:ODValidId): ODValidStatValue|null - resetStat(id:ODValidId): ODValidStatValue|null + resetStat(id:ODValidId): Promise + resetStat(id:ODValidId): Promise - resetStat(id:ODValidId): ODValidStatValue|null { + resetStat(id:ODValidId): Promise { return super.resetStat(id) } } @@ -219,24 +219,24 @@ export class ODStatScope_DefaultUser extends ODStatScope { return super.exists(id) } - getStat(id:StatsId, scopeId:string): ODValidStatValue|null - getStat(id:ODValidId, scopeId:string): ODValidStatValue|null + getStat(id:StatsId, scopeId:string): Promise + getStat(id:ODValidId, scopeId:string): Promise - getStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + getStat(id:ODValidId, scopeId:string): Promise { return super.getStat(id,scopeId) } - setStat(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean - setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + setStat(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise - setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise { return super.setStat(id,scopeId,value,mode) } - resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null - resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null + resetStat(id:ODValidId, scopeId:string): Promise + resetStat(id:ODValidId, scopeId:string): Promise - resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + resetStat(id:ODValidId, scopeId:string): Promise { return super.resetStat(id,scopeId) } } @@ -282,24 +282,24 @@ export class ODStatScope_DefaultTicket extends ODStatScope { return super.exists(id) } - getStat(id:StatsId, scopeId:string): ODValidStatValue|null - getStat(id:ODValidId, scopeId:string): ODValidStatValue|null + getStat(id:StatsId, scopeId:string): Promise + getStat(id:ODValidId, scopeId:string): Promise - getStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + getStat(id:ODValidId, scopeId:string): Promise { return super.getStat(id,scopeId) } - setStat(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean - setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + setStat(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise - setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise { return super.setStat(id,scopeId,value,mode) } - resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null - resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null + resetStat(id:ODValidId, scopeId:string): Promise + resetStat(id:ODValidId, scopeId:string): Promise - resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + resetStat(id:ODValidId, scopeId:string): Promise { return super.resetStat(id,scopeId) } } @@ -340,24 +340,24 @@ export class ODStatScope_DefaultParticipants extends ODStatScope { return super.exists(id) } - getStat(id:StatsId, scopeId:string): ODValidStatValue|null - getStat(id:ODValidId, scopeId:string): ODValidStatValue|null + getStat(id:StatsId, scopeId:string): Promise + getStat(id:ODValidId, scopeId:string): Promise - getStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + getStat(id:ODValidId, scopeId:string): Promise { return super.getStat(id,scopeId) } - setStat(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean - setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean + setStat(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise - setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise { return super.setStat(id,scopeId,value,mode) } - resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null - resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null + resetStat(id:ODValidId, scopeId:string): Promise + resetStat(id:ODValidId, scopeId:string): Promise - resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + resetStat(id:ODValidId, scopeId:string): Promise { return super.resetStat(id,scopeId) } } \ No newline at end of file diff --git a/src/core/api/modules/stat.ts b/src/core/api/modules/stat.ts index baff800..0c1fe37 100644 --- a/src/core/api/modules/stat.ts +++ b/src/core/api/modules/stat.ts @@ -53,18 +53,18 @@ export class ODStatsManager extends ODManager { } //delete all deletable stats - deletableStats.forEach((data) => { + for (const data of deletableStats){ if (!this.database) return - this.database.delete(data.category,data.key) - }) + await this.database.delete(data.category,data.key) + } } async reset(){ if (!this.database) return const data = await this.database.getAll() - data.forEach((data) => { + for (const d of data){ if (!this.database) return - this.database.delete(data.category,data.key) - }) + await this.database.delete(d.category,d.key) + } } onInit(callback:ODStatsManagerInitCallback){ this.#initListeners.push(callback) @@ -90,10 +90,10 @@ export class ODStatScope extends ODManager { useDatabase(database:ODDatabase){ this.database = database } - getStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + async getStat(id:ODValidId, scopeId:string): Promise { if (!this.database) return null const newId = new ODId(id) - const data = this.database.get(this.id.value+"_"+newId.value,scopeId) + const data = await this.database.get(this.id.value+"_"+newId.value,scopeId) if (typeof data == "undefined"){ //set stats to default value & return @@ -105,28 +105,28 @@ export class ODStatScope extends ODManager { //return null on error return null } - setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + async setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise { if (!this.database) return false const stat = this.get(id) if (!stat) return false if (mode == "set" || typeof value != "number"){ - this.database.set(this.id.value+"_"+stat.id.value,scopeId,value) + await this.database.set(this.id.value+"_"+stat.id.value,scopeId,value) }else if (mode == "increase"){ const currentValue = this.getStat(id,scopeId) - if (typeof currentValue != "number") this.database.set(this.id.value+"_"+stat.id.value,scopeId,0) - else this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue+value) + if (typeof currentValue != "number") await this.database.set(this.id.value+"_"+stat.id.value,scopeId,0) + else await this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue+value) }else if (mode == "decrease"){ const currentValue = this.getStat(id,scopeId) - if (typeof currentValue != "number") this.database.set(this.id.value+"_"+stat.id.value,scopeId,0) - else this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue-value) + if (typeof currentValue != "number") await this.database.set(this.id.value+"_"+stat.id.value,scopeId,0) + else await this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue-value) } return true } - resetStat(id:ODValidId, scopeId:string): ODValidStatValue|null { + async resetStat(id:ODValidId, scopeId:string): Promise { if (!this.database) return null const stat = this.get(id) if (!stat) return null - if (stat.value != null) this.database.set(this.id.value+"_"+stat.id.value,scopeId,stat.value) + if (stat.value != null) await this.database.set(this.id.value+"_"+stat.id.value,scopeId,stat.value) return stat.value } init(): string[] { @@ -149,7 +149,7 @@ export class ODStatScope extends ODManager { result.push(await stat.render("",scopeId,guild,channel,user)) }else{ //normal render (with value) - const value = this.getStat(stat.id,scopeId) + const value = await this.getStat(stat.id,scopeId) if (value != null) result.push(await stat.render(value,scopeId,guild,channel,user)) } @@ -163,13 +163,13 @@ export class ODStatScope extends ODManager { } export class ODStatGlobalScope extends ODStatScope { - getStat(id:ODValidId): ODValidStatValue|null { + getStat(id:ODValidId): Promise { return super.getStat(id,"GLOBAL") } - setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): boolean { + setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise { return super.setStat(id,"GLOBAL",value,mode) } - resetStat(id:ODValidId): ODValidStatValue|null { + resetStat(id:ODValidId): Promise { return super.resetStat(id,"GLOBAL") } render(scopeId:"GLOBAL", guild:discord.Guild, channel:discord.TextBasedChannel, user: discord.User): Promise { diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index aee5ce3..b5e2d29 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -394,7 +394,7 @@ const loadAutoCode = () => { await openticket.actions.get("openticket:close-ticket").run("autoclose",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) await channel.send((await openticket.builders.messages.getSafe("openticket:autoclose-message").build("timeout",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) count++ - openticket.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") } } } @@ -420,7 +420,7 @@ const loadAutoCode = () => { //autoclose ticket await openticket.actions.get("openticket:close-ticket").run("autoclose",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) await channel.send((await openticket.builders.messages.getSafe("openticket:autoclose-message").build("leave",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) - openticket.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") } } } @@ -447,7 +447,7 @@ const loadAutoCode = () => { await channel.send((await openticket.builders.messages.getSafe("openticket:autodelete-message").build("timeout",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) await openticket.actions.get("openticket:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) count++ - openticket.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") } } } @@ -473,7 +473,7 @@ const loadAutoCode = () => { //autodelete ticket await channel.send((await openticket.builders.messages.getSafe("openticket:autodelete-message").build("leave",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) await openticket.actions.get("openticket:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) - openticket.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") + await openticket.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") } } } From 91ea12a6cc278a7ddc91cdf52cd6c10228e7fc14 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Fri, 6 Dec 2024 15:44:58 +0100 Subject: [PATCH 063/157] Added Arabic translation --- README.md | 4 +- index.js | 3 +- languages/arabic.json | 478 +++++++++++++++++++++++++++ languages/turkish.json | 2 +- src/core/api/defaults/language.ts | 1 + src/data/framework/languageLoader.ts | 1 + 6 files changed, 485 insertions(+), 4 deletions(-) create mode 100644 languages/arabic.json diff --git a/README.md b/README.md index b2dab52..e29738f 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@

Open Ticket is 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! -You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 18 Languages! If you need any help, feel free to join our discord server! +You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 19 Languages! If you need any help, feel free to join our discord server!

⭐️ Help us grow by giving a star! ⭐️

@@ -131,9 +131,9 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇹🇭 Thai |modshd |🟢 Up To Date | |🇹🇷 Turkish |palestinian |🟢 Up To Date | |🇫🇷 French |guillee.3 |🟢 Up To Date | +|🇦🇪 Arabic |palestinian |🟢 Up To Date | |🇪🇪 Estonian |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇮 Finnish |iamnotmega |🔵 Up To Date (ChatGPT) | -|🇦🇪 Arabic |deqressing |🟠 Temporary Outdated (beta) | |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | |🇵🇱 Polish |mkevas |🟠 Temporary Outdated (beta) | |🇳🇴 Norwegian |noonenook |🟠 Temporary Outdated (beta) | diff --git a/index.js b/index.js index 5c6053b..13d1eda 100644 --- a/index.js +++ b/index.js @@ -4,7 +4,8 @@ const nodepath = require('path') /////////////// STARTUP FLAGS /////////////// const flags = [ - //add startup flags here (e.g. "--no-compile") + //PTERODACTYL PANEL + //add startup flags here (e.g. "--no-compile") when running via the panel ] process.argv.push(...flags) /////////////// STARTUP FLAGS /////////////// diff --git a/languages/arabic.json b/languages/arabic.json new file mode 100644 index 0000000..4402491 --- /dev/null +++ b/languages/arabic.json @@ -0,0 +1,478 @@ +{ + "_TRANSLATION": { + "otversion": "v4.0.0", + "translators": ["palestinian"], + "lastedited": "06/12/2024", + "language": "Arabic", + "automated": false + }, + "checker": { + "system": { + "typeError": "[خطأ]", + "headerOpenTicket": "فتح تذكرة", + "typeWarning": "[تحذير]", + "typeInfo": "[معلومات]", + "headerConfigChecker": "مدقق التكوين", + "headerDescription": "تحقق من الأخطاء في ملفات التكوين الخاصة بك!", + "footerError": "لن يبدأ البوت حتى يتم إصلاح جميع {0}!", + "footerWarning": "من المستحسن إصلاح جميع {0} قبل البدء!", + "footerSupport": "الدعم: {0} - الوثائق: {1}", + "compactInformation": "استخدم {0} لمزيد من المعلومات!", + "dataPath": "المسار", + "dataDocs": "الوثائق", + "dataMessages": "الرسالة" + }, + "messages": { + "stringTooShort": "لا يمكن أن تكون هذه السلسلة أقصر من {0} حرفًا!", + "stringTooLong": "لا يمكن أن تكون هذه السلسلة أطول من {0} حرفًا!", + "stringLengthInvalid": "يجب أن تكون هذه السلسلة بطول {0} حرفًا!", + "stringStartsWith": "يجب أن تبدأ هذه السلسلة بـ {0}!", + "stringEndsWith": "يجب أن تنتهي هذه السلسلة بـ {0}!", + "stringContains": "يجب أن تحتوي هذه السلسلة على {0}!", + "stringChoices": "يمكن أن تكون هذه السلسلة واحدة فقط من القيم التالية: {0}!", + "stringRegex": "هذه السلسلة غير صالحة!", + + "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": "لا يمكن أن تكون هذه القيمة صحيحة!", + "booleanFalse": "لا يمكن أن تكون هذه القيمة خاطئة!", + + "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": "هذا الرابط غير صالح!", + "urlInvalidHttp": "يمكن أن يستخدم هذا الرابط بروتوكول https:// فقط!", + "urlInvalidProtocol": "يمكن أن يستخدم هذا الرابط بروتوكولات http:// و https:// فقط!", + "urlInvalidHostname": "هذا الرابط يحتوي على اسم مضيف غير مسموح به!", + "urlInvalidExtension": "هذا الرابط يحتوي على امتداد غير صالح! اختر بين: {0}!", + "urlInvalidPath": "هذا الرابط يحتوي على مسار غير صالح!", + "idNotUnique": "هذا المعرف ليس فريدًا، استخدم معرفًا آخر بدلاً من ذلك!", + "idNonExistent": "المعرف {0} غير موجود!", + + "invalidType": "تحتاج هذه الخاصية إلى أن تكون من النوع: {0}!", + "propertyMissing": "الخاصية {0} مفقودة من هذا الكائن!", + "propertyOptional": "الخاصية {0} اختيارية في هذا الكائن!", + "objectDisabled": "هذا الكائن معطل، قم بتمكينه باستخدام {0}!", + "nullInvalid": "لا يمكن أن تكون هذه الخاصية فارغة!", + "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": "`` => معلمة مطلوبة\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": "تم إعادة تسمية هذه التذكرة إلى {0} بواسطة {1}!", + "renameDm": "تمت إعادة تسمية تذكرتك إلى {0} في خادمنا!", + "moveLog": "تم نقل هذه التذكرة إلى {0} بواسطة {1}!", + "moveDm": "تم نقل تذكرتك إلى {0} في خادمنا!", + "addLog": "{0} تم إضافته إلى هذه التذكرة بواسطة {1}!", + "addDm": "{0} تم إضافته إلى تذكرتك في خادمنا!", + "removeLog": "{0} تم إزالته من هذه التذكرة بواسطة {1}!", + "removeDm": "{0} تم إزالته من تذكرتك في خادمنا!", + + "blacklistAddLog": "{0} تم حظره بواسطة {1}!", + "blacklistRemoveLog": "{0} تم إزالته من القائمة السوداء بواسطة {1}!", + "blacklistAddDm": "لقد تم حظرك في خادمنا!\nمن الآن فصاعدًا، لا يمكنك إنشاء تذكرة!", + "blacklistRemoveDm": "تمت إزالتك من القائمة السوداء في خادمنا!\nالآن يمكنك إنشاء تذاكر مرة أخرى!", + "clearLog": "{0} تذاكر تم حذفها بواسطة {1}!" + } + }, + "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": "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 ": "عرض إحصائيات مستخدم في الخادم.", + "statsUser User": "المستخدم الذي تريد عرض إحصائياته.", + "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": "النصوص التي تم إنشاؤها" + } + } +} \ No newline at end of file diff --git a/languages/turkish.json b/languages/turkish.json index 9eed6e8..d77a434 100644 --- a/languages/turkish.json +++ b/languages/turkish.json @@ -2,7 +2,7 @@ "_TRANSLATION": { "otversion": "v4.0.0", "translators": ["palestinian"], - "lastedited": "26/08/2024", + "lastedited": "26/11/2024", "language": "Turkish", "automated": false }, diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index 0f98a18..fc62c7e 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -463,6 +463,7 @@ export interface ODLanguageManagerIds_Default { "openticket:thai":ODLanguage, "openticket:turkish":ODLanguage, "openticket:french":ODLanguage, + "openticket:arabic":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 6e4f2bc..ccb3983 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -21,6 +21,7 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODJsonLanguage("openticket:thai","thai.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:turkish","turkish.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:french","french.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:arabic","arabic.json")) /** How to add more languages? * - Register the language to the manager (see above) From 1e2321313ff14788f9ce2fbf62ee68c3e8598c3d Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Fri, 6 Dec 2024 15:59:08 +0100 Subject: [PATCH 064/157] Implemented "removeParticipantsOnClose" Implemented the option "removeParticipantsOnClose" in the config/general.json. It wasn't implemented in the code by accident. --- src/actions/closeTicket.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/actions/closeTicket.ts b/src/actions/closeTicket.ts index d8374d3..b414851 100644 --- a/src/actions/closeTicket.ts +++ b/src/actions/closeTicket.ts @@ -83,9 +83,15 @@ export const registerActions = async () => { }) }) ticket.get("openticket:participants").value.forEach((participant) => { - //all participants that aren't roles/admins => readonly + //all participants that aren't roles/admins => readonly (OR non-viewable when enabled) if (participant.type == "user"){ - permissions.push({ + if (generalConfig.data.system.removeParticipantsOnClose) permissions.push({ + type:discord.OverwriteType.Member, + id:participant.id, + allow:[], + deny:["SendMessages","AddReactions","AttachFiles","SendPolls","ViewChannel","ReadMessageHistory"] + }) + else permissions.push({ type:discord.OverwriteType.Member, id:participant.id, allow:["ViewChannel","ReadMessageHistory"], From a037d76060d54904365605796685d2d8ba7dcc01 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 7 Dec 2024 00:34:49 +0100 Subject: [PATCH 065/157] Fixed database ghosted unused-options bug Fixed a problem where unused ticket options would stay in the options database in certain circumstances. Even when there is no ticket that uses the option anymore. --- database/global.json | 8 +------- src/data/framework/codeLoader.ts | 14 +++++++++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/database/global.json b/database/global.json index fb44b71..0637a08 100644 --- a/database/global.json +++ b/database/global.json @@ -1,7 +1 @@ -[ - {"category":"openticket:last-version","key":"openticket:version","value":"v4.0.0"}, - {"category":"openticket:last-version","key":"openticket:api","value":"v1.0.0"}, - {"category":"openticket:last-version","key":"openticket:transcripts","value":"v2.0.0"}, - {"category":"openticket:last-version","key":"openticket:livestatus","value":"v2.0.0"}, - {"category":"openticket:last-version","key":"openticket:last-version","value":"v4.0.0"} -] \ No newline at end of file +[] \ No newline at end of file diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index b5e2d29..43f54f2 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -133,13 +133,17 @@ export const loadDatabaseCleanersCode = async () => { })) //OPTION DATABASE CLEANER - openticket.code.add(new api.ODCode("openticket:option-database-cleaner",10,() => { + openticket.code.add(new api.ODCode("openticket:option-database-cleaner",10,async () => { //delete all unused options (async) - openticket.options.getAll().forEach(async (option) => { - if (await optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ - await optionDatabase.delete("openticket:used-option",option.id.value) + for (const option of (await optionDatabase.getCategory("openticket:used-option") ?? [])){ + if (!openticket.options.exists(option.key)){ + //remove because option isn't loaded into memory (0 tickets require it) + await optionDatabase.delete("openticket:used-option",option.key) + }else if (!openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.key)){ + //remove when loaded into memory (0 tickets require it) + await optionDatabase.delete("openticket:used-option",option.key) } - }) + } })) //USER DATABASE CLEANER (full async/parallel because it takes a lot of time) From 0c2b688862c44e54ef083adb3d92068f26587cc4 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 7 Dec 2024 13:27:24 +0100 Subject: [PATCH 066/157] Fixed English translation typo's --- languages/custom.json | 2 +- languages/english.json | 2 +- src/core/api/defaults/checker.ts | 2 +- src/core/startup/manageMigration.ts | 4 +++- src/data/framework/checkerLoader.ts | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/languages/custom.json b/languages/custom.json index 0069238..67aef9d 100644 --- a/languages/custom.json +++ b/languages/custom.json @@ -13,7 +13,7 @@ "typeWarning":"[WARNING]", "typeInfo":"[INFO]", "headerConfigChecker":"CONFIG CHECKER", - "headerDescription":"check for errors in you config files!", + "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}", diff --git a/languages/english.json b/languages/english.json index ceb0f92..b9f69d2 100644 --- a/languages/english.json +++ b/languages/english.json @@ -13,7 +13,7 @@ "typeWarning":"[WARNING]", "typeInfo":"[INFO]", "headerConfigChecker":"CONFIG CHECKER", - "headerDescription":"check for errors in you config files!", + "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}", diff --git a/src/core/api/defaults/checker.ts b/src/core/api/defaults/checker.ts index 1044e12..650cd80 100644 --- a/src/core/api/defaults/checker.ts +++ b/src/core/api/defaults/checker.ts @@ -77,7 +77,7 @@ export class ODCheckerRenderer_Default extends ODCheckerRenderer { const t = { headerOpenticket:tm.get("other","openticket:header-openticket") ?? "OPEN TICKET", headerConfigchecker:tm.get("other","openticket:header-configchecker") ?? "CONFIG CHECKER", - headerDescription:tm.get("other","openticket:header-description") ?? "check for errors in you config files!", + headerDescription:tm.get("other","openticket:header-description") ?? "check for errors in your config files!", footerError:tm.get("other","openticket:footer-error") ?? "the bot won't start until all {0}'s are fixed!", footerWarning:tm.get("other","openticket:footer-warning") ?? "it's recommended to fix all {0}'s before starting!", footerSupport:tm.get("other","openticket:footer-support") ?? "SUPPORT: {0} - DOCS: {1}", diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index 9aa5def..515efb7 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -34,9 +34,11 @@ export const loadVersionMigrationSystem = async () => { const preloadMigrationContext = async () => { openticket.debug.debug("-- MIGRATION CONTEXT START --") await (await import("../../data/framework/flagLoader.js")).loadAllFlags() - openticket.flags.init() + await openticket.flags.init() await (await import("../../data/framework/configLoader.js")).loadAllConfigs() + await openticket.configs.init() await (await import("../../data/framework/databaseLoader.js")).loadAllDatabases() + await openticket.databases.init() openticket.debug.visible = true } diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts index 5097f27..e8d4e08 100644 --- a/src/data/framework/checkerLoader.ts +++ b/src/data/framework/checkerLoader.ts @@ -32,7 +32,7 @@ export const registerDefaultCheckerSystemTranslations = (tm:api.ODCheckerTransla tm.quickTranslate(lm,"checker.system.typeWarning","other","openticket:type-warning") // [WARNING] (ignore) tm.quickTranslate(lm,"checker.system.typeInfo","other","openticket:type-info") // [INFO] (ignore) tm.quickTranslate(lm,"checker.system.headerConfigChecker","other","openticket:header-configchecker") // CONFIG CHECKER - tm.quickTranslate(lm,"checker.system.headerDescription","other","openticket:header-description") // check for errors in you config files! + tm.quickTranslate(lm,"checker.system.headerDescription","other","openticket:header-description") // check for errors in your config files! tm.quickTranslate(lm,"checker.system.footerError","other","openticket:footer-error") // the bot won't start until all {0}'s are fixed! tm.quickTranslate(lm,"checker.system.footerWarning","other","openticket:footer-warning") // it's recommended to fix all {0}'s before starting! tm.quickTranslate(lm,"checker.system.footerSupport","other","openticket:footer-support") // SUPPORT: {0} - DOCS: {1} From 106cb0f718cd104c31687643dbe71a53788e1687 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 7 Dec 2024 21:46:49 +0100 Subject: [PATCH 067/157] Fixed dropdown not supporting empty emojis Fixed a bug that caused the bot to crash when spawning a dropdown panel which includes an option without emoji. --- plugins/example-plugin/index.ts | 1 - src/builders/dropdowns.ts | 7 ++++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/example-plugin/index.ts b/plugins/example-plugin/index.ts index 1a9396a..ec70562 100644 --- a/plugins/example-plugin/index.ts +++ b/plugins/example-plugin/index.ts @@ -7,7 +7,6 @@ import * as discord from "discord.js" ///////////////////////////////////////////// if (utilities.project != "openticket") throw new api.ODPluginError("This plugin only works in Open Ticket!") -if (!utilities.isBeta) throw new api.ODPluginError("This plugin is made for the beta version of Open Ticket!") //Add Typescript autocomplete support for plugin data. (!!!OPTIONAL!!!) declare module "../../src/core/api/api.js" { diff --git a/src/builders/dropdowns.ts b/src/builders/dropdowns.ts index 5a35404..15f70fa 100644 --- a/src/builders/dropdowns.ts +++ b/src/builders/dropdowns.ts @@ -17,14 +17,15 @@ const panelDropdowns = () => { new api.ODWorker("openticket:panel-dropdown-tickets",0,async (instance,params) => { const {panel,options} = params - const parsedOptions: api.ODDropdownData["options"] = options.map((option) => { const desc = option.get("openticket:description").value.substring(0,100) + const emoji = option.get("openticket:button-emoji").value return { label:option.get("openticket:button-label").value.substring(0,100), value:"od:ticket-option_"+panel.id.value+"_"+option.id.value, - emoji:option.get("openticket:button-emoji").value, - description:(desc.length > 0) ? desc : undefined + emoji:(emoji.length > 0) ? emoji : undefined, + description:(desc.length > 0) ? desc : undefined, + default:false } }) From b7f5c7191d574ef34051b7afd4d8214117dee472 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 8 Dec 2024 18:28:22 +0100 Subject: [PATCH 068/157] Fixed responder TS typo --- src/core/api/modules/responder.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/api/modules/responder.ts b/src/core/api/modules/responder.ts index 2b7338f..bc6b223 100644 --- a/src/core/api/modules/responder.ts +++ b/src/core/api/modules/responder.ts @@ -217,8 +217,8 @@ export class ODCommandResponderInstanceOptions { }else return null } - getMentionable(name:string,required:true): discord.User|discord.Role - getMentionable(name:string,required:false): discord.User|discord.Role|null + getMentionable(name:string,required:true): discord.User|discord.GuildMember|discord.Role + getMentionable(name:string,required:false): discord.User|discord.GuildMember|discord.Role|null getMentionable(name:string,required:boolean){ if (this.#interaction instanceof discord.ChatInputCommandInteraction){ try { @@ -229,7 +229,7 @@ export class ODCommandResponderInstanceOptions { }else if (this.#interaction instanceof discord.Message){ const opt = this.#options.find((opt) => opt.type == "mentionable" && opt.name == name) - if (opt && (opt.value instanceof discord.User || opt.value instanceof discord.Role)) return opt.value + if (opt && (opt.value instanceof discord.User || opt.value instanceof discord.GuildMember || opt.value instanceof discord.Role)) return opt.value else return null }else return null From 4e7d45ea0799edadcc542666e0a2945854bed562 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 8 Dec 2024 18:28:49 +0100 Subject: [PATCH 069/157] Increased button label length to 80 characters --- src/core/api/modules/checker.ts | 2 +- src/data/framework/checkerLoader.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 9917134..77bdc6f 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -398,7 +398,7 @@ export interface ODCheckerMessage { * This interface has the basic options for the `ODCheckerStructure`! */ export interface ODCheckerStructureOptions { - /**Add a custom checker function */ + /**Add a custom checker function. Returns `true` when valid. */ custom?:(checker:ODChecker, value:ODValidJsonType, locationTrace:ODCheckerLocationTrace, locationId:ODId, locationDocs:string|null) => boolean, /**Set the url to the documentation of this variable. */ docs?:string diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts index e8d4e08..8d7f271 100644 --- a/src/data/framework/checkerLoader.ts +++ b/src/data/framework/checkerLoader.ts @@ -301,7 +301,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opentick //TICKET BUTTON {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-button",{children:[ {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("openticket:ticket-button-emoji",0,1,true)}, - {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:50})}, + {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:80})}, {key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-color",{choices:["gray","red","green","blue"]})}, ],custom:(checker,value,locationTrace,locationId,locationDocs) => { const lt = checker.locationTraceDeref(locationTrace) @@ -385,7 +385,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opentick //WEBSITE BUTTON {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-button",{children:[ {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("openticket:ticket-button-emoji",0,1,true)}, - {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:50})}, + {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:80})}, ],custom:(checker,value,locationTrace,locationId,locationDocs) => { const lt = checker.locationTraceDeref(locationTrace) //check if emoji & label exists @@ -410,7 +410,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opentick //ROLE BUTTON {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-button",{children:[ {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("openticket:ticket-button-emoji",0,1,true)}, - {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:50})}, + {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:80})}, {key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-color",{choices:["gray","red","green","blue"]})}, ],custom:(checker,value,locationTrace,locationId,locationDocs) => { const lt = checker.locationTraceDeref(locationTrace) From 8a6a8e527f4869ddd33aa0980a6692452ddf7487 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 8 Dec 2024 18:29:00 +0100 Subject: [PATCH 070/157] Added 6 new plugins to README.md --- README.md | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index e29738f..4aaa581 100644 --- a/README.md +++ b/README.md @@ -57,27 +57,41 @@ You're also able to customise every little aspect of the bot! From embeds to tra Example Panel 2 ## 🧩 Plugins -View all available Open Ticket plugins in our [Official Plugin Repository](https://github.com/DJj123dj/open-discord-plugins)! +**Download all plugins in our [Official Plugin Repository](https://github.com/DJj123dj/open-discord-plugins)!** ### 📦 Official *(made by DJdj Development)* -|Name |Category |Description | -|---------------------------------------------------------------------|----------------------------|-------------------------| -|[`example-plugin`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-plugin/) |Example |This is just an example plugin for people that want to create their own plugin. | -|[`example-command`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-command/) |Example |Sample custom command using the Open Discord system. | -|[`ot-jump-to-top`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-jump-to-top/) |Command |Add a simple command to jump to the top of the ticket. | -|[`ot-kill-switch`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-kill-switch/) |Command |Temporarily disable the ticket system using a kill switch. | -|[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |Channel Management |Simple plugin to keep the channel prefix when using the /rename command. | -|[`ot-no-slash-clear`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-no-slash-clear/) |Development |Disable the automatic removal of slash commands that aren't used by Open Ticket. | -|[`ot-better-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-better-status/) |Client Activity |An advanced status plugin to rotate between states. It also allows for the use of variables. | -|[`ot-sqlite-database`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-sqlite-database/) |Database |With this plugin, the database will be an SQLite file. It's a must-have for large servers! | -|[`ot-ticket-message-extras`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ticket-message-extras/) |Customisation |A plugin which adds a few little features to the ticket message. | - +|Name |Category |Description | +|----------------------------------------------------------------------|----------------------------|-------------------------| +|[`example-plugin`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-plugin/) |📄 Example |This is just an example plugin for people that want to create their own plugin. | +|[`example-command`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-command/) |📄 Example |Sample custom command using the Open Discord system. | +|[`ot-jump-to-top`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-jump-to-top/) |📢 Command |Add a simple command to jump to the top of the ticket. | +|[`ot-kill-switch`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-kill-switch/) |📢 Command |Temporarily disable the ticket system using a kill switch. | +|[`ot-hosting-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-hosting-status/) |📢 Command |A simple command to send hosting status updates to a channel. | +|[`ot-sqlite-database`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-sqlite-database/) |⚙️ Utility |With this plugin, the database will be an SQLite file. It's a must-have for large servers! | +|[`ot-no-slash-clear`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-no-slash-clear/) |⚙️ Utility |Disable the automatic removal of slash commands that aren't used by Open Ticket. | +|[`ot-migrate-v3`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-migrate-v3/) |⚙️ Utility |Use this plugin to migrate all tickets from Open Ticket v3 to v4. | +|[`ot-ticket-message-extras`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ticket-message-extras/) |🎨 Customisation |A plugin which adds a few little features to the ticket message. | +|[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |🎨 Customisation |Simple plugin to keep the channel prefix when using the /rename command. | +|[`ot-customise-buttons`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-customise-buttons/) |🎨 Customisation |Customise almost all built-in buttons. This includes the claim, reopen, close & delete buttons. | +|[`ot-alt-detector`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-alt-detector/) |💼 Management |Use the discord-alt-detector npm package by DJdj Development in your ticket bot. | +|[`ot-alt-detector`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-alt-detector/) |💼 Management |Use the discord-alt-detector npm package by DJdj Development in your ticket bot. | +|[`ot-embeds`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-embeds/) |💼 Management |Create custom premade embeds in the config or use the command to create one from scratch. | +|[`ot-better-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-better-status/) |🤖 Client |An advanced status plugin to rotate between states. It also allows for the use of variables. | ### ✅ Verified *(made by community)* |Name |Author |Category |Description | |---------------------------------------------------------------------|----------------------------|----------------------------|-------------------------| -|[`ot-config-reload`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-config-reload/) |guillee.3 |Config |This plugin adds a new command that allows reloading the Open Ticket config files without the need for a restart. | -|[`ot-feedback`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-feedback/) |an_developer |Feedback System |A plugin to gather feedback of your support service. | +|[`ot-config-reload`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-config-reload/) |guillee.3 |⚙️ Utility |This plugin adds a new command that allows reloading the Open Ticket config files without the need for a restart. | +|[`ot-feedback`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-feedback/) |an_developer |💼 Management |A plugin to gather feedback of your support service. | +|[`ot-assign-role`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-assign-role/) |rapid.fast |💼 Management |This plugin assigns a predefined role to a user upon creating a ticket. | + +### 📢 Categories +- **📄 Example** - These plugins serve as an example or starting template. +- **📢 Command** - These plugins add new commands to the bot. +- **⚙️ Utility** - These plugins help with backend & systems. You won't notice it in discord itself. +- **🎨 Customisation** - These plugins help you customise the bot even further. +- **💼 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 From c6e836455cd03649f1e3f9d08a51ec1506258f3b Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:46:10 +0100 Subject: [PATCH 071/157] Updated README.md Contributors --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4aaa581..04dcd21 100644 --- a/README.md +++ b/README.md @@ -95,15 +95,17 @@ You're also able to customise every little aspect of the bot! From embeds to tra ## 🛠️ Contributors ### 🖥️ Team -The team behind Open Ticket! +This is the main team working on Open Ticket. Don't forget to check their profiles! + - - + + +
Profile Picture Profile PictureProfile Picture
DJj123djSanke💻 DJj123dj💬 Sanke💬 DevBack
From f0183c319a0206dd5147f06f49dd210462e2ca0d Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:46:40 +0100 Subject: [PATCH 072/157] Added Hindi Translation (by an_developer) --- README.md | 3 +- languages/hindi.json | 478 +++++++++++++++++++++++++++ src/core/api/defaults/language.ts | 1 + src/data/framework/languageLoader.ts | 1 + 4 files changed, 482 insertions(+), 1 deletion(-) create mode 100644 languages/hindi.json diff --git a/README.md b/README.md index 04dcd21..5a2c675 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@

Open Ticket is 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! -You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 19 Languages! If you need any help, feel free to join our discord server! +You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 20 Languages! If you need any help, feel free to join our discord server!

⭐️ Help us grow by giving a star! ⭐️

@@ -148,6 +148,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |🇹🇷 Turkish |palestinian |🟢 Up To Date | |🇫🇷 French |guillee.3 |🟢 Up To Date | |🇦🇪 Arabic |palestinian |🟢 Up To Date | +|🇮🇳 Hindi |an_developer |🟢 Up To Date | |🇪🇪 Estonian |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇮 Finnish |iamnotmega |🔵 Up To Date (ChatGPT) | |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | diff --git a/languages/hindi.json b/languages/hindi.json new file mode 100644 index 0000000..a66c8fc --- /dev/null +++ b/languages/hindi.json @@ -0,0 +1,478 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translators":["an_developer"], + "lastedited":"14/12/2024", + "language":"Hindi", + "automated":false + }, + "checker":{ + "system":{ + "typeError":"[गलती]", + "headerOpenTicket":"खुला टिकट", + "typeWarning":"[चेतावनी]", + "typeInfo":"[जानकारी]", + "headerConfigChecker":"कॉन्फिग चेकर", + "headerDescription":"अपनी कॉन्फ़िग फ़ाइलों में त्रुटियों की जाँच करें!", + "footerError":"जब तक सभी {0} ठीक नहीं हो जाते, बॉट प्रारंभ नहीं होगा!", + "footerWarning":"प्रारंभ करने से पहले सभी {0} को ठीक करने की अनुशंसा की जाती है!", + "footerSupport":"समर्थन: {0} - दस्तावेज़: {1}", + "compactInformation":"अधिक जानकारी के लिए {0} का उपयोग करें!", + "dataPath":"पथ", + "dataDocs":"डॉक्स", + "dataMessages":"संदेश" + }, + "messages":{ + "stringTooShort":"यह स्ट्रिंग {0} वर्णों से छोटी नहीं हो सकती!", + "stringTooLong":"यह स्ट्रिंग {0} वर्णों से अधिक लंबी नहीं हो सकती!", + "stringLengthInvalid":"यह स्ट्रिंग {0} अक्षर लंबी होनी चाहिए!", + "stringStartsWith":"यह स्ट्रिंग {0} से शुरू होनी चाहिए!", + "stringEndsWith":"इस स्ट्रिंग को {0} पर समाप्त होना चाहिए!", + "stringContains":"इस स्ट्रिंग में {0} होना आवश्यक है!", + "stringChoices":"यह स्ट्रिंग केवल निम्नलिखित मानों में से एक हो सकती है: {0}!", + "stringRegex":"यह स्ट्रिंग अमान्य है!", + + "numberTooShort":"यह संख्या {0} वर्णों से छोटी नहीं हो सकती!", + "numberTooLong":"यह संख्या {0} वर्णों से अधिक लंबी नहीं हो सकती!", + "numberLengthInvalid":"यह संख्या {0} वर्ण लंबी होनी चाहिए!", + "numberTooSmall":"यह संख्या कम से कम {0} होनी चाहिए!", + "numberTooLarge":"यह संख्या अधिकतम {0} होनी चाहिए!", + "numberNotEqual":"यह संख्या {0} होनी चाहिए!", + "numberStep":"यह संख्या {0} का गुणज होनी चाहिए!", + "numberStepOffset":"यह संख्या {1} से शुरू होकर {0} का गुणज होनी चाहिए!", + "numberStartsWith":"यह संख्या {0} से शुरू होनी चाहिए!", + "numberEndsWith":"यह संख्या {0} पर समाप्त होनी चाहिए!", + "numberContains":"इस संख्या में {0} होना आवश्यक है!", + "numberChoices":"यह संख्या केवल निम्नलिखित मानों में से एक हो सकती है: {0}!", + "numberFloat":"यह संख्या दशमलव नहीं हो सकती!", + "numberNegative":"यह संख्या ऋणात्मक नहीं हो सकती!", + "numberPositive":"यह संख्या सकारात्मक नहीं हो सकती!", + "numberZero":"यह संख्या शून्य नहीं हो सकती!", + + "booleanTrue":"यह बूलियन सत्य नहीं हो सकता!", + "booleanFalse":"यह बूलियन झूठा नहीं हो सकता!", + + "arrayEmptyDisabled":"इस सरणी को खाली रहने की अनुमति नहीं है!", + "arrayEmptyRequired":"यह सरणी खाली होनी आवश्यक है!", + "arrayTooShort":"इस सरणी की लंबाई कम से कम {0} होनी चाहिए!", + "arrayTooLong":"इस सरणी की लंबाई अधिकतम {0} होनी चाहिए!", + "arrayLengthInvalid":"इस सरणी की लंबाई {0} होनी चाहिए!", + "arrayInvalidTypes":"इस सरणी में केवल निम्नलिखित प्रकार हो सकते हैं: {0}!", + "arrayDouble":"यह सरणी एक ही मान को दो बार अनुमति नहीं देती है!", + + "discordInvalidId":"यह एक अमान्य कलह {0} आईडी है!", + "discordInvalidIdOptions":"यह एक अमान्य कलह {0} आईडी है! ", + "discordInvalidToken":"यह एक अमान्य कलह टोकन है (वाक्यविन्यास की दृष्टि से)!", + "colorInvalid":"यह अमान्य हेक्स रंग है!", + "emojiTooShort":"इस स्ट्रिंग में कम से कम {0} इमोजी होना आवश्यक है!", + "emojiTooLong":"इस स्ट्रिंग में अधिकतम {0} इमोजी होना आवश्यक है!", + "emojiCustom":"यह इमोजी कस्टम डिसॉर्डर इमोजी नहीं हो सकता!", + "emojiInvalid":"यह एक अमान्य इमोजी है!", + "urlInvalid":"यह यूआरएल अमान्य है!", + "urlInvalidHttp":"यह यूआरएल केवल https:// प्रोटोकॉल का उपयोग कर सकता है!", + "urlInvalidProtocol":"यह यूआरएल केवल http:// और https:// प्रोटोकॉल का उपयोग कर सकता है!", + "urlInvalidHostname":"इस यूआरएल में एक अस्वीकृत होस्टनाम है!", + "urlInvalidExtension":"इस यूआरएल में एक अमान्य एक्सटेंशन है! ", + "urlInvalidPath":"इस यूआरएल में एक अमान्य पथ है!", + "idNotUnique":"यह आईडी अद्वितीय नहीं है, इसके बजाय किसी अन्य आईडी का उपयोग करें!", + "idNonExistent":"आईडी {0} मौजूद नहीं है!", + + "invalidType":"यह संपत्ति इस प्रकार की होनी चाहिए: {0}!", + "propertyMissing":"इस ऑब्जेक्ट में संपत्ति {0} गायब है!", + "propertyOptional":"इस ऑब्जेक्ट में संपत्ति {0} वैकल्पिक है!", + "objectDisabled":"यह ऑब्जेक्ट अक्षम है, इसे {0} का उपयोग करके सक्षम करें!", + "nullInvalid":"यह संपत्ति शून्य नहीं हो सकती!", + "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":"`` => आवश्यक पैरामीटर\n", + "statsReset":"बॉट आँकड़े सफलतापूर्वक रीसेट कर दिए गए हैं!", + "statsError":"टिकट आँकड़े देखने में असमर्थ!\n", + "blacklistAdd":"{0} को सफलतापूर्वक काली सूची में डाल दिया गया है!", + "blacklistRemove":"{0} सफलतापूर्वक जारी कर दिया गया है!", + "blacklistGetSuccess":"{0} वर्तमान में ब्लैकलिस्टेड है!", + "blacklistGetEmpty":"{0} वर्तमान में काली सूची में नहीं डाला गया है!", + "blacklistViewEmpty":"अभी तक किसी को भी काली सूची में नहीं डाला गया है!", + "blacklistViewTip":"किसी उपयोगकर्ता को ब्लैकलिस्ट करने के लिए \"/ब्लैकलिस्ट ऐड\" का उपयोग करें!", + "clearVerify":"क्या आप वाकई एकाधिक टिकट हटाना चाहते हैं?\n", + "clearReady":"{0} टिकट सफलतापूर्वक हटा दिए गए हैं!", + "rolesEmpty":"कोई भूमिका अद्यतन नहीं की गई है!", + + "autocloseLeave":"यह टिकट स्वतः बंद हो गया है क्योंकि निर्माता ने सर्वर छोड़ दिया है!", + "autocloseTimeout":"यह टिकट स्वतः बंद कर दिया गया है क्योंकि यह `{0}h` से अधिक समय से निष्क्रिय है!", + "autodeleteLeave":"यह टिकट स्वतः हटा दिया गया है क्योंकि निर्माता ने सर्वर छोड़ दिया है!", + "autodeleteTimeout":"यह टिकट स्वतः हटा दिया गया है क्योंकि यह `{0} दिनों` से अधिक समय से निष्क्रिय है!", + "autocloseEnabled":"इस टिकट में ऑटोक्लोज़ सक्षम कर दिया गया है!\n", + "autocloseDisabled":"इस टिकट में ऑटोक्लोज़ अक्षम कर दिया गया है!\n", + "autodeleteEnabled":"इस टिकट में ऑटोडिलीट सक्षम कर दिया गया है!\n", + "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":"इस टिकट में {1} द्वारा {0} जोड़ा गया है!", + "addDm":"हमारे सर्वर में आपके टिकट में {0} जोड़ दिया गया है!", + "removeLog":"{1} द्वारा इस टिकट से {0} हटा दिया गया है!", + "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" + } + }, + "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":"वर्तमान चैनल वैध टिकट नहीं है! ", + "notInGuild":"यह {0} डीएम में काम नहीं करता! ", + "channelRename":"विवाद की दर सीमा के कारण, वर्तमान में बॉट के लिए चैनल का नाम बदलना असंभव है। ", + "channelRenameSource":"इस त्रुटि का स्रोत है: {0}", + "busy":"इस {0} का उपयोग करने में असमर्थ!\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":"आपके पास `प्रशासक` की अनुमति होनी चाहिए।" + }, + "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":"प्रतिलिपियाँ बनाई गईं" + } + } +} \ No newline at end of file diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index fc62c7e..5326e50 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -464,6 +464,7 @@ export interface ODLanguageManagerIds_Default { "openticket:turkish":ODLanguage, "openticket:french":ODLanguage, "openticket:arabic":ODLanguage, + "openticket:hindi":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index ccb3983..c987623 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -22,6 +22,7 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODJsonLanguage("openticket:turkish","turkish.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:french","french.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:arabic","arabic.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:hindi","hindi.json")) /** How to add more languages? * - Register the language to the manager (see above) From bf13e15d56542d29c97dbe676e126995a597fd30 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 15 Dec 2024 19:47:20 +0100 Subject: [PATCH 073/157] Disabled autoclose & delete by default --- config/options.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/options.json b/config/options.json index 6dc8604..e9d4ca4 100644 --- a/config/options.json +++ b/config/options.json @@ -70,13 +70,13 @@ "autoclose":{ "enableInactiveHours":false, "inactiveHours":24, - "enableUserLeave":true, + "enableUserLeave":false, "disableOnClaim":false }, "autodelete":{ "enableInactiveDays":false, "inactiveDays":7, - "enableUserLeave":true, + "enableUserLeave":false, "disableOnClaim":false }, "cooldown":{ From 7646b3fc35e6f3d247db692e825f6b5fb6835086 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 15 Dec 2024 20:11:39 +0100 Subject: [PATCH 074/157] Increased HTML Transcript log level --- src/core/api/openticket/transcript.ts | 2 ++ src/data/openticket/transcriptLoader.ts | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/core/api/openticket/transcript.ts b/src/core/api/openticket/transcript.ts index 5e89525..6be48ff 100644 --- a/src/core/api/openticket/transcript.ts +++ b/src/core/api/openticket/transcript.ts @@ -246,6 +246,8 @@ export class ODTranscriptCollector { } } }catch{} + + //DEPRECATED WARNING!!! => msg.interaction might break in a future version of discord.js => required for slash command name }else if (msg.interaction && msg.interaction.type == discord.InteractionType.ApplicationCommand){ //slash command reply const member = await msg.guild.members.fetch(msg.interaction.user.id) diff --git a/src/data/openticket/transcriptLoader.ts b/src/data/openticket/transcriptLoader.ts index 3f46803..b0ec97e 100644 --- a/src/data/openticket/transcriptLoader.ts +++ b/src/data/openticket/transcriptLoader.ts @@ -448,15 +448,24 @@ export const loadAllTranscriptCompilers = async () => { const req = new ODHTTPHtmlPostRequest("apis.dj-dj.be",htmlFinal) const res = await req.run() + //check status if (!res || res.status != 200 || !res.body){ - if (res.status == 429) return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts due to Ratelimt! Try again in a few minutes!",messages,data:null} - else return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts!",messages,data:null} + //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 + openticket.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{ var data: api.ODTranscriptHtmlV2Response = JSON.parse(res.body) - if (!data || data["status"] != "success") return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts! (Status: Error)",messages,data:null} + if (!data || data["status"] != "success"){ + openticket.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{ - return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts due to JSON parse error!",messages,data:null} + openticket.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} } const url = "https://transcripts.dj-dj.be/v2/"+data.time+"_"+data.id+".html" From 05b4080ac5dbeb11e5b5d858cdedeb13867c2c1c Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 25 Dec 2024 18:20:58 +0100 Subject: [PATCH 075/157] Plugins can now use import path shortcuts Plugins are now able to use import path shortcuts to import all API classes, utilities and the openticket globals. You can now import everything from "#opendiscord" instead of "../../src/index" --- package.json | 8 ++++++-- plugins/example-plugin/index.ts | 4 ++-- tsconfig.json | 5 +---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 8e2a1dd..88c5943 100644 --- a/package.json +++ b/package.json @@ -35,5 +35,9 @@ "url": "https://github.com/DJj123dj/open-ticket/issues", "email": "support@dj-dj.be" }, - "homepage": "https://openticket.dj-dj.be" -} + "homepage": "https://openticket.dj-dj.be", + "imports": { + "#opendiscord":"./dist/src/index.js", + "#opendiscord-types":"./dist/src/core/api/api.js" + } +} \ No newline at end of file diff --git a/plugins/example-plugin/index.ts b/plugins/example-plugin/index.ts index ec70562..fce3aac 100644 --- a/plugins/example-plugin/index.ts +++ b/plugins/example-plugin/index.ts @@ -1,4 +1,4 @@ -import {api, openticket, utilities} from "../../src/index" +import {api, openticket, utilities} from "#opendiscord" import * as discord from "discord.js" ///////////////////////////////////////////// @@ -9,7 +9,7 @@ import * as discord from "discord.js" if (utilities.project != "openticket") throw new api.ODPluginError("This plugin only works in Open Ticket!") //Add Typescript autocomplete support for plugin data. (!!!OPTIONAL!!!) -declare module "../../src/core/api/api.js" { +declare module "#opendiscord-types" { export interface ODConfigManagerIds_Default { "example-plugin:config":api.ODJsonConfig } diff --git a/tsconfig.json b/tsconfig.json index 50bcbcf..95a1996 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,10 +1,7 @@ { "compilerOptions": { "target": "ES2022", - "rootDirs":[ - "./src", - "./plugins" - ], + "rootDir":"./", "outDir": "./dist/", "module": "NodeNext", "moduleResolution": "NodeNext", From 72f7cbce262608b5f227579bcaf38bd9c83661c5 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 25 Dec 2024 18:21:37 +0100 Subject: [PATCH 076/157] Improved default config message descriptions. --- config/options.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/options.json b/config/options.json index e9d4ca4..277a5ff 100644 --- a/config/options.json +++ b/config/options.json @@ -30,7 +30,7 @@ "dmMessage":{ "enabled":false, - "text":"Thanks for creating a ticket in our server! (or leave empty)", + "text":"Thank you for creating a ticket in our server! (or leave empty)", "embed":{ "enabled":false, "title":"Embed Title! (or leave empty)", @@ -51,7 +51,7 @@ "embed":{ "enabled":true, "title":"Question Ticket", - "description":"Thanks for creating a 'Question' ticket in our server!\nOur support team will help you soon!", + "description":"Thank you for creating a 'Question' ticket in our server!\nOur support team will help you as soon as possible!", "customColor":"#f8ab00 (or leave empty)", "image":"https://www.example.com/image.png (or leave empty)", From 0cbf9910907a28a3d74bc8f6ed0f694807e80eff Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 25 Dec 2024 21:05:01 +0100 Subject: [PATCH 077/157] Update transcripts.json --- config/transcripts.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/config/transcripts.json b/config/transcripts.json index 5ce9a88..15b111c 100644 --- a/config/transcripts.json +++ b/config/transcripts.json @@ -31,15 +31,13 @@ "background":{ "enableCustomBackground":false, "backgroundColor":"#f8ba00 (or leave empty)", - "backgroundImage":"https://www.example.com/image.png (or leave empty)" - + "backgroundImage":"https://www.example.com/image.png (or leave empty)" }, "header":{ "enableCustomHeader":false, "backgroundColor":"#202225", "decoColor":"#f8ba00", "textColor":"#ffffff" - }, "stats":{ "enableCustomStats":false, From cfa692b3562dcf9439c474eb53715e1ea3fbfb50 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 6 Jan 2025 20:51:11 +0100 Subject: [PATCH 078/157] =?UTF-8?q?Updated=20README.md=20year=20to=202025?= =?UTF-8?q?=20=F0=9F=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5a2c675..4eb09c0 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ You're also able to customise every little aspect of the bot! From embeds to tra ### 📌 Features - **💩 no bloat/credits** - Your Open Ticket bot doesn't contain any form of bloat or credits! +- **🔒 tested & secure** - Open Ticket has been tested by thousands of servers and is very secure! - **📈 scalable** - Open Ticket is made to handle huge servers! Even if your server contains more than 100k members! - **📄 html transcripts** - Make use of the most customisable, beautiful and easy-to-use HTML Transcripts! - **✅ ticket actions** - Close, Reopen, Delete, Rename & Move all your tickets! @@ -183,4 +184,4 @@ Please help us grow by giving a star! It would help us a lot! **README.md**
[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)
-© 2024 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file +© 2025 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file From 91657f7519502fc57ba0628ca37a851c76b81150 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 6 Jan 2025 20:51:36 +0100 Subject: [PATCH 079/157] Fixed ot-sqlite-database plugin stats not working --- src/core/api/modules/stat.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/api/modules/stat.ts b/src/core/api/modules/stat.ts index 0c1fe37..fb91120 100644 --- a/src/core/api/modules/stat.ts +++ b/src/core/api/modules/stat.ts @@ -112,12 +112,12 @@ export class ODStatScope extends ODManager { if (mode == "set" || typeof value != "number"){ await this.database.set(this.id.value+"_"+stat.id.value,scopeId,value) }else if (mode == "increase"){ - const currentValue = this.getStat(id,scopeId) - if (typeof currentValue != "number") await this.database.set(this.id.value+"_"+stat.id.value,scopeId,0) + const currentValue = await this.getStat(id,scopeId) + if (typeof currentValue != "number") await this.database.set(this.id.value+"_"+stat.id.value,scopeId,0+value) else await this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue+value) }else if (mode == "decrease"){ - const currentValue = this.getStat(id,scopeId) - if (typeof currentValue != "number") await this.database.set(this.id.value+"_"+stat.id.value,scopeId,0) + const currentValue = await this.getStat(id,scopeId) + if (typeof currentValue != "number") await this.database.set(this.id.value+"_"+stat.id.value,scopeId,0-value) else await this.database.set(this.id.value+"_"+stat.id.value,scopeId,currentValue-value) } return true From 17e19026811b78a52ffc8c223e99e380a8524a57 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 6 Jan 2025 21:14:41 +0100 Subject: [PATCH 080/157] Updated discord.js to v14.17.2 --- package.json | 8 +++--- src/core/api/modules/responder.ts | 45 +++++++++++++++++++------------ 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 88c5943..018ffc8 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "dependencies": { "@types/node": "^22.5.0", "ansis": "^2.3.0", - "discord.js": "^14.16.1", + "discord.js": "^14.17.2", "formatted-json-stringify": "^1.1.0", "typescript": "^5.5.4" }, @@ -37,7 +37,7 @@ }, "homepage": "https://openticket.dj-dj.be", "imports": { - "#opendiscord":"./dist/src/index.js", - "#opendiscord-types":"./dist/src/core/api/api.js" + "#opendiscord": "./dist/src/index.js", + "#opendiscord-types": "./dist/src/core/api/api.js" } -} \ No newline at end of file +} diff --git a/src/core/api/modules/responder.ts b/src/core/api/modules/responder.ts index bc6b223..0f42eb5 100644 --- a/src/core/api/modules/responder.ts +++ b/src/core/api/modules/responder.ts @@ -315,13 +315,14 @@ export class ODCommandResponderInstance { async reply(msg:ODMessageBuildResult): Promise> { try { + const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] if (this.type == "interaction" && this.interaction instanceof discord.ChatInputCommandInteraction){ if (this.interaction.replied || this.interaction.deferred){ - const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.editReply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:sent} }else{ - const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.reply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:await sent.fetch()} } @@ -337,7 +338,8 @@ export class ODCommandResponderInstance { async defer(ephemeral:boolean){ if (this.type != "interaction" || !(this.interaction instanceof discord.ChatInputCommandInteraction)) return false if (this.interaction.deferred) return false - await this.interaction.deferReply({ephemeral}) + const msgFlags: number[] = ephemeral ? [discord.MessageFlags.Ephemeral] : [] + await this.interaction.deferReply({flags:msgFlags}) this.didReply = true return true } @@ -438,12 +440,13 @@ export class ODButtonResponderInstance { async reply(msg:ODMessageBuildResult): Promise> { try{ + const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] if (this.interaction.replied || this.interaction.deferred){ - const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.editReply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:sent} }else{ - const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.reply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:await sent.fetch()} } @@ -453,12 +456,13 @@ export class ODButtonResponderInstance { } async update(msg:ODMessageBuildResult): Promise> { try{ + const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] if (this.interaction.replied || this.interaction.deferred){ - const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.editReply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:await sent.fetch()} }else{ - const sent = await this.interaction.update(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.update(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:await sent.fetch()} } @@ -469,7 +473,8 @@ export class ODButtonResponderInstance { async defer(type:"reply"|"update", ephemeral:boolean){ if (this.interaction.deferred) return false if (type == "reply"){ - await this.interaction.deferReply({ephemeral}) + const msgFlags: number[] = ephemeral ? [discord.MessageFlags.Ephemeral] : [] + await this.interaction.deferReply({flags:msgFlags}) }else{ await this.interaction.deferUpdate() } @@ -668,12 +673,13 @@ export class ODDropdownResponderInstance { async reply(msg:ODMessageBuildResult): Promise> { try { + const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] if (this.interaction.replied || this.interaction.deferred){ - const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.editReply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:sent} }else{ - const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.reply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:await sent.fetch()} } @@ -683,12 +689,13 @@ export class ODDropdownResponderInstance { } async update(msg:ODMessageBuildResult): Promise> { try{ + const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] if (this.interaction.replied || this.interaction.deferred){ - const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.editReply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:await sent.fetch()} }else{ - const sent = await this.interaction.update(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.update(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:await sent.fetch()} } @@ -699,7 +706,8 @@ export class ODDropdownResponderInstance { async defer(type:"reply"|"update", ephemeral:boolean){ if (this.interaction.deferred) return false if (type == "reply"){ - await this.interaction.deferReply({ephemeral}) + const msgFlags: number[] = ephemeral ? [discord.MessageFlags.Ephemeral] : [] + await this.interaction.deferReply({flags:msgFlags}) }else{ await this.interaction.deferUpdate() } @@ -839,12 +847,13 @@ export class ODModalResponderInstance { async reply(msg:ODMessageBuildResult): Promise> { try{ + const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] if (this.interaction.replied || this.interaction.deferred){ - const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.editReply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:sent} }else{ - const sent = await this.interaction.reply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.reply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:await sent.fetch()} } @@ -854,8 +863,9 @@ export class ODModalResponderInstance { } async update(msg:ODMessageBuildResult): Promise> { try{ + const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] if (this.interaction.replied || this.interaction.deferred){ - const sent = await this.interaction.editReply(Object.assign(msg.message,{ephemeral:msg.ephemeral})) + const sent = await this.interaction.editReply(Object.assign(msg.message,{flags:msgFlags})) this.didReply = true return {success:true,message:await sent.fetch()} }else throw new ODSystemError() @@ -866,7 +876,8 @@ export class ODModalResponderInstance { async defer(type:"reply"|"update", ephemeral:boolean){ if (this.interaction.deferred) return false if (type == "reply"){ - await this.interaction.deferReply({ephemeral}) + const msgFlags: number[] = ephemeral ? [discord.MessageFlags.Ephemeral] : [] + await this.interaction.deferReply({flags:msgFlags}) }else{ await this.interaction.deferUpdate() } From e65a092bc0defd970d0ec6655ca0931d9b6801cb Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 6 Jan 2025 22:29:09 +0100 Subject: [PATCH 081/157] Small bug fixes --- src/builders/embeds.ts | 29 ++++++----------------------- src/core/api/defaults/config.ts | 6 +++--- 2 files changed, 9 insertions(+), 26 deletions(-) diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts index 78cb533..f8e9c47 100644 --- a/src/builders/embeds.ts +++ b/src/builders/embeds.ts @@ -490,7 +490,7 @@ const panelEmbeds = () => { if (!panel.exists("openticket:embed")) return const embedOptions = panel.get("openticket:embed").value - instance.setColor(embedOptions.customColor ? (embedOptions.customColor as discord.ColorResolvable) : generalConfig.data.mainColor) + instance.setColor(embedOptions.customColor ? embedOptions.customColor : generalConfig.data.mainColor) instance.setTitle(embedOptions.title) if (embedOptions.thumbnail) instance.setThumbnail(embedOptions.thumbnail) if (embedOptions.image) instance.setImage(embedOptions.image) @@ -586,7 +586,7 @@ const ticketEmbeds = () => { const {user,ticket} = params const embedOptions = ticket.option.get("openticket:ticket-message-embed").value - instance.setColor(embedOptions.customColor ? (embedOptions.customColor as discord.ColorResolvable) : generalConfig.data.mainColor) + instance.setColor(embedOptions.customColor ? embedOptions.customColor : generalConfig.data.mainColor) if (embedOptions.title) instance.setTitle(embedOptions.title) if (embedOptions.thumbnail) instance.setThumbnail(embedOptions.thumbnail) if (embedOptions.image) instance.setImage(embedOptions.image) @@ -985,8 +985,9 @@ const transcriptEmbeds = () => { embeds.get("openticket:transcript-text-ready").workers.add( new api.ODWorker("openticket:transcript-text-ready",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler} = params + const transcriptConfig = openticket.configs.get("openticket:transcripts") - instance.setColor(generalConfig.data.mainColor) + instance.setColor(transcriptConfig.data.embedSettings.customColor ? transcriptConfig.data.embedSettings.customColor : generalConfig.data.mainColor) instance.setTitle(utilities.emojiTitle("📄",lang.getTranslation("transcripts.success.ready"))) instance.setTimestamp(new Date()) instance.addFields({name:lang.getTranslation("params.uppercase.ticket")+":",value:"#"+channel.name,inline:false}) @@ -1014,8 +1015,9 @@ const transcriptEmbeds = () => { embeds.get("openticket:transcript-html-ready").workers.add( new api.ODWorker("openticket:transcript-html-ready",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler,result} = params + const transcriptConfig = openticket.configs.get("openticket:transcripts") - instance.setColor(generalConfig.data.mainColor) + instance.setColor(transcriptConfig.data.embedSettings.customColor ? transcriptConfig.data.embedSettings.customColor : generalConfig.data.mainColor) instance.setTitle(utilities.emojiTitle("📄",lang.getTranslation("transcripts.success.ready"))) instance.setTimestamp(new Date()) instance.addFields({name:lang.getTranslation("params.uppercase.ticket")+":",value:"#"+channel.name,inline:false}) @@ -1162,25 +1164,6 @@ const clearEmbeds = () => { ) } -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE -//TRANSLATION FINISHED UNTIL HERE - const autoEmbeds = () => { //AUTOCLOSE MESSAGE embeds.add(new api.ODEmbed("openticket:autoclose-message")) diff --git a/src/core/api/defaults/config.ts b/src/core/api/defaults/config.ts index e4db760..0f0a9d6 100644 --- a/src/core/api/defaults/config.ts +++ b/src/core/api/defaults/config.ts @@ -200,7 +200,7 @@ export interface ODJsonConfig_DefaultOptionEmbedSettingsType { enabled:boolean, title:string, description:string, - customColor:string, + customColor:discord.ColorResolvable, image:string, thumbnail:string, @@ -312,7 +312,7 @@ export interface ODJsonConfig_DefaultPanelEmbedSettingsType { title:string, description:string, - customColor:string, + customColor:discord.ColorResolvable, url:string, image:string, @@ -426,7 +426,7 @@ export class ODJsonConfig_DefaultTranscripts extends ODJsonConfig { mode:"html"|"text" }, embedSettings:{ - customColor:string, + customColor:discord.ColorResolvable, listAllParticipants:boolean, includeTicketStats:boolean }, From abd672dd3b90e4941ffbb3a8ea8b052d6c9edf3d Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 7 Jan 2025 19:36:29 +0100 Subject: [PATCH 082/157] Small bug fixes (plugin system) --- .github/CONTENT_CREATORS.md | 2 +- src/core/api/modules/plugin.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/CONTENT_CREATORS.md b/.github/CONTENT_CREATORS.md index f72f41f..af0ea14 100644 --- a/.github/CONTENT_CREATORS.md +++ b/.github/CONTENT_CREATORS.md @@ -1,6 +1,6 @@ # 🎥 Content Creators Hi there! We're searching for content creators to create tutorials & setup guides for Open Ticket. -You can get many great rewards from helpin us! +You can get many great rewards from helping us! You can choose which type of tutorial you want to make. You can create a quick setup, full setup, plugin tutorial or something else! You are not required to talk in the video, but make sure it has some kind of subtitles instead. diff --git a/src/core/api/modules/plugin.ts b/src/core/api/modules/plugin.ts index 31fd16b..864f6fe 100644 --- a/src/core/api/modules/plugin.ts +++ b/src/core/api/modules/plugin.ts @@ -20,10 +20,10 @@ export class ODPluginManager extends ODManager { } /**Check if a plugin has loaded successfully.*/ - isPluginLoaded(id:ODValidId){ + isPluginLoaded(id:ODValidId): boolean { const newId = new ODId(id) const plugin = this.get(newId) - return (plugin && plugin.executed) + return (plugin !== null && plugin.executed) } } From 061523578085b5578320642769d44fd1424a5fcc Mon Sep 17 00:00:00 2001 From: JasperAtSchool Date: Thu, 9 Jan 2025 17:48:50 +0100 Subject: [PATCH 083/157] Added new API comments (part 1) --- src/core/api/modules/base.ts | 11 ++++++----- src/core/api/modules/checker.ts | 12 ++++++------ src/core/api/modules/code.ts | 17 ++++++++++------- src/core/api/modules/config.ts | 10 +++++----- src/core/api/modules/console.ts | 2 +- src/core/api/modules/database.ts | 6 +++--- src/core/api/modules/event.ts | 4 ++-- src/core/api/modules/language.ts | 30 ++++++++++++++++++++++++++++-- src/core/api/modules/post.ts | 2 +- src/core/api/modules/worker.ts | 2 +- 10 files changed, 63 insertions(+), 33 deletions(-) diff --git a/src/core/api/modules/base.ts b/src/core/api/modules/base.ts index b422fce..a77e90d 100644 --- a/src/core/api/modules/base.ts +++ b/src/core/api/modules/base.ts @@ -45,7 +45,7 @@ export type ODInterfaceWithPartialProperty void)|null = null @@ -192,10 +192,11 @@ export type ODManagerAddCallback = (data:DataTyp /**## ODManager `class` * This is an open ticket manager. * - * It can be used to store & manage different aspects of the bot! - * You will probably to extend this class when creating your own classes & managers. + * It can be used to store & manage classes based on their `ODId`. + * It is somewhat the same as the default JS `Map()`. + * You can extend this class when creating your own classes & managers. * - * This class has many useful functions based on `ODId` (add, get, remove, getAll, getFiltered, exists) + * This class has many useful functions based on `ODId` (add, get, remove, getAll, getFiltered, exists, loopAll, ...) */ export class ODManager extends ODManagerChangeHelper { /**Alias to open ticket debugger. */ diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 77bdc6f..01cee77 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -19,7 +19,7 @@ export interface ODCheckerResult { * * It manages all config checkers in the bot and allows plugins to access config checkers from open ticket & other plugins! * - * You will use this class to get/add a config checker (`ODChecker`) in your plugin! + * You can use this class to get/add a config checker (`ODChecker`) in your plugin! * @example * //get checker for ./config/general.json => ODChecker class * const testChecker = openticket.checkers.get("openticket:general") @@ -99,7 +99,7 @@ export class ODCheckerManager extends ODManager { * (e.g. The `messages.json` needs to access the `"id"` from `options.json`) * * - * You will probably use this class when you create your own config checker! + * You can use this class when you create your own config checker implementation! (not required for using the built-in config checker) */ export class ODCheckerStorage { /**This is the array that stores all the data. ❌ **(don't edit unless really needed!)***/ @@ -150,7 +150,7 @@ export class ODCheckerStorage { * It's responsible for rendering the config checker result in the console. * This class doesn't provide any components! You need to create them by extending this class * - * You will only use this class if you want to change how the config checker looks! + * You can use this class if you want to change how the config checker looks! */ export class ODCheckerRenderer { /**Get all components */ @@ -174,7 +174,7 @@ export class ODCheckerRenderer { * It's used to store & manage the translation for each message from the config checker! * Most translations are stored by message id, but there are some exceptions like the additional text on the checker report. * - * You will use this class if you want to translate your config checker messages! **This is optional & isn't required for the checker to work!** + * You can use this class if you want to translate your config checker messages! **This is optional & isn't required for the checker to work!** */ export class ODCheckerTranslationRegister { /**This is the array that stores all the data. ❌ **(don't edit unless really needed!)***/ @@ -298,7 +298,7 @@ export type ODCheckerLocationTrace = (string|number)[] * It checks a specific config file for invalid/missing configurations. This data can then be used to show to the user what's wrong! * You can check for example if a string is longer/shorter than a certain amount of characters & more! * - * You will use this class when you create your own custom config file & you want to check it for syntax errors. + * You can use this class when you create your own custom config file & you want to check it for syntax errors. * @example * //create a new checker with id "test" => ./config/test.json * const testConfig = new api.ODConfig("test","test.json") @@ -410,7 +410,7 @@ export interface ODCheckerStructureOptions { * This class will check for a single variable in a config file, customise it in the settings! * If you want prebuilt checkers (for strings, booleans, numbers, ...), check the other `ODCheckerStructure`'s! * - * You will almost never use this class! It's better if you extend on another `ODConfigCheckerStructure`! + * **Not recommended to use!** It's recommended to extend from another `ODConfigCheckerStructure` class! */ export class ODCheckerStructure { /**The id of this checker structure */ diff --git a/src/core/api/modules/code.ts b/src/core/api/modules/code.ts index 08cb395..8d1885c 100644 --- a/src/core/api/modules/code.ts +++ b/src/core/api/modules/code.ts @@ -8,11 +8,14 @@ import { ODDebugger } from "./console" /**## ODCode `class` * This is an open ticket code runner. * - * It is just a function that will run just before the bot has started completely! - * This can be used for code that needs to run at startup, but isn't really time dependent. - * - * - It has an `id` for identification of the function - * - A `priority` to know when to execute this function (related to others) + * Using this, you're able to execute a function just before the startup screen. (90% of the code is already loaded) + * You can also specify a priority to change the execution order. + * In Open Ticket, this is used for the following processes: + * - Autoclose/delete + * - Database syncronisation (with tickets, stats & used options) + * - Panel auto-update + * - Database Garbage Collection (removing tickets that don't exist anymore) + * - And more! */ export class ODCode extends ODManagerData { /**The priority of this code */ @@ -32,14 +35,14 @@ export class ODCode extends ODManagerData { * * It manages & executes `ODCode`'s in the correct order. * - * You will probably register a function/code in this class for something that doesn't really need to be timed. + * Use this to register a function/code which executes just before the startup screen. (90% is already loaded) */ export class ODCodeManager extends ODManager { constructor(debug:ODDebugger){ super(debug,"code") } - /**Execute all functions or code. */ + /**Execute all `ODCode` functions in order of their priority (high to low). */ async execute(){ const derefArray = [...this.getAll()] const workers = derefArray.sort((a,b) => b.priority-a.priority) diff --git a/src/core/api/modules/config.ts b/src/core/api/modules/config.ts index 8e635ed..796d1f6 100644 --- a/src/core/api/modules/config.ts +++ b/src/core/api/modules/config.ts @@ -9,9 +9,9 @@ import fs from "fs" /**## ODConfigManager `class` * This is an open ticket config manager. * - * It manages all config files in the bot and allows plugins to access config files from open ticket & other plugins! + * It manages all config files in the bot and allows plugins to access config files from Open Ticket & other plugins! * - * You will use this class to get/add a config file (`ODConfig`) in your plugin! + * You can use this class to get/change/add a config file (`ODConfig`) in your plugin! */ export class ODConfigManager extends ODManager { constructor(debug:ODDebugger){ @@ -33,7 +33,7 @@ export class ODConfigManager extends ODManager { * This is an open ticket config helper. * This class doesn't do anything at all, it just gives a template & basic methods for a config. Use `ODJsonConfig` instead! * - * You will only use this class if you want to create your own config implementation (e.g. `yml`, `xml`,...)! + * You can use this class if you want to create your own config implementation (e.g. `yml`, `xml`,...)! */ export class ODConfig extends ODManagerData { /**The name of the file with extension. */ @@ -55,8 +55,8 @@ export class ODConfig extends ODManagerData { } /**## ODJsonConfig `class` - * This is an open ticket config helper. - * You will use this class to get & edit variables from the config files or to create your own config! + * This is an open ticket JSON config. + * You can use this class to get & edit variables from the config files or to create your own JSON config! * @example * //create a config from: ./config/test.json with the id "some-config" * const config = new api.ODJsonConfig("some-config","test.json") diff --git a/src/core/api/modules/console.ts b/src/core/api/modules/console.ts index b6e0943..d36ce20 100644 --- a/src/core/api/modules/console.ts +++ b/src/core/api/modules/console.ts @@ -583,7 +583,7 @@ export class ODLiveStatusUrlSource extends ODLiveStatusSource { * * It manages all LiveStatus sources and has the renderer for all LiveStatus messages. * - * You will probably use this to customise or add stuff to the LiveStatus system. + * You can use this to customise or add stuff to the LiveStatus system. * Access it in the global `openticket.startscreen.livestatus` variable! */ export class ODLiveStatusManager extends ODManager { diff --git a/src/core/api/modules/database.ts b/src/core/api/modules/database.ts index 24d4ab9..767f307 100644 --- a/src/core/api/modules/database.ts +++ b/src/core/api/modules/database.ts @@ -12,7 +12,7 @@ import * as fjs from "formatted-json-stringify" * * It manages all databases in the bot and allows to permanently store data from the bot! * - * You will use this class to get/add a database (`ODDatabase`) in your plugin! + * You can use this class to get/add a database (`ODDatabase`) in your plugin! */ export class ODDatabaseManager extends ODManager { constructor(debug:ODDebugger){ @@ -35,7 +35,7 @@ export class ODDatabaseManager extends ODManager { * This is an open ticket database template. * This class doesn't do anything at all, it just gives a template & basic methods for a database. Use `ODJsonDatabase` instead! * - * You will only use this class if you want to create your own database implementation (e.g. `mongodb`, `mysql`,...)! + * You can use this class if you want to create your own database implementation (e.g. `mongodb`, `mysql`,...)! */ export class ODDatabase extends ODManagerData { /**The name of the file with extension. */ @@ -83,7 +83,7 @@ export type ODJsonDatabaseStructure = {category:string, key:string, value:ODVali * It stores data in a `json` file as a large `Array` using the `category`, `key`, `value` strategy. * You can store the following types: `string`, `number`, `boolean`, `array`, `object` & `null`! * - * You will use this class if you want to create your own database or use an existing one! + * You can use this class if you want to add your own database or to use an existing one! */ export class ODJsonDatabase extends ODDatabase { constructor(id:ODValidId, file:string, customPath?:string){ diff --git a/src/core/api/modules/event.ts b/src/core/api/modules/event.ts index 27633c1..9d52d8b 100644 --- a/src/core/api/modules/event.ts +++ b/src/core/api/modules/event.ts @@ -75,8 +75,8 @@ export class ODEvent extends ODManagerData { * * This class is made to manage all events in the bot. You can compare it with the built-in node.js `EventEmitter` * - * You will probably not create this class yourself, but use it globaly instead! - * Check out the `openticket.events` class! + * It's not recommended to create this class yourself. Plugin events should be registered in their `plugin.json` file instead. + * All events are available in the `openticket.events` global! */ export class ODEventManager extends ODManager { /**Reference to the Open Ticket debugger */ diff --git a/src/core/api/modules/language.ts b/src/core/api/modules/language.ts index 71a12c3..4cac88b 100644 --- a/src/core/api/modules/language.ts +++ b/src/core/api/modules/language.ts @@ -6,17 +6,36 @@ import nodepath from "path" import { ODDebugger } from "./console" import fs from "fs" +/**## ODLanguageMetadata `interface` + * This interface contains all metadata available in the language files. + */ export interface ODLanguageMetadata { + /**The version of Open Ticket this translation is made for. */ otversion:string, + /**The name of the language in english (with capital letter). */ language:string, + /**A list of translators (discord/github username) who've contributed to this language. */ translators:string[], + /**The last date that this translation has been modified (format: DD/MM/YYYY) */ lastedited:string, + /**When `true`, the translator made use of some sort of automation while creating the translation. (e.g. ChatGPT, Google Translate, DeepL, ...) */ automated:boolean } +/**## ODLanguageManager `class` + * This is an open ticket language manager. + * + * It manages all languages in the bot and manages translation for you! + * Get a translation via the `getTranslation()` or `getTranslationWithParams()` methods. + * + * Add new languages using the `ODlanguage` class in your plugin! + */ export class ODLanguageManager extends ODManager { + /**The currently selected language. */ current: ODLanguage|null = null + /**The currently selected backup language. (used when translation missing in current language) */ backup: ODLanguage|null = null + /**An alias to Open Ticket debugger. */ #debug: ODDebugger constructor(debug:ODDebugger, presets:boolean){ @@ -27,6 +46,7 @@ export class ODLanguageManager extends ODManager { this.#debug = debug } + /**Set the current language by providing the ID of a language which is registered in this manager. */ setCurrentLanguage(id:ODValidId){ this.current = this.get(id) const languageId = this.current?.id.value ?? "" @@ -36,9 +56,11 @@ export class ODLanguageManager extends ODManager { {key:"automated",value:languageAutomated}, ]) } + /**Get the current language (same as `this.current`) */ getCurrentLanguage(){ return (this.current) ? this.current : null } + /**Set the backup language by providing the ID of a language which is registered in this manager. */ setBackupLanguage(id:ODValidId){ this.backup = this.get(id) const languageId = this.backup?.id.value ?? "" @@ -48,16 +70,20 @@ export class ODLanguageManager extends ODManager { {key:"automated",value:languageAutomated}, ]) } + /**Get the backup language (same as `this.backup`) */ getBackupLanguage(){ return (this.backup) ? this.backup : null } + /**Get the metadata of the current/backup language. */ getLanguageMetadata(frombackup?:boolean): ODLanguageMetadata|null { if (frombackup) return (this.backup) ? this.backup.metadata : null return (this.current) ? this.current.metadata : null } + /**Get the ID (string) of the current language. (Not backup language) */ getCurrentLanguageId(){ return (this.current) ? this.current.id.value : "" } + /**Get a translation string by JSON location. (e.g. `"checker.system.typeError"`) */ getTranslation(id:string): string|null { if (!this.current) return this.#getBackupTranslation(id) @@ -75,7 +101,7 @@ export class ODLanguageManager extends ODManager { if (typeof result == "string") return result else return this.#getBackupTranslation(id) } - + /**Get a backup translation string by JSON location. (system only) */ #getBackupTranslation(id:string): string|null { if (!this.backup) return null @@ -93,7 +119,7 @@ export class ODLanguageManager extends ODManager { if (typeof result == "string") return result else return null } - + /**Get a backup translation string by JSON location and replace `{0}`,`{1}`,`{2}`,... with the provided parameters. */ getTranslationWithParams(id:string, params:string[]): string|null { let translation = this.getTranslation(id) if (!translation) return translation diff --git a/src/core/api/modules/post.ts b/src/core/api/modules/post.ts index de5b5f6..b985b1c 100644 --- a/src/core/api/modules/post.ts +++ b/src/core/api/modules/post.ts @@ -11,7 +11,7 @@ import * as discord from "discord.js" * * It manages `ODPosts`'s for you. * - * You will probably use this to get the logs channel of the bot (or some other static channel/category). + * You can use this to get the logs channel of the bot (or some other static channel/category). */ export class ODPostManager extends ODManager> { /**A reference to the main server of the bot */ diff --git a/src/core/api/modules/worker.ts b/src/core/api/modules/worker.ts index 617beb1..7b9cf96 100644 --- a/src/core/api/modules/worker.ts +++ b/src/core/api/modules/worker.ts @@ -36,7 +36,7 @@ export class ODWorker extends ODManager * * It manages & executes `ODWorker`'s in the correct order. * - * You will probably register a custom worker in this class to create a message or button. + * You can register a custom worker in this class to create a message or button. */ export class ODWorkerManager extends ODManager> { /**The order of execution for workers inside this manager. */ From ce0af7e1e9760716f9a2db98318465143a9750e0 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 9 Jan 2025 18:34:29 +0100 Subject: [PATCH 084/157] Added new API comments (part 2) --- src/core/api/modules/language.ts | 16 +++++++ src/core/api/modules/permission.ts | 69 ++++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 3 deletions(-) diff --git a/src/core/api/modules/language.ts b/src/core/api/modules/language.ts index 4cac88b..c9f683b 100644 --- a/src/core/api/modules/language.ts +++ b/src/core/api/modules/language.ts @@ -143,6 +143,14 @@ export class ODLanguageManager extends ODManager { } } +/**## ODLanguage `class` + * This is an open ticket language file. + * + * It contains metadata and all translation strings available in this language. + * Register this class to an `ODLanguageManager` to use it! + * + * JSON languages should be created using the `ODJsonLanguage` class instead! + */ export class ODLanguage extends ODManagerData { /**The name of the file with extension. */ file: string = "" @@ -164,6 +172,14 @@ export class ODLanguage extends ODManagerData { } } +/**## ODJsonLanguage `class` + * This is an open ticket JSON language file. + * + * It contains metadata and all translation strings from a certain JSON file (in `./languages/`). + * Register this class to an `ODLanguageManager` to use it! + * + * Use the `ODLanguage` class to use translations from non-JSON files! + */ export class ODJsonLanguage extends ODLanguage { constructor(id:ODValidId, file:string, customPath?:string){ super(id,{}) diff --git a/src/core/api/modules/permission.ts b/src/core/api/modules/permission.ts index 5602d29..ee2b03e 100644 --- a/src/core/api/modules/permission.ts +++ b/src/core/api/modules/permission.ts @@ -5,28 +5,65 @@ import { ODId, ODValidId, ODManager, ODSystemError, ODManagerData } from "./base import * as discord from "discord.js" import { ODDebugger } from "./console" +/**## ODPermissionType `type` + * All available permission types/levels. Can be used in the `ODPermission` class. + */ export type ODPermissionType = "member"|"support"|"moderator"|"admin"|"owner"|"developer" + +/**## ODPermissionScope `type` + * The scope in which a certain permission is active. + */ export type ODPermissionScope = "global-user"|"channel-user"|"global-role"|"channel-role" + +/**## ODPermissionResult `interface` + * The result returned by `ODPermissionManager.getPermissions()`. + */ export interface ODPermissionResult { + /**The permission type. */ type:ODPermissionType + /**The permission scope. */ scope:ODPermissionScope|"default" + /**The highest level available for this scope. */ level:ODPermissionLevel, + /**The permission which returned this level. */ source:ODPermission|null } +/**## ODPermissionLevel `enum` + * All available permission types/levels. But as `enum` instead of `type`. Used to calculate the level. + */ export enum ODPermissionLevel { + /**A normal member. (Default for everyone) */ member, + /**Support team. Higher than a normal member. (Used for ticket-admins) */ support, + /**Moderator. Higher than the support team. (Unused) */ moderator, + /**Admin. Higher than a moderator. (Used for global-admins) */ admin, + /**Server owner. (Able to use all commands including `/stats reset`) */ owner, + /**Bot owner or all users from dev team. (Able to use all commands including `/stats reset`) */ developer } +/**## ODPermission `class` + * This is an open ticket permission. + * + * It defines a single permission level for a specific scope (global/channel & user/role) + * These permissions only apply to commands & interactions. + * They are not related to channel permissions in the ticket system. + * + * Register this class to an `ODPermissionManager` to use it! + */ export class ODPermission extends ODManagerData { + /**The scope of this permission. */ readonly scope: ODPermissionScope + /**The type/level of this permission. */ readonly permission: ODPermissionType + /**The user/role of this permission. */ readonly value: discord.Role|discord.User + /**The channel that this permission applies to. (`null` when global) */ readonly channel: discord.Channel|null constructor(id:ODValidId, scope:"global-user", permission:ODPermissionType, value:discord.User) @@ -42,18 +79,39 @@ export class ODPermission extends ODManagerData { } } +/**## ODPermissionSettings `interface` + * Optional settings for the `getPermissions()` method in the `ODPermissionManager`. + */ export interface ODPermissionSettings { + /**Include permissions from the global user scope. */ allowGlobalUserScope?:boolean, + /**Include permissions from the global role scope. */ allowGlobalRoleScope?:boolean, + /**Include permissions from the channel user scope. */ allowChannelUserScope?:boolean, + /**Include permissions from the channel role scope. */ allowChannelRoleScope?:boolean, + /**Only include permissions of which the id matches this regex. */ idRegex?:RegExp } +/**## ODPermissionCalculationCallback `type` + * The callback of the permission calculation. (Used in `ODPermissionManager`) + */ export type ODPermissionCalculationCallback = (user:discord.User, channel?:discord.Channel|null, guild?:discord.Guild|null, settings?:ODPermissionSettings|null) => Promise +/**## ODPermissionManager `class` + * This is an open ticket permission manager. + * + * It manages all permissions in the bot! + * Use the `getPermissions()` and `hasPermissions()` methods to get user perms. + * + * Add new permissions using the `ODPermission` class in your plugin! + */ export class ODPermissionManager extends ODManager { + /**The function for calculating permissions in this manager. */ #calculation: ODPermissionCalculationCallback|null + /**The result which is returned when no other permissions match. (`member` by default) */ defaultResult: ODPermissionResult = { level:ODPermissionLevel["member"], scope:"default", @@ -66,12 +124,15 @@ export class ODPermissionManager extends ODManager { this.#calculation = useDefaultCalculation ? this.#defaultCalculation : null } + /**Edit the permission calculation function in this manager. */ setCalculation(calculation:ODPermissionCalculationCallback){ this.#calculation = calculation } + /**Edit the result which is returned when no other permissions match. (`member` by default) */ setDefaultResult(result:ODPermissionResult){ this.defaultResult = result } + /**Get an `ODPermissionResult` based on a few context factors. Use `hasPermissions()` to simplify the result. */ getPermissions(user:discord.User, channel?:discord.Channel|null, guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise { try{ if (!this.#calculation) throw new ODSystemError("ODPermissionManager:getPermissions() => missing perms calculation") @@ -81,6 +142,7 @@ export class ODPermissionManager extends ODManager { throw new ODSystemError("ODPermissionManager:getPermissions() => failed perms calculation") } } + /**Simplifies the `ODPermissionResult` returned from `getPermissions()` and returns a boolean to check if the user matches the required permissions. */ hasPermissions(minimum:ODPermissionType, data:ODPermissionResult){ if (minimum == "member") return true else if (minimum == "support") return (data.level >= ODPermissionLevel["support"]) @@ -90,6 +152,7 @@ export class ODPermissionManager extends ODManager { else if (minimum == "developer") return (data.level >= ODPermissionLevel["developer"]) else throw new ODSystemError("Invalid minimum permission type at ODPermissionManager.hasPermissions()") } + /**Check for permissions. (default calculation) */ async #defaultCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise { const globalCalc = await this.#defaultGlobalCalculation(user,channel,guild,settings) const channelCalc = await this.#defaultChannelCalculation(user,channel,guild,settings) @@ -97,7 +160,7 @@ export class ODPermissionManager extends ODManager { if (globalCalc.level > channelCalc.level) return globalCalc else return channelCalc } - /**Check for global permissions. Then this result can be compared with the channel one. */ + /**Check for global permissions. Result will be compared with the channel perms in `#defaultCalculation()`. */ async #defaultGlobalCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise { const idRegex = (settings && typeof settings.idRegex != "undefined") ? settings.idRegex : null const allowGlobalUserScope = (settings && typeof settings.allowGlobalUserScope != "undefined") ? settings.allowGlobalUserScope : true @@ -160,7 +223,7 @@ export class ODPermissionManager extends ODManager { //spread result to prevent accidental referencing return {...this.defaultResult} } - /**Check for channel permissions. Then this result can be compared with the global one. */ + /**Check for channel permissions. Result will be compared with the global perms in `#defaultCalculation()`. */ async #defaultChannelCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise { const idRegex = (settings && typeof settings.idRegex != "undefined") ? settings.idRegex : null const allowChannelUserScope = (settings && typeof settings.allowChannelUserScope != "undefined") ? settings.allowChannelUserScope : true @@ -220,7 +283,7 @@ export class ODPermissionManager extends ODManager { } } - //spread result to prevent accidental referencing + //spread result to prevent accidental modification because of referencing return {...this.defaultResult} } } \ No newline at end of file From 02e8b7d0a1212aad17f823a273bd9005f43038b6 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 9 Jan 2025 19:42:11 +0100 Subject: [PATCH 085/157] Added new API comments (part 3) --- src/core/api/modules/plugin.ts | 69 ++++++++++++++++++++++++++++++- src/core/api/modules/verifybar.ts | 22 +++++++++- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/src/core/api/modules/plugin.ts b/src/core/api/modules/plugin.ts index 864f6fe..6bd03df 100644 --- a/src/core/api/modules/plugin.ts +++ b/src/core/api/modules/plugin.ts @@ -5,13 +5,29 @@ import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId, ODVersion } f import nodepath from "path" import { ODConsolePluginMessage, ODConsoleWarningMessage, ODDebugger } from "./console" +/**## ODUnknownCrashedPlugin `interface` + * Basic details for a plugin that crashed while loading the `plugin.json` file. + */ export interface ODUnknownCrashedPlugin { + /**The name of the plugin. (path when plugin crashed before `name` was loaded) */ name:string, + /**The description of the plugin. (when found before crashing) */ description:string } +/**## ODPluginManager `class` + * This is an open ticket plugin manager. + * + * It manages all active plugins in the bot! + * It also contains all "plugin classes" which are managers registered by plugins. + * These are accessible via the `openticket.plugins.classes` global. + * + * Use `isPluginLoaded()` to check if a plugin has been loaded. + */ export class ODPluginManager extends ODManager { + /**A manager for all custom managers registered by plugins. */ classes: ODPluginClassManager + /**A list of basic details from all plugins that crashed while loading the `plugin.json` file. */ unknownCrashedPlugins: ODUnknownCrashedPlugin[] = [] constructor(debug:ODDebugger){ @@ -19,7 +35,7 @@ export class ODPluginManager extends ODManager { this.classes = new ODPluginClassManager(debug) } - /**Check if a plugin has loaded successfully.*/ + /**Check if a plugin has been loaded successfully and is available for usage.*/ isPluginLoaded(id:ODValidId): boolean { const newId = new ODId(id) const plugin = this.get(newId) @@ -27,43 +43,84 @@ export class ODPluginManager extends ODManager { } } +/**## ODPluginData `interface` + * Parsed data from the `plugin.json` file in a plugin. + */ export interface ODPluginData { + /**The name of this plugin (shown on startup) */ name:string, + /**The id of this plugin. (Must be identical to directory name) */ id:string, + /**The version of this plugin. */ version:string, + /**The location of the start file of the plugin relative to the rootDir of the plugin */ startFile:string, + /**Is this plugin enabled? */ enabled:boolean, + /**The priority of this plugin. Higher priority will load before lower priority. */ priority:number, + /**A list of events to register to the `openticket.events` global before loading any plugins. This way, plugins with a higher priority are able to use events from this plugin as well! */ events:string[] + /**Npm dependencies which are required for this plugin to work. */ npmDependencies:string[], + /**Plugins which are required for this plugin to work. */ requiredPlugins:string[], + /**Plugins which are incompatible with this plugin. */ incompatiblePlugins:string[], + /**Additional details about this plugin. */ details:ODPluginDetails } +/**## ODPluginDetails `interface` + * Additional details in the `plugin.json` file from a plugin. + */ export interface ODPluginDetails { + /**The author of the plugin. */ author:string, + /**A short description of this plugin. */ shortDescription:string, + /**A large description of this plugin. */ longDescription:string, + /**A URL to a cover image of this plugin. (currently unused) */ imageUrl:string, + /**A URL to the website/project page of this plugin. (currently unused) */ projectUrl:string, + /**A list of tags/categories that this plugin affects. */ tags:string[] } +/**## ODPlugin `class` + * This is an open ticket plugin. + * + * It represents a single plugin in the `./plugins/` directory. + * All plugins are accessible via the `openticket.plugins` global. + * + * Don't re-execute plugins which are already enabled! It might break the bot or plugin. + */ export class ODPlugin extends ODManagerData { + /**The name of the directory of this plugin. (same as id) */ dir: string + /**All plugin data found in the `plugin.json` file. */ data: ODPluginData + /**The name of this plugin. */ name: string + /**The priority of this plugin. */ priority: number + /**The version of this plugin. */ version: ODVersion + /**The additional details of this plugin. */ details: ODPluginDetails + /**Is this plugin enabled? */ enabled: boolean + /**Did this plugin execute successfully?. */ executed: boolean + /**Did this plugin crash? (A reason is available in the `crashReason`) */ crashed: boolean + /**The reason which caused this plugin to crash. */ crashReason: null|"incompatible.plugin"|"missing.plugin"|"missing.dependency"|"executed" = null constructor(dir:string, jsondata:ODPluginData){ @@ -160,6 +217,16 @@ export class ODPlugin extends ODManagerData { } } +/**## ODPluginClassManager `class` + * This is an open ticket plugin class manager. + * + * It manages all managers registered by plugins! + * Plugins are able to register their own managers, handlers, functions, classes, ... here. + * By doing this, other plugins are also able to make use of it. + * This can be useful for plugins that want to extend other plugins. + * + * Use `isPluginLoaded()` to check if a plugin has been loaded before trying to access the manager. + */ export class ODPluginClassManager extends ODManager { constructor(debug:ODDebugger){ super(debug,"plugin class") diff --git a/src/core/api/modules/verifybar.ts b/src/core/api/modules/verifybar.ts index 6d8a914..037d6d4 100644 --- a/src/core/api/modules/verifybar.ts +++ b/src/core/api/modules/verifybar.ts @@ -8,12 +8,21 @@ import { ODButtonResponderInstance } from "./responder" import * as discord from "discord.js" import { ODWorkerManager } from "./worker" -export type ODVerifyBarCallback = (responder:ODButtonResponderInstance,customData?:string) => void|Promise - +/**## ODVerifyBar `class` + * This is an open ticket verifybar. + * + * It is contains 2 sets of workers and a lot of utilities for the (✅ ❌) verifybars in the bot. + * + * It doesn't contain the code which activates or spawns the verifybars! + */ export class ODVerifyBar extends ODManagerData { + /**All workers that will run when the verifybar is accepted. */ success: ODWorkerManager|null}> + /**All workers that will run when the verifybar is stopped. */ failure: ODWorkerManager|null}> + /**The message that will be built wen activating this verifybar. */ message: ODMessage<"verifybar",{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message}> + /**When disabled, it will skip the verifybar and instantly fire the `success` workers. */ enabled: boolean constructor(id:ODValidId, message:ODMessage<"verifybar",{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalMessage:discord.Message}>, enabled?:boolean){ @@ -24,6 +33,7 @@ export class ODVerifyBar extends ODManagerData { this.enabled = enabled ?? true } + /**Build the message and reply to a button with this verifybar. */ async activate(responder:ODButtonResponderInstance){ if (this.enabled){ //show verifybar @@ -36,6 +46,14 @@ export class ODVerifyBar extends ODManagerData { } } +/**## ODVerifyBarManager `class` + * This is an open ticket verifybar manager. + * + * It contains all (✅ ❌) verifybars in the bot. + * The `ODVerifyBar` classes contain `ODWorkerManager`'s that will be fired when the continue/stop buttons are pressed. + * + * It doesn't contain the code which activates the verifybars! This should be implemented by your own. + */ export class ODVerifyBarManager extends ODManager { constructor(debug:ODDebugger){ super(debug,"verifybar") From dd5374f84c2c89bde00086cb87b7029339686f62 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Fri, 10 Jan 2025 23:01:03 +0100 Subject: [PATCH 086/157] Update plugin.json --- plugins/example-plugin/plugin.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/example-plugin/plugin.json b/plugins/example-plugin/plugin.json index 76fd490..264b156 100644 --- a/plugins/example-plugin/plugin.json +++ b/plugins/example-plugin/plugin.json @@ -8,7 +8,7 @@ "priority":0, "events":[], - "npmDependencies":["discord.js"], + "npmDependencies":[], "requiredPlugins":[], "incompatiblePlugins":[], From 1a1a3f3b028edd3b7e976fae61318a428f6ccdc6 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 11 Jan 2025 22:27:52 +0100 Subject: [PATCH 087/157] Update README.md --- README.md | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 4eb09c0..036fde2 100644 --- a/README.md +++ b/README.md @@ -26,24 +26,32 @@ You're also able to customise every little aspect of the bot! From embeds to tra > The translation count may not be accurate! ### 📌 Features -- **💩 no bloat/credits** - Your Open Ticket bot doesn't contain any form of bloat or credits! +- **💩 no bloat** - Your Open Ticket bot doesn't contain any form of bloat or credits! - **🔒 tested & secure** - Open Ticket has been tested by thousands of servers and is very secure! -- **📈 scalable** - Open Ticket is made to handle huge servers! Even if your server contains more than 100k members! -- **📄 html transcripts** - Make use of the most customisable, beautiful and easy-to-use HTML Transcripts! +- **📈 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, Rename & Move all your tickets! -- **🇬🇧 translation** - Open Ticket has been translated in more than **16 languages** by our community! +- **🇬🇧 translation** - Open Ticket has been translated in more than **20 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 everywhere** - Create an infinite amount of tickets & panels! -- **📝 advanced plugins** - Create the most advanced plugins that you want or use premade ones by our community! +- **∞ unlimited** - Create an infinite amount of tickets & panels! +- **📝 advanced plugins** - Create advanced plugins or use pre-made ones by our community! - **👥 user management** - Add & Remove users from all tickets! - **📊 detailed stats** - Open Ticket has ticket, user & global staticstics available for everyone! - **🚫 blacklist** - Blacklist users to prevent them from creating a ticket! - **❓ questions** - Let users answer questions in a modal before the ticket is created! - **📦 commands** - Open Ticket supports both slash & text commands! -- **📥 extra types** - The bot also supports Reaction Roles & Url Buttons, because why not ¯\\_(ツ)_/¯ -- **🎛️ dependencies** - We try to use as little external dependencies as needed! -- **📢 commands** - The bot contains more than 25 commands! And it's expandable with plugins! +- **📥 extra buttons** - The bot also supports Reaction Roles & Url Buttons, because why not ¯\\_(ツ)_/¯ +- **✨ commands** - The bot contains more than 25 commands! + +#### And more using plugins! + - **💬 reviews** - Create & customise your own review system! + - **📢 feedback** - Collect feedback & create forms for people to answer! + - **🔄 rotating status** - Create a rotating bot status & use dynamic variables from the bot! + - **💾 sqlite database** - Use an `sqlite` database for increased performances! + - **🎉 custom embeds** - Create your own embeds and use them in your server! + - **🎨 customisation** - Yep, you heard it right! Even more customisation! + - **😁 And so much more...** > ### 📦 Resources > Resources might not be accurate yet! *(because v4 is still in beta)*
@@ -52,13 +60,19 @@ You're also able to customise every little aspect of the bot! From embeds to tra > Open Ticket Plugins ## 📸 Preview -Ticket Message -Ticket Stats Message -Example Panel 1 -Example Panel 2 +Ticket Message +Ticket Stats Message +Example Panel 1 +Example Panel 2 ## 🧩 Plugins -**Download all plugins in our [Official Plugin Repository](https://github.com/DJj123dj/open-discord-plugins)!** +**Download all plugins in our [Official Plugin Repository](https://github.com/DJj123dj/open-discord-plugins)!**
+> #### ⭐ Featured Plugins (Top 5 Most Used) +> **[`ot-sqlite-database`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-sqlite-database/), +> [`ot-migrate-v3`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-migrate-v3/), +> [`ot-reviews`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-reviews/), +> [`ot-feedback`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-feedback/), +> [`ot-customise-buttons`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-customise-buttons/)** ### 📦 Official *(made by DJdj Development)* |Name |Category |Description | @@ -68,15 +82,18 @@ You're also able to customise every little aspect of the bot! From embeds to tra |[`ot-jump-to-top`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-jump-to-top/) |📢 Command |Add a simple command to jump to the top of the ticket. | |[`ot-kill-switch`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-kill-switch/) |📢 Command |Temporarily disable the ticket system using a kill switch. | |[`ot-hosting-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-hosting-status/) |📢 Command |A simple command to send hosting status updates to a channel. | +|[`ot-shutdown`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-shutdown/) |📢 Command |A simple command to turn off the bot from a slash command (server & bot owner only). | |[`ot-sqlite-database`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-sqlite-database/) |⚙️ Utility |With this plugin, the database will be an SQLite file. It's a must-have for large servers! | |[`ot-no-slash-clear`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-no-slash-clear/) |⚙️ Utility |Disable the automatic removal of slash commands that aren't used by Open Ticket. | |[`ot-migrate-v3`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-migrate-v3/) |⚙️ Utility |Use this plugin to migrate all tickets from Open Ticket v3 to v4. | |[`ot-ticket-message-extras`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ticket-message-extras/) |🎨 Customisation |A plugin which adds a few little features to the ticket message. | |[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |🎨 Customisation |Simple plugin to keep the channel prefix when using the /rename command. | |[`ot-customise-buttons`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-customise-buttons/) |🎨 Customisation |Customise almost all built-in buttons. This includes the claim, reopen, close & delete buttons. | -|[`ot-alt-detector`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-alt-detector/) |💼 Management |Use the discord-alt-detector npm package by DJdj Development in your ticket bot. | +|[`ot-ephemeral-messages`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ephemeral-messages/) |🎨 Customisation |Customise for every messages if it needs to be ephemeral or not. | |[`ot-alt-detector`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-alt-detector/) |💼 Management |Use the discord-alt-detector npm package by DJdj Development in your ticket bot. | |[`ot-embeds`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-embeds/) |💼 Management |Create custom premade embeds in the config or use the command to create one from scratch. | +|[`ot-move-actions`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-move-actions/) |💼 Management |Automatically unclaim/unpin a ticket when it's moved using `/move`. | +|[`ot-reviews`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-reviews/) |💼 Management |Review system for Open Ticket! It is very customisable and has lots of features. | |[`ot-better-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-better-status/) |🤖 Client |An advanced status plugin to rotate between states. It also allows for the use of variables. | ### ✅ Verified *(made by community)* @@ -182,6 +199,6 @@ Please help us grow by giving a star! It would help us a lot! Open Ticket Logo **README.md**
-[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)
+[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)
© 2025 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file From 499901fbf1cd3cd1d988c99a4e8c6bedd118ddeb Mon Sep 17 00:00:00 2001 From: JasperAtSchool Date: Tue, 14 Jan 2025 16:37:43 +0100 Subject: [PATCH 088/157] Added new API comments (part 4) --- src/core/api/defaults/config.ts | 78 +++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/src/core/api/defaults/config.ts b/src/core/api/defaults/config.ts index 0f0a9d6..bee6f3e 100644 --- a/src/core/api/defaults/config.ts +++ b/src/core/api/defaults/config.ts @@ -52,22 +52,28 @@ export class ODConfigManager_Default extends ODConfigManager { * This interface is an object which has all properties for the status object in the `general.json` config! */ export interface ODJsonConfig_DefaultStatusType { + /**Is the status enabled? */ enabled:boolean, + /**The type of status (e.g. playing, listening, custom, ...) */ type:Exclude, + /**The text for the status. */ text:string, + /**The status of the bot (e.g. online, invisible, idle, do not disturb) */ status:ODClientActivityStatus } /**## ODJsonConfig_DefaultMessageSettingsType `interface` - * This interface is an object which has all properties for the system/messages/... object in the `general.json` config! + * This interface is an object which has all properties for the "system"."messages".... object in the `general.json` config! */ export interface ODJsonConfig_DefaultMessageSettingsType { + /**Enable sending DM logs to the ticket creator for this action. */ dm:boolean, + /**Enable sending logsto the log channel for this action. */ logs:boolean } /**## ODJsonConfig_DefaultCmdPermissionSettingsType `type` - * This type is a collection of command permission settings for the system/permissions/... object in the `general.json` config! + * This type is a collection of command permission settings for the "system"."permissions".... object in the `general.json` config! */ export type ODJsonConfig_DefaultCmdPermissionSettingsType = "admin"|"everyone"|"none"|string @@ -79,56 +85,96 @@ export type ODJsonConfig_DefaultCmdPermissionSettingsType = "admin"|"everyone"|" */ export class ODJsonConfig_DefaultGeneral extends ODJsonConfig { declare data: { + /**This object contains a few URLs and metadata for the config. */ _INFO:{ + /**A link to the Open Ticket documentation. */ support:string, + /**A link to the DJdj Development discord server. */ discord:string, + /**The version of Open Ticket this config is compatible with. */ version:string }, + /**The token of the bot. (Empty when using `tokenFromENV`) */ token:string, + /**Use the token from the `.env` file as `TOKEN=xxxxx`. */ tokenFromENV:boolean, + /**The main (hex) color used in almost every embed in the bot. */ mainColor:discord.ColorResolvable, + /**The language to use. Can be the id of the language or the id without the prefix when using `openticket:...`. */ language:string, + /**The prefix used in all text-commands. */ prefix:string, + /**The id of the discord server where the bot is used. */ serverId:string, + /**A list of discord role ids which are able to access all tickets & commands. */ globalAdmins:string[], + /**Are slash commands enabled? */ slashCommands:boolean, + /**Are text commands enabled? */ textCommands:boolean, + /**All settings related to the status of the bot. */ status:ODJsonConfig_DefaultStatusType, + /**All settings related to the ticket system. */ system:{ + /**Remove all participants (except admins) from the ticket when it's closed. */ removeParticipantsOnClose:boolean, + /**Reply with an ephemeral message when a ticket is created. */ replyOnTicketCreation:boolean, + /**Reply with an ephemeral message when reaction roles are changed. */ replyOnReactionRole:boolean, + /**Use a translated config checker in the console. */ useTranslatedConfigChecker:boolean, + /**Prefer slash-commands over text-commands when displaying them in menu's and messages. */ preferSlashOverText:boolean, + /**Reply with "unknown command" when the prefix is used without a valid command. */ sendErrorOnUnknownCommand:boolean, + /**Display the question fields (in a ticket message) in code blocks. */ questionFieldsInCodeBlock:boolean, + /**Disable the (✅❌) buttons and directly run the action. */ disableVerifyBars:boolean, + /**Display error embeds/messages with red instead of the default bot color. */ useRedErrorEmbeds:boolean, + /**The emoji style used in the bot. This will affect all embeds, titles & messages in the bot. */ emojiStyle:"before"|"after"|"double"|"disabled", + + /**Enable/disable the ticket claim & unclaim button in the ticket message. */ enableTicketClaimButtons:boolean, + /**Enable/disable the ticket close & re-open button in the ticket message. */ enableTicketCloseButtons:boolean, + /**Enable/disable the ticket pin & unpin button in the ticket message. */ enableTicketPinButtons:boolean, + /**Enable/disable the ticket delete button in the ticket message. */ enableTicketDeleteButtons:boolean, + /**Enable/disable the "with reason" button for all actions in the ticket message. */ enableTicketActionWithReason:boolean, + /**Enable/disable the delete without transcript feature (button & /delete command). */ enableDeleteWithoutTranscript:boolean, + /**All settings related to the log channel. */ logs:{ + /**Enable logging. Individual actions should still be added via the `"system"."messages"..."logs"` */ enabled:boolean, + /**The channel to send logs to. */ channel:string }, + /**All settings related to global ticket limits. */ limits:{ + /**Enable global ticket limits. */ enabled:boolean, + /**The maximum amount of tickets that are allowed in the server at the same time. */ globalMaximum:number, + /**The maximum amount of tickets that a user is allowed to create at the same time. */ userMaximum:number }, + /**Configure permissions for all Open Ticket commands & actions. */ permissions:{ help:ODJsonConfig_DefaultCmdPermissionSettingsType, panel:ODJsonConfig_DefaultCmdPermissionSettingsType, @@ -151,6 +197,7 @@ export class ODJsonConfig_DefaultGeneral extends ODJsonConfig { autodelete:ODJsonConfig_DefaultCmdPermissionSettingsType }, + /**Configure dm & log messages for all Open Ticket commands & actions. */ messages:{ creation:ODJsonConfig_DefaultMessageSettingsType, closing:ODJsonConfig_DefaultMessageSettingsType, @@ -174,22 +221,32 @@ export class ODJsonConfig_DefaultGeneral extends ODJsonConfig { * This interface is an object which has all basic properties for options in the `options.json` config! */ export interface ODJsonConfig_DefaultOptionType { + /**The id of this option. */ id:string, + /**The name of this option. */ name:string, + /**The description of this option. */ description:string, + /**The type of this option. This type also determines the other option-specific variables. */ type:"ticket"|"website"|"role", + /**All settings related to the button for the 3 option types. */ button:{ + /**The emoji of the button. (can also be empty) */ emoji:string, + /**The label of the button (can also be empty) */ label:string } } /**## ODJsonConfig_DefaultOptionButtonSettingsType `interface` - * This interface is an object which has all button settings for ticket options in the `options.json` config! + * This interface is an object which has all button settings for ticket & reaction role options in the `options.json` config! */ export interface ODJsonConfig_DefaultOptionButtonSettingsType { + /**The emoji of the button. (can also be empty) */ emoji:string, + /**The label of the button (can also be empty) */ label:string, + /**The color of the button (not available in options with the 'website' type!) */ color:ODValidButtonColor } @@ -197,14 +254,27 @@ export interface ODJsonConfig_DefaultOptionButtonSettingsType { * This interface is an object which has all message embed settings for ticket options in the `options.json` config! */ export interface ODJsonConfig_DefaultOptionEmbedSettingsType { + /**Is this embed enabled? */ enabled:boolean, + /**The title of the embed. */ title:string, + /**The description of this embed. */ description:string, + /**A custom color for this embed. (The default bot color is used when empty) */ customColor:discord.ColorResolvable, + /**A URL to an image displayed in the embed. */ image:string, + /**A URL to a thumbnail displayed in the embed. */ thumbnail:string, - fields:{name:string, value:string, inline:boolean}[], + /**A list of fields displayed in the embed. */ + fields:{ + /**The name of this field. */ + name:string, + /**The value of this field. => empty not allowed */ + value:string, + inline:boolean + }[], timestamp:boolean } From 9a73ee0d016391db0812e4c502be4920c0068259 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 14 Jan 2025 16:46:22 +0100 Subject: [PATCH 089/157] Fixed bug with option description being empty Fixed a bug which caused the /panel command to crash when using an option without any description in combination with the "describeOptionsInEmbedFields" mode enabled. --- src/data/openticket/panelLoader.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/data/openticket/panelLoader.ts b/src/data/openticket/panelLoader.ts index 07d17cb..cb86bdf 100644 --- a/src/data/openticket/panelLoader.ts +++ b/src/data/openticket/panelLoader.ts @@ -96,6 +96,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { if (opt.exists("openticket:admins")) description = description + "\nAdmins: "+opt.get("openticket:admins").value.map((admin) => discord.roleMention(admin)).join(", ") } + if (description == "") description = "``" return {name:utilities.emojiTitle(emoji,name),value:description} }else if (opt instanceof api.ODWebsiteOption){ @@ -104,6 +105,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + if (description == "") description = "``" return {name:utilities.emojiTitle(emoji,name),value:description} }else if (opt instanceof api.ODRoleOption){ @@ -117,6 +119,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { if (opt.exists("openticket:roles")) description = description + "\nRoles: "+opt.get("openticket:roles").value.map((admin) => discord.roleMention(admin)).join(", ") } + if (description == "") description = "``" return {name:utilities.emojiTitle(emoji,name),value:description} }else{ @@ -124,7 +127,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { const emoji = opt.get("openticket:button-emoji") as api.ODOptionData|null const name = opt.get("openticket:name") as api.ODOptionData|null const description = opt.get("openticket:description") as api.ODOptionData|null - return {name:utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`")),value:(description ? description.value : "``")} + return {name:utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`")),value:((description && description.value) ? description.value : "``")} } }) else if (mode == "text") return title+options.map((opt) => { From 138378ac31145689936ed671a3b748fa86621a3d Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:18:47 +0100 Subject: [PATCH 090/157] Added new API comments (part 5) --- src/core/api/defaults/config.ts | 146 +++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 2 deletions(-) diff --git a/src/core/api/defaults/config.ts b/src/core/api/defaults/config.ts index bee6f3e..bcc5654 100644 --- a/src/core/api/defaults/config.ts +++ b/src/core/api/defaults/config.ts @@ -275,6 +275,7 @@ export interface ODJsonConfig_DefaultOptionEmbedSettingsType { value:string, inline:boolean }[], + /**Enable setting the timestamp of the embed to the current time. */ timestamp:boolean } @@ -282,8 +283,11 @@ export interface ODJsonConfig_DefaultOptionEmbedSettingsType { * This interface is an object which has all message ping settings for ticket options in the `options.json` config! */ export interface ODJsonConfig_DefaultOptionPingSettingsType { + /**Ping `@here`. */ "@here":boolean, + /**Ping `@everyone`. */ "@everyone":boolean, + /**A list of custom discord role ids to ping. */ custom:string[] } @@ -293,49 +297,92 @@ export interface ODJsonConfig_DefaultOptionPingSettingsType { export interface ODJsonConfig_DefaultOptionTicketType extends ODJsonConfig_DefaultOptionType { type:"ticket", button:ODJsonConfig_DefaultOptionButtonSettingsType, + /**A list of discord role ids which are able to access this ticket type & use commands. */ ticketAdmins:string[], + /**A list of discord role ids which are able to access this ticket type but can't write in the chat. */ readonlyAdmins:string[], + /**When enabled, blacklisted users can still create this ticket type. (used for appeals, etc) */ allowCreationByBlacklistedUsers:boolean, + /**A list of valid question ids from the `questions.json` config. */ questions:string[], + /**All settings related to the ticket channel itself. */ channel:{ + /**The prefix used in the name of this ticket channel. */ prefix:string, + /**The type of suffix used in the name of this ticket channel. */ suffix:"user-name"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed", + /**An optional discord category id to create this ticket in. */ category:string, + /**An optional discord category id to move this ticket to when closed. */ closedCategory:string, + /**An optional discord category id to create this ticket in when the primary one is full (max. 50 tickets). */ backupCategory:string, - claimedCategory:{user:string, category:string}[], + /**A list of discord category ids to move this ticket to when claimed by a specific user. */ + claimedCategory:{ + /**The user which claimed the ticket. */ + user:string, + /**The category to move the ticket to when claimed by this user. */ + category:string + }[], + /**The channel description/topic shown at the top of the channel in discord. */ description:string }, + /**All settings related to the message sent in DM to the creator when the ticket is created. */ dmMessage:{ + /**Enable this message. */ enabled:boolean, + /**The raw text contents of this message. (empty for embed only) */ text:string, + /**The embed of this message. */ embed:ODJsonConfig_DefaultOptionEmbedSettingsType }, + /**All settings related to the message sent in the ticket channel when the ticket is created. */ ticketMessage:{ + /**Enable this message. */ enabled:boolean, + /**The raw text contents of this message. (empty for embed only) */ text:string, + /**The embed of this message. */ embed:ODJsonConfig_DefaultOptionEmbedSettingsType, + /**Additional ping/mention settings for this ticket channel. */ ping:ODJsonConfig_DefaultOptionPingSettingsType }, + /**All settings related to autoclosing this ticket type. */ autoclose:{ + /**Enable autoclosing when the ticket is inactive for the set duration of time. */ enableInactiveHours:boolean, + /**The amount of hours this ticket is required to be inactive for. */ inactiveHours:number, + /**Enable autoclosing when the creator of the ticket leaves the server. */ enableUserLeave:boolean, + /**Disable autoclosing when the ticket is claimed by someone. */ disableOnClaim:boolean }, + /**All settings related to autodeleting this ticket type. */ autodelete:{ + /**Enable autodeleting when the ticket is inactive for the set duration of time. */ enableInactiveDays:boolean, + /**The amount of days this ticket is required to be inactive for. */ inactiveDays:number, + /**Enable autodeleting when the creator of the ticket leaves the server. */ enableUserLeave:boolean, + /**Disable autodeleting when the ticket is claimed by someone. */ disableOnClaim:boolean }, + /**All settings related to the cooldown of this ticket type */ cooldown:{ + /**Enable cooldown (per user) */ enabled:boolean, + /**The amount of minutes a user needs to wait before being able to create a ticket again. */ cooldownMinutes:number }, + /**All settings related to the limits of this ticket type */ limits:{ + /**Enable option ticket limits. */ enabled:boolean, + /**The maximum amount of tickets of this type that are allowed in the server at the same time. */ globalMaximum:number, + /**The maximum amount of tickets of this type that a user is allowed to create at the same time. */ userMaximum:number } } @@ -345,6 +392,7 @@ export interface ODJsonConfig_DefaultOptionTicketType extends ODJsonConfig_Defau */ export interface ODJsonConfig_DefaultOptionWebsiteType extends ODJsonConfig_DefaultOptionType { type:"website", + /**The URL this button will point to. */ url:string } @@ -354,9 +402,13 @@ export interface ODJsonConfig_DefaultOptionWebsiteType extends ODJsonConfig_Defa export interface ODJsonConfig_DefaultOptionRoleType extends ODJsonConfig_DefaultOptionType { type:"role", button:ODJsonConfig_DefaultOptionButtonSettingsType, + /**All roles which will be affected by this button. */ roles:string[], + /**The mode determines what will happen with the affected roles on the user. */ mode:OTRoleUpdateMode, + /**A list of roles to remove from the user when given at least one of the affected roles. */ removeRolesOnAdd:string[], + /**Automatically add these roles when the user joins the server. */ addOnMemberJoin:boolean } @@ -378,18 +430,34 @@ export class ODJsonConfig_DefaultOptions extends ODJsonConfig { * This interface is an object which has all message embed settings for panels in the `panels.json` config! */ export interface ODJsonConfig_DefaultPanelEmbedSettingsType { + /**Is this embed enabled? */ enabled:boolean, + /**The title of the embed. */ title:string, + /**The description of this embed. */ description:string, + /**A custom color for this embed. (The default bot color is used when empty) */ customColor:discord.ColorResolvable, + /**An optional URL used in the title of the embed. */ url:string, + /**A URL to an image displayed in the embed. */ image:string, + /**A URL to a thumbnail displayed in the embed. */ thumbnail:string, + /**The footer of this embed. */ footer:string, - fields:{name:string,value:string,inline:boolean}[], + /**A list of fields displayed in the embed. (except when using "describeOptionsInEmbedFields") */ + fields:{ + /**The name of this field. */ + name:string, + /**The value of this field. => empty not allowed */ + value:string, + inline:boolean + }[], + /**Enable setting the timestamp of the embed to the current time. */ timestamp:boolean } @@ -397,23 +465,37 @@ export interface ODJsonConfig_DefaultPanelEmbedSettingsType { * This interface is an object which has all properties for panels in the `panels.json` config! */ export interface ODJsonConfig_DefaultPanelType { + /**The id of this panel. */ id:string, + /**The name of this panel. */ name:string, + /**When enabled, the panel uses a dropdown instead of buttons. */ dropdown:boolean, + /**A list of valid options ids from the `options.json` config. */ options:string[], + /**The raw text contents of this panel. (empty for embed only) */ text:string, + /**The embed of this panel. */ embed:ODJsonConfig_DefaultPanelEmbedSettingsType, settings:{ + /**The placeholder used in the dropdown when enabled. */ dropdownPlaceholder:string, + /**Enable a max tickets warning in the text contents. */ enableMaxTicketsWarningInText:boolean, + /**Enable a max tickets warning in the embed. */ enableMaxTicketsWarningInEmbed:boolean, + /**The layout/complexity of the describe options feature. */ describeOptionsLayout:"simple"|"normal"|"detailed", + /**A custom title for the describe options feature. */ describeOptionsCustomTitle:string, + /**Describe the options in the text contents. */ describeOptionsInText:boolean, + /**Describe the options in the embed fields. */ describeOptionsInEmbedFields:boolean, + /**Describe the options in the embed description. */ describeOptionsInEmbedDescription:boolean } } @@ -432,15 +514,24 @@ export class ODJsonConfig_DefaultPanels extends ODJsonConfig { * This interface is an object which has all properties for short questions in the `questions.json` config! */ export interface ODJsonConfig_DefaultShortQuestionType { + /**The id of this question. */ id:string, + /**The name of this question. */ name:string, + /**The type of this question. */ type:"short", + /**Is this question required? */ required:boolean, + /**A placeholder for the question. */ placeholder:string, + /**Settings related to the length of the input. */ length:{ + /**Enable text length verification. */ enabled:boolean, + /**The minimum text input length. */ min:number, + /**The maximum text input length. */ max:number } } @@ -449,15 +540,24 @@ export interface ODJsonConfig_DefaultShortQuestionType { * This interface is an object which has all properties for paragraph questions in the `questions.json` config! */ export interface ODJsonConfig_DefaultParagraphQuestionType { + /**The id of this question. */ id:string, + /**The name of this question. */ name:string, + /**The type of this question. */ type:"paragraph", + /**Is this question required? */ required:boolean, + /**A placeholder for the question. */ placeholder:string, + /**Settings related to the length of the input. */ length:{ + /**Enable text length verification. */ enabled:boolean, + /**The minimum text input length. */ min:number, + /**The maximum text input length. */ max:number } } @@ -483,56 +583,98 @@ export class ODJsonConfig_DefaultQuestions extends ODJsonConfig { */ export class ODJsonConfig_DefaultTranscripts extends ODJsonConfig { declare data: { + /**All general settings related to transcripts. */ general:{ + /**Are transcripts enabled? */ enabled:boolean, + /**Enable sending the generated transcript in a channel. */ enableChannel:boolean, + /**Enable sending the generated transcript to the DM of the ticket creator. */ enableCreatorDM:boolean, + /**Enable sending the generated transcript to the DM of the participants. */ enableParticipantDM:boolean, + /**Enable sending the generated transcript to the DM of all admins which were active in the ticket. */ enableActiveAdminDM:boolean, + /**Enable sending the generated transcript to the DM of all admins which were assigned to the ticket. */ enableEveryAdminDM:boolean, + /**A discord channel id for the `"enableChannel"` setting. */ channel:string, + /**Want to use text or HTML transcripts? */ mode:"html"|"text" }, + /**All settings related to the embed from the transcripts. (UNIMPLEMENTED!!) */ embedSettings:{ + /**Unimplemented feature */ customColor:discord.ColorResolvable, + /**Unimplemented feature */ listAllParticipants:boolean, + /**Unimplemented feature */ includeTicketStats:boolean }, + /**The layout of the text transcripts. */ textTranscriptStyle:{ + /**The layout/complexity of the text transcripts. */ layout:"simple"|"normal"|"detailed", + /**Include stats in the transcript. */ includeStats:boolean, + /**Include user & message ids in the transcript. */ includeIds:boolean, + /**Include embeds in the transcript. */ includeEmbeds:boolean, + /**Include files in the transcript. */ includeFiles:boolean, + /**Include bot messages in the transcript. */ includeBotMessages:boolean, + /**How to name the transcript file? */ fileMode:"custom"|"channel-name"|"channel-id"|"user-name"|"user-id", + /**A custom name for the transcript file (when using `"custom"`) */ customFileName:string }, + /**The layout of the HTML transcripts. */ htmlTranscriptStyle:{ + /**Settings related to the background. */ background:{ + /**Enable a custom background. */ enableCustomBackground:boolean, + /**The background (hex) color. */ backgroundColor:string, + /**The background image url. */ backgroundImage:string }, + /**Settings related to the header. */ header:{ + /**Enable a custom header. */ enableCustomHeader:boolean, + /**The background (hex) color of the header. */ backgroundColor:string, + /**The deco color (horizontal line) of the header. */ decoColor:string, + /**The text color of the header. */ textColor:string }, + /**Settings related to the stats section. */ stats:{ + /**Enable a custom stats section. */ enableCustomStats:false, + /**The background color of the stats section. */ backgroundColor:string, + /**The key text color of the stats section. */ keyTextColor:string, + /**The value text color of the stats section. */ valueTextColor:string, + /**The background color of the hide button in the stats section. */ hideBackgroundColor:string, + /**The text color of the hide button in the stats section. */ hideTextColor:string }, + /**Settings related to the favicon. */ favicon:{ + /**Enable a custom background. */ enableCustomFavicon:boolean, + /**A link to the custom favicon. */ imageUrl:string } } From 7d30bf24d95bd3f3e0cecd2899eceec1dd917574 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:53:11 +0100 Subject: [PATCH 091/157] The bot will now only re-compile when changed The bot will now only re-compile when the plugins or source code changes. (computed using a hash) This reduces the average startup time by 50%. --- index.js | 148 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 114 insertions(+), 34 deletions(-) diff --git a/index.js b/index.js index 13d1eda..25e9576 100644 --- a/index.js +++ b/index.js @@ -1,53 +1,133 @@ -const fs = require("fs") -const ts = require("typescript") -const nodepath = require('path') - /////////////// STARTUP FLAGS /////////////// const flags = [ + // Edit flags here when being unable to use the flags in the command prompt. //PTERODACTYL PANEL //add startup flags here (e.g. "--no-compile") when running via the panel ] process.argv.push(...flags) /////////////// STARTUP FLAGS /////////////// +/* + ██████╗ ██████╗ ███████╗███╗ ██╗ ████████╗██╗ ██████╗██╗ ██╗███████╗████████╗ +██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝ +██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ ██║██║ █████╔╝ █████╗ ██║ +██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║ ██║ ██║██║ ██╔═██╗ ██╔══╝ ██║ +╚██████╔╝██║ ███████╗██║ ╚████║ ██║ ██║╚██████╗██║ ██╗███████╗ ██║ + ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚══════╝ ╚═╝ + v4.0.0 - Made by DJj123dj & Contributors + + Discord: https://discord.dj-dj.be + Docs: https://otdocs.dj-dj.be + Support Us: https://github.com/sponsors/DJj123dj/ + + */ +/////////////////////////////////////////// +////////// COMPILATION + STARTUP ////////// +/////////////////////////////////////////// +const fs = require("fs") +const ts = require("typescript") +const {createHash,Hash} = require("crypto") +const nodepath = require('path') + +/** ## What is this? + * This is a function which compares `./src/` with a hash stored in `./dist/hash.txt`. + * The hash is based on the modified date & file metadata of all files in `./src/`. + * + * If the hash is different, the bot will automatically re-compile. + * This will help you save CPU resources because the bot shouldn't re-compile when nothing has been changed :) + * + * @param {string} dir + * @param {Hash|null} upperHash + */ +function computeSourceHash(dir,upperHash){ + const hash = upperHash ? upperHash : createHash("sha256") + const info = fs.readdirSync(dir,{withFileTypes:true}) + + for (const file of info) { + const fullPath = nodepath.join(dir,file.name) + if (file.isFile()){ + const statInfo = fs.statSync(fullPath) + //compute hash using file metadata + const fileInfo = `${fullPath}:${statInfo.size}:${statInfo.mtimeMs}` + hash.update(fileInfo) + + }else if (file.isDirectory()){ + //recursively compute all folders + computeSourceHash(fullPath,hash) + } + } + //return when not being called recursively + if (!upperHash) { + return hash.digest("hex") + } +} +function requiresCompilation(){ + //check hashes when not using "--compile-only" flag + if (process.argv.includes("--compile-only")) return true + + console.log("OT: Comparing prebuilds with source...") + const sourceHash = computeSourceHash("./src/") + const pluginHash = computeSourceHash("./plugins/") + const hash = sourceHash+":"+pluginHash + + if (fs.existsSync("./dist/hash.txt")){ + const distHash = fs.readFileSync("./dist/hash.txt").toString() + if (distHash === hash) return false + else return true + }else return true +} +function saveNewCompilationHash(){ + const sourceHash = computeSourceHash("./src/") + const pluginHash = computeSourceHash("./plugins/") + const hash = sourceHash+":"+pluginHash + fs.writeFileSync("./dist/hash.txt",hash) +} + if (!process.argv.includes("--no-compile")){ - //REMOVE EXISTING BUILDS - console.log("OT: Removing Prebuilds...") - fs.rmSync("./dist",{recursive:true,force:true}) + if (requiresCompilation()){ + console.log("OT: Compilation Required...") - //COMPILE TYPESCRIPT - console.log("OT: Compiling Typescript...") - const configPath = nodepath.resolve('./tsconfig.json') - const configFile = ts.readConfigFile(configPath,ts.sys.readFile) + //REMOVE EXISTING BUILDS + console.log("OT: Removing Prebuilds...") + fs.rmSync("./dist",{recursive:true,force:true}) - //check for tsconfig errors - if (configFile.error){ - const message = ts.formatDiagnosticsWithColorAndContext([configFile.error],ts.createCompilerHost({})) - console.error(message) - process.exit(1) - } + //COMPILE TYPESCRIPT + console.log("OT: Compiling Typescript...") + const configPath = nodepath.resolve('./tsconfig.json') + const configFile = ts.readConfigFile(configPath,ts.sys.readFile) - //parse tsconfig file - const parsedConfig = ts.parseJsonConfigFileContent(configFile.config,ts.sys,nodepath.dirname(configPath)) + //check for tsconfig errors + if (configFile.error){ + const message = ts.formatDiagnosticsWithColorAndContext([configFile.error],ts.createCompilerHost({})) + console.error(message) + process.exit(1) + } - //create program/compiler - const program = ts.createProgram({ - rootNames:parsedConfig.fileNames, - options:parsedConfig.options - }) + //parse tsconfig file + const parsedConfig = ts.parseJsonConfigFileContent(configFile.config,ts.sys,nodepath.dirname(configPath)) - //emit all compiled files - const emitResult = program.emit() + //create program/compiler + const program = ts.createProgram({ + rootNames:parsedConfig.fileNames, + options:parsedConfig.options + }) - //print emit errors/warnings (type errors) - const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) - const formattedDiagnostics = ts.formatDiagnosticsWithColorAndContext(allDiagnostics, ts.createCompilerHost(parsedConfig.options)) - console.log(formattedDiagnostics) + //emit all compiled files + const emitResult = program.emit() - if (emitResult.emitSkipped || allDiagnostics.find((d) => d.category == ts.DiagnosticCategory.Error || d.category == ts.DiagnosticCategory.Warning)){ - console.log("OT: Compilation Failed!") - process.exit(1) - } + //print emit errors/warnings (type errors) + const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics) + const formattedDiagnostics = ts.formatDiagnosticsWithColorAndContext(allDiagnostics, ts.createCompilerHost(parsedConfig.options)) + console.log(formattedDiagnostics) + + if (emitResult.emitSkipped || allDiagnostics.find((d) => d.category == ts.DiagnosticCategory.Error || d.category == ts.DiagnosticCategory.Warning)){ + console.log("OT: Compilation Failed!") + process.exit(1) + } + }else console.log("OT: No Compilation Required...") + + //save new compilation hash + saveNewCompilationHash() } //START BOT From b6985f9d285eebda90484f03c631f658163d0f9b Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 14 Jan 2025 17:56:27 +0100 Subject: [PATCH 092/157] Updated LICENSE --- LICENSE => LICENSE.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) rename LICENSE => LICENSE.md (97%) diff --git a/LICENSE b/LICENSE.md similarity index 97% rename from LICENSE rename to LICENSE.md index e72bfdd..a79bc68 100644 --- a/LICENSE +++ b/LICENSE.md @@ -1,3 +1,7 @@ +# Open Ticket (License) +© 2025 - DJj123dj & Contributors + +``` GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 @@ -70,7 +74,7 @@ modification follow. TERMS AND CONDITIONS - 0. Definitions. + 1. Definitions. "This License" refers to version 3 of the GNU General Public License. @@ -671,4 +675,16 @@ into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -. \ No newline at end of file +. +``` + +### Additional Terms for Open Ticket +The following additional terms apply to the use of this software: + +1. This software may not be used as part of a public Discord bot service that is monetized (e.g., generating revenue through subscriptions, donations, or other forms of payment) without the prior written permission of the original author. + +2. This software may not be used as part of a public Discord bot service on multiple Discord servers without attribution to the original author. + +3. You are allowed to use this bot in a Discord server that makes money or is for-profit, provided that the income is not generated directly from the ticket bot or its functionality. + +These additional terms are an extension to the GNU GPL v3 and must be followed alongside the original license terms. In case of any conflict between these additional terms and the GNU GPL v3, the additional terms shall take precedence. \ No newline at end of file From 334c9dde210ba2d623339aa0591ed8aef9934e4f Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 14 Jan 2025 18:14:23 +0100 Subject: [PATCH 093/157] Moved sponsors more to top of README.md --- README.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 036fde2..c8c74ff 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,25 @@ You're also able to customise every little aspect of the bot! From embeds to tra > Open Ticket Docs > Open Ticket Plugins +### ❤️ Sponsors +A big thanks to all our sponsors! Without them, it wouldn't be possible to create this project! + + + + + + + + +
Profile Picture
roppl3r
+ +**Past Sponsors:**
+ +SpyEye +Mods HD +DOSEV5 + + ## 📸 Preview Ticket Message Ticket Stats Message @@ -127,25 +146,6 @@ This is the main team working on Open Ticket. Don't forget to check their profil -### ❤️ Sponsors -A big thanks to all our sponsors! Without them, it wouldn't be possible to create this project! - - - - - - - - -
Profile Picture
roppl3r
- -**Past Sponsors:**
- -SpyEye -Mods HD -DOSEV5 - - ### 💬 Translators |Language |Maintainer (discord name) |Status | |---------------------|--------------------------|-----------------------------| From 3a30152cb2fd5b6568bb58b7c95bfe7217edde60 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 18 Jan 2025 20:36:08 +0100 Subject: [PATCH 094/157] Improved startup time (5 sec) due to config bug --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index cad3851..6d94def 100644 --- a/src/index.ts +++ b/src/index.ts @@ -254,7 +254,7 @@ const main = async () => { openticket.checkers.renderer.render(components) //wait 5 seconds when there are warnings (not for errors & info) - if (result.messages.length > 0 && result.messages.every((message) => message.type != "error")) await utilities.timer(5000) + if (result.messages.length > 0 && result.messages.some((msg) => msg.type == "warning") && result.messages.every((msg) => msg.type != "error")) await utilities.timer(5000) await openticket.events.get("afterCheckersRendered").emit([openticket.checkers.renderer,openticket.checkers]) } From 03982f644e49b2b51e9d1f5e2670d9a0e552cee3 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 18 Jan 2025 20:40:52 +0100 Subject: [PATCH 095/157] MAJOR: Full rewrite of slash cmd loading system The system of detecting, comparing & registering slash cmds has been rewritten and updated for future compatibility. This will break all current plugins (so please wait until they are updated) => Increased speed => All cmd params are now used when comparing => Future compability & removed deprecated functions => New universal utility interfaces for slash commands => And more! --- src/core/api/modules/client.ts | 555 +++++++++++++++++++++++-------- src/core/api/modules/defaults.ts | 3 + src/index.ts | 14 +- 3 files changed, 427 insertions(+), 145 deletions(-) diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index 2e839bb..07eae5f 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -402,11 +402,354 @@ export class ODClientActivityManager { } } +/**## ODSlashCommandUniversalTranslation `interface` + * A universal template for a slash command translation. (used in names & descriptions) + * + * Why universal? Both **existing slash commands** & **unregistered templates** can be converted to this type. + */ +export interface ODSlashCommandUniversalTranslation { + /**The language code or locale of this language. */ + language:`${discord.Locale}`, + /**The translation of the name in this language. */ + value:string +} + +/**## ODSlashCommandUniversalOptionChoice `interface` + * A universal template for a slash command option choice. (used in `string` options) + * + * Why universal? Both **existing slash commands** & **unregistered templates** can be converted to this type. + */ +export interface ODSlashCommandUniversalOptionChoice { + /**The name of this choice. */ + name:string, + /**All localized names of this choice. */ + nameLocalizations:readonly ODSlashCommandUniversalTranslation[], + /**The value of this choice. */ + value:string +} + +/**## ODSlashCommandUniversalOption `interface` + * A universal template for a slash command option. + * + * Why universal? Both **existing slash commands** & **unregistered templates** can be converted to this type. + */ +export interface ODSlashCommandUniversalOption { + /**The type of this option. */ + type:discord.ApplicationCommandOptionType, + /**The name of this option. */ + name:string, + /**All localized names of this option. */ + nameLocalizations:readonly ODSlashCommandUniversalTranslation[], + /**The description of this option. */ + description:string, + /**All localized descriptions of this option. */ + descriptionLocalizations:readonly ODSlashCommandUniversalTranslation[], + /**Is this option required? */ + required:boolean, + + /**Is autocomplete enabled in this option? */ + autocomplete:boolean|null, + /**Choices for this option (only when type is `string`) */ + choices:ODSlashCommandUniversalOptionChoice[], + /**A list of sub-options for this option (only when type is `subCommand` or `subCommandGroup`) */ + options:readonly ODSlashCommandUniversalOption[], + /**A list of allowed channel types for this option (only when type is `channel`) */ + channelTypes:readonly discord.ChannelType[], + /**The minimum amount required for this option (only when type is `number` or `integer`) */ + minValue:number|null, + /**The maximum amount required for this option (only when type is `number` or `integer`) */ + maxValue:number|null, + /**The minimum length required for this option (only when type is `string`) */ + minLength:number|null, + /**The maximum length required for this option (only when type is `string`) */ + maxLength:number|null +} + +/**## ODSlashCommandUniversalCommand `interface` + * A universal template for a slash command. + * + * Why universal? Both **existing slash commands** & **unregistered templates** can be converted to this type. + */ +export interface ODSlashCommandUniversalCommand { + /**The type of this command. (required => `ChatInput`) */ + type:discord.ApplicationCommandType.ChatInput, + /**The name of this command. */ + name:string, + /**All localized names of this command. */ + nameLocalizations:readonly ODSlashCommandUniversalTranslation[], + /**The description of this command. */ + description:string, + /**All localized descriptions of this command. */ + descriptionLocalizations:readonly ODSlashCommandUniversalTranslation[], + /**The id of the guild this command is registered in. */ + guildId:string|null, + /**Is this command for 18+ users only? */ + nsfw:boolean, + /**A list of options for this command. */ + options:readonly ODSlashCommandUniversalOption[], + /**A bitfield of the user permissions required to use this command. */ + defaultMemberPermissions:bigint, + /**Is this command available in DM? */ + dmPermission:boolean, + /**A list of contexts where you can install this command. */ + integrationTypes:readonly discord.ApplicationIntegrationType[], + /**A list of contexts where you can use this command. */ + contexts:readonly discord.InteractionContextType[] +} + +/**## ODSlashCommandBuilder `interface` + * The builder for slash commands. Here you can add options to the command. + */ +export interface ODSlashCommandBuilder extends discord.ChatInputApplicationCommandData { + /**@deprecated `dmPermission` is deprecated. Use `context` instead! (Not using contexts might result in the slash command being re-registered on every startup!) */ + dmPermission?:boolean + /**This field is required in Open Ticket for future compatibility. */ + integrationTypes:discord.ApplicationIntegrationType[], + /**This field is required in Open Ticket for future compatibility. */ + contexts:discord.InteractionContextType[] +} + +export class ODSlashCommandComparator { + /**Convert a `discord.ApplicationCommandOptionChoiceData` to a universal Open Ticket slash command option choice object for comparison. */ + #convertOptionChoice(choice:discord.ApplicationCommandOptionChoiceData): ODSlashCommandUniversalOptionChoice { + const nameLoc = choice.nameLocalizations ?? {} + return { + name:choice.name, + nameLocalizations:Object.keys(nameLoc).map((key) => {return {language:key as `${discord.Locale}`,value:nameLoc[key]}}), + value:choice.value + } + } + /**Convert a `discord.ApplicationCommandOptionData` to a universal Open Ticket slash command option object for comparison. */ + #convertBuilderOption(option:discord.ApplicationCommandOptionData): ODSlashCommandUniversalOption { + const nameLoc = option.nameLocalizations ?? {} + const descLoc = option.descriptionLocalizations ?? {} + return { + type:option.type, + name:option.name, + nameLocalizations:Object.keys(nameLoc).map((key) => {return {language:key as `${discord.Locale}`,value:nameLoc[key]}}), + description:option.description, + descriptionLocalizations:Object.keys(descLoc).map((key) => {return {language:key as `${discord.Locale}`,value:descLoc[key]}}), + required:(option.type != discord.ApplicationCommandOptionType.SubcommandGroup && option.type != discord.ApplicationCommandOptionType.Subcommand && option.required) ? true : false, + + autocomplete:option.autocomplete ?? false, + choices:(option.type == discord.ApplicationCommandOptionType.String && !option.autocomplete && option.choices) ? option.choices.map((choice) => this.#convertOptionChoice(choice)) : [], + options:((option.type == discord.ApplicationCommandOptionType.SubcommandGroup || option.type == discord.ApplicationCommandOptionType.Subcommand) && option.options) ? option.options.map((opt) => this.#convertBuilderOption(opt)) : [], + channelTypes:(option.type == discord.ApplicationCommandOptionType.Channel && option.channelTypes) ? option.channelTypes : [], + minValue:(option.type == discord.ApplicationCommandOptionType.Number && option.minValue) ? option.minValue : null, + maxValue:(option.type == discord.ApplicationCommandOptionType.Number && option.maxValue) ? option.maxValue : null, + minLength:(option.type == discord.ApplicationCommandOptionType.String && option.minLength) ? option.minLength : null, + maxLength:(option.type == discord.ApplicationCommandOptionType.String && option.maxLength) ? option.maxLength : null + } + } + /**Convert a `discord.ApplicationCommandOption` to a universal Open Ticket slash command option object for comparison. */ + #convertCommandOption(option:discord.ApplicationCommandOption): ODSlashCommandUniversalOption { + const nameLoc = option.nameLocalizations ?? {} + const descLoc = option.descriptionLocalizations ?? {} + + return { + type:option.type, + name:option.name, + nameLocalizations:Object.keys(nameLoc).map((key) => {return {language:key as `${discord.Locale}`,value:nameLoc[key]}}), + description:option.description, + descriptionLocalizations:Object.keys(descLoc).map((key) => {return {language:key as `${discord.Locale}`,value:descLoc[key]}}), + required:(option.type != discord.ApplicationCommandOptionType.SubcommandGroup && option.type != discord.ApplicationCommandOptionType.Subcommand && option.required) ? true : false, + + autocomplete:option.autocomplete ?? false, + choices:(option.type == discord.ApplicationCommandOptionType.String && !option.autocomplete && option.choices) ? option.choices.map((choice) => this.#convertOptionChoice(choice)) : [], + options:((option.type == discord.ApplicationCommandOptionType.SubcommandGroup || option.type == discord.ApplicationCommandOptionType.Subcommand) && option.options) ? option.options.map((opt) => this.#convertBuilderOption(opt)) : [], + channelTypes:(option.type == discord.ApplicationCommandOptionType.Channel && option.channelTypes) ? option.channelTypes : [], + minValue:(option.type == discord.ApplicationCommandOptionType.Number && option.minValue) ? option.minValue : null, + maxValue:(option.type == discord.ApplicationCommandOptionType.Number && option.maxValue) ? option.maxValue : null, + minLength:(option.type == discord.ApplicationCommandOptionType.String && option.minLength) ? option.minLength : null, + maxLength:(option.type == discord.ApplicationCommandOptionType.String && option.maxLength) ? option.maxLength : null + } + } + /**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'!") + const nameLoc = builder.nameLocalizations ?? {} + const descLoc = builder.descriptionLocalizations ?? {} + return { + type:1, + name:builder.name, + nameLocalizations:Object.keys(nameLoc).map((key) => {return {language:key as `${discord.Locale}`,value:nameLoc[key]}}), + description:builder.description, + descriptionLocalizations:Object.keys(descLoc).map((key) => {return {language:key as `${discord.Locale}`,value:descLoc[key]}}), + guildId:guildId, + nsfw:builder.nsfw ?? false, + options:builder.options ? builder.options.map((opt) => this.#convertBuilderOption(opt)) : [], + defaultMemberPermissions:discord.PermissionsBitField.resolve(builder.defaultMemberPermissions ?? ["ViewChannel"]), + dmPermission:(builder.contexts && builder.contexts.includes(discord.InteractionContextType.BotDM)) ?? false, + integrationTypes:builder.integrationTypes ?? [discord.ApplicationIntegrationType.GuildInstall], + contexts:builder.contexts ?? [] + } + } + /**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'!") + const nameLoc = cmd.nameLocalizations ?? {} + const descLoc = cmd.descriptionLocalizations ?? {} + return { + type:1, + name:cmd.name, + nameLocalizations:Object.keys(nameLoc).map((key) => {return {language:key as `${discord.Locale}`,value:nameLoc[key]}}), + description:cmd.description, + descriptionLocalizations:Object.keys(descLoc).map((key) => {return {language:key as `${discord.Locale}`,value:descLoc[key]}}), + guildId:cmd.guildId, + nsfw:cmd.nsfw, + options:cmd.options ? cmd.options.map((opt) => this.#convertCommandOption(opt)) : [], + defaultMemberPermissions:discord.PermissionsBitField.resolve(cmd.defaultMemberPermissions ?? ["ViewChannel"]), + dmPermission:(cmd.contexts && cmd.contexts.includes(discord.InteractionContextType.BotDM)) ? true : false, + integrationTypes:cmd.integrationTypes ?? [discord.ApplicationIntegrationType.GuildInstall], + contexts:cmd.contexts ?? [] + } + } + /**Returns `true` when the 2 slash command options are the same. */ + compareOption(optA:ODSlashCommandUniversalOption,optB:ODSlashCommandUniversalOption): boolean { + if (optA.name != optB.name) return false + if (optA.description != optB.description) return false + if (optA.type != optB.type) return false + if (optA.required != optB.required) return false + if (optA.autocomplete != optB.autocomplete) return false + if (optA.minValue != optB.minValue) return false + if (optA.maxValue != optB.maxValue) return false + if (optA.minLength != optB.minLength) return false + if (optA.maxLength != optB.maxLength) return false + + //nameLocalizations + if (optA.nameLocalizations.length != optB.nameLocalizations.length) return false + if (!optA.nameLocalizations.every((nameA) => { + const nameB = optB.nameLocalizations.find((nameB) => nameB.language == nameA.language) + if (!nameB || nameA.value != nameB.value) return false + else return true + })) return false + + //descriptionLocalizations + if (optA.descriptionLocalizations.length != optB.descriptionLocalizations.length) return false + if (!optA.descriptionLocalizations.every((descA) => { + const descB = optB.descriptionLocalizations.find((descB) => descB.language == descA.language) + if (!descB || descA.value != descB.value) return false + else return true + })) return false + + //choices + if (optA.choices.length != optB.choices.length) return false + if (!optA.choices.every((choiceA,index) => { + const choiceB = optB.choices[index] + if (choiceA.name != choiceB.name) return false + if (choiceA.value != choiceB.value) return false + + //nameLocalizations + if (choiceA.nameLocalizations.length != choiceB.nameLocalizations.length) return false + if (!choiceA.nameLocalizations.every((nameA) => { + const nameB = choiceB.nameLocalizations.find((nameB) => nameB.language == nameA.language) + if (!nameB || nameA.value != nameB.value) return false + else return true + })) return false + + return true + })) return false + + //channelTypes + if (optA.channelTypes.length != optB.channelTypes.length) return false + if (!optA.channelTypes.every((typeA) => { + return optB.channelTypes.includes(typeA) + })) return false + + //options + if (optA.options.length != optB.options.length) return false + if (!optA.options.every((subOptA,index) => { + return this.compareOption(subOptA,optB.options[index]) + })) return false + + return true + } + /**Returns `true` when the 2 slash commands are the same. */ + compare(cmdA:ODSlashCommandUniversalCommand,cmdB:ODSlashCommandUniversalCommand): boolean { + if (cmdA.name != cmdB.name) return false + if (cmdA.description != cmdB.description) return false + if (cmdA.type != cmdB.type) return false + if (cmdA.nsfw != cmdB.nsfw) return false + if (cmdA.guildId != cmdB.guildId) return false + if (cmdA.dmPermission != cmdB.dmPermission) return false + if (cmdA.defaultMemberPermissions != cmdB.defaultMemberPermissions) return false + + //nameLocalizations + if (cmdA.nameLocalizations.length != cmdB.nameLocalizations.length) return false + if (!cmdA.nameLocalizations.every((nameA) => { + const nameB = cmdB.nameLocalizations.find((nameB) => nameB.language == nameA.language) + if (!nameB || nameA.value != nameB.value) return false + else return true + })) return false + + //descriptionLocalizations + if (cmdA.descriptionLocalizations.length != cmdB.descriptionLocalizations.length) return false + if (!cmdA.descriptionLocalizations.every((descA) => { + const descB = cmdB.descriptionLocalizations.find((descB) => descB.language == descA.language) + if (!descB || descA.value != descB.value) return false + else return true + })) return false + + //contexts + if (cmdA.contexts.length != cmdB.contexts.length) return false + if (!cmdA.contexts.every((contextA) => { + return cmdB.contexts.includes(contextA) + })) return false + + //integrationTypes + if (cmdA.integrationTypes.length != cmdB.integrationTypes.length) return false + if (!cmdA.integrationTypes.every((integrationA) => { + return cmdB.integrationTypes.includes(integrationA) + })) return false + + //options + if (cmdA.options.length != cmdB.options.length) return false + if (!cmdA.options.every((optA,index) => { + return this.compareOption(optA,cmdB.options[index]) + })) return false + + return true + } +} + /**## ODSlashCommandInteractionCallback `type` * Callback for the slash command interaction listener. */ export type ODSlashCommandInteractionCallback = (interaction:discord.ChatInputCommandInteraction,cmd:ODSlashCommand) => void +/**## ODSlashCommandRegisteredResult `type` + * The result which will be returned when getting all (un)registered slash commands from the manager. + */ +export type ODSlashCommandRegisteredResult = { + /**A list of all registered commands. */ + registered:{ + /**The instance (`ODSlashCommand`) from this command. */ + instance:ODSlashCommand, + /**The (universal) slash command object/template of this command. */ + cmd:ODSlashCommandUniversalCommand, + /**Does this command require an update? */ + requiresUpdate:boolean + }[], + /**A list of all unregistered commands. */ + unregistered:{ + /**The instance (`ODSlashCommand`) from this command. */ + instance:ODSlashCommand, + /**The (universal) slash command object/template of this command. */ + cmd:null, + /**Does this command require an update? */ + requiresUpdate:true + }[], + /**A list of all unused commands (not found in `ODSlashCommandManager`). */ + unused:{ + /**The instance (`ODSlashCommand`) from this command. */ + instance:null, + /**The (universal) slash command object/template of this command. */ + cmd:ODSlashCommandUniversalCommand, + /**Does this command require an update? */ + requiresUpdate:false + }[] +} + /**## ODSlashCommandManager `class` * This is an open ticket client slash manager. * @@ -418,7 +761,7 @@ export class ODSlashCommandManager extends ODManager { /**Alias to open ticket debugger. */ #debug: ODDebugger - /**Copy of discord.js client. */ + /**Refrerence to discord.js client. */ manager: ODClientManager /**Discord.js application commands manager. */ commandManager: discord.ApplicationCommandManager|null @@ -426,6 +769,8 @@ export class ODSlashCommandManager extends ODManager { #interactionListeners: {name:string|RegExp, callback:ODSlashCommandInteractionCallback}[] = [] /**Set the soft limit for maximum amount of listeners. A warning will be shown when there are more listeners than this limit. */ listenerLimit: number = 100 + /**A utility class used to compare 2 slash commands with each other. */ + comparator: ODSlashCommandComparator = new ODSlashCommandComparator() constructor(debug:ODDebugger, manager:ODClientManager){ super(debug,"slash command") @@ -434,41 +779,83 @@ export class ODSlashCommandManager extends ODManager { this.commandManager = (manager.client.application) ? manager.client.application.commands : null } - /**Create all commands that don't exist yet. (global by default OR guildId for per-server) */ - async createNewCommands(guildId?:string){ - if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") - const cmds = await this.#existsCmd(guildId) - - let i = 0 - while (i < cmds.nonExisting.length){ - await this.#createCmd(cmds.nonExisting[i]) - this.#debug.debug("Created new slash command",[{key:"id",value:cmds.nonExisting[i].id.value},{key:"name",value:cmds.nonExisting[i].name}]) - i++ - } - } - /**Update all commands that already exist. (global by default OR guildId for per-server) */ - async updateExistingCommands(guildId?:string,force?:boolean){ - if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") - const cmds = await this.#existsCmd(guildId) - const filtered = cmds.existing.filter((cmd) => (cmd.requiresUpdate == true || force)) + /**Get all registered & unregistered slash commands. */ + async getAllRegisteredCommands(guildId?:string): Promise { + if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") - for (const cmd of filtered){ - await this.#createCmd(cmd.cmd) - this.#debug.debug("Updated existing slash command",[ - {key:"id",value:cmd.cmd.id.value}, - {key:"name",value:cmd.cmd.name}, - {key:"force",value:force ? "true" : "false"} + const cmds = (await this.commandManager.fetch({guildId})).toJSON() + const registered: {instance:ODSlashCommand, cmd:ODSlashCommandUniversalCommand, requiresUpdate:boolean}[] = [] + const unregistered: {instance:ODSlashCommand, cmd:null, requiresUpdate:true}[] = [] + const unused: {instance:null, cmd:ODSlashCommandUniversalCommand, requiresUpdate:false}[] = [] + + await this.loopAll((instance) => { + if (guildId && instance.guildId != guildId) return + + const index = cmds.findIndex((cmd) => cmd.name == instance.name) + const cmd = cmds[index] + cmds.splice(index,1) + if (cmd){ + //command is registered (and may need to be updated) + const universalBuilder = this.comparator.convertBuilder(instance.builder,instance.guildId) + const universalCmd = this.comparator.convertCommand(cmd) + const didChange = !this.comparator.compare(universalBuilder,universalCmd) + const requiresUpdate = didChange || (instance.requiresUpdate ? instance.requiresUpdate(universalCmd) : false) + registered.push({instance,cmd:universalCmd,requiresUpdate}) + + //command is not registered + }else unregistered.push({instance,cmd:null,requiresUpdate:true}) + }) + + cmds.forEach((cmd) => { + //command does not exist in the manager + unused.push({instance:null,cmd:this.comparator.convertCommand(cmd),requiresUpdate:false}) + }) + + return {registered,unregistered,unused} + } + /**Create all commands that are not registered yet.*/ + async createNewCommands(instances:ODSlashCommand[]){ + if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") + + for (const instance of instances){ + await this.createCmd(instance) + this.#debug.debug("Created new slash command",[ + {key:"id",value:instance.id.value}, + {key:"name",value:instance.name} ]) } } - /**Remove all commands that exist but aren't used by open ticket. (global by default OR guildId for per-server) */ - async removeUnusedCommands(guildId?:string){ + /**Update all commands that are already registered. */ + async updateExistingCommands(instances:ODSlashCommand[]){ if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") - const cmds = (await this.#unusedCmd(guildId)).map((cmd) => cmd.name) - await this.#removeCmd(cmds,guildId) + + for (const instance of instances){ + await this.createCmd(instance) + this.#debug.debug("Updated existing slash command",[{key:"id",value:instance.id.value},{key:"name",value:instance.name}]) + } } - /**Create a slash command from an `ODSlashCommand` class */ - async #createCmd(cmd:ODSlashCommand){ + /**Remove all commands that are registered but unused by Open Ticket. */ + async removeUnusedCommands(instances:ODSlashCommandUniversalCommand[],guildId?:string){ + if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") + if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") + + const cmds = await this.commandManager.fetch({guildId}) + + for (const instance of instances){ + const cmd = cmds.find((cmd) => cmd.name == instance.name) + if (cmd){ + try { + await cmd.delete() + this.#debug.debug("Removed existing slash command",[{key:"name",value:cmd.name},{key:"guildId",value:guildId ?? "/"}]) + }catch(err){ + process.emit("uncaughtException",err) + throw new ODSystemError("Failed to delete slash command '/"+cmd.name+"'!") + } + } + } + } + /**Create a slash command. **(SYSTEM ONLY)** => Use `ODSlashCommandManager` for registering commands the default way! */ + async createCmd(cmd:ODSlashCommand){ if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") try { await this.commandManager.create(cmd.builder,(cmd.guildId ?? undefined)) @@ -477,107 +864,6 @@ export class ODSlashCommandManager extends ODManager { throw new ODSystemError("Failed to register slash command '/"+cmd.name+"'!") } } - /**Remove slash cmds by name */ - async #removeCmd(names:string[],guildId?:string){ - if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") - - const cmds = await this.commandManager.fetch({guildId}) - - cmds?.forEach((cmd) => { - if (!names.includes(cmd.name)) return - cmd.delete() - this.#debug.debug("Removed existing slash command",[{key:"name",value:cmd.name}]) - }) - } - /**Get all existing & non-existing slash commands. */ - async #existsCmd(guildId?:string){ - if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") - - const cmds = await this.commandManager.fetch({guildId}) - const existing: {cmd:ODSlashCommand, requiresUpdate:boolean}[] = [] - const nonExisting: ODSlashCommand[] = [] - - await this.loopAll((cmd) => { - if (guildId && cmd.guildId != guildId) return - const result = cmds.find((cmddata) => cmddata.name == cmd.name) - if (result){ - //command already exists (and may need to be updated) - const requiresUpdate = cmd.requiresUpdate ? cmd.requiresUpdate({ - name:result.name, - description:result.description, - options:result.options as readonly discord.ApplicationCommandOptionData[], - nsfw:result.nsfw, - dmPermission:result.dmPermission ?? undefined, - defaultMemberPermissions:result.defaultMemberPermissions, - nameLocalizations:result.nameLocalizations ?? undefined, - descriptionLocalizations:result.descriptionLocalizations ?? undefined - }) : false - existing.push({cmd,requiresUpdate}) - - //command doesn't exists yet - }else nonExisting.push(cmd) - }) - - return {existing,nonExisting} - } - /**Get all unused slash commands. */ - async #unusedCmd(guildId?:string){ - if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") - - const cmds = await this.commandManager.fetch({guildId}) - const unused: discord.ApplicationCommand[] = [] - - const allCommands = this.getAll() - cmds.forEach((cmddata) => { - if (guildId && cmddata.guildId != guildId) return - - if (!allCommands.find((cmd) => { - if (cmd.name != cmddata.name) return false - if (cmd.builder.description != cmddata.description) return false - return this.#checkUnusedOptions(cmddata.options,cmd.builder.options ?? []) - - })) unused.push(cmddata) - }) - - return unused - } - /**Returns `true` if the options are the same in both arrays. It will work recursively! */ - #checkUnusedOptions(currentOptions:readonly discord.ApplicationCommandOption[], newOptions:readonly discord.ApplicationCommandOptionData[]){ - if ((!newOptions || newOptions.length == 0) && currentOptions.length == 0) return true - else if (newOptions && newOptions.length != currentOptions.length) return false - - if (!currentOptions.every((currentOpt,index) => { - const newOpt = newOptions[index] - if (newOpt.name != currentOpt.name) return false - if (newOpt.type != currentOpt.type) return false - if (newOpt.description != currentOpt.description) return false - - if (newOpt.type == discord.ApplicationCommandOptionType.Number && currentOpt.type == discord.ApplicationCommandOptionType.Number){ - //check for min & max values when type is number - if (newOpt.minValue != currentOpt.minValue) return false - if (newOpt.maxValue != currentOpt.maxValue) return false - } - if (newOpt.type == discord.ApplicationCommandOptionType.String && currentOpt.type == discord.ApplicationCommandOptionType.String){ - //check for min & max length values when type is string - if (newOpt.minLength != currentOpt.minLength) return false - if (newOpt.maxLength != currentOpt.maxLength) return false - } - - //check for required normal options - if (currentOpt.type != discord.ApplicationCommandOptionType.SubcommandGroup && currentOpt.type != discord.ApplicationCommandOptionType.Subcommand && newOpt.type != discord.ApplicationCommandOptionType.SubcommandGroup && newOpt.type != discord.ApplicationCommandOptionType.Subcommand){ - if (currentOpt.required != newOpt.required) return false - - //check for sub-options in subcommands - }else if ((currentOpt.type == discord.ApplicationCommandOptionType.SubcommandGroup && newOpt.type == discord.ApplicationCommandOptionType.SubcommandGroup) || (currentOpt.type == discord.ApplicationCommandOptionType.Subcommand && newOpt.type == discord.ApplicationCommandOptionType.Subcommand)){ - if (currentOpt.options && newOpt.options){ - return this.#checkUnusedOptions(currentOpt.options,newOpt.options) - } - } - - return true - })) return false - return true - } /**Start listening to the discord.js client `interactionCreate` event. */ startListeningToInteractions(){ this.manager.client.on("interactionCreate",(interaction) => { @@ -612,15 +898,10 @@ export class ODSlashCommandManager extends ODManager { } } -/**## ODSlashCommandBuilder `interface` - * The builder for slash commands. Here you can add options to the command. - */ -export interface ODSlashCommandBuilder extends discord.ChatInputApplicationCommandData {} - /**## ODSlashCommandUpdateFunction `type` * The function responsible for updating slash commands when they already exist. */ -export type ODSlashCommandUpdateFunction = (current:ODSlashCommandBuilder) => boolean +export type ODSlashCommandUpdateFunction = (command:ODSlashCommandUniversalCommand) => boolean /**## ODSlashCommand `class` * This is an open ticket slash command. diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index 25f5bf0..ea334fb 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -83,6 +83,8 @@ export interface ODDefaults { slashCommandRegistering:boolean, /**When enabled, the bot is forced to re-register all slash commands in the server. This can be used in case of a auto-update malfunction. */ forceSlashCommandRegistration:boolean, + /**When enabled, the bot is allowed to unregister all slash commands which aren't used in Open Ticket. Disable this if you don't want to use the Open Ticket `ODSlashCommand` classes. */ + allowSlashCommandRemoval:boolean, /**Load the default open ticket text commands. */ textCommandLoading:boolean, @@ -265,6 +267,7 @@ export class ODDefaultsManager { slashCommandLoading:true, slashCommandRegistering:true, forceSlashCommandRegistration:false, + allowSlashCommandRemoval:true, textCommandLoading:true, questionLoading:true, diff --git a/src/index.ts b/src/index.ts index 6d94def..ac48088 100644 --- a/src/index.ts +++ b/src/index.ts @@ -394,15 +394,13 @@ const main = async () => { openticket.log("Registering slash commands... (this can take up to 2 minutes)","system") await openticket.events.get("onSlashCommandRegister").emit([openticket.client.slashCommands,openticket.client]) if (openticket.defaults.getDefault("slashCommandRegistering")){ - //GLOBAL - await openticket.client.slashCommands.removeUnusedCommands() //remove all commands that aren't used - await openticket.client.slashCommands.createNewCommands() //create all new commands that don't exist yet - await openticket.client.slashCommands.updateExistingCommands(undefined,openticket.defaults.getDefault("forceSlashCommandRegistration")) //update all commands that need to be re-registered + //get all commands that are already registered in the bot + const cmds = await openticket.client.slashCommands.getAllRegisteredCommands() - //DEFAULT SERVER - await openticket.client.slashCommands.removeUnusedCommands(serverId) //remove all commands that aren't used - await openticket.client.slashCommands.createNewCommands(serverId) //create all new commands that don't exist yet - await openticket.client.slashCommands.updateExistingCommands(serverId) //update all commands that need to be re-registered + //remove unused cmds, create new cmds & update existing cmds + if (openticket.defaults.getDefault("allowSlashCommandRemoval")) await openticket.client.slashCommands.removeUnusedCommands(cmds.unused.map((cmd) => cmd.cmd)) + await openticket.client.slashCommands.createNewCommands(cmds.unregistered.map((cmd) => cmd.instance)) + await openticket.client.slashCommands.updateExistingCommands(cmds.registered.filter((cmd) => cmd.requiresUpdate || openticket.defaults.getDefault("forceSlashCommandRegistration")).map((cmd) => cmd.instance)) await openticket.events.get("afterSlashCommandsRegistered").emit([openticket.client.slashCommands,openticket.client]) } From c3474fb017e3a8c69478fb5918d49ba2abca30e1 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 18 Jan 2025 20:41:12 +0100 Subject: [PATCH 096/157] Made built-in cmds compatible with slash update --- src/data/framework/commandLoader.ts | 99 ++++++++++++++++------------- 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/src/data/framework/commandLoader.ts b/src/data/framework/commandLoader.ts index ee0e326..3ecc123 100644 --- a/src/data/framework/commandLoader.ts +++ b/src/data/framework/commandLoader.ts @@ -36,7 +36,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"help", description:lang.getTranslation("commands.help"), - dmPermission:true + contexts:[discord.InteractionContextType.BotDM,discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], })) //PANEL @@ -44,7 +45,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"panel", description:lang.getTranslation("commands.panel"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"id", @@ -62,15 +64,12 @@ export const loadAllSlashCommands = async () => { ] },(current) => { //check if this slash command needs to be updated - if (!current.options) return true - const idOption = current.options.find((opt) => opt.name == "id" && opt.type == acot.String) as discord.ApplicationCommandStringOptionData|undefined - if (!idOption || !idOption.choices || idOption.choices.length != panelChoices.length) return true - else if (!panelChoices.every((panel) => { - if (!idOption.choices) return false - else if (!idOption.choices.find((choice) => choice.value == panel.value && choice.name == panel.name)) return false - else return true + const idOption = current.options.find((opt) => opt.name == "id" && opt.type == acot.String) + if (!idOption || idOption.choices.length != panelChoices.length) return true + if (!panelChoices.every((panel) => { + return (idOption.choices.find((c) => c.value == panel.value && c.name == panel.name)) ? true : false })) return true - else return false + return false })) //TICKET (when enabled) @@ -78,7 +77,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"ticket", description:lang.getTranslation("commands.ticket"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"id", @@ -90,15 +90,12 @@ export const loadAllSlashCommands = async () => { ] },(current) => { //check if this slash command needs to be updated - if (!current.options) return true - const idOption = current.options.find((opt) => opt.name == "id" && opt.type == acot.String) as discord.ApplicationCommandStringOptionData|undefined - if (!idOption || !idOption.choices || idOption.choices.length != ticketChoices.length) return true - else if (!ticketChoices.every((ticket) => { - if (!idOption.choices) return false - else if (!idOption.choices.find((choice) => choice.value == ticket.value && choice.name == ticket.name)) return false - else return true + const idOption = current.options.find((opt) => opt.name == "id" && opt.type == acot.String) + if (!idOption || idOption.choices.length != ticketChoices.length) return true + if (!ticketChoices.every((ticket) => { + return (idOption.choices.find((c) => c.value == ticket.value && c.name == ticket.name)) ? true : false })) return true - else return false + return false })) //CLOSE @@ -106,7 +103,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"close", description:lang.getTranslation("commands.close"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"reason", @@ -122,7 +120,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"delete", description:lang.getTranslation("commands.delete"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"reason", @@ -142,7 +141,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"delete", description:lang.getTranslation("commands.delete"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"reason", @@ -158,7 +158,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"reopen", description:lang.getTranslation("commands.reopen"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"reason", @@ -174,7 +175,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"claim", description:lang.getTranslation("commands.claim"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"user", @@ -196,7 +198,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"unclaim", description:lang.getTranslation("commands.unclaim"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"reason", @@ -212,7 +215,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"pin", description:lang.getTranslation("commands.pin"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"reason", @@ -228,7 +232,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"unpin", description:lang.getTranslation("commands.unpin"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"reason", @@ -244,7 +249,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"move", description:lang.getTranslation("commands.move"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"id", @@ -262,15 +268,12 @@ export const loadAllSlashCommands = async () => { ] },(current) => { //check if this slash command needs to be updated - if (!current.options) return true - const idOption = current.options.find((opt) => opt.name == "id" && opt.type == acot.String) as discord.ApplicationCommandStringOptionData|undefined - if (!idOption || !idOption.choices || idOption.choices.length != ticketChoices.length) return true - else if (!ticketChoices.every((ticket) => { - if (!idOption.choices) return false - else if (!idOption.choices.find((choice) => choice.value == ticket.value && choice.name == ticket.name)) return false - else return true + const idOption = current.options.find((opt) => opt.name == "id" && opt.type == acot.String) + if (!idOption || idOption.choices.length != ticketChoices.length) return true + if (!ticketChoices.every((ticket) => { + return (idOption.choices.find((c) => c.value == ticket.value && c.name == ticket.name)) ? true : false })) return true - else return false + return false })) //RENAME @@ -278,7 +281,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"rename", description:lang.getTranslation("commands.rename"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"name", @@ -301,7 +305,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"add", description:lang.getTranslation("commands.add"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"user", @@ -323,7 +328,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"remove", description:lang.getTranslation("commands.remove"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"user", @@ -345,7 +351,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"blacklist", description:lang.getTranslation("commands.blacklist"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"view", @@ -411,7 +418,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"stats", description:lang.getTranslation("commands.stats"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"reset", @@ -465,7 +473,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"clear", description:lang.getTranslation("commands.clear"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"filter", @@ -491,7 +500,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"autoclose", description:lang.getTranslation("commands.autoclose"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"disable", @@ -534,7 +544,8 @@ export const loadAllSlashCommands = async () => { type:act.ChatInput, name:"autodelete", description:lang.getTranslation("commands.autodelete"), - dmPermission:false, + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], options:[ { name:"disable", From ff23b0e89e3b742e80d9db8b2568bdeb90a4be2f Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 18 Jan 2025 21:53:53 +0100 Subject: [PATCH 097/157] Added comment to dump command --- src/core/startup/dump.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/core/startup/dump.ts b/src/core/startup/dump.ts index 1929e9f..83c5656 100644 --- a/src/core/startup/dump.ts +++ b/src/core/startup/dump.ts @@ -2,7 +2,26 @@ import {openticket, api, utilities} from "../../index" import * as discord from "discord.js" import * as fs from "fs" + +/** WHAT IS THIS?? + * This is the '!OPENTICKET:dump' command. + * It's a utility command which can only be used by the creator of Open Ticket or the owner of the bot. + * This command will send the `otdebug.txt` file in DM. It's not dangerous as the `otdebug.txt` file doesn't contain any sensitive data (only logs). + * + * WHY DOES IT EXIST?? + * This command can be used to quickly get the `otdebug.txt` file without having access to the hosting + * in case you're helping someone with setting up (or debugging) Open Ticket. + * + * CAN I DISABLE IT?? + * If you want to turn it off, you can always do it below this message! + */ + +///////// DISABLE DUMP COMMAND ///////// +const disableDumpCommand = false +//////////////////////////////////////// + export const loadDumpCommand = () => { + if (disableDumpCommand) return openticket.client.textCommands.add(new api.ODTextCommand("openticket:dump",{ allowBots:false, guildPermission:true, From 9da823aa4b7fd0a7c204a09478c2d9fcb3a44fda Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 19 Jan 2025 00:17:39 +0100 Subject: [PATCH 098/157] Added new progress bars API & classes --- src/core/api/api.ts | 2 + src/core/api/defaults/event.ts | 8 + src/core/api/defaults/progressbar.ts | 82 +++++++++ src/core/api/defaults/session.ts | 2 +- src/core/api/main.ts | 6 +- src/core/api/modules/defaults.ts | 6 + src/core/api/modules/progressbar.ts | 217 ++++++++++++++++++++++++ src/data/framework/eventLoader.ts | 6 + src/data/framework/progressBarLoader.ts | 7 + src/index.ts | 15 ++ 10 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 src/core/api/defaults/progressbar.ts create mode 100644 src/core/api/modules/progressbar.ts create mode 100644 src/data/framework/progressBarLoader.ts diff --git a/src/core/api/api.ts b/src/core/api/api.ts index 7f393a0..10e7906 100644 --- a/src/core/api/api.ts +++ b/src/core/api/api.ts @@ -25,6 +25,7 @@ export * from "./modules/code" export * from "./modules/cooldown" export * from "./modules/post" export * from "./modules/verifybar" +export * from "./modules/progressbar" export * from "./modules/startscreen" //OPENTICKET DEFAULT MODULES @@ -48,6 +49,7 @@ export * from "./defaults/worker" export * from "./defaults/code" export * from "./defaults/cooldown" export * from "./defaults/post" +export * from "./defaults/progressbar" export * from "./defaults/startscreen" export * from "./defaults/console" diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts index 3e70d00..edab225 100644 --- a/src/core/api/defaults/event.ts +++ b/src/core/api/defaults/event.ts @@ -32,6 +32,7 @@ import { ODPostManager_Default } from "./post" import { ODVerifyBarManager_Default } from "./verifybar" import { ODStartScreenManager_Default } from "./startscreen" import { ODLiveStatusManager_Default } from "./console" +import { ODProgressBarManager_Default, ODProgressBarRendererManager_Default } from "./progressbar" //OPEN TICKET MODULES import { ODOptionManager, ODTicketOption } from "../openticket/option" @@ -56,11 +57,18 @@ export interface ODEventIds_Default { "onPluginClassLoad": ODEvent_Default<(classes:ODPluginClassManager_Default, plugins:ODPluginManager_Default) => ODPromiseVoid> "afterPluginClassesLoaded": ODEvent_Default<(classes:ODPluginClassManager_Default, plugins:ODPluginManager_Default) => ODPromiseVoid> + //flags "onFlagLoad": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> "afterFlagsLoaded": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> "onFlagInit": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> "afterFlagsInitiated": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> + //progres bars + "onProgressBarRendererLoad": ODEvent_Default<(renderers:ODProgressBarRendererManager_Default) => ODPromiseVoid> + "afterProgressBarRenderersLoaded": ODEvent_Default<(renderers:ODProgressBarRendererManager_Default) => ODPromiseVoid> + "onProgressBarLoad": ODEvent_Default<(progressbars:ODProgressBarManager_Default) => ODPromiseVoid> + "afterProgressBarsLoaded": ODEvent_Default<(progressbars:ODProgressBarManager_Default) => ODPromiseVoid> + //configs "onConfigLoad": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> "afterConfigsLoaded": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid> diff --git a/src/core/api/defaults/progressbar.ts b/src/core/api/defaults/progressbar.ts new file mode 100644 index 0000000..ff5df36 --- /dev/null +++ b/src/core/api/defaults/progressbar.ts @@ -0,0 +1,82 @@ +/////////////////////////////////////// +//DEFAULT PROGRESS BAR MODULE +/////////////////////////////////////// +import { ODValidId } from "../modules/base" +import { ODProgressBar, ODProgressBarManager, ODProgressBarRenderer, ODProgressBarRendererManager } from "../modules/progressbar" + + +/**## ODProgressBarRendererManagerIds_Default `type` + * This type is an array of ids available in the `ODProgressBarRendererManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODProgressBarRendererManagerIds_Default { + "test-progressbar-renderer":ODProgressBarRenderer<{}> +} + +/**## ODProgressBarRendererManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODProgressBarRendererManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.progressbars.renderers`! + */ +export class ODProgressBarRendererManager_Default extends ODProgressBarRendererManager { + get(id:ProgressBarId): ODProgressBarRendererManagerIds_Default[ProgressBarId] + get(id:ODValidId): ODProgressBarRenderer<{}>|null + + get(id:ODValidId): ODProgressBarRenderer<{}>|null { + return super.get(id) + } + + remove(id:ProgressBarId): ODProgressBarRendererManagerIds_Default[ProgressBarId] + remove(id:ODValidId): ODProgressBarRenderer<{}>|null + + remove(id:ODValidId): ODProgressBarRenderer<{}>|null { + return super.remove(id) + } + + exists(id:keyof ODProgressBarRendererManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODProgressBarManagerIds_Default `type` + * This type is an array of ids available in the `ODProgressBarManager_Default` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODProgressBarManagerIds_Default { + "test-progressbar":ODProgressBar +} + +/**## ODProgressBarManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODProgressBarManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `openticket.progressbars`! + */ +export class ODProgressBarManager_Default extends ODProgressBarManager { + declare renderers: ODProgressBarRendererManager_Default + + get(id:ProgressBarId): ODProgressBarManagerIds_Default[ProgressBarId] + get(id:ODValidId): ODProgressBar|null + + get(id:ODValidId): ODProgressBar|null { + return super.get(id) + } + + remove(id:ProgressBarId): ODProgressBarManagerIds_Default[ProgressBarId] + remove(id:ODValidId): ODProgressBar|null + + remove(id:ODValidId): ODProgressBar|null { + return super.remove(id) + } + + exists(id:keyof ODProgressBarManagerIds_Default): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} \ No newline at end of file diff --git a/src/core/api/defaults/session.ts b/src/core/api/defaults/session.ts index cce95ec..b7153cd 100644 --- a/src/core/api/defaults/session.ts +++ b/src/core/api/defaults/session.ts @@ -9,7 +9,7 @@ import { ODSession, ODSessionManager } from "../modules/session" * It's used to generate typescript declarations for this class. */ export interface ODSessionManagerIds_Default { - "test-session":ODSession + //"test-session":ODSession } /**## ODSessionManager_Default `default_class` diff --git a/src/core/api/main.ts b/src/core/api/main.ts index 5860bd9..498c0da 100644 --- a/src/core/api/main.ts +++ b/src/core/api/main.ts @@ -25,6 +25,7 @@ import { ODCodeManager_Default } from "./defaults/code" import { ODCooldownManager_Default } from "./defaults/cooldown" import { ODPostManager_Default } from "./defaults/post" import { ODVerifyBarManager_Default } from "./defaults/verifybar" +import { ODProgressBarManager_Default } from "./defaults/progressbar" import { ODStartScreenManager_Default } from "./defaults/startscreen" import { ODLiveStatusManager_Default } from "./defaults/console" @@ -65,6 +66,8 @@ export class ODMain { plugins: ODPluginManager_Default /**The manager that manages & checks all the console flags of the bot. (like `--debug`) */ flags: ODFlagManager_Default + /**The manager responsible for progress bars in the console. */ + progressbars: ODProgressBarManager_Default /**The manager that manages & contains all the config files of the bot. (like `config/general.json`) */ configs: ODConfigManager_Default /**The manager that manages & contains all the databases of the bot. (like `database/global.json`) */ @@ -136,9 +139,10 @@ export class ODMain { this.console = new ODConsoleManager(100,this.debugfile) this.debug = new ODDebugger(this.console) this.events = new ODEventManager_Default(this.debug) - + this.plugins = new ODPluginManager_Default(this.debug) this.flags = new ODFlagManager_Default(this.debug) + this.progressbars = new ODProgressBarManager_Default(this.debug) this.configs = new ODConfigManager_Default(this.debug) this.databases = new ODDatabaseManager_Default(this.debug) this.sessions = new ODSessionManager_Default(this.debug) diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index ea334fb..4aaa295 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -27,6 +27,10 @@ export interface ODDefaults { flagLoading:boolean, /**Enable the default initializer for open ticket flags. */ flagInitiating:boolean, + /**Load the default open ticket progress bar renderers. */ + progressBarRendererLoading:boolean, + /**Load the default open ticket progress bars. */ + progressBarLoading:boolean, /**Load the default open ticket configs. */ configLoading:boolean, /**Enable the default initializer for open ticket config. */ @@ -237,6 +241,8 @@ export class ODDefaultsManager { flagLoading:true, flagInitiating:true, + progressBarRendererLoading:true, + progressBarLoading:true, configLoading:true, configInitiating:true, databaseLoading:true, diff --git a/src/core/api/modules/progressbar.ts b/src/core/api/modules/progressbar.ts new file mode 100644 index 0000000..2a4209b --- /dev/null +++ b/src/core/api/modules/progressbar.ts @@ -0,0 +1,217 @@ +/////////////////////////////////////// +//PROGRESS BAR MODULE +/////////////////////////////////////// +import { ODSystemError, ODManager, ODManagerData, ODValidId } from "./base" +import { ODDebugger } from "./console" +import readline from "readline" + +/**## ODProgressBarRendererManager `class` + * This is an open ticket progress bar renderer manager. + * + * It is responsible for managing all console progress bar renderers in Open Ticket. + * + * A renderer is a function which will try to visualize the progress bar in the console. + */ +export class ODProgressBarRendererManager extends ODManager> { + constructor(debug:ODDebugger){ + super(debug,"progress bar renderer") + } +} + +/**## ODProgressBarManager `class` + * This is an open ticket progress bar manager. + * + * It is responsible for managing all console progress bars in Open Ticket. An example of this is the slash command registration progress bar. + * + * There are many types of progress bars available, but you can also create your own! + */ +export class ODProgressBarManager extends ODManager { + renderers: ODProgressBarRendererManager + + constructor(debug:ODDebugger){ + super(debug,"progress bar") + this.renderers = new ODProgressBarRendererManager(debug) + } +} + +/**## ODProgressBarRenderFunc `type` + * This is the render function for an Open Ticket console progress bar. + */ +export type ODProgressBarRenderFunc = (settings:Settings,min:number,max:number,value:number) => string + +/**## ODProgressBarRenderer `class` + * This is an open ticket console progress bar renderer. + * + * It is used to render a progress bar in the console of the bot. + * + * There are already a lot of default options available if you just want an easy progress bar! + */ +export class ODProgressBarRenderer extends ODManagerData { + settings: Settings + #render: ODProgressBarRenderFunc + + constructor(id:ODValidId,render:ODProgressBarRenderFunc,settings:Settings){ + super(id) + this.#render = render + this.settings = settings + } + + /**Render a progress bar using this renderer. */ + render(min:number,max:number,value:number){ + try { + return this.#render(this.settings,min,max,value) + }catch(err){ + process.emit("uncaughtException",err) + return "" + } + } +} + +/**## ODProgressBar `class` + * This is an open ticket console progress bar. + * + * It is used to create a simple or advanced progress bar in the console of the bot. + * These progress bars are not visible in the `otdebug.txt` file and should only be used as extra visuals. + * + * Use other classes as existing templates or create your own progress bar from scratch using this class. + */ +export class ODProgressBar extends ODManagerData { + /**The renderer of this progress bar. */ + renderer: ODProgressBarRenderer<{}> + /**Is this progress bar currently active? */ + #active: boolean = false + /**A list of listeners when the progress bar stops. */ + #stopListeners: Function[] = [] + /**The current value of the progress bar. */ + protected value: number + /**The minimum value of the progress bar. */ + min: number + /**The maximum value of the progress bar. */ + max: number + /**The initial value of the progress bar. */ + initialValue: number + + /**Enable automatic stopping when reaching `min` or `max`. */ + autoStop: null|"min"|"max" + + constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,min:number,max:number,value:number,autoStop:null|"min"|"max"){ + super(id) + this.renderer = renderer + this.min = min + this.max = max + this.initialValue = this.#parseValue(value) + this.value = this.#parseValue(value) + this.autoStop = autoStop + } + /**Parse a value in such a way that it doesn't go below/above the min/max limits. */ + #parseValue(value:number){ + if (value > this.max) return this.max + else if (value < this.min) return this.min + else return value + } + /**Render progress bar to the console. */ + #renderStdout(){ + if (!this.#active) return + readline.clearLine(process.stdout,0) + readline.cursorTo(process.stdout,0) + process.stdout.write(this.renderer.render(this.min,this.max,this.value)) + } + /**Start showing this progress bar in the console. */ + start(){ + if (this.#active) throw new ODSystemError("ODProgressBar => unable to start when already active!") + this.value = this.#parseValue(this.initialValue) + this.#active = true + this.#renderStdout() + } + /**Update this progress bar while active. (will automatically update the progress bar in the console) */ + protected update(value:number,stop?:boolean){ + if (!this.#active) throw new ODSystemError("ODProgressBar => unable to update when not active yet!") + this.value = this.#parseValue(value) + this.#renderStdout() + if (stop || (this.autoStop == "max" && this.value == this.max) || (this.autoStop == "min" && this.value == this.min)){ + process.stdout.write("\n") + this.#active = false + this.#stopListeners.forEach((cb) => cb()) + this.#stopListeners = [] + } + } + /**Wait for the progress bar to finish. */ + finished(): Promise { + return new Promise((resolve) => { + this.#stopListeners.push(resolve) + }) + } +} + +/**## ODTimedProgressBar `class` + * This is an open ticket timed console progress bar. + * + * It is used to create a simple timed progress bar in the console. + * You can set a fixed duration (milliseconds) in the constructor. + */ +export class ODTimedProgressBar extends ODProgressBar { + /**The time in milliseconds. */ + time: number + /**The mode of the timer. */ + mode: "increasing"|"decreasing" + + constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,time:number,mode:"increasing"|"decreasing"){ + super(id,renderer,0,time,0,(mode == "increasing") ? "max" : "min") + this.time = time + this.mode = mode + } + + /**The timer which is used. */ + async #timer(ms:number): Promise { + return new Promise((resolve) => { + setTimeout(() => { + resolve() + },ms) + }) + } + /**Run the timed progress bar. */ + async #execute(){ + let i = 0 + const fragment = this.time/100 + while (i < 100){ + await this.#timer(fragment) + i++ + super.update((this.mode == "increasing") ? (i*fragment) : this.time-(i*fragment)) + } + } + start(){ + super.start() + this.#execute() + } +} + +/**## ODManualProgressBar `class` + * This is an open ticket manual console progress bar. + * + * It is used to create a simple manual progress bar in the console. + * You can update the progress manually using `update()`. + */ +export class ODManualProgressBar extends ODProgressBar { + constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,amount:number,autoStop:null|"min"|"max"){ + super(id,renderer,0,amount,0,autoStop) + } + start(){ + super.start() + } + /**Set the value of the progress bar. */ + set(value:number,stop?:boolean){ + super.update(value,stop) + } + /**Get the current value of the progress bar. */ + get(){ + return this.value + } + /**Increase the value of the progress bar. */ + increase(amount:number,stop?:boolean){ + super.update(this.value+amount,stop) + } + /**Decrease the value of the progress bar. */ + decrease(amount:number,stop?:boolean){ + super.update(this.value-amount,stop) + } +} \ No newline at end of file diff --git a/src/data/framework/eventLoader.ts b/src/data/framework/eventLoader.ts index ad5f88d..beae995 100644 --- a/src/data/framework/eventLoader.ts +++ b/src/data/framework/eventLoader.ts @@ -17,6 +17,12 @@ export const loadAllEvents = () => { "onFlagInit", "afterFlagsInitiated", + //progress bars + "onProgressBarRendererLoad", + "afterProgressBarRenderersLoaded", + "onProgressBarLoad", + "afterProgressBarsLoaded", + //configs "onConfigLoad", "afterConfigsLoaded", diff --git a/src/data/framework/progressBarLoader.ts b/src/data/framework/progressBarLoader.ts new file mode 100644 index 0000000..afc94bf --- /dev/null +++ b/src/data/framework/progressBarLoader.ts @@ -0,0 +1,7 @@ +import {openticket, api, utilities} from "../../index" + +export const loadAllProgressBarRenderers = async () => { +} + +export const loadAllProgressBars = async () => { +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index ac48088..24d20a2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -114,6 +114,21 @@ const main = async () => { openticket.debug.visible = (debugFlag) ? debugFlag.value : false } + //load progress bar renderers + openticket.log("Loading progress bars...","system") + if (openticket.defaults.getDefault("progressBarRendererLoading")){ + await (await import("./data/framework/progressBarLoader.js")).loadAllProgressBarRenderers() + } + await openticket.events.get("onProgressBarRendererLoad").emit([openticket.progressbars.renderers]) + await openticket.events.get("afterProgressBarRenderersLoaded").emit([openticket.progressbars.renderers]) + + //load progress bars + if (openticket.defaults.getDefault("progressBarLoading")){ + await (await import("./data/framework/progressBarLoader.js")).loadAllProgressBars() + } + await openticket.events.get("onProgressBarLoad").emit([openticket.progressbars]) + await openticket.events.get("afterProgressBarsLoaded").emit([openticket.progressbars]) + //load config openticket.log("Loading configs...","system") if (openticket.defaults.getDefault("configLoading")){ From 7809ffc5c62274b1b9f35ceb40528a1825e006e6 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 19 Jan 2025 15:15:29 +0100 Subject: [PATCH 099/157] Fixed typo's in comments --- src/core/api/defaults/action.ts | 4 ++-- src/core/api/defaults/base.ts | 4 ++-- src/core/api/defaults/builder.ts | 24 ++++++++++++------------ src/core/api/defaults/checker.ts | 16 ++++++++-------- src/core/api/defaults/client.ts | 8 ++++---- src/core/api/defaults/code.ts | 4 ++-- src/core/api/defaults/config.ts | 4 ++-- src/core/api/defaults/console.ts | 4 ++-- src/core/api/defaults/cooldown.ts | 4 ++-- src/core/api/defaults/database.ts | 12 ++++++------ src/core/api/defaults/event.ts | 4 ++-- src/core/api/defaults/flag.ts | 4 ++-- src/core/api/defaults/helpmenu.ts | 18 +++++++++--------- src/core/api/defaults/language.ts | 6 +++--- src/core/api/defaults/plugin.ts | 8 ++++---- src/core/api/defaults/post.ts | 4 ++-- src/core/api/defaults/progressbar.ts | 8 ++++---- src/core/api/defaults/responder.ts | 16 ++++++++-------- src/core/api/defaults/session.ts | 4 ++-- src/core/api/defaults/startscreen.ts | 4 ++-- src/core/api/defaults/stat.ts | 14 +++++++------- src/core/api/defaults/verifybar.ts | 4 ++-- src/core/api/openticket/option.ts | 6 +++--- src/core/api/openticket/panel.ts | 2 +- src/core/api/openticket/question.ts | 4 ++-- src/core/api/openticket/role.ts | 2 +- src/core/api/openticket/ticket.ts | 2 +- src/core/api/openticket/transcript.ts | 2 +- src/data/framework/startScreenLoader.ts | 7 ------- 29 files changed, 98 insertions(+), 105 deletions(-) diff --git a/src/core/api/defaults/action.ts b/src/core/api/defaults/action.ts index c8d68a8..3bc15ee 100644 --- a/src/core/api/defaults/action.ts +++ b/src/core/api/defaults/action.ts @@ -11,8 +11,8 @@ import { ODTranscriptCompiler, ODTranscriptCompilerCompileResult } from "../open import { ODMessageBuildSentResult } from "../modules/builder" import { ODRole, OTRoleUpdateMode, OTRoleUpdateResult } from "../openticket/role" -/**## ODActionManagerIds_Default `type` - * This type is an array of ids available in the `ODActionManager_Default` class. +/**## ODActionManagerIds_Default `interface` + * This interface is a list of ids available in the `ODActionManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODActionManagerIds_Default { diff --git a/src/core/api/defaults/base.ts b/src/core/api/defaults/base.ts index fceda6e..5575d96 100644 --- a/src/core/api/defaults/base.ts +++ b/src/core/api/defaults/base.ts @@ -3,8 +3,8 @@ /////////////////////////////////////// import { ODVersion, ODVersionManager, ODValidId } from "../modules/base" -/**## ODVersionManagerIds_Default `type` - * This type is an array of ids available in the `ODVersionManager` class. +/**## ODVersionManagerIds_Default `interface` + * This interface is a list of ids available in the `ODVersionManager` class. * It's used to generate typescript declarations for this class. */ export interface ODVersionManagerIds_Default { diff --git a/src/core/api/defaults/builder.ts b/src/core/api/defaults/builder.ts index 0620071..5ec6f0e 100644 --- a/src/core/api/defaults/builder.ts +++ b/src/core/api/defaults/builder.ts @@ -29,8 +29,8 @@ export class ODBuilderManager_Default extends ODBuilderManager { declare modals: ODModalManager_Default } -/**## ODButtonManagerIds_Default `type` - * This type is an array of ids available in the `ODButtonManager_Default` class. +/**## ODButtonManagerIds_Default `interface` + * This interface is a list of ids available in the `ODButtonManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODButtonManagerIds_Default { @@ -111,8 +111,8 @@ export class ODButton_Default } -/**## ODDropdownManagerIds_Default `type` - * This type is an array of ids available in the `ODDropdownManager_Default` class. +/**## ODDropdownManagerIds_Default `interface` + * This interface is a list of ids available in the `ODDropdownManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODDropdownManagerIds_Default { @@ -165,8 +165,8 @@ export class ODDropdown_Default } -/**## ODFileManagerIds_Default `type` - * This type is an array of ids available in the `ODFileManager_Default` class. +/**## ODFileManagerIds_Default `interface` + * This interface is a list of ids available in the `ODFileManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODFileManagerIds_Default { @@ -219,8 +219,8 @@ export class ODFile_Default } -/**## ODEmbedManagerIds_Default `type` - * This type is an array of ids available in the `ODEmbedManager_Default` class. +/**## ODEmbedManagerIds_Default `interface` + * This interface is a list of ids available in the `ODEmbedManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODEmbedManagerIds_Default { @@ -339,8 +339,8 @@ export class ODEmbed_Default } -/**## ODMessageManagerIds_Default `type` - * This type is an array of ids available in the `ODMessageManager_Default` class. +/**## ODMessageManagerIds_Default `interface` + * This interface is a list of ids available in the `ODMessageManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODMessageManagerIds_Default { @@ -470,8 +470,8 @@ export class ODMessage_Default } -/**## ODModalManagerIds_Default `type` - * This type is an array of ids available in the `ODModalManager_Default` class. +/**## ODModalManagerIds_Default `interface` + * This interface is a list of ids available in the `ODModalManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODModalManagerIds_Default { diff --git a/src/core/api/defaults/checker.ts b/src/core/api/defaults/checker.ts index 650cd80..97d5191 100644 --- a/src/core/api/defaults/checker.ts +++ b/src/core/api/defaults/checker.ts @@ -6,8 +6,8 @@ import { ODValidId } from "../modules/base" import { ODCheckerManager, ODChecker, ODCheckerTranslationRegister, ODCheckerRenderer, ODCheckerFunctionManager, ODCheckerResult, ODCheckerFunction } from "../modules/checker" import ansis from "ansis" -/**## ODCheckerManagerIds_Default `type` - * This type is an array of ids available in the `ODCheckerManager_Default` class. +/**## ODCheckerManagerIds_Default `interface` + * This interface is a list of ids available in the `ODCheckerManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODCheckerManagerIds_Default { @@ -208,8 +208,8 @@ export class ODCheckerRenderer_Default extends ODCheckerRenderer { } } -/**## ODCheckerTranslationRegisterOtherIds_Default `type` - * This type is an array of ids available in the `ODCheckerTranslationRegister_Default` class. +/**## ODCheckerTranslationRegisterOtherIds_Default `interface` + * This interface is a list of ids available in the `ODCheckerTranslationRegister_Default` class. * It's used to generate typescript declarations for this class. */ export type ODCheckerTranslationRegisterOtherIds_Default = ( @@ -228,8 +228,8 @@ export type ODCheckerTranslationRegisterOtherIds_Default = ( "openticket:footer-support" ) -/**## ODCheckerTranslationRegisterMessageIds_Default `type` - * This type is an array of ids available in the `ODCheckerTranslationRegister_Default` class. +/**## ODCheckerTranslationRegisterMessageIds_Default `interface` + * This interface is a list of ids available in the `ODCheckerTranslationRegister_Default` class. * It's used to generate typescript declarations for this class. */ export type ODCheckerTranslationRegisterMessageIds_Default = ( @@ -341,8 +341,8 @@ export class ODCheckerTranslationRegister_Default extends ODCheckerTranslationRe } } -/**## ODCheckerFunctionManagerIds_Default `type` - * This type is an array of ids available in the `ODCheckerFunctionManager_Default` class. +/**## ODCheckerFunctionManagerIds_Default `interface` + * This interface is a list of ids available in the `ODCheckerFunctionManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODCheckerFunctionManagerIds_Default { diff --git a/src/core/api/defaults/client.ts b/src/core/api/defaults/client.ts index 95e2cfe..5962896 100644 --- a/src/core/api/defaults/client.ts +++ b/src/core/api/defaults/client.ts @@ -15,8 +15,8 @@ export class ODClientManager_Default extends ODClientManager { declare textCommands: ODTextCommandManager_Default } -/**## ODSlashCommandManagerIds_Default `type` - * This type is an array of ids available in the `ODSlashCommandManager_Default` class. +/**## ODSlashCommandManagerIds_Default `interface` + * This interface is a list of ids available in the `ODSlashCommandManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODSlashCommandManagerIds_Default { @@ -77,8 +77,8 @@ export class ODSlashCommandManager_Default extends ODSlashCommandManager { } } -/**## ODTextCommandManagerIds_Default `type` - * This type is an array of ids available in the `ODTextCommandManager_Default` class. +/**## ODTextCommandManagerIds_Default `interface` + * This interface is a list of ids available in the `ODTextCommandManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODTextCommandManagerIds_Default { diff --git a/src/core/api/defaults/code.ts b/src/core/api/defaults/code.ts index 4275298..90e2436 100644 --- a/src/core/api/defaults/code.ts +++ b/src/core/api/defaults/code.ts @@ -4,8 +4,8 @@ import { ODValidId } from "../modules/base" import { ODCode, ODCodeManager } from "../modules/code" -/**## ODCodeManagerIds_Default `type` - * This type is an array of ids available in the `ODCodeManager_Default` class. +/**## ODCodeManagerIds_Default `interface` + * This interface is a list of ids available in the `ODCodeManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODCodeManagerIds_Default { diff --git a/src/core/api/defaults/config.ts b/src/core/api/defaults/config.ts index bcc5654..c265927 100644 --- a/src/core/api/defaults/config.ts +++ b/src/core/api/defaults/config.ts @@ -7,8 +7,8 @@ import { ODConfigManager, ODConfig, ODJsonConfig } from "../modules/config" import { ODClientActivityStatus, ODClientActivityType } from "../modules/client" import { OTRoleUpdateMode } from "../openticket/role" -/**## ODConfigManagerIds_Default `type` - * This type is an array of ids available in the `ODConfigManager_Default` class. +/**## ODConfigManagerIds_Default `interface` + * This interface is a list of ids available in the `ODConfigManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODConfigManagerIds_Default { diff --git a/src/core/api/defaults/console.ts b/src/core/api/defaults/console.ts index 58f6feb..f0d3813 100644 --- a/src/core/api/defaults/console.ts +++ b/src/core/api/defaults/console.ts @@ -4,8 +4,8 @@ import { ODValidId } from "../modules/base" import { ODLiveStatusUrlSource, ODLiveStatusManager, ODLiveStatusSource } from "../modules/console" -/**## ODLiveStatusManagerIds_Default `type` - * This type is an array of ids available in the `ODLiveStatusManager_Default` class. +/**## ODLiveStatusManagerIds_Default `interface` + * This interface is a list of ids available in the `ODLiveStatusManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODLiveStatusManagerIds_Default { diff --git a/src/core/api/defaults/cooldown.ts b/src/core/api/defaults/cooldown.ts index 0a0c1a2..09b3cd2 100644 --- a/src/core/api/defaults/cooldown.ts +++ b/src/core/api/defaults/cooldown.ts @@ -4,8 +4,8 @@ import { ODValidId } from "../modules/base" import { ODCooldown, ODCooldownManager } from "../modules/cooldown" -/**## ODCooldownManagerIds_Default `type` - * This type is an array of ids available in the `ODCooldownManager_Default` class. +/**## ODCooldownManagerIds_Default `interface` + * This interface is a list of ids available in the `ODCooldownManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODCooldownManagerIds_Default { diff --git a/src/core/api/defaults/database.ts b/src/core/api/defaults/database.ts index a9d2d26..514911f 100644 --- a/src/core/api/defaults/database.ts +++ b/src/core/api/defaults/database.ts @@ -6,8 +6,8 @@ import { ODDatabaseManager, ODDatabase, ODFormattedJsonDatabase } from "../modul import { ODTicketJson } from "../openticket/ticket" import { ODOptionJson } from "../openticket/option" -/**## ODDatabaseManagerIds_Default `type` - * This type is an array of ids available in the `ODDatabaseManager_Default` class. +/**## ODDatabaseManagerIds_Default `interface` + * This interface is a list of ids available in the `ODDatabaseManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODDatabaseManagerIds_Default { @@ -48,7 +48,7 @@ export class ODDatabaseManager_Default extends ODDatabaseManager { } /**## ODFormattedJsonDatabaseIds_DefaultGlobal `type` - * This type is an array of ids available in the `ODFormattedJsonDatabase_DefaultGlobal` class. + * This interface is a list of ids available in the `ODFormattedJsonDatabase_DefaultGlobal` class. * It's used to generate typescript declarations for this class. */ export interface ODFormattedJsonDatabaseIds_DefaultGlobal { @@ -102,7 +102,7 @@ export class ODFormattedJsonDatabase_DefaultGlobal extends ODFormattedJsonDataba } /**## ODFormattedJsonDatabaseIds_DefaultTickets `type` - * This type is an array of ids available in the `ODDatabaseManager_Default` class. + * This interface is a list of ids available in the `ODDatabaseManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODFormattedJsonDatabaseIds_DefaultTickets { @@ -153,7 +153,7 @@ export class ODFormattedJsonDatabase_DefaultTickets extends ODFormattedJsonDatab } /**## ODFormattedJsonDatabaseIds_DefaultUsers `type` - * This type is an array of ids available in the `ODDatabaseManager_Default` class. + * This interface is a list of ids available in the `ODDatabaseManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODFormattedJsonDatabaseIds_DefaultUsers { @@ -205,7 +205,7 @@ export class ODFormattedJsonDatabase_DefaultUsers extends ODFormattedJsonDatabas /**## ODFormattedJsonDatabaseIds_DefaultOptions `type` - * This type is an array of ids available in the `ODDatabaseManager_Default` class. + * This interface is a list of ids available in the `ODDatabaseManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODFormattedJsonDatabaseIds_DefaultOptions { diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts index edab225..c4500b8 100644 --- a/src/core/api/defaults/event.ts +++ b/src/core/api/defaults/event.ts @@ -43,8 +43,8 @@ import { ODBlacklistManager } from "../openticket/blacklist" import { ODTranscriptManager_Default } from "../openticket/transcript" import { ODRole, ODRoleManager } from "../openticket/role" -/**## ODEventIds_Default `type` - * This type is an array of ids available in the `ODEvent_Default` class. +/**## ODEventIds_Default `interface` + * This interface is a list of ids available in the `ODEvent_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODEventIds_Default { diff --git a/src/core/api/defaults/flag.ts b/src/core/api/defaults/flag.ts index 7c9a459..a7b8e17 100644 --- a/src/core/api/defaults/flag.ts +++ b/src/core/api/defaults/flag.ts @@ -4,8 +4,8 @@ import { ODValidId } from "../modules/base" import { ODFlagManager, ODFlag } from "../modules/flag" -/**## ODFlagManagerIds_Default `type` - * This type is an array of ids available in the `ODFlagManager_Default` class. +/**## ODFlagManagerIds_Default `interface` + * This interface is a list of ids available in the `ODFlagManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODFlagManagerIds_Default { diff --git a/src/core/api/defaults/helpmenu.ts b/src/core/api/defaults/helpmenu.ts index 7add16f..7269ebc 100644 --- a/src/core/api/defaults/helpmenu.ts +++ b/src/core/api/defaults/helpmenu.ts @@ -4,8 +4,8 @@ import { ODValidId } from "../modules/base" import { ODHelpMenuCategory, ODHelpMenuCommandComponent, ODHelpMenuComponent, ODHelpMenuManager } from "../modules/helpmenu" -/**## ODHelpMenuManagerIds_Default `type` - * This type is an array of ids available in the `ODHelpMenuManager_Default` class. +/**## ODHelpMenuManagerIds_Default `interface` + * This interface is a list of ids available in the `ODHelpMenuManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerIds_Default { @@ -48,7 +48,7 @@ export class ODHelpMenuManager_Default extends ODHelpMenuManager { } /**## ODHelpMenuManagerCategoryIds_DefaultGeneral `type` - * This type is an array of ids available in the `ODHelpMenuCategory_DefaultGeneral` class. + * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultGeneral` class. * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultGeneral { @@ -86,7 +86,7 @@ export class ODHelpMenuCategory_DefaultGeneral extends ODHelpMenuCategory { } /**## ODHelpMenuManagerCategoryIds_DefaultTicketBasic `type` - * This type is an array of ids available in the `ODHelpMenuCategory_DefaultTicketBasic` class. + * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultTicketBasic` class. * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultTicketBasic { @@ -125,7 +125,7 @@ export class ODHelpMenuCategory_DefaultTicketBasic extends ODHelpMenuCategory { } /**## ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced `type` - * This type is an array of ids available in the `ODHelpMenuCategory_DefaultTicketAdvanced` class. + * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultTicketAdvanced` class. * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced { @@ -165,7 +165,7 @@ export class ODHelpMenuCategory_DefaultTicketAdvanced extends ODHelpMenuCategory } /**## ODHelpMenuManagerCategoryIds_DefaultTicketUser `type` - * This type is an array of ids available in the `ODHelpMenuCategory_DefaultTicketUser` class. + * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultTicketUser` class. * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultTicketUser { @@ -205,7 +205,7 @@ export class ODHelpMenuCategory_DefaultTicketUser extends ODHelpMenuCategory { } /**## ODHelpMenuManagerCategoryIds_DefaultAdmin `type` - * This type is an array of ids available in the `ODHelpMenuCategory_DefaultAdmin` class. + * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultAdmin` class. * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultAdmin { @@ -246,7 +246,7 @@ export class ODHelpMenuCategory_DefaultAdmin extends ODHelpMenuCategory { } /**## ODHelpMenuManagerCategoryIds_DefaultAdvanced `type` - * This type is an array of ids available in the `ODHelpMenuCategory_DefaultAdvanced` class. + * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultAdvanced` class. * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultAdvanced { @@ -288,7 +288,7 @@ export class ODHelpMenuCategory_DefaultAdvanced extends ODHelpMenuCategory { } /**## ODHelpMenuManagerCategoryIds_DefaultExtra `type` - * This type is an array of ids available in the `ODHelpMenuCategory_DefaultExtra` class. + * This interface is a list of ids available in the `ODHelpMenuCategory_DefaultExtra` class. * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultExtra {} diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index 5326e50..6d8b927 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -5,7 +5,7 @@ import { ODValidId } from "../modules/base" import { ODLanguageManager, ODLanguage } from "../modules/language" /**## ODLanguageManagerTranslations_Default `type` - * This type is an array of ids available in the `ODLanguageManager_Default` class. + * This interface is a list of ids available in the `ODLanguageManager_Default` class. * It's used to generate typescript declarations for this class. */ export type ODLanguageManagerTranslations_Default = ( @@ -439,8 +439,8 @@ export type ODLanguageManagerTranslations_Default = ( "stats.properties.transcriptsCreated" ) -/**## ODLanguageManagerIds_Default `type` - * This type is an array of ids available in the `ODLanguageManager_Default` class. +/**## ODLanguageManagerIds_Default `interface` + * This interface is a list of ids available in the `ODLanguageManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODLanguageManagerIds_Default { diff --git a/src/core/api/defaults/plugin.ts b/src/core/api/defaults/plugin.ts index 4bd5f77..5f7c5b4 100644 --- a/src/core/api/defaults/plugin.ts +++ b/src/core/api/defaults/plugin.ts @@ -4,8 +4,8 @@ import { ODValidId, ODManagerData } from "../modules/base" import { ODPlugin, ODPluginClassManager, ODPluginManager } from "../modules/plugin" -/**## ODPluginManagerIds_Default `type` - * This type is an array of ids available in the `ODPluginManager_Default` class. +/**## ODPluginManagerIds_Default `interface` + * This interface is a list of ids available in the `ODPluginManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODPluginManagerIds_Default {} @@ -41,8 +41,8 @@ export class ODPluginManager_Default extends ODPluginManager { } } -/**## ODPluginClassManagerIds_Default `type` - * This type is an array of ids available in the `ODPluginClassManager_Default` class. +/**## ODPluginClassManagerIds_Default `interface` + * This interface is a list of ids available in the `ODPluginClassManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODPluginClassManagerIds_Default {} diff --git a/src/core/api/defaults/post.ts b/src/core/api/defaults/post.ts index 0b0dc27..79d497b 100644 --- a/src/core/api/defaults/post.ts +++ b/src/core/api/defaults/post.ts @@ -5,8 +5,8 @@ import { ODValidId } from "../modules/base" import { ODPost, ODPostManager } from "../modules/post" import * as discord from "discord.js" -/**## ODPostManagerIds_Default `type` - * This type is an array of ids available in the `ODPostManager_Default` class. +/**## ODPostManagerIds_Default `interface` + * This interface is a list of ids available in the `ODPostManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODPostManagerIds_Default { diff --git a/src/core/api/defaults/progressbar.ts b/src/core/api/defaults/progressbar.ts index ff5df36..0b8f8ec 100644 --- a/src/core/api/defaults/progressbar.ts +++ b/src/core/api/defaults/progressbar.ts @@ -5,8 +5,8 @@ import { ODValidId } from "../modules/base" import { ODProgressBar, ODProgressBarManager, ODProgressBarRenderer, ODProgressBarRendererManager } from "../modules/progressbar" -/**## ODProgressBarRendererManagerIds_Default `type` - * This type is an array of ids available in the `ODProgressBarRendererManager_Default` class. +/**## ODProgressBarRendererManagerIds_Default `interface` + * This interface is a list of ids available in the `ODProgressBarRendererManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODProgressBarRendererManagerIds_Default { @@ -42,8 +42,8 @@ export class ODProgressBarRendererManager_Default extends ODProgressBarRendererM } } -/**## ODProgressBarManagerIds_Default `type` - * This type is an array of ids available in the `ODProgressBarManager_Default` class. +/**## ODProgressBarManagerIds_Default `interface` + * This interface is a list of ids available in the `ODProgressBarManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODProgressBarManagerIds_Default { diff --git a/src/core/api/defaults/responder.ts b/src/core/api/defaults/responder.ts index ffe944f..cedcb0f 100644 --- a/src/core/api/defaults/responder.ts +++ b/src/core/api/defaults/responder.ts @@ -18,8 +18,8 @@ export class ODResponderManager_Default extends ODResponderManager { declare modals: ODModalResponderManager_Default } -/**## ODCommandResponderManagerIds_Default `type` - * This type is an array of ids available in the `ODCommandResponderManager_Default` class. +/**## ODCommandResponderManagerIds_Default `interface` + * This interface is a list of ids available in the `ODCommandResponderManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODCommandResponderManagerIds_Default { @@ -86,8 +86,8 @@ export class ODCommandResponder_Default } -/**## ODButtonResponderManagerIds_Default `type` - * This type is an array of ids available in the `ODButtonResponderManager_Default` class. +/**## ODButtonResponderManagerIds_Default `interface` + * This interface is a list of ids available in the `ODButtonResponderManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODButtonResponderManagerIds_Default { @@ -153,8 +153,8 @@ export class ODButtonResponder_Default } -/**## ODDropdownResponderManagerIds_Default `type` - * This type is an array of ids available in the `ODDropdownResponderManager_Default` class. +/**## ODDropdownResponderManagerIds_Default `interface` + * This interface is a list of ids available in the `ODDropdownResponderManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODDropdownResponderManagerIds_Default { @@ -200,8 +200,8 @@ export class ODDropdownResponder_Default } -/**## ODModalResponderManagerIds_Default `type` - * This type is an array of ids available in the `ODModalResponderManager_Default` class. +/**## ODModalResponderManagerIds_Default `interface` + * This interface is a list of ids available in the `ODModalResponderManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODModalResponderManagerIds_Default { diff --git a/src/core/api/defaults/session.ts b/src/core/api/defaults/session.ts index b7153cd..d75685b 100644 --- a/src/core/api/defaults/session.ts +++ b/src/core/api/defaults/session.ts @@ -4,8 +4,8 @@ import { ODValidId } from "../modules/base" import { ODSession, ODSessionManager } from "../modules/session" -/**## ODSessionManagerIds_Default `type` - * This type is an array of ids available in the `ODSessionManager_Default` class. +/**## ODSessionManagerIds_Default `interface` + * This interface is a list of ids available in the `ODSessionManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODSessionManagerIds_Default { diff --git a/src/core/api/defaults/startscreen.ts b/src/core/api/defaults/startscreen.ts index 4d49c07..7507475 100644 --- a/src/core/api/defaults/startscreen.ts +++ b/src/core/api/defaults/startscreen.ts @@ -4,8 +4,8 @@ import { ODValidId } from "../modules/base" import { ODStartScreenCategoryComponent, ODStartScreenComponent, ODStartScreenFlagsCategoryComponent, ODStartScreenHeaderComponent, ODStartScreenLiveStatusCategoryComponent, ODStartScreenLogoComponent, ODStartScreenManager, ODStartScreenPluginsCategoryComponent, ODStartScreenPropertiesCategoryComponent } from "../modules/startscreen" -/**## ODStartScreenManagerIds_Default `type` - * This type is an array of ids available in the `ODStartScreenManager_Default` class. +/**## ODStartScreenManagerIds_Default `interface` + * This interface is a list of ids available in the `ODStartScreenManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODStartScreenManagerIds_Default { diff --git a/src/core/api/defaults/stat.ts b/src/core/api/defaults/stat.ts index d4ea1e9..320ac59 100644 --- a/src/core/api/defaults/stat.ts +++ b/src/core/api/defaults/stat.ts @@ -5,8 +5,8 @@ import { Guild, TextBasedChannel, User } from "discord.js" import { ODValidId } from "../modules/base" import { ODStatScope, ODStatGlobalScope, ODStatsManager, ODStat, ODBasicStat, ODDynamicStat, ODValidStatValue, ODStatScopeSetMode } from "../modules/stat" -/**## ODStatsManagerIds_Default `type` - * This type is an array of ids available in the `ODStatsManager_Default` class. +/**## ODStatsManagerIds_Default `interface` + * This interface is a list of ids available in the `ODStatsManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODStatsManagerIds_Default { @@ -47,7 +47,7 @@ export class ODStatsManager_Default extends ODStatsManager { } /**## ODStatGlobalScopeIds_DefaultGlobal `type` - * This type is an array of ids available in the `ODStatGlobalScope_DefaultGlobal` class. + * This interface is a list of ids available in the `ODStatGlobalScope_DefaultGlobal` class. * It's used to generate typescript declarations for this class. */ export interface ODStatGlobalScopeIds_DefaultGlobal { @@ -115,7 +115,7 @@ export class ODStatGlobalScope_DefaultGlobal extends ODStatGlobalScope { } /**## ODStatGlobalScopeIds_DefaultSystem `type` - * This type is an array of ids available in the `ODStatScope_DefaultSystem` class. + * This interface is a list of ids available in the `ODStatScope_DefaultSystem` class. * It's used to generate typescript declarations for this class. */ export interface ODStatGlobalScopeIds_DefaultSystem { @@ -174,7 +174,7 @@ export class ODStatGlobalScope_DefaultSystem extends ODStatGlobalScope { } /**## ODStatScopeIds_DefaultUser `type` - * This type is an array of ids available in the `ODStatScope_DefaultUser` class. + * This interface is a list of ids available in the `ODStatScope_DefaultUser` class. * It's used to generate typescript declarations for this class. */ export interface ODStatScopeIds_DefaultUser { @@ -242,7 +242,7 @@ export class ODStatScope_DefaultUser extends ODStatScope { } /**## ODStatScopeIds_DefaultTicket `type` - * This type is an array of ids available in the `ODStatScope_DefaultTicket` class. + * This interface is a list of ids available in the `ODStatScope_DefaultTicket` class. * It's used to generate typescript declarations for this class. */ export interface ODStatScopeIds_DefaultTicket { @@ -305,7 +305,7 @@ export class ODStatScope_DefaultTicket extends ODStatScope { } /**## ODStatScopeIds_DefaultParticipants `type` - * This type is an array of ids available in the `ODStatScope_DefaultParticipants` class. + * This interface is a list of ids available in the `ODStatScope_DefaultParticipants` class. * It's used to generate typescript declarations for this class. */ export interface ODStatScopeIds_DefaultParticipants { diff --git a/src/core/api/defaults/verifybar.ts b/src/core/api/defaults/verifybar.ts index 3df5f8f..095f82f 100644 --- a/src/core/api/defaults/verifybar.ts +++ b/src/core/api/defaults/verifybar.ts @@ -7,8 +7,8 @@ import { ODWorkerManager_Default } from "../defaults/worker" import { ODVerifyBarManager, ODVerifyBar } from "../modules/verifybar" import * as discord from "discord.js" -/**## ODVerifyBarManagerIds_Default `type` - * This type is an array of ids available in the `ODVerifyBarManager_Default` class. +/**## ODVerifyBarManagerIds_Default `interface` + * This interface is a list of ids available in the `ODVerifyBarManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODVerifyBarManagerIds_Default { diff --git a/src/core/api/openticket/option.ts b/src/core/api/openticket/option.ts index 3aeff49..9e717fc 100644 --- a/src/core/api/openticket/option.ts +++ b/src/core/api/openticket/option.ts @@ -93,7 +93,7 @@ export class ODOptionData extends ODManagerDat } /**## ODTicketOptionIds `type` - * This type is an array of ids available in the `ODTicketOption` class. + * This interface is a list of ids available in the `ODTicketOption` class. * It's used to generate typescript declarations for this class. */ export interface ODTicketOptionIds { @@ -178,7 +178,7 @@ export class ODTicketOption extends ODOption { } /**## ODWebsiteOptionIds `type` - * This type is an array of ids available in the `ODWebsiteOption` class. + * This interface is a list of ids available in the `ODWebsiteOption` class. * It's used to generate typescript declarations for this class. */ export interface ODWebsiteOptionIds { @@ -225,7 +225,7 @@ export class ODWebsiteOption extends ODOption { } /**## ODRoleOptionIds `type` - * This type is an array of ids available in the `ODRoleOption` class. + * This interface is a list of ids available in the `ODRoleOption` class. * It's used to generate typescript declarations for this class. */ export interface ODRoleOptionIds { diff --git a/src/core/api/openticket/panel.ts b/src/core/api/openticket/panel.ts index 5c37b2d..378aead 100644 --- a/src/core/api/openticket/panel.ts +++ b/src/core/api/openticket/panel.ts @@ -31,7 +31,7 @@ export interface ODPanelJson { } /**## ODPanelIds `type` - * This type is an array of ids available in the `ODPanel` class. + * This interface is a list of ids available in the `ODPanel` class. * It's used to generate typescript declarations for this class. */ export interface ODPanelIds { diff --git a/src/core/api/openticket/question.ts b/src/core/api/openticket/question.ts index da22cdd..7cb78cc 100644 --- a/src/core/api/openticket/question.ts +++ b/src/core/api/openticket/question.ts @@ -86,7 +86,7 @@ export class ODQuestionData extends ODManagerD } /**## ODShortQuestionIds `type` - * This type is an array of ids available in the `ODShortQuestion` class. + * This interface is a list of ids available in the `ODShortQuestion` class. * It's used to generate typescript declarations for this class. */ export interface ODShortQuestionIds { @@ -133,7 +133,7 @@ export class ODShortQuestion extends ODQuestion { } /**## ODParagraphQuestionIds `type` - * This type is an array of ids available in the `ODParagraphQuestion` class. + * This interface is a list of ids available in the `ODParagraphQuestion` class. * It's used to generate typescript declarations for this class. */ export interface ODParagraphQuestionIds { diff --git a/src/core/api/openticket/role.ts b/src/core/api/openticket/role.ts index cae14b8..cf93e12 100644 --- a/src/core/api/openticket/role.ts +++ b/src/core/api/openticket/role.ts @@ -52,7 +52,7 @@ export class ODRoleData extends ODManagerData } /**## ODRoleIds `type` - * This type is an array of ids available in the `ODRole` class. + * This interface is a list of ids available in the `ODRole` class. * It's used to generate typescript declarations for this class. */ export interface ODRoleIds { diff --git a/src/core/api/openticket/ticket.ts b/src/core/api/openticket/ticket.ts index 02c7058..94641a9 100644 --- a/src/core/api/openticket/ticket.ts +++ b/src/core/api/openticket/ticket.ts @@ -129,7 +129,7 @@ export interface ODTicketJson { } /**## ODTicketIds `type` - * This type is an array of ids available in the `ODTicket` class. + * This interface is a list of ids available in the `ODTicket` class. * It's used to generate typescript declarations for this class. */ export interface ODTicketIds { diff --git a/src/core/api/openticket/transcript.ts b/src/core/api/openticket/transcript.ts index 6be48ff..2e297ff 100644 --- a/src/core/api/openticket/transcript.ts +++ b/src/core/api/openticket/transcript.ts @@ -61,7 +61,7 @@ export class ODTranscriptCompiler extends ODManagerData { } /**## ODTranscriptCompilerIds `type` - * This type is an array of ids available in the `ODTranscriptCompiler` class. + * This interface is a list of ids available in the `ODTranscriptCompiler` class. * It's used to generate typescript declarations for this class. */ export interface ODTranscriptCompilerIds { diff --git a/src/data/framework/startScreenLoader.ts b/src/data/framework/startScreenLoader.ts index ecc407d..8c5ea9d 100644 --- a/src/data/framework/startScreenLoader.ts +++ b/src/data/framework/startScreenLoader.ts @@ -2,13 +2,6 @@ import {openticket, api, utilities} from "../../index" import ansis from "ansis" export const loadAllStartScreenComponents = async () => { - /** - "openticket:flags":ODStartScreenFlagsCategoryComponent, - "openticket:plugins":ODStartScreenPluginsCategoryComponent, - - "openticket:livestatus":ODStartScreenLiveStatusCategoryComponent, - */ - //LOGO openticket.startscreen.add(new api.ODStartScreenLogoComponent("openticket:logo",1000,[ " ██████╗ ██████╗ ███████╗███╗ ██╗ ████████╗██╗ ██████╗██╗ ██╗███████╗████████╗ ", From 5e5ac3e40935a7bed4b4dc05de70b006ff2e9f6c Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 19 Jan 2025 15:16:04 +0100 Subject: [PATCH 100/157] Implemented progress bars when loading slash cmds --- src/core/api/defaults/progressbar.ts | 92 ++++++++++++++++++++++++- src/core/api/modules/client.ts | 26 +++++-- src/core/api/modules/progressbar.ts | 49 ++++++++----- src/data/framework/progressBarLoader.ts | 60 ++++++++++++++++ src/index.ts | 14 +++- 5 files changed, 213 insertions(+), 28 deletions(-) diff --git a/src/core/api/defaults/progressbar.ts b/src/core/api/defaults/progressbar.ts index 0b8f8ec..20127dd 100644 --- a/src/core/api/defaults/progressbar.ts +++ b/src/core/api/defaults/progressbar.ts @@ -2,15 +2,99 @@ //DEFAULT PROGRESS BAR MODULE /////////////////////////////////////// import { ODValidId } from "../modules/base" -import { ODProgressBar, ODProgressBarManager, ODProgressBarRenderer, ODProgressBarRendererManager } from "../modules/progressbar" +import { ODValidConsoleColor } from "../modules/console" +import { ODManualProgressBar, ODProgressBar, ODProgressBarManager, ODProgressBarRenderer, ODProgressBarRendererManager } from "../modules/progressbar" +import ansis from "ansis" +/**## ODProgressBarRenderer_DefaultSettingsLabel `type` + * All available label types for the default progress bar renderer + */ +export type ODProgressBarRenderer_DefaultSettingsLabel = "value"|"percentage"|"fraction"|"time-ms"|"time-sec"|"time-min" + +/**## ODProgressBarRenderer_DefaultSettings `interface` + * This interface contains the settings for the default progress bar renderer. + */ +export interface ODProgressBarRenderer_DefaultSettings { + /**The color of the progress bar border. */ + borderColor:ODValidConsoleColor|"openticket", + /**The color of the progress bar (filled side). */ + filledBarColor:ODValidConsoleColor|"openticket", + /**The color of the progress bar (empty side). */ + emptyBarColor:ODValidConsoleColor|"openticket", + /**The color of the text before the progress bar. */ + prefixColor:ODValidConsoleColor|"openticket", + /**The color of the text after the progress bar. */ + suffixColor:ODValidConsoleColor|"openticket", + /**The color of the progress bar label. */ + labelColor:ODValidConsoleColor|"openticket", + + /**The character used in the left border. */ + leftBorderChar:string, + /**The character used in the right border. */ + rightBorderChar:string, + /**The character used in the filled side of the progress bar. */ + filledBarChar:string, + /**The character used in the empty side of the progress bar. */ + emptyBarChar:string, + /**The label type. (will show a number related to the progress) */ + labelType:ODProgressBarRenderer_DefaultSettingsLabel, + /**The position of the label. */ + labelPosition:"start"|"end", + /**The width of the bar. (50 characters by default) */ + barWidth:number, + + /**Show the bar. */ + showBar:boolean, + /**Show the label. */ + showLabel:boolean, + /**Show the border. */ + showBorder:boolean, +} + +export class ODProgressBarRenderer_Default extends ODProgressBarRenderer { + constructor(id:ODValidId,settings:ODProgressBarRenderer_DefaultSettings){ + super(id,(settings,min,max,value,rawPrefix,rawSuffix) => { + const percentage = (value-min)/(max-min) + const barLevel = Math.round(percentage*settings.barWidth) + + const borderAnsis = (settings.borderColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.borderColor] + const filledBarAnsis = (settings.filledBarColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.filledBarColor] + const emptyBarAnsis = (settings.emptyBarColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.emptyBarColor] + const labelAnsis = (settings.labelColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.labelColor] + const prefixAnsis = (settings.prefixColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.prefixColor] + const suffixAnsis = (settings.suffixColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.suffixColor] + + const leftBorder = (settings.showBorder) ? borderAnsis(settings.leftBorderChar) : "" + const rightBorder = (settings.showBorder) ? borderAnsis(settings.rightBorderChar) : "" + const bar = (settings.showBar) ? filledBarAnsis(settings.filledBarChar.repeat(barLevel))+emptyBarAnsis(settings.emptyBarChar.repeat(settings.barWidth-barLevel)) : "" + const prefix = (rawPrefix) ? prefixAnsis(rawPrefix)+" " : "" + const suffix = (rawSuffix) ? " "+suffixAnsis(rawSuffix) : "" + let label: string + if (!settings.showLabel) label = "" + if (settings.labelType == "fraction") label = labelAnsis(value+"/"+max) + else if (settings.labelType == "percentage") label = labelAnsis(Math.round(percentage*100)+"%") + else if (settings.labelType == "time-ms") label = labelAnsis(value+"ms") + else if (settings.labelType == "time-sec") label = labelAnsis(Math.round(value*10)/10+"sec") + else if (settings.labelType == "time-min") label = labelAnsis(Math.round(value*10)/10+"min") + else label = labelAnsis(value.toString()) + + const labelWithPrefixAndSuffix = prefix+label+suffix + return (settings.labelPosition == "start") ? labelWithPrefixAndSuffix+" "+leftBorder+bar+rightBorder : leftBorder+bar+rightBorder+" "+labelWithPrefixAndSuffix + },settings) + } +} /**## ODProgressBarRendererManagerIds_Default `interface` * This interface is a list of ids available in the `ODProgressBarRendererManager_Default` class. * It's used to generate typescript declarations for this class. */ export interface ODProgressBarRendererManagerIds_Default { - "test-progressbar-renderer":ODProgressBarRenderer<{}> + "openticket:value-renderer":ODProgressBarRenderer_Default, + "openticket:fraction-renderer":ODProgressBarRenderer_Default, + "openticket:percentage-renderer":ODProgressBarRenderer_Default, + "openticket:time-ms-renderer":ODProgressBarRenderer_Default, + "openticket:time-sec-renderer":ODProgressBarRenderer_Default, + "openticket:time-min-renderer":ODProgressBarRenderer_Default, } /**## ODProgressBarRendererManager_Default `default_class` @@ -47,7 +131,9 @@ export class ODProgressBarRendererManager_Default extends ODProgressBarRendererM * It's used to generate typescript declarations for this class. */ export interface ODProgressBarManagerIds_Default { - "test-progressbar":ODProgressBar + "openticket:slash-command-remove":ODManualProgressBar, + "openticket:slash-command-create":ODManualProgressBar, + "openticket:slash-command-update":ODManualProgressBar, } /**## ODProgressBarManager_Default `default_class` diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index 07eae5f..393b9dd 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -5,6 +5,7 @@ import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base import * as discord from "discord.js" import { ODConsoleWarningMessage, ODDebugger } from "./console" import { ODMessageBuildResult, ODMessageBuildSentResult } from "./builder" +import { ODManualProgressBar } from "./progressbar" /**## ODClientIntents `type` * A list of intents required when inviting the bot. @@ -814,8 +815,12 @@ export class ODSlashCommandManager extends ODManager { return {registered,unregistered,unused} } /**Create all commands that are not registered yet.*/ - async createNewCommands(instances:ODSlashCommand[]){ + async createNewCommands(instances:ODSlashCommand[],progress?:ODManualProgressBar){ if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") + if (instances.length > 0 && progress){ + progress.max = instances.length + progress.start() + } for (const instance of instances){ await this.createCmd(instance) @@ -823,22 +828,32 @@ export class ODSlashCommandManager extends ODManager { {key:"id",value:instance.id.value}, {key:"name",value:instance.name} ]) + if (progress) progress.increase(1) } } /**Update all commands that are already registered. */ - async updateExistingCommands(instances:ODSlashCommand[]){ + async updateExistingCommands(instances:ODSlashCommand[],progress?:ODManualProgressBar){ if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") - + if (instances.length > 0 && progress){ + progress.max = instances.length + progress.start() + } + for (const instance of instances){ await this.createCmd(instance) this.#debug.debug("Updated existing slash command",[{key:"id",value:instance.id.value},{key:"name",value:instance.name}]) + if (progress) progress.increase(1) } } /**Remove all commands that are registered but unused by Open Ticket. */ - async removeUnusedCommands(instances:ODSlashCommandUniversalCommand[],guildId?:string){ + async removeUnusedCommands(instances:ODSlashCommandUniversalCommand[],guildId?:string,progress?:ODManualProgressBar){ if (!this.manager.ready) throw new ODSystemError("Client isn't ready yet! Unable to register slash commands!") if (!this.commandManager) throw new ODSystemError("Couldn't get client application to register slash commands!") - + if (instances.length > 0 && progress){ + progress.max = instances.length + progress.start() + } + const cmds = await this.commandManager.fetch({guildId}) for (const instance of instances){ @@ -852,6 +867,7 @@ export class ODSlashCommandManager extends ODManager { throw new ODSystemError("Failed to delete slash command '/"+cmd.name+"'!") } } + if (progress) progress.increase(1) } } /**Create a slash command. **(SYSTEM ONLY)** => Use `ODSlashCommandManager` for registering commands the default way! */ diff --git a/src/core/api/modules/progressbar.ts b/src/core/api/modules/progressbar.ts index 2a4209b..182360b 100644 --- a/src/core/api/modules/progressbar.ts +++ b/src/core/api/modules/progressbar.ts @@ -37,7 +37,7 @@ export class ODProgressBarManager extends ODManager { /**## ODProgressBarRenderFunc `type` * This is the render function for an Open Ticket console progress bar. */ -export type ODProgressBarRenderFunc = (settings:Settings,min:number,max:number,value:number) => string +export type ODProgressBarRenderFunc = (settings:Settings,min:number,max:number,value:number,prefix:string|null,suffix:string|null) => string /**## ODProgressBarRenderer `class` * This is an open ticket console progress bar renderer. @@ -57,14 +57,22 @@ export class ODProgressBarRenderer extends ODManagerData { } /**Render a progress bar using this renderer. */ - render(min:number,max:number,value:number){ + render(min:number,max:number,value:number,prefix:string|null,suffix:string|null){ try { - return this.#render(this.settings,min,max,value) + return this.#render(this.settings,min,max,value,prefix,suffix) }catch(err){ process.emit("uncaughtException",err) return "" } } + + withAdditionalSettings(settings:Partial): ODProgressBarRenderer { + const newSettings: Settings = {...this.settings} + for (const key of Object.keys(settings)){ + if (typeof settings[key] != "undefined") newSettings[key] = settings[key] + } + return new ODProgressBarRenderer(this.id,this.#render,newSettings) + } } /**## ODProgressBar `class` @@ -90,11 +98,15 @@ export class ODProgressBar extends ODManagerData { max: number /**The initial value of the progress bar. */ initialValue: number + /**The prefix displayed in the progress bar. */ + prefix:string|null + /**The prefix displayed in the progress bar. */ + suffix:string|null /**Enable automatic stopping when reaching `min` or `max`. */ autoStop: null|"min"|"max" - constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,min:number,max:number,value:number,autoStop:null|"min"|"max"){ + constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,min:number,max:number,value:number,autoStop:null|"min"|"max",prefix:string|null,suffix:string|null){ super(id) this.renderer = renderer this.min = min @@ -102,6 +114,8 @@ export class ODProgressBar extends ODManagerData { this.initialValue = this.#parseValue(value) this.value = this.#parseValue(value) this.autoStop = autoStop + this.prefix = prefix + this.suffix = suffix } /**Parse a value in such a way that it doesn't go below/above the min/max limits. */ #parseValue(value:number){ @@ -114,18 +128,19 @@ export class ODProgressBar extends ODManagerData { if (!this.#active) return readline.clearLine(process.stdout,0) readline.cursorTo(process.stdout,0) - process.stdout.write(this.renderer.render(this.min,this.max,this.value)) + process.stdout.write(this.renderer.render(this.min,this.max,this.value,this.prefix,this.suffix)) } /**Start showing this progress bar in the console. */ - start(){ - if (this.#active) throw new ODSystemError("ODProgressBar => unable to start when already active!") + start(): boolean { + if (this.#active) return false this.value = this.#parseValue(this.initialValue) this.#active = true this.#renderStdout() + return true } /**Update this progress bar while active. (will automatically update the progress bar in the console) */ - protected update(value:number,stop?:boolean){ - if (!this.#active) throw new ODSystemError("ODProgressBar => unable to update when not active yet!") + protected update(value:number,stop?:boolean): boolean { + if (!this.#active) return false this.value = this.#parseValue(value) this.#renderStdout() if (stop || (this.autoStop == "max" && this.value == this.max) || (this.autoStop == "min" && this.value == this.min)){ @@ -134,6 +149,7 @@ export class ODProgressBar extends ODManagerData { this.#stopListeners.forEach((cb) => cb()) this.#stopListeners = [] } + return true } /**Wait for the progress bar to finish. */ finished(): Promise { @@ -155,8 +171,8 @@ export class ODTimedProgressBar extends ODProgressBar { /**The mode of the timer. */ mode: "increasing"|"decreasing" - constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,time:number,mode:"increasing"|"decreasing"){ - super(id,renderer,0,time,0,(mode == "increasing") ? "max" : "min") + constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,time:number,mode:"increasing"|"decreasing",prefix:string|null,suffix:string|null){ + super(id,renderer,0,time,0,(mode == "increasing") ? "max" : "min",prefix,suffix) this.time = time this.mode = mode } @@ -180,8 +196,10 @@ export class ODTimedProgressBar extends ODProgressBar { } } start(){ - super.start() + const res = super.start() + if (!res) return false this.#execute() + return true } } @@ -192,11 +210,8 @@ export class ODTimedProgressBar extends ODProgressBar { * You can update the progress manually using `update()`. */ export class ODManualProgressBar extends ODProgressBar { - constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,amount:number,autoStop:null|"min"|"max"){ - super(id,renderer,0,amount,0,autoStop) - } - start(){ - super.start() + constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,amount:number,autoStop:null|"min"|"max",prefix:string|null,suffix:string|null){ + super(id,renderer,0,amount,0,autoStop,prefix,suffix) } /**Set the value of the progress bar. */ set(value:number,stop?:boolean){ diff --git a/src/data/framework/progressBarLoader.ts b/src/data/framework/progressBarLoader.ts index afc94bf..f990c17 100644 --- a/src/data/framework/progressBarLoader.ts +++ b/src/data/framework/progressBarLoader.ts @@ -1,7 +1,67 @@ import {openticket, api, utilities} from "../../index" export const loadAllProgressBarRenderers = async () => { + const defaultSettings: api.ODProgressBarRenderer_DefaultSettings = { + borderColor:"gray", + filledBarColor:"openticket", + emptyBarColor:"gray", + prefixColor:"white", + suffixColor:"white", + labelColor:"white", + + leftBorderChar:"[", + rightBorderChar:"]", + filledBarChar:"█", + emptyBarChar:"▒", + labelType:"value", + labelPosition:"end", + barWidth:50, + + showBar:true, + showLabel:true, + showBorder:true, + } + + //VALUE RENDERER + const valueRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} + valueRendererSettings.labelType = "value" + openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:value-renderer",valueRendererSettings)) + + //FRACTION RENDERER + const fractionRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} + fractionRendererSettings.labelType = "fraction" + openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:fraction-renderer",fractionRendererSettings)) + + //PERCENTAGE RENDERER + const percentageRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} + percentageRendererSettings.labelType = "percentage" + openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:percentage-renderer",percentageRendererSettings)) + + //TIME MS RENDERER + const timeMsRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} + timeMsRendererSettings.labelType = "time-ms" + openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-ms-renderer",timeMsRendererSettings)) + + //TIME SEC RENDERER + const timeSecRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} + timeSecRendererSettings.labelType = "time-sec" + openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-sec-renderer",timeSecRendererSettings)) + + //TIME MIN RENDERER + const timeMinRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} + timeMinRendererSettings.labelType = "time-min" + openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-min-renderer",timeMinRendererSettings)) } export const loadAllProgressBars = async () => { + const fractRenderer = openticket.progressbars.renderers.get("openticket:fraction-renderer") + + //SLASH COMMAND REMOVE (doesn't have correct amount yet) + openticket.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-remove",fractRenderer.withAdditionalSettings({filledBarColor:"red"}),0,"max",null,"Commands Removed")) + + //SLASH COMMAND CREATE (doesn't have correct amount yet) + openticket.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-create",fractRenderer.withAdditionalSettings({filledBarColor:"green"}),0,"max",null,"Commands Created")) + + //SLASH COMMAND UPDATE (doesn't have correct amount yet) + openticket.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-update",fractRenderer.withAdditionalSettings({filledBarColor:"openticket"}),0,"max",null,"Commands Updated")) } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 24d20a2..e356ba9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -411,11 +411,19 @@ const main = async () => { if (openticket.defaults.getDefault("slashCommandRegistering")){ //get all commands that are already registered in the bot const cmds = await openticket.client.slashCommands.getAllRegisteredCommands() + const removableCmds = cmds.unused.map((cmd) => cmd.cmd) + const newCmds = cmds.unregistered.map((cmd) => cmd.instance) + const updatableCmds = cmds.registered.filter((cmd) => cmd.requiresUpdate || openticket.defaults.getDefault("forceSlashCommandRegistration")).map((cmd) => cmd.instance) + + //init progress bars + const removeProgress = openticket.progressbars.get("openticket:slash-command-remove") + const createProgress = openticket.progressbars.get("openticket:slash-command-create") + const updateProgress = openticket.progressbars.get("openticket:slash-command-update") //remove unused cmds, create new cmds & update existing cmds - if (openticket.defaults.getDefault("allowSlashCommandRemoval")) await openticket.client.slashCommands.removeUnusedCommands(cmds.unused.map((cmd) => cmd.cmd)) - await openticket.client.slashCommands.createNewCommands(cmds.unregistered.map((cmd) => cmd.instance)) - await openticket.client.slashCommands.updateExistingCommands(cmds.registered.filter((cmd) => cmd.requiresUpdate || openticket.defaults.getDefault("forceSlashCommandRegistration")).map((cmd) => cmd.instance)) + if (openticket.defaults.getDefault("allowSlashCommandRemoval")) await openticket.client.slashCommands.removeUnusedCommands(removableCmds,undefined,removeProgress) + await openticket.client.slashCommands.createNewCommands(newCmds,createProgress) + await openticket.client.slashCommands.updateExistingCommands(updatableCmds,updateProgress) await openticket.events.get("afterSlashCommandsRegistered").emit([openticket.client.slashCommands,openticket.client]) } From 1ab207b4eb9bddfe50eea406943d4446533ef1aa Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 20 Jan 2025 20:42:23 +0100 Subject: [PATCH 101/157] Found more missing translations --- src/data/framework/statLoader.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/framework/statLoader.ts b/src/data/framework/statLoader.ts index d75074a..a095bec 100644 --- a/src/data/framework/statLoader.ts +++ b/src/data/framework/statLoader.ts @@ -91,14 +91,14 @@ export const loadAllStats = async () => { if (!ticket) return "" const claimed = ticket.exists("openticket:claimed") ? ticket.get("openticket:claimed").value : false - return claimed ? lang.getTranslation("params.uppercase.claimed")+": 🟢 `Yes`" : lang.getTranslation("params.uppercase.claimed")+": 🔴 `No`" + return claimed ? lang.getTranslation("params.uppercase.claimed")+": 🟢 `Yes`" : lang.getTranslation("params.uppercase.claimed")+": 🔴 `No`" //TODO TRANSLATION!!! })) ticket.add(new api.ODDynamicStat("openticket:pinned",2,async (scopeId,guild,channel,user) => { const ticket = openticket.tickets.get(scopeId) if (!ticket) return "" const pinned = ticket.exists("openticket:pinned") ? ticket.get("openticket:pinned").value : false - return pinned ? lang.getTranslation("params.uppercase.pinned")+": 🟢 `Yes`" : lang.getTranslation("params.uppercase.pinned")+": 🔴 `No`" + return pinned ? lang.getTranslation("params.uppercase.pinned")+": 🟢 `Yes`" : lang.getTranslation("params.uppercase.pinned")+": 🔴 `No`" //TODO TRANSLATION!!! })) ticket.add(new api.ODDynamicStat("openticket:creation-date",1,async (scopeId,guild,channel,user) => { const ticket = openticket.tickets.get(scopeId) From 7fb169789bc86e3c217fee1d88cd01875f57b6c6 Mon Sep 17 00:00:00 2001 From: JasperAtSchool Date: Tue, 21 Jan 2025 12:05:36 +0100 Subject: [PATCH 102/157] Added new API comments (part 6) --- src/core/api/modules/responder.ts | 72 +++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/core/api/modules/responder.ts b/src/core/api/modules/responder.ts index 0f42eb5..b5d3a2d 100644 --- a/src/core/api/modules/responder.ts +++ b/src/core/api/modules/responder.ts @@ -33,12 +33,33 @@ export class ODResponderImplementation ex } } +/**## ODResponderTimeoutErrorCallback `type` + * This is the callback for the responder timeout function. It will be executed when something went wrong or the action takes too much time. + */ export type ODResponderTimeoutErrorCallback = (instance:Instance, source:Source) => void|Promise +/**## ODResponderManager `class` + * This is an open ticket responder manager. + * + * It contains all Open Ticket responders. Responders can respond to an interaction, button, dropdown, modal or command. + * + * Using the Open Ticket responder system has a few advantages compared to vanilla discord.js: + * - plugins can extend/edit replies + * - automatically reply on error + * - independent workers (with priority) + * - fail-safe design using try-catch + * - write code once => reply to both slash & text commands at the same time! + * - know where the request came from & parse options/subcommands & without errors! + * - And so much more! + */ export class ODResponderManager { + /**A manager for all (text & slash) command responders. */ commands: ODCommandResponderManager + /**A manager for all button responders. */ buttons: ODButtonResponderManager + /**A manager for all dropdown/select menu responders. */ dropdowns: ODDropdownResponderManager + /**A manager for all modal responders. */ modals: ODModalResponderManager constructor(debug:ODDebugger, client:ODClientManager){ @@ -49,9 +70,26 @@ export class ODResponderManager { } } +/**## ODCommandResponderManager `class` + * This is an open ticket command responder manager. + * + * It contains all Open Ticket command responders. These can respond to text & slash commands. + * + * Using the Open Ticket responder system has a few advantages compared to vanilla discord.js: + * - plugins can extend/edit replies + * - automatically reply on error + * - independent workers (with priority) + * - fail-safe design using try-catch + * - write code once => reply to both slash & text commands at the same time! + * - know where the request came from & parse options/subcommands & without errors! + * - And so much more! + */ export class ODCommandResponderManager extends ODManager> { + /**An alias to the Open Ticket client manager. */ #client: ODClientManager + /**The callback executed when the default workers take too much time to reply. */ #timeoutErrorCallback: ODResponderTimeoutErrorCallback|null = null + /**The amount of milliseconds before the timeout error callback is executed. */ #timeoutMs: number|null = null constructor(debug:ODDebugger, debugname:string, client:ODClientManager){ @@ -86,9 +124,17 @@ export class ODCommandResponderManager extends ODManager|null, timeoutMs:number|null, options?:ODTextCommandInteractionOption[]){ From 40bd873a335cc13a0005f77ff579c426464cf1f2 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 22 Jan 2025 15:13:13 +0100 Subject: [PATCH 103/157] Added new API comments (part 7) --- src/core/api/modules/responder.ts | 163 ++++++++++++++++++++++++++-- src/core/api/modules/startscreen.ts | 95 ++++++++++++++++ src/core/api/modules/stat.ts | 79 ++++++++++++++ src/core/api/openticket/option.ts | 6 - 4 files changed, 329 insertions(+), 14 deletions(-) diff --git a/src/core/api/modules/responder.ts b/src/core/api/modules/responder.ts index b5d3a2d..600d93a 100644 --- a/src/core/api/modules/responder.ts +++ b/src/core/api/modules/responder.ts @@ -131,7 +131,7 @@ export class ODCommandResponderManager extends ODManager> { try { const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] @@ -407,6 +408,7 @@ export class ODCommandResponderInstance { return {success:false,message:null} } } + /**Defer this command. */ async defer(ephemeral:boolean){ if (this.type != "interaction" || !(this.interaction instanceof discord.ChatInputCommandInteraction)) return false if (this.interaction.deferred) return false @@ -415,6 +417,7 @@ export class ODCommandResponderInstance { this.didReply = true return true } + /**Show a modal as reply to this command. */ async modal(modal:ODModalBuildResult){ if (this.type != "interaction" || !(this.interaction instanceof discord.ChatInputCommandInteraction)) return false this.interaction.showModal(modal.modal) @@ -423,6 +426,11 @@ export class ODCommandResponderInstance { } } +/**## ODCommandResponder `class` + * This is an open ticket command responder. + * + * This class manages all workers which are executed when the related command is triggered. + */ export class ODCommandResponder extends ODResponderImplementation { /**The prefix of the text command needs to match this */ prefix: string @@ -439,10 +447,27 @@ export class ODCommandResponder extends OD } } +/**## ODButtonResponderManager `class` + * This is an open ticket button responder manager. + * + * It contains all Open Ticket button responders. These can respond to button interactions. + * + * Using the Open Ticket responder system has a few advantages compared to vanilla discord.js: + * - plugins can extend/edit replies + * - automatically reply on error + * - independent workers (with priority) + * - fail-safe design using try-catch + * - know where the request came from! + * - And so much more! + */ export class ODButtonResponderManager extends ODManager> { + /**An alias to the Open Ticket client manager. */ #client: ODClientManager + /**The callback executed when the default workers take too much time to reply. */ #timeoutErrorCallback: ODResponderTimeoutErrorCallback|null = null + /**The amount of milliseconds before the timeout error callback is executed. */ #timeoutMs: number|null = null + /**A list of listeners which will listen to the raw interactionCreate event from discord.js */ #listeners: ((interaction:discord.ButtonInteraction) => void)[] = [] constructor(debug:ODDebugger, debugname:string, client:ODClientManager){ @@ -474,13 +499,25 @@ export class ODButtonResponderManager extends ODManager|null, timeoutMs:number|null){ @@ -510,6 +547,7 @@ export class ODButtonResponderInstance { },timeoutMs ?? 2500) } + /**Reply to this button. */ async reply(msg:ODMessageBuildResult): Promise> { try{ const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] @@ -526,6 +564,7 @@ export class ODButtonResponderInstance { return {success:false,message:null} } } + /**Update the message of this button. */ async update(msg:ODMessageBuildResult): Promise> { try{ const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] @@ -542,6 +581,7 @@ export class ODButtonResponderInstance { return {success:false,message:null} } } + /**Defer this button. */ async defer(type:"reply"|"update", ephemeral:boolean){ if (this.interaction.deferred) return false if (type == "reply"){ @@ -553,12 +593,14 @@ export class ODButtonResponderInstance { this.didReply = true return true } + /**Show a modal as reply to this button. */ async modal(modal:ODModalBuildResult){ this.interaction.showModal(modal.modal) this.didReply = true return true } + /**Get a component from the original message of this button. */ getMessageComponent(type:"button",id:string|RegExp): discord.ButtonComponent|null getMessageComponent(type:"string-dropdown",id:string|RegExp): discord.StringSelectMenuComponent|null getMessageComponent(type:"user-dropdown",id:string|RegExp): discord.UserSelectMenuComponent|null @@ -582,11 +624,17 @@ export class ODButtonResponderInstance { return result } + /**Get the first embed of the original message if it exists. */ getMessageEmbed(): discord.Embed|null { return this.message.embeds[0] ?? null } } +/**## ODButtonResponder `class` + * This is an open ticket button responder. + * + * This class manages all workers which are executed when the related button is triggered. + */ export class ODButtonResponder extends ODResponderImplementation { /**Respond to this button */ async respond(instance:ODButtonResponderInstance, source:Source, params:Params){ @@ -595,10 +643,27 @@ export class ODButtonResponder extends ODResponder } } +/**## ODDropdownResponderManager `class` + * This is an open ticket dropdown responder manager. + * + * It contains all Open Ticket dropdown responders. These can respond to dropdown interactions. + * + * Using the Open Ticket responder system has a few advantages compared to vanilla discord.js: + * - plugins can extend/edit replies + * - automatically reply on error + * - independent workers (with priority) + * - fail-safe design using try-catch + * - know where the request came from! + * - And so much more! + */ export class ODDropdownResponderManager extends ODManager> { + /**An alias to the Open Ticket client manager. */ #client: ODClientManager + /**The callback executed when the default workers take too much time to reply. */ #timeoutErrorCallback: ODResponderTimeoutErrorCallback|null = null + /**The amount of milliseconds before the timeout error callback is executed. */ #timeoutMs: number|null = null + /**A list of listeners which will listen to the raw interactionCreate event from discord.js */ #listeners: ((interaction:discord.AnySelectMenuInteraction) => void)[] = [] constructor(debug:ODDebugger, debugname:string, client:ODClientManager){ @@ -630,8 +695,15 @@ export class ODDropdownResponderManager extends ODManager { if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getRoleValues() dropdown type isn't role!") try { @@ -663,6 +738,7 @@ export class ODDropdownResponderInstanceValues { throw new ODSystemError("ODDropdownResponderInstanceValues:getRoleValues() invalid values!") } } + /**Get the selected users. */ async getUserValues(): Promise { if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getUserValues() dropdown type isn't user!") try { @@ -676,6 +752,7 @@ export class ODDropdownResponderInstanceValues { throw new ODSystemError("ODDropdownResponderInstanceValues:getUserValues() invalid values!") } } + /**Get the selected channels. */ async getChannelValues(): Promise { if (this.#type != "role") throw new ODSystemError("ODDropdownResponderInstanceValues:getChannelValues() dropdown type isn't channel!") try { @@ -692,15 +769,29 @@ export class ODDropdownResponderInstanceValues { } } +/**## ODDropdownResponderInstance `class` + * This is an open ticket dropdown responder instance. + * + * An instance is an active dropdown interaction. You can reply to the dropdown using `reply()`. + */ export class ODDropdownResponderInstance { - interaction:discord.AnySelectMenuInteraction + /**The interaction which is the source of this instance. */ + interaction: discord.AnySelectMenuInteraction + /**Did a worker already reply to this instance/interaction? */ didReply: boolean = false + /**The dropdown type. */ type: ODDropdownData["type"] + /**The manager for all values of this dropdown. */ values: ODDropdownResponderInstanceValues + /**The user who triggered this dropdown. */ user: discord.User + /**The guild member who triggered this dropdown. */ member: discord.GuildMember|null + /**The guild where this dropdown was triggered. */ guild: discord.Guild|null + /**The channel where this dropdown was triggered. */ channel: discord.TextBasedChannel + /**The message this dropdown originates from. */ message: discord.Message constructor(interaction:discord.AnySelectMenuInteraction, errorCallback:ODResponderTimeoutErrorCallback|null, timeoutMs:number|null){ @@ -743,6 +834,7 @@ export class ODDropdownResponderInstance { },timeoutMs ?? 2500) } + /**Reply to this dropdown. */ async reply(msg:ODMessageBuildResult): Promise> { try { const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] @@ -759,6 +851,7 @@ export class ODDropdownResponderInstance { return {success:false,message:null} } } + /**Update the message of this dropdown. */ async update(msg:ODMessageBuildResult): Promise> { try{ const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] @@ -775,6 +868,7 @@ export class ODDropdownResponderInstance { return {success:false,message:null} } } + /**Defer this dropdown. */ async defer(type:"reply"|"update", ephemeral:boolean){ if (this.interaction.deferred) return false if (type == "reply"){ @@ -786,12 +880,14 @@ export class ODDropdownResponderInstance { this.didReply = true return true } + /**Show a modal as reply to this dropdown. */ async modal(modal:ODModalBuildResult){ this.interaction.showModal(modal.modal) this.didReply = true return true } + /**Get a component from the original message of this dropdown. */ getMessageComponent(type:"button",id:string|RegExp): discord.ButtonComponent|null getMessageComponent(type:"string-dropdown",id:string|RegExp): discord.StringSelectMenuComponent|null getMessageComponent(type:"user-dropdown",id:string|RegExp): discord.UserSelectMenuComponent|null @@ -815,11 +911,17 @@ export class ODDropdownResponderInstance { return result } + /**Get the first embed of the original message if it exists. */ getMessageEmbed(): discord.Embed|null { return this.message.embeds[0] ?? null } } +/**## ODDropdownResponder `class` + * This is an open ticket dropdown responder. + * + * This class manages all workers which are executed when the related dropdown is triggered. + */ export class ODDropdownResponder extends ODResponderImplementation { /**Respond to this dropdown */ async respond(instance:ODDropdownResponderInstance, source:Source, params:Params){ @@ -828,10 +930,27 @@ export class ODDropdownResponder extends ODRespond } } +/**## ODModalResponderManager `class` + * This is an open ticket modal responder manager. + * + * It contains all Open Ticket modal responders. These can respond to modal interactions. + * + * Using the Open Ticket responder system has a few advantages compared to vanilla discord.js: + * - plugins can extend/edit replies + * - automatically reply on error + * - independent workers (with priority) + * - fail-safe design using try-catch + * - know where the request came from! + * - And so much more! + */ export class ODModalResponderManager extends ODManager> { + /**An alias to the Open Ticket client manager. */ #client: ODClientManager + /**The callback executed when the default workers take too much time to reply. */ #timeoutErrorCallback: ODResponderTimeoutErrorCallback|null = null + /**The amount of milliseconds before the timeout error callback is executed. */ #timeoutMs: number|null = null + /**A list of listeners which will listen to the raw interactionCreate event from discord.js */ #listeners: ((interaction:discord.ModalSubmitInteraction) => void)[] = [] constructor(debug:ODDebugger, debugname:string, client:ODClientManager){ @@ -863,12 +982,20 @@ export class ODModalResponderManager extends ODManager|null, timeoutMs:number|null){ @@ -917,6 +1056,7 @@ export class ODModalResponderInstance { },timeoutMs ?? 2500) } + /**Reply to this modal. */ async reply(msg:ODMessageBuildResult): Promise> { try{ const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] @@ -933,6 +1073,7 @@ export class ODModalResponderInstance { return {success:false,message:null} } } + /**Update the message of this modal. */ async update(msg:ODMessageBuildResult): Promise> { try{ const msgFlags: number[] = msg.ephemeral ? [discord.MessageFlags.Ephemeral] : [] @@ -945,6 +1086,7 @@ export class ODModalResponderInstance { return {success:false,message:null} } } + /**Defer this modal. */ async defer(type:"reply"|"update", ephemeral:boolean){ if (this.interaction.deferred) return false if (type == "reply"){ @@ -958,6 +1100,11 @@ export class ODModalResponderInstance { } } +/**## ODModalResponder `class` + * This is an open ticket modal responder. + * + * This class manages all workers which are executed when the related modal is triggered. + */ export class ODModalResponder extends ODResponderImplementation { /**Respond to this modal */ async respond(instance:ODModalResponderInstance, source:Source, params:Params){ diff --git a/src/core/api/modules/startscreen.ts b/src/core/api/modules/startscreen.ts index 80c106d..92b5a60 100644 --- a/src/core/api/modules/startscreen.ts +++ b/src/core/api/modules/startscreen.ts @@ -7,8 +7,17 @@ import { ODFlag } from "./flag" import { ODPlugin, ODUnknownCrashedPlugin } from "./plugin" import ansis from "ansis" +/**## ODStartScreenComponentRenderCallback `type` + * This is the render function of a startscreen component. It also sends the location of where the component is rendered. + */ export type ODStartScreenComponentRenderCallback = (location:number) => string|Promise +/**## ODStartScreenManager `class` + * This is an open ticket startscreen manager. + * + * This class is responsible for managing & rendering the startscreen of the bot. + * The startscreen is the part you see when the bot has started up successfully. (e.g. the Open Ticket logo, logs, livestatus, flags, ...) + */ export class ODStartScreenManager extends ODManager { /**Alias to the Open Ticket debugger. */ #debug: ODDebugger @@ -47,10 +56,22 @@ export class ODStartScreenManager extends ODManager { } } +/**## ODStartScreenComponent `class` + * This is an open ticket startscreen component. + * + * This component can be rendered to the start screen of the bot. + * An optional priority can be specified to choose the location of the component. + * + * It's recommended to use pre-built components except if you really need a custom one. + */ export class ODStartScreenComponent extends ODManagerData { + /**The priority of this component. */ priority: number + /**An optional render function which will be inserted before the default renderer. */ renderBefore: ODStartScreenComponentRenderCallback|null = null + /**The render function which will render the contents of this component. */ render: ODStartScreenComponentRenderCallback + /**An optional render function which will be inserted behind the default renderer. */ renderAfter: ODStartScreenComponentRenderCallback|null = null constructor(id:ODValidId, priority:number, render:ODStartScreenComponentRenderCallback){ @@ -59,6 +80,7 @@ export class ODStartScreenComponent extends ODManagerData { this.render = render } + /**Render this component and combine it with the `renderBefore` & `renderAfter` contents. */ async renderAll(location:number){ const textBefore = (this.renderBefore) ? await this.renderBefore(location) : "" const text = await this.render(location) @@ -67,15 +89,30 @@ export class ODStartScreenComponent extends ODManagerData { } } +/**## ODStartScreenProperty `type` + * This interface contains properties used in a few default templates of the startscreen component. + */ export interface ODStartScreenProperty { + /**The key or name of this property. */ key:string, + /**The value or contents of this property. */ value:string } +/**## ODStartScreenLogoComponent `class` + * This is an open ticket startscreen logo component. + * + * This component will render an ASCII art logo (from an array) to the startscreen. Every property in the array is another row. + * An optional priority can be specified to choose the location of the component. + */ export class ODStartScreenLogoComponent extends ODStartScreenComponent { + /**The ASCII logo contents. */ logo: string[] + /**When enabled, the component will add a new line above the logo. */ topPadding: boolean + /**When enabled, the component will add a new line below the logo. */ bottomPadding: boolean + /**The color of the logo in hex format. */ logoHexColor: string constructor(id:ODValidId, priority:number, logo:string[], topPadding?:boolean, bottomPadding?:boolean, logoHexColor?:string){ @@ -92,14 +129,28 @@ export class ODStartScreenLogoComponent extends ODStartScreenComponent { } } +/**## ODStartScreenHeaderAlignmentSettings `type` + * This interface contains all settings used in the startscreen header component. + */ export interface ODStartScreenHeaderAlignmentSettings { + /**The alignment settings for this header. */ align:"center"|"left"|"right", + /**The width or component to use when calculating center & right alignment. */ width:number|ODStartScreenComponent } +/**## ODStartScreenHeaderComponent `class` + * This is an open ticket startscreen header component. + * + * This component will render a header to the startscreen. Properties can be aligned left, right or centered. + * An optional priority can be specified to choose the location of the component. + */ export class ODStartScreenHeaderComponent extends ODStartScreenComponent { + /**All properties of this header component. */ properties: ODStartScreenProperty[] + /**The spacer used between properties. */ spacer: string + /**The alignment settings of this header component. */ align: ODStartScreenHeaderAlignmentSettings|null constructor(id:ODValidId, priority:number, properties:ODStartScreenProperty[], spacer?:string, align?:ODStartScreenHeaderAlignmentSettings){ @@ -140,8 +191,16 @@ export class ODStartScreenHeaderComponent extends ODStartScreenComponent { } } +/**## ODStartScreenCategoryComponent `class` + * This is an open ticket startscreen category component. + * + * This component will render a category to the startscreen. This will only render the category name. You'll need to provide your own renderer for the contents. + * An optional priority can be specified to choose the location of the component. + */ export class ODStartScreenCategoryComponent extends ODStartScreenComponent { + /**The name of this category. */ name: string + /**When enabled, this category will still be rendered when the contents are empty. (enabled by default) */ renderIfEmpty: boolean constructor(id:ODValidId, priority:number, name:string, render:ODStartScreenComponentRenderCallback, renderIfEmpty?:boolean){ @@ -156,8 +215,16 @@ export class ODStartScreenCategoryComponent extends ODStartScreenComponent { } } +/**## ODStartScreenPropertiesCategoryComponent `class` + * This is an open ticket startscreen properties category component. + * + * This component will render a properties category to the startscreen. This will list the properties in the category. + * An optional priority can be specified to choose the location of the component. + */ export class ODStartScreenPropertiesCategoryComponent extends ODStartScreenCategoryComponent { + /**The properties of this category component. */ properties: ODStartScreenProperty[] + /**The hex color for the key/name of all the properties. */ propertyHexColor: string constructor(id:ODValidId, priority:number, name:string, properties:ODStartScreenProperty[], propertyHexColor?:string, renderIfEmpty?:boolean){ @@ -170,7 +237,14 @@ export class ODStartScreenPropertiesCategoryComponent extends ODStartScreenCateg } } +/**## ODStartScreenFlagsCategoryComponent `class` + * This is an open ticket startscreen flags category component. + * + * This component will render a flags category to the startscreen. This will list the enabled flags in the category. + * An optional priority can be specified to choose the location of the component. + */ export class ODStartScreenFlagsCategoryComponent extends ODStartScreenCategoryComponent { + /**A list of all flags to render. */ flags: ODFlag[] constructor(id:ODValidId, priority:number, flags:ODFlag[]){ @@ -181,8 +255,16 @@ export class ODStartScreenFlagsCategoryComponent extends ODStartScreenCategoryCo } } +/**## ODStartScreenPluginsCategoryComponent `class` + * This is an open ticket startscreen plugins category component. + * + * This component will render a plugins category to the startscreen. This will list the enabled, disabled & crashed plugins in the category. + * An optional priority can be specified to choose the location of the component. + */ export class ODStartScreenPluginsCategoryComponent extends ODStartScreenCategoryComponent { + /**A list of all plugins to render. */ plugins: ODPlugin[] + /**A list of all crashed plugins to render. */ unknownCrashedPlugins: ODUnknownCrashedPlugin[] constructor(id:ODValidId, priority:number, plugins:ODPlugin[], unknownCrashedPlugins:ODUnknownCrashedPlugin[]){ @@ -200,7 +282,14 @@ export class ODStartScreenPluginsCategoryComponent extends ODStartScreenCategory } } +/**## ODStartScreenLiveStatusCategoryComponent `class` + * This is an open ticket startscreen livestatus category component. + * + * This component will render a livestatus category to the startscreen. This will list the livestatus messages in the category. + * An optional priority can be specified to choose the location of the component. + */ export class ODStartScreenLiveStatusCategoryComponent extends ODStartScreenCategoryComponent { + /**A reference to the Open Ticket livestatus manager. */ livestatus: ODLiveStatusManager constructor(id:ODValidId, priority:number, livestatus:ODLiveStatusManager){ @@ -212,6 +301,12 @@ export class ODStartScreenLiveStatusCategoryComponent extends ODStartScreenCateg } } +/**## ODStartScreenLogsCategoryComponent `class` + * This is an open ticket startscreen logs category component. + * + * This component will render a logs category to the startscreen. This will only render the logs category name. + * An optional priority can be specified to choose the location of the component. + */ export class ODStartScreenLogCategoryComponent extends ODStartScreenCategoryComponent { constructor(id:ODValidId, priority:number){ super(id,priority,"logs",() => "",true) diff --git a/src/core/api/modules/stat.ts b/src/core/api/modules/stat.ts index fb91120..ef22771 100644 --- a/src/core/api/modules/stat.ts +++ b/src/core/api/modules/stat.ts @@ -6,10 +6,31 @@ import { ODDebugger } from "./console" import { ODDatabase, ODJsonDatabaseStructure } from "./database" import * as discord from "discord.js" +/**## ODValidStatValue `type` + * These are the only allowed types for a stat value to improve compatibility with different database systems. + */ export type ODValidStatValue = string|number|boolean + +/**## ODStatsManagerInitCallback `type` + * This callback can be used to execute something when the stats have been initiated. + * + * By default this is used to clear stats from users that left the server or tickets which don't exist anymore. + */ export type ODStatsManagerInitCallback = (database:ODJsonDatabaseStructure, deletables:ODJsonDatabaseStructure) => void|Promise + +/**## ODStatScopeSetMode `type` + * This type contains all valid methods for changing the value of a stat. + */ export type ODStatScopeSetMode = "set"|"increase"|"decrease" +/**## ODStatsManager `class` + * This is an open ticket stats manager. + * + * This class is responsible for managing all stats of the bot. + * Stats are categorized in "scopes" which can be accessed in this manager. + * + * Stats can be accessed in the individual scopes. + */ export class ODStatsManager extends ODManager { /**Alias to open ticket debugger. */ #debug: ODDebugger @@ -23,6 +44,7 @@ export class ODStatsManager extends ODManager { this.#debug = debug } + /**Select the database to use to read/write all stats from/to. */ useDatabase(database:ODDatabase){ this.database = database } @@ -31,6 +53,7 @@ export class ODStatsManager extends ODManager { if (this.database) data.useDatabase(this.database) return super.add(data,overwrite) } + /**Init all stats and run `onInit()` listeners. */ async init(){ if (!this.database) throw new ODSystemError("Unable to initialize stats scopes due to missing database!") @@ -58,6 +81,7 @@ export class ODStatsManager extends ODManager { await this.database.delete(data.category,data.key) } } + /**Reset all stats. (clears the entire database) */ async reset(){ if (!this.database) return const data = await this.database.getAll() @@ -66,11 +90,20 @@ export class ODStatsManager extends ODManager { await this.database.delete(d.category,d.key) } } + /**Run a function when the stats are initialized. This can be used to clear stats from users that left the server or tickets which don't exist anymore. */ onInit(callback:ODStatsManagerInitCallback){ this.#initListeners.push(callback) } } +/**## ODStatScope `class` + * This is an open ticket stat scope. + * + * A scope can contain multiple stats. Every scope is seperated from other scopes. + * Here, you can read & write the values of all stats. + * + * The built-in Open Ticket scopes are: `global`, `user`, `ticket` + */ export class ODStatScope extends ODManager { /**The id of this statistics scope. */ id: ODId @@ -87,9 +120,11 @@ export class ODStatScope extends ODManager { this.name = name } + /**Select the database to use to read/write all stats from/to. (Automatically assigned when used in `ODStatsManager`) */ useDatabase(database:ODDatabase){ this.database = database } + /**Get the value of a statistic. The `scopeId` is the unique id of the user, channel, role, etc that the stats are related to. */ async getStat(id:ODValidId, scopeId:string): Promise { if (!this.database) return null const newId = new ODId(id) @@ -105,6 +140,7 @@ export class ODStatScope extends ODManager { //return null on error return null } + /**Set, increase or decrease the value of a statistic. The `scopeId` is the unique id of the user, channel, role, etc that the stats are related to. */ async setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise { if (!this.database) return false const stat = this.get(id) @@ -122,6 +158,7 @@ export class ODStatScope extends ODManager { } return true } + /**Reset the value of a statistic to the initial value. The `scopeId` is the unique id of the user, channel, role, etc that the stats are related to. */ async resetStat(id:ODValidId, scopeId:string): Promise { if (!this.database) return null const stat = this.get(id) @@ -129,11 +166,13 @@ export class ODStatScope extends ODManager { if (stat.value != null) await this.database.set(this.id.value+"_"+stat.id.value,scopeId,stat.value) return stat.value } + /**Initialize this stat scope & return a list of all statistic ids in the following format: `_` */ init(): string[] { //get all valid stats categories this.ready = true return this.getAll().map((stat) => this.id.value+"_"+stat.id.value) } + /**Render all stats in this scope for usage in a discord message/embed. */ async render(scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User): Promise { //sort from high priority to low const derefArray = [...this.getAll()] @@ -162,6 +201,14 @@ export class ODStatScope extends ODManager { } } +/**## ODStatGlobalScope `class` + * This is an open ticket stat global scope. + * + * A scope can contain multiple stats. Every scope is seperated from other scopes. + * Here, you can read & write the values of all stats. + * + * This scope is made specifically for the global stats of Open Ticket. + */ export class ODStatGlobalScope extends ODStatScope { getStat(id:ODValidId): Promise { return super.getStat(id,"GLOBAL") @@ -177,11 +224,25 @@ export class ODStatGlobalScope extends ODStatScope { } } +/**## ODStatRenderer `type` + * This callback will render a single statistic for a discord embed/message. + */ export type ODStatRenderer = (value:ODValidStatValue, scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise +/**## ODStat `class` + * This is an open ticket statistic. + * + * This single statistic doesn't do anything except defining the rules of this statistic. + * Use it in a stats scope to register a new statistic. A statistic can also include a priority to choose the render priority. + * + * It's recommended to use the `ODBasicStat` & `ODDynamicStat` classes instead of this one! + */ export class ODStat extends ODManagerData { + /**The priority of this statistic. */ priority: number + /**The render function of this statistic. */ render: ODStatRenderer + /**The value of this statistic. */ value: ODValidStatValue|null constructor(id:ODValidId, priority:number, render:ODStatRenderer, value?:ODValidStatValue){ @@ -192,7 +253,14 @@ export class ODStat extends ODManagerData { } } +/**## ODBasicStat `class` + * This is an open ticket basic statistic. + * + * This single statistic will store a number, boolean or string in the database. + * Use it to create a simple statistic for any stats scope. + */ export class ODBasicStat extends ODStat { + /**The name of this stat. Rendered in discord embeds/messages. */ name: string constructor(id:ODValidId, priority:number, name:string, value:ODValidStatValue){ @@ -203,8 +271,19 @@ export class ODBasicStat extends ODStat { } } +/**## ODDynamicStatRenderer `type` + * This callback will render a single dynamic statistic for a discord embed/message. + */ export type ODDynamicStatRenderer = (scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise +/**## ODDynamicStat `class` + * This is an open ticket dynamic statistic. + * + * A dynamic statistic does not store anything in the database! Instead, it will execute a function to return a custom result. + * This can be used to show statistics which are not stored in the database. + * + * This is used in Open Ticket for the live ticket status, participants & system status. + */ export class ODDynamicStat extends ODStat { constructor(id:ODValidId, priority:number, render:ODDynamicStatRenderer){ super(id,priority,(value,scopeId,guild,channel,user) => { diff --git a/src/core/api/openticket/option.ts b/src/core/api/openticket/option.ts index 9e717fc..c75838f 100644 --- a/src/core/api/openticket/option.ts +++ b/src/core/api/openticket/option.ts @@ -276,16 +276,10 @@ export class ODRoleOption extends ODOption { } export class ODOptionSuffixManager extends ODManager { - /**Alias to open ticket global database. */ - database: ODDatabase|null = null - constructor(debug:ODDebugger){ super(debug,"ticket suffix") } - useDatabase(database:ODDatabase){ - this.database = database - } /**Instantly get the suffix from an option. */ getSuffixFromOption(option:ODTicketOption,user:discord.User): string|null { const suffix = this.getAll().find((suffix) => suffix.option.id.value == option.id.value) From 3bd308007c781dd6ef5c88918940161745d64c7e Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 22 Jan 2025 16:58:24 +0100 Subject: [PATCH 104/157] Updated sponsors --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c8c74ff..9256e7b 100644 --- a/README.md +++ b/README.md @@ -65,9 +65,11 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat + +
Profile PictureProfile Picture
roppl3rBENZORICH
From 66b0377a2b1636d589629ab05497ff922887bc79 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 22 Jan 2025 17:11:01 +0100 Subject: [PATCH 105/157] Update index.ts --- plugins/example-plugin/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/example-plugin/index.ts b/plugins/example-plugin/index.ts index fce3aac..c664819 100644 --- a/plugins/example-plugin/index.ts +++ b/plugins/example-plugin/index.ts @@ -10,6 +10,9 @@ if (utilities.project != "openticket") throw new api.ODPluginError("This plugin //Add Typescript autocomplete support for plugin data. (!!!OPTIONAL!!!) declare module "#opendiscord-types" { + export interface ODPluginManagerIds_Default { + "example-plugin":api.ODPlugin + } export interface ODConfigManagerIds_Default { "example-plugin:config":api.ODJsonConfig } From 19e5902320bb8739b23a1a7bd6127e44ae450d9f Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Fri, 24 Jan 2025 17:34:05 +0100 Subject: [PATCH 106/157] Fixed: checker not working correctly using .env Fixed the config checker not working correctly when parsing the token from the .env file. --- config/general.json | 2 +- src/data/framework/checkerLoader.ts | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/config/general.json b/config/general.json index b45ca8f..4905aa3 100644 --- a/config/general.json +++ b/config/general.json @@ -5,7 +5,7 @@ "version":"open-ticket-v4.0.0" }, - "token":"your bot token here! Or leave empty when you use tokenFromENV", + "token":"your bot token here! (or leave empty when using 'tokenFromENV')", "tokenFromENV":false, "mainColor":"#f8ba00", diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts index 8d7f271..70603a3 100644 --- a/src/data/framework/checkerLoader.ts +++ b/src/data/framework/checkerLoader.ts @@ -169,6 +169,12 @@ const createPanelEmbedStructure = (id:api.ODValidId) => { ]})}) } +function loadFromEnv(){ + const generalConfig = openticket.configs.get("openticket:general") + if (generalConfig.data && generalConfig.data.tokenFromENV && typeof generalConfig.data.tokenFromENV == "boolean") return generalConfig.data.tokenFromENV + else return false +} + //STRUCTURES export const defaultGeneralStructure = new api.ODCheckerObjectStructure("openticket:general",{children:[ //STATUS @@ -187,7 +193,7 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opentic ]})}, //BASIC - {key:"token",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordToken("openticket:token")}, + {key:"token",optional:false,priority:0,checker:(loadFromEnv()) ? new api.ODCheckerStringStructure("openticket:token-disabled",{}) : new api.ODCheckerCustomStructure_DiscordToken("openticket:token")}, {key:"tokenFromENV",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:token-env",{})}, {key:"mainColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:main-color",true,false)}, {key:"language",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:language",{ From d35eb8f8bf6845df5d3e9ef048511dfb3970b1eb Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 25 Jan 2025 10:56:18 +0100 Subject: [PATCH 107/157] Updated issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 4 +-- .github/ISSUE_TEMPLATE/documentation.md | 27 +++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 27 +++++++++++++++++++ .github/ISSUE_TEMPLATE/html_transcripts.md | 20 +++++++++++++++ .github/ISSUE_TEMPLATE/new_language.md | 30 ++++++++++++++++++++++ .github/ISSUE_TEMPLATE/plugin_request.md | 20 +++++++++++++++ .github/ISSUE_TEMPLATE/question.md | 28 ++++++++++++++++++++ .github/ISSUE_TEMPLATE/updated_language.md | 24 +++++++++++++++++ 8 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/documentation.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/ISSUE_TEMPLATE/html_transcripts.md create mode 100644 .github/ISSUE_TEMPLATE/new_language.md create mode 100644 .github/ISSUE_TEMPLATE/plugin_request.md create mode 100644 .github/ISSUE_TEMPLATE/question.md create mode 100644 .github/ISSUE_TEMPLATE/updated_language.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 311eb2f..eb3b7f0 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,9 +1,7 @@ --- name: Bug Report about: Report bugs to help us improve Open Ticket! -title: "[BUG] Your Bug" -labels: bug -assignees: DJj123dj +title: "Your Bug Name" --- ### Bug Description: diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 0000000..718003a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,27 @@ +--- +name: Documentation +about: Do you know anything to be improved in the Open Ticket documentation? +title: "Documentation Improvement Name" +labels: "Documentation" +--- + +### Related Docs/Systems: +Choose related systems/docs for this improvement/change: +- [ ] Guides +- [ ] Developer Guides +- [ ] API Reference +- [ ] Blog +- [ ] System (Docusaurus & Javascript) +- [ ] Assets (images) +- [ ] Other + +### Improvement Description: +A clear and concise description of the improvement. + +> Please explain it as detailed as possible! + +### Screenshots: +If applicable, add screenshots to help explain your request. + +### Additional Notes: +Add any other context about the request here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..90d54e1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,27 @@ +--- +name: Feature Request +about: Do you have a great idea for Open Ticket? Let us know using this issue! +title: "Your Feature Name" +labels: "Concept" +--- + +### Feature Description: +A clear and concise description of what the feature is. + +### Affected Systems +Systems which are affected, improved or modified: +- (example) Slash command registration... +- (example) API embed builders... +- Scroll down to '....' +- See error + +> Leave empty when you don't know which parts this feature affects! + +### Advantages & Use Cases: +What advantages & use cases do you think this feature would result in? + +### Screenshots: +If applicable, add screenshots to help explain your feature request. + +### Additional Notes: +Add any other context about the request here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/html_transcripts.md b/.github/ISSUE_TEMPLATE/html_transcripts.md new file mode 100644 index 0000000..a3b2484 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/html_transcripts.md @@ -0,0 +1,20 @@ +--- +name: HTML Transcripts +about: Found a bug related to the HTML Transcripts? Or do you have a feature request? +title: "Your Bug/Improvement Name" +labels: "HTML Transcripts" +--- + +### Feature/Bug Description: +A clear and concise description of what the feature/bug report is. + +### Screenshots: +If applicable, add screenshots to help explain your feature request or bug report. + +### Files: +Please include the `otdebug.txt` file in your report! With this file, we can take a deep-dive in to the error that happend. +> #### Include this file for bug reports! +> This file doesn't contain any credentials or sensitive information! + +### Additional Notes: +Add any other context about the problem here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/new_language.md b/.github/ISSUE_TEMPLATE/new_language.md new file mode 100644 index 0000000..2f54f30 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new_language.md @@ -0,0 +1,30 @@ +--- +name: New Language +about: Do you want to add a new language to Open Ticket? +title: "Language Name" +labels: "New Translation" +--- + +### Language Name +The name of the new language. + +### Language Description/Details: +A clear and concise description of the translation/language. + +### Checklist +Before the language is fully implemented, the following checklist must be met: +- [ ] **📌 Created a language file in the `./languages/` directory.** +- [ ] **📌 The translation file uses the `.json` format.** +- [ ] **📌 The `"_TRANSLATION"` metadata in the language file is correctly configured.** + - [ ] The `"otversion"` is correct. + - [ ] The `"translators"` list is up to date has the discord/github usernames from all translators. + - [ ] The `"lastedited"` variable is the last edited date in the following format: `DD/MM/YYYY`. + - [ ] The `"language"` variable is the name of the language in English. + - [ ] `"automated"` is enabled when `Google Translate`, `DeepL`, `ChatGPT` or any other kind of translation tools were used. +- [ ] **📌 The language has been added to the `README.md` list.** +- [ ] **📌 The language counters have been updated in the `README.md`.** +- [ ] **📌 The language has been added to the list in the `ODLanguageManagerIds_Default` interface in (`./src/core/api/defaults/language.ts`).** +- [ ] **📌 The language has been added to the list in `./src/data/languageLoader.ts`.** + +### Additional Notes: +Add any other context about the problem here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/plugin_request.md b/.github/ISSUE_TEMPLATE/plugin_request.md new file mode 100644 index 0000000..4300ef0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/plugin_request.md @@ -0,0 +1,20 @@ +--- +name: Plugin Request +about: Do you have an idea for an Open Ticket plugin? +title: "Your Plugin Name" +labels: "Plugin" +--- + +### Plugin Description: +A clear and concise description of what the plugin is & does. + +> Please explain the plugin as detailed as possible! + +### Advantages & Use Cases: +What advantages & use cases do you think this plugin would result in? + +### Screenshots: +If applicable, add screenshots to help explain your plugin request. + +### Additional Notes: +Add any other context about the request here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 0000000..1def67d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,28 @@ +--- +name: Question +about: Do you have a question about Open Ticket? +title: "My Question" +labels: "Question" +--- + +### Question: +A clear and concise description of the question. + +> Please explain the question as detailed as possible! + +### Screenshots: +If applicable, add screenshots to help explain your plugin request. + +### Checklist: +Before creating this question, the following checklist must be met: +- [ ] **📌 I've read the docs (https://otdocs.dj-dj.be) and I didn't found the solution.** +- [ ] **📌 I've asked other people & they didn't know the solution.** +- [ ] **📌 The question is not related to the following subjects: (If so, ask it in our discord server: https://discord.dj-dj.be)** + - Configuring the bot + - Hosting the bot (24/7) + - Updating the bot +- [ ] **📌 I know that this issue is publicly visible for everyone and I haven't shared any private info.** + + +### Additional Notes: +Add any other context about the request here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/updated_language.md b/.github/ISSUE_TEMPLATE/updated_language.md new file mode 100644 index 0000000..15f1cd9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/updated_language.md @@ -0,0 +1,24 @@ +--- +name: Updated Language +about: Do you want to update/improve an existing language in Open Ticket? +title: "Language Name" +labels: "Updated Translation" +--- + +### Language Name +The name of the existing language. + +### Language Description/Details: +A clear and concise description of the translation/language changes. + +### Checklist +Before the language is updated, the following checklist must be met: +- [ ] **📌 The `"_TRANSLATION"` metadata in the language file is correctly configured.** + - [ ] The `"otversion"` is correct. + - [ ] The `"translators"` list is up to date has the discord/github usernames from all translators. + - [ ] The `"lastedited"` variable is the last edited date in the following format: `DD/MM/YYYY`. + - [ ] The `"language"` variable is the name of the language in English. + - [ ] `"automated"` is enabled when `Google Translate`, `DeepL`, `ChatGPT` or any other kind of translation tools were used. + +### Additional Notes: +Add any other context about the problem here. \ No newline at end of file From 057a5fc6ae7b6d1b985ca0c21f39904520311041 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 25 Jan 2025 11:18:10 +0100 Subject: [PATCH 108/157] Fixed #124 : DMs are now sent to ticket creator --- src/actions/addTicketUser.ts | 3 ++- src/actions/claimTicket.ts | 3 ++- src/actions/closeTicket.ts | 3 ++- src/actions/deleteTicket.ts | 3 ++- src/actions/moveTicket.ts | 3 ++- src/actions/pinTicket.ts | 3 ++- src/actions/removeTicketUser.ts | 3 ++- src/actions/renameTicket.ts | 3 ++- src/actions/reopenTicket.ts | 3 ++- src/actions/unclaimTicket.ts | 3 ++- src/actions/unpinTicket.ts | 3 ++- 11 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/actions/addTicketUser.ts b/src/actions/addTicketUser.ts index 8081b91..becfd0a 100644 --- a/src/actions/addTicketUser.ts +++ b/src/actions/addTicketUser.ts @@ -65,7 +65,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.adding.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.adding.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket,data} = params diff --git a/src/actions/claimTicket.ts b/src/actions/claimTicket.ts index 6ce25a3..ba0e6c7 100644 --- a/src/actions/claimTicket.ts +++ b/src/actions/claimTicket.ts @@ -74,7 +74,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.claiming.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.claiming.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params diff --git a/src/actions/closeTicket.ts b/src/actions/closeTicket.ts index b414851..350869e 100644 --- a/src/actions/closeTicket.ts +++ b/src/actions/closeTicket.ts @@ -132,7 +132,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.closing.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.closing.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params diff --git a/src/actions/deleteTicket.ts b/src/actions/deleteTicket.ts index e6f8367..447d9d5 100644 --- a/src/actions/deleteTicket.ts +++ b/src/actions/deleteTicket.ts @@ -76,7 +76,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.deleting.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.deleting.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) }), new api.ODWorker("openticket:delete-channel",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params diff --git a/src/actions/moveTicket.ts b/src/actions/moveTicket.ts index dfcd7ba..840cd26 100644 --- a/src/actions/moveTicket.ts +++ b/src/actions/moveTicket.ts @@ -198,7 +198,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.moving.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.moving.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params diff --git a/src/actions/pinTicket.ts b/src/actions/pinTicket.ts index c0dfb32..8348215 100644 --- a/src/actions/pinTicket.ts +++ b/src/actions/pinTicket.ts @@ -72,7 +72,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.pinning.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.pinning.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params diff --git a/src/actions/removeTicketUser.ts b/src/actions/removeTicketUser.ts index b22b62b..d72f7b7 100644 --- a/src/actions/removeTicketUser.ts +++ b/src/actions/removeTicketUser.ts @@ -59,7 +59,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.removing.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.removing.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket,data} = params diff --git a/src/actions/renameTicket.ts b/src/actions/renameTicket.ts index 312be72..ba294b8 100644 --- a/src/actions/renameTicket.ts +++ b/src/actions/renameTicket.ts @@ -56,7 +56,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.renaming.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.renaming.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params diff --git a/src/actions/reopenTicket.ts b/src/actions/reopenTicket.ts index dccf05c..1893b1f 100644 --- a/src/actions/reopenTicket.ts +++ b/src/actions/reopenTicket.ts @@ -158,7 +158,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.reopening.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.reopening.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params diff --git a/src/actions/unclaimTicket.ts b/src/actions/unclaimTicket.ts index 302fb3a..1841453 100644 --- a/src/actions/unclaimTicket.ts +++ b/src/actions/unclaimTicket.ts @@ -103,7 +103,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.claiming.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.claiming.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params diff --git a/src/actions/unpinTicket.ts b/src/actions/unpinTicket.ts index e624c65..c5baab5 100644 --- a/src/actions/unpinTicket.ts +++ b/src/actions/unpinTicket.ts @@ -65,7 +65,8 @@ export const registerActions = async () => { } //to dm - if (generalConfig.data.system.messages.pinning.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) + const creator = await openticket.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.pinning.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params From 73d188c5dc581cb6fdc3374b55863a412b81f3e9 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 25 Jan 2025 11:28:32 +0100 Subject: [PATCH 109/157] Fixed #129 : Improved invalid token error --- src/core/api/modules/client.ts | 6 ++++-- src/index.ts | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index 393b9dd..1633032 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -147,9 +147,11 @@ export class ODClientManager { this.#debug.debug("Finished discord.js client.login()") this.loggedIn = true }catch(err){ - if (err.message.toLowerCase() == "used disallowed intents"){ + if (err.message.toLowerCase().includes("used disallowed intents")){ process.emit("uncaughtException",new ODSystemError("Used disallowed intents")) - }else reject("login error: "+err) + }else if (err.message.toLowerCase().includes("tokeninvalid") || err.message.toLowerCase().includes("an invalid token was provided")){ + process.emit("uncaughtException",new ODSystemError("Invalid discord bot token provided")) + }else reject("OT Login Error: "+err) } }) } diff --git a/src/index.ts b/src/index.ts index e356ba9..3da07f8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -49,16 +49,16 @@ const main = async () => { await openticket.events.get("onErrorHandling").emit([error,origin]) if (openticket.defaults.getDefault("errorHandling")){ //custom error messages for known errors - if (error.message == "Used disallowed intents"){ + if (error.message.toLowerCase().includes("used disallowed intents")){ //invalid intents openticket.log("Open Ticket doesn't work without Privileged Gateway Intents enabled!","error") openticket.log("Enable them in the discord developer portal!","info") console.log("\n") process.exit(1) - }else if (error.message == "An invalid token was provided."){ + }else if (error.message.toLowerCase().includes("invalid discord bot token provided")){ //invalid token openticket.log("An invalid discord auth token was provided!","error") - openticket.log("Check the config if you have copied the token correctly!","info") + openticket.log("Check the config if you have inserted the bot token correctly!","info") console.log("\n") process.exit(1) }else{ @@ -453,7 +453,7 @@ const main = async () => { await openticket.events.get("afterClientInitiated").emit([openticket.client]) //client login - await openticket.client.login() + await openticket.client.login().catch((reason) => process.emit("uncaughtException",new api.ODSystemError(reason))) openticket.log("discord.js client ready!","info") } From 0437af1507bcdbb6daa82ac7b7a1a5c849f0a2d8 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 25 Jan 2025 11:43:13 +0100 Subject: [PATCH 110/157] Fixed #120 : Temporarily removed bot status state Will be added back in a future update, but customisable instead of double text :) --- src/core/api/modules/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index 1633032..974e26b 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -384,7 +384,7 @@ export class ODClientActivityManager { this.manager.client.user.setPresence({ activities:[{ type:this.#getStatusTypeEnum(type), - state:text, + state:undefined, name:text, }], status:this.status From 04789d5426720a9f05d30f8781b73ca459d4c0c3 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 25 Jan 2025 11:47:50 +0100 Subject: [PATCH 111/157] Fixed #121 : Ticket busy will now reset on reboot --- src/core/api/defaults/code.ts | 3 ++- src/data/framework/codeLoader.ts | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/core/api/defaults/code.ts b/src/core/api/defaults/code.ts index 90e2436..e7ced95 100644 --- a/src/core/api/defaults/code.ts +++ b/src/core/api/defaults/code.ts @@ -23,7 +23,8 @@ export interface ODCodeManagerIds_Default { "openticket:autoclose-timeout":ODCode, "openticket:autoclose-leave":ODCode, "openticket:autodelete-timeout":ODCode, - "openticket:autodelete-leave":ODCode + "openticket:autodelete-leave":ODCode, + "openticket:ticket-anti-busy":ODCode, } /**## ODCodeManager_Default `default_class` diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index 43f54f2..4fece50 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -483,4 +483,12 @@ const loadAutoCode = () => { } }) })) + + //TICKET ANTI BUSY + openticket.code.add(new api.ODCode("openticket:ticket-anti-busy",-1,() => { + for (const ticket of openticket.tickets.getAll()){ + //free tickets from corruption due to openticket:busy variable + ticket.get("openticket:busy").value = false + } + })) } \ No newline at end of file From 213ec3222531757619c3680cad031ce0dcff0fe7 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 25 Jan 2025 14:06:41 +0100 Subject: [PATCH 112/157] Fixed small bugs --- src/actions/deleteTicket.ts | 4 +++- src/core/api/modules/console.ts | 4 ++-- src/data/openticket/transcriptLoader.ts | 4 ++-- src/index.ts | 3 ++- src/livestatus.json | 20 ++++++++++++++++++++ 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/actions/deleteTicket.ts b/src/actions/deleteTicket.ts index 447d9d5..8748bf8 100644 --- a/src/actions/deleteTicket.ts +++ b/src/actions/deleteTicket.ts @@ -40,9 +40,11 @@ export const registerActions = async () => { //create transcript if (!params.withoutTranscript){ const transcriptRes = await openticket.actions.get("openticket:create-transcript").run(source,{guild,channel,user,ticket}) + //transcript failure if (typeof transcriptRes.success == "boolean" && !transcriptRes.success && transcriptRes.compiler){ const {compiler} = transcriptRes await channel.send((await openticket.builders.messages.getSafe("openticket:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason:transcriptRes.errorReason ?? null})).message) + .catch((reason) => openticket.log("Unable to send transcript failure to ticket channel!","error",[{key:"id",value:channel.id}])) //undo deletion ticket.get("openticket:for-deletion").value = false @@ -83,7 +85,7 @@ export const registerActions = async () => { const {guild,channel,user,ticket,reason} = params //delete channel & events await openticket.events.get("onTicketChannelDeletion").emit([ticket,channel,user]) - await channel.delete("Ticket Deleted") + await channel.delete("Ticket Deleted").catch((reason) => openticket.log("Unable to delete ticket channel!","error",[{key:"id",value:channel.id}])) await openticket.events.get("afterTicketChannelDeleted").emit([ticket,user]) //delete permissions from manager diff --git a/src/core/api/modules/console.ts b/src/core/api/modules/console.ts index d36ce20..5b7e527 100644 --- a/src/core/api/modules/console.ts +++ b/src/core/api/modules/console.ts @@ -73,7 +73,7 @@ export class ODConsoleMessage { }) const pstring = (pstrings.length > 0) ? " ("+pstrings.join(", ")+")" : "" const date = new Date() - const dstring = `${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}` + const dstring = `${date.getDate()}/${date.getMonth()+1}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}` return `[${dstring} ${this.prefix}] ${this.message}${pstring}` } /**Render the parameters of this message in a specific color. */ @@ -348,7 +348,7 @@ export class ODDebugFileManager { /**Generate the stats/header of the debug file (containing the version) */ #createStatsText(){ const date = new Date() - const dstring = `${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}` + const dstring = `${date.getDate()}/${date.getMonth()+1}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}` return [ "=========================", "OPEN TICKET DEBUG FILE:", diff --git a/src/data/openticket/transcriptLoader.ts b/src/data/openticket/transcriptLoader.ts index b0ec97e..3430b91 100644 --- a/src/data/openticket/transcriptLoader.ts +++ b/src/data/openticket/transcriptLoader.ts @@ -47,7 +47,7 @@ export const loadAllTranscriptCompilers = async () => { openticket.transcripts.add(new api.ODTranscriptCompiler<{contents:string}>("openticket: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!",messages:null,data:null} + 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) const finalMessages: string[] = [] @@ -195,7 +195,7 @@ export const loadAllTranscriptCompilers = async () => { },async (ticket,channel,user) => { //COMPILE const rawMessages = await collector.collectAllMessages(ticket) - if (!rawMessages) return {ticket,channel,user,success:false,errorReason:"Unable to collect messages!",messages:null,data:null} + 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) const htmlMessages: api.ODTranscriptHtmlV2Data["messages"] = [] diff --git a/src/index.ts b/src/index.ts index 3da07f8..b1f87cf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,8 +20,9 @@ INFORMATION: ============ - Open Ticket v4.0.0 - © DJdj Development + Open Ticket v4.0.0 - © DJdj Development + support us: https://github.com/sponsors/DJj123dj discord: https://discord.dj-dj.be website: https://openticket.dj-dj.be github: https://otgithub.dj-dj.be diff --git a/src/livestatus.json b/src/livestatus.json index 4dcdd4d..88633e9 100644 --- a/src/livestatus.json +++ b/src/livestatus.json @@ -38,5 +38,25 @@ "usingTextTranscripts":true, "usingHtmlTranscripts":true } + }, + { + "message":{ + "title":"Support Us", + "titleColor":"magenta", + "description":"Support our development at https://github.com/sponsors/DJj123dj/", + "descriptionColor":"normal" + }, + "active":{ + "versions":["4.0.0"], + "languages":[], + "allLanguages":true, + "usingPlugins":true, + "notUsingPlugins":true, + "usingSlashCommands":true, + "notUsingSlashCommands":true, + "notUsingTranscripts":true, + "usingTextTranscripts":true, + "usingHtmlTranscripts":true + } } ] \ No newline at end of file From 6516857866fe4efe2035ad84e3059a2c9305d813 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 25 Jan 2025 22:54:50 +0100 Subject: [PATCH 113/157] Fixed deprecation of HTML Transcripts interactions --- package.json | 5 ++++ src/core/api/main.ts | 2 +- src/core/api/modules/client.ts | 15 ++++++++++-- src/core/api/openticket/transcript.ts | 35 ++++++++++++++++++--------- src/core/startup/init.ts | 1 + 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 018ffc8..8fba6ed 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "type": "commonjs", "license": "GPL-3.0-only", "dependencies": { + "@discordjs/rest": "^2.4.2", "@types/node": "^22.5.0", "ansis": "^2.3.0", "discord.js": "^14.17.2", @@ -39,5 +40,9 @@ "imports": { "#opendiscord": "./dist/src/index.js", "#opendiscord-types": "./dist/src/core/api/api.js" + }, + "funding":{ + "type": "individual", + "url": "https://github.com/sponsors/DJj123dj" } } diff --git a/src/core/api/main.ts b/src/core/api/main.ts index 498c0da..9ca7165 100644 --- a/src/core/api/main.ts +++ b/src/core/api/main.ts @@ -173,7 +173,7 @@ export class ODMain { this.panels = new ODPanelManager(this.debug) this.tickets = new ODTicketManager(this.debug,this.client) this.blacklist = new ODBlacklistManager(this.debug) - this.transcripts = new ODTranscriptManager_Default(this.debug,this.tickets) + this.transcripts = new ODTranscriptManager_Default(this.debug,this.tickets,this.client) this.roles = new ODRoleManager(this.debug) } diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index 974e26b..2a4f101 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -3,6 +3,7 @@ /////////////////////////////////////// import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId } from "./base" import * as discord from "discord.js" +import {REST} from "@discordjs/rest" import { ODConsoleWarningMessage, ODDebugger } from "./console" import { ODMessageBuildResult, ODMessageBuildSentResult } from "./builder" import { ODManualProgressBar } from "./progressbar" @@ -43,11 +44,21 @@ export class ODClientManager { partials: ODClientPartials[] = [] /**List of required bot permissions. Add permissions to this list using the `onClientLoad` event. */ permissions: ODClientPermissions[] = [] - /**The bot token, empty by default. */ - token: string = "" + /**The discord bot token, empty by default. */ + set token(value:string){ + this.#token = value + this.rest.setToken(value) + } + get token(){ + return this.#token + } + /**The discord bot token. **DON'T USE THIS!!!** (use `ODClientManager.token` instead) */ + #token: string = "" /**The discord.js `discord.Client`. Only use it when initiated! */ client: discord.Client = new discord.Client({intents:[]}) //temporary client + /**The discord.js REST client. Used for stuff that discord.js can't handle :) */ + rest: discord.REST = new REST({version:"10"}) /**Is the bot initiated? */ initiated: boolean = false /**Is the bot logged in? */ diff --git a/src/core/api/openticket/transcript.ts b/src/core/api/openticket/transcript.ts index 2e297ff..b26af78 100644 --- a/src/core/api/openticket/transcript.ts +++ b/src/core/api/openticket/transcript.ts @@ -5,15 +5,19 @@ import { ODId, ODManager, ODValidJsonType, ODValidId, ODManagerData, ODValidButt import { ODDebugger } from "../modules/console" import { ODTicket, ODTicketManager } from "./ticket" import { ODMessageBuildResult } from "../modules/builder" +import { ODClientManager } from "../modules/client" import * as discord from "discord.js" export class ODTranscriptManager extends ODManager> { /**The manager responsible for collecting all messages in a channel. */ collector: ODTranscriptCollector + /**Alias for the client manager. */ + #client: ODClientManager - constructor(debug:ODDebugger, tickets:ODTicketManager){ + constructor(debug:ODDebugger, tickets:ODTicketManager, client:ODClientManager){ super(debug,"transcript compiler") - this.collector = new ODTranscriptCollector(tickets) + this.#client = client + this.collector = new ODTranscriptCollector(tickets,client) } } @@ -101,9 +105,12 @@ export class ODTranscriptManager_Default extends ODTranscriptManager { export class ODTranscriptCollector { /**Alias for the ticket manager. */ #tickets: ODTicketManager + /**Alias for the client manager. */ + #client: ODClientManager - constructor(tickets:ODTicketManager){ + constructor(tickets:ODTicketManager,client:ODClientManager){ this.#tickets = tickets + this.#client = client } /**Collect all messages from a given ticket channel. It may not include all messages depending on the ratelimit. */ @@ -247,14 +254,20 @@ export class ODTranscriptCollector { } }catch{} - //DEPRECATED WARNING!!! => msg.interaction might break in a future version of discord.js => required for slash command name - }else if (msg.interaction && msg.interaction.type == discord.InteractionType.ApplicationCommand){ - //slash command reply - const member = await msg.guild.members.fetch(msg.interaction.user.id) - reply = { - type:"interaction", - name:msg.interaction.commandName, - user:this.#handleUserData(msg.interaction.user,member) + }else if (msg.interactionMetadata){ + try{ + //get slash command name from undocumented property in discord REST API + const restMsg = await this.#client.rest.get(discord.Routes.channelMessage(msg.channelId,msg.id)) as discord.APIMessage & {interaction_metadata:{name:string}} + const commandName = restMsg.interaction_metadata.name ?? "unknown-command" + //slash command reply + const member = await msg.guild.members.fetch(msg.interactionMetadata.user.id) + reply = { + type:"interaction", + name:commandName, + user:this.#handleUserData(msg.interactionMetadata.user,member) + } + }catch(err){ + process.emit("uncaughtException",err) } } diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index fb089dd..494cf08 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -26,6 +26,7 @@ const moduleInstalled = (id:string, throwError:boolean) => { } } +moduleInstalled("@discordjs/rest",true) moduleInstalled("discord.js",true) moduleInstalled("ansis",true) moduleInstalled("formatted-json-stringify",true) From bbae139c6bc33218e5b0aff47d7fbf1e8e4dc8d8 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 25 Jan 2025 23:10:45 +0100 Subject: [PATCH 114/157] Updated README.md --- .github/SECURITY.md | 2 +- README.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/SECURITY.md b/.github/SECURITY.md index 36d5567..b0d15bb 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -1,7 +1,7 @@ # Security Policy Open Ticket Logo -[![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.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v4.0.0) +[![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.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v4.0.0) [![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!
Here you can find a list of all supported & deprecated versions of the bot.
diff --git a/README.md b/README.md index 9256e7b..58a0cdb 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Open Ticket Documentation Open Ticket License Open Ticket Stars +Sponsor DJj123dj

@@ -203,4 +204,4 @@ Please help us grow by giving a star! It would help us a lot! **README.md**
[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)
-© 2025 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file +© 2025 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) - [Support Us](https://github.com/sponsors/DJj123dj) \ No newline at end of file From 43356fef0557cc16082ee860d28bad98af1c7d4c Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 27 Jan 2025 23:15:58 +0100 Subject: [PATCH 115/157] Added Lithuanian translation (by tsgindrius) --- README.md | 5 +- languages/lithuanian.json | 478 +++++++++++++++++++++++++++ src/core/api/defaults/language.ts | 1 + src/data/framework/languageLoader.ts | 1 + 4 files changed, 483 insertions(+), 2 deletions(-) create mode 100644 languages/lithuanian.json diff --git a/README.md b/README.md index 58a0cdb..090440e 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@

Open Ticket is 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! -You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 20 Languages! If you need any help, feel free to join our discord server! +You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 21 Languages! If you need any help, feel free to join our discord server!

⭐️ Help us grow by giving a star! ⭐️

@@ -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, Rename & Move all your tickets! -- **🇬🇧 translation** - Open Ticket has been translated in more than **20 languages** by our community! +- **🇬🇧 translation** - Open Ticket has been translated in more than **21 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! @@ -170,6 +170,7 @@ This is the main team working on Open Ticket. Don't forget to check their profil |🇫🇷 French |guillee.3 |🟢 Up To Date | |🇦🇪 Arabic |palestinian |🟢 Up To Date | |🇮🇳 Hindi |an_developer |🟢 Up To Date | +|🇱🇹 Lithuanian |tsgindrius |🟢 Up To Date | |🇪🇪 Estonian |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇮 Finnish |iamnotmega |🔵 Up To Date (ChatGPT) | |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | diff --git a/languages/lithuanian.json b/languages/lithuanian.json new file mode 100644 index 0000000..18e3828 --- /dev/null +++ b/languages/lithuanian.json @@ -0,0 +1,478 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translators":["TsgIndrius"], + "lastedited":"26/01/2025", + "language":"Lithuanian", + "automated":false + }, + "checker":{ + "system":{ + "typeError":"[KLAIDA]", + "headerOpenTicket":"Atidaryti Bilietą", + "typeWarning":"[Įspėjimas]", + "typeInfo":"[INFORMACIJA]", + "headerConfigChecker":"KONFIGŪROS PATIKRINIMAS", + "headerDescription":"pažiūrėk klaidą savo konfigūracijos faile!", + "footerError":"Bot'as negali pastartuoti kol visi {0}' nebus sutvarkyti!", + "footerWarning":"Rekomenduojama sutvarkyti visus {0}' prieš paleidžiant bot'a!", + "footerSupport":"PAGALBA: {0} - DOCS: {1}", + "compactInformation":"NAUDOK {0} DĖL IŠSAMESNĖS INFORMACIJOS!", + "dataPath":"path", + "dataDocs":"docs", + "dataMessages":"pranešimas" + }, + "messages":{ + "stringTooShort":"Ši eilutė negali būti trumpesnė nei {0} raidžių!", + "stringTooLong":"Ši eilutė negali būti ilgesnė nei {0} raidžių!", + "stringLengthInvalid":"Šita eilutė turi būti ilgesnė negu {0} raidžių ilgio!", + "stringStartsWith":"Šita eilutė turi prasidėti su {0}!", + "stringEndsWith":"Ši eilutė turi baigtis su {0}!", + "stringContains":"Šita eilutė turi turėti {0}!", + "stringChoices":"Ši eilutė gali būti tik viena iš šių pasirinkimų: {0}!", + "stringRegex":"Šita eilutė nėra teisinga!", + + "numberTooShort":"Šis skaičius negali būti trumpesnis nei {0} raidžių!", + "numberTooLong":"Šis skaičius negali būti ilgesnis nei {0} raidžių!", + "numberLengthInvalid":"Šis skaičius turi būti {0} raidžių ilgio!", + "numberTooSmall":"Šis skaičius turi būti bent {0}!", + "numberTooLarge":"Šis skaičius turi būti ne daugiau negu {0}!", + "numberNotEqual":"Šis skaičius turi būti {0}!", + "numberStep":"Šis skaičius turi būti kartotinis {0}!", + "numberStepOffset":"Šis skaičius turi būti kartotinis {0} pradedant nuo {1}!", + "numberStartsWith":"Šitas skaičius turi pradėti nuo {0}!", + "numberEndsWith":"Šitas numeris turi baigtis su {0}!", + "numberContains":"Šitas skaičius turi turėti {0}!", + "numberChoices":"Šitas skaičius gali būti tik vienas iš šių pasirinkimų: {0}!", + "numberFloat":"Šis skaičius negali būti dešimtainis!", + "numberNegative":"Šitas numeris negali būti neigiamas!", + "numberPositive":"Šitas numeris negali būti teigiamas!", + "numberZero":"Šitas numeris negali būti nulinis!", + + "booleanTrue":"Šis boolean negali būti tiesa!", + "booleanFalse":"Šis boolean negali būti neteisingas!", + + "arrayEmptyDisabled":"Šis array negali būti tuščias!", + "arrayEmptyRequired":"Šis array turi būti tuščias!", + "arrayTooShort":"Šis array turi būti bent ilgesnis negu {0}!", + "arrayTooLong":"Šitas array turi būti trumpesnis negu {0}!", + "arrayLengthInvalid":"Šio array ilgis turi būti {0}!", + "arrayInvalidTypes":"Šiame array gali būti tik šie tipai: {0}!", + "arrayDouble":"Šis array neleidžia tureti tos pačios reikšmės du kartus!", + + "discordInvalidId":"Šitas neteisingas discord'o {0} ID!", + "discordInvalidIdOptions":"Tai neteisingas discord {0} ID! Taip pat galite naudoti vieną iš šių: {1}!", + "discordInvalidToken":"Šitas Token yra neteisingas prašyčiau idėti teisinga Token!", + "colorInvalid":"Tai netinkama šešioliktainė spalva!", + "emojiTooShort":"Ši eilutė turi turėti bent {0} jaustukų!", + "emojiTooLong":"Šią eilutę reikia turėti maziau negu {0} jaustukų!", + "emojiCustom":"Šitas jaustukas negali būti nuosavas!", + "emojiInvalid":"Šitas jaustukas netinkamas!", + "urlInvalid":"Šitas linkas neveikiantis!", + "urlInvalidHttp":"Šitas linkas turi naudoti https:// protocol!", + "urlInvalidProtocol":"Šitas linkas turi naudoti http:// & https:// protocols!", + "urlInvalidHostname":"Šio linko serverio pavadinimas neleidžiamas!", + "urlInvalidExtension":"Šiame URL yra netinkamas plėtinys! Pasirinkite tarp: {0}!", + "urlInvalidPath":"Šiame URL yra netinkamas kelias!", + "idNotUnique":"Šis ID nėra unikalus, naudokite kitą ID!", + "idNonExistent":"Šitas ID {0} neegzistuoja!", + + "invalidType":"Šios valdos turi būti tipas: {0}!", + "propertyMissing":"Ši valda {0} šio objekto trūksta!", + "propertyOptional":"Ši valda {0} yra neprivalomas šiame objekte!", + "objectDisabled":"Šis objektas išjungtas, ijunkite jį naudodami {0}!", + "nullInvalid":"Ši valda negali būti niekinė!", + "switchInvalidType":"Tai turi būti vienas iš toliau nurodytų tipų: {0}!", + "objectSwitchInvalid":"Šis objektas turi būti vieno iš šių tipų: {0}!", + + "invalidLanguage":"Neiteisinga Kalba!", + "invalidButton":"Šis mygtukas turi turėti bent {0} arba {1}!", + "unusedOption":"Šis pasirinkimas {0} nėra naudojamas!", + "unusedQuestion":"Klausimas {0} nėra naudojamas niekur!", + "dropdownOption":"Pasirinkimas su įjungtu išskleidžiamuoju meniu gali būti tik „bilieto“ tipo parinktys!" + } + }, + "actions":{ + "buttons":{ + "create":"Aplankykite Bilietą", + "close":"Uždarykite Bilieta", + "delete":"Ištrinti Bilieta", + "reopen":"Atnaujinti Bilieta", + "claim":"Claim Bilieta", + "unclaim":"Unclaim Bilieta", + "pin":"Prisegti Bilieta", + "unpin":"Atsegti Bilieta", + "clear":"Ištrinti Bilieta", + "helpSwitchSlash":"Pamatyti Slash Komandas", + "helpSwitchText":"Peržiūrėti Teksto Komandas ", + "helpPage":"Puslapis {0}", + "withReason":"Su Priežastimi", + "withoutTranscript":"Be Išrašo" + }, + "titles":{ + "created":"Bilietas Sukurtas", + "close":"Bilietas Uždarytas", + "delete":"Bilietas Ištrintas", + "reopen":"Bilietas Atnaujintas", + "claim":"Bilietas Claimed", + "unclaim":"Bilietas Unclaimed", + "pin":"Bilietas Prisegtas", + "unpin":"Bilietas Atsegtas", + "rename":"Bilietas Pervadytas", + "move":"Bilietas Perkeltas", + "add":"Bilieto Naudotojas Pridėtas", + "remove":"Bilieto Naudotojas Pašalintas", + + "help":"Galimi Komandos", + "statsReset":"Atkurti Statusa", + "blacklistAdd":"Naudotojas Užblokuotas", + "blacklistRemove":"Naudotojas Atblokuotas", + "blacklistGet":"Naudotojas Užblokuotas", + "blacklistView":"Dabartinis Užblokavimai", + "blacklistAddDm":"Žmogus buvo užblokuotas", + "blacklistRemoveDm":"Pašalino užblokavima", + "clear":"Bilietai išvalyti", + "roles":"Roles Atnaujinti", + + "autoclose":"Bilietas automatiškai uždarytas", + "autocloseEnabled":"Automatinis uždarymas įjungtas", + "autocloseDisabled":"Automatinis uždarymas išjungtas", + "autodelete":"Bilietas automatiškai ištrintas", + "autodeleteEnabled":"Bilieto automatinis ištrynimas įjungtas", + "autodeleteDisabled":"Bilieto automatinis ištrynimas išjungtas" + }, + "descriptions":{ + "create":"Jūsų bilietas sukurtas. Spustelėkite toliau esantį mygtuką, kad jį pasiektumėte!", + "close":"Bilietas buvo sėkmingai uždarytas!", + "delete":"Bilietas buvo sėkmingai ištrintas!", + "reopen":"Bilietas buvo sėkmingai atidarytas!", + "claim":"Bilietas buvo sėkmingai claimed!", + "unclaim":"Bilietas buvo sėkmingai unclaimed!", + "pin":"Bilietas buvo sėkmingai prisegtas!", + "unpin":"Bilietas buvo sėkmingai atsegtas", + "rename":"Bilietas buvo pervadytas į {0} sėkmingai!", + "move":"Bilietas buvo perkeltas į {0} sėkmingai!", + "add":"{0} buvo pridėtas į bilieta sekmingai!", + "remove":"{0} buvo pašalintas iš bilieto sėkmingai!", + + "helpExplanation":"`` => reikalingas parametras\n`[pavadinimas]` => pasirenkamas parametras", + "statsReset":"Boto statistika buvo sekmingai nustatyti iš naujo!", + "statsError":"Negaliu matyti bilieto statistikos!\n{0} nėra bilietas!", + "blacklistAdd":"{0} buvo sėkmingai užblokuotas!", + "blacklistRemove":"{0} buvo sėkmingai užblokuotas!", + "blacklistGetSuccess":"{0} yra užblokuotas!", + "blacklistGetEmpty":"{0} nėra užblokuotas!", + "blacklistViewEmpty":"Dar niekas nebuvo užblokuotas!", + "blacklistViewTip":"Norėdami užblokuoti naudotoja, naudokite \"/blacklist add\".!", + "clearVerify":"Ar tikrai norite ištrinti kelis bilietus?\nŠio veiksmo anuliuoti negalima!", + "clearReady":"{0} bilietai buvo sėkmingai pašalinti!", + "rolesEmpty":"Jokie roles nebuvo atnaujinti!", + + "autocloseLeave":"Šis bilietas buvo automatiškai uždarytas, nes kūrėjas paliko serverį!", + "autocloseTimeout":"Šis bilietas buvo automatiškai uždarytas, nes buvo neaktyvus daugiau nei `{0}h`!", + "autodeleteLeave":"Šis bilietas buvo automatiškai ištrintas, nes kūrėjas paliko serverį!", + "autodeleteTimeout":"Šis bilietas buvo automatiškai ištrintas, nes buvo neaktyvus daugiau nei `{0} dienas`!", + "autocloseEnabled":"Šiame biliete įjungtas automatinis uždarymas!\nJis bus uždarytas, kai bus neaktyvus ilgiau nei `{0}h`!", + "autocloseDisabled":"Šiame biliete automatinis uždarymas išjungtas!\nJis nebebus automatiškai uždarytas!", + "autodeleteEnabled":"Šiame biliete įgalintas automatinis ištrynimas!\nJis bus ištrintas, kai bus neaktyvus ilgiau nei `{0} dienas`!", + "autodeleteDisabled":"Automatinis ištrynimas šiame biliete išjungtas!\nJis nebebus automatiškai ištrintas!", + + "ticketMessageLimit":"Tu gali sukurti tik {0} bilietus tuo pačiu metu!", + "ticketMessageAutoclose":"Šis bilietas bus automatiškai uždarytas, kai bus neaktyvus {0}h!", + "ticketMessageAutodelete":"Šis bilietas bus automatiškai ištrintas, kai neaktyvus {0} dienas!", + "panelReady":"Žemiau rasite skydelį!\nŠį pranešimą dabar galima ištrinti!" + }, + "modal":{ + "closePlaceholder":"Kodėl tu uždarei šį bilieta?", + "deletePlaceholder":"Kodėl tu ištrinei šita bilieta?", + "reopenPlaceholder":"Kam tu atidarei bilieta?", + "claimPlaceholder":"Kam tu claimed šita bilieta?", + "unclaimPlaceholder":"Kam tu Unclaimed šita bilieta?", + "pinPlaceholder":"Kam tu prisegei šita bilieta?", + "unpinPlaceholder":"Kam tu atsegei šita bilieta?" + }, + "logs":{ + "createLog":"Naujas bilietas buvo sukurtas {0}!", + "closeLog":"šitas bilietas bus uždarytas už {0}!", + "closeDm":"Tavo bilietas buvo uždarytas!", + "deleteLog":"Šitas bilietas buvo ištrintas nuo {0}!", + "deleteDm":"Jūsų bilietas buvo ištrintas!", + "reopenLog":"Šitas bilietas buvo atidarytas nuo {0}!", + "reopenDm":"Tavo bilietas buvo atidarytas!", + "claimLog":"Šitas bilietas buvo claimed nuo {0}!", + "claimDm":"Tavo bilietas buvo claimed!", + "unclaimLog":"Bilietas buvo unclaimed nuo {0}!", + "unclaimDm":"Tavo bilietas buvo unclaimed!", + "pinLog":"This ticket has been pinned by {0}!", + "pinDm":"Bilietas buvo prisegtas!", + "unpinLog":"Bilietas buvo atsegtas nuo {0}!", + "unpinDm":"Tavo bilietas buvo atsegtas!", + "renameLog":"Šitas bilietas buvo pervadintas į {0} nuo {1}!", + "renameDm":"Tavo bilietas buvo pervadytas į {0}!", + "moveLog":"Šitas bilietas buvo perkeltas į {0} nuo {1}!", + "moveDm":"Tavo bilietas buvo perkeltas į {0}!", + "addLog":"{0} buvo pridėtas į bilieta nuo {1}!", + "addDm":"{0} Buvo pridėtas į tavo bilieta!", + "removeLog":"{0} buvo pašalintas iš šito bilieto nuo {1}!", + "removeDm":"{0} buvo pasalintas iš tavo bilieto!", + + "blacklistAddLog":"{0} buvo užblokuotas nuo {1}!", + "blacklistRemoveLog":"{0} buvo atblokuotas nuo {1}!", + "blacklistAddDm":"Jūs buvote užblokuotas!\nNuo šiol negalite sukurti bilieto!", + "blacklistRemoveDm":"Jūs buvote pašalinti iš juodojo sąrašo mūsų serveryje!\nDabar vėl galite kurti bilietus!", + "clearLog":"{0} bilietai buvo pašalinti nuo {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Peržiūrėti Išrašus", + "ready":"Išrašai sukurti", + "textFileDescription":"!", + "htmlProgress":"Palaukite, kol šis html išrašas bus apdorojamas...", + + "createdChannel":"Naujas {0} išrašas buvo sukurtas!", + "createdCreator":"Naujas {0} vieno iš jūsų bilietų išrašas sukurtas!", + "createdParticipant":"Naujas {0} išrašas buvo sukurta viename iš bilietų, kuriuose dalyvavote!", + "createdActiveAdmin":"Naujas {0} išrašas buvo sukurta viename iš bilietų, kuriuose dalyvavote kaip administratorius!", + "createdEveryAdmin":"Naujas {0} išrašas buvo sukurta viename iš bilietų, kuriuose buvote administratorius!", + "createdOther":"Naujas {0} išrašas buvo sukurtas!" + }, + "errors":{ + "retry":"Bandyk Iš naujo", + "continue":"Ištrinti be išrašo", + "backup":"Sukurti Atsarginį išraša", + "error":"Kažkas nepavyko bandant sukurti išraša.\nKą norėtumėte daryti?\n\nŠis bilietas nebus ištrintas, kol spustelėsite vieną iš šių mygtukų." + } + }, + "errors":{ + "titles":{ + "internalError":"Vidinė klaida", + "optionMissing":"Trūksta komandos parinkties", + "optionInvalid":"Netinkama komandos parinktis", + "unknownCommand":"Nepažystama komanda", + "noPermissions":"Jokių leidimų", + "unknownTicket":"Nepažystamas bilietas", + "deprecatedTicket":"Nebenaudojamas bilietas", + "unknownOption":"Nepažystamas pasirinkimas", + "unknownPanel":"Nepažystama skydelis", + "notInGuild":"Nera serveryje", + "channelRename":"Negaliu pervadyti kanalo", + "busy":"Bilietas yra užimtas" + }, + "descriptions":{ + "askForInfo":"Susisiek su savininku šito bilieto del daigiau informacijos!", + "askForInfoResolve":"Susisiekite su šio bot'o savininku, jei ši problema neišsprendžiama po kelių bandymų.", + "internalError":"Nepavyko atsakyti į šį {0} dėl vidinės klaidos!", + "optionMissing":"Šioje komandoje trūksta būtino parametro!", + "optionInvalid":"Šios komandos parametras neteisingas!", + "optionInvalidChoose":"Pasirink tarp", + "unknownCommand":"Norėdami gauti daugiau informacijos, pabandykite apsilankyti pagalbos meniu!", + "noPermissions":"Jums neleidžiama to naudoti {0}!", + "noPermissionsList":"Reikalingas Leidimas: (vienas iš jų)", + "noPermissionsCooldown":"Jums neleidžiama naudoti šio {0}, nes reikia atvėsti!", + "noPermissionsBlacklist":"Jums neleidžiama naudoti šio {0}, nes buvote užblokuotas!", + "noPermissionsLimitGlobal":"Jums neleidžiama kurti bilieto, nes serveris pasiekė maksimalų bilietų limitą!", + "noPermissionsLimitGlobalUser":"Jums neleidžiama kurti bilieto, nes pasiekėte maksimalų bilietų limitą!", + "noPermissionsLimitOption":"Jums neleidžiama kurti bilieto, nes serveris pasiekė maksimalų šios parinkties bilietų limitą!", + "noPermissionsLimitOptionUser":"Jums neleidžiama kurti bilieto, nes pasiekėte maksimalų šios parinkties bilietų limitą!", + "unknownTicket":"Išbandykite šią komandą dar kartą naudodami galiojantį bilietą!", + "deprecatedTicket":"Dabartinis kanalas negalioja! Tai galėjo būti bilietas iš senos Open Ticket versijos!", + "notInGuild":"Šis {0} neveikia DM! Bandykite dar kartą serveryje!", + "channelRename":"Dėl discord'o greičio apribojimų, šiuo metu robotas negali pervardyti kanalo. Kanalas bus automatiškai pervardytas per 10 minučių, jei robotas nebus paleistas iš naujo.", + "channelRenameSource":"Šios klaidos šaltinis yra: {0}", + "busy":"Neįmanoma naudoti šio {0}!\nBilietą šiuo metu apdoroja botas.\n\nBandykite dar kartą po kelių sekundžių!" + }, + "optionInvalidReasons":{ + "stringRegex":"Vertė neatitinka šablono!", + "stringMinLength":"Reikšmė turi būti bent {0} simbolių!", + "stringMaxLength":"Reikšmę turi sudaryti daugiausia {0} simboliai!", + "numberInvalid":"Neteisingas numeris!", + "numberMin":"Skaičius turi būti bent {0}!", + "numberMax":"Skaičius turi būti didžiausias {0}!", + "numberDecimal":"Skaičius negali būti dešimtainis!", + "numberNegative":"Skaičius negali būti neigiamas!", + "numberPositive":"Skaičius negali būti teigiamas!", + "numberZero":"Skaičius negali būti nulis!", + "channelNotFound":"Negaliu surasti kanalo!", + "userNotFound":"Negaliu surasti naudotojo!", + "roleNotFound":"Negaliu surasti rolės!", + "memberNotFound":"negaliu surasti naudotojo!", + "mentionableNotFound":"negaliu surasti naudotojo arba rolės!", + "channelType":"Neteisingas kanalo tipas!", + "notInGuild":"Ši parinktis reikalauja, kad būtumėte serveryje!" + }, + "permissions":{ + "developer":"Tu turi būti developeris šito boto.", + "owner":"Tu turi būti serverio savininkas.", + "admin":"Tu turi būti serverio administratorius.", + "moderator":"Tu turi būt serverio moderatorius.", + "support":"Tu turi būti prižiūrėtojas.", + "member":"Tu turi būti narys.", + "discord-administrator":"Tu turi turėti `ADMINISTRATOR` leidima." + }, + "actionInvalid":{ + "close":"Bilietas yra jau uždarytas!", + "reopen":"Bilietas nėra uždarytas!", + "claim":"Bilietas jau yra claimed!", + "unclaim":"Bilietas nera claimed!", + "pin":"Bilietas jau yra prisegtas!", + "unpin":"Bilietas nėra prisegtas!", + "add":"Šitas naudotojas jau gali matyti šita bilieta!", + "remove":"Negaliu pašalinti naudotojo iš bilieto!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Bilietas", + "tickets":"Bilietao", + "reason":"Priežastis", + "creator":"Kūrėjas", + "remaining":"Liko laiko", + "added":"Pridėta", + "removed":"Pašalinta", + "filter":"Filteris", + "claimedBy":"Claimed nuo {0}", + "method":"Metodas", + "type":"Tipas", + "blacklisted":"Užblokuotas", + "panel":"Skydelis", + "command":"Komanda", + "system":"Sistema", + "true":"Teisingai", + "false":"Klaidingai", + "syntax":"Sintaksė", + "originalName":"Orginalus Pavadinimas", + "newName":"Naujas pavadinimas", + "until":"Iki", + "validOptions":"Galiojančios parinktys", + "validPanels":"Galiojančios Skydeliai", + "autoclose":"Automatinis uždarymas", + "autodelete":"Automatinis Ištrinimas", + "startupDate":"Paleidimo data", + "version":"Versija", + "name":"Pavadinimas", + "role":"Role", + "status":"Statusas", + "claimed":"Claimed", + "pinned":"Prisegta", + "creationDate":"Sukūrimo data" + }, + "lowercase":{ + "text":"tekstas", + "html":"html", + "command":"komanda", + "modal":"modal", + "button":"mygtukas", + "dropdown":"išskleidžiamas meniu", + "method":"metodas" + } + }, + "commands":{ + "reason":"Nurodykite pasirenkamą priežastį, kuri bus matoma veiksmo žurnaluose.", + "help":"Gaukite visų galimų komandų sąrašą.", + "panel":"Pateikite pranešimą išskleidžiamuoju meniu arba mygtukais (bilietui sukurti).", + "panelId":"Skydelio, kurį norite sukurti, identifikatorius.", + "panelAutoUpdate":"Ar norite, kad šis skydelis būtų automatiškai atnaujintas redaguojant?", + "ticket":"Iškart sukurkite bilietą.", + "ticketId":"Bilieto, kurį norite sukurti, identifikatorius.", + "close":"Uždaryti bilieta.", + "delete":"Ištrinti bilieta.", + "deleteNoTranscript":"Ištrinti šita bilieta nesukuriant išrašo.", + "reopen":"Atidaryti bilieta.", + "claim":"Claim bileta.", + "claimUser":"Claim bilieta kažka kita negu save.", + "unclaim":"Unclaim bilieta.", + "pin":"Prisegti bilieta.", + "unpin":"Atsegti bilieta.", + "move":"Perkelti bilieta.", + "moveId":"Parinkties, į kurią norite pereiti, identifikatorius.", + "rename":"Pervadinti bilieta.", + "renameName":"Naujas pavadinimas šitam bilietui.", + "add":"Pridėk naudotoja prie bilieto.", + "addUser":"Asmuo kurį norite pridėti.", + "remove":"Pašalinti naudotoja iš bilieto.", + "removeUser":"Pašalinti asmuo iš bilieto.", + "blacklist":"Tvarkykite bilietų užblokavimo sąrašą.", + "blacklistView":"Peržiūrėkite dabartinio užblokavimo sąrašą.", + "blacklistAdd":"Pridėk asmenį i užblokuoti saraša.", + "blacklistRemove":"Pašalinti asmenį iš užblokuotų sarašo.", + "blacklistGet":"Gaukite išsamią informaciją iš naudotojo kuris buvo užblokuotas.", + "blacklistGetUser":"Asmuo kurio nori gauti informacija.", + "stats":"Peržiūrėkite boto, nario ar bilieto statistiką.", + "statsReset":"Iš naujo nustatykite visą roboto statistiką (ir pradėkite skaičiuoti nuo nulio).", + "statsGlobal":"Peržiūrėkite pasaulinę statistiką.", + "statsUser":"Peržiūrėkite serverio vartotojo statistiką.", + "statsUserUser":"Asmuo kuri norite peržiūrėti.", + "statsTicket":"Peržiūrėkite bilieto statistiką serveryje.", + "statsTicketTicket":"Pamatyti Bilieta.", + "clear":"Ištrinkite kelis bilietus vienu metu.", + "clearFilter":"Bilietų išvalymo filtras.", + "clearFilters":{ + "all":"Visus", + "open":"Atidarytus", + "close":"Uždarytus", + "claim":"Claimed", + "unclaim":"Unclaimed", + "pin":"Prisegtus", + "unpin":"Atsegtus", + "autoclose":"Automatinius uždarymus" + }, + "autoclose":"Tvarkykite automatinį uždarymą biliete.", + "autocloseDisable":"Išjungti automatinį uždarymą šiame biliete.", + "autocloseEnable":"Įgalinti automatinį uždarymą šiame biliete.", + "autocloseEnableTime":"Norint jį uždaryti, šis bilietas turi būti neaktyvus.", + "autodelete":"Tvarkykite automatinį ištrynimą biliete.", + "autodeleteDisable":"Išjungti automatinį ištrynimą šiame biliete.", + "autodeleteEnable":"Įgalinti automatinį ištrynimą šiame biliete.", + "autodeleteEnableTime":"Kiek dienų šis bilietas turi būti neaktyvus, kad jį būtų galima ištrinti." + }, + "helpMenu":{ + "help":"Gauk saraša galimų komandų.", + "ticket":"Iškart atidaryk bilieta.", + "close":"Uždarykite bilietą, tai išjungs rašymą šiame kanale.", + "delete":"Ištrinkite bilietą. Kai įjungta, sukuriamas nuorašas.", + "reopen":"Iš naujo atidarykite bilietą, todėl vėl galėsite rašyti šiame kanale.", + "pin":"Prisekite bilietą. Taip bilietas bus perkeltas į viršų ir prie pavadinimo bus pridėta emocija „📌“..", + "unpin":"Atsegti bilietą. Bilietas liks savo pozicijoje, bet praras emociją „📌“..", + "move":"Perkelkite bilietą. Tai pakeis šio bilieto tipą.", + "rename":"Pervardykite bilietą. Tai pakeis šio bilieto kanalo pavadinimą.", + "claim":"CLaim bilieto. Taip galite pranešti savo komandai, kad tvarkote šį bilietą.", + "unclaim":"Unclaim bilietą. Taip galite pranešti savo komandai, kad šis bilietas vėl netvarkomas.", + "add":"Pridėkite vartotoją prie bilieto. Tai leis vartotojui skaityti ir rašyti šiame biliete.", + "remove":"Pašalinkite vartotoją iš bilieto. Tai pašalins vartotojo galimybę skaityti ir rašyti šiame biliete.", + "panel":"Pateikite pranešimą išskleidžiamuoju meniu arba mygtukais (bilietui sukurti).", + "blacklistView":"Peržiūrėkite dabartinio užblokuotų žmonių sąrašą.", + "blacklistAdd":"Užblokuok žmogų nuo kurimosi bikieto.", + "blacklistRemove":"Pašalinkite vartotoją iš juodojo sąrašo.", + "blacklistGet":"Gaukite išsamią informaciją iš naudotojo, įtraukto į juodąjį sąrašą.", + "statsGlobal":"Peržiūrėkite pasaulinę statistiką.", + "statsTicket":"Peržiūrėkite bilieto statistiką serveryje.", + "statsUser":"Peržiūrėkite serverio vartotojo statistiką.", + "statsReset":"Iš naujo nustatykite visą roboto statistiką (ir pradėkite skaičiuoti nuo nulio).", + "autocloseDisable":"Išjungti automatinį uždarymą šiame biliete.", + "autocloseEnable":"Įgalinti automatinį uždarymą šiame biliete.", + "autodeleteDisable":"Išjungti automatinį ištrynimą šiame biliete.", + "autodeleteEnable":"Įgalinti automatinį ištrynimą šiame biliete." + }, + "stats":{ + "scopes":{ + "global":"Globalinė statistika", + "system":"Sisteminė statistika", + "user":"Naudotojo statistika", + "ticket":"Bilieto statistika", + "participants":"Dalyviai" + }, + "properties":{ + "ticketsCreated":"Bilietai Sukurti", + "ticketsClosed":"BILIETAI Uždaryti", + "ticketsDeleted":"Bilietai Ištrinti", + "ticketsReopened":"Bilietai Atnaujinti", + "ticketsAutoclosed":"Bilietai uždaryti automatiškai", + "ticketsClaimed":"Bilietai Claim", + "ticketsPinned":"Bilietai Prisegti", + "ticketsMoved":"Bilietai Perkelti", + "usersBlacklisted":"Naudojas Užblokuotas", + "transcriptsCreated":"Išrašai sukurti" + } + } +} \ No newline at end of file diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index 6d8b927..5c44f41 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -465,6 +465,7 @@ export interface ODLanguageManagerIds_Default { "openticket:french":ODLanguage, "openticket:arabic":ODLanguage, "openticket:hindi":ODLanguage, + "openticket:lithuanian":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index c987623..34483fc 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -23,6 +23,7 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODJsonLanguage("openticket:french","french.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:arabic","arabic.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:hindi","hindi.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:lithuanian","lithuanian.json")) /** How to add more languages? * - Register the language to the manager (see above) From 507d25455694dad818ecc3402a0f4dc4f3a67032 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 27 Jan 2025 23:37:49 +0100 Subject: [PATCH 116/157] Added new API comments (part 8) --- src/core/api/modules/base.ts | 10 ++--- src/core/api/openticket/blacklist.ts | 16 +++++++ src/core/api/openticket/option.ts | 62 ++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 5 deletions(-) diff --git a/src/core/api/modules/base.ts b/src/core/api/modules/base.ts index a77e90d..45c1e3e 100644 --- a/src/core/api/modules/base.ts +++ b/src/core/api/modules/base.ts @@ -51,11 +51,11 @@ export type ODInterfaceWithPartialProperty void)|null){ this.#change = callback } @@ -170,7 +170,7 @@ export class ODManagerRedirectHelper { * There is an `id:ODId` property & also some events used in the manager. */ export class ODManagerData extends ODManagerChangeHelper { - /**The id of this data */ + /**The id of this data. */ id: ODId constructor(id:ODValidId){ diff --git a/src/core/api/openticket/blacklist.ts b/src/core/api/openticket/blacklist.ts index 4340139..448efc6 100644 --- a/src/core/api/openticket/blacklist.ts +++ b/src/core/api/openticket/blacklist.ts @@ -4,7 +4,15 @@ import { ODManager, ODManagerData, ODValidId } from "../modules/base" import { ODDebugger } from "../modules/console" +/**## ODBlacklist `class` + * This is an open ticket blacklisted user. + * + * This class contains the id of the user this class belongs to & an optional reason for being blacklisted. + * + * Create this class & add it to the `ODBlacklistManager` to blacklist someone! + */ export class ODBlacklist extends ODManagerData { + /**The reason why this user got blacklisted. (optional) */ #reason: string|null constructor(id:ODValidId,reason:string|null){ @@ -12,6 +20,7 @@ export class ODBlacklist extends ODManagerData { this.#reason = reason } + /**The reason why this user got blacklisted. (optional) */ set reason(reason:string|null) { this.#reason = reason this._change() @@ -21,6 +30,13 @@ export class ODBlacklist extends ODManagerData { } } +/**## ODBlacklistManager `class` + * This is an open ticket blacklist manager. + * + * This class manages all blacklisted users & their reason. Check if someone is blacklisted using their ID in the `exists()` method. + * + * All `ODBlacklist`'s added, removed & edited in this list will be synced automatically with the database. + */ export class ODBlacklistManager extends ODManager { constructor(debug:ODDebugger){ super(debug,"blacklist") diff --git a/src/core/api/openticket/option.ts b/src/core/api/openticket/option.ts index c75838f..a708083 100644 --- a/src/core/api/openticket/option.ts +++ b/src/core/api/openticket/option.ts @@ -9,8 +9,17 @@ import * as discord from "discord.js" import * as crypto from "crypto" import { OTRoleUpdateMode } from "./role" +/**## ODOptionManager `class` + * This is an open ticket option manager. + * + * This class manages all registered options in the bot. This also includes temporary options generated from tickets where the original option got deleted. + * + * All option types including: tickets, websites & reaction roles are stored here. + */ export class ODOptionManager extends ODManager { + /**A reference to the Open Ticket debugger. */ #debug: ODDebugger + /**The option suffix manager used to generate channel suffixes for ticket names. */ suffix: ODOptionSuffixManager constructor(debug:ODDebugger){ @@ -25,20 +34,41 @@ export class ODOptionManager extends ODManager { } } +/**## ODOptionDataJson `interface` + * The JSON representatation from a single option property. + */ export interface ODOptionDataJson { + /**The id of this property. */ id:string, + /**The value of this property. */ value:ODValidJsonType } +/**## ODOptionDataJson `interface` + * The JSON representatation from a single option. + */ export interface ODOptionJson { + /**The id of this option. */ id:string, + /**The type of this option. (e.g. `openticket:ticket`, `openticket:website`, `openticket:role`) */ type:string, + /**The version of Open Ticket used to create this option & store it in the database. */ version:string, + /**The full list of properties/variables related to this option. */ data:ODOptionDataJson[] } +/**## ODOption `class` + * This is an open ticket option. + * + * This class contains all data related to this option (parsed from the config). + * + * It's recommended to use `ODTicketOption`, `ODWebsiteOption` or `ODRoleOption` instead! + */ export class ODOption extends ODManager> { + /**The id of this option. (from the config) */ id:ODId + /**The type of this option. (e.g. `openticket:ticket`, `openticket:website`, `openticket:role`) */ type: string constructor(id:ODValidId, type:string, data:ODOptionData[]){ @@ -50,6 +80,7 @@ export class ODOption extends ODManager> { }) } + /**Convert this option to a JSON object for storing this option in the database. */ toJson(version:ODVersion): ODOptionJson { const data = this.getAll().map((data) => { return { @@ -66,12 +97,21 @@ export class ODOption extends ODManager> { } } + /**Create an option from a JSON object in the database. */ static fromJson(json:ODOptionJson): ODOption { return new ODOption(json.id,json.type,json.data.map((data) => new ODOptionData(data.id,data.value))) } } +/**## ODOptionData `class` + * This is open ticket option data. + * + * This class contains a single property for a ticket option. (string, number, boolean, object, array, null) + * + * When this property is edited, the database will be updated automatically. + */ export class ODOptionData extends ODManagerData { + /**The value of this property. */ #value: DataType constructor(id:ODValidId, value:DataType){ @@ -79,6 +119,7 @@ export class ODOptionData extends ODManagerDat this.#value = value } + /**The value of this property. */ set value(value:DataType){ this.#value = value this._change() @@ -144,6 +185,13 @@ export interface ODTicketOptionIds { "openticket:limits-maximum-user":ODOptionData } +/**## ODTicketOption `class` + * This is an open ticket ticket option. + * + * This class contains all data related to an Open Ticket ticket option (parsed from the config). + * + * Use this option to create a new ticket! + */ export class ODTicketOption extends ODOption { type: "openticket:ticket" = "openticket:ticket" @@ -191,6 +239,13 @@ export interface ODWebsiteOptionIds { "openticket:url":ODOptionData, } +/**## ODWebsiteOption `class` + * This is an open ticket website option. + * + * This class contains all data related to an Open Ticket website option (parsed from the config). + * + * Use this option to create a button which links to a website! + */ export class ODWebsiteOption extends ODOption { type: "openticket:website" = "openticket:website" @@ -242,6 +297,13 @@ export interface ODRoleOptionIds { "openticket:add-on-join":ODOptionData } +/**## ODRoleOption `class` + * This is an open ticket role option. + * + * This class contains all data related to an Open Ticket role option (parsed from the config). + * + * Use this option to create a button for reaction roles! + */ export class ODRoleOption extends ODOption { type: "openticket:role" = "openticket:role" From 5e1cfe7942fadf370d8180a647d824f0aa0e3380 Mon Sep 17 00:00:00 2001 From: JasperAtSchool Date: Tue, 28 Jan 2025 11:21:49 +0100 Subject: [PATCH 117/157] Added new API comments (part 9) --- src/core/api/openticket/option.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/core/api/openticket/option.ts b/src/core/api/openticket/option.ts index a708083..33604e3 100644 --- a/src/core/api/openticket/option.ts +++ b/src/core/api/openticket/option.ts @@ -337,12 +337,19 @@ export class ODRoleOption extends ODOption { } } +/**## ODOptionSuffixManager `class` + * This is an open ticket option suffix manager. + * + * This class manages all suffixes from option in the bot. The id of an option suffix is the same as the option id. + * + * All ticket options should have a corresponding option suffix class. + */ export class ODOptionSuffixManager extends ODManager { constructor(debug:ODDebugger){ super(debug,"ticket suffix") } - /**Instantly get the suffix from an option. */ + /**Instantly get the suffix from an `ODTicketOption`. */ getSuffixFromOption(option:ODTicketOption,user:discord.User): string|null { const suffix = this.getAll().find((suffix) => suffix.option.id.value == option.id.value) if (!suffix) return null @@ -350,6 +357,13 @@ export class ODOptionSuffixManager extends ODManager { } } +/**## ODOptionSuffix `class` + * This is an open ticket option suffix. + * + * This class can generate a suffix for a discord channel name from a specific option. + * + * Use `getSuffix()` to get the new suffix! + */ export class ODOptionSuffix extends ODManagerData { /**The option of this suffix. */ option: ODTicketOption From 58fb7b751216d8794f37d434d9f26ea848b32556 Mon Sep 17 00:00:00 2001 From: JasperAtSchool Date: Tue, 28 Jan 2025 14:16:43 +0100 Subject: [PATCH 118/157] Added new API comments (part 10) --- src/actions/reactionRole.ts | 2 +- src/core/api/defaults/action.ts | 6 +- src/core/api/defaults/builder.ts | 6 +- src/core/api/defaults/config.ts | 4 +- src/core/api/openticket/option.ts | 55 +++++++++++++++-- src/core/api/openticket/panel.ts | 36 +++++++++++ src/core/api/openticket/question.ts | 54 +++++++++++++++++ src/core/api/openticket/role.ts | 94 +++++++++++++++++++++-------- src/core/api/openticket/ticket.ts | 47 ++++++++++++++- 9 files changed, 266 insertions(+), 38 deletions(-) diff --git a/src/actions/reactionRole.ts b/src/actions/reactionRole.ts index 884a2cd..65148ce 100644 --- a/src/actions/reactionRole.ts +++ b/src/actions/reactionRole.ts @@ -32,7 +32,7 @@ export const registerActions = async () => { } //update roles of user - const result: api.OTRoleUpdateResult[] = [] + const result: api.ODRoleUpdateResult[] = [] for (const r of roles){ try{ if (r.members.has(user.id) && (mode == "add&remove" || mode == "remove")){ diff --git a/src/core/api/defaults/action.ts b/src/core/api/defaults/action.ts index 3bc15ee..ba14c35 100644 --- a/src/core/api/defaults/action.ts +++ b/src/core/api/defaults/action.ts @@ -9,7 +9,7 @@ import { ODRoleOption, ODTicketOption } from "../openticket/option" import { ODTicket, ODTicketClearFilter } from "../openticket/ticket" import { ODTranscriptCompiler, ODTranscriptCompilerCompileResult } from "../openticket/transcript" import { ODMessageBuildSentResult } from "../modules/builder" -import { ODRole, OTRoleUpdateMode, OTRoleUpdateResult } from "../openticket/role" +import { ODRole, ODRoleUpdateMode, ODRoleUpdateResult } from "../openticket/role" /**## ODActionManagerIds_Default `interface` * This interface is a list of ids available in the `ODActionManager_Default` class. @@ -102,8 +102,8 @@ export interface ODActionManagerIds_Default { }, "openticket:reaction-role":{ source:"panel-button"|"other", - params:{guild:discord.Guild,user:discord.User,option:ODRoleOption,overwriteMode:OTRoleUpdateMode|null}, - result:{result:OTRoleUpdateResult[],role:ODRole}, + params:{guild:discord.Guild,user:discord.User,option:ODRoleOption,overwriteMode:ODRoleUpdateMode|null}, + result:{result:ODRoleUpdateResult[],role:ODRole}, workers:"openticket:reaction-role"|"openticket:logs" }, "openticket:clear-tickets":{ diff --git a/src/core/api/defaults/builder.ts b/src/core/api/defaults/builder.ts index 5ec6f0e..4509adc 100644 --- a/src/core/api/defaults/builder.ts +++ b/src/core/api/defaults/builder.ts @@ -12,7 +12,7 @@ import { ODRoleOption, ODTicketOption, ODWebsiteOption } from "../openticket/opt import { ODVerifyBar } from "../modules/verifybar" import * as discord from "discord.js" import { ODTranscriptCompiler, ODTranscriptCompilerCompileResult } from "../openticket/transcript" -import { ODRole, OTRoleUpdateResult } from "../openticket/role" +import { ODRole, ODRoleUpdateResult } from "../openticket/role" /**## ODBuilderManager_Default `default_class` * This is a special class that adds type definitions & typescript to the ODBuilderManager class. @@ -280,7 +280,7 @@ export interface ODEmbedManagerIds_Default { "openticket: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:"openticket:transcript-html-progress"}, "openticket:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"openticket:transcript-error"}, - "openticket:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:OTRoleUpdateResult[]},workers:"openticket:reaction-role"}, + "openticket:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"openticket:reaction-role"}, "openticket:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-verify-message"}, "openticket:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-message"}, "openticket:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-logs"}, @@ -411,7 +411,7 @@ export interface ODMessageManagerIds_Default { "openticket: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:"openticket:transcript-html-progress"}, "openticket:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"openticket:transcript-error"}, - "openticket:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:OTRoleUpdateResult[]},workers:"openticket:reaction-role"}, + "openticket:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"openticket:reaction-role"}, "openticket:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-verify-message"}, "openticket:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-message"}, "openticket:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-logs"}, diff --git a/src/core/api/defaults/config.ts b/src/core/api/defaults/config.ts index c265927..98ab2aa 100644 --- a/src/core/api/defaults/config.ts +++ b/src/core/api/defaults/config.ts @@ -5,7 +5,7 @@ import { ODValidButtonColor, ODValidId } from "../modules/base" import * as discord from "discord.js" import { ODConfigManager, ODConfig, ODJsonConfig } from "../modules/config" import { ODClientActivityStatus, ODClientActivityType } from "../modules/client" -import { OTRoleUpdateMode } from "../openticket/role" +import { ODRoleUpdateMode } from "../openticket/role" /**## ODConfigManagerIds_Default `interface` * This interface is a list of ids available in the `ODConfigManager_Default` class. @@ -405,7 +405,7 @@ export interface ODJsonConfig_DefaultOptionRoleType extends ODJsonConfig_Default /**All roles which will be affected by this button. */ roles:string[], /**The mode determines what will happen with the affected roles on the user. */ - mode:OTRoleUpdateMode, + mode:ODRoleUpdateMode, /**A list of roles to remove from the user when given at least one of the affected roles. */ removeRolesOnAdd:string[], /**Automatically add these roles when the user joins the server. */ diff --git a/src/core/api/openticket/option.ts b/src/core/api/openticket/option.ts index 33604e3..5f0adec 100644 --- a/src/core/api/openticket/option.ts +++ b/src/core/api/openticket/option.ts @@ -7,7 +7,7 @@ import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODValidButtonCo import { ODDebugger } from "../modules/console" import * as discord from "discord.js" import * as crypto from "crypto" -import { OTRoleUpdateMode } from "./role" +import { ODRoleUpdateMode } from "./role" /**## ODOptionManager `class` * This is an open ticket option manager. @@ -106,7 +106,7 @@ export class ODOption extends ODManager> { /**## ODOptionData `class` * This is open ticket option data. * - * This class contains a single property for a ticket option. (string, number, boolean, object, array, null) + * This class contains a single property for an option. (string, number, boolean, object, array, null) * * When this property is edited, the database will be updated automatically. */ @@ -292,7 +292,7 @@ export interface ODRoleOptionIds { "openticket:button-color":ODOptionData, "openticket:roles":ODOptionData, - "openticket:mode":ODOptionData, + "openticket:mode":ODOptionData, "openticket:remove-roles-on-add":ODOptionData, "openticket:add-on-join":ODOptionData } @@ -379,18 +379,39 @@ export class ODOptionSuffix extends ODManagerData { } } +/**## ODOptionUserNameSuffix `class` + * This is an open ticket user-name option suffix. + * + * This class can generate a user-name suffix for a discord channel name from a specific option. + * + * Use `getSuffix()` to get the new suffix! + */ export class ODOptionUserNameSuffix extends ODOptionSuffix { getSuffix(user:discord.User): string { return user.username } } +/**## ODOptionUserIdSuffix `class` + * This is an open ticket user-id option suffix. + * + * This class can generate a user-id suffix for a discord channel name from a specific option. + * + * Use `getSuffix()` to get the new suffix! + */ export class ODOptionUserIdSuffix extends ODOptionSuffix { getSuffix(user:discord.User): string { return user.id } } +/**## ODOptionCounterDynamicSuffix `class` + * This is an open ticket counter-dynamic option suffix. + * + * This class can generate a counter-dynamic suffix for a discord channel name from a specific option. + * + * Use `getSuffix()` to get the new suffix! + */ export class ODOptionCounterDynamicSuffix extends ODOptionSuffix { /**The database where the value of this counter is stored. */ database: ODDatabase @@ -401,6 +422,7 @@ export class ODOptionCounterDynamicSuffix extends ODOptionSuffix { this.#init() } + /**Initialize the database for this suffix. */ async #init(){ if (!await this.database.exists("openticket:option-suffix-counter",this.option.id.value)) await this.database.set("openticket:option-suffix-counter",this.option.id.value,0) } @@ -413,6 +435,13 @@ export class ODOptionCounterDynamicSuffix extends ODOptionSuffix { } } +/**## ODOptionCounterFixedSuffix `class` + * This is an open ticket counter-fixed option suffix. + * + * This class can generate a counter-fixed suffix for a discord channel name from a specific option. + * + * Use `getSuffix()` to get the new suffix! + */ export class ODOptionCounterFixedSuffix extends ODOptionSuffix { /**The database where the value of this counter is stored. */ database: ODDatabase @@ -423,6 +452,7 @@ export class ODOptionCounterFixedSuffix extends ODOptionSuffix { this.#init() } + /**Initialize the database for this suffix. */ async #init(){ if (!await this.database.exists("openticket:option-suffix-counter",this.option.id.value)) await this.database.set("openticket:option-suffix-counter",this.option.id.value,0) } @@ -439,6 +469,13 @@ export class ODOptionCounterFixedSuffix extends ODOptionSuffix { } } +/**## ODOptionRandomNumberSuffix `class` + * This is an open ticket random-number option suffix. + * + * This class can generate a random-number suffix for a discord channel name from a specific option. + * + * Use `getSuffix()` to get the new suffix! + */ export class ODOptionRandomNumberSuffix extends ODOptionSuffix { /**The database where previous random numbers are stored. */ database: ODDatabase @@ -449,9 +486,11 @@ export class ODOptionRandomNumberSuffix extends ODOptionSuffix { this.#init() } + /**Initialize the database for this suffix. */ async #init(){ if (!await this.database.exists("openticket:option-suffix-history",this.option.id.value)) await this.database.set("openticket:option-suffix-history",this.option.id.value,[]) } + /**Get a unique number for this suffix. */ #generateUniqueValue(history:string[]): string { const rawNumber = Math.round(Math.random()*1000).toString() let number = rawNumber @@ -473,6 +512,13 @@ export class ODOptionRandomNumberSuffix extends ODOptionSuffix { } } +/**## ODOptionRandomHexSuffix `class` + * This is an open ticket random-hex option suffix. + * + * This class can generate a random-hex suffix for a discord channel name from a specific option. + * + * Use `getSuffix()` to get the new suffix! + */ export class ODOptionRandomHexSuffix extends ODOptionSuffix { /**The database where previous random hexes are stored. */ database: ODDatabase @@ -483,10 +529,11 @@ export class ODOptionRandomHexSuffix extends ODOptionSuffix { this.#init() } + /**Initialize the database for this suffix. */ async #init(){ if (!await this.database.exists("openticket:option-suffix-history",this.option.id.value)) await this.database.set("openticket:option-suffix-history",this.option.id.value,[]) - } + /**Get a unique hex-string for this suffix. */ #generateUniqueValue(history:string[]): string { const hex = crypto.randomBytes(2).toString("hex") if (history.includes(hex)) return this.#generateUniqueValue(history) diff --git a/src/core/api/openticket/panel.ts b/src/core/api/openticket/panel.ts index 378aead..9ff8364 100644 --- a/src/core/api/openticket/panel.ts +++ b/src/core/api/openticket/panel.ts @@ -5,7 +5,15 @@ import { ODJsonConfig_DefaultPanelEmbedSettingsType } from "../defaults/config" import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODValidButtonColor, ODManagerData } from "../modules/base" import { ODDebugger } from "../modules/console" +/**## ODPanelManager `class` + * This is an open ticket panel manager. + * + * This class manages all registered panels in the bot. Only panels which are available in this manager can be auto-updated. + * + * Panels are not stored in the database and will be parsed from the config every startup. + */ export class ODPanelManager extends ODManager { + /**A reference to the Open Ticket debugger. */ #debug: ODDebugger constructor(debug:ODDebugger){ @@ -19,14 +27,25 @@ export class ODPanelManager extends ODManager { } } +/**## ODPanelDataJson `interface` + * The JSON representatation from a single panel property. + */ export interface ODPanelDataJson { + /**The id of this property. */ id:string, + /**The value of this property. */ value:ODValidJsonType } +/**## ODPanelDataJson `interface` + * The JSON representatation from a single panel. + */ export interface ODPanelJson { + /**The id of this panel. */ id:string, + /**The version of Open Ticket used to create this panel. */ version:string, + /**The full list of properties/variables related to this panel. */ data:ODPanelDataJson[] } @@ -54,7 +73,13 @@ export interface ODPanelIds { "openticket:describe-options-in-embed-description":ODPanelData } +/**## ODPanel `class` + * This is an open ticket panel. + * + * This class contains all data related to this panel (parsed from the config). + */ export class ODPanel extends ODManager> { + /**The id of this panel. (from the config) */ id:ODId constructor(id:ODValidId, data:ODPanelData[]){ @@ -65,6 +90,7 @@ export class ODPanel extends ODManager> { }) } + /**Convert this panel to a JSON object for storing this panel in the database. */ toJson(version:ODVersion): ODPanelJson { const data = this.getAll().map((data) => { return { @@ -80,6 +106,7 @@ export class ODPanel extends ODManager> { } } + /**Create a panel from a JSON object in the database. */ static fromJson(json:ODPanelJson): ODPanel { return new ODPanel(json.id,json.data.map((data) => new ODPanelData(data.id,data.value))) } @@ -106,7 +133,15 @@ export class ODPanel extends ODManager> { } } +/**## ODPanelData `class` + * This is open ticket panel data. + * + * This class contains a single property for a panel. (string, number, boolean, object, array, null) + * + * When this property is edited, the database will be updated automatically. + */ export class ODPanelData extends ODManagerData { + /**The value of this property. */ #value: DataType constructor(id:ODValidId, value:DataType){ @@ -114,6 +149,7 @@ export class ODPanelData extends ODManagerData this.#value = value } + /**The value of this property. */ set value(value:DataType){ this.#value = value this._change() diff --git a/src/core/api/openticket/question.ts b/src/core/api/openticket/question.ts index 7cb78cc..605a8d2 100644 --- a/src/core/api/openticket/question.ts +++ b/src/core/api/openticket/question.ts @@ -4,7 +4,15 @@ import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } from "../modules/base" import { ODDebugger } from "../modules/console" +/**## ODQuestionManager `class` + * This is an open ticket question manager. + * + * This class manages all registered questions in the bot. Only questions which are available in this manager can be used in options. + * + * Questions are not stored in the database and will be parsed from the config every startup. + */ export class ODQuestionManager extends ODManager { + /**A reference to the Open Ticket debugger. */ #debug: ODDebugger constructor(debug:ODDebugger){ @@ -18,20 +26,41 @@ export class ODQuestionManager extends ODManager { } } +/**## ODQuestionDataJson `interface` + * The JSON representatation from a single question property. + */ export interface ODQuestionDataJson { + /**The id of this property. */ id:string, + /**The value of this property. */ value:ODValidJsonType } +/**## ODQuestionDataJson `interface` + * The JSON representatation from a single question. + */ export interface ODQuestionJson { + /**The id of this question. */ id:string, + /**The type of this question. */ type:string, + /**The version of Open Ticket used to create this question. */ version:string, + /**The full list of properties/variables related to this question. */ data:ODQuestionDataJson[] } +/**## ODQuestion `class` + * This is an open ticket question. + * + * This class contains all data related to this question (parsed from the config). + * + * Use `ODShortQuestion` or `ODParagraphQuestion` instead! + */ export class ODQuestion extends ODManager> { + /**The id of this question. (from the config) */ id:ODId + /**The type of this question (e.g. `openticket:short` or `openticket:paragraph`) */ type: string constructor(id:ODValidId, type:string, data:ODQuestionData[]){ @@ -43,6 +72,7 @@ export class ODQuestion extends ODManager> { }) } + /**Convert this question to a JSON object for storing this question in the database. */ toJson(version:ODVersion): ODQuestionJson { const data = this.getAll().map((data) => { return { @@ -59,12 +89,21 @@ export class ODQuestion extends ODManager> { } } + /**Create a question from a JSON object in the database. */ static fromJson(json:ODQuestionJson): ODQuestion { return new ODQuestion(json.id,json.type,json.data.map((data) => new ODQuestionData(data.id,data.value))) } } +/**## ODQuestionData `class` + * This is open ticket question data. + * + * This class contains a single property for a question. (string, number, boolean, object, array, null) + * + * When this property is edited, the database will be updated automatically. + */ export class ODQuestionData extends ODManagerData { + /**The value of this property. */ #value: DataType constructor(id:ODValidId, value:DataType){ @@ -72,6 +111,7 @@ export class ODQuestionData extends ODManagerD this.#value = value } + /**The value of this property. */ set value(value:DataType){ this.#value = value this._change() @@ -99,6 +139,13 @@ export interface ODShortQuestionIds { "openticket:length-max":ODQuestionData } +/**## ODShortQuestion `class` + * This is an open ticket short question. + * + * This class contains all data related to an Open Ticket short question (parsed from the config). + * + * Use this question in an option to add a short text field to the modal! + */ export class ODShortQuestion extends ODQuestion { type: "openticket:short" = "openticket:short" @@ -146,6 +193,13 @@ export interface ODParagraphQuestionIds { "openticket:length-max":ODQuestionData } +/**## ODParagraphQuestion `class` + * This is an open ticket paragraph question. + * + * This class contains all data related to an Open Ticket paragraph question (parsed from the config). + * + * Use this question in an option to add a paragraph text field to the modal! + */ export class ODParagraphQuestion extends ODQuestion { type: "openticket:paragraph" = "openticket:paragraph" diff --git a/src/core/api/openticket/role.ts b/src/core/api/openticket/role.ts index cf93e12..cd6772d 100644 --- a/src/core/api/openticket/role.ts +++ b/src/core/api/openticket/role.ts @@ -5,7 +5,15 @@ import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } import { ODDebugger } from "../modules/console" import * as discord from "discord.js" +/**## ODRoleManager `class` + * This is an open ticket role manager. + * + * This class manages all registered reaction roles in the bot. + * + * Roles are not stored in the database and will be parsed from the config every startup. + */ export class ODRoleManager extends ODManager { + /**A reference to the Open Ticket debugger. */ #debug: ODDebugger constructor(debug:ODDebugger){ @@ -19,50 +27,48 @@ export class ODRoleManager extends ODManager { } } +/**## ODRoleDataJson `interface` + * The JSON representatation from a single role property. + */ export interface ODRoleDataJson { + /**The id of this property. */ id:string, + /**The value of this property. */ value:ODValidJsonType } +/**## ODRoleDataJson `interface` + * The JSON representatation from a single role. + */ export interface ODRoleJson { + /**The id of this role. */ id:string, + /**The version of Open Ticket used to create this role. */ version:string, + /**The full list of properties/variables related to this role. */ data:ODRoleDataJson[] } -export class ODRoleData extends ODManagerData { - #value: DataType - - constructor(id:ODValidId, value:DataType){ - super(id) - this.#value = value - } - - set value(value:DataType){ - this.#value = value - this._change() - } - get value(): DataType { - return this.#value - } - /**Refresh the database. Is only required to be used when updating `ODRoleData` with an object/array as value. */ - refreshDatabase(){ - this._change() - } -} - /**## ODRoleIds `type` * This interface is a list of ids available in the `ODRole` class. * It's used to generate typescript declarations for this class. */ export interface ODRoleIds { "openticket:roles":ODRoleData, - "openticket:mode":ODRoleData, + "openticket:mode":ODRoleData, "openticket:remove-roles-on-add":ODRoleData, "openticket:add-on-join":ODRoleData } +/**## ODRole `class` + * This is an open ticket role. + * + * This class contains all data related to this role (parsed from the config). + * + * These properties will be used to handle reaction role options. + */ export class ODRole extends ODManager> { + /**The id of this role. (from the config) */ id:ODId constructor(id:ODValidId, data:ODRoleData[]){ @@ -73,6 +79,7 @@ export class ODRole extends ODManager> { }) } + /**Convert this role to a JSON object for storing this role in the database. */ toJson(version:ODVersion): ODRoleJson { const data = this.getAll().map((data) => { return { @@ -88,6 +95,7 @@ export class ODRole extends ODManager> { } } + /**Create a role from a JSON object in the database. */ static fromJson(json:ODRoleJson): ODRole { return new ODRole(json.id,json.data.map((data) => new ODRoleData(data.id,data.value))) } @@ -114,9 +122,47 @@ export class ODRole extends ODManager> { } } -export interface OTRoleUpdateResult { +/**## ODRoleData `class` + * This is open ticket role data. + * + * This class contains a single property for a role. (string, number, boolean, object, array, null) + * + * When this property is edited, the database will be updated automatically. + */ +export class ODRoleData extends ODManagerData { + /**The value of this property. */ + #value: DataType + + constructor(id:ODValidId, value:DataType){ + super(id) + this.#value = value + } + + /**The value of this property. */ + set value(value:DataType){ + this.#value = value + this._change() + } + get value(): DataType { + return this.#value + } + /**Refresh the database. Is only required to be used when updating `ODRoleData` with an object/array as value. */ + refreshDatabase(){ + this._change() + } +} + +/**## ODRoleUpdateResult `interface` + * This interface represents the result of a single role when the roles of users are updated. + */ +export interface ODRoleUpdateResult { + /**The role which was affected. */ role:discord.Role, + /**The action which was done. `null` when nothing happend. */ action:"added"|"removed"|null } -export type OTRoleUpdateMode = "add&remove"|"add"|"remove" \ No newline at end of file +/**## ODRoleUpdateMode `type` + * This is the mode of the reaction role option in the config. + */ +export type ODRoleUpdateMode = "add&remove"|"add"|"remove" \ No newline at end of file diff --git a/src/core/api/openticket/ticket.ts b/src/core/api/openticket/ticket.ts index 94641a9..d08e3d9 100644 --- a/src/core/api/openticket/ticket.ts +++ b/src/core/api/openticket/ticket.ts @@ -4,13 +4,22 @@ import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } from "../modules/base" import { ODDebugger } from "../modules/console" import { ODClientManager_Default } from "../defaults/client" -import { ODOption, ODOptionJson, ODTicketOption } from "./option" +import { ODTicketOption } from "./option" import * as discord from "discord.js" +/**## ODTicketManager `class` + * This is an open ticket ticket manager. + * + * This class manages all currently created tickets in the bot. + * + * All tickets which are added, removed or modified in this manager will be updated automatically in the database. + */ export class ODTicketManager extends ODManager { /**A reference to the main server of the bot */ #guild: discord.Guild|null = null + /**A reference to the Open Ticket client manager. */ #client: ODClientManager_Default + /**A reference to the Open Ticket debugger. */ #debug: ODDebugger constructor(debug:ODDebugger, client:ODClientManager_Default){ @@ -116,15 +125,27 @@ export class ODTicketManager extends ODManager { } } +/**## ODTicketDataJson `interface` + * The JSON representatation from a single ticket property. + */ export interface ODTicketDataJson { + /**The id of this property. */ id:string, + /**The value of this property. */ value:ODValidJsonType } +/**## ODTicketDataJson `interface` + * The JSON representatation from a single ticket. + */ export interface ODTicketJson { + /**The id of this ticket. */ id:string, + /**The option id related to this ticket. */ option:string, + /**The version of Open Ticket used to create this ticket. */ version:string, + /**The full list of properties/variables related to this ticket. */ data:ODTicketDataJson[] } @@ -164,8 +185,17 @@ export interface ODTicketIds { "openticket:answers":ODTicketData<{id:string,name:string,type:"short"|"paragraph",value:string|null}[]>, } +/**## ODTicket `class` + * This is an Open Ticket ticket. + * + * This class contains all data related to this ticket (parsed from the database). + * + * These properties contain the current state of the ticket & are used by actions like claiming, pinning, closing, ... + */ export class ODTicket extends ODManager> { + /**The id of this ticket. (discord channel id) */ id:ODId + /**The option related to this ticket. */ #option: ODTicketOption constructor(id:ODValidId, option:ODTicketOption, data:ODTicketData[]){ @@ -177,6 +207,7 @@ export class ODTicket extends ODManager> { }) } + /**The option related to this ticket. */ set option(option:ODTicketOption){ this.#option = option this._change() @@ -185,6 +216,7 @@ export class ODTicket extends ODManager> { return this.#option } + /**Convert this ticket to a JSON object for storing this ticket in the database. */ toJson(version:ODVersion): ODTicketJson { const data = this.getAll().map((data) => { return { @@ -201,6 +233,7 @@ export class ODTicket extends ODManager> { } } + /**Create a ticket from a JSON object in the database. */ static fromJson(json:ODTicketJson, option:ODTicketOption): ODTicket { return new ODTicket(json.id,option,json.data.map((data) => new ODTicketData(data.id,data.value))) } @@ -227,7 +260,15 @@ export class ODTicket extends ODManager> { } } +/**## ODTicketData `class` + * This is open ticket ticket data. + * + * This class contains a single property for a ticket. (string, number, boolean, object, array, null) + * + * When this property is edited, the database will be updated automatically. + */ export class ODTicketData extends ODManagerData { + /**The value of this property. */ #value: DataType constructor(id:ODValidId, value:DataType){ @@ -235,6 +276,7 @@ export class ODTicketData extends ODManagerDat this.#value = value } + /**The value of this property. */ set value(value:DataType){ this.#value = value this._change() @@ -248,4 +290,7 @@ export class ODTicketData extends ODManagerDat } } +/**## ODTicketClearFilter `type` + * This type contains all possible "clear filters" for the `/clear` command. + */ export type ODTicketClearFilter = "all"|"open"|"closed"|"claimed"|"unclaimed"|"pinned"|"unpinned"|"autoclosed" \ No newline at end of file From f6c70fa62a49dfc0ad88ef2ebcc6fab049aa3c6b Mon Sep 17 00:00:00 2001 From: JasperAtSchool Date: Tue, 28 Jan 2025 14:22:26 +0100 Subject: [PATCH 119/157] Added new API comments (part 11) --- src/core/api/modules/action.ts | 4 +- src/core/api/modules/base.ts | 30 +++---- src/core/api/modules/builder.ts | 40 ++++----- src/core/api/modules/checker.ts | 54 ++++++------ src/core/api/modules/client.ts | 22 ++--- src/core/api/modules/code.ts | 4 +- src/core/api/modules/config.ts | 6 +- src/core/api/modules/console.ts | 34 ++++---- src/core/api/modules/cooldown.ts | 14 +-- src/core/api/modules/database.ts | 8 +- src/core/api/modules/defaults.ts | 124 +++++++++++++-------------- src/core/api/modules/event.ts | 8 +- src/core/api/modules/flag.ts | 4 +- src/core/api/modules/helpmenu.ts | 12 +-- src/core/api/modules/language.ts | 6 +- src/core/api/modules/permission.ts | 4 +- src/core/api/modules/plugin.ts | 6 +- src/core/api/modules/post.ts | 4 +- src/core/api/modules/progressbar.ts | 12 +-- src/core/api/modules/responder.ts | 34 ++++---- src/core/api/modules/session.ts | 6 +- src/core/api/modules/startscreen.ts | 20 ++--- src/core/api/modules/stat.ts | 18 ++-- src/core/api/modules/verifybar.ts | 4 +- src/core/api/modules/worker.ts | 4 +- src/core/api/openticket/blacklist.ts | 4 +- src/core/api/openticket/option.ts | 28 +++--- src/core/api/openticket/panel.ts | 6 +- src/core/api/openticket/question.ts | 10 +-- src/core/api/openticket/role.ts | 6 +- src/core/api/openticket/ticket.ts | 4 +- 31 files changed, 270 insertions(+), 270 deletions(-) diff --git a/src/core/api/modules/action.ts b/src/core/api/modules/action.ts index dd9a46f..92a5993 100644 --- a/src/core/api/modules/action.ts +++ b/src/core/api/modules/action.ts @@ -6,7 +6,7 @@ import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker" import { ODDebugger } from "./console" /**## ODActionImplementation `class` - * This is an open ticket action implementation. + * This is an Open Ticket action implementation. * * It is a basic implementation of the `ODWorkerManager` used by all `ODAction` classes. * @@ -28,7 +28,7 @@ export class ODActionImplementation = T|Promise export type ODValidButtonColor = "gray"|"red"|"green"|"blue" /**## ODValidId `type` - * This is a valid open ticket identifier. It can be an `ODId` or `string`! + * This is a valid Open Ticket identifier. It can be an `ODId` or `string`! * - * You will see this type in many functions from open ticket. + * You will see this type in many functions from Open Ticket. */ export type ODValidId = string|ODId @@ -41,7 +41,7 @@ export type ODValidJsonType = string|number|boolean|object|ODValidJsonType[]|nul export type ODInterfaceWithPartialProperty = Omit & Partial> /**## ODId `class` - * This is an open ticket identifier. + * This is an Open Ticket identifier. * * It can only contain the following characters: `a-z`, `A-Z`, `0-9`, `:`, `-` & `_` * @@ -99,7 +99,7 @@ export class ODId { } /**## ODManagerChangeHelper `class` - * This is an open ticket manager change helper. + * This is an Open Ticket manager change helper. * * It is used to let the "onChange" event in the `ODManager` class work. * You can use this class when extending your own `ODManager` @@ -124,7 +124,7 @@ export class ODManagerChangeHelper { } /**## ODManagerRedirectHelper `class` - * This is open ticket ticket manager redirect helper. + * This is Open Ticket ticket manager redirect helper. * * It is used to redirect a source to another source when the id isn't found. * @@ -163,7 +163,7 @@ export class ODManagerRedirectHelper { } /**## ODManagerData `class` - * This is open ticket manager data. + * This is Open Ticket manager data. * * It provides a template for all classes that are used in the `ODManager`. * @@ -190,7 +190,7 @@ export type ODManagerCallback = (data:DataType) export type ODManagerAddCallback = (data:DataType, overwritten:boolean) => void /**## ODManager `class` - * This is an open ticket manager. + * This is an Open Ticket manager. * * It can be used to store & manage classes based on their `ODId`. * It is somewhat the same as the default JS `Map()`. @@ -199,7 +199,7 @@ export type ODManagerAddCallback = (data:DataTyp * This class has many useful functions based on `ODId` (add, get, remove, getAll, getFiltered, exists, loopAll, ...) */ export class ODManager extends ODManagerChangeHelper { - /**Alias to open ticket debugger. */ + /**Alias to Open Ticket debugger. */ #debug?: ODDebugger /**The message to send when debugging this manager. */ #debugname?: string @@ -383,7 +383,7 @@ export class ODManager extends ODManagerChangeHe await cb(data,data.id) } } - /**Use the open ticket debugger in this manager for logs*/ + /**Use the Open Ticket debugger in this manager for logs*/ useDebug(debug?:ODDebugger, debugname?:string){ this.#debug = debug this.#debugname = debugname @@ -403,7 +403,7 @@ export class ODManager extends ODManagerChangeHe } /**## ODManagerWithSafety `class` - * This is an open ticket safe manager. + * This is an Open Ticket safe manager. * * It functions exactly the same as a normal `ODManager`, but it has 1 function extra! * The `getSafe()` function will always return data, because when it doesn't find an id, it returns pre-configured backup data. @@ -435,7 +435,7 @@ export class ODManagerWithSafety extends ODManag } /**## ODVersionManager `class` - * A open ticket version manager. + * A Open Ticket version manager. * * It is used to manage different `ODVersion`'s from the bot. You will use it to check which version of the bot is used. */ @@ -446,11 +446,11 @@ export class ODVersionManager extends ODManager { } /**## ODVersion `class` - * This is an open ticket version. + * This is an Open Ticket version. * * It has many features like comparing versions & checking if they are compatible. * - * You can use it in your own plugin, but most of the time you will use it to check the open ticket version! + * You can use it in your own plugin, but most of the time you will use it to check the Open Ticket version! */ export class ODVersion extends ODManagerData { /**The first number of the version (example: `v1.2.3` => `1`) */ @@ -726,7 +726,7 @@ export class ODEnvHelper { /**## ODSystemError `class` * A wrapper for the node.js `Error` class that makes the error look better in the console! * - * This wrapper is made for open ticket system errors! **It can only be used by open ticket itself!** + * This wrapper is made for Open Ticket system errors! **It can only be used by Open Ticket itself!** */ export class ODSystemError extends Error { /**This variable gets detected by the error handling system to know how to render it */ @@ -742,7 +742,7 @@ export class ODSystemError extends Error { /**## ODPluginError `class` * A wrapper for the node.js `Error` class that makes the error look better in the console! * - * This wrapper is made for open ticket plugin errors! **It can only be used by plugins!** + * This wrapper is made for Open Ticket plugin errors! **It can only be used by plugins!** */ export class ODPluginError extends Error { /**This variable gets detected by the error handling system to know how to render it */ diff --git a/src/core/api/modules/builder.ts b/src/core/api/modules/builder.ts index b4c0945..edd71e0 100644 --- a/src/core/api/modules/builder.ts +++ b/src/core/api/modules/builder.ts @@ -7,7 +7,7 @@ import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker" import { ODDebugger } from "./console" /**## ODBuilderImplementation `class` - * This is an open ticket builder implementation. + * This is an Open Ticket builder implementation. * * It is a basic implementation of the `ODWorkerManager` used by all `ODBuilder` classes. * @@ -48,7 +48,7 @@ export class ODBuilderImplementation extends ODBuilderImplementat } /**## ODDropdownManager `class` - * This is an open ticket dropdown manager. + * This is an Open Ticket dropdown manager. * * It contains all Open Ticket dropdown builders. Here, you can add your own dropdowns or edit existing ones! * @@ -309,7 +309,7 @@ export interface ODDropdownData { } /**## ODDropdownInstance `class` - * This is an open ticket dropdown instance. + * This is an Open Ticket dropdown instance. * * It contains all properties & functions to build a dropdown! */ @@ -394,7 +394,7 @@ export class ODDropdownInstance { } /**## ODDropdown `class` - * This is an open ticket dropdown builder. + * This is an Open Ticket dropdown builder. * * With this class, you can create a dropdown to use in a message. * The only difference with normal dropdowns is that this one can be edited by Open Ticket plugins! @@ -500,7 +500,7 @@ export class ODDropdown extends ODBuilderImplement } /**## ODFileManager `class` - * This is an open ticket file manager. + * This is an Open Ticket file manager. * * It contains all Open Ticket file builders. Here, you can add your own files or edit existing ones! * @@ -544,7 +544,7 @@ export interface ODFileBuildResult { } /**## ODFileInstance `class` - * This is an open ticket file instance. + * This is an Open Ticket file instance. * * It contains all properties & functions to build a file! */ @@ -585,7 +585,7 @@ export class ODFileInstance { } /**## ODFile `class` - * This is an open ticket file builder. + * This is an Open Ticket file builder. * * With this class, you can create a file to use in a message. * The only difference with normal files is that this one can be edited by Open Ticket plugins! @@ -623,7 +623,7 @@ export class ODFile extends ODBuilderImplementatio } /**## ODEmbedManager `class` - * This is an open ticket embed manager. + * This is an Open Ticket embed manager. * * It contains all Open Ticket embed builders. Here, you can add your own embeds or edit existing ones! * @@ -686,7 +686,7 @@ export interface ODEmbedBuildResult { } /**## ODEmbedInstance `class` - * This is an open ticket embed instance. + * This is an Open Ticket embed instance. * * It contains all properties & functions to build an embed! */ @@ -786,7 +786,7 @@ export class ODEmbedInstance { } /**## ODEmbed `class` - * This is an open ticket embed builder. + * This is an Open Ticket embed builder. * * With this class, you can create a embed to use in a message. * The only difference with normal embeds is that this one can be edited by Open Ticket plugins! @@ -837,7 +837,7 @@ export class ODEmbed extends ODBuilderImplementati } /**## ODMessageManager `class` - * This is an open ticket message manager. + * This is an Open Ticket message manager. * * It contains all Open Ticket message builders. Here, you can add your own messages or edit existing ones! * @@ -899,7 +899,7 @@ export interface ODMessageBuildSentResult { } /**## ODMessageInstance `class` - * This is an open ticket message instance. + * This is an Open Ticket message instance. * * It contains all properties & functions to build a message! */ @@ -1002,7 +1002,7 @@ export class ODMessageInstance { } /**## ODMessage `class` - * This is an open ticket message builder. + * This is an Open Ticket message builder. * * With this class, you can create a message to send in a discord channel. * The only difference with normal messages is that this one can be edited by Open Ticket plugins! @@ -1078,7 +1078,7 @@ export class ODMessage extends ODBuilderImplementa } /**## ODModalManager `class` - * This is an open ticket modal manager. + * This is an Open Ticket modal manager. * * It contains all Open Ticket modal builders. Here, you can add your own modals or edit existing ones! * @@ -1149,7 +1149,7 @@ export interface ODModalBuildResult { } /**## ODModalInstance `class` - * This is an open ticket modal instance. + * This is an Open Ticket modal instance. * * It contains all properties & functions to build a modal! */ @@ -1196,7 +1196,7 @@ export class ODModalInstance { } /**## ODModal `class` - * This is an open ticket modal builder. + * This is an Open Ticket modal builder. * * With this class, you can create a modal to use as response in interactions. * The only difference with normal modals is that this one can be edited by Open Ticket plugins! diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 01cee77..4d54377 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -15,9 +15,9 @@ export interface ODCheckerResult { } /**## ODCheckerManager `class` - * This is an open ticket checker manager. + * This is an Open Ticket checker manager. * - * It manages all config checkers in the bot and allows plugins to access config checkers from open ticket & other plugins! + * It manages all config checkers in the bot and allows plugins to access config checkers from Open Ticket & other plugins! * * You can use this class to get/add a config checker (`ODChecker`) in your plugin! * @example @@ -93,7 +93,7 @@ export class ODCheckerManager extends ODManager { } /**## ODCheckerStorage `class` - * This is an open ticket checker storage. + * This is an Open Ticket checker storage. * * It stores temporary data to share between config checkers! * (e.g. The `messages.json` needs to access the `"id"` from `options.json`) @@ -145,7 +145,7 @@ export class ODCheckerStorage { } /**## ODCheckerRenderer `class` - * This is an open ticket checker renderer. + * This is an Open Ticket checker renderer. * * It's responsible for rendering the config checker result in the console. * This class doesn't provide any components! You need to create them by extending this class @@ -169,7 +169,7 @@ export class ODCheckerRenderer { } /**## ODCheckerTranslationRegister `class` - * This is an open ticket checker translation register. + * This is an Open Ticket checker translation register. * * It's used to store & manage the translation for each message from the config checker! * Most translations are stored by message id, but there are some exceptions like the additional text on the checker report. @@ -227,7 +227,7 @@ export class ODCheckerTranslationRegister { } /**## ODCheckerFunction `class` - * This is an open ticket config checker function. + * This is an Open Ticket config checker function. * * It is a global function that will be executed after all config checkers. It can do additional checks for invalid/missing configurations. * It's mostly used for things that need to be checked globally! @@ -243,7 +243,7 @@ export class ODCheckerFunction extends ODManagerData { } /**## ODCheckerFunctionManager `class` - * This is an open ticket config checker function manager. + * This is an Open Ticket config checker function manager. * * It manages all `ODCheckerFunction`'s and it has some extra shortcuts for frequently used methods. */ @@ -293,7 +293,7 @@ export class ODCheckerFunctionManager extends ODManager { export type ODCheckerLocationTrace = (string|number)[] /**## ODChecker `class` - * This is an open ticket config checker. + * This is an Open Ticket config checker. * * It checks a specific config file for invalid/missing configurations. This data can then be used to show to the user what's wrong! * You can check for example if a string is longer/shorter than a certain amount of characters & more! @@ -405,7 +405,7 @@ export interface ODCheckerStructureOptions { } /**## ODCheckerStructure `class` - * This is an open ticket config checker structure. + * This is an Open Ticket config checker structure. * * This class will check for a single variable in a config file, customise it in the settings! * If you want prebuilt checkers (for strings, booleans, numbers, ...), check the other `ODCheckerStructure`'s! @@ -423,7 +423,7 @@ export class ODCheckerStructure { this.options = options } - /**Check a variable if it matches all settings in this checker. This function is automatically executed by open ticket! */ + /**Check a variable if it matches all settings in this checker. This function is automatically executed by Open Ticket! */ check(checker:ODChecker, value:ODValidJsonType, locationTrace:ODCheckerLocationTrace): boolean { if (typeof this.options.custom != "undefined"){ return this.options.custom(checker,value,locationTrace,this.id,(this.options.docs ?? null)) @@ -440,7 +440,7 @@ export interface ODCheckerObjectStructureOptions extends ODCheckerStructureOptio } /**## ODCheckerObjectStructure `class` - * This is an open ticket config checker structure. + * This is an Open Ticket config checker structure. * * This class will check for an object variable in a config file, customise it in the settings! * A checker for the children can be set in the settings. @@ -514,7 +514,7 @@ export interface ODCheckerStringStructureOptions extends ODCheckerStructureOptio } /**## ODCheckerStringStructure `class` - * This is an open ticket config checker structure. + * This is an Open Ticket config checker structure. * * This class will check for a string variable in a config file, customise it in the settings! */ @@ -599,7 +599,7 @@ export interface ODCheckerNumberStructureOptions extends ODCheckerStructureOptio } /**## ODCheckerNumberStructure `class` - * This is an open ticket config checker structure. + * This is an Open Ticket config checker structure. * * This class will check for a number variable in a config file, customise it in the settings! */ @@ -681,7 +681,7 @@ export interface ODCheckerBooleanStructureOptions extends ODCheckerStructureOpti } /**## ODCheckerBooleanStructure `class` - * This is an open ticket config checker structure. + * This is an Open Ticket config checker structure. * * This class will check for a boolean variable in a config file, customise it in the settings! */ @@ -732,7 +732,7 @@ export interface ODCheckerArrayStructureOptions extends ODCheckerStructureOption } /**## ODCheckerArrayStructure `class` - * This is an open ticket config checker structure. + * This is an Open Ticket config checker structure. * * This class will check for an array variable in a config file, customise it in the settings! */ @@ -835,7 +835,7 @@ export interface ODCheckerNullStructureOptions extends ODCheckerStructureOptions } /**## ODCheckerNullStructure `class` - * This is an open ticket config checker structure. + * This is an Open Ticket config checker structure. * * This class will check for a null variable in a config file, customise it in the settings! */ @@ -885,7 +885,7 @@ export interface ODCheckerTypeSwitchStructureOptions extends ODCheckerStructureO } /**## ODCheckerTypeSwitchStructure `class` - * This is an open ticket config checker structure. + * This is an Open Ticket config checker structure. * * This class will switch checkers based on the type of the variable in a config file, customise it in the settings! */ @@ -948,7 +948,7 @@ export interface ODCheckerObjectSwitchStructureOptions extends ODCheckerStructur } /**## ODCheckerObjectSwitchStructure `class` - * This is an open ticket config checker structure. + * This is an Open Ticket config checker structure. * * This class will switch object checkers based on a variable match in one of the objects, customise it in the settings! */ @@ -1011,7 +1011,7 @@ export interface ODCheckerEnabledObjectStructureOptions extends ODCheckerStructu } /**## ODCheckerEnabledObjectStructure `class` - * This is an open ticket config checker structure. + * This is an Open Ticket config checker structure. * * This class will enable an object checker based on a variable match in the object, customise it in the settings! */ @@ -1049,7 +1049,7 @@ export class ODCheckerEnabledObjectStructure extends ODCheckerStructure { } /**## ODCheckerCustomStructure_DiscordId `class` - * This is an open ticket custom checker structure. + * This is an Open Ticket custom checker structure. * * This class extends a primitive config checker & adds another layer of checking in the `custom` function. * You can compare it to a blueprint for a specific checker. @@ -1089,7 +1089,7 @@ export class ODCheckerCustomStructure_DiscordId extends ODCheckerStringStructure } /**## ODCheckerCustomStructure_DiscordIdArray `class` - * This is an open ticket custom checker structure. + * This is an Open Ticket custom checker structure. * * This class extends a primitive config checker & adds another layer of checking in the `custom` function. * You can compare it to a blueprint for a specific checker. @@ -1113,7 +1113,7 @@ export class ODCheckerCustomStructure_DiscordIdArray extends ODCheckerArrayStruc } /**## ODCheckerCustomStructure_DiscordToken `class` - * This is an open ticket custom checker structure. + * This is an Open Ticket custom checker structure. * * This class extends a primitive config checker & adds another layer of checking in the `custom` function. * You can compare it to a blueprint for a specific checker. @@ -1138,7 +1138,7 @@ export class ODCheckerCustomStructure_DiscordToken extends ODCheckerStringStruct } /**## ODCheckerCustomStructure_DiscordToken `class` - * This is an open ticket custom checker structure. + * This is an Open Ticket custom checker structure. * * This class extends a primitive config checker & adds another layer of checking in the `custom` function. * You can compare it to a blueprint for a specific checker. @@ -1172,7 +1172,7 @@ export class ODCheckerCustomStructure_HexColor extends ODCheckerStringStructure } /**## ODCheckerCustomStructure_EmojiString `class` - * This is an open ticket custom checker structure. + * This is an Open Ticket custom checker structure. * * This class extends a primitive config checker & adds another layer of checking in the `custom` function. * You can compare it to a blueprint for a specific checker. @@ -1239,7 +1239,7 @@ export interface ODCheckerCustomStructureOptions_UrlString { } /**## ODCheckerCustomStructure_UrlString `class` - * This is an open ticket custom checker structure. + * This is an Open Ticket custom checker structure. * * This class extends a primitive config checker & adds another layer of checking in the `custom` function. * You can compare it to a blueprint for a specific checker. @@ -1343,7 +1343,7 @@ export class ODCheckerCustomStructure_UrlString extends ODCheckerStringStructure } /**## ODCheckerCustomStructure_UniqueId `class` - * This is an open ticket custom checker structure. + * This is an Open Ticket custom checker structure. * * This class extends a primitive config checker & adds another layer of checking in the `custom` function. * You can compare it to a blueprint for a specific checker. @@ -1382,7 +1382,7 @@ export class ODCheckerCustomStructure_UniqueId extends ODCheckerStringStructure } /**## ODCheckerCustomStructure_UniqueIdArray `class` - * This is an open ticket custom checker structure. + * This is an Open Ticket custom checker structure. * * This class extends a primitive config checker & adds another layer of checking in the `custom` function. * You can compare it to a blueprint for a specific checker. diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index 2a4f101..646cd3a 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -26,14 +26,14 @@ export type ODClientPartials = ("User"|"Channel"|"GuildMember"|"Message"|"Reacti export type ODClientPermissions = ("CreateInstantInvite"|"KickMembers"|"BanMembers"|"Administrator"|"ManageChannels"|"ManageGuild"|"AddReactions"|"ViewAuditLog"|"PrioritySpeaker"|"Stream"|"ViewChannel"|"SendMessages"|"SendTTSMessages"|"ManageMessages"|"EmbedLinks"|"AttachFiles"|"ReadMessageHistory"|"MentionEveryone"|"UseExternalEmojis"|"ViewGuildInsights"|"Connect"|"Speak"|"MuteMembers"|"DeafenMembers"|"MoveMembers"|"UseVAD"|"ChangeNickname"|"ManageNicknames"|"ManageRoles"|"ManageWebhooks"|"ManageGuildExpressions"|"UseApplicationCommands"|"RequestToSpeak"|"ManageEvents"|"ManageThreads"|"CreatePublicThreads"|"CreatePrivateThreads"|"UseExternalStickers"|"SendMessagesInThreads"|"UseEmbeddedActivities"|"ModerateMembers"|"ViewCreatorMonetizationAnalytics"|"UseSoundboard"|"UseExternalSounds"|"SendVoiceMessages") /**## ODClientManager `class` - * This is an open ticket client manager. + * This is an Open Ticket client manager. * * It is responsible for managing the discord.js client. Here, you can set the status, register slash commands and much more! * * If you want, you can also listen for custom events on the `ODClientManager.client` variable (`discord.Client`) */ export class ODClientManager { - /**Alias to open ticket debugger. */ + /**Alias to Open Ticket debugger. */ #debug: ODDebugger /**List of required bot intents. Add intents to this list using the `onClientLoad` event. */ @@ -68,7 +68,7 @@ export class ODClientManager { /**The main server of the bot. Provided by serverId in the config */ mainServer: discord.Guild|null = null - /**(❌ DO NOD OVERWRITE ❌) Internal open ticket function to continue the startup when the client is ready! */ + /**(❌ DO NOD OVERWRITE ❌) Internal Open Ticket function to continue the startup when the client is ready! */ readyListener: (() => Promise)|null = null /**The status manager is responsible for setting the bot status. */ activity: ODClientActivityManager @@ -333,14 +333,14 @@ export type ODClientActivityStatus = ("online"|"invisible"|"idle"|"dnd") /**## ODClientActivityManager `class` - * This is an open ticket client activity manager. + * This is an Open Ticket client activity manager. * * It's responsible for managing the client status. Here, you can set the activity & status of the bot. * * It also has a built-in refresh function, so the status will refresh every 10 minutes to keep it visible. */ export class ODClientActivityManager { - /**Alias to open ticket debugger. */ + /**Alias to Open Ticket debugger. */ #debug: ODDebugger /**Copy of discord.js client */ @@ -765,14 +765,14 @@ export type ODSlashCommandRegisteredResult = { } /**## ODSlashCommandManager `class` - * This is an open ticket client slash manager. + * This is an Open Ticket client slash manager. * * It's responsible for managing all the slash commands from the client. * * Here, you can add & remove slash commands & the bot will do the (de)registering. */ export class ODSlashCommandManager extends ODManager { - /**Alias to open ticket debugger. */ + /**Alias to Open Ticket debugger. */ #debug: ODDebugger /**Refrerence to discord.js client. */ @@ -933,7 +933,7 @@ export class ODSlashCommandManager extends ODManager { export type ODSlashCommandUpdateFunction = (command:ODSlashCommandUniversalCommand) => boolean /**## ODSlashCommand `class` - * This is an open ticket slash command. + * This is an Open Ticket slash command. * * When registered, you can listen for this command using the `ODCommandResponder`. The advantages of using this class for creating a slash command are: * - automatic option parsing (even for channels, users, roles & mentions)! @@ -1106,7 +1106,7 @@ export interface ODTextCommandBuilder { } /**## ODTextCommand `class` - * This is an open ticket text command. + * This is an Open Ticket text command. * * When registered, you can listen for this command using the `ODCommandResponder`. The advantages of using this class for creating a text command are: * - automatic option parsing (even for channels, users, roles & mentions)! @@ -1263,14 +1263,14 @@ export type ODTextCommandError = ( export type ODTextCommandErrorCallback = (error:ODTextCommandError) => void /**## ODTextCommandManager `class` - * This is an open ticket client text manager. + * This is an Open Ticket client text manager. * * It's responsible for managing all the text commands from the client. * * Here, you can add & remove text commands & the bot will do the (de)registering. */ export class ODTextCommandManager extends ODManager { - /**Alias to open ticket debugger. */ + /**Alias to Open Ticket debugger. */ #debug: ODDebugger /**Copy of discord.js client. */ manager: ODClientManager diff --git a/src/core/api/modules/code.ts b/src/core/api/modules/code.ts index 8d1885c..a655b46 100644 --- a/src/core/api/modules/code.ts +++ b/src/core/api/modules/code.ts @@ -6,7 +6,7 @@ import { ODDebugger } from "./console" /**## ODCode `class` - * This is an open ticket code runner. + * This is an Open Ticket code runner. * * Using this, you're able to execute a function just before the startup screen. (90% of the code is already loaded) * You can also specify a priority to change the execution order. @@ -31,7 +31,7 @@ export class ODCode extends ODManagerData { } /**## ODCodeManager `class` - * This is an open ticket code manager. + * This is an Open Ticket code manager. * * It manages & executes `ODCode`'s in the correct order. * diff --git a/src/core/api/modules/config.ts b/src/core/api/modules/config.ts index 796d1f6..4d34b2d 100644 --- a/src/core/api/modules/config.ts +++ b/src/core/api/modules/config.ts @@ -7,7 +7,7 @@ import { ODDebugger } from "./console" import fs from "fs" /**## ODConfigManager `class` - * This is an open ticket config manager. + * This is an Open Ticket config manager. * * It manages all config files in the bot and allows plugins to access config files from Open Ticket & other plugins! * @@ -30,7 +30,7 @@ export class ODConfigManager extends ODManager { } /**## ODConfig `class` - * This is an open ticket config helper. + * This is an Open Ticket config helper. * This class doesn't do anything at all, it just gives a template & basic methods for a config. Use `ODJsonConfig` instead! * * You can use this class if you want to create your own config implementation (e.g. `yml`, `xml`,...)! @@ -55,7 +55,7 @@ export class ODConfig extends ODManagerData { } /**## ODJsonConfig `class` - * This is an open ticket JSON config. + * This is an Open Ticket JSON config. * You can use this class to get & edit variables from the config files or to create your own JSON config! * @example * //create a config from: ./config/test.json with the id "some-config" diff --git a/src/core/api/modules/console.ts b/src/core/api/modules/console.ts index 5b7e527..aa2d99d 100644 --- a/src/core/api/modules/console.ts +++ b/src/core/api/modules/console.ts @@ -25,7 +25,7 @@ export interface ODConsoleMessageParam { } /**## ODConsoleMessage `class` - * This is an open ticket console message. + * This is an Open Ticket console message. * * It is used to create beautiful & styled logs in the console with a prefix, message & parameters. * It also has full color support using `ansis` and parameters are parsed for you! @@ -117,7 +117,7 @@ export class ODConsoleMessage { } /**## ODConsoleInfoMessage `class` - * This is an open ticket console info message. + * This is an Open Ticket console info message. * * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "INFO" messages! */ @@ -128,7 +128,7 @@ export class ODConsoleInfoMessage extends ODConsoleMessage { } /**## ODConsoleSystemMessage `class` - * This is an open ticket console system message. + * This is an Open Ticket console system message. * * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "SYSTEM" messages! */ @@ -139,7 +139,7 @@ export class ODConsoleSystemMessage extends ODConsoleMessage { } /**## ODConsolePluginMessage `class` - * This is an open ticket console plugin message. + * This is an Open Ticket console plugin message. * * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "PLUGIN" messages! */ @@ -150,7 +150,7 @@ export class ODConsolePluginMessage extends ODConsoleMessage { } /**## ODConsoleDebugMessage `class` - * This is an open ticket console debug message. + * This is an Open Ticket console debug message. * * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "DEBUG" messages! */ @@ -161,7 +161,7 @@ export class ODConsoleDebugMessage extends ODConsoleMessage { } /**## ODConsoleWarningMessage `class` - * This is an open ticket console warning message. + * This is an Open Ticket console warning message. * * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "WARNING" messages! */ @@ -172,7 +172,7 @@ export class ODConsoleWarningMessage extends ODConsoleMessage { } /**## ODConsoleErrorMessage `class` - * This is an open ticket console error message. + * This is an Open Ticket console error message. * * It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "ERROR" messages! */ @@ -183,7 +183,7 @@ export class ODConsoleErrorMessage extends ODConsoleMessage { } /**## ODError `class` - * This is an open ticket error. + * This is an Open Ticket error. * * It is used to render and log Node.js errors & crashes in a styled way to the console & `otdebug.txt` file! */ @@ -227,7 +227,7 @@ export class ODError { export type ODConsoleMessageTypes = "info"|"system"|"plugin"|"debug"|"warning"|"error" /**## ODConsoleManager `class` - * This is the open ticket console manager. + * This is the Open Ticket console manager. * * It handles the entire console system of Open Ticket. It's also the place where you need to log `ODConsoleMessage`'s. * This manager keeps a short history of messages sent to the console which is configurable by plugins. @@ -285,7 +285,7 @@ export class ODConsoleManager { } /**## ODDebugFileManager `class` - * This is the open ticket debug file manager. + * This is the Open Ticket debug file manager. * * It manages the Open Ticket debug file (`otdebug.txt`) which keeps a history of all system logs. * There are even internal logs that aren't logged to the console which are available in this file! @@ -398,7 +398,7 @@ export class ODDebugFileManager { } /**## ODDebugger `class` - * This is the open ticket debugger. + * This is the Open Ticket debugger. * * It is a simple wrapper around the `ODConsoleManager` to handle debugging (primarily for `ODManagers`). * Messages created using this debugger are only logged to the debug file unless specified otherwise. @@ -408,7 +408,7 @@ export class ODDebugFileManager { * Using this system, all additions & removals inside a manager are logged to the debug file. This makes searching for errors a lot easier! */ export class ODDebugger { - /**An alias to the open ticket console manager. */ + /**An alias to the Open Ticket console manager. */ console: ODConsoleManager /**When enabled, debug logs are also shown in the console. */ visible: boolean = false @@ -475,7 +475,7 @@ export interface ODLiveStatusSourceData { } /**## ODLiveStatusSource `class` - * This is the open ticket livestatus source. + * This is the Open Ticket livestatus source. * * It is an empty template for a livestatus source. * By default, you should use `ODLiveStatusUrlSource` or `ODLiveStatusFileSource`, @@ -526,7 +526,7 @@ export class ODLiveStatusSource extends ODManagerData { } /**## ODLiveStatusFileSource `class` - * This is the open ticket livestatus file source. + * This is the Open Ticket livestatus file source. * * It is a LiveStatus source that will read the data from a local file. * @@ -545,7 +545,7 @@ export class ODLiveStatusFileSource extends ODLiveStatusSource { } /**## ODLiveStatusUrlSource `class` - * This is the open ticket livestatus url source. + * This is the Open Ticket livestatus url source. * * It is a LiveStatus source that will read the data from a http URL (json file). * @@ -579,7 +579,7 @@ export class ODLiveStatusUrlSource extends ODLiveStatusSource { } /**## ODLiveStatusManager `class` - * This is the open ticket livestatus manager. + * This is the Open Ticket livestatus manager. * * It manages all LiveStatus sources and has the renderer for all LiveStatus messages. * @@ -611,7 +611,7 @@ export class ODLiveStatusManager extends ODManager { } /**## ODLiveStatusRenderer `class` - * This is the open ticket livestatus renderer. + * This is the Open Ticket livestatus renderer. * * It's responsible for rendering all LiveStatus messages to the console. */ diff --git a/src/core/api/modules/cooldown.ts b/src/core/api/modules/cooldown.ts index 93a1fc6..ad5abfe 100644 --- a/src/core/api/modules/cooldown.ts +++ b/src/core/api/modules/cooldown.ts @@ -5,7 +5,7 @@ import { ODId, ODValidId, ODManager, ODSystemError, ODManagerData } from "./base import { ODDebugger } from "./console" /**## ODCooldownManager `class` - * This is an open ticket cooldown manager. + * This is an Open Ticket cooldown manager. * * It is responsible for managing all cooldowns in Open Ticket. An example of this is the ticket creation cooldown. * @@ -24,7 +24,7 @@ export class ODCooldownManager extends ODManager> { } /**## ODCooldownData `class` - * This is open ticket cooldown data. + * This is Open Ticket cooldown data. * * It contains the instance of an active cooldown (e.g. for a user). It is handled by the cooldown itself. */ @@ -42,7 +42,7 @@ export class ODCooldownData extends ODManagerData { } /**## ODCooldown `class` - * This is an open ticket cooldown. + * This is an Open Ticket cooldown. * * It doesn't do anything on it's own, but it provides the methods that are used to interact with a cooldown. * This class can be extended from to create a working cooldown. @@ -77,7 +77,7 @@ export class ODCooldown extends ODManagerData { } /**## ODCounterCooldown `class` - * This is an open ticket counter cooldown. + * This is an Open Ticket counter cooldown. * * It is is a cooldown based on a counter. When the number exceeds the limit, the cooldown is activated. * The number will automatically be decreased with a set amount & interval. @@ -154,7 +154,7 @@ export class ODCounterCooldown extends ODCooldown<{value:number}> { } /**## ODIncrementalCounterCooldown `class` - * This is an open ticket incremental counter cooldown. + * This is an Open Ticket incremental counter cooldown. * * It is is a cooldown based on an incremental counter. It is exactly the same as the normal counter, * with the only difference being that it still increments when the limit is already exeeded. @@ -232,7 +232,7 @@ export class ODIncrementalCounterCooldown extends ODCooldown<{value:number}> { } /**## ODTimeoutCooldown `class` - * This is an open ticket timeout cooldown. + * This is an Open Ticket timeout cooldown. * * It is a cooldown based on a timer. When triggered/updated, the cooldown is activated for the set amount of time. * After the timer has timed out, the cooldown will be deleted. @@ -288,7 +288,7 @@ export class ODTimeoutCooldown extends ODCooldown<{date:number}> { } /**## ODIncrementalTimeoutCooldown `class` - * This is an open ticket incremental timeout cooldown. + * This is an Open Ticket incremental timeout cooldown. * * It is is a cooldown based on an incremental timer. It is exactly the same as the normal timer, * with the only difference being that it adds additional time when triggered/updated while the cooldown is already active. diff --git a/src/core/api/modules/database.ts b/src/core/api/modules/database.ts index 767f307..ab6d601 100644 --- a/src/core/api/modules/database.ts +++ b/src/core/api/modules/database.ts @@ -8,7 +8,7 @@ import { ODDebugger } from "./console" import * as fjs from "formatted-json-stringify" /**## ODDatabaseManager `class` - * This is an open ticket database manager. + * This is an Open Ticket database manager. * * It manages all databases in the bot and allows to permanently store data from the bot! * @@ -32,7 +32,7 @@ export class ODDatabaseManager extends ODManager { } /**## ODDatabase `class` - * This is an open ticket database template. + * This is an Open Ticket database template. * This class doesn't do anything at all, it just gives a template & basic methods for a database. Use `ODJsonDatabase` instead! * * You can use this class if you want to create your own database implementation (e.g. `mongodb`, `mysql`,...)! @@ -79,7 +79,7 @@ export class ODDatabase extends ODManagerData { export type ODJsonDatabaseStructure = {category:string, key:string, value:ODValidJsonType}[] /**## ODJsonDatabase `class` - * This is an open ticket JSON database. + * This is an Open Ticket JSON database. * It stores data in a `json` file as a large `Array` using the `category`, `key`, `value` strategy. * You can store the following types: `string`, `number`, `boolean`, `array`, `object` & `null`! * @@ -179,7 +179,7 @@ export class ODJsonDatabase extends ODDatabase { /**## ODFormattedJsonDatabase `class` - * This is an open ticket Formatted JSON database. + * This is an Open Ticket Formatted JSON database. * It stores data in a `json` file as a large `Array` using the `category`, `key`, `value` strategy. * You can store the following types: `string`, `number`, `boolean`, `array`, `object` & `null`! * diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index 4aaa295..0747ad2 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -20,31 +20,31 @@ export interface ODDefaults { /**Don't crash the bot when a plugin crashes! */ softPluginLoading:boolean, - /**Load the default open ticket plugin classes. */ + /**Load the default Open Ticket plugin classes. */ pluginClassLoading:boolean, - /**Load the default open ticket flags. */ + /**Load the default Open Ticket flags. */ flagLoading:boolean, - /**Enable the default initializer for open ticket flags. */ + /**Enable the default initializer for Open Ticket flags. */ flagInitiating:boolean, - /**Load the default open ticket progress bar renderers. */ + /**Load the default Open Ticket progress bar renderers. */ progressBarRendererLoading:boolean, - /**Load the default open ticket progress bars. */ + /**Load the default Open Ticket progress bars. */ progressBarLoading:boolean, - /**Load the default open ticket configs. */ + /**Load the default Open Ticket configs. */ configLoading:boolean, - /**Enable the default initializer for open ticket config. */ + /**Enable the default initializer for Open Ticket config. */ configInitiating:boolean, - /**Load the default open ticket databases. */ + /**Load the default Open Ticket databases. */ databaseLoading:boolean, - /**Enable the default initializer for open ticket database. */ + /**Enable the default initializer for Open Ticket database. */ databaseInitiating:boolean, - /**Load the default open ticket sessions. */ + /**Load the default Open Ticket sessions. */ sessionLoading:boolean, - /**Load the default open ticket languages. */ + /**Load the default Open Ticket languages. */ languageLoading:boolean, - /**Enable the default initializer for open ticket languages. */ + /**Enable the default initializer for Open Ticket languages. */ languageInitiating:boolean, /**Enable selecting the current language from `config/general.json`. */ languageSelection:boolean, @@ -53,13 +53,13 @@ export interface ODDefaults { /****[NOT FOR PLUGIN TRANSLATIONS]** The full list of available languages (used in the default config checker). */ languageList:string[], - /**Load the default open ticket config checker. */ + /**Load the default Open Ticket config checker. */ checkerLoading:boolean, - /**Load the default open ticket config checker functions. */ + /**Load the default Open Ticket config checker functions. */ checkerFunctionLoading:boolean, /**Enable the default execution of the config checkers. */ checkerExecution:boolean, - /**Load the default open ticket config checker translations. */ + /**Load the default Open Ticket config checker translations. */ checkerTranslationLoading:boolean, /**Enable the default rendering of the config checkers. */ checkerRendering:boolean, @@ -68,111 +68,111 @@ export interface ODDefaults { /**Render the checker even when there are no errors & warnings. */ checkerRenderEmpty:boolean, - /**Load the default open ticket client configuration. */ + /**Load the default Open Ticket client configuration. */ clientLoading:boolean, - /**Load the default open ticket client initialization. */ + /**Load the default Open Ticket client initialization. */ clientInitiating:boolean, - /**Load the default open ticket client ready actions (status, commands, permissions, ...). */ + /**Load the default Open Ticket client ready actions (status, commands, permissions, ...). */ clientReady:boolean, /**Create a warning when the bot is present in multiple guilds. */ clientMultiGuildWarning:boolean, - /**Load the default open ticket client activity (from `config/general.json`). */ + /**Load the default Open Ticket client activity (from `config/general.json`). */ clientActivityLoading:boolean, - /**Load the default open ticket client activity initialization (& status refresh). */ + /**Load the default Open Ticket client activity initialization (& status refresh). */ clientActivityInitiating:boolean, - /**Load the default open ticket slash commands. */ + /**Load the default Open Ticket slash commands. */ slashCommandLoading:boolean, - /**Load the default open ticket slash command registerer (register slash cmds in discord). */ + /**Load the default Open Ticket slash command registerer (register slash cmds in discord). */ slashCommandRegistering:boolean, /**When enabled, the bot is forced to re-register all slash commands in the server. This can be used in case of a auto-update malfunction. */ forceSlashCommandRegistration:boolean, /**When enabled, the bot is allowed to unregister all slash commands which aren't used in Open Ticket. Disable this if you don't want to use the Open Ticket `ODSlashCommand` classes. */ allowSlashCommandRemoval:boolean, - /**Load the default open ticket text commands. */ + /**Load the default Open Ticket text commands. */ textCommandLoading:boolean, - /**Load the default open ticket questions (from `config/questions.json`) */ + /**Load the default Open Ticket questions (from `config/questions.json`) */ questionLoading:boolean, - /**Load the default open ticket options (from `config/options.json`) */ + /**Load the default Open Ticket options (from `config/options.json`) */ optionLoading:boolean, - /**Load the default open ticket panels (from `config/panels.json`) */ + /**Load the default Open Ticket panels (from `config/panels.json`) */ panelLoading:boolean, - /**Load the default open ticket tickets (from `database/tickets.json`) */ + /**Load the default Open Ticket tickets (from `database/tickets.json`) */ ticketLoading:boolean, - /**Load the default open ticket reaction roles (from `config/options.json`) */ + /**Load the default Open Ticket reaction roles (from `config/options.json`) */ roleLoading:boolean, - /**Load the default open ticket blacklist (from `database/users.json`) */ + /**Load the default Open Ticket blacklist (from `database/users.json`) */ blacklistLoading:boolean, - /**Load the default open ticket transcript compilers. */ + /**Load the default Open Ticket transcript compilers. */ transcriptCompilerLoading:boolean, - /**Load the default open ticket transcript history (from `database/transcripts.json`) */ + /**Load the default Open Ticket transcript history (from `database/transcripts.json`) */ transcriptHistoryLoading:boolean, - /**Load the default open ticket button builders. */ + /**Load the default Open Ticket button builders. */ buttonBuildersLoading:boolean, - /**Load the default open ticket dropdown builders. */ + /**Load the default Open Ticket dropdown builders. */ dropdownBuildersLoading:boolean, - /**Load the default open ticket file builders. */ + /**Load the default Open Ticket file builders. */ fileBuildersLoading:boolean, - /**Load the default open ticket embed builders. */ + /**Load the default Open Ticket embed builders. */ embedBuildersLoading:boolean, - /**Load the default open ticket message builders. */ + /**Load the default Open Ticket message builders. */ messageBuildersLoading:boolean, - /**Load the default open ticket modal builders. */ + /**Load the default Open Ticket modal builders. */ modalBuildersLoading:boolean, - /**Load the default open ticket command responders. */ + /**Load the default Open Ticket command responders. */ commandRespondersLoading:boolean, - /**Load the default open ticket button responders. */ + /**Load the default Open Ticket button responders. */ buttonRespondersLoading:boolean, - /**Load the default open ticket dropdown responders. */ + /**Load the default Open Ticket dropdown responders. */ dropdownRespondersLoading:boolean, - /**Load the default open ticket modal responders. */ + /**Load the default Open Ticket modal responders. */ modalRespondersLoading:boolean, - /**Set the time (in ms) before open ticket sends an error message when no reply is sent in a responder. */ + /**Set the time (in ms) before Open Ticket sends an error message when no reply is sent in a responder. */ responderTimeoutMs:number, - /**Load the default open ticket actions. */ + /**Load the default Open Ticket actions. */ actionsLoading:boolean, - /**Load the default open ticket verify bars. */ + /**Load the default Open Ticket verify bars. */ verifyBarsLoading:boolean, - /**Load the default open ticket permissions. */ + /**Load the default Open Ticket permissions. */ permissionsLoading:boolean, - /**Load the default open ticket posts. */ + /**Load the default Open Ticket posts. */ postsLoading:boolean, - /**Initiate the default open ticket posts. */ + /**Initiate the default Open Ticket posts. */ postsInitiating:boolean, - /**Load the default open ticket cooldowns. */ + /**Load the default Open Ticket cooldowns. */ cooldownsLoading:boolean, - /**Initiate the default open ticket cooldowns. */ + /**Initiate the default Open Ticket cooldowns. */ cooldownsInitiating:boolean, - /**Load the default open ticket help menu categories. */ + /**Load the default Open Ticket help menu categories. */ helpMenuCategoryLoading:boolean, - /**Load the default open ticket help menu components. */ + /**Load the default Open Ticket help menu components. */ helpMenuComponentLoading:boolean, - /**Load the default open ticket stat scopes. */ + /**Load the default Open Ticket stat scopes. */ statScopesLoading:boolean, - /**Load the default open ticket stats. */ + /**Load the default Open Ticket stats. */ statLoading:boolean, - /**Initiate the default open ticket stats. */ + /**Initiate the default Open Ticket stats. */ statInitiating:boolean, - /**Load the default open ticket code/functions. */ + /**Load the default Open Ticket code/functions. */ codeLoading:boolean, - /**Execute the default open ticket code/functions. */ + /**Execute the default Open Ticket code/functions. */ codeExecution:boolean, - /**Load the default open ticket livestatus. */ + /**Load the default Open Ticket livestatus. */ liveStatusLoading:boolean, - /**Load the default open ticket startscreen. */ + /**Load the default Open Ticket startscreen. */ startScreenLoading:boolean, - /**Render the default open ticket startscreen. */ + /**Render the default Open Ticket startscreen. */ startScreenRendering:boolean, - /**Load the emoji style from the open ticket general config. */ + /**Load the emoji style from the Open Ticket general config. */ emojiTitleStyleLoading:boolean, /**The emoji style to use in embed & message titles using `utilities.emoijTitle()` */ emojiTitleStyle:"disabled"|"before"|"after"|"double", @@ -217,9 +217,9 @@ export type ODDefaultsStringArray = { }[keyof ODDefaults] /**## ODDefaultsManager `class` - * This is an open ticket defaults manager. + * This is an Open Ticket defaults manager. * - * It manages all settings in open ticket that are not meant to be in the config. + * It manages all settings in Open Ticket that are not meant to be in the config. * Here you can disable certain default features to replace them or to specifically enable them! * * You are unable to add your own defaults, you can only edit Open Ticket defaults! diff --git a/src/core/api/modules/event.ts b/src/core/api/modules/event.ts index 9d52d8b..18328cb 100644 --- a/src/core/api/modules/event.ts +++ b/src/core/api/modules/event.ts @@ -5,13 +5,13 @@ import { ODManagerData, ODManager, ODValidId } from "./base" import { ODConsoleWarningMessage, ODDebugger } from "./console" /**## ODEvent `class` - * This is an open ticket event. + * This is an Open Ticket event. * * This class is made to work with the `ODEventManager` to handle events. * The function of this specific class is to manage all listeners for a specifc event! */ export class ODEvent extends ODManagerData { - /**Alias to open ticket debugger. */ + /**Alias to Open Ticket debugger. */ #debug?: ODDebugger /**The list of permanent listeners. */ listeners: Function[] = [] @@ -20,7 +20,7 @@ export class ODEvent extends ODManagerData { /**The max listener limit before a possible memory leak will be announced */ listenerLimit: number = 25 - /**Use the open ticket debugger in this manager for logs*/ + /**Use the Open Ticket debugger in this manager for logs*/ useDebug(debug:ODDebugger|null){ this.#debug = debug ?? undefined } @@ -71,7 +71,7 @@ export class ODEvent extends ODManagerData { } /**## ODEventManager `class` - * This is an open ticket event manager. + * This is an Open Ticket event manager. * * This class is made to manage all events in the bot. You can compare it with the built-in node.js `EventEmitter` * diff --git a/src/core/api/modules/flag.ts b/src/core/api/modules/flag.ts index bbc3257..3794f3a 100644 --- a/src/core/api/modules/flag.ts +++ b/src/core/api/modules/flag.ts @@ -5,7 +5,7 @@ import { ODId, ODValidId, ODManager, ODManagerData } from "./base" import { ODDebugger } from "./console" /**## ODFlag `class` - * This is an open ticket flag. + * This is an Open Ticket flag. * * A flag is a boolean that can be specified by a parameter in the console. * It's useful for small settings that are only required once in a while. @@ -54,7 +54,7 @@ export class ODFlag extends ODManagerData { } /**## ODFlagManager `class` - * This is an open ticket flag manager. + * This is an Open Ticket flag manager. * * This class is responsible for managing & initiating all flags of the bot. * It also contains a shortcut for initiating all flags. diff --git a/src/core/api/modules/helpmenu.ts b/src/core/api/modules/helpmenu.ts index 514e1f3..44deec2 100644 --- a/src/core/api/modules/helpmenu.ts +++ b/src/core/api/modules/helpmenu.ts @@ -10,7 +10,7 @@ import { ODDebugger } from "./console" export type ODHelpMenuComponentRenderer = (page:number, category:number, location:number, mode:"slash"|"text") => string|Promise /**## ODHelpMenuComponent `class` - * This is an open ticket help menu component. + * This is an Open Ticket help menu component. * * It can render something on the Open Ticket help menu. */ @@ -28,7 +28,7 @@ export class ODHelpMenuComponent extends ODManagerData { } /**## ODHelpMenuTextComponent `class` - * This is an open ticket help menu text component. + * This is an Open Ticket help menu text component. * * It can render a static piece of text on the Open Ticket help menu. */ @@ -69,7 +69,7 @@ export interface ODHelpMenuCommandComponentSettings { } /**## ODHelpMenuCommandComponent `class` - * This is an open ticket help menu command component. + * This is an Open Ticket help menu command component. * * It contains a useful helper to render a command in the Open Ticket help menu. */ @@ -93,7 +93,7 @@ export class ODHelpMenuCommandComponent extends ODHelpMenuComponent { } /**## ODHelpMenuCategory `class` - * This is an open ticket help menu category. + * This is an Open Ticket help menu category. * * Every category in the help menu is an embed field by default. * Try to limit the amount of components per category. @@ -148,7 +148,7 @@ export class ODHelpMenuCategory extends ODManager { export type ODHelpMenuRenderResult = {name:string, value:string}[][] /**## ODHelpMenuManager `class` - * This is an open ticket help menu manager. + * This is an Open Ticket help menu manager. * * It is responsible for rendering the entire help menu content. * You are also able to configure the amount of categories per page here. @@ -156,7 +156,7 @@ export type ODHelpMenuRenderResult = {name:string, value:string}[][] * Fewer Categories == More Clean Menu */ export class ODHelpMenuManager extends ODManager { - /**Alias to open ticket debugger. */ + /**Alias to Open Ticket debugger. */ #debug: ODDebugger /**The amount of categories per-page. */ categoriesPerPage: number = 3 diff --git a/src/core/api/modules/language.ts b/src/core/api/modules/language.ts index c9f683b..5333945 100644 --- a/src/core/api/modules/language.ts +++ b/src/core/api/modules/language.ts @@ -23,7 +23,7 @@ export interface ODLanguageMetadata { } /**## ODLanguageManager `class` - * This is an open ticket language manager. + * This is an Open Ticket language manager. * * It manages all languages in the bot and manages translation for you! * Get a translation via the `getTranslation()` or `getTranslationWithParams()` methods. @@ -144,7 +144,7 @@ export class ODLanguageManager extends ODManager { } /**## ODLanguage `class` - * This is an open ticket language file. + * This is an Open Ticket language file. * * It contains metadata and all translation strings available in this language. * Register this class to an `ODLanguageManager` to use it! @@ -173,7 +173,7 @@ export class ODLanguage extends ODManagerData { } /**## ODJsonLanguage `class` - * This is an open ticket JSON language file. + * This is an Open Ticket JSON language file. * * It contains metadata and all translation strings from a certain JSON file (in `./languages/`). * Register this class to an `ODLanguageManager` to use it! diff --git a/src/core/api/modules/permission.ts b/src/core/api/modules/permission.ts index ee2b03e..fbfd12b 100644 --- a/src/core/api/modules/permission.ts +++ b/src/core/api/modules/permission.ts @@ -48,7 +48,7 @@ export enum ODPermissionLevel { } /**## ODPermission `class` - * This is an open ticket permission. + * This is an Open Ticket permission. * * It defines a single permission level for a specific scope (global/channel & user/role) * These permissions only apply to commands & interactions. @@ -101,7 +101,7 @@ export interface ODPermissionSettings { export type ODPermissionCalculationCallback = (user:discord.User, channel?:discord.Channel|null, guild?:discord.Guild|null, settings?:ODPermissionSettings|null) => Promise /**## ODPermissionManager `class` - * This is an open ticket permission manager. + * This is an Open Ticket permission manager. * * It manages all permissions in the bot! * Use the `getPermissions()` and `hasPermissions()` methods to get user perms. diff --git a/src/core/api/modules/plugin.ts b/src/core/api/modules/plugin.ts index 6bd03df..07fffa4 100644 --- a/src/core/api/modules/plugin.ts +++ b/src/core/api/modules/plugin.ts @@ -16,7 +16,7 @@ export interface ODUnknownCrashedPlugin { } /**## ODPluginManager `class` - * This is an open ticket plugin manager. + * This is an Open Ticket plugin manager. * * It manages all active plugins in the bot! * It also contains all "plugin classes" which are managers registered by plugins. @@ -93,7 +93,7 @@ export interface ODPluginDetails { } /**## ODPlugin `class` - * This is an open ticket plugin. + * This is an Open Ticket plugin. * * It represents a single plugin in the `./plugins/` directory. * All plugins are accessible via the `openticket.plugins` global. @@ -218,7 +218,7 @@ export class ODPlugin extends ODManagerData { } /**## ODPluginClassManager `class` - * This is an open ticket plugin class manager. + * This is an Open Ticket plugin class manager. * * It manages all managers registered by plugins! * Plugins are able to register their own managers, handlers, functions, classes, ... here. diff --git a/src/core/api/modules/post.ts b/src/core/api/modules/post.ts index b985b1c..ef6dfca 100644 --- a/src/core/api/modules/post.ts +++ b/src/core/api/modules/post.ts @@ -7,7 +7,7 @@ import { ODDebugger } from "./console" import * as discord from "discord.js" /**## ODPostManager `class` - * This is an open ticket post manager. + * This is an Open Ticket post manager. * * It manages `ODPosts`'s for you. * @@ -36,7 +36,7 @@ export class ODPostManager extends ODManager> } /**## ODPost `class` - * This is an open ticket post class. + * This is an Open Ticket post class. * * A post is just a shortcut to a static discord channel or category. * This can be used to get a specific channel over and over again! diff --git a/src/core/api/modules/progressbar.ts b/src/core/api/modules/progressbar.ts index 182360b..b9b8289 100644 --- a/src/core/api/modules/progressbar.ts +++ b/src/core/api/modules/progressbar.ts @@ -6,7 +6,7 @@ import { ODDebugger } from "./console" import readline from "readline" /**## ODProgressBarRendererManager `class` - * This is an open ticket progress bar renderer manager. + * This is an Open Ticket progress bar renderer manager. * * It is responsible for managing all console progress bar renderers in Open Ticket. * @@ -19,7 +19,7 @@ export class ODProgressBarRendererManager extends ODManager { export type ODProgressBarRenderFunc = (settings:Settings,min:number,max:number,value:number,prefix:string|null,suffix:string|null) => string /**## ODProgressBarRenderer `class` - * This is an open ticket console progress bar renderer. + * This is an Open Ticket console progress bar renderer. * * It is used to render a progress bar in the console of the bot. * @@ -76,7 +76,7 @@ export class ODProgressBarRenderer extends ODManagerData { } /**## ODProgressBar `class` - * This is an open ticket console progress bar. + * This is an Open Ticket console progress bar. * * It is used to create a simple or advanced progress bar in the console of the bot. * These progress bars are not visible in the `otdebug.txt` file and should only be used as extra visuals. @@ -160,7 +160,7 @@ export class ODProgressBar extends ODManagerData { } /**## ODTimedProgressBar `class` - * This is an open ticket timed console progress bar. + * This is an Open Ticket timed console progress bar. * * It is used to create a simple timed progress bar in the console. * You can set a fixed duration (milliseconds) in the constructor. @@ -204,7 +204,7 @@ export class ODTimedProgressBar extends ODProgressBar { } /**## ODManualProgressBar `class` - * This is an open ticket manual console progress bar. + * This is an Open Ticket manual console progress bar. * * It is used to create a simple manual progress bar in the console. * You can update the progress manually using `update()`. diff --git a/src/core/api/modules/responder.ts b/src/core/api/modules/responder.ts index 600d93a..d09e13d 100644 --- a/src/core/api/modules/responder.ts +++ b/src/core/api/modules/responder.ts @@ -9,7 +9,7 @@ import { ODClientManager, ODSlashCommand, ODTextCommand, ODTextCommandInteractio import { ODDropdownData, ODMessageBuildResult, ODMessageBuildSentResult, ODModalBuildResult } from "./builder" /**## ODResponderImplementation `class` - * This is an open ticket responder implementation. + * This is an Open Ticket responder implementation. * * It is a basic implementation of the `ODWorkerManager` used by all `ODResponder` classes. * @@ -39,7 +39,7 @@ export class ODResponderImplementation ex export type ODResponderTimeoutErrorCallback = (instance:Instance, source:Source) => void|Promise /**## ODResponderManager `class` - * This is an open ticket responder manager. + * This is an Open Ticket responder manager. * * It contains all Open Ticket responders. Responders can respond to an interaction, button, dropdown, modal or command. * @@ -71,7 +71,7 @@ export class ODResponderManager { } /**## ODCommandResponderManager `class` - * This is an open ticket command responder manager. + * This is an Open Ticket command responder manager. * * It contains all Open Ticket command responders. These can respond to text & slash commands. * @@ -125,7 +125,7 @@ export class ODCommandResponderManager extends ODManager extends OD } /**## ODButtonResponderManager `class` - * This is an open ticket button responder manager. + * This is an Open Ticket button responder manager. * * It contains all Open Ticket button responders. These can respond to button interactions. * @@ -500,7 +500,7 @@ export class ODButtonResponderManager extends ODManager extends ODResponder } /**## ODDropdownResponderManager `class` - * This is an open ticket dropdown responder manager. + * This is an Open Ticket dropdown responder manager. * * It contains all Open Ticket dropdown responders. These can respond to dropdown interactions. * @@ -696,7 +696,7 @@ export class ODDropdownResponderManager extends ODManager extends ODRespond } /**## ODModalResponderManager `class` - * This is an open ticket modal responder manager. + * This is an Open Ticket modal responder manager. * * It contains all Open Ticket modal responders. These can respond to modal interactions. * @@ -983,7 +983,7 @@ export class ODModalResponderManager extends ODManager void /**## ODSession `class` - * This is an open ticket session. + * This is an Open Ticket session. * * It can be used to create 100% unique id's for usage in the bot. An id can also store additional data which isn't saved to the filesystem. * You can almost compare it to the PHP session system. diff --git a/src/core/api/modules/startscreen.ts b/src/core/api/modules/startscreen.ts index 92b5a60..7990c19 100644 --- a/src/core/api/modules/startscreen.ts +++ b/src/core/api/modules/startscreen.ts @@ -13,7 +13,7 @@ import ansis from "ansis" export type ODStartScreenComponentRenderCallback = (location:number) => string|Promise /**## ODStartScreenManager `class` - * This is an open ticket startscreen manager. + * This is an Open Ticket startscreen manager. * * This class is responsible for managing & rendering the startscreen of the bot. * The startscreen is the part you see when the bot has started up successfully. (e.g. the Open Ticket logo, logs, livestatus, flags, ...) @@ -57,7 +57,7 @@ export class ODStartScreenManager extends ODManager { } /**## ODStartScreenComponent `class` - * This is an open ticket startscreen component. + * This is an Open Ticket startscreen component. * * This component can be rendered to the start screen of the bot. * An optional priority can be specified to choose the location of the component. @@ -100,7 +100,7 @@ export interface ODStartScreenProperty { } /**## ODStartScreenLogoComponent `class` - * This is an open ticket startscreen logo component. + * This is an Open Ticket startscreen logo component. * * This component will render an ASCII art logo (from an array) to the startscreen. Every property in the array is another row. * An optional priority can be specified to choose the location of the component. @@ -140,7 +140,7 @@ export interface ODStartScreenHeaderAlignmentSettings { } /**## ODStartScreenHeaderComponent `class` - * This is an open ticket startscreen header component. + * This is an Open Ticket startscreen header component. * * This component will render a header to the startscreen. Properties can be aligned left, right or centered. * An optional priority can be specified to choose the location of the component. @@ -192,7 +192,7 @@ export class ODStartScreenHeaderComponent extends ODStartScreenComponent { } /**## ODStartScreenCategoryComponent `class` - * This is an open ticket startscreen category component. + * This is an Open Ticket startscreen category component. * * This component will render a category to the startscreen. This will only render the category name. You'll need to provide your own renderer for the contents. * An optional priority can be specified to choose the location of the component. @@ -216,7 +216,7 @@ export class ODStartScreenCategoryComponent extends ODStartScreenComponent { } /**## ODStartScreenPropertiesCategoryComponent `class` - * This is an open ticket startscreen properties category component. + * This is an Open Ticket startscreen properties category component. * * This component will render a properties category to the startscreen. This will list the properties in the category. * An optional priority can be specified to choose the location of the component. @@ -238,7 +238,7 @@ export class ODStartScreenPropertiesCategoryComponent extends ODStartScreenCateg } /**## ODStartScreenFlagsCategoryComponent `class` - * This is an open ticket startscreen flags category component. + * This is an Open Ticket startscreen flags category component. * * This component will render a flags category to the startscreen. This will list the enabled flags in the category. * An optional priority can be specified to choose the location of the component. @@ -256,7 +256,7 @@ export class ODStartScreenFlagsCategoryComponent extends ODStartScreenCategoryCo } /**## ODStartScreenPluginsCategoryComponent `class` - * This is an open ticket startscreen plugins category component. + * This is an Open Ticket startscreen plugins category component. * * This component will render a plugins category to the startscreen. This will list the enabled, disabled & crashed plugins in the category. * An optional priority can be specified to choose the location of the component. @@ -283,7 +283,7 @@ export class ODStartScreenPluginsCategoryComponent extends ODStartScreenCategory } /**## ODStartScreenLiveStatusCategoryComponent `class` - * This is an open ticket startscreen livestatus category component. + * This is an Open Ticket startscreen livestatus category component. * * This component will render a livestatus category to the startscreen. This will list the livestatus messages in the category. * An optional priority can be specified to choose the location of the component. @@ -302,7 +302,7 @@ export class ODStartScreenLiveStatusCategoryComponent extends ODStartScreenCateg } /**## ODStartScreenLogsCategoryComponent `class` - * This is an open ticket startscreen logs category component. + * This is an Open Ticket startscreen logs category component. * * This component will render a logs category to the startscreen. This will only render the logs category name. * An optional priority can be specified to choose the location of the component. diff --git a/src/core/api/modules/stat.ts b/src/core/api/modules/stat.ts index ef22771..63ebcca 100644 --- a/src/core/api/modules/stat.ts +++ b/src/core/api/modules/stat.ts @@ -24,7 +24,7 @@ export type ODStatsManagerInitCallback = (database:ODJsonDatabaseStructure, dele export type ODStatScopeSetMode = "set"|"increase"|"decrease" /**## ODStatsManager `class` - * This is an open ticket stats manager. + * This is an Open Ticket stats manager. * * This class is responsible for managing all stats of the bot. * Stats are categorized in "scopes" which can be accessed in this manager. @@ -32,9 +32,9 @@ export type ODStatScopeSetMode = "set"|"increase"|"decrease" * Stats can be accessed in the individual scopes. */ export class ODStatsManager extends ODManager { - /**Alias to open ticket debugger. */ + /**Alias to Open Ticket debugger. */ #debug: ODDebugger - /**Alias to open ticket stats database. */ + /**Alias to Open Ticket stats database. */ database: ODDatabase|null = null /**All the listeners for the init event. */ #initListeners: ODStatsManagerInitCallback[] = [] @@ -97,7 +97,7 @@ export class ODStatsManager extends ODManager { } /**## ODStatScope `class` - * This is an open ticket stat scope. + * This is an Open Ticket stat scope. * * A scope can contain multiple stats. Every scope is seperated from other scopes. * Here, you can read & write the values of all stats. @@ -109,7 +109,7 @@ export class ODStatScope extends ODManager { id: ODId /**Is this stat scope already initialized? */ ready: boolean = false - /**Alias to open ticket stats database. */ + /**Alias to Open Ticket stats database. */ database: ODDatabase|null = null /**The name of this scope (used in embed title) */ name:string @@ -202,7 +202,7 @@ export class ODStatScope extends ODManager { } /**## ODStatGlobalScope `class` - * This is an open ticket stat global scope. + * This is an Open Ticket stat global scope. * * A scope can contain multiple stats. Every scope is seperated from other scopes. * Here, you can read & write the values of all stats. @@ -230,7 +230,7 @@ export class ODStatGlobalScope extends ODStatScope { export type ODStatRenderer = (value:ODValidStatValue, scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise /**## ODStat `class` - * This is an open ticket statistic. + * This is an Open Ticket statistic. * * This single statistic doesn't do anything except defining the rules of this statistic. * Use it in a stats scope to register a new statistic. A statistic can also include a priority to choose the render priority. @@ -254,7 +254,7 @@ export class ODStat extends ODManagerData { } /**## ODBasicStat `class` - * This is an open ticket basic statistic. + * This is an Open Ticket basic statistic. * * This single statistic will store a number, boolean or string in the database. * Use it to create a simple statistic for any stats scope. @@ -277,7 +277,7 @@ export class ODBasicStat extends ODStat { export type ODDynamicStatRenderer = (scopeId:string, guild:discord.Guild, channel:discord.TextBasedChannel, user:discord.User) => string|Promise /**## ODDynamicStat `class` - * This is an open ticket dynamic statistic. + * This is an Open Ticket dynamic statistic. * * A dynamic statistic does not store anything in the database! Instead, it will execute a function to return a custom result. * This can be used to show statistics which are not stored in the database. diff --git a/src/core/api/modules/verifybar.ts b/src/core/api/modules/verifybar.ts index 037d6d4..2b74277 100644 --- a/src/core/api/modules/verifybar.ts +++ b/src/core/api/modules/verifybar.ts @@ -9,7 +9,7 @@ import * as discord from "discord.js" import { ODWorkerManager } from "./worker" /**## ODVerifyBar `class` - * This is an open ticket verifybar. + * This is an Open Ticket verifybar. * * It is contains 2 sets of workers and a lot of utilities for the (✅ ❌) verifybars in the bot. * @@ -47,7 +47,7 @@ export class ODVerifyBar extends ODManagerData { } /**## ODVerifyBarManager `class` - * This is an open ticket verifybar manager. + * This is an Open Ticket verifybar manager. * * It contains all (✅ ❌) verifybars in the bot. * The `ODVerifyBar` classes contain `ODWorkerManager`'s that will be fired when the continue/stop buttons are pressed. diff --git a/src/core/api/modules/worker.ts b/src/core/api/modules/worker.ts index 7b9cf96..566603d 100644 --- a/src/core/api/modules/worker.ts +++ b/src/core/api/modules/worker.ts @@ -9,7 +9,7 @@ import { ODId, ODManager, ODManagerData, ODValidId } from "./base" export type ODWorkerCallback = (instance:Instance, params:Params, source:Source, cancel:() => void) => void|Promise /**## ODWorker `class` - * This is an open ticket worker. + * This is an Open Ticket worker. * * You can compare it with a normal javascript callback, but slightly more advanced! * @@ -32,7 +32,7 @@ export class ODWorker extends ODManager } /**## ODWorker `class` - * This is an open ticket worker manager. + * This is an Open Ticket worker manager. * * It manages & executes `ODWorker`'s in the correct order. * diff --git a/src/core/api/openticket/blacklist.ts b/src/core/api/openticket/blacklist.ts index 448efc6..d7dedcd 100644 --- a/src/core/api/openticket/blacklist.ts +++ b/src/core/api/openticket/blacklist.ts @@ -5,7 +5,7 @@ import { ODManager, ODManagerData, ODValidId } from "../modules/base" import { ODDebugger } from "../modules/console" /**## ODBlacklist `class` - * This is an open ticket blacklisted user. + * This is an Open Ticket blacklisted user. * * This class contains the id of the user this class belongs to & an optional reason for being blacklisted. * @@ -31,7 +31,7 @@ export class ODBlacklist extends ODManagerData { } /**## ODBlacklistManager `class` - * This is an open ticket blacklist manager. + * This is an Open Ticket blacklist manager. * * This class manages all blacklisted users & their reason. Check if someone is blacklisted using their ID in the `exists()` method. * diff --git a/src/core/api/openticket/option.ts b/src/core/api/openticket/option.ts index 5f0adec..8268a59 100644 --- a/src/core/api/openticket/option.ts +++ b/src/core/api/openticket/option.ts @@ -10,7 +10,7 @@ import * as crypto from "crypto" import { ODRoleUpdateMode } from "./role" /**## ODOptionManager `class` - * This is an open ticket option manager. + * This is an Open Ticket option manager. * * This class manages all registered options in the bot. This also includes temporary options generated from tickets where the original option got deleted. * @@ -59,7 +59,7 @@ export interface ODOptionJson { } /**## ODOption `class` - * This is an open ticket option. + * This is an Open Ticket option. * * This class contains all data related to this option (parsed from the config). * @@ -104,7 +104,7 @@ export class ODOption extends ODManager> { } /**## ODOptionData `class` - * This is open ticket option data. + * This is Open Ticket option data. * * This class contains a single property for an option. (string, number, boolean, object, array, null) * @@ -186,7 +186,7 @@ export interface ODTicketOptionIds { } /**## ODTicketOption `class` - * This is an open ticket ticket option. + * This is an Open Ticket ticket option. * * This class contains all data related to an Open Ticket ticket option (parsed from the config). * @@ -240,7 +240,7 @@ export interface ODWebsiteOptionIds { } /**## ODWebsiteOption `class` - * This is an open ticket website option. + * This is an Open Ticket website option. * * This class contains all data related to an Open Ticket website option (parsed from the config). * @@ -298,7 +298,7 @@ export interface ODRoleOptionIds { } /**## ODRoleOption `class` - * This is an open ticket role option. + * This is an Open Ticket role option. * * This class contains all data related to an Open Ticket role option (parsed from the config). * @@ -338,7 +338,7 @@ export class ODRoleOption extends ODOption { } /**## ODOptionSuffixManager `class` - * This is an open ticket option suffix manager. + * This is an Open Ticket option suffix manager. * * This class manages all suffixes from option in the bot. The id of an option suffix is the same as the option id. * @@ -358,7 +358,7 @@ export class ODOptionSuffixManager extends ODManager { } /**## ODOptionSuffix `class` - * This is an open ticket option suffix. + * This is an Open Ticket option suffix. * * This class can generate a suffix for a discord channel name from a specific option. * @@ -380,7 +380,7 @@ export class ODOptionSuffix extends ODManagerData { } /**## ODOptionUserNameSuffix `class` - * This is an open ticket user-name option suffix. + * This is an Open Ticket user-name option suffix. * * This class can generate a user-name suffix for a discord channel name from a specific option. * @@ -393,7 +393,7 @@ export class ODOptionUserNameSuffix extends ODOptionSuffix { } /**## ODOptionUserIdSuffix `class` - * This is an open ticket user-id option suffix. + * This is an Open Ticket user-id option suffix. * * This class can generate a user-id suffix for a discord channel name from a specific option. * @@ -406,7 +406,7 @@ export class ODOptionUserIdSuffix extends ODOptionSuffix { } /**## ODOptionCounterDynamicSuffix `class` - * This is an open ticket counter-dynamic option suffix. + * This is an Open Ticket counter-dynamic option suffix. * * This class can generate a counter-dynamic suffix for a discord channel name from a specific option. * @@ -436,7 +436,7 @@ export class ODOptionCounterDynamicSuffix extends ODOptionSuffix { } /**## ODOptionCounterFixedSuffix `class` - * This is an open ticket counter-fixed option suffix. + * This is an Open Ticket counter-fixed option suffix. * * This class can generate a counter-fixed suffix for a discord channel name from a specific option. * @@ -470,7 +470,7 @@ export class ODOptionCounterFixedSuffix extends ODOptionSuffix { } /**## ODOptionRandomNumberSuffix `class` - * This is an open ticket random-number option suffix. + * This is an Open Ticket random-number option suffix. * * This class can generate a random-number suffix for a discord channel name from a specific option. * @@ -513,7 +513,7 @@ export class ODOptionRandomNumberSuffix extends ODOptionSuffix { } /**## ODOptionRandomHexSuffix `class` - * This is an open ticket random-hex option suffix. + * This is an Open Ticket random-hex option suffix. * * This class can generate a random-hex suffix for a discord channel name from a specific option. * diff --git a/src/core/api/openticket/panel.ts b/src/core/api/openticket/panel.ts index 9ff8364..21ec71b 100644 --- a/src/core/api/openticket/panel.ts +++ b/src/core/api/openticket/panel.ts @@ -6,7 +6,7 @@ import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODValidButtonCo import { ODDebugger } from "../modules/console" /**## ODPanelManager `class` - * This is an open ticket panel manager. + * This is an Open Ticket panel manager. * * This class manages all registered panels in the bot. Only panels which are available in this manager can be auto-updated. * @@ -74,7 +74,7 @@ export interface ODPanelIds { } /**## ODPanel `class` - * This is an open ticket panel. + * This is an Open Ticket panel. * * This class contains all data related to this panel (parsed from the config). */ @@ -134,7 +134,7 @@ export class ODPanel extends ODManager> { } /**## ODPanelData `class` - * This is open ticket panel data. + * This is Open Ticket panel data. * * This class contains a single property for a panel. (string, number, boolean, object, array, null) * diff --git a/src/core/api/openticket/question.ts b/src/core/api/openticket/question.ts index 605a8d2..cd99aad 100644 --- a/src/core/api/openticket/question.ts +++ b/src/core/api/openticket/question.ts @@ -5,7 +5,7 @@ import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } import { ODDebugger } from "../modules/console" /**## ODQuestionManager `class` - * This is an open ticket question manager. + * This is an Open Ticket question manager. * * This class manages all registered questions in the bot. Only questions which are available in this manager can be used in options. * @@ -51,7 +51,7 @@ export interface ODQuestionJson { } /**## ODQuestion `class` - * This is an open ticket question. + * This is an Open Ticket question. * * This class contains all data related to this question (parsed from the config). * @@ -96,7 +96,7 @@ export class ODQuestion extends ODManager> { } /**## ODQuestionData `class` - * This is open ticket question data. + * This is Open Ticket question data. * * This class contains a single property for a question. (string, number, boolean, object, array, null) * @@ -140,7 +140,7 @@ export interface ODShortQuestionIds { } /**## ODShortQuestion `class` - * This is an open ticket short question. + * This is an Open Ticket short question. * * This class contains all data related to an Open Ticket short question (parsed from the config). * @@ -194,7 +194,7 @@ export interface ODParagraphQuestionIds { } /**## ODParagraphQuestion `class` - * This is an open ticket paragraph question. + * This is an Open Ticket paragraph question. * * This class contains all data related to an Open Ticket paragraph question (parsed from the config). * diff --git a/src/core/api/openticket/role.ts b/src/core/api/openticket/role.ts index cd6772d..6240470 100644 --- a/src/core/api/openticket/role.ts +++ b/src/core/api/openticket/role.ts @@ -6,7 +6,7 @@ import { ODDebugger } from "../modules/console" import * as discord from "discord.js" /**## ODRoleManager `class` - * This is an open ticket role manager. + * This is an Open Ticket role manager. * * This class manages all registered reaction roles in the bot. * @@ -61,7 +61,7 @@ export interface ODRoleIds { } /**## ODRole `class` - * This is an open ticket role. + * This is an Open Ticket role. * * This class contains all data related to this role (parsed from the config). * @@ -123,7 +123,7 @@ export class ODRole extends ODManager> { } /**## ODRoleData `class` - * This is open ticket role data. + * This is Open Ticket role data. * * This class contains a single property for a role. (string, number, boolean, object, array, null) * diff --git a/src/core/api/openticket/ticket.ts b/src/core/api/openticket/ticket.ts index d08e3d9..bd00bec 100644 --- a/src/core/api/openticket/ticket.ts +++ b/src/core/api/openticket/ticket.ts @@ -8,7 +8,7 @@ import { ODTicketOption } from "./option" import * as discord from "discord.js" /**## ODTicketManager `class` - * This is an open ticket ticket manager. + * This is an Open Ticket ticket manager. * * This class manages all currently created tickets in the bot. * @@ -261,7 +261,7 @@ export class ODTicket extends ODManager> { } /**## ODTicketData `class` - * This is open ticket ticket data. + * This is Open Ticket ticket data. * * This class contains a single property for a ticket. (string, number, boolean, object, array, null) * From baa4e358789aa44971859c6e7d57cf7fcca57cde Mon Sep 17 00:00:00 2001 From: JasperAtSchool Date: Tue, 28 Jan 2025 14:33:10 +0100 Subject: [PATCH 120/157] Added new API comments (part 12) --- src/core/api/openticket/transcript.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/core/api/openticket/transcript.ts b/src/core/api/openticket/transcript.ts index b26af78..7f3961b 100644 --- a/src/core/api/openticket/transcript.ts +++ b/src/core/api/openticket/transcript.ts @@ -8,6 +8,13 @@ import { ODMessageBuildResult } from "../modules/builder" import { ODClientManager } from "../modules/client" import * as discord from "discord.js" +/**## ODTranscriptManager `class` + * This is an Open Ticket transcript manager. + * + * This class manages all transcript generators in the bot. + * + * The 2 default built-in transcript generators are: `openticket:html-compiler` & `openticket:text-compiler`. + */ export class ODTranscriptManager extends ODManager> { /**The manager responsible for collecting all messages in a channel. */ collector: ODTranscriptCollector @@ -21,13 +28,30 @@ export class ODTranscriptManager extends ODManager> { } } +/**## 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 + +/**## ODTranscriptCompilerCompileFunction `type` + * This function will generate/compile the transcript itself. + */ export type ODTranscriptCompilerCompileFunction = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => ODTranscriptCompilerCompileResult|Promise> + +/**## 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. + */ export type ODTranscriptCompilerReadyFunction = (result:ODTranscriptCompilerCompileResult) => ODTranscriptCompilerReadyResult|Promise +/**## ODTranscriptCompilerInitResult `interface` + * This is the result which is returned by the `init()` function. + */ export interface ODTranscriptCompilerInitResult { + /**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 } From ed9afffd7014ec70c6cfc60d866f563934f448c0 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 28 Jan 2025 18:16:14 +0100 Subject: [PATCH 121/157] Finished API comments --- src/core/api/openticket/transcript.ts | 92 +++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/core/api/openticket/transcript.ts b/src/core/api/openticket/transcript.ts index 7f3961b..dddb245 100644 --- a/src/core/api/openticket/transcript.ts +++ b/src/core/api/openticket/transcript.ts @@ -55,23 +55,49 @@ export interface ODTranscriptCompilerInitResult { pendingMessage:ODMessageBuildResult|null } +/**## ODTranscriptCompilerCompileResult `interface` + * This is the result which is returned by the `compile()` function. + */ export interface ODTranscriptCompilerCompileResult { + /**The ticket this transcript is being created for. */ ticket:ODTicket, + /**The channel this transcript is being created for. */ channel:discord.TextChannel, + /**The user who created the transcript. */ user:discord.User + /**Was the compilation successfull? */ success:boolean, + /**When not successfull, what was the reason? This will also be shown to the user. */ errorReason:string|null, + /**A list of all messages sent in the ticket channel. */ messages:ODTranscriptMessageData[]|null, + /**The result returned by the `compiler()` function. Contains the transcript contents, url or something else. */ data:Data|null } + +/**## ODTranscriptCompilerReadyResult `interface` + * This is the result which is returned by the `ready()` function. + */ export interface ODTranscriptCompilerReadyResult { + /**The message to be sent in the specified channel in the server. */ channelMessage?:ODMessageBuildResult, + /**The message to be sent to the DM of the ticket creator. */ creatorDmMessage?:ODMessageBuildResult, + /**The message to be sent to the DM of all participants. */ participantDmMessage?:ODMessageBuildResult, + /**The message to be sent to the DM of all admins who actively participated in the ticket. */ activeAdminDmMessage?:ODMessageBuildResult, + /**The message to be sent to the DM of all admins who were assigned to this ticket. */ everyAdminDmMessage?:ODMessageBuildResult } +/**## ODTranscriptCompiler `class` + * This is an Open Ticket transcript compiler. + * + * This class manages all functions to generate a transcript. + * + * These functions should be defined when creating this compiler. Existing compilers already exist for html & text transcripts. + */ export class ODTranscriptCompiler 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 @@ -126,6 +152,13 @@ export class ODTranscriptManager_Default extends ODTranscriptManager { } } +/**## ODTranscriptCollector `class` + * This is an Open Ticket transcript collector. + * + * The only goal of this class is to collect & parse all messages from a ticket channel. + * + * It also contains utility functions for counting all messages, calculating file sizes & more! + */ export class ODTranscriptCollector { /**Alias for the ticket manager. */ #tickets: ODTicketManager @@ -169,6 +202,7 @@ export class ODTranscriptCollector { if (!messages) return null return messages.length } + /**Convert an array of discord messages to an array of `ODTranscriptMessageData`'s. This is used to simplify the process of the transcript compilers. */ async convertMessagesToTranscriptData(messages:discord.Message[]): Promise { const final: ODTranscriptMessageData[] = [] for (const msg of messages){ @@ -401,6 +435,9 @@ export class ODTranscriptCollector { } } +/**## ODTranscriptCollectorIncludeSettings `interface` + * Additional settings for the `ODTranscriptCollector` + */ export interface ODTranscriptCollectorIncludeSettings { /**Collect messages from normal discord users. */ users: boolean, @@ -410,6 +447,9 @@ export interface ODTranscriptCollectorIncludeSettings { client: boolean } +/**## ODTranscriptMessageData `interface` + * A universal representatation of a discord message for transcripts. + */ export interface ODTranscriptMessageData { /**The message author. */ author: ODTranscriptUserData, @@ -439,8 +479,14 @@ export interface ODTranscriptMessageData { reactions: ODTranscriptReactionData[] } +/**## ODTranscriptMessageType `type` + * A message type for the `ODTranscriptMessageData` interface. + */ export type ODTranscriptMessageType = "default"|"important"|"ephemeral"|"pinned.message"|"welcome.message"|"boost.message"|"thread.message" +/**## ODTranscriptUserData `interface` + * A universal representatation of a discord user for transcripts. + */ export interface ODTranscriptUserData { /**The id of this user. */ id: string, @@ -456,6 +502,9 @@ export interface ODTranscriptUserData { color: discord.HexColorString } +/**## ODTranscriptEmbedData `interface` + * A universal representatation of a discord embed for transcripts. + */ export interface ODTranscriptEmbedData { /**The title of this embed. */ title: string|null, @@ -481,6 +530,9 @@ export interface ODTranscriptEmbedData { fields: ODTranscriptEmbedFieldData[] } +/**## ODTranscriptEmbedFieldData `interface` + * A universal representatation of a discord embed field for transcripts. + */ export interface ODTranscriptEmbedFieldData { /**The name of this embed field. */ name: string, @@ -490,6 +542,9 @@ export interface ODTranscriptEmbedFieldData { inline: boolean } +/**## ODTranscriptFileData `interface` + * A universal representatation of a discord message attachment for transcripts. + */ export interface ODTranscriptFileData { /**The file type or extension. */ type: string, @@ -507,11 +562,17 @@ export interface ODTranscriptFileData { alt: string|null } +/**## ODTranscriptComponentRowData `interface` + * A universal representatation of a discord message action row for transcripts. + */ export interface ODTranscriptComponentRowData { /**All components (buttons & dropdowns) present in this action row. */ components: (ODTranscriptButtonComponentData|ODTranscriptDropdownComponentData)[] } +/**## ODTranscriptComponentData `interface` + * A universal representatation of a discord message action row component for transcripts. + */ export interface ODTranscriptComponentData { /**The custom id of this component. */ id: string|null, @@ -521,6 +582,9 @@ export interface ODTranscriptComponentData { type: "button"|"dropdown" } +/**## ODTranscriptButtonComponentData `interface` + * A universal representatation of a discord message button for transcripts. + */ export interface ODTranscriptButtonComponentData extends ODTranscriptComponentData { /**The type of this component. */ type: "button" @@ -536,6 +600,9 @@ export interface ODTranscriptButtonComponentData extends ODTranscriptComponentDa url: string|null } +/**## ODTranscriptDropdownComponentData `interface` + * A universal representatation of a discord message dropdown for transcripts. + */ export interface ODTranscriptDropdownComponentData extends ODTranscriptComponentData { /**The type of this component. */ type: "dropdown" @@ -545,6 +612,9 @@ export interface ODTranscriptDropdownComponentData extends ODTranscriptComponent options: ODTranscriptDropdownComponentOptionData[] } +/**## ODTranscriptDropdownComponentOptionData `interface` + * A universal representatation of a discord message dropdown option for transcripts. + */ export interface ODTranscriptDropdownComponentOptionData { /**The custom id of this dropdown option. */ id: string, @@ -556,11 +626,17 @@ export interface ODTranscriptDropdownComponentOptionData { emoji: ODTranscriptEmojiData|null } +/**## ODTranscriptReplyData `interface` + * A universal representatation of a discord reply/interaction for transcripts. + */ export interface ODTranscriptReplyData { /**The type of reply. */ type: "interaction"|"message", } +/**## ODTranscriptReplyData `interface` + * A universal representatation of a discord interaction reply for transcripts. + */ export interface ODTranscriptInteractionReplyData extends ODTranscriptReplyData { /**The type of reply. */ type: "interaction", @@ -570,6 +646,9 @@ export interface ODTranscriptInteractionReplyData extends ODTranscriptReplyData name: string } +/**## ODTranscriptReplyData `interface` + * A universal representatation of a discord message reply for transcripts. + */ export interface ODTranscriptMessageReplyData extends ODTranscriptReplyData { /**The type of reply. */ type: "message", @@ -585,6 +664,9 @@ export interface ODTranscriptMessageReplyData extends ODTranscriptReplyData { content: string|null } +/**## ODTranscriptEmojiData `interface` + * A universal representatation of a discord emoji for transcripts. + */ export interface ODTranscriptEmojiData { /**The id of this emoji. */ id: string|null, @@ -598,6 +680,9 @@ export interface ODTranscriptEmojiData { emoji: string, } +/**## ODTranscriptReactionData `interface` + * A universal representatation of a discord message reaction for transcripts. + */ export interface ODTranscriptReactionData extends ODTranscriptEmojiData { /**The amount of emojis for this reaction. */ amount: number, @@ -605,6 +690,9 @@ export interface ODTranscriptReactionData extends ODTranscriptEmojiData { super: boolean } +/**## ODTranscriptHtmlV2Data `interface` + * The structure of the data sent to the Open Ticket HTML Transcripts v2 API. + */ export interface ODTranscriptHtmlV2Data { version:"2", otversion:string, @@ -792,6 +880,7 @@ export interface ODTranscriptHtmlV2Data { } } }[], + //sadly enough, no premium yet :) premium:{ enabled:boolean, premiumToken:string, @@ -818,6 +907,9 @@ export interface ODTranscriptHtmlV2Data { } } +/**## ODTranscriptHtmlV2Response `interface` + * The structure of the response received from the Open Ticket HTML Transcripts v2 API. + */ export interface ODTranscriptHtmlV2Response { status:"success"|"error", id:string, From deebd2b7580b12034840559543ec70f115ff90cb Mon Sep 17 00:00:00 2001 From: DanoGlez Date: Tue, 28 Jan 2025 23:14:55 +0000 Subject: [PATCH 122/157] Added Polish --- README.md | 6 +- languages/polski.json | 478 +++++++++++++++++++++++++++ src/core/api/defaults/language.ts | 1 + src/data/framework/languageLoader.ts | 1 + 4 files changed, 483 insertions(+), 3 deletions(-) create mode 100644 languages/polski.json diff --git a/README.md b/README.md index 090440e..f2f5a6c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@

Open Ticket is 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! -You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 21 Languages! If you need any help, feel free to join our discord server! +You're also able to customise every little aspect of the bot! From embeds to transcripts. Open Ticket is also translated in more than 22 Languages! If you need any help, feel free to join our discord server!

⭐️ Help us grow by giving a star! ⭐️

@@ -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, Rename & Move all your tickets! -- **🇬🇧 translation** - Open Ticket has been translated in more than **21 languages** by our community! +- **🇬🇧 translation** - Open Ticket has been translated in more than **22 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! @@ -174,7 +174,7 @@ This is the main team working on Open Ticket. Don't forget to check their profil |🇪🇪 Estonian |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇮 Finnish |iamnotmega |🔵 Up To Date (ChatGPT) | |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | -|🇵🇱 Polish |mkevas |🟠 Temporary Outdated (beta) | +|🇵🇱 Polish |danoglez |🟢 Up To Date | |🇳🇴 Norwegian |noonenook |🟠 Temporary Outdated (beta) | |❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | |❓ Persian |sasanwm |🟠 Temporary Outdated (beta) | diff --git a/languages/polski.json b/languages/polski.json new file mode 100644 index 0000000..597de04 --- /dev/null +++ b/languages/polski.json @@ -0,0 +1,478 @@ +{ + "_TRANSLATION":{ + "otversion":"v4.0.0", + "translators":["DanoGlez"], + "lastedited":"28/01/2025", + "language":"Polski", + "automated":false + }, + "checker":{ + "system":{ + "typeError":"[BŁĄD]", + "headerOpenTicket":"OTWÓRZ TICKET", + "typeWarning":"[OSTRZEŻENIE]", + "typeInfo":"[INFO]", + "headerConfigChecker":"SPRAWDZANIE KONFIGURACJI", + "headerDescription":"sprawdź błędy w swoich plikach konfiguracyjnych!", + "footerError":"bot nie uruchomi się, dopóki wszystkie {0} nie zostaną naprawione!", + "footerWarning":"zaleca się naprawienie wszystkich {0} przed uruchomieniem!", + "footerSupport":"WSPARCIE: {0} - DOKUMENTACJA: {1}", + "compactInformation":"użyj {0}, aby uzyskać więcej informacji!", + "dataPath":"ścieżka", + "dataDocs":"dokumentacja", + "dataMessages":"wiadomość" + }, + "messages":{ + "stringTooShort":"Ten tekst nie może być krótszy niż {0} znaków!", + "stringTooLong":"Ten tekst nie może być dłuższy niż {0} znaków!", + "stringLengthInvalid":"Ten tekst musi mieć {0} znaków!", + "stringStartsWith":"Ten tekst musi zaczynać się od {0}!", + "stringEndsWith":"Ten tekst musi kończyć się na {0}!", + "stringContains":"Ten tekst musi zawierać {0}!", + "stringChoices":"Ten tekst może być tylko jednym z następujących wartości: {0}!", + "stringRegex":"Ten tekst jest nieprawidłowy!", + + "numberTooShort":"Ta liczba nie może być krótsza niż {0} znaków!", + "numberTooLong":"Ta liczba nie może być dłuższa niż {0} znaków!", + "numberLengthInvalid":"Ta liczba musi mieć {0} znaków!", + "numberTooSmall":"Ta liczba musi wynosić co najmniej {0}!", + "numberTooLarge":"Ta liczba może wynosić maksymalnie {0}!", + "numberNotEqual":"Ta liczba musi wynosić {0}!", + "numberStep":"Ta liczba musi być wielokrotnością {0}!", + "numberStepOffset":"Ta liczba musi być wielokrotnością {0}, zaczynając od {1}!", + "numberStartsWith":"Ta liczba musi zaczynać się od {0}!", + "numberEndsWith":"Ta liczba musi kończyć się na {0}!", + "numberContains":"Ta liczba musi zawierać {0}!", + "numberChoices":"Ta liczba może być tylko jedną z następujących wartości: {0}!", + "numberFloat":"Ta liczba nie może być dziesiętna!", + "numberNegative":"Ta liczba nie może być ujemna!", + "numberPositive":"Ta liczba nie może być dodatnia!", + "numberZero":"Ta liczba nie może wynosić zero!", + + "booleanTrue":"Ta wartość logiczna nie może być prawdziwa!", + "booleanFalse":"Ta wartość logiczna nie może być fałszywa!", + + "arrayEmptyDisabled":"Ta tablica nie może być pusta!", + "arrayEmptyRequired":"Ta tablica musi być pusta!", + "arrayTooShort":"Ta tablica musi mieć co najmniej {0} elementów!", + "arrayTooLong":"Ta tablica może mieć maksymalnie {0} elementów!", + "arrayLengthInvalid":"Ta tablica musi mieć {0} elementów!", + "arrayInvalidTypes":"Ta tablica może zawierać tylko następujące typy: {0}!", + "arrayDouble":"Ta tablica nie może zawierać tych samych wartości dwukrotnie!", + + "discordInvalidId":"To jest nieprawidłowe ID Discorda {0}!", + "discordInvalidIdOptions":"To jest nieprawidłowe ID Discorda {0}! Możesz również użyć jednego z tych: {1}!", + "discordInvalidToken":"To jest nieprawidłowy token Discorda (składniowo)!", + "colorInvalid":"To jest nieprawidłowy kolor w formacie hex!", + "emojiTooShort":"Ten tekst musi zawierać co najmniej {0} emoji!", + "emojiTooLong":"Ten tekst może zawierać maksymalnie {0} emoji!", + "emojiCustom":"To emoji nie może być niestandardowym emoji Discorda!", + "emojiInvalid":"To jest nieprawidłowe emoji!", + "urlInvalid":"Ten URL jest nieprawidłowy!", + "urlInvalidHttp":"Ten URL może korzystać tylko z protokołu https://!", + "urlInvalidProtocol":"Ten URL może korzystać tylko z protokołów http:// i https://!", + "urlInvalidHostname":"Ten URL ma niedozwoloną nazwę hosta!", + "urlInvalidExtension":"Ten URL ma nieprawidłowe rozszerzenie! Wybierz spośród: {0}!", + "urlInvalidPath":"Ten URL ma nieprawidłową ścieżkę!", + "idNotUnique":"To ID nie jest unikalne, użyj innego ID!", + "idNonExistent":"ID {0} nie istnieje!", + + "invalidType":"Ta właściwość musi być typu: {0}!", + "propertyMissing":"Właściwość {0} jest wymagana w tym obiekcie!", + "propertyOptional":"Właściwość {0} jest opcjonalna w tym obiekcie!", + "objectDisabled":"Ten obiekt jest wyłączony, włącz go za pomocą {0}!", + "nullInvalid":"Ta właściwość nie może być null!", + "switchInvalidType":"To musi być jeden z następujących typów: {0}!", + "objectSwitchInvalid":"Ten obiekt musi być jednym z następujących typów: {0}!", + + "invalidLanguage":"To jest nieprawidłowy język!", + "invalidButton":"Ten przycisk musi zawierać co najmniej {0} lub {1}!", + "unusedOption":"Opcja {0} nie jest nigdzie używana!", + "unusedQuestion":"Pytanie {0} nie jest nigdzie używane!", + "dropdownOption":"Panel z włączonym rozwijanym menu może zawierać tylko opcje typu 'ticket'!" + } + }, + "actions":{ + "buttons":{ + "create":"Otwórz Ticket", + "close":"Zamknij Ticket", + "delete":"Usuń Ticket", + "reopen":"Otwórz ponownie Ticket", + "claim":"Przejmij Ticket", + "unclaim":"Porzuć Ticket", + "pin":"Przypnij Ticket", + "unpin":"Odepnij Ticket", + "clear":"Usuń Tickety", + "helpSwitchSlash":"Pokaż Komendy Slash", + "helpSwitchText":"Pokaż Komendy Tekstowe", + "helpPage":"Strona {0}", + "withReason":"Z Powodem", + "withoutTranscript":"Bez Transkrypcji" + }, + "titles":{ + "created":"Ticket Utworzony", + "close":"Ticket Zamknięty", + "delete":"Ticket Usunięty", + "reopen":"Ticket Ponownie Otwarty", + "claim":"Ticket Przejety", + "unclaim":"Ticket Porzucony", + "pin":"Ticket Przypięty", + "unpin":"Ticket Odpięty", + "rename":"Ticket Przemianowany", + "move":"Ticket Przeniesiony", + "add":"Użytkownik Dodany do Ticketa", + "remove":"Użytkownik Usunięty z Ticketa", + + "help":"Dostępne Komendy", + "statsReset":"Statystyki Zresetowane", + "blacklistAdd":"Użytkownik Zablokowany", + "blacklistRemove":"Użytkownik Odblokowany", + "blacklistGet":"Zablokowany Użytkownik", + "blacklistView":"Aktualna Lista Zablokowanych", + "blacklistAddDm":"Dodano do Listy Zablokowanych", + "blacklistRemoveDm":"Usunięto z Listy Zablokowanych", + "clear":"Tickety Usunięte", + "roles":"Role Zaktualizowane", + + "autoclose":"Ticket Automatycznie Zamknięty", + "autocloseEnabled":"Automatyczne Zamknięcie Włączone", + "autocloseDisabled":"Automatyczne Zamknięcie Wyłączone", + "autodelete":"Ticket Automatycznie Usunięty", + "autodeleteEnabled":"Automatyczne Usuwanie Włączone", + "autodeleteDisabled":"Automatyczne Usuwanie Wyłączone" + }, + "descriptions":{ + "create":"Twój ticket został utworzony. Kliknij poniższy przycisk, aby go otworzyć!", + "close":"Ticket został pomyślnie zamknięty!", + "delete":"Ticket został pomyślnie usunięty!", + "reopen":"Ticket został pomyślnie ponownie otwarty!", + "claim":"Ticket został pomyślnie przypisany!", + "unclaim":"Ticket został pomyślnie odpisany!", + "pin":"Ticket został pomyślnie przypięty!", + "unpin":"Ticket został pomyślnie odpięty!", + "rename":"Ticket został pomyślnie przemianowany na {0}!", + "move":"Ticket został pomyślnie przeniesiony do {0}!", + "add":"{0} został pomyślnie dodany do ticketa!", + "remove":"{0} został pomyślnie usunięty z ticketa!", + + "helpExplanation":"`` => wymagany parametr\n`[name]` => opcjonalny parametr", + "statsReset":"Statystyki bota zostały pomyślnie zresetowane!", + "statsError":"Nie można wyświetlić statystyk ticketa!\n{0} nie jest ticketem!", + "blacklistAdd":"{0} został pomyślnie dodany do czarnej listy!", + "blacklistRemove":"{0} został pomyślnie usunięty z czarnej listy!", + "blacklistGetSuccess":"{0} jest obecnie na czarnej liście!", + "blacklistGetEmpty":"{0} nie znajduje się obecnie na czarnej liście!", + "blacklistViewEmpty":"Nikt nie został jeszcze dodany do czarnej listy!", + "blacklistViewTip":"Użyj \"/blacklist add\", aby dodać użytkownika do czarnej listy!", + "clearVerify":"Czy na pewno chcesz usunąć wiele ticketów?\nTej operacji nie można cofnąć!", + "clearReady":"{0} ticketów zostało pomyślnie usuniętych!", + "rolesEmpty":"Nie zaktualizowano żadnych ról!", + + "autocloseLeave":"Ten ticket został automatycznie zamknięty, ponieważ jego twórca opuścił serwer!", + "autocloseTimeout":"Ten ticket został automatycznie zamknięty z powodu braku aktywności przez więcej niż `{0}h`!", + "autodeleteLeave":"Ten ticket został automatycznie usunięty, ponieważ jego twórca opuścił serwer!", + "autodeleteTimeout":"Ten ticket został automatycznie usunięty z powodu braku aktywności przez więcej niż `{0} dni`!", + "autocloseEnabled":"Autoczynność została włączona w tym tickecie!\nZostanie on zamknięty, jeśli będzie nieaktywny przez więcej niż `{0}h`!", + "autocloseDisabled":"Autoczynność została wyłączona w tym tickecie!\nNie będzie on już zamykany automatycznie!", + "autodeleteEnabled":"Autousuwanie zostało włączone w tym tickecie!\nZostanie on usunięty, jeśli będzie nieaktywny przez więcej niż `{0} dni`!", + "autodeleteDisabled":"Autousuwanie zostało wyłączone w tym tickecie!\nNie będzie on już usuwany automatycznie!", + + "ticketMessageLimit":"Możesz utworzyć maksymalnie {0} ticket(y) jednocześnie!", + "ticketMessageAutoclose":"Ten ticket zostanie automatycznie zamknięty, jeśli będzie nieaktywny przez {0}h!", + "ticketMessageAutodelete":"Ten ticket zostanie automatycznie usunięty, jeśli będzie nieaktywny przez {0} dni!", + "panelReady":"Panel znajduje się poniżej!\nTeraz możesz usunąć tę wiadomość!" + }, + "modal":{ + "closePlaceholder":"Dlaczego zamknąłeś ten ticket?", + "deletePlaceholder":"Dlaczego usunąłeś ten ticket?", + "reopenPlaceholder":"Dlaczego ponownie otworzyłeś ten ticket?", + "claimPlaceholder":"Dlaczego przypisałeś ten ticket?", + "unclaimPlaceholder":"Dlaczego odpisano ten ticket?", + "pinPlaceholder":"Dlaczego przypiąłeś ten ticket?", + "unpinPlaceholder":"Dlaczego odpiąłeś ten ticket?" + }, + "logs":{ + "createLog":"Nowy ticket został utworzony przez {0}!", + "closeLog":"Ten ticket został zamknięty przez {0}!", + "closeDm":"Twój ticket został zamknięty na naszym serwerze!", + "deleteLog":"Ten ticket został usunięty przez {0}!", + "deleteDm":"Twój ticket został usunięty na naszym serwerze!", + "reopenLog":"Ten ticket został ponownie otwarty przez {0}!", + "reopenDm":"Twój ticket został ponownie otwarty na naszym serwerze!", + "claimLog":"Ten ticket został przypisany przez {0}!", + "claimDm":"Twój ticket został przypisany na naszym serwerze!", + "unclaimLog":"Ten ticket został odpisany przez {0}!", + "unclaimDm":"Twój ticket został odpisany na naszym serwerze!", + "pinLog":"Ten ticket został przypięty przez {0}!", + "pinDm":"Twój ticket został przypięty na naszym serwerze!", + "unpinLog":"Ten ticket został odpięty przez {0}!", + "unpinDm":"Twój ticket został odpięty na naszym serwerze!", + "renameLog":"Ten ticket został przemianowany na {0} przez {1}!", + "renameDm":"Twój ticket został przemianowany na {0} na naszym serwerze!", + "moveLog":"Ten ticket został przeniesiony do {0} przez {1}!", + "moveDm":"Twój ticket został przeniesiony do {0} na naszym serwerze!", + "addLog":"{0} został dodany do tego ticketa przez {1}!", + "addDm":"{0} został dodany do twojego ticketa na naszym serwerze!", + "removeLog":"{0} został usunięty z tego ticketa przez {1}!", + "removeDm":"{0} został usunięty z twojego ticketa na naszym serwerze!", + + "blacklistAddLog":"{0} został dodany do czarnej listy przez {1}!", + "blacklistRemoveLog":"{0} został usunięty z czarnej listy przez {1}!", + "blacklistAddDm":"Zostałeś dodany do czarnej listy na naszym serwerze!\nOd teraz nie możesz tworzyć ticketów!", + "blacklistRemoveDm":"Zostałeś usunięty z czarnej listy na naszym serwerze!\nTeraz możesz ponownie tworzyć tickety!", + "clearLog":"{0} ticketów zostało usuniętych przez {1}!" + } + }, + "transcripts":{ + "success":{ + "visit":"Otwórz transkrypt", + "ready":"Transkrypt został utworzony", + "textFileDescription":"To jest tekstowy transkrypt usuniętego ticketa!", + "htmlProgress":"Proszę czekać, trwa przetwarzanie tego transkryptu w formacie HTML...", + + "createdChannel":"Nowy transkrypt {0} został utworzony na serwerze!", + "createdCreator":"Nowy transkrypt {0} został utworzony dla jednego z twoich ticketów!", + "createdParticipant":"Nowy transkrypt {0} został utworzony w jednym z ticketów, w których brałeś udział!", + "createdActiveAdmin":"Nowy transkrypt {0} został utworzony w jednym z ticketów, w których brałeś udział jako administrator!", + "createdEveryAdmin":"Nowy transkrypt {0} został utworzony w jednym z ticketów, w których byłeś administratorem!", + "createdOther":"Nowy transkrypt {0} został utworzony!" + }, + "errors":{ + "retry":"Spróbuj ponownie", + "continue":"Usuń bez transkryptu", + "backup":"Utwórz kopię zapasową transkryptu", + "error":"Coś poszło nie tak podczas próby utworzenia transkryptu.\nCo chciałbyś zrobić?\n\nTen ticket nie zostanie usunięty, dopóki nie klikniesz jednego z tych przycisków." + } + }, + "errors":{ + "titles":{ + "internalError":"Błąd wewnętrzny", + "optionMissing":"Brakująca opcja polecenia", + "optionInvalid":"Nieprawidłowa opcja polecenia", + "unknownCommand":"Nieznane polecenie", + "noPermissions":"Brak uprawnień", + "unknownTicket":"Nieznany ticket", + "deprecatedTicket":"Przestarzały ticket", + "unknownOption":"Nieznana opcja", + "unknownPanel":"Nieznany panel", + "notInGuild":"Nie na serwerze", + "channelRename":"Nie można zmienić nazwy kanału", + "busy":"Ticket jest zajęty" + }, + "descriptions":{ + "askForInfo":"Skontaktuj się z właścicielem tego bota, aby uzyskać więcej informacji!", + "askForInfoResolve":"Skontaktuj się z właścicielem bota, jeśli problem nie rozwiąże się po kilku próbach.", + "internalError":"Nie udało się odpowiedzieć na to {0} z powodu błędu wewnętrznego!", + "optionMissing":"Brak wymaganego parametru w tym poleceniu!", + "optionInvalid":"Parametr w tym poleceniu jest nieprawidłowy!", + "optionInvalidChoose":"Wybierz spośród", + "unknownCommand":"Spróbuj odwiedzić menu pomocy, aby uzyskać więcej informacji!", + "noPermissions":"Nie masz uprawnień do użycia tego {0}!", + "noPermissionsList":"Wymagane uprawnienia: (jedno z nich)", + "noPermissionsCooldown":"Nie możesz użyć tego {0}, ponieważ masz nałożone ograniczenie czasowe!", + "noPermissionsBlacklist":"Nie możesz użyć tego {0}, ponieważ jesteś na czarnej liście!", + "noPermissionsLimitGlobal":"Nie możesz utworzyć ticketa, ponieważ serwer osiągnął maksymalny limit ticketów!", + "noPermissionsLimitGlobalUser":"Nie możesz utworzyć ticketa, ponieważ osiągnąłeś maksymalny limit ticketów!", + "noPermissionsLimitOption":"Nie możesz utworzyć ticketa, ponieważ serwer osiągnął maksymalny limit ticketów dla tej opcji!", + "noPermissionsLimitOptionUser":"Nie możesz utworzyć ticketa, ponieważ osiągnąłeś maksymalny limit ticketów dla tej opcji!", + "unknownTicket":"Spróbuj ponownie użyć tego polecenia w prawidłowym tickecie!", + "deprecatedTicket":"Obecny kanał nie jest prawidłowym ticketem! Może to być ticket z starej wersji Open Ticket!", + "notInGuild":"To {0} nie działa w DM! Spróbuj ponownie na serwerze!", + "channelRename":"Z powodu ograniczeń Discorda obecnie niemożliwe jest, aby bot zmienił nazwę kanału. Kanał zostanie automatycznie przemianowany w ciągu 10 minut, jeśli bot nie zostanie zrestartowany.", + "channelRenameSource":"Źródło tego błędu: {0}", + "busy":"Nie można użyć tego {0}!\nTicket jest obecnie przetwarzany przez bota.\n\nSpróbuj ponownie za kilka sekund!" + }, + "optionInvalidReasons":{ + "stringRegex":"Wartość nie pasuje do wzorca!", + "stringMinLength":"Wartość musi mieć co najmniej {0} znaków!", + "stringMaxLength":"Wartość może mieć maksymalnie {0} znaków!", + "numberInvalid":"Nieprawidłowa liczba!", + "numberMin":"Liczba musi wynosić co najmniej {0}!", + "numberMax":"Liczba może wynosić maksymalnie {0}!", + "numberDecimal":"Liczba nie może być dziesiętna!", + "numberNegative":"Liczba nie może być ujemna!", + "numberPositive":"Liczba nie może być dodatnia!", + "numberZero":"Liczba nie może wynosić zero!", + "channelNotFound":"Nie można znaleźć kanału!", + "userNotFound":"Nie można znaleźć użytkownika!", + "roleNotFound":"Nie można znaleźć roli!", + "memberNotFound":"Nie można znaleźć użytkownika!", + "mentionableNotFound":"Nie można znaleźć użytkownika ani roli!", + "channelType":"Nieprawidłowy typ kanału!", + "notInGuild":"Ta opcja wymaga, abyś był na serwerze!" + }, + "permissions":{ + "developer":"Musisz być deweloperem bota.", + "owner":"Musisz być właścicielem serwera.", + "admin":"Musisz być administratorem serwera.", + "moderator":"Musisz być moderatorem.", + "support":"Musisz należeć do zespołu wsparcia.", + "member":"Musisz być członkiem.", + "discord-administrator":"Musisz mieć uprawnienie `ADMINISTRATOR`." + }, + "actionInvalid":{ + "close":"Ticket jest już zamknięty!", + "reopen":"Ticket nie jest jeszcze zamknięty!", + "claim":"Ticket jest już przypisany!", + "unclaim":"Ticket nie jest jeszcze przypisany!", + "pin":"Ticket jest już przypięty!", + "unpin":"Ticket nie jest przypięty!", + "add":"Ten użytkownik już ma dostęp do ticketa!", + "remove":"Nie można usunąć tego użytkownika z ticketa!" + } + }, + "params":{ + "uppercase":{ + "ticket":"Ticket", + "tickets":"Tickety", + "reason":"Powód", + "creator":"Twórca", + "remaining":"Pozostały czas", + "added":"Dodano", + "removed":"Usunięto", + "filter":"Filtr", + "claimedBy":"Przypisane przez {0}", + "method":"Metoda", + "type":"Typ", + "blacklisted":"Na czarnej liście", + "panel":"Panel", + "command":"Polecenie", + "system":"System", + "true":"Prawda", + "false":"Fałsz", + "syntax":"Składnia", + "originalName":"Oryginalna nazwa", + "newName":"Nowa nazwa", + "until":"Do", + "validOptions":"Prawidłowe opcje", + "validPanels":"Prawidłowe panele", + "autoclose":"Automatyczne zamknięcie", + "autodelete":"Automatyczne usunięcie", + "startupDate":"Data uruchomienia", + "version":"Wersja", + "name":"Nazwa", + "role":"Rola", + "status":"Status", + "claimed":"Przypisane", + "pinned":"Przypięte", + "creationDate":"Data utworzenia" + }, + "lowercase":{ + "text":"tekst", + "html":"html", + "command":"polecenie", + "modal":"modal", + "button":"przycisk", + "dropdown":"rozwijane menu", + "method":"metoda" + } + }, + "commands":{ + "reason":"Określ opcjonalny powód, który będzie widoczny w logach.", + "help":"Uzyskaj listę wszystkich dostępnych poleceń.", + "panel":"Wyślij wiadomość z rozwijanym menu lub przyciskami (do tworzenia ticketów).", + "panelId":"Identyfikator panelu, który chcesz wyświetlić.", + "panelAutoUpdate":"Czy chcesz, aby ten panel automatycznie aktualizował się po edycji?", + "ticket":"Natychmiast utwórz ticket.", + "ticketId":"Identyfikator ticketa, który chcesz utworzyć.", + "close":"Zamknij ticket.", + "delete":"Usuń ticket.", + "deleteNoTranscript":"Usuń ten ticket bez tworzenia transkryptu.", + "reopen":"Ponownie otwórz ticket.", + "claim":"Przypisz ticket.", + "claimUser":"Przypisz ten ticket innej osobie zamiast sobie.", + "unclaim":"Odpowiedz ticket.", + "pin":"Przypnij ticket.", + "unpin":"Odepnij ticket.", + "move":"Przenieś ticket.", + "moveId":"Identyfikator opcji, do której chcesz przenieść ticket.", + "rename":"Zmień nazwę ticketa.", + "renameName":"Nowa nazwa dla tego ticketa.", + "add":"Dodaj użytkownika do ticketa.", + "addUser":"Użytkownik do dodania.", + "remove":"Usuń użytkownika z ticketa.", + "removeUser":"Użytkownik do usunięcia.", + "blacklist":"Zarządzaj czarną listą ticketów.", + "blacklistView":"Wyświetl listę obecnej czarnej listy.", + "blacklistAdd":"Dodaj użytkownika do czarnej listy.", + "blacklistRemove":"Usuń użytkownika z czarnej listy.", + "blacklistGet":"Uzyskaj szczegóły użytkownika na czarnej liście.", + "blacklistGetUser":"Użytkownik do uzyskania szczegółów.", + "stats":"Wyświetl statystyki bota, użytkownika lub ticketa.", + "statsReset":"Zresetuj wszystkie statystyki bota (i zacznij liczyć od zera).", + "statsGlobal":"Wyświetl globalne statystyki.", + "statsUser":"Wyświetl statystyki użytkownika na serwerze.", + "statsUserUser":"Użytkownik do wyświetlenia.", + "statsTicket":"Wyświetl statystyki ticketa na serwerze.", + "statsTicketTicket":"Ticket do wyświetlenia.", + "clear":"Usuń wiele ticketów jednocześnie.", + "clearFilter":"Filtr do usuwania ticketów.", + "clearFilters":{ + "all":"Wszystkie", + "open":"Otwarte", + "close":"Zamknięte", + "claim":"Przypisane", + "unclaim":"Nieprzypisane", + "pin":"Przypięte", + "unpin":"Nieprzypięte", + "autoclose":"Automatycznie zamknięte" + }, + "autoclose":"Zarządzaj automatycznym zamknięciem ticketa.", + "autocloseDisable":"Wyłącz automatyczne zamknięcie w tym tickecie.", + "autocloseEnable":"Włącz automatyczne zamknięcie w tym tickecie.", + "autocloseEnableTime":"Liczba godzin braku aktywności potrzebna do zamknięcia ticketa.", + "autodelete":"Zarządzaj automatycznym usunięciem ticketa.", + "autodeleteDisable":"Wyłącz automatyczne usunięcie w tym tickecie.", + "autodeleteEnable":"Włącz automatyczne usunięcie w tym tickecie.", + "autodeleteEnableTime":"Liczba dni braku aktywności potrzebna do usunięcia ticketa." + }, + "helpMenu":{ + "help":"Uzyskaj listę wszystkich dostępnych poleceń.", + "ticket":"Natychmiast utwórz ticket.", + "close":"Zamknij ticket, wyłączając możliwość pisania na tym kanale.", + "delete":"Usuń ticket, tworząc transkrypt, jeśli jest włączony.", + "reopen":"Ponownie otwórz ticket, włączając możliwość pisania na tym kanale.", + "pin":"Przypnij ticket. To przeniesie ticket na górę i doda emoji '📌' do nazwy.", + "unpin":"Odepnij ticket. Ticket pozostanie na swojej pozycji, ale straci emoji '📌'.", + "move":"Przenieś ticket. To zmieni typ tego ticketa.", + "rename":"Zmień nazwę ticketa. To zmieni nazwę kanału tego ticketa.", + "claim":"Przypisz ticket. Dzięki temu możesz poinformować zespół, że zajmujesz się tym ticketem.", + "unclaim":"Odpowiedz ticket. Dzięki temu możesz poinformować zespół, że ticket jest ponownie dostępny.", + "add":"Dodaj użytkownika do ticketa. Pozwoli to użytkownikowi na odczyt i pisanie w tym tickecie.", + "remove":"Usuń użytkownika z ticketa. To odbierze użytkownikowi możliwość odczytu i pisania w tym tickecie.", + "panel":"Wyślij wiadomość z rozwijanym menu lub przyciskami (do tworzenia ticketów).", + "blacklistView":"Wyświetl listę obecnej czarnej listy.", + "blacklistAdd":"Dodaj użytkownika do czarnej listy.", + "blacklistRemove":"Usuń użytkownika z czarnej listy.", + "blacklistGet":"Uzyskaj szczegóły użytkownika na czarnej liście.", + "statsGlobal":"Wyświetl globalne statystyki.", + "statsTicket":"Wyświetl statystyki ticketa na serwerze.", + "statsUser":"Wyświetl statystyki użytkownika na serwerze.", + "statsReset":"Zresetuj wszystkie statystyki bota (i zacznij liczyć od zera).", + "autocloseDisable":"Wyłącz automatyczne zamknięcie w tym tickecie.", + "autocloseEnable":"Włącz automatyczne zamknięcie w tym tickecie.", + "autodeleteDisable":"Wyłącz automatyczne usunięcie w tym tickecie.", + "autodeleteEnable":"Włącz automatyczne usunięcie w tym tickecie." + }, + "stats":{ + "scopes":{ + "global":"Globalne statystyki", + "system":"Statystyki systemu", + "user":"Statystyki użytkownika", + "ticket":"Statystyki ticketa", + "participants":"Uczestnicy" + }, + "properties":{ + "ticketsCreated":"Tickety utworzone", + "ticketsClosed":"Tickety zamknięte", + "ticketsDeleted":"Tickety usunięte", + "ticketsReopened":"Tickety ponownie otwarte", + "ticketsAutoclosed":"Tickety automatycznie zamknięte", + "ticketsClaimed":"Tickety przypisane", + "ticketsPinned":"Tickety przypięte", + "ticketsMoved":"Tickety przeniesione", + "usersBlacklisted":"Użytkownicy na czarnej liście", + "transcriptsCreated":"Transkrypty utworzone" + } + } +} \ No newline at end of file diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index 5c44f41..e1932b2 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -466,6 +466,7 @@ export interface ODLanguageManagerIds_Default { "openticket:arabic":ODLanguage, "openticket:hindi":ODLanguage, "openticket:lithuanian":ODLanguage, + "openticket:polski":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 34483fc..9bed56b 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -24,6 +24,7 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODJsonLanguage("openticket:arabic","arabic.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:hindi","hindi.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:lithuanian","lithuanian.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:polski","polski.json")) /** How to add more languages? * - Register the language to the manager (see above) From 52b49ec564892a4acdc50332e82e62e81ded1ae1 Mon Sep 17 00:00:00 2001 From: DanoGlez Date: Tue, 28 Jan 2025 23:23:18 +0000 Subject: [PATCH 123/157] Added Custom Emojis feat: allow custom emojis by modifying checker --- src/core/api/modules/checker.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 01cee77..5802125 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -1194,6 +1194,10 @@ export class ODCheckerCustomStructure_EmojiString extends ODCheckerStringStructu const lt = checker.locationTraceDeref(locationTrace) if (typeof value != "string") return false + // check if the string is a valid custom emoji + const customEmojiFormat = /^[\w-]+:\d+$/ + if (customEmojiFormat.test(value)) return true + const discordEmojiSplitter = /(?:)/g const splitted = value.split(discordEmojiSplitter) const discordEmojiAmount = splitted.length-1 From 96d6758b4a21a11d3c49618a454f2d3630394212 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 29 Jan 2025 19:35:10 +0100 Subject: [PATCH 124/157] Update README.md --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 090440e..80b3b17 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ You're also able to customise every little aspect of the bot! From embeds to tra #### And more using plugins! - **💬 reviews** - Create & customise your own review system! - **📢 feedback** - Collect feedback & create forms for people to answer! + - **🏷️ tags** - Create tags & answer questions automatically using keywords! + - **📝 forms** - Create advanced forms and ask people for additional details! - **🔄 rotating status** - Create a rotating bot status & use dynamic variables from the bot! - **💾 sqlite database** - Use an `sqlite` database for increased performances! - **🎉 custom embeds** - Create your own embeds and use them in your server! @@ -94,7 +96,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat > [`ot-migrate-v3`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-migrate-v3/), > [`ot-reviews`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-reviews/), > [`ot-feedback`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-feedback/), -> [`ot-customise-buttons`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-customise-buttons/)** +> [`ot-tags`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-tags/)** ### 📦 Official *(made by DJdj Development)* |Name |Category |Description | @@ -112,18 +114,22 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |🎨 Customisation |Simple plugin to keep the channel prefix when using the /rename command. | |[`ot-customise-buttons`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-customise-buttons/) |🎨 Customisation |Customise almost all built-in buttons. This includes the claim, reopen, close & delete buttons. | |[`ot-ephemeral-messages`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ephemeral-messages/) |🎨 Customisation |Customise for every messages if it needs to be ephemeral or not. | +|[`ot-footers`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-footers/) |🎨 Customisation |A simple plugin to add footers in all Open Ticket embeds. | |[`ot-alt-detector`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-alt-detector/) |💼 Management |Use the discord-alt-detector npm package by DJdj Development in your ticket bot. | |[`ot-embeds`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-embeds/) |💼 Management |Create custom premade embeds in the config or use the command to create one from scratch. | |[`ot-move-actions`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-move-actions/) |💼 Management |Automatically unclaim/unpin a ticket when it's moved using `/move`. | |[`ot-reviews`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-reviews/) |💼 Management |Review system for Open Ticket! It is very customisable and has lots of features. | +|[`ot-tags`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-tags/) |💼 Management |Use tags to quickly reply with a pre-existing text. | |[`ot-better-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-better-status/) |🤖 Client |An advanced status plugin to rotate between states. It also allows for the use of variables. | ### ✅ Verified *(made by community)* |Name |Author |Category |Description | |---------------------------------------------------------------------|----------------------------|----------------------------|-------------------------| |[`ot-config-reload`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-config-reload/) |guillee.3 |⚙️ Utility |This plugin adds a new command that allows reloading the Open Ticket config files without the need for a restart. | +|[`ot-ticket-forms`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ticket-forms/) |guillee.3 |💼 Management |An advanced forms plugin for Open Ticket. | |[`ot-feedback`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-feedback/) |an_developer |💼 Management |A plugin to gather feedback of your support service. | |[`ot-assign-role`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-assign-role/) |rapid.fast |💼 Management |This plugin assigns a predefined role to a user upon creating a ticket. | +|[`ot-translate-cmds`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-translate-cmds/) |guillee.3 |🤖 Client |Translate all built-in command names, descriptions & options. | ### 📢 Categories - **📄 Example** - These plugins serve as an example or starting template. @@ -205,4 +211,4 @@ Please help us grow by giving a star! It would help us a lot! **README.md**
[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)
-© 2025 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) - [Support Us](https://github.com/sponsors/DJj123dj) \ No newline at end of file +© 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) \ No newline at end of file From c57f3397a4d44fbcd932f3c736651d8ad9f79381 Mon Sep 17 00:00:00 2001 From: Jasper Date: Wed, 29 Jan 2025 19:46:04 +0100 Subject: [PATCH 125/157] Update checker.ts --- src/core/api/modules/checker.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 59740a0..6863ed4 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -1194,10 +1194,6 @@ export class ODCheckerCustomStructure_EmojiString extends ODCheckerStringStructu const lt = checker.locationTraceDeref(locationTrace) if (typeof value != "string") return false - // check if the string is a valid custom emoji - const customEmojiFormat = /^[\w-]+:\d+$/ - if (customEmojiFormat.test(value)) return true - const discordEmojiSplitter = /(?:)/g const splitted = value.split(discordEmojiSplitter) const discordEmojiAmount = splitted.length-1 @@ -1472,4 +1468,4 @@ export class ODCheckerCustomStructure_Template extends ODCheckerTemplateStructur this.idk = idk } } -*/ \ No newline at end of file +*/ From e51cc54090fed973aae9efdc38b3988237bfb482 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 29 Jan 2025 19:50:31 +0100 Subject: [PATCH 126/157] Fixed polish translation --- README.md | 2 +- languages/{polski.json => polish.json} | 2 +- src/core/api/defaults/language.ts | 2 +- src/data/framework/languageLoader.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename languages/{polski.json => polish.json} (99%) diff --git a/README.md b/README.md index d9b5684..314aff8 100644 --- a/README.md +++ b/README.md @@ -177,10 +177,10 @@ This is the main team working on Open Ticket. Don't forget to check their profil |🇦🇪 Arabic |palestinian |🟢 Up To Date | |🇮🇳 Hindi |an_developer |🟢 Up To Date | |🇱🇹 Lithuanian |tsgindrius |🟢 Up To Date | +|🇵🇱 Polish |danoglez |🟢 Up To Date | |🇪🇪 Estonian |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇮 Finnish |iamnotmega |🔵 Up To Date (ChatGPT) | |🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | -|🇵🇱 Polish |danoglez |🟢 Up To Date | |🇳🇴 Norwegian |noonenook |🟠 Temporary Outdated (beta) | |❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | |❓ Persian |sasanwm |🟠 Temporary Outdated (beta) | diff --git a/languages/polski.json b/languages/polish.json similarity index 99% rename from languages/polski.json rename to languages/polish.json index 597de04..7f076ef 100644 --- a/languages/polski.json +++ b/languages/polish.json @@ -3,7 +3,7 @@ "otversion":"v4.0.0", "translators":["DanoGlez"], "lastedited":"28/01/2025", - "language":"Polski", + "language":"Polish", "automated":false }, "checker":{ diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index e1932b2..d384005 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -466,7 +466,7 @@ export interface ODLanguageManagerIds_Default { "openticket:arabic":ODLanguage, "openticket:hindi":ODLanguage, "openticket:lithuanian":ODLanguage, - "openticket:polski":ODLanguage, + "openticket:polish":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 9bed56b..f4094b0 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -24,7 +24,7 @@ export const loadAllLanguages = async () => { openticket.languages.add(new api.ODJsonLanguage("openticket:arabic","arabic.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:hindi","hindi.json")) openticket.languages.add(new api.ODJsonLanguage("openticket:lithuanian","lithuanian.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:polski","polski.json")) + openticket.languages.add(new api.ODJsonLanguage("openticket:polish","polish.json")) /** How to add more languages? * - Register the language to the manager (see above) From 8e7fe4e50257f0d5acc60a0042336faceca3596b Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 29 Jan 2025 21:36:26 +0100 Subject: [PATCH 127/157] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 314aff8..0a4f8ad 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ You're also able to customise every little aspect of the bot! From embeds to tra - **📊 detailed stats** - Open Ticket has ticket, user & global staticstics available for everyone! - **🚫 blacklist** - Blacklist users to prevent them from creating a ticket! - **❓ questions** - Let users answer questions in a modal before the ticket is created! -- **📦 commands** - Open Ticket supports both slash & text commands! +- **📦 slash & text** - Open Ticket supports both slash & text commands! - **📥 extra buttons** - The bot also supports Reaction Roles & Url Buttons, because why not ¯\\_(ツ)_/¯ - **✨ commands** - The bot contains more than 25 commands! From f5e78949d7307629856a1d5204dc31fc320c9e1d Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:03:02 +0100 Subject: [PATCH 128/157] Added typedoc for OT Docs API Reference --- .docs/createDocs.js | 246 ++++++++++++++++++++++++++++++++++++++ .docs/typedoc-config.json | 13 ++ .gitignore | 18 ++- package.json | 3 +- src/core/startup/init.ts | 4 +- 5 files changed, 275 insertions(+), 9 deletions(-) create mode 100644 .docs/createDocs.js create mode 100644 .docs/typedoc-config.json diff --git a/.docs/createDocs.js b/.docs/createDocs.js new file mode 100644 index 0000000..639150e --- /dev/null +++ b/.docs/createDocs.js @@ -0,0 +1,246 @@ +//@ts-check +const fs = require("fs") + +/*////// OT DOCS GENERATOR //////// +What does this file do?: +Well, this file will parse the result returned from typedoc (the documentation generator). +The resulting file will then be used in the OT Docs markdown generator to generate the Open Ticket API Reference. + +In short: +This file generates the documentation for Open Ticket :) + +Contributing: +If you want to contribute to the Open Ticket Docs, please run the following command: + +> npm run docs + +This will give you a "result.json" file which can then be used in the OT Docs. +Further instructions can be found there. +/////////////////////////////////*/ + +if (!fs.existsSync(".docs/typedoc-result.json")){ + console.log("Unable to generate documentation! Run typedoc first!") + process.exit(1) +} +const result = JSON.parse(fs.readFileSync(".docs/typedoc-result.json").toString()) +const availableElements = [] +const skipElementNames = [ + "#opendiscord-types" +] + +const handleFunction = (memberType) => { + if (!memberType || !memberType.signatures || !Array.isArray(memberType.signatures)) return {type:"unknown"} + + //try to get signature + let signature = memberType.signatures.find((s) => !s.typeParameters) + if (!signature) signature = memberType.signatures[0] + if (!signature) return {type:"unknown"} + + //try to get comment + let comment = signature.comment + if (!comment) comment = memberType.signatures.find((s) => s.comment)?.comment + if (!comment) comment = null + + const signatureInherited = signature.flags.isInherited ? true : false + const signatureComment = comment ? comment.summary?.map((c) => c.text).join("") : null + const signatureParameters = signature.parameters?.map((p) => { + return {name:p.name,details:handleType(p.type)} + }) ?? [] + const signatureReturns = handleType(signature.type) + + return {type:"function",inherited:signatureInherited,comment:signatureComment,parameters:signatureParameters,returns:signatureReturns} +} + +const handleType = (memberType) => { + if (!memberType || !memberType.type) return {type:"unknown"} + else if (memberType.type == "intrinsic") return {type:"primitive",name:memberType.name} + else if (memberType.type == "array") return {type:"array",child:handleType(memberType.elementType)} + else if (memberType.type == "union") return {type:"union",children:memberType.types.map((t) => handleType(t))} + else if (memberType.type == "intersection") return {type:"intersection",children:memberType.types.map((t) => handleType(t))} + else if (memberType.type == "reference"){ + const referenceTypeArguments = (memberType.typeArguments) ? memberType.typeArguments.map((ta) => handleType(ta)) : null + let referenceType = availableElements.find((el) => el.name == memberType.name)?.type ?? null + + if (referenceType){ + //member is known type (from Open Ticket) + return {type:"reference",name:memberType.name,target:referenceType,typeArguments:referenceTypeArguments} + }else if (memberType.package){ + //member is type from node.js or another package + if (memberType.package == "typescript") return {type:"internal",name:memberType.name,typeArguments:referenceTypeArguments} + if (memberType.package == "open-ticket" && memberType.refersToTypeParameter) return {type:"typeParam",name:memberType.name,typeArguments:referenceTypeArguments} + else return {type:"external",package:memberType.package,name:memberType.name,typeArguments:referenceTypeArguments} + }else return {type:"unknown"} + } + else if (memberType.type == "literal") return {type:"literal",name:(typeof memberType.value == "string") ? JSON.stringify(memberType.value) : String(memberType.value)} + else if (memberType.type == "reflection" && memberType.declaration && memberType.declaration.signatures && memberType.declaration.signatures[0]){ + return handleFunction(memberType.declaration) + }else if (memberType.type == "typeOperator"){ + if (memberType.operator == "keyof") return {type:"keyof",child:handleType(memberType.target)} + else if (memberType.operator == "readonly") return {type:"readonly",child:handleType(memberType.target)} + else if (memberType.operator == "unique") return {type:"unique",child:handleType(memberType.target)} + } + else if (memberType.type == "conditional") return {type:"conditional",checker:handleType(memberType.checkType),extends:handleType(memberType.extendsType),trueValue:handleType(memberType.trueType),falseValue:handleType(memberType.falseType)} + else if (memberType.type == "indexedAccess") return {type:"index",index:handleType(memberType.indexType),object:handleType(memberType.objectType)} + else if (memberType.type == "mapped") return {type:"mapped",parameterName:memberType.parameter,parameter:handleType(memberType.parameterType),template:handleType(memberType.templateType)} + else if (memberType.type == "optional") return {type:"optional",child:handleType(memberType.elementType)} + else if (memberType.type == "predicate") return {type:"predicate",name:memberType.name,target:handleType(memberType.targetType)} + else if (memberType.type == "query") return {type:"query",target:handleType(memberType.queryType)} + else if (memberType.type == "rest") return {type:"rest",child:handleType(memberType.elementType)} + else if (memberType.type == "tuple") return {type:"tuple",children:memberType.elements.map((t) => handleType(t))} + else if (memberType.type == "templateLiteral") return {type:"template",head:memberType.head,tails:memberType.tail.map((t) => { + return {element:handleType(t[0]),text:t[1]} + })} + else return {type:"unknown"} +} + +for (const file of result.children){ + const classIds = file.groups?.find((g) => g.title == "Classes")?.children ?? [] + const interfaceIds = file.groups?.find((g) => g.title == "Interfaces")?.children ?? [] + const typeIds = file.groups?.find((g) => g.title == "Type Aliases")?.children ?? [] + const enumIds = file.groups?.find((g) => g.title == "Enumerations")?.children ?? [] + const varIds = file.groups?.find((g) => g.title == "Variables")?.children ?? [] + + for (const declaration of file.children){ + const declarationName = declaration.name + const declarationType = classIds.includes(declaration.id) ? "class" : interfaceIds.includes(declaration.id) ? "interface" : typeIds.includes(declaration.id) ? "type" : enumIds.includes(declaration.id) ? "enum" : varIds.includes(declaration.id) ? "variable" : "other" + availableElements.push({name:declarationName,type:declarationType}) + } +} + +const exported = [] +for (const file of result.children){ + const classIds = file.groups?.find((g) => g.title == "Classes")?.children ?? [] + const interfaceIds = file.groups?.find((g) => g.title == "Interfaces")?.children ?? [] + const typeIds = file.groups?.find((g) => g.title == "Type Aliases")?.children ?? [] + const enumIds = file.groups?.find((g) => g.title == "Enumerations")?.children ?? [] + const varIds = file.groups?.find((g) => g.title == "Variables")?.children ?? [] + + for (const declaration of (file.children ?? [])){ + const declarationName = declaration.name + if (skipElementNames.includes(declarationName)) continue + + const declarationType = classIds.includes(declaration.id) ? "class" : interfaceIds.includes(declaration.id) ? "interface" : typeIds.includes(declaration.id) ? "type" : enumIds.includes(declaration.id) ? "enum" : varIds.includes(declaration.id) ? "variable" : "other" + const declarationTypeParams = (declaration.typeParameters) ? declaration.typeParameters.map((tp) => { + return {name:tp.name,type:handleType(tp.type)} + }) : null + const declarationComment = declaration.comment?.summary?.map((c) => c.text).join("") ?? null + const declarationConstant = declaration.flags.isConst ? true : false + + const rawDeclarationSource = declaration.sources ? (declaration.sources[0] ?? null) : null + const declarationSource = rawDeclarationSource ? rawDeclarationSource.fileName+":"+rawDeclarationSource.line+":"+rawDeclarationSource.character : null + + const declarationChildren = [] + if (declarationType == "class"){ + //CLASS + const constructorIds = declaration.groups?.find((g) => g.title == "Constructors")?.children ?? [] + const propertyIds = declaration.groups?.find((g) => g.title == "Properties")?.children ?? [] + const methodIds = declaration.groups?.find((g) => g.title == "Methods")?.children ?? [] + + for (const member of (declaration.children ?? [])){ + const memberName = member.name + const memberType = constructorIds.includes(member.id) ? "constructor" : propertyIds.includes(member.id) ? "property" : methodIds.includes(member.id) ? "method" : "other" + let memberComment = member.comment?.summary?.map((c) => c.text).join("") ?? null + + const rawMemberSource = member.sources ? (member.sources[0] ?? null) : null + let memberSource = rawMemberSource ? rawMemberSource.fileName+":"+rawMemberSource.line+":"+rawMemberSource.character : null + + let memberDetails = null + if (memberType == "property"){ + //CLASS => PROPERTY + memberDetails = handleType(member.type) + + }else if (memberType == "method"){ + //CLASS => METHOD + memberDetails = handleFunction(member) + memberComment = memberDetails.comment + } + + declarationChildren.push({ + type:memberType, + name:memberName, + comment:memberComment, + source:memberSource, + details:memberDetails + }) + } + }else if (declarationType == "interface"){ + //INTERFACE + const propertyIds = declaration.groups?.find((g) => g.title == "Properties")?.children ?? [] + const methodIds = declaration.groups?.find((g) => g.title == "Methods")?.children ?? [] + + for (const member of (declaration.children ?? [])){ + const memberName = member.name + const memberType = propertyIds.includes(member.id) ? "property" : methodIds.includes(member.id) ? "method" : "other" + let memberComment = member.comment?.summary?.map((c) => c.text).join("") ?? null + + const rawMemberSource = member.sources ? (member.sources[0] ?? null) : null + let memberSource = rawMemberSource ? rawMemberSource.fileName+":"+rawMemberSource.line+":"+rawMemberSource.character : null + + let memberDetails = null + if (memberType == "property"){ + //INTERFACE => PROPERTY + memberDetails = handleType(member.type) + }else if (memberType == "method"){ + //INTERFACE => METHOD + memberDetails = handleFunction(member) + memberComment = memberDetails.comment + } + + declarationChildren.push({ + type:memberType, + name:memberName, + comment:memberComment, + source:memberSource, + details:memberDetails + }) + } + }else if (declarationType == "type"){ + //TYPE + declarationChildren.push(handleType(declaration.type)) + }else if (declarationType == "enum"){ + //ENUM + const enumerableIds = declaration.groups?.find((g) => g.title == "Enumeration Members")?.children ?? [] + + for (const member of (declaration.children ?? [])){ + const memberName = member.name + const memberType = enumerableIds.includes(member.id) ? "enumerable" : "other" + const memberComment = member.comment?.summary?.map((c) => c.text).join("") ?? null + + const rawMemberSource = member.sources ? (member.sources[0] ?? null) : null + let memberSource = rawMemberSource ? rawMemberSource.fileName+":"+rawMemberSource.line+":"+rawMemberSource.character : null + + let memberDetails = null + if (memberType == "enumerable"){ + //INTERFACE => PROPERTY + memberDetails = handleType(member.type) + } + + declarationChildren.push({ + type:memberType, + name:memberName, + comment:memberComment, + source:memberSource, + details:memberDetails + }) + } + }else if (declarationType == "variable"){ + //VARIABLE + declarationChildren.push(handleType(declaration.type)) + + }else if (declarationType == "other"){ + } + + exported.push({ + type:declarationType, + name:declarationName, + comment:declarationComment, + constant:declarationConstant, + source:declarationSource, + children:declarationChildren, + typeParams:declarationTypeParams + }) + } +} + +fs.writeFileSync(".docs/result.json",JSON.stringify(exported,null,"\t")) +fs.rmSync(".docs/typedoc-result.json") \ No newline at end of file diff --git a/.docs/typedoc-config.json b/.docs/typedoc-config.json new file mode 100644 index 0000000..61e64f7 --- /dev/null +++ b/.docs/typedoc-config.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "entryPoints": [ + "../src/core/api/modules/", + "../src/core/api/defaults/", + "../src/core/api/openticket/", + "../src/core/api/main.ts", + "../src/core/startup/init.ts", + ], + "entryPointStrategy": "expand", + "json": "./typedoc-result.json", + "basePath": "../" +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index b9a2291..3a10e77 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,22 @@ node_modules/ package-lock.json +.vscode/ + devconfig/ devdatabase/ +plugins/* +!plugins/example-plugin/ +database/openticket.sqlite +dist/ + otdebug.txt + .DS_Store */.DS_Store */*/.DS_Store */*/*/.DS_Store **/.DS_Store -TEMP/ -.vscode/ -plugins/* -!plugins/example-plugin/ -dist/ -database/openticket.sqlite \ No newline at end of file + +.docs/* +!.docs/createDocs.js +!.docs/typedoc-config.json \ No newline at end of file diff --git a/package.json b/package.json index 8fba6ed..dbede6b 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "start": "node index.js", "startnc": "node index.js --no-compile", "test": "node index.js --dev-config --dev-database", - "testnc": "node index.js --no-compile --dev-config --dev-database" + "testnc": "node index.js --no-compile --dev-config --dev-database", + "docs": "npx typedoc --options .docs/typedoc-config.json && node .docs/createDocs.js" }, "type": "commonjs", "license": "GPL-3.0-only", diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index 494cf08..bb987e9 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -61,7 +61,7 @@ const timer = (ms:number): Promise => { }) } -interface ODUtilities { +export interface ODUtilities { /**## project `utility variable` * This is the name of the project you are currently in. * @@ -120,7 +120,7 @@ interface ODUtilities { * * It shouldn't be used by plugins because this is an internal API feature! */ -class ODVersionMigration { +export class ODVersionMigration { /**The version to migrate data to */ version: api.ODVersion /**The migration function */ From ac587568d3bbbbb0bfb10179b516fee823d65be4 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Fri, 31 Jan 2025 17:14:56 +0100 Subject: [PATCH 129/157] Update createDocs.js --- .docs/createDocs.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.docs/createDocs.js b/.docs/createDocs.js index 639150e..dc0375f 100644 --- a/.docs/createDocs.js +++ b/.docs/createDocs.js @@ -153,6 +153,11 @@ for (const file of result.children){ //CLASS => METHOD memberDetails = handleFunction(member) memberComment = memberDetails.comment + + }else if (memberType == "constructor"){ + //CLASS => CONSTRUCTOR + memberDetails = handleFunction(member) + memberComment = memberDetails.comment } declarationChildren.push({ @@ -211,7 +216,7 @@ for (const file of result.children){ let memberDetails = null if (memberType == "enumerable"){ - //INTERFACE => PROPERTY + //ENUM => ENUMERABLE memberDetails = handleType(member.type) } @@ -227,7 +232,6 @@ for (const file of result.children){ //VARIABLE declarationChildren.push(handleType(declaration.type)) - }else if (declarationType == "other"){ } exported.push({ From ce242741cdc4da3bd187697fc7485bc66a00374c Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 1 Feb 2025 10:05:26 +0100 Subject: [PATCH 130/157] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0a4f8ad..86fec4b 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |[`ot-ticket-forms`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ticket-forms/) |guillee.3 |💼 Management |An advanced forms plugin for Open Ticket. | |[`ot-feedback`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-feedback/) |an_developer |💼 Management |A plugin to gather feedback of your support service. | |[`ot-assign-role`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-assign-role/) |rapid.fast |💼 Management |This plugin assigns a predefined role to a user upon creating a ticket. | +|[`ot-volume-warning`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-volume-warning/) |guillee.3 |💼 Management |Alerts ticket creators when too many tickets are open, indicating possible response delays. | |[`ot-translate-cmds`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-translate-cmds/) |guillee.3 |🤖 Client |Translate all built-in command names, descriptions & options. | ### 📢 Categories From 29f8e1452c03c4456c234d5ced016b7147127c47 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 1 Feb 2025 10:22:27 +0100 Subject: [PATCH 131/157] BREAKING: changed openticket to opendiscord in API --- plugins/example-plugin/index.ts | 14 +- src/actions/addTicketUser.ts | 36 +- src/actions/claimTicket.ts | 130 ++--- src/actions/clearTickets.ts | 22 +- src/actions/closeTicket.ts | 132 ++--- src/actions/createTicket.ts | 60 +-- src/actions/createTicketPermissions.ts | 32 +- src/actions/createTranscript.ts | 48 +- src/actions/deleteTicket.ts | 222 ++++----- src/actions/handleTranscriptErrors.ts | 68 +-- src/actions/handleVerifyBar.ts | 14 +- src/actions/moveTicket.ts | 60 +-- src/actions/pinTicket.ts | 130 ++--- src/actions/reactionRole.ts | 24 +- src/actions/removeTicketUser.ts | 36 +- src/actions/renameTicket.ts | 38 +- src/actions/reopenTicket.ts | 184 +++---- src/actions/unclaimTicket.ts | 134 ++--- src/actions/unpinTicket.ts | 126 ++--- src/builders/buttons.ts | 12 +- src/builders/dropdowns.ts | 4 +- src/builders/embeds.ts | 48 +- src/builders/files.ts | 10 +- src/builders/messages.ts | 36 +- src/builders/modals.ts | 8 +- src/commands/add.ts | 40 +- src/commands/autoclose.ts | 46 +- src/commands/autodelete.ts | 44 +- src/commands/blacklist.ts | 52 +- src/commands/claim.ts | 66 +-- src/commands/clear.ts | 44 +- src/commands/close.ts | 66 +-- src/commands/delete.ts | 76 +-- src/commands/help.ts | 44 +- src/commands/move.ts | 42 +- src/commands/panel.ts | 36 +- src/commands/pin.ts | 66 +-- src/commands/remove.ts | 40 +- src/commands/rename.ts | 36 +- src/commands/reopen.ts | 72 +-- src/commands/role.ts | 20 +- src/commands/stats.ts | 44 +- src/commands/ticket.ts | 140 +++--- src/commands/unclaim.ts | 66 +-- src/commands/unpin.ts | 66 +-- src/core/api/defaults/action.ts | 2 +- src/core/api/defaults/base.ts | 2 +- src/core/api/defaults/builder.ts | 14 +- src/core/api/defaults/checker.ts | 8 +- src/core/api/defaults/client.ts | 6 +- src/core/api/defaults/code.ts | 2 +- src/core/api/defaults/config.ts | 2 +- src/core/api/defaults/console.ts | 2 +- src/core/api/defaults/cooldown.ts | 2 +- src/core/api/defaults/database.ts | 2 +- src/core/api/defaults/event.ts | 4 +- src/core/api/defaults/flag.ts | 2 +- src/core/api/defaults/helpmenu.ts | 16 +- src/core/api/defaults/language.ts | 2 +- src/core/api/defaults/permission.ts | 2 +- src/core/api/defaults/plugin.ts | 4 +- src/core/api/defaults/post.ts | 2 +- src/core/api/defaults/progressbar.ts | 4 +- src/core/api/defaults/responder.ts | 10 +- src/core/api/defaults/session.ts | 2 +- src/core/api/defaults/startscreen.ts | 2 +- src/core/api/defaults/stat.ts | 12 +- src/core/api/defaults/verifybar.ts | 2 +- src/core/api/modules/builder.ts | 6 +- src/core/api/modules/checker.ts | 15 - src/core/api/modules/console.ts | 4 +- src/core/api/modules/event.ts | 2 +- src/core/api/modules/plugin.ts | 6 +- src/core/api/openticket/transcript.ts | 2 +- src/core/startup/dump.ts | 10 +- src/core/startup/init.ts | 22 +- src/core/startup/manageMigration.ts | 54 +- src/core/startup/migration.ts | 2 +- src/core/startup/pluginLauncher.ts | 58 +-- src/data/framework/checkerLoader.ts | 36 +- src/data/framework/codeLoader.ts | 196 ++++---- src/data/framework/commandLoader.ts | 20 +- src/data/framework/configLoader.ts | 14 +- src/data/framework/cooldownLoader.ts | 6 +- src/data/framework/databaseLoader.ts | 14 +- src/data/framework/eventLoader.ts | 4 +- src/data/framework/flagLoader.ts | 30 +- src/data/framework/helpMenuLoader.ts | 10 +- src/data/framework/languageLoader.ts | 48 +- src/data/framework/liveStatusLoader.ts | 4 +- src/data/framework/permissionLoader.ts | 44 +- src/data/framework/postLoader.ts | 10 +- src/data/framework/progressBarLoader.ts | 22 +- src/data/framework/startScreenLoader.ts | 34 +- src/data/framework/statLoader.ts | 26 +- src/data/openticket/blacklistLoader.ts | 6 +- src/data/openticket/optionLoader.ts | 34 +- src/data/openticket/panelLoader.ts | 12 +- src/data/openticket/questionLoader.ts | 14 +- src/data/openticket/roleLoader.ts | 6 +- src/data/openticket/ticketLoader.ts | 14 +- src/data/openticket/transcriptLoader.ts | 80 +-- src/index.ts | 630 ++++++++++++------------ 103 files changed, 2160 insertions(+), 2175 deletions(-) diff --git a/plugins/example-plugin/index.ts b/plugins/example-plugin/index.ts index c664819..5441b05 100644 --- a/plugins/example-plugin/index.ts +++ b/plugins/example-plugin/index.ts @@ -1,4 +1,4 @@ -import {api, openticket, utilities} from "#opendiscord" +import {api, opendiscord, utilities} from "#opendiscord" import * as discord from "discord.js" ///////////////////////////////////////////// @@ -19,7 +19,7 @@ declare module "#opendiscord-types" { } //Let's register the example config. This way it's available for all plugins & systems. -openticket.events.get("onConfigLoad").listen((configManager) => { +opendiscord.events.get("onConfigLoad").listen((configManager) => { configManager.add(new api.ODJsonConfig("example-plugin:config","config.json","./plugins/example-plugin/")) /*===== What did we do? ===== - "example-plugin:config" Is the ID of this config. You can use this id troughout the bot to access this config file. Even in other plugins. @@ -29,18 +29,18 @@ openticket.events.get("onConfigLoad").listen((configManager) => { //Let's also log it to the console to let us know it worked! const ourConfig = configManager.get("example-plugin:config") - openticket.log("The example config loaded successfully!","plugin",[ + opendiscord.log("The example config loaded successfully!","plugin",[ {key:"var-1",value:ourConfig.data.testVariable1}, {key:"var-2",value:ourConfig.data.testVariable2.toString()}, {key:"var-3",value:ourConfig.data.testVariable3.toString()} ]) }) -openticket.events.get("onTicketCreate").listen((creator) => { +opendiscord.events.get("onTicketCreate").listen((creator) => { //This is logged before the ticket is created (after the button is pressed) - openticket.log("Ticket is getting created...","plugin") + opendiscord.log("Ticket is getting created...","plugin") }) -openticket.events.get("afterTicketCreated").listen((ticket,creator,channel) => { +opendiscord.events.get("afterTicketCreated").listen((ticket,creator,channel) => { //This is logged after the ticket is created - openticket.log("Ticket ready!","plugin") + opendiscord.log("Ticket ready!","plugin") }) \ No newline at end of file diff --git a/src/actions/addTicketUser.ts b/src/actions/addTicketUser.ts index becfd0a..1ed7118 100644 --- a/src/actions/addTicketUser.ts +++ b/src/actions/addTicketUser.ts @@ -1,19 +1,19 @@ /////////////////////////////////////// //TICKET ADD USER SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:add-ticket-user")) - openticket.actions.get("openticket:add-ticket-user").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:add-ticket-user")) + opendiscord.actions.get("openticket:add-ticket-user").workers.add([ new api.ODWorker("openticket:add-ticket-user",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params if (channel.isThread()) throw new api.ODSystemError("Unable to add user to ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketUserAdd").emit([ticket,user,data,channel,reason]) + await opendiscord.events.get("onTicketUserAdd").emit([ticket,user,data,channel,reason]) //update ticket ticket.get("openticket:participants").value.push({type:"user",id:data.id}) @@ -31,47 +31,47 @@ export const registerActions = async () => { ReadMessageHistory:true }) }catch{ - openticket.log("Failed to add channel permission overwrites on add-ticket-user","error") + opendiscord.log("Failed to add channel permission overwrites on add-ticket-user","error") } //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket user adding!","error",[ + opendiscord.log("Unable to edit ticket message on ticket user adding!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value,hidden:true} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } //reply with new message - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:add-message").build(source,{guild,channel,user,ticket,reason,data})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:add-message").build(source,{guild,channel,user,ticket,reason,data})).message) ticket.get("openticket:busy").value = false - await openticket.events.get("afterTicketUserAdded").emit([ticket,user,data,channel,reason]) + await opendiscord.events.get("afterTicketUserAdded").emit([ticket,user,data,channel,reason]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.adding.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.adding.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.adding.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket,data} = params - openticket.log(user.displayName+" added "+data.displayName+" to a ticket!","info",[ + opendiscord.log(user.displayName+" added "+data.displayName+" to a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -81,7 +81,7 @@ export const registerActions = async () => { ]) }) ]) - openticket.actions.get("openticket:add-ticket-user").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:add-ticket-user").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false }) diff --git a/src/actions/claimTicket.ts b/src/actions/claimTicket.ts index ba0e6c7..a70c28e 100644 --- a/src/actions/claimTicket.ts +++ b/src/actions/claimTicket.ts @@ -1,19 +1,19 @@ /////////////////////////////////////// //TICKET CLAIMING SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:claim-ticket")) - openticket.actions.get("openticket:claim-ticket").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:claim-ticket")) + opendiscord.actions.get("openticket:claim-ticket").workers.add([ new api.ODWorker("openticket:claim-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to claim ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketClaim").emit([ticket,user,channel,reason]) + await opendiscord.events.get("onTicketClaim").emit([ticket,user,channel,reason]) //update ticket ticket.get("openticket:claimed").value = true @@ -22,8 +22,8 @@ export const registerActions = async () => { ticket.get("openticket:busy").value = true //update stats - await openticket.stats.get("openticket:global").setStat("openticket:tickets-claimed",1,"increase") - await openticket.stats.get("openticket:user").setStat("openticket:tickets-claimed",user.id,1,"increase") + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-claimed",1,"increase") + await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-claimed",user.id,1,"increase") //update category const rawClaimCategory = ticket.option.get("openticket:channel-categories-claimed").value.find((c) => c.user == user.id) @@ -34,53 +34,53 @@ export const registerActions = async () => { ticket.get("openticket:category-mode").value = "claimed" ticket.get("openticket:category").value = claimCategory }catch(e){ - openticket.log("Unable to move ticket to 'claimed category'!","error",[ + opendiscord.log("Unable to move ticket to 'claimed category'!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"categoryid",value:claimCategory} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket claiming!","error",[ + opendiscord.log("Unable to edit ticket message on ticket claiming!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } //reply with new message - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:claim-message").build(source,{guild,channel,user,ticket,reason})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:claim-message").build(source,{guild,channel,user,ticket,reason})).message) ticket.get("openticket:busy").value = false - await openticket.events.get("afterTicketClaimed").emit([ticket,user,channel,reason]) + await opendiscord.events.get("afterTicketClaimed").emit([ticket,user,channel,reason]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.claiming.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.claiming.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params - openticket.log(user.displayName+" claimed a ticket!","info",[ + opendiscord.log(user.displayName+" claimed a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -90,7 +90,7 @@ export const registerActions = async () => { ]) }) ]) - openticket.actions.get("openticket:claim-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:claim-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false }) @@ -98,37 +98,37 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //CLAIM TICKET TICKET MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:claim-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:claim-ticket-ticket-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:claim-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:claim-ticket-ticket-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.claim if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -136,86 +136,86 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already claimed if (ticket.get("openticket:claimed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start claiming ticket if (params.data == "reason"){ //claim with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:claim-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:claim-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //claim without reason await instance.defer("update",false) - await openticket.actions.get("openticket:claim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:claim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - openticket.verifybars.get("openticket:claim-ticket-ticket-message").failure.add([ + opendiscord.verifybars.get("openticket:claim-ticket-ticket-message").failure.add([ new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //CLAIM TICKET UNCLAIM MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:claim-ticket-unclaim-message",openticket.builders.messages.getSafe("openticket:verifybar-unclaim-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:claim-ticket-unclaim-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:claim-ticket-unclaim-message",opendiscord.builders.messages.getSafe("openticket:verifybar-unclaim-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:claim-ticket-unclaim-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.claim if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -223,55 +223,55 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already claimed if (ticket.get("openticket:claimed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start claiming ticket if (params.data == "reason"){ //claim with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:claim-ticket-reason").build("unclaim-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:claim-ticket-reason").build("unclaim-message",{guild,channel,user,ticket})) }else{ //claim without reason await instance.defer("update",false) - await openticket.actions.get("openticket:claim-ticket").run("unclaim-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:claim-message").build("unclaim-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("openticket:claim-ticket").run("unclaim-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:claim-message").build("unclaim-message",{guild,channel,user,ticket,reason:null})) } }) ]) - openticket.verifybars.get("openticket:claim-ticket-unclaim-message").failure.add([ + opendiscord.verifybars.get("openticket:claim-ticket-unclaim-message").failure.add([ new api.ODWorker("openticket:back-to-unclaim-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await openticket.builders.messages.getSafe("openticket:unclaim-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:unclaim-message").build("other",{guild,channel,user,ticket,reason})) }) ]) } \ No newline at end of file diff --git a/src/actions/clearTickets.ts b/src/actions/clearTickets.ts index 97ecbf4..03a5ff2 100644 --- a/src/actions/clearTickets.ts +++ b/src/actions/clearTickets.ts @@ -1,40 +1,40 @@ /////////////////////////////////////// //CLEAR TICKETS SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:clear-tickets")) - openticket.actions.get("openticket:clear-tickets").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:clear-tickets")) + opendiscord.actions.get("openticket:clear-tickets").workers.add([ new api.ODWorker("openticket:clear-tickets",2,async (instance,params,source,cancel) => { const {guild,channel,user,filter,list} = params - await openticket.events.get("onTicketsClear").emit([list,user,channel,filter]) + await opendiscord.events.get("onTicketsClear").emit([list,user,channel,filter]) const nameList: string[] = [] for (const ticket of list){ - const ticketChannel = await openticket.tickets.getTicketChannel(ticket) + const ticketChannel = await opendiscord.tickets.getTicketChannel(ticket) if (!ticketChannel) return nameList.push("#"+ticketChannel.name) - await openticket.actions.get("openticket:delete-ticket").run("clear",{guild,channel:ticketChannel,user,ticket,reason:"Cleared Ticket",sendMessage:true,withoutTranscript:false}) + await opendiscord.actions.get("openticket:delete-ticket").run("clear",{guild,channel:ticketChannel,user,ticket,reason:"Cleared Ticket",sendMessage:true,withoutTranscript:false}) } instance.list = nameList - await openticket.events.get("afterTicketsCleared").emit([list,user,channel,filter]) + await opendiscord.events.get("afterTicketsCleared").emit([list,user,channel,filter]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,filter,list} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.deleting.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:clear-logs").build(source,{guild,channel,user,filter,list:instance.list ?? []})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:clear-logs").build(source,{guild,channel,user,filter,list:instance.list ?? []})) } }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,user,filter,list} = params - openticket.log(user.displayName+" cleared "+list.length+" tickets!","info",[ + opendiscord.log(user.displayName+" cleared "+list.length+" tickets!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"method",value:source}, diff --git a/src/actions/closeTicket.ts b/src/actions/closeTicket.ts index 350869e..b093b63 100644 --- a/src/actions/closeTicket.ts +++ b/src/actions/closeTicket.ts @@ -1,19 +1,19 @@ /////////////////////////////////////// //TICKET CLOSING SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:close-ticket")) - openticket.actions.get("openticket:close-ticket").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:close-ticket")) + opendiscord.actions.get("openticket:close-ticket").workers.add([ new api.ODWorker("openticket:close-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to close ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketClose").emit([ticket,user,channel,reason]) + await opendiscord.events.get("onTicketClose").emit([ticket,user,channel,reason]) //update ticket ticket.get("openticket:closed").value = true @@ -24,8 +24,8 @@ export const registerActions = async () => { ticket.get("openticket:busy").value = true //update stats - await openticket.stats.get("openticket:global").setStat("openticket:tickets-closed",1,"increase") - await openticket.stats.get("openticket:user").setStat("openticket:tickets-closed",user.id,1,"increase") + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-closed",1,"increase") + await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-closed",user.id,1,"increase") //update category const closeCategory = ticket.option.get("openticket:channel-category-closed").value @@ -35,12 +35,12 @@ export const registerActions = async () => { ticket.get("openticket:category-mode").value = "closed" ticket.get("openticket:category").value = closeCategory }catch(e){ - openticket.log("Unable to move ticket to 'closed category'!","error",[ + opendiscord.log("Unable to move ticket to 'closed category'!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"categoryid",value:closeCategory} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } @@ -51,7 +51,7 @@ export const registerActions = async () => { allow:[], deny:["ViewChannel","SendMessages","ReadMessageHistory"] }] - const globalAdmins = openticket.configs.get("openticket:general").data.globalAdmins + const globalAdmins = opendiscord.configs.get("openticket:general").data.globalAdmins const optionAdmins = ticket.option.get("openticket:admins").value const readonlyAdmins = ticket.option.get("openticket:admins-readonly").value @@ -102,43 +102,43 @@ export const registerActions = async () => { channel.permissionOverwrites.set(permissions) //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket closing!","error",[ + opendiscord.log("Unable to edit ticket message on ticket closing!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } //reply with new message - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:close-message").build(source,{guild,channel,user,ticket,reason})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:close-message").build(source,{guild,channel,user,ticket,reason})).message) ticket.get("openticket:busy").value = false - await openticket.events.get("afterTicketClosed").emit([ticket,user,channel,reason]) + await opendiscord.events.get("afterTicketClosed").emit([ticket,user,channel,reason]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.closing.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.closing.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.closing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params - openticket.log(user.displayName+" closed a ticket!","info",[ + opendiscord.log(user.displayName+" closed a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -148,7 +148,7 @@ export const registerActions = async () => { ]) }) ]) - openticket.actions.get("openticket:close-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:close-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false }) @@ -156,37 +156,37 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //CLOSE TICKET TICKET MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:close-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:close-ticket-ticket-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:close-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:close-ticket-ticket-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.close if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -194,86 +194,86 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:close-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already closed if (ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start closing ticket if (params.data == "reason"){ //close with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:close-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:close-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //close without reason await instance.defer("update",false) - await openticket.actions.get("openticket:close-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:close-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - openticket.verifybars.get("openticket:close-ticket-ticket-message").failure.add([ + opendiscord.verifybars.get("openticket:close-ticket-ticket-message").failure.add([ new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //CLOSE TICKET REOPEN MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:close-ticket-reopen-message",openticket.builders.messages.getSafe("openticket:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:close-ticket-reopen-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:close-ticket-reopen-message",opendiscord.builders.messages.getSafe("openticket:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:close-ticket-reopen-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.close if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -281,55 +281,55 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:close-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already closed if (ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start closing ticket if (params.data == "reason"){ //close with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:close-ticket-reason").build("reopen-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:close-ticket-reason").build("reopen-message",{guild,channel,user,ticket})) }else{ //close without reason await instance.defer("update",false) - await openticket.actions.get("openticket:close-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:close-message").build("reopen-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("openticket:close-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:close-message").build("reopen-message",{guild,channel,user,ticket,reason:null})) } }) ]) - openticket.verifybars.get("openticket:close-ticket-reopen-message").failure.add([ + opendiscord.verifybars.get("openticket:close-ticket-reopen-message").failure.add([ new api.ODWorker("openticket:back-to-reopen-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) }) ]) } \ No newline at end of file diff --git a/src/actions/createTicket.ts b/src/actions/createTicket.ts index 7174a9d..0815fd3 100644 --- a/src/actions/createTicket.ts +++ b/src/actions/createTicket.ts @@ -1,26 +1,26 @@ /////////////////////////////////////// //TICKET CREATION SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:create-ticket")) - openticket.actions.get("openticket:create-ticket").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:create-ticket")) + opendiscord.actions.get("openticket:create-ticket").workers.add([ new api.ODWorker("openticket:create-ticket",3,async (instance,params,source,cancel) => { const {guild,user,answers,option} = params - await openticket.events.get("onTicketCreate").emit([user]) - await openticket.events.get("onTicketChannelCreation").emit([option,user]) + await opendiscord.events.get("onTicketCreate").emit([user]) + await opendiscord.events.get("onTicketChannelCreation").emit([option,user]) //get channel properties const channelPrefix = option.get("openticket:channel-prefix").value const channelCategory = option.get("openticket:channel-category").value const channelBackupCategory = option.get("openticket:channel-category-backup").value const channelDescription = option.get("openticket:channel-description").value - const channelSuffix = openticket.options.suffix.getSuffixFromOption(option,user) + const channelSuffix = opendiscord.options.suffix.getSuffixFromOption(option,user) const channelName = channelPrefix+channelSuffix //handle category @@ -28,10 +28,10 @@ export const registerActions = async () => { let categoryMode: "backup"|"normal"|null = null if (channelCategory != ""){ //category enabled - const normalCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelCategory) + const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory) if (!normalCategory){ //default category was not found - openticket.log("Ticket Creation Error: Unable to find category! #1","error",[ + opendiscord.log("Ticket Creation Error: Unable to find category! #1","error",[ {key:"categoryid",value:channelCategory}, {key:"backup",value:"false"} ]) @@ -39,10 +39,10 @@ export const registerActions = async () => { //default category was found if (normalCategory.children.cache.size >= 50 && channelBackupCategory != ""){ //use backup category - const backupCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelBackupCategory) + const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory) if (!backupCategory){ //default category was not found - openticket.log("Ticket Creation Error: Unable to find category! #2","error",[ + opendiscord.log("Ticket Creation Error: Unable to find category! #2","error",[ {key:"categoryid",value:channelBackupCategory}, {key:"backup",value:"true"} ]) @@ -65,7 +65,7 @@ export const registerActions = async () => { allow:[], deny:["ViewChannel","SendMessages","ReadMessageHistory"] }] - const globalAdmins = openticket.configs.get("openticket:general").data.globalAdmins + const globalAdmins = opendiscord.configs.get("openticket:general").data.globalAdmins const optionAdmins = option.get("openticket:admins").value const readonlyAdmins = option.get("openticket:admins-readonly").value @@ -114,7 +114,7 @@ export const registerActions = async () => { permissionOverwrites:permissions }) - await openticket.events.get("afterTicketChannelCreated").emit([option,channel,user]) + await opendiscord.events.get("afterTicketChannelCreated").emit([option,channel,user]) //create participants const participants: {type:"role"|"user",id:string}[] = [] @@ -159,43 +159,43 @@ export const registerActions = async () => { ]) //manage stats - await openticket.stats.get("openticket:global").setStat("openticket:tickets-created",1,"increase") - await openticket.stats.get("openticket:user").setStat("openticket:tickets-created",user.id,1,"increase") + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-created",1,"increase") + await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-created",user.id,1,"increase") //manage bot permissions - await openticket.events.get("onTicketPermissionsCreated").emit([option,openticket.permissions,channel,user]) + await opendiscord.events.get("onTicketPermissionsCreated").emit([option,opendiscord.permissions,channel,user]) await (await import("../data/framework/permissionLoader.js")).addTicketPermissions(ticket) - await openticket.events.get("afterTicketPermissionsCreated").emit([option,openticket.permissions,channel,user]) + await opendiscord.events.get("afterTicketPermissionsCreated").emit([option,opendiscord.permissions,channel,user]) //export channel & ticket instance.channel = channel instance.ticket = ticket - openticket.tickets.add(ticket) + opendiscord.tickets.add(ticket) }), new api.ODWorker("openticket:send-ticket-message",2,async (instance,params,source,cancel) => { const {guild,user,answers,option} = params const {ticket,channel} = instance - if (!ticket || !channel) return openticket.log("Ticket Creation Error: Unable to send ticket message. Previous worker failed!","error") + if (!ticket || !channel) return opendiscord.log("Ticket Creation Error: Unable to send ticket message. Previous worker failed!","error") - await openticket.events.get("onTicketMainMessageCreated").emit([ticket,channel,user]) + await opendiscord.events.get("onTicketMainMessageCreated").emit([ticket,channel,user]) //check if ticket message is enabled if (!option.get("openticket:ticket-message-enabled").value) return try { - const msg = await channel.send((await openticket.builders.messages.getSafe("openticket:ticket-message").build(source,{guild,channel,user,ticket})).message) + const msg = await channel.send((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build(source,{guild,channel,user,ticket})).message) ticket.get("openticket:ticket-message").value = msg.id //manage stats - await openticket.stats.get("openticket:ticket").setStat("openticket:messages-sent",ticket.id.value,1,"increase") + await opendiscord.stats.get("openticket:ticket").setStat("openticket:messages-sent",ticket.id.value,1,"increase") - await openticket.events.get("afterTicketMainMessageCreated").emit([ticket,msg,channel,user]) + await opendiscord.events.get("afterTicketMainMessageCreated").emit([ticket,msg,channel,user]) }catch(err){ process.emit("uncaughtException",err) //something went wrong while sending the ticket message - channel.send((await openticket.builders.messages.getSafe("openticket:error").build("other",{guild,channel,user,error:"Ticket Message: Creation Error!\n=> Ticket Is Still Created Succesfully",layout:"advanced"})).message) + channel.send((await opendiscord.builders.messages.getSafe("openticket:error").build("other",{guild,channel,user,error:"Ticket Message: Creation Error!\n=> Ticket Is Still Created Succesfully",layout:"advanced"})).message) } - await openticket.events.get("afterTicketCreated").emit([ticket,user,channel]) + await opendiscord.events.get("afterTicketCreated").emit([ticket,user,channel]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,user,answers,option} = params @@ -203,20 +203,20 @@ export const registerActions = async () => { //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.creation.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-created-logs").build(source,{guild,channel,user,ticket})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-created-logs").build(source,{guild,channel,user,ticket})) } //to dm - if (generalConfig.data.system.messages.creation.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:ticket-created-dm").build(source,{guild,channel,user,ticket})) + if (generalConfig.data.system.messages.creation.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("openticket:ticket-created-dm").build(source,{guild,channel,user,ticket})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,user,answers,option} = params const {ticket,channel} = instance - if (!ticket || !channel) return openticket.log("Ticket Creation Error: Unable to create logs. Previous worker failed!","error") + if (!ticket || !channel) return opendiscord.log("Ticket Creation Error: Unable to create logs. Previous worker failed!","error") - openticket.log(user.displayName+" created a ticket!","info",[ + opendiscord.log(user.displayName+" created a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, diff --git a/src/actions/createTicketPermissions.ts b/src/actions/createTicketPermissions.ts index 342cbb4..c5b4c33 100644 --- a/src/actions/createTicketPermissions.ts +++ b/src/actions/createTicketPermissions.ts @@ -1,17 +1,17 @@ /////////////////////////////////////// //TICKET CREATION SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:create-ticket-permissions")) - openticket.actions.get("openticket:create-ticket-permissions").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:create-ticket-permissions")) + opendiscord.actions.get("openticket:create-ticket-permissions").workers.add([ new api.ODWorker("openticket:check-blacklist",4,(instance,params,source,cancel) => { - if (!params.option.get("openticket:allow-blacklisted-users").value && openticket.blacklist.exists(params.user.id)){ + if (!params.option.get("openticket:allow-blacklisted-users").value && opendiscord.blacklist.exists(params.user.id)){ instance.valid = false instance.reason = "blacklist" - openticket.log(params.user.displayName+" tried to create a ticket but is blacklisted!","info",[ + opendiscord.log(params.user.displayName+" tried to create a ticket but is blacklisted!","info",[ {key:"user",value:params.user.username}, {key:"userid",value:params.user.id,hidden:true}, {key:"option",value:params.option.id.value} @@ -20,14 +20,14 @@ export const registerActions = async () => { } }), new api.ODWorker("openticket:check-cooldown",3,(instance,params,source,cancel) => { - const cooldown = openticket.cooldowns.get("openticket:option-cooldown_"+params.option.id.value) + const cooldown = opendiscord.cooldowns.get("openticket:option-cooldown_"+params.option.id.value) if (cooldown && cooldown instanceof api.ODTimeoutCooldown && cooldown.use(params.user.id)){ instance.valid = false instance.reason = "cooldown" const remaining = cooldown.remaining(params.user.id) ?? 0 instance.cooldownUntil = new Date(new Date().getTime() + remaining) - openticket.log(params.user.displayName+" tried to create a ticket but is on cooldown!","info",[ + opendiscord.log(params.user.displayName+" tried to create a ticket but is on cooldown!","info",[ {key:"user",value:params.user.username}, {key:"userid",value:params.user.id,hidden:true}, {key:"option",value:params.option.id.value}, @@ -37,18 +37,18 @@ export const registerActions = async () => { } }), new api.ODWorker("openticket:check-global-limits",2,(instance,params,source,cancel) => { - const generalConfig = openticket.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("openticket:general") if (!generalConfig.data.system.limits.enabled) return - const allTickets = openticket.tickets.getAll() + const allTickets = opendiscord.tickets.getAll() const globalTicketCount = allTickets.length - const userTickets = openticket.tickets.getFiltered((ticket) => ticket.exists("openticket:opened-by") && (ticket.get("openticket:opened-by").value == params.user.id)) + const userTickets = opendiscord.tickets.getFiltered((ticket) => ticket.exists("openticket:opened-by") && (ticket.get("openticket:opened-by").value == params.user.id)) const userTicketCount = userTickets.length if (globalTicketCount >= generalConfig.data.system.limits.globalMaximum){ instance.valid = false instance.reason = "global-limit" - openticket.log(params.user.displayName+" tried to create a ticket but reached the limit!","info",[ + opendiscord.log(params.user.displayName+" tried to create a ticket but reached the limit!","info",[ {key:"user",value:params.user.username}, {key:"userid",value:params.user.id,hidden:true}, {key:"option",value:params.option.id.value}, @@ -58,7 +58,7 @@ export const registerActions = async () => { }else if (userTicketCount >= generalConfig.data.system.limits.userMaximum){ instance.valid = false instance.reason = "global-user-limit" - openticket.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ + opendiscord.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ {key:"user",value:params.user.username}, {key:"userid",value:params.user.id,hidden:true}, {key:"option",value:params.option.id.value}, @@ -70,15 +70,15 @@ export const registerActions = async () => { new api.ODWorker("openticket:check-option-limits",1,(instance,params,source,cancel) => { if (!params.option.exists("openticket:limits-enabled") || !params.option.get("openticket:limits-enabled").value) return - const allTickets = openticket.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value) + const allTickets = opendiscord.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value) const globalTicketCount = allTickets.length - const userTickets = openticket.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value && ticket.exists("openticket:opened-by") && (ticket.get("openticket:opened-by").value == params.user.id)) + const userTickets = opendiscord.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value && ticket.exists("openticket:opened-by") && (ticket.get("openticket:opened-by").value == params.user.id)) const userTicketCount = userTickets.length if (globalTicketCount >= params.option.get("openticket:limits-maximum-global").value){ instance.valid = false instance.reason = "option-limit" - openticket.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ + opendiscord.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ {key:"user",value:params.user.username}, {key:"userid",value:params.user.id,hidden:true}, {key:"option",value:params.option.id.value}, @@ -88,7 +88,7 @@ export const registerActions = async () => { }else if (userTicketCount >= params.option.get("openticket:limits-maximum-user").value){ instance.valid = false instance.reason = "option-user-limit" - openticket.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ + opendiscord.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ {key:"user",value:params.user.username}, {key:"userid",value:params.user.id,hidden:true}, {key:"option",value:params.option.id.value}, diff --git a/src/actions/createTranscript.ts b/src/actions/createTranscript.ts index 10fab95..90e2d1f 100644 --- a/src/actions/createTranscript.ts +++ b/src/actions/createTranscript.ts @@ -1,23 +1,23 @@ /////////////////////////////////////// //TRANSCRIPT CREATION SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const transcriptConfig = openticket.configs.get("openticket:transcripts") +const transcriptConfig = opendiscord.configs.get("openticket:transcripts") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:create-transcript")) - openticket.actions.get("openticket:create-transcript").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:create-transcript")) + opendiscord.actions.get("openticket:create-transcript").workers.add([ new api.ODWorker("openticket:select-compiler",4,async (instance,params,source,cancel) => { const {channel,user,ticket} = params if (channel.type != discord.ChannelType.GuildText) return cancel() if (!transcriptConfig.data.general.enabled) return cancel() - await openticket.events.get("onTranscriptCreate").emit([openticket.transcripts,ticket,channel,user]) + await opendiscord.events.get("onTranscriptCreate").emit([opendiscord.transcripts,ticket,channel,user]) instance.errorReason = null - const participants = await openticket.tickets.getAllTicketParticipants(params.ticket) + const participants = await opendiscord.tickets.getAllTicketParticipants(params.ticket) if (!participants){ instance.pendingMessage = null instance.errorReason = "Unable to fetch ticket channel participants!" @@ -26,8 +26,8 @@ export const registerActions = async () => { instance.participants = participants //select transcript compiler - if (transcriptConfig.data.general.mode == "text") instance.compiler = openticket.transcripts.get("openticket:text-compiler") - else if (transcriptConfig.data.general.mode == "html") instance.compiler = openticket.transcripts.get("openticket:html-compiler") + if (transcriptConfig.data.general.mode == "text") instance.compiler = opendiscord.transcripts.get("openticket:text-compiler") + else if (transcriptConfig.data.general.mode == "html") instance.compiler = opendiscord.transcripts.get("openticket:html-compiler") }), new api.ODWorker("openticket:init-transcript",3,async (instance,params,source,cancel) => { const {channel,user,ticket} = params @@ -35,13 +35,13 @@ export const registerActions = async () => { if (!transcriptConfig.data.general.enabled) return cancel() //run transcript compiler init() - await openticket.events.get("onTranscriptInit").emit([openticket.transcripts,ticket,channel,user]) + await opendiscord.events.get("onTranscriptInit").emit([opendiscord.transcripts,ticket,channel,user]) if (instance.compiler.init){ try{ const result = await instance.compiler.init(ticket,channel,user) if (result.success && result.pendingMessage && transcriptConfig.data.general.enableChannel){ //send init message to channel - const post = openticket.posts.get("openticket:transcripts") + const post = opendiscord.posts.get("openticket:transcripts") if (post){ instance.pendingMessage = await post.send(result.pendingMessage) } @@ -57,7 +57,7 @@ export const registerActions = async () => { throw new api.ODSystemError("ODAction(ot:create-transcript) => Failed transcript compiler init()! (see error above)") } } - await openticket.events.get("afterTranscriptInitiated").emit([openticket.transcripts,ticket,channel,user]) + await opendiscord.events.get("afterTranscriptInitiated").emit([opendiscord.transcripts,ticket,channel,user]) }), new api.ODWorker("openticket:compile-transcript",2,async (instance,params,source,cancel) => { const {channel,user,ticket} = params @@ -69,7 +69,7 @@ export const registerActions = async () => { } //run transcript compiler compile() - await openticket.events.get("onTranscriptCompile").emit([openticket.transcripts,ticket,channel,user]) + 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) @@ -87,7 +87,7 @@ export const registerActions = async () => { throw new api.ODSystemError("ODAction(ot:create-transcript) => Failed transcript compiler compile()! (see error above)") } } - await openticket.events.get("afterTranscriptCompiled").emit([openticket.transcripts,ticket,channel,user]) + await opendiscord.events.get("afterTranscriptCompiled").emit([opendiscord.transcripts,ticket,channel,user]) }), new api.ODWorker("openticket:ready-transcript",1,async (instance,params,source,cancel) => { if (!instance.result){ @@ -98,7 +98,7 @@ export const registerActions = async () => { //run transcript compiler ready() utilities.runAsync(async () => { - await openticket.events.get("onTranscriptReady").emit([openticket.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) + await opendiscord.events.get("onTranscriptReady").emit([opendiscord.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) if (instance.compiler.ready){ try{ const {channelMessage,creatorDmMessage,participantDmMessage,activeAdminDmMessage,everyAdminDmMessage} = await instance.compiler.ready(instance.result) @@ -110,7 +110,7 @@ export const registerActions = async () => { instance.pendingMessage.message.edit(channelMessage.message) }else{ //send ready message to channel - const post = openticket.posts.get("openticket:transcripts") + const post = opendiscord.posts.get("openticket:transcripts") if (post) await post.send(channelMessage) } } @@ -120,16 +120,16 @@ export const registerActions = async () => { for (const p of instance.participants){ if (p.role == "creator" && transcriptConfig.data.general.enableCreatorDM && creatorDmMessage){ //send creator dm message - await openticket.client.sendUserDm(p.user,creatorDmMessage) + await opendiscord.client.sendUserDm(p.user,creatorDmMessage) }else if (p.role == "participant" && transcriptConfig.data.general.enableParticipantDM && participantDmMessage){ //send participant dm message - await openticket.client.sendUserDm(p.user,participantDmMessage) + await opendiscord.client.sendUserDm(p.user,participantDmMessage) }else if (p.role == "admin" && transcriptConfig.data.general.enableActiveAdminDM && instance.result.success && instance.result.messages && instance.result.messages.some((msg) => msg.author.id == p.user.id) && activeAdminDmMessage){ //send active admin dm message - await openticket.client.sendUserDm(p.user,activeAdminDmMessage) + await opendiscord.client.sendUserDm(p.user,activeAdminDmMessage) }else if (p.role == "admin" && transcriptConfig.data.general.enableEveryAdminDM && everyAdminDmMessage){ //send every admin dm message - await openticket.client.sendUserDm(p.user,everyAdminDmMessage) + await opendiscord.client.sendUserDm(p.user,everyAdminDmMessage) } } } @@ -141,17 +141,17 @@ export const registerActions = async () => { throw new api.ODSystemError("ODAction(ot:create-transcript) => Failed transcript compiler ready()! (see error above)") } } - await openticket.events.get("afterTranscriptReady").emit([openticket.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) + await opendiscord.events.get("afterTranscriptReady").emit([opendiscord.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) }) //update stats - await openticket.stats.get("openticket:global").setStat("openticket:transcripts-created",1,"increase") - await openticket.stats.get("openticket:user").setStat("openticket:transcripts-created",params.user.id,1,"increase") - await openticket.events.get("afterTranscriptCreated").emit([openticket.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) + await opendiscord.stats.get("openticket:global").setStat("openticket:transcripts-created",1,"increase") + await opendiscord.stats.get("openticket:user").setStat("openticket:transcripts-created",params.user.id,1,"increase") + await opendiscord.events.get("afterTranscriptCreated").emit([opendiscord.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {user,channel,ticket} = params - openticket.log(user.displayName+" created a transcript!","info",[ + opendiscord.log(user.displayName+" created a transcript!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, diff --git a/src/actions/deleteTicket.ts b/src/actions/deleteTicket.ts index 8748bf8..72234bd 100644 --- a/src/actions/deleteTicket.ts +++ b/src/actions/deleteTicket.ts @@ -1,55 +1,55 @@ /////////////////////////////////////// //TICKET DELETION SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:delete-ticket")) - openticket.actions.get("openticket:delete-ticket").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:delete-ticket")) + opendiscord.actions.get("openticket:delete-ticket").workers.add([ new api.ODWorker("openticket:delete-ticket",3,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to delete ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketDelete").emit([ticket,user,channel,reason]) + await opendiscord.events.get("onTicketDelete").emit([ticket,user,channel,reason]) //update ticket ticket.get("openticket:for-deletion").value = true ticket.get("openticket:busy").value = true //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket deletion!","error",[ + opendiscord.log("Unable to edit ticket message on ticket deletion!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:delete-message").build(source,{guild,channel,user,ticket,reason})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:delete-message").build(source,{guild,channel,user,ticket,reason})).message) //create transcript if (!params.withoutTranscript){ - const transcriptRes = await openticket.actions.get("openticket:create-transcript").run(source,{guild,channel,user,ticket}) + const transcriptRes = await opendiscord.actions.get("openticket:create-transcript").run(source,{guild,channel,user,ticket}) //transcript failure if (typeof transcriptRes.success == "boolean" && !transcriptRes.success && transcriptRes.compiler){ const {compiler} = transcriptRes - await channel.send((await openticket.builders.messages.getSafe("openticket:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason:transcriptRes.errorReason ?? null})).message) - .catch((reason) => openticket.log("Unable to send transcript failure to ticket channel!","error",[{key:"id",value:channel.id}])) + await channel.send((await opendiscord.builders.messages.getSafe("openticket:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason:transcriptRes.errorReason ?? null})).message) + .catch((reason) => opendiscord.log("Unable to send transcript failure to ticket channel!","error",[{key:"id",value:channel.id}])) //undo deletion ticket.get("openticket:for-deletion").value = false ticket.get("openticket:busy").value = false - openticket.log("Canceled ticket deletion because of transcript system malfunction!","warning",[ + opendiscord.log("Canceled ticket deletion because of transcript system malfunction!","warning",[ {key:"compiler",value:compiler.id.value}, {key:"reason",value:transcriptRes.errorReason ?? "/"}, ]) @@ -58,11 +58,11 @@ export const registerActions = async () => { } //update stats - await openticket.stats.get("openticket:global").setStat("openticket:tickets-deleted",1,"increase") - await openticket.stats.get("openticket:user").setStat("openticket:tickets-deleted",user.id,1,"increase") + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-deleted",1,"increase") + await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-deleted",user.id,1,"increase") //delete ticket from manager - openticket.tickets.remove(ticket.id) + opendiscord.tickets.remove(ticket.id) //delete permissions from manager await (await import("../data/framework/permissionLoader.js")).removeTicketPermissions(ticket) @@ -73,30 +73,30 @@ export const registerActions = async () => { //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.deleting.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.deleting.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.deleting.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) }), new api.ODWorker("openticket:delete-channel",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //delete channel & events - await openticket.events.get("onTicketChannelDeletion").emit([ticket,channel,user]) - await channel.delete("Ticket Deleted").catch((reason) => openticket.log("Unable to delete ticket channel!","error",[{key:"id",value:channel.id}])) - await openticket.events.get("afterTicketChannelDeleted").emit([ticket,user]) + await opendiscord.events.get("onTicketChannelDeletion").emit([ticket,channel,user]) + await channel.delete("Ticket Deleted").catch((reason) => opendiscord.log("Unable to delete ticket channel!","error",[{key:"id",value:channel.id}])) + await opendiscord.events.get("afterTicketChannelDeleted").emit([ticket,user]) //delete permissions from manager await (await import("../data/framework/permissionLoader.js")).removeTicketPermissions(ticket) - await openticket.events.get("afterTicketDeleted").emit([ticket,user,reason]) + await opendiscord.events.get("afterTicketDeleted").emit([ticket,user,reason]) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params - openticket.log(user.displayName+" deleted a ticket!","info",[ + opendiscord.log(user.displayName+" deleted a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -107,7 +107,7 @@ export const registerActions = async () => { ]) }) ]) - openticket.actions.get("openticket:delete-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:delete-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false params.ticket.get("openticket:for-deletion").value = false @@ -116,37 +116,37 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //DELETE TICKET TICKET MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:delete-ticket-ticket-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:delete-ticket-ticket-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -154,84 +154,84 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket if (params.data == "reason"){ //delete with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:delete-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:delete-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //delete without reason await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true,withoutTranscript:(params.data == "no-transcript")}) + opendiscord.actions.get("openticket:delete-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true,withoutTranscript:(params.data == "no-transcript")}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable ticket.get("openticket:for-deletion").value = true - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - openticket.verifybars.get("openticket:delete-ticket-ticket-message").failure.add([ + opendiscord.verifybars.get("openticket:delete-ticket-ticket-message").failure.add([ new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //DELETE TICKET CLOSE MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-close-message",openticket.builders.messages.getSafe("openticket:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:delete-ticket-close-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-close-message",opendiscord.builders.messages.getSafe("openticket:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:delete-ticket-close-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -239,88 +239,88 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket if (params.data == "reason"){ //delete with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:delete-ticket-reason").build("close-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:delete-ticket-reason").build("close-message",{guild,channel,user,ticket})) }else{ //delete without reason await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) + opendiscord.actions.get("openticket:delete-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable ticket.get("openticket:for-deletion").value = true - await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("close-message",{guild,channel,user,ticket,reason:null})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("close-message",{guild,channel,user,ticket,reason:null})) } }) ]) - openticket.verifybars.get("openticket:delete-ticket-close-message").failure.add([ + opendiscord.verifybars.get("openticket:delete-ticket-close-message").failure.add([ new api.ODWorker("openticket:back-to-close-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await openticket.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) }) ]) //DELETE TICKET REOPEN MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-reopen-message",openticket.builders.messages.getSafe("openticket:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:delete-ticket-reopen-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-reopen-message",opendiscord.builders.messages.getSafe("openticket:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:delete-ticket-reopen-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -328,88 +328,88 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket if (params.data == "reason"){ //delete with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:delete-ticket-reason").build("reopen-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:delete-ticket-reason").build("reopen-message",{guild,channel,user,ticket})) }else{ //delete without reason await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) + opendiscord.actions.get("openticket:delete-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable ticket.get("openticket:for-deletion").value = true - await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("reopen-message",{guild,channel,user,ticket,reason:null})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("reopen-message",{guild,channel,user,ticket,reason:null})) } }) ]) - openticket.verifybars.get("openticket:delete-ticket-reopen-message").failure.add([ + opendiscord.verifybars.get("openticket:delete-ticket-reopen-message").failure.add([ new api.ODWorker("openticket:back-to-reopen-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) }) ]) //DELETE TICKET AUTOCLOSE MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-autoclose-message",openticket.builders.messages.getSafe("openticket:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:delete-ticket-autoclose-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-autoclose-message",opendiscord.builders.messages.getSafe("openticket:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:delete-ticket-autoclose-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -417,50 +417,50 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket if (params.data == "reason"){ //delete with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:delete-ticket-reason").build("autoclose-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:delete-ticket-reason").build("autoclose-message",{guild,channel,user,ticket})) }else{ //delete without reason await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) + opendiscord.actions.get("openticket:delete-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable ticket.get("openticket:for-deletion").value = true - await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("autoclose-message",{guild,channel,user,ticket,reason:null})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("autoclose-message",{guild,channel,user,ticket,reason:null})) } }) ]) - openticket.verifybars.get("openticket:delete-ticket-autoclose-message").failure.add([ + opendiscord.verifybars.get("openticket:delete-ticket-autoclose-message").failure.add([ new api.ODWorker("openticket:back-to-autoclose-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await openticket.builders.messages.getSafe("openticket:autoclose-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:autoclose-message").build("other",{guild,channel,user,ticket})) }) ]) } \ No newline at end of file diff --git a/src/actions/handleTranscriptErrors.ts b/src/actions/handleTranscriptErrors.ts index e15eae6..2249e81 100644 --- a/src/actions/handleTranscriptErrors.ts +++ b/src/actions/handleTranscriptErrors.ts @@ -1,43 +1,43 @@ /////////////////////////////////////// //TRANSCRIPT ERROR SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerButtonResponders = async () => { //TRANSCRIPT ERROR RETRY - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:transcript-error-retry",/^od:transcript-error-retry_([^_]+)/)) - openticket.responders.buttons.get("openticket:transcript-error-retry").workers.add([ + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:transcript-error-retry",/^od:transcript-error-retry_([^_]+)/)) + opendiscord.responders.buttons.get("openticket:transcript-error-retry").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -48,33 +48,33 @@ export const registerButtonResponders = async () => { if (originalSource != "slash" && originalSource != "text" && originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "other") return if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket (without reason) await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Retried)",sendMessage:false,withoutTranscript:false}) + opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Retried)",sendMessage:false,withoutTranscript:false}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable ticket.get("openticket:for-deletion").value = true - await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Retried)"})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Retried)"})) }), new api.ODWorker("openticket:logs",-1,async (instance,params,source,cancel) => { const {user,channel} = instance if (channel.isDMBased()) return - openticket.log(user.displayName+" retried deleting a ticket with transcript!","info",[ + opendiscord.log(user.displayName+" retried deleting a ticket with transcript!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -85,37 +85,37 @@ export const registerButtonResponders = async () => { ]) //TRANSCRIPT ERROR CONTINUE - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:transcript-error-continue",/^od:transcript-error-continue_([^_]+)/)) - openticket.responders.buttons.get("openticket:transcript-error-continue").workers.add([ + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:transcript-error-continue",/^od:transcript-error-continue_([^_]+)/)) + opendiscord.responders.buttons.get("openticket:transcript-error-continue").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -126,33 +126,33 @@ export const registerButtonResponders = async () => { if (originalSource != "slash" && originalSource != "text" && originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "other") return if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket (without reason) await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Continued)",sendMessage:false,withoutTranscript:true}) + opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Continued)",sendMessage:false,withoutTranscript:true}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable ticket.get("openticket:for-deletion").value = true - await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Continued)"})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Continued)"})) }), new api.ODWorker("openticket:logs",-1,async (instance,params,source,cancel) => { const {user,channel} = instance if (channel.isDMBased()) return - openticket.log(user.displayName+" continued deleting a ticket without transcript!","info",[ + opendiscord.log(user.displayName+" continued deleting a ticket without transcript!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, diff --git a/src/actions/handleVerifyBar.ts b/src/actions/handleVerifyBar.ts index 4154a4b..c222db7 100644 --- a/src/actions/handleVerifyBar.ts +++ b/src/actions/handleVerifyBar.ts @@ -1,30 +1,30 @@ /////////////////////////////////////// //VERIFYBAR SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" export const registerButtonResponders = async () => { //VERIFYBAR SUCCESS - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:verifybar-success",/^od:verifybar-success_([^_]+)/)) - openticket.responders.buttons.get("openticket:verifybar-success").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:verifybar-success",/^od:verifybar-success_([^_]+)/)) + opendiscord.responders.buttons.get("openticket:verifybar-success").workers.add( new api.ODWorker("openticket:handle-verifybar",0,async (instance,params,source,cancel) => { const id = instance.interaction.customId.split("_")[1] const customData = instance.interaction.customId.split("_")[2] as string|undefined - const verifybar = openticket.verifybars.get(id) + const verifybar = opendiscord.verifybars.get(id) if (!verifybar) return if (verifybar.success) await verifybar.success.executeWorkers(instance,"verifybar",{data:customData ?? null,verifybarMessage:instance.message}) }) ) //VERIFYBAR FAILURE - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:verifybar-failure",/^od:verifybar-failure_([^_]+)/)) - openticket.responders.buttons.get("openticket:verifybar-failure").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:verifybar-failure",/^od:verifybar-failure_([^_]+)/)) + opendiscord.responders.buttons.get("openticket:verifybar-failure").workers.add( new api.ODWorker("openticket:handle-verifybar",0,async (instance,params,source,cancel) => { const id = instance.interaction.customId.split("_")[1] const customData = instance.interaction.customId.split("_")[2] as string|undefined - const verifybar = openticket.verifybars.get(id) + const verifybar = opendiscord.verifybars.get(id) if (!verifybar) return if (verifybar.failure) await verifybar.failure.executeWorkers(instance,"verifybar",{data:customData ?? null,verifybarMessage:instance.message}) }) diff --git a/src/actions/moveTicket.ts b/src/actions/moveTicket.ts index 840cd26..da4cbcd 100644 --- a/src/actions/moveTicket.ts +++ b/src/actions/moveTicket.ts @@ -1,24 +1,24 @@ /////////////////////////////////////// //TICKET MOVING SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:move-ticket")) - openticket.actions.get("openticket:move-ticket").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:move-ticket")) + opendiscord.actions.get("openticket:move-ticket").workers.add([ new api.ODWorker("openticket:move-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params if (channel.isThread()) throw new api.ODSystemError("Unable to move ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketMove").emit([ticket,user,channel,reason]) + await opendiscord.events.get("onTicketMove").emit([ticket,user,channel,reason]) ticket.option = data //update stats - await openticket.stats.get("openticket:global").setStat("openticket:tickets-moved",1,"increase") - await openticket.stats.get("openticket:user").setStat("openticket:tickets-moved",user.id,1,"increase") + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-moved",1,"increase") + await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-moved",user.id,1,"increase") //get new channel properties const channelPrefix = ticket.option.get("openticket:channel-prefix").value @@ -44,10 +44,10 @@ export const registerActions = async () => { categoryMode = "closed" }else if (channelCategory != ""){ //category enabled - const normalCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelCategory) + const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory) if (!normalCategory){ //default category was not found - openticket.log("Ticket Move Error: Unable to find category! #1","error",[ + opendiscord.log("Ticket Move Error: Unable to find category! #1","error",[ {key:"categoryid",value:channelCategory}, {key:"backup",value:"false"} ]) @@ -55,10 +55,10 @@ export const registerActions = async () => { //default category was found if (normalCategory.children.cache.size >= 50 && channelBackupCategory != ""){ //use backup category - const backupCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelBackupCategory) + const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory) if (!backupCategory){ //default category was not found - openticket.log("Ticket Move Error: Unable to find category! #2","error",[ + opendiscord.log("Ticket Move Error: Unable to find category! #2","error",[ {key:"categoryid",value:channelBackupCategory}, {key:"backup",value:"true"} ]) @@ -77,17 +77,17 @@ export const registerActions = async () => { try { //only move category when not the same. if (channel.parentId != category) await utilities.timedAwait(channel.setParent(category,{lockPermissions:false}),2500,(err) => { - openticket.log("Failed to change channel category on ticket move","error") + opendiscord.log("Failed to change channel category on ticket move","error") }) ticket.get("openticket:category-mode").value = categoryMode ticket.get("openticket:category").value = category }catch(e){ - openticket.log("Unable to move ticket to 'moved category'!","error",[ + opendiscord.log("Unable to move ticket to 'moved category'!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"categoryid",value:category ?? "/"} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } //handle permissions @@ -97,7 +97,7 @@ export const registerActions = async () => { allow:[], deny:["ViewChannel","SendMessages","ReadMessageHistory"] }] - const globalAdmins = openticket.configs.get("openticket:general").data.globalAdmins + const globalAdmins = opendiscord.configs.get("openticket:general").data.globalAdmins const optionAdmins = ticket.option.get("openticket:admins").value const readonlyAdmins = ticket.option.get("openticket:admins-readonly").value @@ -140,7 +140,7 @@ export const registerActions = async () => { try{ await channel.permissionOverwrites.set(permissions) }catch{ - openticket.log("Failed to reset channel permissions on ticket move!","error") + opendiscord.log("Failed to reset channel permissions on ticket move!","error") } //handle participants @@ -158,53 +158,53 @@ export const registerActions = async () => { const originalName = channel.name try{ await utilities.timedAwait(channel.setName(channelName),2500,(err) => { - openticket.log("Failed to rename channel on ticket move","error") + opendiscord.log("Failed to rename channel on ticket move","error") }) }catch(err){ - await channel.send((await openticket.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-move",{guild,channel,user,originalName,newName:channelName})).message) + await channel.send((await opendiscord.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-move",{guild,channel,user,originalName,newName:channelName})).message) } try{ if (channel.type == discord.ChannelType.GuildText) channel.setTopic(channelDescription) }catch{} //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket renaming!","error",[ + opendiscord.log("Unable to edit ticket message on ticket renaming!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } //reply with new message - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:move-message").build(source,{guild,channel,user,ticket,reason,data})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:move-message").build(source,{guild,channel,user,ticket,reason,data})).message) ticket.get("openticket:busy").value = false - await openticket.events.get("afterTicketMoved").emit([ticket,user,channel,reason]) + await opendiscord.events.get("afterTicketMoved").emit([ticket,user,channel,reason]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.moving.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.moving.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.moving.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params - openticket.log(user.displayName+" moved a ticket!","info",[ + opendiscord.log(user.displayName+" moved a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -214,7 +214,7 @@ export const registerActions = async () => { ]) }) ]) - openticket.actions.get("openticket:move-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:move-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false }) diff --git a/src/actions/pinTicket.ts b/src/actions/pinTicket.ts index 8348215..dafc6fe 100644 --- a/src/actions/pinTicket.ts +++ b/src/actions/pinTicket.ts @@ -1,19 +1,19 @@ /////////////////////////////////////// //TICKET PINNING SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:pin-ticket")) - openticket.actions.get("openticket:pin-ticket").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:pin-ticket")) + opendiscord.actions.get("openticket:pin-ticket").workers.add([ new api.ODWorker("openticket:pin-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to pin ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketPin").emit([ticket,user,channel,reason]) + await opendiscord.events.get("onTicketPin").emit([ticket,user,channel,reason]) //update ticket ticket.get("openticket:pinned").value = true @@ -22,8 +22,8 @@ export const registerActions = async () => { ticket.get("openticket:busy").value = true //update stats - await openticket.stats.get("openticket:global").setStat("openticket:tickets-pinned",1,"increase") - await openticket.stats.get("openticket:user").setStat("openticket:tickets-pinned",user.id,1,"increase") + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-pinned",1,"increase") + await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-pinned",user.id,1,"increase") //move to top of category if (channel.parent){ @@ -35,50 +35,50 @@ export const registerActions = async () => { const newName = "📌"+channel.name try{ await utilities.timedAwait(channel.setName(newName),2500,(err) => { - openticket.log("Failed to rename channel on ticket pin","error") + opendiscord.log("Failed to rename channel on ticket pin","error") }) }catch(err){ - await channel.send((await openticket.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-pin",{guild,channel,user,originalName,newName})).message) + await channel.send((await opendiscord.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-pin",{guild,channel,user,originalName,newName})).message) } //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket pinning!","error",[ + opendiscord.log("Unable to edit ticket message on ticket pinning!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"message",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } //reply with new message - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:pin-message").build(source,{guild,channel,user,ticket,reason})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:pin-message").build(source,{guild,channel,user,ticket,reason})).message) ticket.get("openticket:busy").value = false - await openticket.events.get("afterTicketPinned").emit([ticket,user,channel,reason]) + await opendiscord.events.get("afterTicketPinned").emit([ticket,user,channel,reason]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.pinning.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.pinning.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params - openticket.log(user.displayName+" pinned a ticket!","info",[ + opendiscord.log(user.displayName+" pinned a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -92,37 +92,37 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //PIN TICKET TICKET MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:pin-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:pin-ticket-ticket-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:pin-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:pin-ticket-ticket-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.pin if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -130,86 +130,86 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already pinned if (ticket.get("openticket:pinned").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start pinning ticket if (params.data == "reason"){ //pin with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:pin-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:pin-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //pin without reason await instance.defer("update",false) - await openticket.actions.get("openticket:pin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:pin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - openticket.verifybars.get("openticket:pin-ticket-ticket-message").failure.add([ + opendiscord.verifybars.get("openticket:pin-ticket-ticket-message").failure.add([ new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //PIN TICKET UNPIN MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:pin-ticket-unpin-message",openticket.builders.messages.getSafe("openticket:verifybar-unpin-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:pin-ticket-unpin-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:pin-ticket-unpin-message",opendiscord.builders.messages.getSafe("openticket:verifybar-unpin-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:pin-ticket-unpin-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.pin if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -217,58 +217,58 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already pinned if (ticket.get("openticket:pinned").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start pinning ticket if (params.data == "reason"){ //pin with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:pin-ticket-reason").build("unpin-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:pin-ticket-reason").build("unpin-message",{guild,channel,user,ticket})) }else{ //pin without reason await instance.defer("update",false) - await openticket.actions.get("openticket:pin-ticket").run("unpin-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:pin-message").build("unpin-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("openticket:pin-ticket").run("unpin-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:pin-message").build("unpin-message",{guild,channel,user,ticket,reason:null})) } }) ]) - openticket.verifybars.get("openticket:pin-ticket-unpin-message").failure.add([ + opendiscord.verifybars.get("openticket:pin-ticket-unpin-message").failure.add([ new api.ODWorker("openticket:back-to-unpin-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await openticket.builders.messages.getSafe("openticket:unpin-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:unpin-message").build("other",{guild,channel,user,ticket,reason})) }) ]) - openticket.actions.get("openticket:pin-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:pin-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false }) diff --git a/src/actions/reactionRole.ts b/src/actions/reactionRole.ts index 65148ce..2400c85 100644 --- a/src/actions/reactionRole.ts +++ b/src/actions/reactionRole.ts @@ -1,32 +1,32 @@ /////////////////////////////////////// //REACTION ROLE SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:reaction-role")) - openticket.actions.get("openticket:reaction-role").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:reaction-role")) + opendiscord.actions.get("openticket:reaction-role").workers.add([ new api.ODWorker("openticket:reaction-role",2,async (instance,params,source,cancel) => { const {guild,user,option,overwriteMode} = params - const role = openticket.roles.get(option.id) + const role = opendiscord.roles.get(option.id) if (!role) throw new api.ODSystemError("ODAction(ot:reaction-role) => Unknown reaction role (ODRole)") instance.role = role const mode = (overwriteMode) ? overwriteMode : role.get("openticket:mode").value - await openticket.events.get("onRoleUpdate").emit([user,role]) + await opendiscord.events.get("onRoleUpdate").emit([user,role]) //get guild member - const member = await openticket.client.fetchGuildMember(guild,user.id) + const member = await opendiscord.client.fetchGuildMember(guild,user.id) if (!member) throw new api.ODSystemError("ODAction(ot:reaction-role) => User isn't a member of the server!") //get all roles const roleIds = role.get("openticket:roles").value const roles: discord.Role[] = [] for (const id of roleIds){ - const r = await openticket.client.fetchGuildRole(guild,id) + const r = await opendiscord.client.fetchGuildRole(guild,id) if (r) roles.push(r) - else openticket.log("Unable to find role in server!","warning",[ + else opendiscord.log("Unable to find role in server!","warning",[ {key:"roleid",value:id} ]) } @@ -58,9 +58,9 @@ export const registerActions = async () => { const removeRoleIds = role.get("openticket:remove-roles-on-add").value const removeRoles: discord.Role[] = [] for (const id of removeRoleIds){ - const r = await openticket.client.fetchGuildRole(guild,id) + const r = await opendiscord.client.fetchGuildRole(guild,id) if (r) removeRoles.push(r) - else openticket.log("Unable to find role in server!","warning",[ + else opendiscord.log("Unable to find role in server!","warning",[ {key:"roleid",value:id} ]) } @@ -79,11 +79,11 @@ export const registerActions = async () => { //update instance & finish event instance.result = result - await openticket.events.get("afterRolesUpdated").emit([user,role]) + await opendiscord.events.get("afterRolesUpdated").emit([user,role]) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,user,option} = params - openticket.log(user.displayName+" updated his roles!","info",[ + opendiscord.log(user.displayName+" updated his roles!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"method",value:source}, diff --git a/src/actions/removeTicketUser.ts b/src/actions/removeTicketUser.ts index d72f7b7..d7908d1 100644 --- a/src/actions/removeTicketUser.ts +++ b/src/actions/removeTicketUser.ts @@ -1,19 +1,19 @@ /////////////////////////////////////// //TICKET REMOVE USER SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:remove-ticket-user")) - openticket.actions.get("openticket:remove-ticket-user").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:remove-ticket-user")) + opendiscord.actions.get("openticket:remove-ticket-user").workers.add([ new api.ODWorker("openticket:remove-ticket-user",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params if (channel.isThread()) throw new api.ODSystemError("Unable to remove user from ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketUserRemove").emit([ticket,user,data,channel,reason]) + await opendiscord.events.get("onTicketUserRemove").emit([ticket,user,data,channel,reason]) //update ticket const index = ticket.get("openticket:participants").value.findIndex((p) => p.type == "user" && p.id == data.id) @@ -26,46 +26,46 @@ export const registerActions = async () => { try{ await channel.permissionOverwrites.delete(data) }catch{ - openticket.log("Failed to remove channel permission overwrites on remove-ticket-user","error") + opendiscord.log("Failed to remove channel permission overwrites on remove-ticket-user","error") } //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket user removal!","error",[ + opendiscord.log("Unable to edit ticket message on ticket user removal!","error",[ {key:"channel",value:channel.id}, {key:"message",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } //reply with new message - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:remove-message").build(source,{guild,channel,user,ticket,reason,data})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:remove-message").build(source,{guild,channel,user,ticket,reason,data})).message) ticket.get("openticket:busy").value = false - await openticket.events.get("afterTicketUserRemoved").emit([ticket,user,data,channel,reason]) + await opendiscord.events.get("afterTicketUserRemoved").emit([ticket,user,data,channel,reason]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.removing.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.removing.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.removing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket,data} = params - openticket.log(user.displayName+" removed "+data.displayName+" from a ticket!","info",[ + opendiscord.log(user.displayName+" removed "+data.displayName+" from a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -75,7 +75,7 @@ export const registerActions = async () => { ]) }) ]) - openticket.actions.get("openticket:remove-ticket-user").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:remove-ticket-user").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false }) diff --git a/src/actions/renameTicket.ts b/src/actions/renameTicket.ts index ba294b8..331ad32 100644 --- a/src/actions/renameTicket.ts +++ b/src/actions/renameTicket.ts @@ -1,68 +1,68 @@ /////////////////////////////////////// //TICKET RENAMING SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:rename-ticket")) - openticket.actions.get("openticket:rename-ticket").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:rename-ticket")) + opendiscord.actions.get("openticket:rename-ticket").workers.add([ new api.ODWorker("openticket:rename-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params if (channel.isThread()) throw new api.ODSystemError("Unable to rename ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketRename").emit([ticket,user,channel,reason]) + await opendiscord.events.get("onTicketRename").emit([ticket,user,channel,reason]) //rename channel (and give error when crashed) const originalName = channel.name try{ await utilities.timedAwait(channel.setName(data),2500,(err) => { - openticket.log("Failed to rename channel on ticket rename","error") + opendiscord.log("Failed to rename channel on ticket rename","error") }) }catch(err){ - await channel.send((await openticket.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-rename",{guild,channel,user,originalName,newName:data})).message) + await channel.send((await opendiscord.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-rename",{guild,channel,user,originalName,newName:data})).message) } //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket renaming!","error",[ + opendiscord.log("Unable to edit ticket message on ticket renaming!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } //reply with new message - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:rename-message").build(source,{guild,channel,user,ticket,reason,data})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:rename-message").build(source,{guild,channel,user,ticket,reason,data})).message) ticket.get("openticket:busy").value = false - await openticket.events.get("afterTicketRenamed").emit([ticket,user,channel,reason]) + await opendiscord.events.get("afterTicketRenamed").emit([ticket,user,channel,reason]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.renaming.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.renaming.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.renaming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params - openticket.log(user.displayName+" renamed a ticket!","info",[ + opendiscord.log(user.displayName+" renamed a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -72,7 +72,7 @@ export const registerActions = async () => { ]) }) ]) - openticket.actions.get("openticket:rename-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:rename-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false }) diff --git a/src/actions/reopenTicket.ts b/src/actions/reopenTicket.ts index 1893b1f..bf7dc70 100644 --- a/src/actions/reopenTicket.ts +++ b/src/actions/reopenTicket.ts @@ -1,19 +1,19 @@ /////////////////////////////////////// //TICKET REOPENING SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:reopen-ticket")) - openticket.actions.get("openticket:reopen-ticket").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:reopen-ticket")) + opendiscord.actions.get("openticket:reopen-ticket").workers.add([ new api.ODWorker("openticket:reopen-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to reopen ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketReopen").emit([ticket,user,channel,reason]) + await opendiscord.events.get("onTicketReopen").emit([ticket,user,channel,reason]) //update ticket ticket.get("openticket:closed").value = false @@ -24,8 +24,8 @@ export const registerActions = async () => { ticket.get("openticket:busy").value = true //update stats - await openticket.stats.get("openticket:global").setStat("openticket:tickets-reopened",1,"increase") - await openticket.stats.get("openticket:user").setStat("openticket:tickets-reopened",user.id,1,"increase") + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-reopened",1,"increase") + await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-reopened",user.id,1,"increase") //update category const channelCategory = ticket.option.get("openticket:channel-category").value @@ -33,10 +33,10 @@ export const registerActions = async () => { if (channelCategory !== ""){ //category enabled try { - const normalCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelCategory) + const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory) if (!normalCategory){ //default category was not found - openticket.log("Ticket Reopening Error: Unable to find category! #1","error",[ + opendiscord.log("Ticket Reopening Error: Unable to find category! #1","error",[ {key:"categoryid",value:channelCategory}, {key:"backup",value:"false"} ]) @@ -44,10 +44,10 @@ export const registerActions = async () => { //default category was found if (normalCategory.children.cache.size >= 49 && channelBackupCategory != ""){ //use backup category - const backupCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelBackupCategory) + const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory) if (!backupCategory){ //default category was not found - openticket.log("Ticket Reopening Error: Unable to find category! #2","error",[ + opendiscord.log("Ticket Reopening Error: Unable to find category! #2","error",[ {key:"categoryid",value:channelBackupCategory}, {key:"backup",value:"true"} ]) @@ -65,11 +65,11 @@ export const registerActions = async () => { } } }catch(e){ - openticket.log("Unable to move ticket to 'reopened category'!","error",[ + opendiscord.log("Unable to move ticket to 'reopened category'!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } }else{ channel.setParent(null,{lockPermissions:false}) @@ -84,7 +84,7 @@ export const registerActions = async () => { allow:[], deny:["ViewChannel","SendMessages","ReadMessageHistory"] }] - const globalAdmins = openticket.configs.get("openticket:general").data.globalAdmins + const globalAdmins = opendiscord.configs.get("openticket:general").data.globalAdmins const optionAdmins = ticket.option.get("openticket:admins").value const readonlyAdmins = ticket.option.get("openticket:admins-readonly").value @@ -129,42 +129,42 @@ export const registerActions = async () => { channel.permissionOverwrites.set(permissions) //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket reopening!","error",[ + opendiscord.log("Unable to edit ticket message on ticket reopening!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:reopen-message").build(source,{guild,channel,user,ticket,reason})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:reopen-message").build(source,{guild,channel,user,ticket,reason})).message) ticket.get("openticket:busy").value = false - await openticket.events.get("afterTicketReopened").emit([ticket,user,channel,reason]) + await opendiscord.events.get("afterTicketReopened").emit([ticket,user,channel,reason]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.reopening.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.reopening.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.reopening.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params - openticket.log(user.displayName+" reopened a ticket!","info",[ + opendiscord.log(user.displayName+" reopened a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -178,37 +178,37 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //REOPEN TICKET TICKET MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:reopen-ticket-ticket-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:reopen-ticket-ticket-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.reopen if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -216,86 +216,86 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not closed if (!ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start reopening ticket if (params.data == "reason"){ //reopen with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:reopen-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:reopen-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //reopen without reason await instance.defer("update",false) - await openticket.actions.get("openticket:reopen-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:reopen-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - openticket.verifybars.get("openticket:reopen-ticket-ticket-message").failure.add([ + opendiscord.verifybars.get("openticket:reopen-ticket-ticket-message").failure.add([ new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //REOPEN TICKET CLOSE MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-close-message",openticket.builders.messages.getSafe("openticket:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:reopen-ticket-close-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-close-message",opendiscord.builders.messages.getSafe("openticket:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:reopen-ticket-close-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.reopen if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -303,90 +303,90 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not closed if (!ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start reopening ticket if (params.data == "reason"){ //reopen with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:reopen-ticket-reason").build("close-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:reopen-ticket-reason").build("close-message",{guild,channel,user,ticket})) }else{ //reopen without reason await instance.defer("update",false) - await openticket.actions.get("openticket:reopen-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("close-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("openticket:reopen-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("close-message",{guild,channel,user,ticket,reason:null})) } }) ]) - openticket.verifybars.get("openticket:reopen-ticket-close-message").failure.add([ + opendiscord.verifybars.get("openticket:reopen-ticket-close-message").failure.add([ new api.ODWorker("openticket:back-to-close-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await openticket.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) }) ]) //REOPEN TICKET AUTOCLOSE MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-autoclose-message",openticket.builders.messages.getSafe("openticket:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:reopen-ticket-autoclose-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-autoclose-message",opendiscord.builders.messages.getSafe("openticket:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:reopen-ticket-autoclose-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.reopen if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -394,55 +394,55 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not closed if (!ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start reopening ticket if (params.data == "reason"){ //reopen with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:reopen-ticket-reason").build("autoclose-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:reopen-ticket-reason").build("autoclose-message",{guild,channel,user,ticket})) }else{ //reopen without reason await instance.defer("update",false) - await openticket.actions.get("openticket:reopen-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("autoclose-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("openticket:reopen-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("autoclose-message",{guild,channel,user,ticket,reason:null})) } }) ]) - openticket.verifybars.get("openticket:reopen-ticket-autoclose-message").failure.add([ + opendiscord.verifybars.get("openticket:reopen-ticket-autoclose-message").failure.add([ new api.ODWorker("openticket:back-to-autoclose-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await openticket.builders.messages.getSafe("openticket:autoclose-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:autoclose-message").build("other",{guild,channel,user,ticket})) }) ]) - openticket.actions.get("openticket:reopen-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:reopen-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false }) diff --git a/src/actions/unclaimTicket.ts b/src/actions/unclaimTicket.ts index 1841453..9186427 100644 --- a/src/actions/unclaimTicket.ts +++ b/src/actions/unclaimTicket.ts @@ -1,19 +1,19 @@ /////////////////////////////////////// //TICKET UNCLAIMING SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:unclaim-ticket")) - openticket.actions.get("openticket:unclaim-ticket").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:unclaim-ticket")) + opendiscord.actions.get("openticket:unclaim-ticket").workers.add([ new api.ODWorker("openticket:unclaim-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to unclaim ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketUnclaim").emit([ticket,user,channel,reason]) + await opendiscord.events.get("onTicketUnclaim").emit([ticket,user,channel,reason]) //update ticket ticket.get("openticket:claimed").value = false @@ -27,10 +27,10 @@ export const registerActions = async () => { if (channelCategory !== ""){ //category enabled try { - const normalCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelCategory) + const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory) if (!normalCategory){ //default category was not found - openticket.log("Ticket Unclaiming Error: Unable to find category! #1","error",[ + opendiscord.log("Ticket Unclaiming Error: Unable to find category! #1","error",[ {key:"categoryid",value:channelCategory}, {key:"backup",value:"false"} ]) @@ -38,10 +38,10 @@ export const registerActions = async () => { //default category was found if (normalCategory.children.cache.size >= 49 && channelBackupCategory != ""){ //use backup category - const backupCategory = await openticket.client.fetchGuildCategoryChannel(guild,channelBackupCategory) + const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory) if (!backupCategory){ //default category was not found - openticket.log("Ticket Unclaiming Error: Unable to find category! #2","error",[ + opendiscord.log("Ticket Unclaiming Error: Unable to find category! #2","error",[ {key:"categoryid",value:channelBackupCategory}, {key:"backup",value:"true"} ]) @@ -60,11 +60,11 @@ export const registerActions = async () => { } }catch(e){ - openticket.log("Unable to move ticket to 'unclaimed category'!","error",[ + opendiscord.log("Unable to move ticket to 'unclaimed category'!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } }else{ channel.setParent(null,{lockPermissions:false}) @@ -73,43 +73,43 @@ export const registerActions = async () => { } //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket unclaiming!","error",[ + opendiscord.log("Unable to edit ticket message on ticket unclaiming!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } //reply with new message - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:unclaim-message").build(source,{guild,channel,user,ticket,reason})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:unclaim-message").build(source,{guild,channel,user,ticket,reason})).message) ticket.get("openticket:busy").value = false - await openticket.events.get("afterTicketUnclaimed").emit([ticket,user,channel,reason]) + await opendiscord.events.get("afterTicketUnclaimed").emit([ticket,user,channel,reason]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.claiming.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.claiming.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params - openticket.log(user.displayName+" unclaimed a ticket!","info",[ + opendiscord.log(user.displayName+" unclaimed a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -123,37 +123,37 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //UNCLAIM TICKET TICKET MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:unclaim-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:unclaim-ticket-ticket-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:unclaim-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:unclaim-ticket-ticket-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unclaim if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -161,86 +161,86 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not claimed if (!ticket.get("openticket:claimed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start unclaiming ticket if (params.data == "reason"){ //unclaim with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:unclaim-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:unclaim-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //unclaim without reason await instance.defer("update",false) - await openticket.actions.get("openticket:unclaim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:unclaim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - openticket.verifybars.get("openticket:unclaim-ticket-ticket-message").failure.add([ + opendiscord.verifybars.get("openticket:unclaim-ticket-ticket-message").failure.add([ new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //UNCLAIM TICKET CLAIM MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:unclaim-ticket-claim-message",openticket.builders.messages.getSafe("openticket:verifybar-claim-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:unclaim-ticket-claim-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:unclaim-ticket-claim-message",opendiscord.builders.messages.getSafe("openticket:verifybar-claim-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:unclaim-ticket-claim-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unclaim if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -248,58 +248,58 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not claimed if (!ticket.get("openticket:claimed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start unclaiming ticket if (params.data == "reason"){ //unclaim with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:unclaim-ticket-reason").build("claim-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:unclaim-ticket-reason").build("claim-message",{guild,channel,user,ticket})) }else{ //unclaim without reason await instance.defer("update",false) - await openticket.actions.get("openticket:unclaim-ticket").run("claim-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:unclaim-message").build("claim-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("openticket:unclaim-ticket").run("claim-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:unclaim-message").build("claim-message",{guild,channel,user,ticket,reason:null})) } }) ]) - openticket.verifybars.get("openticket:unclaim-ticket-claim-message").failure.add([ + opendiscord.verifybars.get("openticket:unclaim-ticket-claim-message").failure.add([ new api.ODWorker("openticket:back-to-claim-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await openticket.builders.messages.getSafe("openticket:claim-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:claim-message").build("other",{guild,channel,user,ticket,reason})) }) ]) - openticket.actions.get("openticket:unclaim-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:unclaim-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false }) diff --git a/src/actions/unpinTicket.ts b/src/actions/unpinTicket.ts index c5baab5..47c3793 100644 --- a/src/actions/unpinTicket.ts +++ b/src/actions/unpinTicket.ts @@ -1,19 +1,19 @@ /////////////////////////////////////// //TICKET UNPINNING SYSTEM /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerActions = async () => { - openticket.actions.add(new api.ODAction("openticket:unpin-ticket")) - openticket.actions.get("openticket:unpin-ticket").workers.add([ + opendiscord.actions.add(new api.ODAction("openticket:unpin-ticket")) + opendiscord.actions.get("openticket:unpin-ticket").workers.add([ new api.ODWorker("openticket:unpin-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to unpin ticket! Open Ticket doesn't support threads!") - await openticket.events.get("onTicketUnpin").emit([ticket,user,channel,reason]) + await opendiscord.events.get("onTicketUnpin").emit([ticket,user,channel,reason]) //update ticket ticket.get("openticket:pinned").value = false @@ -27,51 +27,51 @@ export const registerActions = async () => { const newName = originalName.replace("📌",""); try{ await utilities.timedAwait(channel.setName(newName),2500,(err) => { - openticket.log("Failed to rename channel on ticket unpin","error") + opendiscord.log("Failed to rename channel on ticket unpin","error") }) }catch(err){ - await channel.send((await openticket.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-unpin",{guild,channel,user,originalName,newName})).message) + await channel.send((await opendiscord.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-unpin",{guild,channel,user,originalName,newName})).message) } } //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on ticket unpinning!","error",[ + opendiscord.log("Unable to edit ticket message on ticket unpinning!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } //reply with new message - if (params.sendMessage) await channel.send((await openticket.builders.messages.getSafe("openticket:unpin-message").build(source,{guild,channel,user,ticket,reason})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:unpin-message").build(source,{guild,channel,user,ticket,reason})).message) ticket.get("openticket:busy").value = false - await openticket.events.get("afterTicketUnpinned").emit([ticket,user,channel,reason]) + await opendiscord.events.get("afterTicketUnpinned").emit([ticket,user,channel,reason]) }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.pinning.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) } //to dm - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.pinning.dm) await openticket.client.sendUserDm(creator,await openticket.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + if (creator && generalConfig.data.system.messages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) }), new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params - openticket.log(user.displayName+" unpinned a ticket!","info",[ + opendiscord.log(user.displayName+" unpinned a ticket!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channel",value:"#"+channel.name}, @@ -85,37 +85,37 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //UNPIN TICKET TICKET MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:unpin-ticket-ticket-message",openticket.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:unpin-ticket-ticket-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:unpin-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:unpin-ticket-ticket-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unpin if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -123,86 +123,86 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not pinned if (!ticket.get("openticket:pinned").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start unpining ticket if (params.data == "reason"){ //unpin with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:unpin-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:unpin-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //unpin without reason await instance.defer("update",false) - await openticket.actions.get("openticket:unpin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:unpin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - openticket.verifybars.get("openticket:unpin-ticket-ticket-message").failure.add([ + opendiscord.verifybars.get("openticket:unpin-ticket-ticket-message").failure.add([ new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //UNPIN TICKET PIN MESSAGE - openticket.verifybars.add(new api.ODVerifyBar("openticket:unpin-ticket-pin-message",openticket.builders.messages.getSafe("openticket:verifybar-pin-message"),!generalConfig.data.system.disableVerifyBars)) - openticket.verifybars.get("openticket:unpin-ticket-pin-message").success.add([ + opendiscord.verifybars.add(new api.ODVerifyBar("openticket:unpin-ticket-pin-message",opendiscord.builders.messages.getSafe("openticket:verifybar-pin-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("openticket:unpin-ticket-pin-message").success.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unpin if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -210,58 +210,58 @@ export const registerVerifyBars = async () => { new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not pinned if (!ticket.get("openticket:pinned").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start unpinning ticket if (params.data == "reason"){ //unpin with reason - instance.modal(await openticket.builders.modals.getSafe("openticket:unpin-ticket-reason").build("pin-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:unpin-ticket-reason").build("pin-message",{guild,channel,user,ticket})) }else{ //unpin without reason await instance.defer("update",false) - await openticket.actions.get("openticket:unpin-ticket").run("pin-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:unpin-message").build("pin-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("openticket:unpin-ticket").run("pin-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:unpin-message").build("pin-message",{guild,channel,user,ticket,reason:null})) } }) ]) - openticket.verifybars.get("openticket:unpin-ticket-pin-message").failure.add([ + opendiscord.verifybars.get("openticket:unpin-ticket-pin-message").failure.add([ new api.ODWorker("openticket:back-to-pin-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await openticket.builders.messages.getSafe("openticket:pin-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:pin-message").build("other",{guild,channel,user,ticket,reason})) }) ]) - openticket.actions.get("openticket:unpin-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("openticket:unpin-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel params.ticket.get("openticket:busy").value = false }) diff --git a/src/builders/buttons.ts b/src/builders/buttons.ts index 78f088e..b4ee648 100644 --- a/src/builders/buttons.ts +++ b/src/builders/buttons.ts @@ -1,12 +1,12 @@ /////////////////////////////////////// //BUTTON BUILDERS /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const buttons = openticket.builders.buttons -const lang = openticket.languages -const generalConfig = openticket.configs.get("openticket:general") +const buttons = opendiscord.builders.buttons +const lang = opendiscord.languages +const generalConfig = opendiscord.configs.get("openticket:general") export const registerAllButtons = async () => { verifybarButtons() @@ -83,7 +83,7 @@ const helpMenuButtons = () => { buttons.get("openticket:help-menu-page").workers.add( new api.ODWorker("openticket:help-menu-page",0,async (instance,params) => { const {mode,page} = params - const totalPages = (await openticket.helpmenu.render(mode)).length + const totalPages = (await opendiscord.helpmenu.render(mode)).length const pageText = (page+1).toString()+"/"+totalPages.toString() instance.setCustomId("od:help-menu-page_"+page.toString()) @@ -127,7 +127,7 @@ const helpMenuButtons = () => { buttons.get("openticket:help-menu-next").workers.add( new api.ODWorker("openticket:help-menu-next",0,async (instance,params) => { const {mode,page} = params - const totalPages = (await openticket.helpmenu.render(mode)).length + const totalPages = (await opendiscord.helpmenu.render(mode)).length instance.setCustomId("od:help-menu-next") instance.setMode("button") diff --git a/src/builders/dropdowns.ts b/src/builders/dropdowns.ts index 15f70fa..76c94d8 100644 --- a/src/builders/dropdowns.ts +++ b/src/builders/dropdowns.ts @@ -1,10 +1,10 @@ /////////////////////////////////////// //DROPDOWN BUILDERS /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const dropdowns = openticket.builders.dropdowns +const dropdowns = opendiscord.builders.dropdowns export const registerAllDropdowns = async () => { panelDropdowns() diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts index f8e9c47..4e9ea38 100644 --- a/src/builders/embeds.ts +++ b/src/builders/embeds.ts @@ -1,13 +1,13 @@ /////////////////////////////////////// //EMBED BUILDERS /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" import nodepath from "path" -const embeds = openticket.builders.embeds -const lang = openticket.languages -const generalConfig = openticket.configs.get("openticket:general") +const embeds = opendiscord.builders.embeds +const lang = opendiscord.languages +const generalConfig = opendiscord.configs.get("openticket:general") export const registerAllEmbeds = async () => { errorEmbeds() @@ -274,7 +274,7 @@ const errorEmbeds = () => { new api.ODWorker("openticket:error-option-unknown",0,async (instance,params,source) => { const {user} = params - const renderedTicketOptions = openticket.options.getAll().map((option) => { + const renderedTicketOptions = opendiscord.options.getAll().map((option) => { if (option instanceof api.ODTicketOption && option.exists("openticket:name")){ return "- **"+option.get("openticket:name").value+":** `"+option.id.value+"`" }else return "- `"+option.id.value+"`" @@ -294,7 +294,7 @@ const errorEmbeds = () => { new api.ODWorker("openticket:error-panel-unknown",0,async (instance,params,source) => { const {user} = params - const renderedPanels = openticket.panels.getAll().map((panel) => { + const renderedPanels = opendiscord.panels.getAll().map((panel) => { if (panel.exists("openticket:name")){ return "- **"+panel.get("openticket:name").value+":** `"+panel.id.value+"`" }else return "- `"+panel.id.value+"`" @@ -370,9 +370,9 @@ const helpMenuEmbeds = () => { instance.setColor(generalConfig.data.mainColor) instance.setTitle(utilities.emojiTitle("ℹ️",lang.getTranslation("actions.titles.help"))) instance.setDescription(lang.getTranslation("actions.descriptions.helpExplanation")) - instance.setThumbnail(openticket.client.client.user.displayAvatarURL()) + instance.setThumbnail(opendiscord.client.client.user.displayAvatarURL()) - const data = await openticket.helpmenu.render(mode) + const data = await opendiscord.helpmenu.render(mode) const currentData = data[page] ?? [] instance.setFields(currentData) }) @@ -386,7 +386,7 @@ const statsEmbeds = () => { new api.ODWorker("openticket:stats-global",0,async (instance,params) => { const {guild,channel,user} = params - const scope = openticket.stats.get("openticket:global") + const scope = opendiscord.stats.get("openticket:global") if (!scope) return const data = await scope.render("GLOBAL",guild,channel,user) @@ -394,9 +394,9 @@ const statsEmbeds = () => { instance.setTitle(scope.name) instance.setDescription(data) - if (openticket.permissions.hasPermissions("owner",await openticket.permissions.getPermissions(user,channel,guild))){ + if (opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(user,channel,guild))){ //show system data when owner or developer - const systemScope = openticket.stats.get("openticket:system") + const systemScope = opendiscord.stats.get("openticket:system") if (!systemScope) return const systemData = await systemScope.render("GLOBAL",guild,channel,user) instance.addFields({name:systemScope.name,value:systemData,inline:false}) @@ -410,8 +410,8 @@ const statsEmbeds = () => { new api.ODWorker("openticket:stats-ticket",0,async (instance,params) => { const {guild,channel,user,scopeData} = params - const scope = openticket.stats.get("openticket:ticket") - const participantsScope = openticket.stats.get("openticket:participants") + const scope = opendiscord.stats.get("openticket:ticket") + const participantsScope = opendiscord.stats.get("openticket:participants") if (!scope || !participantsScope) return const data = await scope.render(scopeData.id.value,guild,channel,user) const participantsData = await participantsScope.render(scopeData.id.value,guild,channel,user) @@ -429,7 +429,7 @@ const statsEmbeds = () => { new api.ODWorker("openticket:stats-user",0,async (instance,params) => { const {guild,channel,user,scopeData} = params - const scope = openticket.stats.get("openticket:user") + const scope = opendiscord.stats.get("openticket:user") if (!scope) return const data = await scope.render(scopeData.id,guild,channel,user) @@ -439,8 +439,8 @@ const statsEmbeds = () => { instance.setThumbnail(scopeData.displayAvatarURL()) }), new api.ODWorker("openticket:easter-egg",-1,async (instance,params) => { - if (!openticket.flags.exists("openticket:no-easter")) return - const easterFlag = openticket.flags.get("openticket:no-easter") + if (!opendiscord.flags.exists("openticket:no-easter")) return + const easterFlag = opendiscord.flags.get("openticket:no-easter") if (!easterFlag.value){ //🥚 add easter egg 🥚 const {user} = params @@ -563,7 +563,7 @@ const ticketEmbeds = () => { const {user,ticket} = params const method = (source == "panel-button" || source == "panel-dropdown") ? lang.getTranslation("params.uppercase.panel") : (source == "slash" || source == "text") ? lang.getTranslation("params.uppercase.command") : lang.getTranslation("params.uppercase.system") - const blacklisted = openticket.blacklist.exists(user.id) ? lang.getTranslation("params.uppercase.true") : lang.getTranslation("params.uppercase.false") + const blacklisted = opendiscord.blacklist.exists(user.id) ? lang.getTranslation("params.uppercase.true") : lang.getTranslation("params.uppercase.false") instance.setColor(generalConfig.data.mainColor) instance.setTitle(utilities.emojiTitle("🎫",lang.getTranslation("actions.titles.created"))) @@ -608,7 +608,7 @@ const ticketEmbeds = () => { else if (!ticket.get("openticket:closed").value && ticket.get("openticket:autoclose-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutoclose",[ticket.option.get("openticket:autoclose-hours").value.toString()])) if (ticket.get("openticket:claimed").value){ - const claimUser = await openticket.tickets.getTicketUser(ticket,"claimer") + const claimUser = await opendiscord.tickets.getTicketUser(ticket,"claimer") if (!claimUser) return instance.setAuthor(lang.getTranslationWithParams("params.uppercase.claimedBy",[claimUser.displayName]),claimUser.displayAvatarURL()) } @@ -774,7 +774,7 @@ const ticketEmbeds = () => { embeds.get("openticket:ticket-action-dm").workers.add( new api.ODWorker("openticket:ticket-action-dm",0,async (instance,params,source) => { const {user,mode,ticket,reason,additionalData} = params - const channel = await openticket.tickets.getTicketChannel(ticket) + const channel = await opendiscord.tickets.getTicketChannel(ticket) instance.setColor(generalConfig.data.mainColor) instance.setTimestamp(new Date()) @@ -823,7 +823,7 @@ const ticketEmbeds = () => { embeds.get("openticket:ticket-action-logs").workers.add( new api.ODWorker("openticket:ticket-action-logs",0,async (instance,params,source) => { const {user,mode,ticket,reason,additionalData} = params - const channel = await openticket.tickets.getTicketChannel(ticket) + const channel = await opendiscord.tickets.getTicketChannel(ticket) instance.setColor(generalConfig.data.mainColor) instance.setThumbnail(user.displayAvatarURL()) @@ -882,7 +882,7 @@ const blacklistEmbeds = () => { const {user} = params const renderedUsers: string[] = [] - await openticket.blacklist.loopAll((blacklist,id) => {renderedUsers.push(discord.userMention(id.value)+" - "+(blacklist.reason ? blacklist.reason : "/"))}) + await opendiscord.blacklist.loopAll((blacklist,id) => {renderedUsers.push(discord.userMention(id.value)+" - "+(blacklist.reason ? blacklist.reason : "/"))}) instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setColor(generalConfig.data.mainColor) @@ -900,7 +900,7 @@ const blacklistEmbeds = () => { embeds.get("openticket:blacklist-get").workers.add( new api.ODWorker("openticket:blacklist-get",0,async (instance,params,source) => { const {user,data} = params - const blacklist = openticket.blacklist.get(data.id) + const blacklist = opendiscord.blacklist.get(data.id) instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setColor(generalConfig.data.mainColor) @@ -985,7 +985,7 @@ const transcriptEmbeds = () => { embeds.get("openticket:transcript-text-ready").workers.add( new api.ODWorker("openticket:transcript-text-ready",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler} = params - const transcriptConfig = openticket.configs.get("openticket:transcripts") + const transcriptConfig = opendiscord.configs.get("openticket:transcripts") instance.setColor(transcriptConfig.data.embedSettings.customColor ? transcriptConfig.data.embedSettings.customColor : generalConfig.data.mainColor) instance.setTitle(utilities.emojiTitle("📄",lang.getTranslation("transcripts.success.ready"))) @@ -1015,7 +1015,7 @@ const transcriptEmbeds = () => { embeds.get("openticket:transcript-html-ready").workers.add( new api.ODWorker("openticket:transcript-html-ready",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler,result} = params - const transcriptConfig = openticket.configs.get("openticket:transcripts") + const transcriptConfig = opendiscord.configs.get("openticket:transcripts") instance.setColor(transcriptConfig.data.embedSettings.customColor ? transcriptConfig.data.embedSettings.customColor : generalConfig.data.mainColor) instance.setTitle(utilities.emojiTitle("📄",lang.getTranslation("transcripts.success.ready"))) diff --git a/src/builders/files.ts b/src/builders/files.ts index ae00fca..c23daa0 100644 --- a/src/builders/files.ts +++ b/src/builders/files.ts @@ -1,12 +1,12 @@ /////////////////////////////////////// //FILE BUILDERS /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const files = openticket.builders.files -const lang = openticket.languages -const transcriptConfig = openticket.configs.get("openticket:transcripts") +const files = opendiscord.builders.files +const lang = opendiscord.languages +const transcriptConfig = opendiscord.configs.get("openticket:transcripts") export const registerAllFiles = async () => { transcriptFiles() @@ -24,7 +24,7 @@ const transcriptFiles = () => { const customName = transcriptConfig.data.textTranscriptStyle.customFileName const creatorId = ticket.get("openticket:opened-by").value ?? "unknown-creator-id" - const creator = (await openticket.tickets.getTicketUser(ticket,"creator")) + const creator = (await opendiscord.tickets.getTicketUser(ticket,"creator")) if (fileMode == "custom") instance.setName(customName.split(".")[0]+".txt") else if (fileMode == "user-id") instance.setName(creatorId+".txt") diff --git a/src/builders/messages.ts b/src/builders/messages.ts index 8f5507b..0bdb0c5 100644 --- a/src/builders/messages.ts +++ b/src/builders/messages.ts @@ -1,16 +1,16 @@ /////////////////////////////////////// //MESSAGE BUILDERS /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const messages = openticket.builders.messages -const buttons = openticket.builders.buttons -const dropdowns = openticket.builders.dropdowns -const files = openticket.builders.files -const embeds = openticket.builders.embeds -const lang = openticket.languages -const generalConfig = openticket.configs.get("openticket:general") +const messages = opendiscord.builders.messages +const buttons = opendiscord.builders.buttons +const dropdowns = opendiscord.builders.dropdowns +const files = opendiscord.builders.files +const embeds = opendiscord.builders.embeds +const lang = opendiscord.languages +const generalConfig = opendiscord.configs.get("openticket:general") export const registerAllMessages = async () => { verifyBarMessages() @@ -36,7 +36,7 @@ const verifyBarMessages = () => { instance.setContent("ODError: Not In Guild => `openticket:verifybar-ticket-message`") return } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-ticket-message`") return @@ -110,7 +110,7 @@ const verifyBarMessages = () => { instance.setContent("ODError: Not In Guild => `openticket:verifybar-close-message`") return } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-close-message`") return @@ -146,7 +146,7 @@ const verifyBarMessages = () => { instance.setContent("ODError: Not In Guild => `openticket:verifybar-reopen-message`") return } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-reopen-message`") return @@ -182,7 +182,7 @@ const verifyBarMessages = () => { instance.setContent("ODError: Not In Guild => `openticket:verifybar-claim-message`") return } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-claim-message`") return @@ -212,7 +212,7 @@ const verifyBarMessages = () => { instance.setContent("ODError: Not In Guild => `openticket:verifybar-unclaim-message`") return } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-unclaim-message`") return @@ -242,7 +242,7 @@ const verifyBarMessages = () => { instance.setContent("ODError: Not In Guild => `openticket:verifybar-pin-message`") return } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-pin-message`") return @@ -272,7 +272,7 @@ const verifyBarMessages = () => { instance.setContent("ODError: Not In Guild => `openticket:verifybar-unpin-message`") return } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-unpin-message`") return @@ -302,7 +302,7 @@ const verifyBarMessages = () => { instance.setContent("ODError: Not In Guild => `openticket:verifybar-autoclose-message`") return } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-autoclose-message`") return @@ -496,7 +496,7 @@ const helpMenuMessages = () => { messages.get("openticket:help-menu").workers.add( new api.ODWorker("openticket:help-menu",0,async (instance,params,source) => { const {mode,page} = params - const totalPages = (await openticket.helpmenu.render(mode)).length + const totalPages = (await opendiscord.helpmenu.render(mode)).length const embed = await embeds.getSafe("openticket:help-menu").build(source,{mode,page}) instance.addEmbed(embed) @@ -589,7 +589,7 @@ const panelMessages = () => { const {guild,channel,user,panel} = params const options: api.ODOption[] = [] panel.get("openticket:options").value.forEach((id) => { - const opt = openticket.options.get(id) + const opt = opendiscord.options.get(id) if (opt) options.push(opt) }) diff --git a/src/builders/modals.ts b/src/builders/modals.ts index 6412467..fef8aa0 100644 --- a/src/builders/modals.ts +++ b/src/builders/modals.ts @@ -1,11 +1,11 @@ /////////////////////////////////////// //MODAL BUILDERS /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const modals = openticket.builders.modals -const lang = openticket.languages +const modals = opendiscord.builders.modals +const lang = opendiscord.languages export const registerAllModals = async () => { ticketModals() @@ -21,7 +21,7 @@ const ticketModals = () => { instance.setTitle(option.exists("openticket:name") ? option.get("openticket:name").value : option.id.value) const questionIds = option.get("openticket:questions").value questionIds.forEach((id) => { - const question = openticket.questions.get(id) + const question = opendiscord.questions.get(id) if (!question) return if (question instanceof api.ODShortQuestion) instance.addQuestion({ customId:question.id.value, diff --git a/src/commands/add.ts b/src/commands/add.ts index 5186c9e..73cb34b 100644 --- a/src/commands/add.ts +++ b/src/commands/add.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //ADD COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //ADD COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:add",generalConfig.data.prefix,"add")) - openticket.responders.commands.get("openticket:add").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:add",generalConfig.data.prefix,"add")) + opendiscord.responders.commands.get("openticket:add").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.add if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,17 +46,17 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:add",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -64,19 +64,19 @@ export const registerCommandResponders = async () => { const reason = instance.options.getString("reason",false) //return when user already added to ticket - const participants = await openticket.tickets.getAllTicketParticipants(ticket) + const participants = await opendiscord.tickets.getAllTicketParticipants(ticket) if (!participants || participants.find((p) => p.user.id == data.id)){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.add"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.add"),layout:"simple"})) return cancel() } //start adding user to ticket await instance.defer(false) - await openticket.actions.get("openticket:add-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data}) - await instance.reply(await openticket.builders.messages.getSafe("openticket:add-message").build(source,{guild,channel,user,ticket,reason,data})) + await opendiscord.actions.get("openticket:add-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:add-message").build(source,{guild,channel,user,ticket,reason,data})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'add' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'add' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, diff --git a/src/commands/autoclose.ts b/src/commands/autoclose.ts index aa57fc8..3a38a93 100644 --- a/src/commands/autoclose.ts +++ b/src/commands/autoclose.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //AUTOCLOSE COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //AUTOCLOSE COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:autoclose",generalConfig.data.prefix,/^autoclose/)) - openticket.responders.commands.get("openticket:autoclose").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:autoclose",generalConfig.data.prefix,/^autoclose/)) + opendiscord.responders.commands.get("openticket:autoclose").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.autoclose if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -47,22 +47,22 @@ export const registerCommandResponders = async () => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return } //return when already closed if (ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -73,36 +73,36 @@ export const registerCommandResponders = async () => { const reason = instance.options.getString("reason",false) ticket.get("openticket:autoclose-enabled").value = false ticket.get("openticket:autoclose-hours").value = 0 - await instance.reply(await openticket.builders.messages.getSafe("openticket:autoclose-disable").build(source,{guild,channel,user,ticket,reason})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:autoclose-disable").build(source,{guild,channel,user,ticket,reason})) }else if (scope == "enable"){ const time = instance.options.getNumber("time",true) const reason = instance.options.getString("reason",false) ticket.get("openticket:autoclose-enabled").value = true ticket.get("openticket:autoclose-hours").value = time - await instance.reply(await openticket.builders.messages.getSafe("openticket:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time})) } //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on autoclose "+scope+"!","error",[ + opendiscord.log("Unable to edit ticket message on autoclose "+scope+"!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { const scope = instance.options.getSubCommand() const reason = instance.options.getString("reason",false) - openticket.log(instance.user.displayName+" used the 'autoclose "+scope+"' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'autoclose "+scope+"' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, diff --git a/src/commands/autodelete.ts b/src/commands/autodelete.ts index 6ee1f9d..939a94a 100644 --- a/src/commands/autodelete.ts +++ b/src/commands/autodelete.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //AUTODELETE COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //AUTODELETE COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:autodelete",generalConfig.data.prefix,/^autodelete/)) - openticket.responders.commands.get("openticket:autodelete").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:autodelete",generalConfig.data.prefix,/^autodelete/)) + opendiscord.responders.commands.get("openticket:autodelete").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.autodelete if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -47,17 +47,17 @@ export const registerCommandResponders = async () => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -68,36 +68,36 @@ export const registerCommandResponders = async () => { const reason = instance.options.getString("reason",false) ticket.get("openticket:autodelete-enabled").value = false ticket.get("openticket:autodelete-days").value = 0 - await instance.reply(await openticket.builders.messages.getSafe("openticket:autodelete-disable").build(source,{guild,channel,user,ticket,reason})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:autodelete-disable").build(source,{guild,channel,user,ticket,reason})) }else if (scope == "enable"){ const time = instance.options.getNumber("time",true) const reason = instance.options.getString("reason",false) ticket.get("openticket:autodelete-enabled").value = true ticket.get("openticket:autodelete-days").value = time - await instance.reply(await openticket.builders.messages.getSafe("openticket:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time})) } //update ticket message - const ticketMessage = await openticket.tickets.getTicketMessage(ticket) + const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ - openticket.log("Unable to edit ticket message on autodelete "+scope+"!","error",[ + opendiscord.log("Unable to edit ticket message on autodelete "+scope+"!","error",[ {key:"channel",value:"#"+channel.name}, {key:"channelid",value:channel.id,hidden:true}, {key:"messageid",value:ticketMessage.id}, {key:"option",value:ticket.option.id.value} ]) - openticket.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) + opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException")) } } }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { const scope = instance.options.getSubCommand() const reason = instance.options.getString("reason",false) - openticket.log(instance.user.displayName+" used the 'autodelete "+scope+"' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'autodelete "+scope+"' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, diff --git a/src/commands/blacklist.ts b/src/commands/blacklist.ts index d7448d4..5f50105 100644 --- a/src/commands/blacklist.ts +++ b/src/commands/blacklist.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //BLACKLIST COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //BLACKLIST COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:blacklist",generalConfig.data.prefix,/^blacklist/)) - openticket.responders.commands.get("openticket:blacklist").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:blacklist",generalConfig.data.prefix,/^blacklist/)) + opendiscord.responders.commands.get("openticket:blacklist").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.blacklist if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -47,25 +47,25 @@ export const registerCommandResponders = async () => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } const scope = instance.options.getSubCommand() if (!scope || (scope != "add" && scope != "get" && scope != "remove" && scope != "view")) return if (scope == "view"){ - await instance.reply(await openticket.builders.messages.getSafe("openticket:blacklist-view").build(source,{guild,channel,user})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:blacklist-view").build(source,{guild,channel,user})) }else if (scope == "get"){ const data = instance.options.getUser("user",true) - await instance.reply(await openticket.builders.messages.getSafe("openticket:blacklist-get").build(source,{guild,channel,user,data})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:blacklist-get").build(source,{guild,channel,user,data})) }else if (scope == "add"){ const data = instance.options.getUser("user",true) const reason = instance.options.getString("reason",false) - openticket.blacklist.add(new api.ODBlacklist(data.id,reason),true) - openticket.log(instance.user.displayName+" added "+data.displayName+" to blacklist!","info",[ + opendiscord.blacklist.add(new api.ODBlacklist(data.id,reason),true) + opendiscord.log(instance.user.displayName+" added "+data.displayName+" to blacklist!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channelid",value:channel.id,hidden:true}, @@ -74,17 +74,17 @@ export const registerCommandResponders = async () => { ]) //manage stats - await openticket.stats.get("openticket:global").setStat("openticket:users-blacklisted",1,"increase") - await openticket.stats.get("openticket:user").setStat("openticket:users-blacklisted",user.id,1,"increase") + await opendiscord.stats.get("openticket:global").setStat("openticket:users-blacklisted",1,"increase") + await opendiscord.stats.get("openticket:user").setStat("openticket:users-blacklisted",user.id,1,"increase") - await instance.reply(await openticket.builders.messages.getSafe("openticket:blacklist-add").build(source,{guild,channel,user,data,reason})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:blacklist-add").build(source,{guild,channel,user,data,reason})) }else if (scope == "remove"){ const data = instance.options.getUser("user",true) const reason = instance.options.getString("reason",false) - openticket.blacklist.remove(data.id) - openticket.log(instance.user.displayName+" removed "+data.displayName+" from blacklist!","info",[ + opendiscord.blacklist.remove(data.id) + opendiscord.log(instance.user.displayName+" removed "+data.displayName+" from blacklist!","info",[ {key:"user",value:user.username}, {key:"userid",value:user.id,hidden:true}, {key:"channelid",value:channel.id,hidden:true}, @@ -92,7 +92,7 @@ export const registerCommandResponders = async () => { {key:"reason",value:reason ?? "/"} ]) - await instance.reply(await openticket.builders.messages.getSafe("openticket:blacklist-remove").build(source,{guild,channel,user,data,reason})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:blacklist-remove").build(source,{guild,channel,user,data,reason})) } }), new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { @@ -107,16 +107,16 @@ export const registerCommandResponders = async () => { //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.blacklisting.logs){ - const logChannel = openticket.posts.get("openticket:logs") - if (logChannel) logChannel.send(await openticket.builders.messages.getSafe("openticket:blacklist-logs").build(source,{guild,channel,user,mode:scope,data,reason})) + const logChannel = opendiscord.posts.get("openticket:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:blacklist-logs").build(source,{guild,channel,user,mode:scope,data,reason})) } //to dm - if (generalConfig.data.system.messages.blacklisting.dm) await openticket.client.sendUserDm(user,await openticket.builders.messages.getSafe("openticket:blacklist-dm").build(source,{guild,channel,user,mode:scope,data,reason})) + if (generalConfig.data.system.messages.blacklisting.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("openticket:blacklist-dm").build(source,{guild,channel,user,mode:scope,data,reason})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { const scope = instance.options.getSubCommand() - openticket.log(instance.user.displayName+" used the 'blacklist "+scope+"' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'blacklist "+scope+"' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, diff --git a/src/commands/claim.ts b/src/commands/claim.ts index c6ad44c..1a4a236 100644 --- a/src/commands/claim.ts +++ b/src/commands/claim.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //CLAIM COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //CLAIM COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:claim",generalConfig.data.prefix,"claim")) - openticket.responders.commands.get("openticket:claim").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:claim",generalConfig.data.prefix,"claim")) + opendiscord.responders.commands.get("openticket:claim").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.claim if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,22 +46,22 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:claim",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already claimed if (ticket.get("openticket:claimed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -70,11 +70,11 @@ export const registerCommandResponders = async () => { //start claiming ticket await instance.defer(false) - await openticket.actions.get("openticket:claim-ticket").run(source,{guild,channel,user:claimUser,ticket,reason,sendMessage:false}) - await instance.reply(await openticket.builders.messages.getSafe("openticket:claim-message").build(source,{guild,channel,user:claimUser,ticket,reason})) + await opendiscord.actions.get("openticket:claim-ticket").run(source,{guild,channel,user:claimUser,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:claim-message").build(source,{guild,channel,user:claimUser,ticket,reason})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'claim' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'claim' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, @@ -86,33 +86,33 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //CLAIM TICKET BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:claim-ticket",/^od:claim-ticket/)) - openticket.responders.buttons.get("openticket:claim-ticket").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:claim-ticket",/^od:claim-ticket/)) + opendiscord.responders.buttons.get("openticket:claim-ticket").workers.add( new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "unclaim-message") return - if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:claim-ticket-ticket-message").activate(instance) - else await openticket.verifybars.get("openticket:claim-ticket-unclaim-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:claim-ticket-ticket-message").activate(instance) + else await opendiscord.verifybars.get("openticket:claim-ticket-unclaim-message").activate(instance) }) ) } export const registerModalResponders = async () => { //CLAIM WITH REASON MODAL RESPONDER - openticket.responders.modals.add(new api.ODModalResponder("openticket:claim-ticket-reason",/^od:claim-ticket-reason_/)) - openticket.responders.modals.get("openticket:claim-ticket-reason").workers.add([ + opendiscord.responders.modals.add(new api.ODModalResponder("openticket:claim-ticket-reason",/^od:claim-ticket-reason_/)) + opendiscord.responders.modals.get("openticket:claim-ticket-reason").workers.add([ new api.ODWorker("openticket:claim-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } - const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -122,15 +122,15 @@ export const registerModalResponders = async () => { //claim with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "unclaim-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:claim-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:claim-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await openticket.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) diff --git a/src/commands/clear.ts b/src/commands/clear.ts index 61a0e7f..4c415ed 100644 --- a/src/commands/clear.ts +++ b/src/commands/clear.ts @@ -1,45 +1,45 @@ /////////////////////////////////////// //CLEAR COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //CLEAR COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:clear",generalConfig.data.prefix,"clear")) - openticket.responders.commands.get("openticket:clear").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:clear",generalConfig.data.prefix,"clear")) + opendiscord.responders.commands.get("openticket:clear").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.clear if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ //only allow global admins (ticket admins aren't allowed to clear tickets) - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild,{allowChannelUserScope:false,allowChannelRoleScope:false}))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild,{allowChannelUserScope:false,allowChannelRoleScope:false}))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -47,14 +47,14 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:clear",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } const tempFilter = instance.options.getString("filter",false) const filter = (tempFilter) ? tempFilter.toLowerCase() as api.ODTicketClearFilter : "all" const list: string[] = [] - const ticketList = openticket.tickets.getAll().filter((ticket) => { + const ticketList = opendiscord.tickets.getAll().filter((ticket) => { if (filter == "all") return true else if (filter == "open" && ticket.get("openticket:open").value) return true else if (filter == "closed" && ticket.get("openticket:closed").value) return true @@ -66,16 +66,16 @@ export const registerCommandResponders = async () => { else return false }) for (const ticket of ticketList){ - const ticketChannel = await openticket.tickets.getTicketChannel(ticket) + const ticketChannel = await opendiscord.tickets.getTicketChannel(ticket) if (ticketChannel) list.push("#"+ticketChannel.name) } //reply with clear verify await instance.defer(true) - await instance.reply(await openticket.builders.messages.getSafe("openticket:clear-verify-message").build(source,{guild,channel,user,filter,list})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:clear-verify-message").build(source,{guild,channel,user,filter,list})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'clear' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'clear' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, @@ -87,8 +87,8 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //CLEAR CONTINUE BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:clear-continue",/^od:clear-continue_/)) - openticket.responders.buttons.get("openticket:clear-continue").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:clear-continue",/^od:clear-continue_/)) + opendiscord.responders.buttons.get("openticket:clear-continue").workers.add( new api.ODWorker("openticket:clear-continue",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild || channel.isDMBased()) return @@ -99,7 +99,7 @@ export const registerButtonResponders = async () => { //start ticket clear instance.defer("update",true) const list: string[] = [] - const ticketList = openticket.tickets.getAll().filter((ticket) => { + const ticketList = opendiscord.tickets.getAll().filter((ticket) => { if (filter == "all") return true else if (filter == "open" && ticket.get("openticket:open").value) return true else if (filter == "closed" && ticket.get("openticket:closed").value) return true @@ -111,12 +111,12 @@ export const registerButtonResponders = async () => { else return false }) for (const ticket of ticketList){ - const ticketChannel = await openticket.tickets.getTicketChannel(ticket) + const ticketChannel = await opendiscord.tickets.getTicketChannel(ticket) if (ticketChannel) list.push("#"+ticketChannel.name) } - await openticket.actions.get("openticket:clear-tickets").run(originalSource,{guild,channel,user,filter,list:ticketList}) - await instance.update(await openticket.builders.messages.getSafe("openticket:clear-message").build(originalSource,{guild,channel,user,filter,list})) + await opendiscord.actions.get("openticket:clear-tickets").run(originalSource,{guild,channel,user,filter,list:ticketList}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:clear-message").build(originalSource,{guild,channel,user,filter,list})) }) ) } \ No newline at end of file diff --git a/src/commands/close.ts b/src/commands/close.ts index fdb107c..14a2cbd 100644 --- a/src/commands/close.ts +++ b/src/commands/close.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //CLOSE COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //CLOSE COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:close",generalConfig.data.prefix,"close")) - openticket.responders.commands.get("openticket:close").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:close",generalConfig.data.prefix,"close")) + opendiscord.responders.commands.get("openticket:close").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.close if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,22 +46,22 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:close",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already closed if (ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -69,11 +69,11 @@ export const registerCommandResponders = async () => { //start closing ticket await instance.defer(false) - await openticket.actions.get("openticket:close-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.reply(await openticket.builders.messages.getSafe("openticket:close-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:close-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:close-message").build(source,{guild,channel,user,ticket,reason})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'close' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'close' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, @@ -85,33 +85,33 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //CLOSE TICKET BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:close-ticket",/^od:close-ticket_/)) - openticket.responders.buttons.get("openticket:close-ticket").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:close-ticket",/^od:close-ticket_/)) + opendiscord.responders.buttons.get("openticket:close-ticket").workers.add( new api.ODWorker("openticket:close-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "reopen-message") return - if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:close-ticket-ticket-message").activate(instance) - else await openticket.verifybars.get("openticket:close-ticket-reopen-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:close-ticket-ticket-message").activate(instance) + else await opendiscord.verifybars.get("openticket:close-ticket-reopen-message").activate(instance) }) ) } export const registerModalResponders = async () => { //CLOSE WITH REASON MODAL RESPONDER - openticket.responders.modals.add(new api.ODModalResponder("openticket:close-ticket-reason",/^od:close-ticket-reason_/)) - openticket.responders.modals.get("openticket:close-ticket-reason").workers.add([ + opendiscord.responders.modals.add(new api.ODModalResponder("openticket:close-ticket-reason",/^od:close-ticket-reason_/)) + opendiscord.responders.modals.get("openticket:close-ticket-reason").workers.add([ new api.ODWorker("openticket:close-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } - const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -121,15 +121,15 @@ export const registerModalResponders = async () => { //close with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "reopen-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await openticket.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) diff --git a/src/commands/delete.ts b/src/commands/delete.ts index e80f677..d98d0a7 100644 --- a/src/commands/delete.ts +++ b/src/commands/delete.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //DELETE COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //DELETE COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:delete",generalConfig.data.prefix,"delete")) - openticket.responders.commands.get("openticket:delete").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:delete",generalConfig.data.prefix,"delete")) + opendiscord.responders.commands.get("openticket:delete").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,17 +46,17 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:delete",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -65,11 +65,11 @@ export const registerCommandResponders = async () => { //start deleting ticket await instance.defer(false) - await instance.reply(await openticket.builders.messages.getSafe("openticket:delete-message").build(source,{guild,channel,user,ticket,reason})) - await openticket.actions.get("openticket:delete-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:delete-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:delete-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript}) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'delete' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'delete' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, @@ -81,35 +81,35 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //DELETE TICKET BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:delete-ticket",/^od:delete-ticket/)) - openticket.responders.buttons.get("openticket:delete-ticket").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:delete-ticket",/^od:delete-ticket/)) + opendiscord.responders.buttons.get("openticket:delete-ticket").workers.add( new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "autoclose-message") return - if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:delete-ticket-ticket-message").activate(instance) - else if (originalSource == "close-message") await openticket.verifybars.get("openticket:delete-ticket-close-message").activate(instance) - else if (originalSource == "reopen-message") await openticket.verifybars.get("openticket:delete-ticket-reopen-message").activate(instance) - else if (originalSource == "autoclose-message") await openticket.verifybars.get("openticket:delete-ticket-autoclose-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:delete-ticket-ticket-message").activate(instance) + else if (originalSource == "close-message") await opendiscord.verifybars.get("openticket:delete-ticket-close-message").activate(instance) + else if (originalSource == "reopen-message") await opendiscord.verifybars.get("openticket:delete-ticket-reopen-message").activate(instance) + else if (originalSource == "autoclose-message") await opendiscord.verifybars.get("openticket:delete-ticket-autoclose-message").activate(instance) }) ) } export const registerModalResponders = async () => { //REOPEN WITH REASON MODAL RESPONDER - openticket.responders.modals.add(new api.ODModalResponder("openticket:delete-ticket-reason",/^od:delete-ticket-reason_/)) - openticket.responders.modals.get("openticket:delete-ticket-reason").workers.add([ + opendiscord.responders.modals.add(new api.ODModalResponder("openticket:delete-ticket-reason",/^od:delete-ticket-reason_/)) + opendiscord.responders.modals.get("openticket:delete-ticket-reason").workers.add([ new api.ODWorker("openticket:delete-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } - const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -120,29 +120,29 @@ export const registerModalResponders = async () => { if (originalSource == "ticket-message"){ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) + opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable ticket.get("openticket:for-deletion").value = true - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "close-message"){ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) + opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "reopen-message"){ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) + opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "autoclose-message"){ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) + opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - openticket.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) + opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) } }) ]) diff --git a/src/commands/help.ts b/src/commands/help.ts index 36b7ec1..a23ab8c 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //HELP COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //HELP COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:help",generalConfig.data.prefix,"help")) - openticket.responders.commands.get("openticket:help").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:help",generalConfig.data.prefix,"help")) + opendiscord.responders.commands.get("openticket:help").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.help if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -53,10 +53,10 @@ export const registerCommandResponders = async () => { }else if (!generalConfig.data.slashCommands) mode = "text" else mode = "slash" - await instance.reply(await openticket.builders.messages.getSafe("openticket:help-menu").build(source,{mode,page:0})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:help-menu").build(source,{mode,page:0})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'help' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'help' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, @@ -68,8 +68,8 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //HELP MENU SWITCH BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-switch",/^od:help-menu-switch_(slash|text)/)) - openticket.responders.buttons.get("openticket:help-menu-switch").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-switch",/^od:help-menu-switch_(slash|text)/)) + opendiscord.responders.buttons.get("openticket:help-menu-switch").workers.add( new api.ODWorker("openticket:update-help-menu",0,async (instance,params,source,cancel) => { const mode = instance.interaction.customId.split("_")[1] as "slash"|"text" const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/) @@ -77,35 +77,35 @@ export const registerButtonResponders = async () => { const newMode = (mode == "slash") ? "text" : "slash" - const msg = await openticket.builders.messages.getSafe("openticket:help-menu").build("button",{mode:newMode,page:currentPage}) + const msg = await opendiscord.builders.messages.getSafe("openticket:help-menu").build("button",{mode:newMode,page:currentPage}) await instance.update(msg) }) ) //HELP MENU PREVIOUS BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-previous",/^od:help-menu-previous/)) - openticket.responders.buttons.get("openticket:help-menu-previous").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-previous",/^od:help-menu-previous/)) + opendiscord.responders.buttons.get("openticket:help-menu-previous").workers.add( new api.ODWorker("openticket:update-help-menu",0,async (instance,params,source,cancel) => { const switchButton = instance.getMessageComponent("button",/^od:help-menu-switch_(slash|text)/) const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/) const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0 const currentMode = (switchButton && switchButton.customId) ? switchButton.customId.split("_")[1] as "text"|"slash" : "slash" - const msg = await openticket.builders.messages.getSafe("openticket:help-menu").build("button",{mode:currentMode,page:currentPage-1}) + const msg = await opendiscord.builders.messages.getSafe("openticket:help-menu").build("button",{mode:currentMode,page:currentPage-1}) await instance.update(msg) }) ) //HELP MENU NEXT BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-next",/^od:help-menu-next/)) - openticket.responders.buttons.get("openticket:help-menu-next").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-next",/^od:help-menu-next/)) + opendiscord.responders.buttons.get("openticket:help-menu-next").workers.add( new api.ODWorker("openticket:update-help-menu",0,async (instance,params,source,cancel) => { const switchButton = instance.getMessageComponent("button",/^od:help-menu-switch_(slash|text)/) const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/) const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0 const currentMode = (switchButton && switchButton.customId) ? switchButton.customId.split("_")[1] as "text"|"slash" : "slash" - const msg = await openticket.builders.messages.getSafe("openticket:help-menu").build("button",{mode:currentMode,page:currentPage+1}) + const msg = await opendiscord.builders.messages.getSafe("openticket:help-menu").build("button",{mode:currentMode,page:currentPage+1}) await instance.update(msg) }) ) diff --git a/src/commands/move.ts b/src/commands/move.ts index f3d1b23..9fd61a0 100644 --- a/src/commands/move.ts +++ b/src/commands/move.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //MOVE COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //MOVE COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:move",generalConfig.data.prefix,"move")) - openticket.responders.commands.get("openticket:move").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:move",generalConfig.data.prefix,"move")) + opendiscord.responders.commands.get("openticket:move").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.move if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,42 +46,42 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:move",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } const id = instance.options.getString("id",true) const reason = instance.options.getString("reason",false) - const option = openticket.options.get(id) + const option = opendiscord.options.get(id) //return if unknown option if (!option || !(option instanceof api.ODTicketOption)){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.titles.unknownOption"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.titles.unknownOption"),layout:"simple"})) return cancel() } //return if option is the same if (ticket.option.id.value == option.id.value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"This ticket is already the same as the chosen option!",layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"This ticket is already the same as the chosen option!",layout:"simple"})) return cancel() } //start moving ticket await instance.defer(false) - await openticket.actions.get("openticket:move-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:option}) - await instance.reply(await openticket.builders.messages.getSafe("openticket:move-message").build(source,{guild,channel,user,ticket,reason,data:option})) + await opendiscord.actions.get("openticket:move-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:option}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:move-message").build(source,{guild,channel,user,ticket,reason,data:option})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'move' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'move' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, diff --git a/src/commands/panel.ts b/src/commands/panel.ts index 0eb103e..5589323 100644 --- a/src/commands/panel.ts +++ b/src/commands/panel.ts @@ -1,45 +1,45 @@ /////////////////////////////////////// //STATS COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //PANEL COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:panel",generalConfig.data.prefix,/^panel/)) - openticket.responders.commands.get("openticket:panel").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:panel",generalConfig.data.prefix,/^panel/)) + opendiscord.responders.commands.get("openticket:panel").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.panel //command is disabled if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -48,30 +48,30 @@ export const registerCommandResponders = async () => { const {guild,channel,user} = instance if (!guild || instance.channel.type == discord.ChannelType.GroupDM){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } const id = instance.options.getString("id",true) - const panel = openticket.panels.get(id) + const panel = opendiscord.panels.get(id) if (!panel){ //invalid panel - instance.reply(await openticket.builders.messages.getSafe("openticket:error-panel-unknown").build(source,{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-panel-unknown").build(source,{guild,channel,user})) return cancel() } - await instance.reply(await openticket.builders.messages.getSafe("openticket:panel-ready").build(source,{guild,channel,user,panel})) - const panelMessage = await instance.channel.send((await openticket.builders.messages.getSafe("openticket:panel").build(source,{guild,channel,user,panel})).message) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:panel-ready").build(source,{guild,channel,user,panel})) + const panelMessage = await instance.channel.send((await opendiscord.builders.messages.getSafe("openticket:panel").build(source,{guild,channel,user,panel})).message) //add panel to database on auto-update if (instance.options.getBoolean("auto-update",false)){ - const globalDatabase = openticket.databases.get("openticket:global") + const globalDatabase = opendiscord.databases.get("openticket:global") await globalDatabase.set("openticket:panel-update",panelMessage.channel.id+"_"+panelMessage.id,panel.id.value) } }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'panel' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'panel' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, diff --git a/src/commands/pin.ts b/src/commands/pin.ts index a29f5ad..ed1460b 100644 --- a/src/commands/pin.ts +++ b/src/commands/pin.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //PIN COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //PIN COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:pin",generalConfig.data.prefix,"pin")) - openticket.responders.commands.get("openticket:pin").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:pin",generalConfig.data.prefix,"pin")) + opendiscord.responders.commands.get("openticket:pin").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.pin if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,22 +46,22 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:pin",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already pinned if (ticket.get("openticket:pinned").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -69,11 +69,11 @@ export const registerCommandResponders = async () => { //start pinning ticket await instance.defer(false) - await openticket.actions.get("openticket:pin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.reply(await openticket.builders.messages.getSafe("openticket:pin-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:pin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:pin-message").build(source,{guild,channel,user,ticket,reason})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'pin' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'pin' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, @@ -85,33 +85,33 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //PIN TICKET BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:pin-ticket",/^od:pin-ticket/)) - openticket.responders.buttons.get("openticket:pin-ticket").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:pin-ticket",/^od:pin-ticket/)) + opendiscord.responders.buttons.get("openticket:pin-ticket").workers.add( new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "unpin-message") return - if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:pin-ticket-ticket-message").activate(instance) - else await openticket.verifybars.get("openticket:pin-ticket-unpin-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:pin-ticket-ticket-message").activate(instance) + else await opendiscord.verifybars.get("openticket:pin-ticket-unpin-message").activate(instance) }) ) } export const registerModalResponders = async () => { //PIN WITH REASON MODAL RESPONDER - openticket.responders.modals.add(new api.ODModalResponder("openticket:pin-ticket-reason",/^od:pin-ticket-reason_/)) - openticket.responders.modals.get("openticket:pin-ticket-reason").workers.add([ + opendiscord.responders.modals.add(new api.ODModalResponder("openticket:pin-ticket-reason",/^od:pin-ticket-reason_/)) + opendiscord.responders.modals.get("openticket:pin-ticket-reason").workers.add([ new api.ODWorker("openticket:pin-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } - const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -121,15 +121,15 @@ export const registerModalResponders = async () => { //pin with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "unpin-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:pin-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:pin-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await openticket.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) diff --git a/src/commands/remove.ts b/src/commands/remove.ts index e38a265..89cccc1 100644 --- a/src/commands/remove.ts +++ b/src/commands/remove.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //REMOVE COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //REMOVE COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:remove",generalConfig.data.prefix,"remove")) - openticket.responders.commands.get("openticket:remove").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:remove",generalConfig.data.prefix,"remove")) + opendiscord.responders.commands.get("openticket:remove").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.remove if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,17 +46,17 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:remove",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -64,19 +64,19 @@ export const registerCommandResponders = async () => { const reason = instance.options.getString("reason",false) //return when user is not a participant of the ticket (admins & creator can't be removed) - const participants = await openticket.tickets.getAllTicketParticipants(ticket) + const participants = await opendiscord.tickets.getAllTicketParticipants(ticket) if (!participants || !participants.find((p) => p.user.id == data.id && p.role == "participant")){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.remove"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.remove"),layout:"simple"})) return cancel() } //start removing user from ticket await instance.defer(false) - await openticket.actions.get("openticket:remove-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data}) - await instance.reply(await openticket.builders.messages.getSafe("openticket:remove-message").build(source,{guild,channel,user,ticket,reason,data})) + await opendiscord.actions.get("openticket:remove-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:remove-message").build(source,{guild,channel,user,ticket,reason,data})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'remove' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'remove' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, diff --git a/src/commands/rename.ts b/src/commands/rename.ts index e5fafb5..39f560a 100644 --- a/src/commands/rename.ts +++ b/src/commands/rename.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //RENAME COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //RENAME COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:rename",generalConfig.data.prefix,"rename")) - openticket.responders.commands.get("openticket:rename").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:rename",generalConfig.data.prefix,"rename")) + opendiscord.responders.commands.get("openticket:rename").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.rename if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,17 +46,17 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:rename",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -65,11 +65,11 @@ export const registerCommandResponders = async () => { //start renaming ticket await instance.defer(false) - await openticket.actions.get("openticket:rename-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:name}) - await instance.reply(await openticket.builders.messages.getSafe("openticket:rename-message").build(source,{guild,channel,user,ticket,reason,data:name})) + await opendiscord.actions.get("openticket:rename-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:name}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:rename-message").build(source,{guild,channel,user,ticket,reason,data:name})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'rename' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'rename' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, diff --git a/src/commands/reopen.ts b/src/commands/reopen.ts index 415ba5d..a7d31e5 100644 --- a/src/commands/reopen.ts +++ b/src/commands/reopen.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //REOPEN COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //REOPEN COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:reopen",generalConfig.data.prefix,"reopen")) - openticket.responders.commands.get("openticket:reopen").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:reopen",generalConfig.data.prefix,"reopen")) + opendiscord.responders.commands.get("openticket:reopen").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.reopen if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,22 +46,22 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:reopen",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not closed if (!ticket.get("openticket:closed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -69,11 +69,11 @@ export const registerCommandResponders = async () => { //start reopening ticket await instance.defer(false) - await openticket.actions.get("openticket:reopen-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.reply(await openticket.builders.messages.getSafe("openticket:reopen-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:reopen-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build(source,{guild,channel,user,ticket,reason})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'reopen' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'reopen' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, @@ -85,34 +85,34 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //REOPEN TICKET BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:reopen-ticket",/^od:reopen-ticket/)) - openticket.responders.buttons.get("openticket:reopen-ticket").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:reopen-ticket",/^od:reopen-ticket/)) + opendiscord.responders.buttons.get("openticket:reopen-ticket").workers.add( new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "close-message" && originalSource != "autoclose-message") return - if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:reopen-ticket-ticket-message").activate(instance) - else if (originalSource == "close-message") await openticket.verifybars.get("openticket:reopen-ticket-close-message").activate(instance) - else await openticket.verifybars.get("openticket:reopen-ticket-autoclose-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:reopen-ticket-ticket-message").activate(instance) + else if (originalSource == "close-message") await opendiscord.verifybars.get("openticket:reopen-ticket-close-message").activate(instance) + else await opendiscord.verifybars.get("openticket:reopen-ticket-autoclose-message").activate(instance) }) ) } export const registerModalResponders = async () => { //REOPEN WITH REASON MODAL RESPONDER - openticket.responders.modals.add(new api.ODModalResponder("openticket:reopen-ticket-reason",/^od:reopen-ticket-reason_/)) - openticket.responders.modals.get("openticket:reopen-ticket-reason").workers.add([ + opendiscord.responders.modals.add(new api.ODModalResponder("openticket:reopen-ticket-reason",/^od:reopen-ticket-reason_/)) + opendiscord.responders.modals.get("openticket:reopen-ticket-reason").workers.add([ new api.ODWorker("openticket:reopen-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } - const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -122,19 +122,19 @@ export const registerModalResponders = async () => { //reopen with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "close-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "autoclose-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await openticket.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) diff --git a/src/commands/role.ts b/src/commands/role.ts index 88ea4f6..b826b50 100644 --- a/src/commands/role.ts +++ b/src/commands/role.ts @@ -1,41 +1,41 @@ /////////////////////////////////////// //ROLE BUTTON (not command) /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerButtonResponders = async () => { //ROLE OPTION BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:role-option",/^od:role-option_/)) - openticket.responders.buttons.get("openticket:role-option").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:role-option",/^od:role-option_/)) + opendiscord.responders.buttons.get("openticket:role-option").workers.add( new api.ODWorker("openticket:role-option",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } //get option const optionId = instance.interaction.customId.split("_")[2] - const option = openticket.options.get(optionId) + const option = opendiscord.options.get(optionId) if (!option || !(option instanceof api.ODRoleOption)){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) return cancel() } //reaction role await instance.defer("reply",true) - const res = await openticket.actions.get("openticket:reaction-role").run("panel-button",{guild,user,option,overwriteMode:null}) + const res = await opendiscord.actions.get("openticket:reaction-role").run("panel-button",{guild,user,option,overwriteMode:null}) if (!res.result || !res.role){ //error - await instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive role update data from worker!",layout:"advanced"})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive role update data from worker!",layout:"advanced"})) return cancel() } - if (generalConfig.data.system.replyOnReactionRole) await instance.reply(await openticket.builders.messages.getSafe("openticket:reaction-role").build("panel-button",{guild,user,role:res.role,result:res.result})) + if (generalConfig.data.system.replyOnReactionRole) await instance.reply(await opendiscord.builders.messages.getSafe("openticket:reaction-role").build("panel-button",{guild,user,role:res.role,result:res.result})) }) ) } \ No newline at end of file diff --git a/src/commands/stats.ts b/src/commands/stats.ts index 1c35760..b01811f 100644 --- a/src/commands/stats.ts +++ b/src/commands/stats.ts @@ -1,30 +1,30 @@ /////////////////////////////////////// //STATS COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //STATS COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:stats",generalConfig.data.prefix,/^stats/)) - openticket.responders.commands.get("openticket:stats").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:stats",generalConfig.data.prefix,/^stats/)) + opendiscord.responders.commands.get("openticket:stats").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.stats //command is disabled if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() } //reset subcommand is owner/developer only if (instance.options.getSubCommand() == "reset"){ - if (!openticket.permissions.hasPermissions("owner",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]})) return cancel() }else return } @@ -32,26 +32,26 @@ export const registerCommandResponders = async () => { //permissions for normal scopes if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -60,30 +60,30 @@ export const registerCommandResponders = async () => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } const scope = instance.options.getSubCommand() if (!scope || (scope != "global" && scope != "ticket" && scope != "user" && scope != "reset")) return if (scope == "global"){ - await instance.reply(await openticket.builders.messages.getSafe("openticket:stats-global").build(source,{guild,channel,user})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:stats-global").build(source,{guild,channel,user})) }else if (scope == "ticket"){ const id = instance.options.getChannel("ticket",false)?.id ?? channel.id - const ticket = openticket.tickets.get(id) + const ticket = opendiscord.tickets.get(id) - if (ticket) await instance.reply(await openticket.builders.messages.getSafe("openticket:stats-ticket").build(source,{guild,channel,user,scopeData:ticket})) - else await instance.reply(await openticket.builders.messages.getSafe("openticket:stats-ticket-unknown").build(source,{guild,channel,user,id})) + if (ticket) await instance.reply(await opendiscord.builders.messages.getSafe("openticket:stats-ticket").build(source,{guild,channel,user,scopeData:ticket})) + else await instance.reply(await opendiscord.builders.messages.getSafe("openticket:stats-ticket-unknown").build(source,{guild,channel,user,id})) }else if (scope == "user"){ const statsUser = instance.options.getUser("user",false) ?? user - await instance.reply(await openticket.builders.messages.getSafe("openticket:stats-user").build(source,{guild,channel,user,scopeData:statsUser})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:stats-user").build(source,{guild,channel,user,scopeData:statsUser})) }else if (scope == "reset"){ const reason = instance.options.getString("reason",false) - openticket.stats.reset() - await instance.reply(await openticket.builders.messages.getSafe("openticket:stats-reset").build(source,{guild,channel,user,reason})) + opendiscord.stats.reset() + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:stats-reset").build(source,{guild,channel,user,reason})) } }), @@ -95,7 +95,7 @@ export const registerCommandResponders = async () => { }else if (scope == "user"){ data = instance.options.getUser("user",false)?.id ?? instance.user.id }else data = "/" - openticket.log(instance.user.displayName+" used the 'stats "+scope+"' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'stats "+scope+"' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, diff --git a/src/commands/ticket.ts b/src/commands/ticket.ts index 5743e74..13e6432 100644 --- a/src/commands/ticket.ts +++ b/src/commands/ticket.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //TICKET COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //TICKET COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:ticket",generalConfig.data.prefix,/^ticket/)) - openticket.responders.commands.get("openticket:ticket").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:ticket",generalConfig.data.prefix,/^ticket/)) + opendiscord.responders.commands.get("openticket:ticket").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.ticket if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -47,51 +47,51 @@ export const registerCommandResponders = async () => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } //get option const optionId = instance.options.getString("id",true) - const option = openticket.options.get(optionId) + const option = opendiscord.options.get(optionId) if (!option || !(option instanceof api.ODTicketOption)){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) return cancel() } //check ticket permissions - const res = await openticket.actions.get("openticket:create-ticket-permissions").run(source,{guild,user,option}) + const res = await opendiscord.actions.get("openticket:create-ticket-permissions").run(source,{guild,user,option}) if (!res.valid){ //error - if (res.reason == "blacklist") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) - else if (res.reason == "cooldown") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) - else if (res.reason == "global-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) - else if (res.reason == "global-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) - else if (res.reason == "option-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) - else if (res.reason == "option-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) - else instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) + if (res.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + else if (res.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) + else if (res.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) + else if (res.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) + else if (res.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) + else if (res.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) + else instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) return cancel() } //start ticket creation if (option.exists("openticket:questions") && option.get("openticket:questions").value.length > 0){ //send modal - instance.modal(await openticket.builders.modals.getSafe("openticket:ticket-questions").build(source,{guild,channel,user,option})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:ticket-questions").build(source,{guild,channel,user,option})) }else{ //create ticket await instance.defer(true) - const res = await openticket.actions.get("openticket:create-ticket").run(source,{guild,user,answers:[],option}) + const res = await opendiscord.actions.get("openticket:create-ticket").run(source,{guild,user,answers:[],option}) if (!res.channel || !res.ticket){ //error - await instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) return cancel() } - await instance.reply(await openticket.builders.messages.getSafe("openticket:ticket-created").build(source,{guild,channel:res.channel,user,ticket:res.ticket})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:ticket-created").build(source,{guild,channel:res.channel,user,ticket:res.ticket})) } }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'ticket' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'ticket' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, @@ -103,53 +103,53 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //TICKET OPTION BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:ticket-option",/^od:ticket-option_/)) - openticket.responders.buttons.get("openticket:ticket-option").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:ticket-option",/^od:ticket-option_/)) + opendiscord.responders.buttons.get("openticket:ticket-option").workers.add( new api.ODWorker("openticket:ticket-option",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } //get option const optionId = instance.interaction.customId.split("_")[2] - const option = openticket.options.get(optionId) + const option = opendiscord.options.get(optionId) if (!option || !(option instanceof api.ODTicketOption)){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) return cancel() } //check ticket permissions - const res = await openticket.actions.get("openticket:create-ticket-permissions").run("panel-button",{guild,user,option}) + const res = await opendiscord.actions.get("openticket:create-ticket-permissions").run("panel-button",{guild,user,option}) if (!res.valid){ //error - if (res.reason == "blacklist") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) - else if (res.reason == "cooldown") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) - else if (res.reason == "global-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) - else if (res.reason == "global-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) - else if (res.reason == "option-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) - else if (res.reason == "option-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) - else instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) + if (res.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + else if (res.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) + else if (res.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) + else if (res.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) + else if (res.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) + else if (res.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) + else instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) return cancel() } //start ticket creation if (option.exists("openticket:questions") && option.get("openticket:questions").value.length > 0){ //send modal - instance.modal(await openticket.builders.modals.getSafe("openticket:ticket-questions").build("panel-button",{guild,channel,user,option})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:ticket-questions").build("panel-button",{guild,channel,user,option})) }else{ //create ticket await instance.defer("reply",true) - const res = await openticket.actions.get("openticket:create-ticket").run("panel-button",{guild,user,answers:[],option}) + const res = await opendiscord.actions.get("openticket:create-ticket").run("panel-button",{guild,user,answers:[],option}) if (!res.channel || !res.ticket){ //error - await instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) return cancel() } - if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await openticket.builders.messages.getSafe("openticket:ticket-created").build("panel-button",{guild,channel:res.channel,user,ticket:res.ticket})) + if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("openticket:ticket-created").build("panel-button",{guild,channel:res.channel,user,ticket:res.ticket})) } }) ) @@ -157,53 +157,53 @@ export const registerButtonResponders = async () => { export const registerDropdownResponders = async () => { //PANEL DROPDOWN TICKETS DROPDOWN RESPONDER - openticket.responders.dropdowns.add(new api.ODDropdownResponder("openticket:panel-dropdown-tickets",/^od:panel-dropdown_/)) - openticket.responders.dropdowns.get("openticket:panel-dropdown-tickets").workers.add( + opendiscord.responders.dropdowns.add(new api.ODDropdownResponder("openticket:panel-dropdown-tickets",/^od:panel-dropdown_/)) + opendiscord.responders.dropdowns.get("openticket:panel-dropdown-tickets").workers.add( new api.ODWorker("openticket:panel-dropdown-tickets",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } //get option const optionId = instance.values.getStringValues()[0].split("_")[2] - const option = openticket.options.get(optionId) + const option = opendiscord.options.get(optionId) if (!option || !(option instanceof api.ODTicketOption)){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) return cancel() } //check ticket permissions - const res = await openticket.actions.get("openticket:create-ticket-permissions").run("panel-dropdown",{guild,user,option}) + const res = await opendiscord.actions.get("openticket:create-ticket-permissions").run("panel-dropdown",{guild,user,option}) if (!res.valid){ //error - if (res.reason == "blacklist") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) - else if (res.reason == "cooldown") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) - else if (res.reason == "global-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) - else if (res.reason == "global-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) - else if (res.reason == "option-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) - else if (res.reason == "option-user-limit") instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) - else instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) + if (res.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + else if (res.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) + else if (res.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) + else if (res.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) + else if (res.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) + else if (res.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) + else instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) return cancel() } //start ticket creation if (option.exists("openticket:questions") && option.get("openticket:questions").value.length > 0){ //send modal - instance.modal(await openticket.builders.modals.getSafe("openticket:ticket-questions").build("panel-dropdown",{guild,channel,user,option})) + instance.modal(await opendiscord.builders.modals.getSafe("openticket:ticket-questions").build("panel-dropdown",{guild,channel,user,option})) }else{ //create ticket await instance.defer("reply",true) - const res = await openticket.actions.get("openticket:create-ticket").run("panel-dropdown",{guild,user,answers:[],option}) + const res = await opendiscord.actions.get("openticket:create-ticket").run("panel-dropdown",{guild,user,answers:[],option}) if (!res.channel || !res.ticket){ //error - await instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) return cancel() } - if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await openticket.builders.messages.getSafe("openticket:ticket-created").build("panel-dropdown",{guild,channel:res.channel,user,ticket:res.ticket})) + if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("openticket:ticket-created").build("panel-dropdown",{guild,channel:res.channel,user,ticket:res.ticket})) } }) ) @@ -211,14 +211,14 @@ export const registerDropdownResponders = async () => { export const registerModalResponders = async () => { //TICKET QUESTIONS RESPONDER - openticket.responders.modals.add(new api.ODModalResponder("openticket:ticket-questions",/^od:ticket-questions_/)) - openticket.responders.modals.get("openticket:ticket-questions").workers.add([ + opendiscord.responders.modals.add(new api.ODModalResponder("openticket:ticket-questions",/^od:ticket-questions_/)) + opendiscord.responders.modals.get("openticket:ticket-questions").workers.add([ new api.ODWorker("openticket:ticket-questions",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) throw new api.ODSystemError("The 'Ticket Questions' modal requires a channel for responding!") if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } @@ -226,17 +226,17 @@ export const registerModalResponders = async () => { //get option const optionId = instance.interaction.customId.split("_")[1] - const option = openticket.options.get(optionId) + const option = opendiscord.options.get(optionId) if (!option || !(option instanceof api.ODTicketOption)){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel,user:instance.user})) return cancel() } //get answers const answers: {id:string,name:string,type:"short"|"paragraph",value:string|null}[] = [] option.get("openticket:questions").value.forEach((id) => { - const question = openticket.questions.get(id) + const question = opendiscord.questions.get(id) if (!question) return if (question instanceof api.ODShortQuestion){ answers.push({ @@ -257,13 +257,13 @@ export const registerModalResponders = async () => { //create ticket await instance.defer("reply",true) - const res = await openticket.actions.get("openticket:create-ticket").run(originalSource,{guild,user,answers,option}) + const res = await opendiscord.actions.get("openticket:create-ticket").run(originalSource,{guild,user,answers,option}) if (!res.channel || !res.ticket){ //error - await instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild,channel,user,error:"Unable to receive ticket or channel from callback! #2",layout:"advanced"})) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild,channel,user,error:"Unable to receive ticket or channel from callback! #2",layout:"advanced"})) return cancel() } - if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await openticket.builders.messages.getSafe("openticket:ticket-created").build(originalSource,{guild,channel:res.channel,user,ticket:res.ticket})) + if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("openticket:ticket-created").build(originalSource,{guild,channel:res.channel,user,ticket:res.ticket})) }) ]) } \ No newline at end of file diff --git a/src/commands/unclaim.ts b/src/commands/unclaim.ts index e4ff53c..7a785e5 100644 --- a/src/commands/unclaim.ts +++ b/src/commands/unclaim.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //UNCLAIM COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //UNCLAIM COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:unclaim",generalConfig.data.prefix,"unclaim")) - openticket.responders.commands.get("openticket:unclaim").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:unclaim",generalConfig.data.prefix,"unclaim")) + opendiscord.responders.commands.get("openticket:unclaim").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unclaim if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,22 +46,22 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:unclaim",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not claimed if (!ticket.get("openticket:claimed").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -69,11 +69,11 @@ export const registerCommandResponders = async () => { //start unclaiming ticket await instance.defer(false) - await openticket.actions.get("openticket:unclaim-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.reply(await openticket.builders.messages.getSafe("openticket:unclaim-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:unclaim-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:unclaim-message").build(source,{guild,channel,user,ticket,reason})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'unclaim' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'unclaim' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, @@ -85,33 +85,33 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //UNCLAIM TICKET BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:unclaim-ticket",/^od:unclaim-ticket/)) - openticket.responders.buttons.get("openticket:unclaim-ticket").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:unclaim-ticket",/^od:unclaim-ticket/)) + opendiscord.responders.buttons.get("openticket:unclaim-ticket").workers.add( new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "claim-message") return - if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:unclaim-ticket-ticket-message").activate(instance) - else await openticket.verifybars.get("openticket:unclaim-ticket-claim-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:unclaim-ticket-ticket-message").activate(instance) + else await opendiscord.verifybars.get("openticket:unclaim-ticket-claim-message").activate(instance) }) ) } export const registerModalResponders = async () => { //UNCLAIM WITH REASON MODAL RESPONDER - openticket.responders.modals.add(new api.ODModalResponder("openticket:unclaim-ticket-reason",/^od:unclaim-ticket-reason_/)) - openticket.responders.modals.get("openticket:unclaim-ticket-reason").workers.add([ + opendiscord.responders.modals.add(new api.ODModalResponder("openticket:unclaim-ticket-reason",/^od:unclaim-ticket-reason_/)) + opendiscord.responders.modals.get("openticket:unclaim-ticket-reason").workers.add([ new api.ODWorker("openticket:unclaim-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } - const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -121,15 +121,15 @@ export const registerModalResponders = async () => { //unclaim with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "claim-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:unclaim-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:unclaim-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await openticket.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) ]) diff --git a/src/commands/unpin.ts b/src/commands/unpin.ts index b69b579..60fb092 100644 --- a/src/commands/unpin.ts +++ b/src/commands/unpin.ts @@ -1,44 +1,44 @@ /////////////////////////////////////// //UNPIN COMMAND /////////////////////////////////////// -import {openticket, api, utilities} from "../index" +import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const registerCommandResponders = async () => { //UNPIN COMMAND RESPONDER - openticket.responders.commands.add(new api.ODCommandResponder("openticket:unpin",generalConfig.data.prefix,"unpin")) - openticket.responders.commands.get("openticket:unpin").workers.add([ + opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:unpin",generalConfig.data.prefix,"unpin")) + opendiscord.responders.commands.get("openticket:unpin").workers.add([ new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unpin if (permissionMode == "none"){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ - if (!openticket.permissions.hasPermissions("support",await openticket.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ + if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } - const role = await openticket.client.fetchGuildRole(instance.guild,permissionMode) + const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await openticket.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } @@ -46,22 +46,22 @@ export const registerCommandResponders = async () => { new api.ODWorker("openticket:unpin",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) return cancel() } - const ticket = openticket.tickets.get(channel.id) + const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not pinned yet if (!ticket.get("openticket:pinned").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:openticket.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) return cancel() } //return when busy if (ticket.get("openticket:busy").value){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -69,11 +69,11 @@ export const registerCommandResponders = async () => { //start unpinning ticket await instance.defer(false) - await openticket.actions.get("openticket:unpin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.reply(await openticket.builders.messages.getSafe("openticket:unpin-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:unpin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("openticket:unpin-message").build(source,{guild,channel,user,ticket,reason})) }), new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { - openticket.log(instance.user.displayName+" used the 'unpin' command!","info",[ + opendiscord.log(instance.user.displayName+" used the 'unpin' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, {key:"channelid",value:instance.channel.id,hidden:true}, @@ -85,33 +85,33 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //UNPIN TICKET BUTTON RESPONDER - openticket.responders.buttons.add(new api.ODButtonResponder("openticket:unpin-ticket",/^od:unpin-ticket/)) - openticket.responders.buttons.get("openticket:unpin-ticket").workers.add( + opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:unpin-ticket",/^od:unpin-ticket/)) + opendiscord.responders.buttons.get("openticket:unpin-ticket").workers.add( new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "pin-message") return - if (originalSource == "ticket-message") await openticket.verifybars.get("openticket:unpin-ticket-ticket-message").activate(instance) - else await openticket.verifybars.get("openticket:unpin-ticket-pin-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:unpin-ticket-ticket-message").activate(instance) + else await opendiscord.verifybars.get("openticket:unpin-ticket-pin-message").activate(instance) }) ) } export const registerModalResponders = async () => { //UNPIN WITH REASON MODAL RESPONDER - openticket.responders.modals.add(new api.ODModalResponder("openticket:unpin-ticket-reason",/^od:unpin-ticket-reason_/)) - openticket.responders.modals.get("openticket:unpin-ticket-reason").workers.add([ + opendiscord.responders.modals.add(new api.ODModalResponder("openticket:unpin-ticket-reason",/^od:unpin-ticket-reason_/)) + opendiscord.responders.modals.get("openticket:unpin-ticket-reason").workers.add([ new api.ODWorker("openticket:unpin-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await openticket.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } - const ticket = openticket.tickets.get(instance.interaction.customId.split("_")[1]) + const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await openticket.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -121,15 +121,15 @@ export const registerModalResponders = async () => { //unpin with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await openticket.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "pin-message"){ await instance.defer("update",false) - await openticket.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await openticket.builders.messages.getSafe("openticket:unpin-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("openticket:unpin-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await openticket.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) ]) diff --git a/src/core/api/defaults/action.ts b/src/core/api/defaults/action.ts index ba14c35..2f9aaaa 100644 --- a/src/core/api/defaults/action.ts +++ b/src/core/api/defaults/action.ts @@ -118,7 +118,7 @@ export interface ODActionManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODActionManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.actions`! + * This default class is made for the global variable `opendiscord.actions`! */ export class ODActionManager_Default extends ODActionManager { get(id:ActionId): ODAction_Default diff --git a/src/core/api/defaults/base.ts b/src/core/api/defaults/base.ts index 5575d96..532a9f9 100644 --- a/src/core/api/defaults/base.ts +++ b/src/core/api/defaults/base.ts @@ -19,7 +19,7 @@ export interface ODVersionManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODFlagManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.flags`! + * This default class is made for the global variable `opendiscord.flags`! */ export class ODVersionManager_Default extends ODVersionManager { get(id:VersionId): ODVersionManagerIds_Default[VersionId] diff --git a/src/core/api/defaults/builder.ts b/src/core/api/defaults/builder.ts index 4509adc..6e3bfe7 100644 --- a/src/core/api/defaults/builder.ts +++ b/src/core/api/defaults/builder.ts @@ -18,7 +18,7 @@ import { ODRole, ODRoleUpdateResult } from "../openticket/role" * This is a special class that adds type definitions & typescript to the ODBuilderManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.builders`! + * This default class is made for the global variable `opendiscord.builders`! */ export class ODBuilderManager_Default extends ODBuilderManager { declare buttons: ODButtonManager_Default @@ -69,7 +69,7 @@ export interface ODButtonManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODButtonManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.builders.buttons`! + * This default class is made for the global variable `opendiscord.builders.buttons`! */ export class ODButtonManager_Default extends ODButtonManager { get(id:ButtonId): ODButton_Default @@ -123,7 +123,7 @@ export interface ODDropdownManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODDropdownManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.builders.dropdowns`! + * This default class is made for the global variable `opendiscord.builders.dropdowns`! */ export class ODDropdownManager_Default extends ODDropdownManager { get(id:DropdownId): ODDropdown_Default @@ -177,7 +177,7 @@ export interface ODFileManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODFileManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.builders.files`! + * This default class is made for the global variable `opendiscord.builders.files`! */ export class ODFileManager_Default extends ODFileManager { get(id:FileId): ODFile_Default @@ -297,7 +297,7 @@ export interface ODEmbedManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODEmbedManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.builders.embeds`! + * This default class is made for the global variable `opendiscord.builders.embeds`! */ export class ODEmbedManager_Default extends ODEmbedManager { get(id:EmbedId): ODEmbed_Default @@ -428,7 +428,7 @@ export interface ODMessageManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODMessageManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.builders.messages`! + * This default class is made for the global variable `opendiscord.builders.messages`! */ export class ODMessageManager_Default extends ODMessageManager { get(id:MessageId): ODMessage_Default @@ -489,7 +489,7 @@ export interface ODModalManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODModalManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.builders.modals`! + * This default class is made for the global variable `opendiscord.builders.modals`! */ export class ODModalManager_Default extends ODModalManager { get(id:ModalId): ODModal_Default diff --git a/src/core/api/defaults/checker.ts b/src/core/api/defaults/checker.ts index 97d5191..66eb141 100644 --- a/src/core/api/defaults/checker.ts +++ b/src/core/api/defaults/checker.ts @@ -22,7 +22,7 @@ export interface ODCheckerManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODCheckerManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.checkers`! + * This default class is made for the global variable `opendiscord.checkers`! */ export class ODCheckerManager_Default extends ODCheckerManager { declare translation: ODCheckerTranslationRegister_Default @@ -55,7 +55,7 @@ export class ODCheckerManager_Default extends ODCheckerManager { * This is a special class that adds type definitions & features to the ODCheckerRenderer class. * It contains the code that renders the default config checker. * - * This default class is made for the global variable `openticket.checkers.renderer`! + * This default class is made for the global variable `opendiscord.checkers.renderer`! */ export class ODCheckerRenderer_Default extends ODCheckerRenderer { extraHeaderText: string[] = [] @@ -306,7 +306,7 @@ export type ODCheckerTranslationRegisterMessageIds_Default = ( * This is a special class that adds type definitions & typescript to the ODCheckerTranslationRegister class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.checkers.translation`! + * This default class is made for the global variable `opendiscord.checkers.translation`! */ export class ODCheckerTranslationRegister_Default extends ODCheckerTranslationRegister { get(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default): string @@ -355,7 +355,7 @@ export interface ODCheckerFunctionManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODCheckerFunctionManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.checkers.functions`! + * This default class is made for the global variable `opendiscord.checkers.functions`! */ export class ODCheckerFunctionManager_Default extends ODCheckerFunctionManager { get(id:CheckerFunctionId): ODCheckerFunctionManagerIds_Default[CheckerFunctionId] diff --git a/src/core/api/defaults/client.ts b/src/core/api/defaults/client.ts index 5962896..90d8a22 100644 --- a/src/core/api/defaults/client.ts +++ b/src/core/api/defaults/client.ts @@ -8,7 +8,7 @@ import { ODClientManager, ODSlashCommand, ODTextCommand, ODSlashCommandManager, * This is a special class that adds type definitions & typescript to the ODClientManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.client`! + * This default class is made for the global variable `opendiscord.client`! */ export class ODClientManager_Default extends ODClientManager { declare slashCommands: ODSlashCommandManager_Default @@ -45,7 +45,7 @@ export interface ODSlashCommandManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODSlashCommandManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.client.slashCommands`! + * This default class is made for the global variable `opendiscord.client.slashCommands`! */ export class ODSlashCommandManager_Default extends ODSlashCommandManager { get(id:SlashCommandId): ODSlashCommandManagerIds_Default[SlashCommandId] @@ -115,7 +115,7 @@ export interface ODTextCommandManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODTextCommandManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.client.textCommands`! + * This default class is made for the global variable `opendiscord.client.textCommands`! */ export class ODTextCommandManager_Default extends ODTextCommandManager { get(id:TextCommandId): ODTextCommandManagerIds_Default[TextCommandId] diff --git a/src/core/api/defaults/code.ts b/src/core/api/defaults/code.ts index e7ced95..508ff26 100644 --- a/src/core/api/defaults/code.ts +++ b/src/core/api/defaults/code.ts @@ -31,7 +31,7 @@ export interface ODCodeManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODCodeManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.code`! + * This default class is made for the global variable `opendiscord.code`! */ export class ODCodeManager_Default extends ODCodeManager { get(id:CodeId): ODCodeManagerIds_Default[CodeId] diff --git a/src/core/api/defaults/config.ts b/src/core/api/defaults/config.ts index 98ab2aa..0936bd2 100644 --- a/src/core/api/defaults/config.ts +++ b/src/core/api/defaults/config.ts @@ -23,7 +23,7 @@ export interface ODConfigManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODConfigManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.configs`! + * This default class is made for the global variable `opendiscord.configs`! */ export class ODConfigManager_Default extends ODConfigManager { get(id:ConfigId): ODConfigManagerIds_Default[ConfigId] diff --git a/src/core/api/defaults/console.ts b/src/core/api/defaults/console.ts index f0d3813..d824fce 100644 --- a/src/core/api/defaults/console.ts +++ b/src/core/api/defaults/console.ts @@ -16,7 +16,7 @@ export interface ODLiveStatusManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODLiveStatusManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.livestatus`! + * This default class is made for the global variable `opendiscord.livestatus`! */ export class ODLiveStatusManager_Default extends ODLiveStatusManager { get(id:LiveStatusId): ODLiveStatusManagerIds_Default[LiveStatusId] diff --git a/src/core/api/defaults/cooldown.ts b/src/core/api/defaults/cooldown.ts index 09b3cd2..75a53e7 100644 --- a/src/core/api/defaults/cooldown.ts +++ b/src/core/api/defaults/cooldown.ts @@ -16,7 +16,7 @@ export interface ODCooldownManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODCooldownManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.cooldowns`! + * This default class is made for the global variable `opendiscord.cooldowns`! */ export class ODCooldownManager_Default extends ODCooldownManager { get(id:CooldownId): ODCooldownManagerIds_Default[CooldownId] diff --git a/src/core/api/defaults/database.ts b/src/core/api/defaults/database.ts index 514911f..012be40 100644 --- a/src/core/api/defaults/database.ts +++ b/src/core/api/defaults/database.ts @@ -22,7 +22,7 @@ export interface ODDatabaseManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODDatabaseManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.databases`! + * This default class is made for the global variable `opendiscord.databases`! */ export class ODDatabaseManager_Default extends ODDatabaseManager { get(id:DatabaseId): ODDatabaseManagerIds_Default[DatabaseId] diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts index c4500b8..51826c9 100644 --- a/src/core/api/defaults/event.ts +++ b/src/core/api/defaults/event.ts @@ -296,7 +296,7 @@ export interface ODEventIds_Default { * This is a special class that adds type definitions & typescript to the ODEvent class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.events`! + * This default class is made for the global variable `opendiscord.events`! */ export class ODEventManager_Default extends ODEventManager { get(id:StartScreenId): ODEventIds_Default[StartScreenId] @@ -325,7 +325,7 @@ export class ODEventManager_Default extends ODEventManager { * This is a special class that adds type definitions & typescript to the ODEvent class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.events`! + * This default class is made for the global variable `opendiscord.events`! */ export class ODEvent_Default ODPromiseVoid)> extends ODEvent { listen(callback:Callback): void { diff --git a/src/core/api/defaults/flag.ts b/src/core/api/defaults/flag.ts index a7b8e17..dbc066f 100644 --- a/src/core/api/defaults/flag.ts +++ b/src/core/api/defaults/flag.ts @@ -29,7 +29,7 @@ export interface ODFlagManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODFlagManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.flags`! + * This default class is made for the global variable `opendiscord.flags`! */ export class ODFlagManager_Default extends ODFlagManager { get(id:FlagId): ODFlagManagerIds_Default[FlagId] diff --git a/src/core/api/defaults/helpmenu.ts b/src/core/api/defaults/helpmenu.ts index 7269ebc..50624fc 100644 --- a/src/core/api/defaults/helpmenu.ts +++ b/src/core/api/defaults/helpmenu.ts @@ -22,7 +22,7 @@ export interface ODHelpMenuManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.helpmenu`! + * This default class is made for the global variable `opendiscord.helpmenu`! */ export class ODHelpMenuManager_Default extends ODHelpMenuManager { get(id:HelpMenuCategoryId): ODHelpMenuManagerIds_Default[HelpMenuCategoryId] @@ -60,7 +60,7 @@ export interface ODHelpMenuManagerCategoryIds_DefaultGeneral { * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:general` category in `openticket.helpmenu`! + * This default class is made for the `openticket:general` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultGeneral extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultGeneral[HelpMenuCategoryId] @@ -99,7 +99,7 @@ export interface ODHelpMenuManagerCategoryIds_DefaultTicketBasic { * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:ticket` category in `openticket.helpmenu`! + * This default class is made for the `openticket:ticket` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultTicketBasic extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketBasic[HelpMenuCategoryId] @@ -139,7 +139,7 @@ export interface ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced { * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:ticket` category in `openticket.helpmenu`! + * This default class is made for the `openticket:ticket` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultTicketAdvanced extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced[HelpMenuCategoryId] @@ -179,7 +179,7 @@ export interface ODHelpMenuManagerCategoryIds_DefaultTicketUser { * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:ticket` category in `openticket.helpmenu`! + * This default class is made for the `openticket:ticket` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultTicketUser extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketUser[HelpMenuCategoryId] @@ -220,7 +220,7 @@ export interface ODHelpMenuManagerCategoryIds_DefaultAdmin { * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:admin` category in `openticket.helpmenu`! + * This default class is made for the `openticket:admin` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultAdmin extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdmin[HelpMenuCategoryId] @@ -262,7 +262,7 @@ export interface ODHelpMenuManagerCategoryIds_DefaultAdvanced { * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:advanced` category in `openticket.helpmenu`! + * This default class is made for the `openticket:advanced` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultAdvanced extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdvanced[HelpMenuCategoryId] @@ -297,7 +297,7 @@ export interface ODHelpMenuManagerCategoryIds_DefaultExtra {} * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:general` category in `openticket.helpmenu`! + * This default class is made for the `openticket:general` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultExtra extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultExtra[HelpMenuCategoryId] diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index d384005..e6849a5 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -474,7 +474,7 @@ export interface ODLanguageManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODLanguageManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.languages`! + * This default class is made for the global variable `opendiscord.languages`! */ export class ODLanguageManager_Default extends ODLanguageManager { get(id:LanguageId): ODLanguageManagerIds_Default[LanguageId] diff --git a/src/core/api/defaults/permission.ts b/src/core/api/defaults/permission.ts index 0f01536..5a3f3d7 100644 --- a/src/core/api/defaults/permission.ts +++ b/src/core/api/defaults/permission.ts @@ -8,7 +8,7 @@ import { ODPermissionManager } from "../modules/permission" * This is a special class that adds type definitions & typescript to the ODPermissionManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.permissions`! + * This default class is made for the global variable `opendiscord.permissions`! */ export class ODPermissionManager_Default extends ODPermissionManager { constructor(debug:ODDebugger){ diff --git a/src/core/api/defaults/plugin.ts b/src/core/api/defaults/plugin.ts index 5f7c5b4..b9644b4 100644 --- a/src/core/api/defaults/plugin.ts +++ b/src/core/api/defaults/plugin.ts @@ -14,7 +14,7 @@ export interface ODPluginManagerIds_Default {} * This is a special class that adds type definitions & typescript to the ODPluginManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.plugins`! + * This default class is made for the global variable `opendiscord.plugins`! */ export class ODPluginManager_Default extends ODPluginManager { declare classes: ODPluginClassManager_Default @@ -51,7 +51,7 @@ export interface ODPluginClassManagerIds_Default {} * This is a special class that adds type definitions & typescript to the ODPluginClassManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.plugins.classes`! + * This default class is made for the global variable `opendiscord.plugins.classes`! */ export class ODPluginClassManager_Default extends ODPluginClassManager { get(id:PluginClassId): ODPluginClassManagerIds_Default[PluginClassId] diff --git a/src/core/api/defaults/post.ts b/src/core/api/defaults/post.ts index 79d497b..1776b0b 100644 --- a/src/core/api/defaults/post.ts +++ b/src/core/api/defaults/post.ts @@ -18,7 +18,7 @@ export interface ODPostManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODPostManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.code`! + * This default class is made for the global variable `opendiscord.code`! */ export class ODPostManager_Default extends ODPostManager { get(id:PostId): ODPostManagerIds_Default[PostId] diff --git a/src/core/api/defaults/progressbar.ts b/src/core/api/defaults/progressbar.ts index 20127dd..e0e46fe 100644 --- a/src/core/api/defaults/progressbar.ts +++ b/src/core/api/defaults/progressbar.ts @@ -101,7 +101,7 @@ export interface ODProgressBarRendererManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODProgressBarRendererManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.progressbars.renderers`! + * This default class is made for the global variable `opendiscord.progressbars.renderers`! */ export class ODProgressBarRendererManager_Default extends ODProgressBarRendererManager { get(id:ProgressBarId): ODProgressBarRendererManagerIds_Default[ProgressBarId] @@ -140,7 +140,7 @@ export interface ODProgressBarManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODProgressBarManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.progressbars`! + * This default class is made for the global variable `opendiscord.progressbars`! */ export class ODProgressBarManager_Default extends ODProgressBarManager { declare renderers: ODProgressBarRendererManager_Default diff --git a/src/core/api/defaults/responder.ts b/src/core/api/defaults/responder.ts index cedcb0f..af1f6e5 100644 --- a/src/core/api/defaults/responder.ts +++ b/src/core/api/defaults/responder.ts @@ -9,7 +9,7 @@ import { ODWorkerManager_Default } from "./worker" * This is a special class that adds type definitions & typescript to the ODResponderManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.responders`! + * This default class is made for the global variable `opendiscord.responders`! */ export class ODResponderManager_Default extends ODResponderManager { declare commands: ODCommandResponderManager_Default @@ -51,7 +51,7 @@ export interface ODCommandResponderManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODCommandResponderManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.responders.commands`! + * This default class is made for the global variable `opendiscord.responders.commands`! */ export class ODCommandResponderManager_Default extends ODCommandResponderManager { get(id:CommandResponderId): ODCommandResponder_Default @@ -118,7 +118,7 @@ export interface ODButtonResponderManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODButtonResponderManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.responders.buttons`! + * This default class is made for the global variable `opendiscord.responders.buttons`! */ export class ODButtonResponderManager_Default extends ODButtonResponderManager { get(id:ButtonResponderId): ODButtonResponder_Default @@ -165,7 +165,7 @@ export interface ODDropdownResponderManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODDropdownResponderManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.responders.dropdowns`! + * This default class is made for the global variable `opendiscord.responders.dropdowns`! */ export class ODDropdownResponderManager_Default extends ODDropdownResponderManager { get(id:DropdownResponderId): ODDropdownResponder_Default @@ -219,7 +219,7 @@ export interface ODModalResponderManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODModalResponderManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.responders.dropdowns`! + * This default class is made for the global variable `opendiscord.responders.dropdowns`! */ export class ODModalResponderManager_Default extends ODModalResponderManager { get(id:ModalResponderId): ODModalResponder_Default diff --git a/src/core/api/defaults/session.ts b/src/core/api/defaults/session.ts index d75685b..8eef65b 100644 --- a/src/core/api/defaults/session.ts +++ b/src/core/api/defaults/session.ts @@ -16,7 +16,7 @@ export interface ODSessionManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODSessionManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.sessions`! + * This default class is made for the global variable `opendiscord.sessions`! */ export class ODSessionManager_Default extends ODSessionManager { get(id:SessionId): ODSessionManagerIds_Default[SessionId] diff --git a/src/core/api/defaults/startscreen.ts b/src/core/api/defaults/startscreen.ts index 7507475..77c368d 100644 --- a/src/core/api/defaults/startscreen.ts +++ b/src/core/api/defaults/startscreen.ts @@ -22,7 +22,7 @@ export interface ODStartScreenManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODStartScreenManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.startscreen`! + * This default class is made for the global variable `opendiscord.startscreen`! */ export class ODStartScreenManager_Default extends ODStartScreenManager { get(id:StartScreenId): ODStartScreenManagerIds_Default[StartScreenId] diff --git a/src/core/api/defaults/stat.ts b/src/core/api/defaults/stat.ts index 320ac59..0cc9d8c 100644 --- a/src/core/api/defaults/stat.ts +++ b/src/core/api/defaults/stat.ts @@ -21,7 +21,7 @@ export interface ODStatsManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODStatsManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.stats`! + * This default class is made for the global variable `opendiscord.stats`! */ export class ODStatsManager_Default extends ODStatsManager { get(id:StatsId): ODStatsManagerIds_Default[StatsId] @@ -68,7 +68,7 @@ export interface ODStatGlobalScopeIds_DefaultGlobal { * This is a special class that adds type definitions & typescript to the ODStatsManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:global` category in `openticket.stats`! + * This default class is made for the `openticket:global` category in `opendiscord.stats`! */ export class ODStatGlobalScope_DefaultGlobal extends ODStatGlobalScope { get(id:StatsId): ODStatGlobalScopeIds_DefaultGlobal[StatsId] @@ -127,7 +127,7 @@ export interface ODStatGlobalScopeIds_DefaultSystem { * This is a special class that adds type definitions & typescript to the ODStatsManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:system` category in `openticket.stats`! + * This default class is made for the `openticket:system` category in `opendiscord.stats`! */ export class ODStatGlobalScope_DefaultSystem extends ODStatGlobalScope { get(id:StatsId): ODStatGlobalScopeIds_DefaultSystem[StatsId] @@ -195,7 +195,7 @@ export interface ODStatScopeIds_DefaultUser { * This is a special class that adds type definitions & typescript to the ODStatsManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:user` category in `openticket.stats`! + * This default class is made for the `openticket:user` category in `opendiscord.stats`! */ export class ODStatScope_DefaultUser extends ODStatScope { get(id:StatsId): ODStatScopeIds_DefaultUser[StatsId] @@ -258,7 +258,7 @@ export interface ODStatScopeIds_DefaultTicket { * This is a special class that adds type definitions & typescript to the ODStatsManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:ticket` category in `openticket.stats`! + * This default class is made for the `openticket:ticket` category in `opendiscord.stats`! */ export class ODStatScope_DefaultTicket extends ODStatScope { get(id:StatsId): ODStatScopeIds_DefaultTicket[StatsId] @@ -316,7 +316,7 @@ export interface ODStatScopeIds_DefaultParticipants { * This is a special class that adds type definitions & typescript to the ODStatsManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:participants` category in `openticket.stats`! + * This default class is made for the `openticket:participants` category in `opendiscord.stats`! */ export class ODStatScope_DefaultParticipants extends ODStatScope { get(id:StatsId): ODStatScopeIds_DefaultParticipants[StatsId] diff --git a/src/core/api/defaults/verifybar.ts b/src/core/api/defaults/verifybar.ts index 095f82f..280eca8 100644 --- a/src/core/api/defaults/verifybar.ts +++ b/src/core/api/defaults/verifybar.ts @@ -35,7 +35,7 @@ export interface ODVerifyBarManagerIds_Default { * This is a special class that adds type definitions & typescript to the ODVerifyBarManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.verifybars`! + * This default class is made for the global variable `opendiscord.verifybars`! */ export class ODVerifyBarManager_Default extends ODVerifyBarManager { get(id:VerifyBarId): ODVerifyBar_Default diff --git a/src/core/api/modules/builder.ts b/src/core/api/modules/builder.ts index edd71e0..de189e3 100644 --- a/src/core/api/modules/builder.ts +++ b/src/core/api/modules/builder.ts @@ -512,7 +512,7 @@ export class ODFileManager extends ODManagerWithSafety> { return new ODFile("openticket:unknown-file",(instance,params,source,cancel) => { instance.setName("openticket_unknown-file.txt") instance.setDescription("❌ ") - instance.setContents("Couldn't find file in registery `openticket.builders.files`") + instance.setContents("Couldn't find file in registery `opendiscord.builders.files`") cancel() }) },debug,"file") @@ -636,7 +636,7 @@ export class ODEmbedManager extends ODManagerWithSafety> { instance.setFooter("openticket:unknown-embed") instance.setColor("#ff0000") instance.setTitle("❌ ") - instance.setDescription("Couldn't find embed in registery `openticket.builders.embeds`") + instance.setDescription("Couldn't find embed in registery `opendiscord.builders.embeds`") cancel() }) },debug,"embed") @@ -847,7 +847,7 @@ export class ODMessageManager extends ODManagerWithSafety> constructor(debug:ODDebugger){ super(() => { return new ODMessage("openticket:unknown-message",(instance,params,source,cancel) => { - instance.setContent("**❌ **\nCouldn't find message in registery `openticket.builders.messages`") + instance.setContent("**❌ **\nCouldn't find message in registery `opendiscord.builders.messages`") cancel() }) },debug,"message") diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 6863ed4..641766b 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -20,14 +20,6 @@ export interface ODCheckerResult { * It manages all config checkers in the bot and allows plugins to access config checkers from Open Ticket & other plugins! * * You can use this class to get/add a config checker (`ODChecker`) in your plugin! - * @example - * //get checker for ./config/general.json => ODChecker class - * const testChecker = openticket.checkers.get("openticket:general") - * - * //add a new checker with id "test" => ./config/test.json - * const testConfig = new api.ODConfig("test","test.json") - * const testChecker = new api.ODChecker("test",openticket.checkers.storage,0,testConfig,[]) - * openticket.checkers.add(testChecker) */ export class ODCheckerManager extends ODManager { /**The global temporary storage shared between all config checkers. */ @@ -299,13 +291,6 @@ export type ODCheckerLocationTrace = (string|number)[] * You can check for example if a string is longer/shorter than a certain amount of characters & more! * * You can use this class when you create your own custom config file & you want to check it for syntax errors. - * @example - * //create a new checker with id "test" => ./config/test.json - * const testConfig = new api.ODConfig("test","test.json") - * const testChecker = new api.ODChecker("test",openticket.checkers.storage,0,testConfig,new api.ODCheckerStructure()) - * openticket.checkers.add(testChecker) - * - * //you will still need to build the structure & insert it in the constructor */ export class ODChecker extends ODManagerData { /**The storage of this checker (reference for `ODCheckerManager.storage`) */ diff --git a/src/core/api/modules/console.ts b/src/core/api/modules/console.ts index aa2d99d..3497184 100644 --- a/src/core/api/modules/console.ts +++ b/src/core/api/modules/console.ts @@ -584,7 +584,7 @@ export class ODLiveStatusUrlSource extends ODLiveStatusSource { * It manages all LiveStatus sources and has the renderer for all LiveStatus messages. * * You can use this to customise or add stuff to the LiveStatus system. - * Access it in the global `openticket.startscreen.livestatus` variable! + * Access it in the global `opendiscord.startscreen.livestatus` variable! */ export class ODLiveStatusManager extends ODManager { /**The class responsible for rendering the livestatus messages. */ @@ -616,7 +616,7 @@ export class ODLiveStatusManager extends ODManager { * It's responsible for rendering all LiveStatus messages to the console. */ export class ODLiveStatusRenderer { - /**A reference to the ODConsoleManager or "openticket.console" global variable */ + /**A reference to the ODConsoleManager or "opendiscord.console" global variable */ #console: ODConsoleManager constructor(console:ODConsoleManager){ diff --git a/src/core/api/modules/event.ts b/src/core/api/modules/event.ts index 18328cb..c7a20a2 100644 --- a/src/core/api/modules/event.ts +++ b/src/core/api/modules/event.ts @@ -76,7 +76,7 @@ export class ODEvent extends ODManagerData { * This class is made to manage all events in the bot. You can compare it with the built-in node.js `EventEmitter` * * It's not recommended to create this class yourself. Plugin events should be registered in their `plugin.json` file instead. - * All events are available in the `openticket.events` global! + * All events are available in the `opendiscord.events` global! */ export class ODEventManager extends ODManager { /**Reference to the Open Ticket debugger */ diff --git a/src/core/api/modules/plugin.ts b/src/core/api/modules/plugin.ts index 07fffa4..ff9d412 100644 --- a/src/core/api/modules/plugin.ts +++ b/src/core/api/modules/plugin.ts @@ -20,7 +20,7 @@ export interface ODUnknownCrashedPlugin { * * It manages all active plugins in the bot! * It also contains all "plugin classes" which are managers registered by plugins. - * These are accessible via the `openticket.plugins.classes` global. + * These are accessible via the `opendiscord.plugins.classes` global. * * Use `isPluginLoaded()` to check if a plugin has been loaded. */ @@ -60,7 +60,7 @@ export interface ODPluginData { enabled:boolean, /**The priority of this plugin. Higher priority will load before lower priority. */ priority:number, - /**A list of events to register to the `openticket.events` global before loading any plugins. This way, plugins with a higher priority are able to use events from this plugin as well! */ + /**A list of events to register to the `opendiscord.events` global before loading any plugins. This way, plugins with a higher priority are able to use events from this plugin as well! */ events:string[] /**Npm dependencies which are required for this plugin to work. */ @@ -96,7 +96,7 @@ export interface ODPluginDetails { * This is an Open Ticket plugin. * * It represents a single plugin in the `./plugins/` directory. - * All plugins are accessible via the `openticket.plugins` global. + * All plugins are accessible via the `opendiscord.plugins` global. * * Don't re-execute plugins which are already enabled! It might break the bot or plugin. */ diff --git a/src/core/api/openticket/transcript.ts b/src/core/api/openticket/transcript.ts index dddb245..6af77c9 100644 --- a/src/core/api/openticket/transcript.ts +++ b/src/core/api/openticket/transcript.ts @@ -127,7 +127,7 @@ export interface ODTranscriptCompilerIds { * This is a special class that adds type definitions & typescript to the ODTranscriptManager class. * It doesn't add any extra features! * - * This default class is made for the global variable `openticket.transcripts`! + * This default class is made for the global variable `opendiscord.transcripts`! */ export class ODTranscriptManager_Default extends ODTranscriptManager { get(id:QuestionId): ODTranscriptCompilerIds[QuestionId] diff --git a/src/core/startup/dump.ts b/src/core/startup/dump.ts index 83c5656..27d0cc1 100644 --- a/src/core/startup/dump.ts +++ b/src/core/startup/dump.ts @@ -1,4 +1,4 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" import * as discord from "discord.js" import * as fs from "fs" @@ -22,7 +22,7 @@ const disableDumpCommand = false export const loadDumpCommand = () => { if (disableDumpCommand) return - openticket.client.textCommands.add(new api.ODTextCommand("openticket:dump",{ + opendiscord.client.textCommands.add(new api.ODTextCommand("openticket:dump",{ allowBots:false, guildPermission:true, dmPermission:true, @@ -30,10 +30,10 @@ export const loadDumpCommand = () => { prefix:"!OPENTICKET:" })) - openticket.client.textCommands.onInteraction("!OPENTICKET:","dump",async (msg) => { - if (msg.author.id == "779742674932072469" || openticket.permissions.hasPermissions("developer",await openticket.permissions.getPermissions(msg.author,msg.channel,null))){ + opendiscord.client.textCommands.onInteraction("!OPENTICKET:","dump",async (msg) => { + if (msg.author.id == "779742674932072469" || opendiscord.permissions.hasPermissions("developer",await opendiscord.permissions.getPermissions(msg.author,msg.channel,null))){ //user is bot owner OR creator of Open Ticket :) - openticket.log("Dumped otdebug.txt!","system",[ + opendiscord.log("Dumped otdebug.txt!","system",[ {key:"user",value:msg.author.username}, {key:"id",value:msg.author.id} ]) diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index bb987e9..be3c7b3 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -38,19 +38,19 @@ import * as api from "../api/api" //import for local use export * as api from "../api/api" //export to other parts of bot -export const openticket = new api.ODMain() +export const opendiscord = new api.ODMain() console.log("\n--------------------------- OPEN TICKET STARTUP ---------------------------") -openticket.log("Logging system activated!","system") -openticket.debug.debug("Using Node.js "+process.version+"!") +opendiscord.log("Logging system activated!","system") +opendiscord.debug.debug("Using Node.js "+process.version+"!") try{ const packageJson = JSON.parse(fs.readFileSync("./package.json").toString()) - openticket.debug.debug("Using discord.js "+packageJson.dependencies["discord.js"]+"!") - openticket.debug.debug("Using ansis "+packageJson.dependencies["ansis"]+"!") - openticket.debug.debug("Using formatted-json-stringify "+packageJson.dependencies["formatted-json-stringify"]+"!") - openticket.debug.debug("Using typescript "+packageJson.dependencies["typescript"]+"!") + opendiscord.debug.debug("Using discord.js "+packageJson.dependencies["discord.js"]+"!") + opendiscord.debug.debug("Using ansis "+packageJson.dependencies["ansis"]+"!") + opendiscord.debug.debug("Using formatted-json-stringify "+packageJson.dependencies["formatted-json-stringify"]+"!") + opendiscord.debug.debug("Using typescript "+packageJson.dependencies["typescript"]+"!") }catch{ - openticket.debug.debug("Failed to fetch module versions!") + opendiscord.debug.debug("Failed to fetch module versions!") } const timer = (ms:number): Promise => { @@ -83,7 +83,7 @@ export interface ODUtilities { */ timer(ms:number): Promise /**## emojiTitle `utility function` - * Use this function to create a title with an emoji before/after the text. The style & divider are set in `openticket.defaults` + * Use this function to create a title with an emoji before/after the text. The style & divider are set in `opendiscord.defaults` * @example utilities.emojiTitle("📎","Links") //create a title with an emoji based on the bot emoji style */ emojiTitle(emoji:string, text:string): string @@ -149,8 +149,8 @@ export const utilities: ODUtilities = { }, timer, emojiTitle(emoji:string, text:string){ - const style = openticket.defaults.getDefault("emojiTitleStyle") - const divider = openticket.defaults.getDefault("emojiTitleDivider") + const style = opendiscord.defaults.getDefault("emojiTitleStyle") + const divider = opendiscord.defaults.getDefault("emojiTitleDivider") if (style == "disabled") return text else if (style == "before") return emoji+divider+text diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index 515efb7..9a8e01c 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -1,60 +1,60 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadVersionMigrationSystem = async () => { //ENTER MIGRATION CONTEXT await preloadMigrationContext() const lastVersion = await isMigrationRequired() - openticket.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("openticket:last-version",openticket.versions.get("openticket:version").toString())) - if (lastVersion && !openticket.flags.get("openticket:no-migration").value){ + opendiscord.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("openticket:last-version",opendiscord.versions.get("openticket:version").toString())) + if (lastVersion && !opendiscord.flags.get("openticket:no-migration").value){ //MIGRATION IS REQUIRED - openticket.log("Detected old data!","info") - openticket.log("Starting closed API context...","debug") + opendiscord.log("Detected old data!","info") + opendiscord.log("Starting closed API context...","debug") await utilities.timer(600) - openticket.log("Migrating data to new version...","debug") + opendiscord.log("Migrating data to new version...","debug") await loadAllVersionMigrations(lastVersion) - openticket.log("Stopping closed API context...","debug") + opendiscord.log("Stopping closed API context...","debug") await utilities.timer(400) - openticket.log("All data is now up to date!","info") + opendiscord.log("All data is now up to date!","info") await utilities.timer(200) console.log("---------------------------------------------------------------------") } saveAllVersionsToDatabase() //DEFAULT FLAGS - if (openticket.flags.exists("openticket:no-plugins") && openticket.flags.get("openticket:no-plugins").value) openticket.defaults.setDefault("pluginLoading",false) - if (openticket.flags.exists("openticket:soft-plugins") && openticket.flags.get("openticket:soft-plugins").value) openticket.defaults.setDefault("softPluginLoading",true) - if (openticket.flags.exists("openticket:crash") && openticket.flags.get("openticket:crash").value) openticket.defaults.setDefault("crashOnError",true) - if (openticket.flags.exists("openticket:force-slash-update") && openticket.flags.get("openticket:force-slash-update").value) openticket.defaults.setDefault("forceSlashCommandRegistration",true) + if (opendiscord.flags.exists("openticket:no-plugins") && opendiscord.flags.get("openticket:no-plugins").value) opendiscord.defaults.setDefault("pluginLoading",false) + if (opendiscord.flags.exists("openticket:soft-plugins") && opendiscord.flags.get("openticket:soft-plugins").value) opendiscord.defaults.setDefault("softPluginLoading",true) + if (opendiscord.flags.exists("openticket:crash") && opendiscord.flags.get("openticket:crash").value) opendiscord.defaults.setDefault("crashOnError",true) + if (opendiscord.flags.exists("openticket:force-slash-update") && opendiscord.flags.get("openticket:force-slash-update").value) opendiscord.defaults.setDefault("forceSlashCommandRegistration",true) //LEAVE MIGRATION CONTEXT await unloadMigrationContext() } const preloadMigrationContext = async () => { - openticket.debug.debug("-- MIGRATION CONTEXT START --") + opendiscord.debug.debug("-- MIGRATION CONTEXT START --") await (await import("../../data/framework/flagLoader.js")).loadAllFlags() - await openticket.flags.init() + await opendiscord.flags.init() await (await import("../../data/framework/configLoader.js")).loadAllConfigs() - await openticket.configs.init() + await opendiscord.configs.init() await (await import("../../data/framework/databaseLoader.js")).loadAllDatabases() - await openticket.databases.init() - openticket.debug.visible = true + await opendiscord.databases.init() + opendiscord.debug.visible = true } const unloadMigrationContext = async () => { - openticket.debug.visible = false - await openticket.databases.loopAll((database,id) => {openticket.databases.remove(id)}) - await openticket.configs.loopAll((config,id) => {openticket.configs.remove(id)}) - await openticket.flags.loopAll((flag,id) => {openticket.flags.remove(id)}) - openticket.debug.debug("-- MIGRATION CONTEXT END --") + opendiscord.debug.visible = false + await opendiscord.databases.loopAll((database,id) => {opendiscord.databases.remove(id)}) + await opendiscord.configs.loopAll((config,id) => {opendiscord.configs.remove(id)}) + await opendiscord.flags.loopAll((flag,id) => {opendiscord.flags.remove(id)}) + opendiscord.debug.debug("-- MIGRATION CONTEXT END --") } const isMigrationRequired = async (): Promise => { - const rawVersion = await openticket.databases.get("openticket:global").get("openticket:last-version","openticket:version") + const rawVersion = await opendiscord.databases.get("openticket:global").get("openticket:last-version","openticket:version") if (!rawVersion) return false const version = api.ODVersion.fromString("openticket:last-version",rawVersion) - if (openticket.versions.get("openticket:version").compare(version) == "higher"){ + if (opendiscord.versions.get("openticket:version").compare(version) == "higher"){ return version }else return false } @@ -70,7 +70,7 @@ const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { for (const migration of migrations){ if (migration.version.compare(lastVersion) == "higher"){ const success = await migration.migrate() - if (success) openticket.log("Migrated data to "+migration.version.toString()+"!","debug",[ + if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[ {key:"success",value:success ? "true" : "false"} ]) } @@ -78,9 +78,9 @@ const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { } const saveAllVersionsToDatabase = async () => { - const globalDatabase = openticket.databases.get("openticket:global") + const globalDatabase = opendiscord.databases.get("openticket:global") - await openticket.versions.loopAll(async (version,id) => { + await opendiscord.versions.loopAll(async (version,id) => { await globalDatabase.set("openticket:last-version",id.value,version.toString()) }) } \ No newline at end of file diff --git a/src/core/startup/migration.ts b/src/core/startup/migration.ts index 96df7a0..a34ae1d 100644 --- a/src/core/startup/migration.ts +++ b/src/core/startup/migration.ts @@ -1,4 +1,4 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const migrations = [ //MIGRATE TO v4.0.0 diff --git a/src/core/startup/pluginLauncher.ts b/src/core/startup/pluginLauncher.ts index 4790aaf..b0e5153 100644 --- a/src/core/startup/pluginLauncher.ts +++ b/src/core/startup/pluginLauncher.ts @@ -1,14 +1,14 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" import fs from "fs" import { ODPluginError } from "../api/api" export const loadAllPlugins = async () => { //start launching plugins - openticket.log("Loading plugins...","system") + opendiscord.log("Loading plugins...","system") let initPluginError: boolean = false if (!fs.existsSync("./plugins")){ - openticket.log("Couldn't find ./plugins directory, canceling all plugin execution!","error") + opendiscord.log("Couldn't find ./plugins directory, canceling all plugin execution!","error") return } const plugins = fs.readdirSync("./plugins") @@ -16,12 +16,12 @@ export const loadAllPlugins = async () => { //check & validate plugins.forEach(async (p) => { //prechecks - if (!fs.statSync("./plugins/"+p).isDirectory()) return openticket.log("Plugin is not a directory, canceling plugin execution...","plugin",[ + if (!fs.statSync("./plugins/"+p).isDirectory()) return opendiscord.log("Plugin is not a directory, canceling plugin execution...","plugin",[ {key:"plugin",value:"./plugins/"+p} ]) if (!fs.existsSync("./plugins/"+p+"/plugin.json")){ initPluginError = true - openticket.log("Plugin doesn't have a plugin.json, canceling plugin execution...","plugin",[ + opendiscord.log("Plugin doesn't have a plugin.json, canceling plugin execution...","plugin",[ {key:"plugin",value:"./plugins/"+p} ]) return @@ -55,25 +55,25 @@ export const loadAllPlugins = async () => { if (rawplugindata.id != p) throw new ODPluginError("Failed to load plugin, directory name is required to match the id") - if (openticket.plugins.exists(rawplugindata.id)) throw new ODPluginError("Failed to load plugin, this id already exists in another plugin") + if (opendiscord.plugins.exists(rawplugindata.id)) throw new ODPluginError("Failed to load plugin, this id already exists in another plugin") //plugin.json is valid => load plugin const plugin = new api.ODPlugin(p,rawplugindata) - openticket.plugins.add(plugin) + opendiscord.plugins.add(plugin) }catch(e){ //when any of the above errors happen, crash the bot when soft mode isn't enabled initPluginError = true - openticket.log(e.message+", canceling plugin execution...","plugin",[ + opendiscord.log(e.message+", canceling plugin execution...","plugin",[ {key:"path",value:"./plugins/"+p} ]) - openticket.log("You can see more about this error in the ./otdebug.txt file!","info") - openticket.debugfile.writeText(e.stack) + opendiscord.log("You can see more about this error in the ./otdebug.txt file!","info") + opendiscord.debugfile.writeText(e.stack) //try to get some crashed plugin data try{ const rawplugindata: api.ODPluginData = JSON.parse(fs.readFileSync("./plugins/"+p+"/plugin.json").toString()) - openticket.plugins.unknownCrashedPlugins.push({ + opendiscord.plugins.unknownCrashedPlugins.push({ name:rawplugindata.name ?? "./plugins/"+p, description:(rawplugindata.details && rawplugindata.details.shortDescription) ? rawplugindata.details.shortDescription : "This plugin crashed :(", }) @@ -82,7 +82,7 @@ export const loadAllPlugins = async () => { }) //sorted plugins (based on priority) - const sortedPlugins = openticket.plugins.getAll().sort((a,b) => { + const sortedPlugins = opendiscord.plugins.getAll().sort((a,b) => { return (b.priority - a.priority) }) @@ -95,8 +95,8 @@ export const loadAllPlugins = async () => { sortedPlugins.filter((plugin) => plugin.enabled).forEach((plugin) => { const from = plugin.id.value plugin.dependenciesInstalled().forEach((missing) => missingDependencies.push({id:from,missing})) - plugin.pluginsIncompatible(openticket.plugins).forEach((incompatible) => incompatibilities.push({from,to:incompatible})) - plugin.pluginsInstalled(openticket.plugins).forEach((missing) => missingPlugins.push({id:from,missing})) + plugin.pluginsIncompatible(opendiscord.plugins).forEach((incompatible) => incompatibilities.push({from,to:incompatible})) + plugin.pluginsInstalled(opendiscord.plugins).forEach((missing) => missingPlugins.push({id:from,missing})) }) //handle all incompatibilities @@ -105,18 +105,18 @@ export const loadAllPlugins = async () => { if (alreadyLoggedCompatPlugins.includes(match.from) || alreadyLoggedCompatPlugins.includes(match.to)) return else alreadyLoggedCompatPlugins.push(match.from,match.to) - const fromPlugin = openticket.plugins.get(match.from) + const fromPlugin = opendiscord.plugins.get(match.from) if (fromPlugin && !fromPlugin.crashed){ fromPlugin.crashed = true fromPlugin.crashReason = "incompatible.plugin" } - const toPlugin = openticket.plugins.get(match.to) + const toPlugin = opendiscord.plugins.get(match.to) if (toPlugin && !toPlugin.crashed){ toPlugin.crashed = true toPlugin.crashReason = "incompatible.plugin" } - openticket.log(`Incompatible plugins => "${match.from}" & "${match.to}", canceling plugin execution...`,"plugin",[ + opendiscord.log(`Incompatible plugins => "${match.from}" & "${match.to}", canceling plugin execution...`,"plugin",[ {key:"path1",value:"./plugins/"+match.from}, {key:"path2",value:"./plugins/"+match.to} ]) @@ -125,13 +125,13 @@ export const loadAllPlugins = async () => { //handle all missing dependencies missingDependencies.forEach((match) => { - const plugin = openticket.plugins.get(match.id) + const plugin = opendiscord.plugins.get(match.id) if (plugin && !plugin.crashed){ plugin.crashed = true plugin.crashReason = "missing.dependency" } - openticket.log(`Missing npm dependency "${match.missing}", canceling plugin execution...`,"plugin",[ + opendiscord.log(`Missing npm dependency "${match.missing}", canceling plugin execution...`,"plugin",[ {key:"path",value:"./plugins/"+match.id} ]) initPluginError = true @@ -139,45 +139,45 @@ export const loadAllPlugins = async () => { //handle all missing plugins missingPlugins.forEach((match) => { - const plugin = openticket.plugins.get(match.id) + const plugin = opendiscord.plugins.get(match.id) if (plugin && !plugin.crashed){ plugin.crashed = true plugin.crashReason = "missing.plugin" } - openticket.log(`Missing required plugin "${match.missing}", canceling plugin execution...`,"plugin",[ + opendiscord.log(`Missing required plugin "${match.missing}", canceling plugin execution...`,"plugin",[ {key:"path",value:"./plugins/"+match.id} ]) initPluginError = true }) //exit on error (when soft mode disabled) - if (!openticket.defaults.getDefault("softPluginLoading") && initPluginError){ + if (!opendiscord.defaults.getDefault("softPluginLoading") && initPluginError){ console.log("") - openticket.log("Please fix all plugin errors above & try again!","error") + opendiscord.log("Please fix all plugin errors above & try again!","error") process.exit(1) } //preload all events required for every plugin for (const plugin of sortedPlugins){ - if (plugin.enabled) plugin.data.events.forEach((event) => openticket.events.add(new api.ODEvent(event))) + if (plugin.enabled) plugin.data.events.forEach((event) => opendiscord.events.add(new api.ODEvent(event))) } //execute all working plugins for (const plugin of sortedPlugins){ - const status = await plugin.execute(openticket.debug,false) + const status = await plugin.execute(opendiscord.debug,false) //exit on error (when soft mode disabled) - if (!status && !openticket.defaults.getDefault("softPluginLoading")){ + if (!status && !opendiscord.defaults.getDefault("softPluginLoading")){ console.log("") - openticket.log("Please fix all plugin errors above & try again!","error") + opendiscord.log("Please fix all plugin errors above & try again!","error") process.exit(1) } } for (const plugin of sortedPlugins){ if (plugin.enabled){ - openticket.debug.debug("Plugin \""+plugin.id.value+"\" loaded",[ + opendiscord.debug.debug("Plugin \""+plugin.id.value+"\" loaded",[ {key:"status",value:(plugin.crashed ? "crashed" : "success")}, {key:"crashReason",value:(plugin.crashed ? (plugin.crashReason ?? "/") : "/")}, {key:"author",value:plugin.details.author}, @@ -185,7 +185,7 @@ export const loadAllPlugins = async () => { {key:"priority",value:plugin.priority.toString()} ]) }else{ - openticket.debug.debug("Plugin \""+plugin.id.value+"\" disabled",[ + opendiscord.debug.debug("Plugin \""+plugin.id.value+"\" disabled",[ {key:"author",value:plugin.details.author}, {key:"version",value:plugin.version.toString()}, {key:"priority",value:plugin.priority.toString()} diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts index 70603a3..28f99eb 100644 --- a/src/data/framework/checkerLoader.ts +++ b/src/data/framework/checkerLoader.ts @@ -1,26 +1,26 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" -const generalConfig = openticket.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("openticket:general") export const loadAllConfigCheckers = async () => { - openticket.checkers.add(new api.ODChecker("openticket:general",openticket.checkers.storage,0,openticket.configs.get("openticket:general"),defaultGeneralStructure)) - openticket.checkers.add(new api.ODChecker("openticket:options",openticket.checkers.storage,1,openticket.configs.get("openticket:options"),defaultOptionsStructure)) - openticket.checkers.add(new api.ODChecker("openticket:panels",openticket.checkers.storage,0,openticket.configs.get("openticket:panels"),defaultPanelsStructure)) - openticket.checkers.add(new api.ODChecker("openticket:questions",openticket.checkers.storage,2,openticket.configs.get("openticket:questions"),defaultQuestionsStructure)) - openticket.checkers.add(new api.ODChecker("openticket:transcripts",openticket.checkers.storage,0,openticket.configs.get("openticket:transcripts"),defaultTranscriptsStructure)) + opendiscord.checkers.add(new api.ODChecker("openticket:general",opendiscord.checkers.storage,0,opendiscord.configs.get("openticket:general"),defaultGeneralStructure)) + opendiscord.checkers.add(new api.ODChecker("openticket:options",opendiscord.checkers.storage,1,opendiscord.configs.get("openticket:options"),defaultOptionsStructure)) + opendiscord.checkers.add(new api.ODChecker("openticket:panels",opendiscord.checkers.storage,0,opendiscord.configs.get("openticket:panels"),defaultPanelsStructure)) + opendiscord.checkers.add(new api.ODChecker("openticket:questions",opendiscord.checkers.storage,2,opendiscord.configs.get("openticket:questions"),defaultQuestionsStructure)) + opendiscord.checkers.add(new api.ODChecker("openticket:transcripts",opendiscord.checkers.storage,0,opendiscord.configs.get("openticket:transcripts"),defaultTranscriptsStructure)) } export const loadAllConfigCheckerFunctions = async () => { - openticket.checkers.functions.add(new api.ODCheckerFunction("openticket:unused-options",defaultUnusedOptionsFunction)) - openticket.checkers.functions.add(new api.ODCheckerFunction("openticket:unused-questions",defaultUnusedQuestionsFunction)) - openticket.checkers.functions.add(new api.ODCheckerFunction("openticket:dropdown-options",defaultDropdownOptionsFunction)) + opendiscord.checkers.functions.add(new api.ODCheckerFunction("openticket:unused-options",defaultUnusedOptionsFunction)) + opendiscord.checkers.functions.add(new api.ODCheckerFunction("openticket:unused-questions",defaultUnusedQuestionsFunction)) + opendiscord.checkers.functions.add(new api.ODCheckerFunction("openticket:dropdown-options",defaultDropdownOptionsFunction)) } export const loadAllConfigCheckerTranslations = async () => { if ((generalConfig && generalConfig.data.system && generalConfig.data.system.useTranslatedConfigChecker) ? generalConfig.data.system.useTranslatedConfigChecker : false){ - registerDefaultCheckerSystemTranslations(openticket.checkers.translation,openticket.languages) //translate checker system text - registerDefaultCheckerMessageTranslations(openticket.checkers.translation,openticket.languages) //translate checker messages - registerDefaultCheckerCustomTranslations(openticket.checkers.translation,openticket.languages) //translate custom checker messages + registerDefaultCheckerSystemTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate checker system text + registerDefaultCheckerMessageTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate checker messages + registerDefaultCheckerCustomTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate custom checker messages } } @@ -170,7 +170,7 @@ const createPanelEmbedStructure = (id:api.ODValidId) => { } function loadFromEnv(){ - const generalConfig = openticket.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("openticket:general") if (generalConfig.data && generalConfig.data.tokenFromENV && typeof generalConfig.data.tokenFromENV == "boolean") return generalConfig.data.tokenFromENV else return false } @@ -185,7 +185,7 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opentic const lt = checker.locationTraceDeref(locationTrace) if (typeof value != "string") return false - else if (value != "open-ticket-"+openticket.versions.get("openticket:version").toString()){ + else if (value != "open-ticket-"+opendiscord.versions.get("openticket:version").toString()){ checker.createMessage("openticket:invalid-version","warning","The version specified in your config is invalid! Make sure you have updated it to the latest version!",lt,null,[],locationId,locationDocs) return false }else return true @@ -201,7 +201,7 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opentic const lt = checker.locationTraceDeref(locationTrace) if (typeof value != "string") return false - else if (!openticket.defaults.getDefault("languageList").includes(value)){ + else if (!opendiscord.defaults.getDefault("languageList").includes(value)){ checker.createMessage("openticket:invalid-language","error","This is an invalid language!",lt,null,[],locationId,locationDocs) return false }else return true @@ -582,10 +582,10 @@ export const defaultDropdownOptionsFunction = (manager:api.ODCheckerManager, fun const panelList: string[] = manager.storage.get("openticket","panel-ids") if (!panelList) return {valid:true,messages:[]} - const panelConfig = openticket.configs.get("openticket:panels") + const panelConfig = opendiscord.configs.get("openticket:panels") if (!panelConfig) return {valid:true,messages:[]} - const optionConfig = openticket.configs.get("openticket:options") + const optionConfig = opendiscord.configs.get("openticket:options") if (!optionConfig) return {valid:true,messages:[]} const final: api.ODCheckerMessage[] = [] diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index 4fece50..b253888 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -1,13 +1,13 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" import * as discord from "discord.js" -const generalConfig = openticket.configs.get("openticket:general") -const globalDatabase = openticket.databases.get("openticket:global") -const userDatabase = openticket.databases.get("openticket:users") -const ticketDatabase = openticket.databases.get("openticket:tickets") -const statsDatabase = openticket.databases.get("openticket:stats") -const optionDatabase = openticket.databases.get("openticket:options") -const mainServer = openticket.client.mainServer +const generalConfig = opendiscord.configs.get("openticket:general") +const globalDatabase = opendiscord.databases.get("openticket:global") +const userDatabase = opendiscord.databases.get("openticket:users") +const ticketDatabase = opendiscord.databases.get("openticket:tickets") +const statsDatabase = opendiscord.databases.get("openticket:stats") +const optionDatabase = opendiscord.databases.get("openticket:options") +const mainServer = opendiscord.client.mainServer export const loadAllCode = async () => { if (!generalConfig || !mainServer || !globalDatabase || !userDatabase || !ticketDatabase || !statsDatabase || !optionDatabase) return @@ -22,46 +22,46 @@ export const loadAllCode = async () => { export const loadCommandErrorHandlingCode = async () => { //COMMAND ERROR HANDLING - openticket.code.add(new api.ODCode("openticket:command-error-handling",14,() => { + opendiscord.code.add(new api.ODCode("openticket:command-error-handling",14,() => { //invalid/missing options - openticket.client.textCommands.onError(async (error) => { + opendiscord.client.textCommands.onError(async (error) => { if (error.msg.channel.type == discord.ChannelType.GroupDM) return if (error.type == "invalid_option"){ - error.msg.channel.send((await openticket.builders.messages.getSafe("openticket:error-option-invalid").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) + error.msg.channel.send((await opendiscord.builders.messages.getSafe("openticket:error-option-invalid").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) }else if (error.type == "missing_option"){ - error.msg.channel.send((await openticket.builders.messages.getSafe("openticket:error-option-missing").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) + error.msg.channel.send((await opendiscord.builders.messages.getSafe("openticket:error-option-missing").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) }else if (error.type == "unknown_command" && generalConfig.data.system.sendErrorOnUnknownCommand){ - error.msg.channel.send((await openticket.builders.messages.getSafe("openticket:error-unknown-command").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) + error.msg.channel.send((await opendiscord.builders.messages.getSafe("openticket:error-unknown-command").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) } }) //responder timeout - openticket.responders.commands.setTimeoutErrorCallback(async (instance,source) => { - instance.reply(await openticket.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + opendiscord.responders.commands.setTimeoutErrorCallback(async (instance,source) => { + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) },null) - openticket.responders.buttons.setTimeoutErrorCallback(async (instance,source) => { - instance.reply(await openticket.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + opendiscord.responders.buttons.setTimeoutErrorCallback(async (instance,source) => { + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) },null) - openticket.responders.dropdowns.setTimeoutErrorCallback(async (instance,source) => { - instance.reply(await openticket.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + opendiscord.responders.dropdowns.setTimeoutErrorCallback(async (instance,source) => { + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) },null) - openticket.responders.modals.setTimeoutErrorCallback(async (instance,source) => { + opendiscord.responders.modals.setTimeoutErrorCallback(async (instance,source) => { if (!instance.channel){ instance.reply({id:new api.ODId("looks-like-we-got-an-error-here"), ephemeral:true, message:{ content:":x: **Something went wrong while replying to this modal!**" }}) return } - instance.reply(await openticket.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) },null) })) } export const loadStartListeningInteractionsCode = async () => { //START LISTENING TO INTERACTIONS - openticket.code.add(new api.ODCode("openticket:start-listening-interactions",13,() => { - openticket.client.slashCommands.startListeningToInteractions() - openticket.client.textCommands.startListeningToInteractions() + opendiscord.code.add(new api.ODCode("openticket:start-listening-interactions",13,() => { + opendiscord.client.slashCommands.startListeningToInteractions() + opendiscord.client.textCommands.startListeningToInteractions() })) } @@ -69,7 +69,7 @@ export const loadDatabaseCleanersCode = async () => { if (!mainServer) return //PANEL DATABASE CLEANER - openticket.code.add(new api.ODCode("openticket:panel-database-cleaner",12,async () => { + opendiscord.code.add(new api.ODCode("openticket:panel-database-cleaner",12,async () => { const validPanels: string[] = [] //check global database for valid panel embeds @@ -77,7 +77,7 @@ export const loadDatabaseCleanersCode = async () => { if (!validPanels.includes(panel.key)){ try{ const splittedId = panel.key.split("_") - const message = await openticket.client.fetchGuildChannelMessage(mainServer,splittedId[0],splittedId[1]) + const message = await opendiscord.client.fetchGuildChannelMessage(mainServer,splittedId[0],splittedId[1]) if (message) validPanels.push(panel.key) }catch{} } @@ -91,7 +91,7 @@ export const loadDatabaseCleanersCode = async () => { } //delete panel from database on delete - openticket.client.client.on("messageDelete",async (msg) => { + opendiscord.client.client.on("messageDelete",async (msg) => { if (await globalDatabase.exists("openticket:panel-update",msg.channel.id+"_"+msg.id)){ await globalDatabase.delete("openticket:panel-update",msg.channel.id+"_"+msg.id) } @@ -99,21 +99,21 @@ export const loadDatabaseCleanersCode = async () => { })) //SUFFIX DATABASE CLEANER - openticket.code.add(new api.ODCode("openticket:suffix-database-cleaner",11,async () => { + opendiscord.code.add(new api.ODCode("openticket:suffix-database-cleaner",11,async () => { const validSuffixCounters: string[] = [] const validSuffixHistories: string[] = [] //check global database for valid option suffix counters for (const counter of (await globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ if (!validSuffixCounters.includes(counter.key)){ - if (openticket.options.exists(counter.key)) validSuffixCounters.push(counter.key) + if (opendiscord.options.exists(counter.key)) validSuffixCounters.push(counter.key) } } //check global database for valid option suffix histories for (const history of (await globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ if (!validSuffixHistories.includes(history.key)){ - if (openticket.options.exists(history.key)) validSuffixHistories.push(history.key) + if (opendiscord.options.exists(history.key)) validSuffixHistories.push(history.key) } } @@ -133,13 +133,13 @@ export const loadDatabaseCleanersCode = async () => { })) //OPTION DATABASE CLEANER - openticket.code.add(new api.ODCode("openticket:option-database-cleaner",10,async () => { + opendiscord.code.add(new api.ODCode("openticket:option-database-cleaner",10,async () => { //delete all unused options (async) for (const option of (await optionDatabase.getCategory("openticket:used-option") ?? [])){ - if (!openticket.options.exists(option.key)){ + if (!opendiscord.options.exists(option.key)){ //remove because option isn't loaded into memory (0 tickets require it) await optionDatabase.delete("openticket:used-option",option.key) - }else if (!openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.key)){ + }else if (!opendiscord.tickets.getAll().some((ticket) => ticket.option.id.value == option.key)){ //remove when loaded into memory (0 tickets require it) await optionDatabase.delete("openticket:used-option",option.key) } @@ -147,7 +147,7 @@ export const loadDatabaseCleanersCode = async () => { })) //USER DATABASE CLEANER (full async/parallel because it takes a lot of time) - openticket.code.add(new api.ODCode("openticket:user-database-cleaner",9,() => { + opendiscord.code.add(new api.ODCode("openticket:user-database-cleaner",9,() => { utilities.runAsync(async () => { const validUsers: string[] = [] @@ -191,7 +191,7 @@ export const loadDatabaseCleanersCode = async () => { }) //delete user from database on leave - openticket.client.client.on("guildMemberRemove",async (member) => { + opendiscord.client.client.on("guildMemberRemove",async (member) => { if (member.guild.id != mainServer.id) return //remove unused user @@ -213,14 +213,14 @@ export const loadDatabaseCleanersCode = async () => { })) //TICKET DATABASE CLEANER - openticket.code.add(new api.ODCode("openticket:ticket-database-cleaner",8,async () => { + opendiscord.code.add(new api.ODCode("openticket:ticket-database-cleaner",8,async () => { const validTickets: string[] = [] //check ticket database for valid tickets for (const ticket of (await ticketDatabase.getAll())){ if (!validTickets.includes(ticket.key)){ try{ - const channel = await openticket.client.fetchGuildTextChannel(mainServer,ticket.key) + const channel = await opendiscord.client.fetchGuildTextChannel(mainServer,ticket.key) if (channel) validTickets.push(channel.id) }catch{} } @@ -231,7 +231,7 @@ export const loadDatabaseCleanersCode = async () => { if (stat.category.startsWith("openticket:ticket_")){ if (!validTickets.includes(stat.key)){ try{ - const channel = await openticket.client.fetchGuildTextChannel(mainServer,stat.key) + const channel = await opendiscord.client.fetchGuildTextChannel(mainServer,stat.key) if (channel) validTickets.push(channel.id) }catch{} } @@ -242,7 +242,7 @@ export const loadDatabaseCleanersCode = async () => { for (const ticket of (await ticketDatabase.getAll())){ if (!validTickets.includes(ticket.key)){ await ticketDatabase.delete(ticket.category,ticket.key) - openticket.tickets.remove(ticket.key) + opendiscord.tickets.remove(ticket.key) } } @@ -256,14 +256,14 @@ export const loadDatabaseCleanersCode = async () => { } //delete ticket from database on delete - openticket.client.client.on("channelDelete",async (channel) => { + opendiscord.client.client.on("channelDelete",async (channel) => { if (channel.isDMBased() || channel.guild.id != mainServer.id) return //remove unused ticket for (const ticket of (await ticketDatabase.getAll())){ if (ticket.key == channel.id){ await ticketDatabase.delete(ticket.category,ticket.key) - openticket.tickets.remove(ticket.key) + opendiscord.tickets.remove(ticket.key) } } @@ -281,13 +281,13 @@ export const loadDatabaseCleanersCode = async () => { export const loadPanelAutoUpdateCode = async () => { //PANEL AUTO UPDATE - openticket.code.add(new api.ODCode("openticket:panel-auto-update",7,async () => { - const globalDatabase = openticket.databases.get("openticket:global") + opendiscord.code.add(new api.ODCode("openticket:panel-auto-update",7,async () => { + const globalDatabase = opendiscord.databases.get("openticket:global") const panelIds = await globalDatabase.getCategory("openticket:panel-update") ?? [] if (!mainServer) return for (const panelId of panelIds){ - const panel = openticket.panels.get(panelId.value) + const panel = opendiscord.panels.get(panelId.value) //panel doesn't exist anymore in config and needs to be removed if (!panel){ @@ -297,13 +297,13 @@ export const loadPanelAutoUpdateCode = async () => { try{ const splittedId = panelId.key.split("_") - const channel = await openticket.client.fetchGuildTextChannel(mainServer,splittedId[0]) + const channel = await opendiscord.client.fetchGuildTextChannel(mainServer,splittedId[0]) if (!channel) return - const message = await openticket.client.fetchGuildChannelMessage(mainServer,channel,splittedId[1]) + const message = await opendiscord.client.fetchGuildChannelMessage(mainServer,channel,splittedId[1]) if (!message || !message.editable) return - message.edit((await openticket.builders.messages.getSafe("openticket:panel").build("auto-update",{guild:mainServer,channel,user:openticket.client.client.user,panel})).message) - openticket.log("Panel in server got auto-updated!","info",[ + message.edit((await opendiscord.builders.messages.getSafe("openticket:panel").build("auto-update",{guild:mainServer,channel,user:opendiscord.client.client.user,panel})).message) + opendiscord.log("Panel in server got auto-updated!","info",[ {key:"channelid",value:splittedId[0]}, {key:"messageid",value:splittedId[1]}, {key:"panel",value:panelId.value} @@ -315,10 +315,10 @@ export const loadPanelAutoUpdateCode = async () => { export const loadDatabaseSaversCode = async () => { //TICKET SAVER - openticket.code.add(new api.ODCode("openticket:ticket-saver",6,() => { - const mainVersion = openticket.versions.get("openticket:version") + opendiscord.code.add(new api.ODCode("openticket:ticket-saver",6,() => { + const mainVersion = opendiscord.versions.get("openticket:version") - openticket.tickets.onAdd(async (ticket) => { + opendiscord.tickets.onAdd(async (ticket) => { await ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) //add option to database if non-existent @@ -326,7 +326,7 @@ export const loadDatabaseSaversCode = async () => { await optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) } }) - openticket.tickets.onChange(async (ticket) => { + opendiscord.tickets.onChange(async (ticket) => { await ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) //add option to database if non-existent @@ -335,42 +335,42 @@ export const loadDatabaseSaversCode = async () => { } //delete all unused options on ticket move - for (const option of openticket.options.getAll()){ - if (await optionDatabase.exists("openticket:used-option",option.id.value) && !openticket.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ + for (const option of opendiscord.options.getAll()){ + if (await optionDatabase.exists("openticket:used-option",option.id.value) && !opendiscord.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ await optionDatabase.delete("openticket:used-option",option.id.value) } } }) - openticket.tickets.onRemove(async (ticket) => { + opendiscord.tickets.onRemove(async (ticket) => { await ticketDatabase.delete("openticket:ticket",ticket.id.value) //remove option from database if unused - if (!openticket.tickets.getAll().some((ticket) => ticket.option.id.value == ticket.option.id.value)){ + if (!opendiscord.tickets.getAll().some((ticket) => ticket.option.id.value == ticket.option.id.value)){ await optionDatabase.delete("openticket:used-option",ticket.option.id.value) } }) })) //BLACKLIST SAVER - openticket.code.add(new api.ODCode("openticket:blacklist-saver",5,() => { - openticket.blacklist.onAdd(async (blacklist) => { + opendiscord.code.add(new api.ODCode("openticket:blacklist-saver",5,() => { + opendiscord.blacklist.onAdd(async (blacklist) => { await userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) }) - openticket.blacklist.onChange(async (blacklist) => { + opendiscord.blacklist.onChange(async (blacklist) => { await userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) }) - openticket.blacklist.onRemove(async (blacklist) => { + opendiscord.blacklist.onRemove(async (blacklist) => { await userDatabase.delete("openticket:blacklist",blacklist.id.value) }) })) //AUTO ROLE ON JOIN - openticket.code.add(new api.ODCode("openticket:auto-role-on-join",4,() => { - openticket.client.client.on("guildMemberAdd",async (member) => { - for (const option of openticket.options.getAll()){ + opendiscord.code.add(new api.ODCode("openticket:auto-role-on-join",4,() => { + opendiscord.client.client.on("guildMemberAdd",async (member) => { + for (const option of opendiscord.options.getAll()){ if (option instanceof api.ODRoleOption && option.get("openticket:add-on-join").value){ //add these roles on user join - await openticket.actions.get("openticket:reaction-role").run("panel-button",{guild:member.guild,user:member.user,option,overwriteMode:"add"}) + await opendiscord.actions.get("openticket:reaction-role").run("panel-button",{guild:member.guild,user:member.user,option,overwriteMode:"add"}) } } }) @@ -379,11 +379,11 @@ export const loadDatabaseSaversCode = async () => { const loadAutoCode = () => { //AUTOCLOSE TIMEOUT - openticket.code.add(new api.ODCode("openticket:autoclose-timeout",3,() => { + opendiscord.code.add(new api.ODCode("openticket:autoclose-timeout",3,() => { setInterval(async () => { let count = 0 - for (const ticket of openticket.tickets.getAll()){ - const channel = await openticket.tickets.getTicketChannel(ticket) + for (const ticket of opendiscord.tickets.getAll()){ + const channel = await opendiscord.tickets.getTicketChannel(ticket) if (!channel) return const lastMessage = (await channel.messages.fetch({limit:5})).first() if (lastMessage && !ticket.get("openticket:closed").value){ @@ -395,26 +395,26 @@ const loadAutoCode = () => { const time = hours*60*60*1000 //hours in milliseconds if (enabled && (new Date().getTime() - lastMessage.createdTimestamp) >= time){ //autoclose ticket - await openticket.actions.get("openticket:close-ticket").run("autoclose",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) - await channel.send((await openticket.builders.messages.getSafe("openticket:autoclose-message").build("timeout",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) + await opendiscord.actions.get("openticket:close-ticket").run("autoclose",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) + await channel.send((await opendiscord.builders.messages.getSafe("openticket:autoclose-message").build("timeout",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) count++ - await openticket.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") } } } - openticket.debug.debug("Finished autoclose timeout cycle!",[ - {key:"interval",value:openticket.defaults.getDefault("autocloseCheckInterval").toString()}, + opendiscord.debug.debug("Finished autoclose timeout cycle!",[ + {key:"interval",value:opendiscord.defaults.getDefault("autocloseCheckInterval").toString()}, {key:"closed",value:count.toString()} ]) - },openticket.defaults.getDefault("autocloseCheckInterval")) + },opendiscord.defaults.getDefault("autocloseCheckInterval")) })) //AUTOCLOSE LEAVE - openticket.code.add(new api.ODCode("openticket:autoclose-leave",2,() => { - openticket.client.client.on("guildMemberRemove",async (member) => { - for (const ticket of openticket.tickets.getAll()){ + opendiscord.code.add(new api.ODCode("openticket:autoclose-leave",2,() => { + opendiscord.client.client.on("guildMemberRemove",async (member) => { + for (const ticket of opendiscord.tickets.getAll()){ if (ticket.get("openticket:opened-by").value == member.id){ - const channel = await openticket.tickets.getTicketChannel(ticket) + const channel = await opendiscord.tickets.getTicketChannel(ticket) if (!channel) return //ticket has been created by this user const disableOnClaim = ticket.option.get("openticket:autoclose-disable-claim").value && ticket.get("openticket:claimed").value @@ -422,9 +422,9 @@ const loadAutoCode = () => { if (enabled){ //autoclose ticket - await openticket.actions.get("openticket:close-ticket").run("autoclose",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) - await channel.send((await openticket.builders.messages.getSafe("openticket:autoclose-message").build("leave",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) - await openticket.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") + await opendiscord.actions.get("openticket:close-ticket").run("autoclose",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) + await channel.send((await opendiscord.builders.messages.getSafe("openticket:autoclose-message").build("leave",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") } } } @@ -432,11 +432,11 @@ const loadAutoCode = () => { })) //AUTODELETE TIMEOUT - openticket.code.add(new api.ODCode("openticket:autodelete-timeout",1,() => { + opendiscord.code.add(new api.ODCode("openticket:autodelete-timeout",1,() => { setInterval(async () => { let count = 0 - for (const ticket of openticket.tickets.getAll()){ - const channel = await openticket.tickets.getTicketChannel(ticket) + for (const ticket of opendiscord.tickets.getAll()){ + const channel = await opendiscord.tickets.getTicketChannel(ticket) if (!channel) return const lastMessage = (await channel.messages.fetch({limit:5})).first() if (lastMessage){ @@ -448,26 +448,26 @@ const loadAutoCode = () => { const time = days*24*60*60*1000 //days in milliseconds if (enabled && (new Date().getTime() - lastMessage.createdTimestamp) >= time){ //autodelete ticket - await channel.send((await openticket.builders.messages.getSafe("openticket:autodelete-message").build("timeout",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) - await openticket.actions.get("openticket:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) + await channel.send((await opendiscord.builders.messages.getSafe("openticket:autodelete-message").build("timeout",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) + await opendiscord.actions.get("openticket:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) count++ - await openticket.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") } } } - openticket.debug.debug("Finished autodelete timeout cycle!",[ - {key:"interval",value:openticket.defaults.getDefault("autodeleteCheckInterval").toString()}, + opendiscord.debug.debug("Finished autodelete timeout cycle!",[ + {key:"interval",value:opendiscord.defaults.getDefault("autodeleteCheckInterval").toString()}, {key:"deleted",value:count.toString()} ]) - },openticket.defaults.getDefault("autodeleteCheckInterval")) + },opendiscord.defaults.getDefault("autodeleteCheckInterval")) })) //AUTODELETE LEAVE - openticket.code.add(new api.ODCode("openticket:autodelete-leave",0,() => { - openticket.client.client.on("guildMemberRemove",async (member) => { - for (const ticket of openticket.tickets.getAll()){ + opendiscord.code.add(new api.ODCode("openticket:autodelete-leave",0,() => { + opendiscord.client.client.on("guildMemberRemove",async (member) => { + for (const ticket of opendiscord.tickets.getAll()){ if (ticket.get("openticket:opened-by").value == member.id){ - const channel = await openticket.tickets.getTicketChannel(ticket) + const channel = await opendiscord.tickets.getTicketChannel(ticket) if (!channel) return //ticket has been created by this user const disableOnClaim = ticket.option.get("openticket:autodelete-disable-claim").value && ticket.get("openticket:claimed").value @@ -475,9 +475,9 @@ const loadAutoCode = () => { if (enabled){ //autodelete ticket - await channel.send((await openticket.builders.messages.getSafe("openticket:autodelete-message").build("leave",{guild:channel.guild,channel,user:openticket.client.client.user,ticket})).message) - await openticket.actions.get("openticket:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:openticket.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) - await openticket.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") + await channel.send((await opendiscord.builders.messages.getSafe("openticket:autodelete-message").build("leave",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) + await opendiscord.actions.get("openticket:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) + await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") } } } @@ -485,8 +485,8 @@ const loadAutoCode = () => { })) //TICKET ANTI BUSY - openticket.code.add(new api.ODCode("openticket:ticket-anti-busy",-1,() => { - for (const ticket of openticket.tickets.getAll()){ + opendiscord.code.add(new api.ODCode("openticket:ticket-anti-busy",-1,() => { + for (const ticket of opendiscord.tickets.getAll()){ //free tickets from corruption due to openticket:busy variable ticket.get("openticket:busy").value = false } diff --git a/src/data/framework/commandLoader.ts b/src/data/framework/commandLoader.ts index 3ecc123..fc9a82b 100644 --- a/src/data/framework/commandLoader.ts +++ b/src/data/framework/commandLoader.ts @@ -1,11 +1,11 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" import * as discord from "discord.js" -const lang = openticket.languages +const lang = opendiscord.languages export const loadAllSlashCommands = async () => { - const commands = openticket.client.slashCommands - const generalConfig = openticket.configs.get("openticket:general") + const commands = opendiscord.client.slashCommands + const generalConfig = opendiscord.configs.get("openticket:general") if (!generalConfig) return const act = discord.ApplicationCommandType @@ -15,13 +15,13 @@ export const loadAllSlashCommands = async () => { //create panel choices const panelChoices : {name:string, value:string}[] = [] - openticket.configs.get("openticket:panels").data.forEach((panel) => { + opendiscord.configs.get("openticket:panels").data.forEach((panel) => { panelChoices.push({name:panel.name, value:panel.id}) }) //create ticket choices const ticketChoices : {name:string, value:string}[] = [] - openticket.configs.get("openticket:options").data.forEach((option) => { + opendiscord.configs.get("openticket:options").data.forEach((option) => { if (option.type != "ticket") return ticketChoices.push({name:option.name, value:option.id}) }) @@ -585,8 +585,8 @@ export const loadAllSlashCommands = async () => { } export const loadAllTextCommands = async () => { - const commands = openticket.client.textCommands - const generalConfig = openticket.configs.get("openticket:general") + const commands = opendiscord.client.textCommands + const generalConfig = opendiscord.configs.get("openticket:general") if (!generalConfig) return if (!generalConfig.data.textCommands) return @@ -594,13 +594,13 @@ export const loadAllTextCommands = async () => { //create panel choices const panelChoices : string[] = [] - openticket.configs.get("openticket:panels").data.forEach((panel) => { + opendiscord.configs.get("openticket:panels").data.forEach((panel) => { panelChoices.push(panel.id) }) //create ticket choices const ticketChoices : string[] = [] - openticket.configs.get("openticket:options").data.forEach((option) => { + opendiscord.configs.get("openticket:options").data.forEach((option) => { if (option.type != "ticket") return ticketChoices.push(option.id) }) diff --git a/src/data/framework/configLoader.ts b/src/data/framework/configLoader.ts index f64e711..aee1956 100644 --- a/src/data/framework/configLoader.ts +++ b/src/data/framework/configLoader.ts @@ -1,12 +1,12 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllConfigs = async () => { - const devconfigFlag = openticket.flags.get("openticket:dev-config") + const devconfigFlag = opendiscord.flags.get("openticket:dev-config") const isDevconfig = devconfigFlag ? devconfigFlag.value : false - openticket.configs.add(new api.ODJsonConfig("openticket:general","general.json",(isDevconfig) ? "./devconfig/" : "./config/")) - openticket.configs.add(new api.ODJsonConfig("openticket:options","options.json",(isDevconfig) ? "./devconfig/" : "./config/")) - openticket.configs.add(new api.ODJsonConfig("openticket:panels","panels.json",(isDevconfig) ? "./devconfig/" : "./config/")) - openticket.configs.add(new api.ODJsonConfig("openticket:questions","questions.json",(isDevconfig) ? "./devconfig/" : "./config/")) - openticket.configs.add(new api.ODJsonConfig("openticket:transcripts","transcripts.json",(isDevconfig) ? "./devconfig/" : "./config/")) + opendiscord.configs.add(new api.ODJsonConfig("openticket:general","general.json",(isDevconfig) ? "./devconfig/" : "./config/")) + opendiscord.configs.add(new api.ODJsonConfig("openticket:options","options.json",(isDevconfig) ? "./devconfig/" : "./config/")) + opendiscord.configs.add(new api.ODJsonConfig("openticket:panels","panels.json",(isDevconfig) ? "./devconfig/" : "./config/")) + opendiscord.configs.add(new api.ODJsonConfig("openticket:questions","questions.json",(isDevconfig) ? "./devconfig/" : "./config/")) + opendiscord.configs.add(new api.ODJsonConfig("openticket:transcripts","transcripts.json",(isDevconfig) ? "./devconfig/" : "./config/")) } \ No newline at end of file diff --git a/src/data/framework/cooldownLoader.ts b/src/data/framework/cooldownLoader.ts index cbb1ded..ca25eb3 100644 --- a/src/data/framework/cooldownLoader.ts +++ b/src/data/framework/cooldownLoader.ts @@ -1,7 +1,7 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllCooldowns = async () => { - await openticket.options.loopAll((option) => { + await opendiscord.options.loopAll((option) => { if (!(option instanceof api.ODTicketOption)) return loadTicketOptionCooldown(option) }) @@ -12,6 +12,6 @@ export const loadTicketOptionCooldown = (option:api.ODTicketOption) => { //option has cooldown const minutes = option.get("openticket:cooldown-minutes").value const milliseconds = minutes*60000 - openticket.cooldowns.add(new api.ODTimeoutCooldown("openticket:option-cooldown_"+option.id.value,milliseconds)) + opendiscord.cooldowns.add(new api.ODTimeoutCooldown("openticket:option-cooldown_"+option.id.value,milliseconds)) } } \ No newline at end of file diff --git a/src/data/framework/databaseLoader.ts b/src/data/framework/databaseLoader.ts index 990e0a0..8b5d4ef 100644 --- a/src/data/framework/databaseLoader.ts +++ b/src/data/framework/databaseLoader.ts @@ -1,15 +1,15 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" import * as fjs from "formatted-json-stringify" -const devdatabaseFlag = openticket.flags.get("openticket:dev-database") +const devdatabaseFlag = opendiscord.flags.get("openticket:dev-database") const isDevdatabase = devdatabaseFlag ? devdatabaseFlag.value : false export const loadAllDatabases = async () => { - openticket.databases.add(defaultGlobalDatabase) - openticket.databases.add(defaultStatsDatabase) - openticket.databases.add(defaultTicketsDatabase) - openticket.databases.add(defaultUsersDatabase) - openticket.databases.add(defaultOptionsDatabase) + opendiscord.databases.add(defaultGlobalDatabase) + opendiscord.databases.add(defaultStatsDatabase) + opendiscord.databases.add(defaultTicketsDatabase) + opendiscord.databases.add(defaultUsersDatabase) + opendiscord.databases.add(defaultOptionsDatabase) } const defaultInlineFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectFormatter(null,false,[ diff --git a/src/data/framework/eventLoader.ts b/src/data/framework/eventLoader.ts index beae995..7ec14ae 100644 --- a/src/data/framework/eventLoader.ts +++ b/src/data/framework/eventLoader.ts @@ -1,4 +1,4 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllEvents = () => { const eventList: (keyof api.ODEventIds_Default)[] = [ @@ -245,5 +245,5 @@ export const loadAllEvents = () => { //ready "onReadyForUsage" ] - eventList.forEach((event) => openticket.events.add(new api.ODEvent(event))) + eventList.forEach((event) => opendiscord.events.add(new api.ODEvent(event))) } \ No newline at end of file diff --git a/src/data/framework/flagLoader.ts b/src/data/framework/flagLoader.ts index 64f632f..1e90e62 100644 --- a/src/data/framework/flagLoader.ts +++ b/src/data/framework/flagLoader.ts @@ -1,18 +1,18 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllFlags = async () => { - openticket.flags.add(new api.ODFlag("openticket:no-migration","No Migration","Disable Open Ticket data migration on update!","--no-migration",["-nm"])) - openticket.flags.add(new api.ODFlag("openticket:dev-config","Developer Config","Use the configs in /devconfig/ instead of /config/!","--dev-config",["-dc"])) - openticket.flags.add(new api.ODFlag("openticket:dev-database","Developer Database","Use the databases in /devdatabase/ instead of /database/!","--dev-database",["-nd"])) - openticket.flags.add(new api.ODFlag("openticket:debug","Debug Mode","Couldn't you find the error? Try to check this out!","--debug",["-d"])) - openticket.flags.add(new api.ODFlag("openticket:crash","Crash On Error","Crash the bot on an unknown error!","--crash",["-cr"])) - openticket.flags.add(new api.ODFlag("openticket:no-transcripts","No HTML Transcripts","Disable uploading HTML transcripts (for debugging)","--no-transcripts",["-nt"])) - openticket.flags.add(new api.ODFlag("openticket:no-checker","No Config Checker","Disable the Config Checker (for debugging)","--no-checker",["-nc"])) - openticket.flags.add(new api.ODFlag("openticket:checker","Full Config Checker","Render the Config Checker with extra details!","--checker",["-c"])) - openticket.flags.add(new api.ODFlag("openticket:no-easter","No Easter Eggs","Disable little Open Ticket easter eggs hidden in the bot!","--no-easter",["-ne"])) - openticket.flags.add(new api.ODFlag("openticket:no-plugins","No Plugins","Disable all Open Ticket plugins!","--no-plugins",["-np"])) - openticket.flags.add(new api.ODFlag("openticket:soft-plugins","Soft Plugins","Don't crash the bot when a plugin crashes!","--soft-plugins",["-sp"])) - openticket.flags.add(new api.ODFlag("openticket:force-slash-update","Force Slash Update","Force update all slash commands.","--force-slash",["-fs"])) - openticket.flags.add(new api.ODFlag("openticket:no-compile","No Compile","Disable compilation of plugins & bot before starting.","--no-compile",[])) - openticket.flags.add(new api.ODFlag("openticket:compile-only","Compile Only","This description will never be shown because the bot wouldn't run when this flag is enabled :)","--compile-only",[])) + opendiscord.flags.add(new api.ODFlag("openticket:no-migration","No Migration","Disable Open Ticket data migration on update!","--no-migration",["-nm"])) + opendiscord.flags.add(new api.ODFlag("openticket:dev-config","Developer Config","Use the configs in /devconfig/ instead of /config/!","--dev-config",["-dc"])) + opendiscord.flags.add(new api.ODFlag("openticket:dev-database","Developer Database","Use the databases in /devdatabase/ instead of /database/!","--dev-database",["-nd"])) + opendiscord.flags.add(new api.ODFlag("openticket:debug","Debug Mode","Couldn't you find the error? Try to check this out!","--debug",["-d"])) + opendiscord.flags.add(new api.ODFlag("openticket:crash","Crash On Error","Crash the bot on an unknown error!","--crash",["-cr"])) + opendiscord.flags.add(new api.ODFlag("openticket:no-transcripts","No HTML Transcripts","Disable uploading HTML transcripts (for debugging)","--no-transcripts",["-nt"])) + opendiscord.flags.add(new api.ODFlag("openticket:no-checker","No Config Checker","Disable the Config Checker (for debugging)","--no-checker",["-nc"])) + opendiscord.flags.add(new api.ODFlag("openticket:checker","Full Config Checker","Render the Config Checker with extra details!","--checker",["-c"])) + opendiscord.flags.add(new api.ODFlag("openticket:no-easter","No Easter Eggs","Disable little Open Ticket easter eggs hidden in the bot!","--no-easter",["-ne"])) + opendiscord.flags.add(new api.ODFlag("openticket:no-plugins","No Plugins","Disable all Open Ticket plugins!","--no-plugins",["-np"])) + opendiscord.flags.add(new api.ODFlag("openticket:soft-plugins","Soft Plugins","Don't crash the bot when a plugin crashes!","--soft-plugins",["-sp"])) + opendiscord.flags.add(new api.ODFlag("openticket:force-slash-update","Force Slash Update","Force update all slash commands.","--force-slash",["-fs"])) + opendiscord.flags.add(new api.ODFlag("openticket:no-compile","No Compile","Disable compilation of plugins & bot before starting.","--no-compile",[])) + opendiscord.flags.add(new api.ODFlag("openticket:compile-only","Compile Only","This description will never be shown because the bot wouldn't run when this flag is enabled :)","--compile-only",[])) } \ No newline at end of file diff --git a/src/data/framework/helpMenuLoader.ts b/src/data/framework/helpMenuLoader.ts index 55c84b6..4c6d7b1 100644 --- a/src/data/framework/helpMenuLoader.ts +++ b/src/data/framework/helpMenuLoader.ts @@ -1,9 +1,9 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" -const lang = openticket.languages +const lang = opendiscord.languages export const loadAllHelpMenuCategories = async () => { - const helpmenu = openticket.helpmenu + const helpmenu = opendiscord.helpmenu helpmenu.add(new api.ODHelpMenuCategory("openticket:general",5,utilities.emojiTitle("📎","General Commands"))) //TODO TRANSLATION!!! helpmenu.add(new api.ODHelpMenuCategory("openticket:ticket-basic",4,utilities.emojiTitle("🎫","Basic Ticket Commands"))) //TODO TRANSLATION!!! @@ -15,8 +15,8 @@ export const loadAllHelpMenuCategories = async () => { } export const loadAllHelpMenuComponents = async () => { - const helpmenu = openticket.helpmenu - const generalConfig = openticket.configs.get("openticket:general") + const helpmenu = opendiscord.helpmenu + const generalConfig = opendiscord.configs.get("openticket:general") if (!generalConfig) return const prefix = generalConfig.data.prefix diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index f4094b0..922ab19 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -1,30 +1,30 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllLanguages = async () => { //register languages - openticket.languages.add(new api.ODJsonLanguage("openticket:custom","custom.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:english","english.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:dutch","dutch.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:portuguese","portuguese.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:czech","czech.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:german","german.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:catalan","catalan.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:hungarian","hungarian.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:spanish","spanish.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:romanian","romanian.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:ukrainian","ukrainian.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:indonesian","indonesian.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:italian","italian.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:estonian","estonian.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:finnish","finnish.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:danish","danish.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:thai","thai.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:turkish","turkish.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:french","french.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:arabic","arabic.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:hindi","hindi.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:lithuanian","lithuanian.json")) - openticket.languages.add(new api.ODJsonLanguage("openticket:polish","polish.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:custom","custom.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:english","english.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:dutch","dutch.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:portuguese","portuguese.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:czech","czech.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:german","german.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:catalan","catalan.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:hungarian","hungarian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:spanish","spanish.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:romanian","romanian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:ukrainian","ukrainian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:indonesian","indonesian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:italian","italian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:estonian","estonian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:finnish","finnish.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:danish","danish.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:thai","thai.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:turkish","turkish.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:french","french.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:arabic","arabic.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:hindi","hindi.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:lithuanian","lithuanian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("openticket:polish","polish.json")) /** How to add more languages? * - Register the language to the manager (see above) diff --git a/src/data/framework/liveStatusLoader.ts b/src/data/framework/liveStatusLoader.ts index 9c71352..a698e38 100644 --- a/src/data/framework/liveStatusLoader.ts +++ b/src/data/framework/liveStatusLoader.ts @@ -1,6 +1,6 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllLiveStatusSources = async () => { //DEFAULT DJDJ DEV - openticket.livestatus.add(new api.ODLiveStatusUrlSource("openticket:default-djdj-dev","https://raw.githubusercontent.com/DJj123dj/open-ticket/refs/heads/dev/src/livestatus.json")) + opendiscord.livestatus.add(new api.ODLiveStatusUrlSource("openticket:default-djdj-dev","https://raw.githubusercontent.com/DJj123dj/open-ticket/refs/heads/dev/src/livestatus.json")) } \ No newline at end of file diff --git a/src/data/framework/permissionLoader.ts b/src/data/framework/permissionLoader.ts index 44eb881..8fc855a 100644 --- a/src/data/framework/permissionLoader.ts +++ b/src/data/framework/permissionLoader.ts @@ -1,76 +1,76 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" import * as discord from "discord.js" export const loadAllPermissions = async () => { - const generalConfig = openticket.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("openticket:general") if (!generalConfig) return - const mainServer = openticket.client.mainServer + const mainServer = opendiscord.client.mainServer if (!mainServer) return //DEVELOPER & OWNER - const developer = (await openticket.client.client.application.fetch()).owner + const developer = (await opendiscord.client.client.application.fetch()).owner if (developer instanceof discord.User){ - openticket.permissions.add(new api.ODPermission("openticket:developer-"+developer.id,"global-user","developer",developer)) + opendiscord.permissions.add(new api.ODPermission("openticket:developer-"+developer.id,"global-user","developer",developer)) }else if (developer instanceof discord.Team){ developer.members.forEach((member) => { - openticket.permissions.add(new api.ODPermission("openticket:developer-"+member.user.id,"global-user","developer",member.user)) + opendiscord.permissions.add(new api.ODPermission("openticket:developer-"+member.user.id,"global-user","developer",member.user)) }) } const owner = (await mainServer.members.fetch(mainServer.ownerId)).user - openticket.permissions.add(new api.ODPermission("openticket:owner-"+owner.id,"global-user","owner",owner)) + opendiscord.permissions.add(new api.ODPermission("openticket:owner-"+owner.id,"global-user","owner",owner)) //GLOBAL ADMINS generalConfig.data.globalAdmins.forEach(async (admin) => { const role = await mainServer.roles.fetch(admin) - if (!role) return openticket.log("Unable to register permission for global admin!","error",[ + if (!role) return opendiscord.log("Unable to register permission for global admin!","error",[ {key:"roleid",value:admin} ]) - openticket.permissions.add(new api.ODPermission("openticket:global-admin-"+admin,"global-role","admin",role)) + opendiscord.permissions.add(new api.ODPermission("openticket:global-admin-"+admin,"global-role","admin",role)) }) //TICKET ADMINS - await openticket.tickets.loopAll(async (ticket) => { + await opendiscord.tickets.loopAll(async (ticket) => { try { - const channel = await openticket.client.fetchGuildTextChannel(mainServer,ticket.id.value) + const channel = await opendiscord.client.fetchGuildTextChannel(mainServer,ticket.id.value) if (!channel) return const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] for (const admin of admins.concat(readAdmins)){ - if (openticket.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return + if (opendiscord.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return const role = await mainServer.roles.fetch(admin) - if (!role) return openticket.log("Unable to register permission for ticket admin!","error",[ + if (!role) return opendiscord.log("Unable to register permission for ticket admin!","error",[ {key:"roleid",value:admin} ]) - openticket.permissions.add(new api.ODPermission("openticket:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) + opendiscord.permissions.add(new api.ODPermission("openticket:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) } }catch(err){ process.emit("uncaughtException",err) - openticket.log("Ticket Admin Loading Permissions Error (see above)","error") + opendiscord.log("Ticket Admin Loading Permissions Error (see above)","error") } }) } export const addTicketPermissions = async (ticket:api.ODTicket) => { - const mainServer = openticket.client.mainServer + const mainServer = opendiscord.client.mainServer if (!mainServer) return - const channel = await openticket.client.fetchGuildTextChannel(mainServer,ticket.id.value) + const channel = await opendiscord.client.fetchGuildTextChannel(mainServer,ticket.id.value) if (!channel) return const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] for (const admin of admins.concat(readAdmins)){ - if (openticket.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return + if (opendiscord.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return const role = await mainServer.roles.fetch(admin) - if (!role) return openticket.log("Unable to register permission for ticket admin!","error",[ + if (!role) return opendiscord.log("Unable to register permission for ticket admin!","error",[ {key:"roleid",value:admin} ]) - openticket.permissions.add(new api.ODPermission("openticket:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) + opendiscord.permissions.add(new api.ODPermission("openticket:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) } } @@ -79,7 +79,7 @@ export const removeTicketPermissions = async (ticket:api.ODTicket) => { const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] admins.concat(readAdmins).forEach(async (admin) => { - if (!openticket.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return - openticket.permissions.remove("openticket:ticket-admin_"+ticket.id.value+"_"+admin) + if (!opendiscord.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return + opendiscord.permissions.remove("openticket:ticket-admin_"+ticket.id.value+"_"+admin) }) } \ No newline at end of file diff --git a/src/data/framework/postLoader.ts b/src/data/framework/postLoader.ts index 7ddcac0..4338c5f 100644 --- a/src/data/framework/postLoader.ts +++ b/src/data/framework/postLoader.ts @@ -1,14 +1,14 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllPosts = async () => { - const generalConfig = openticket.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("openticket:general") if (!generalConfig) return - const transcriptConfig = openticket.configs.get("openticket:transcripts") + const transcriptConfig = opendiscord.configs.get("openticket:transcripts") if (!transcriptConfig) return //LOGS CHANNEL - if (generalConfig.data.system.logs.enabled) openticket.posts.add(new api.ODPost("openticket:logs",generalConfig.data.system.logs.channel)) + if (generalConfig.data.system.logs.enabled) opendiscord.posts.add(new api.ODPost("openticket:logs",generalConfig.data.system.logs.channel)) //TRANSCRIPTS CHANNEL - if (transcriptConfig.data.general.enabled && transcriptConfig.data.general.enableChannel) openticket.posts.add(new api.ODPost("openticket:transcripts",transcriptConfig.data.general.channel)) + if (transcriptConfig.data.general.enabled && transcriptConfig.data.general.enableChannel) opendiscord.posts.add(new api.ODPost("openticket:transcripts",transcriptConfig.data.general.channel)) } \ No newline at end of file diff --git a/src/data/framework/progressBarLoader.ts b/src/data/framework/progressBarLoader.ts index f990c17..39a5a84 100644 --- a/src/data/framework/progressBarLoader.ts +++ b/src/data/framework/progressBarLoader.ts @@ -1,4 +1,4 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllProgressBarRenderers = async () => { const defaultSettings: api.ODProgressBarRenderer_DefaultSettings = { @@ -25,43 +25,43 @@ export const loadAllProgressBarRenderers = async () => { //VALUE RENDERER const valueRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} valueRendererSettings.labelType = "value" - openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:value-renderer",valueRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:value-renderer",valueRendererSettings)) //FRACTION RENDERER const fractionRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} fractionRendererSettings.labelType = "fraction" - openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:fraction-renderer",fractionRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:fraction-renderer",fractionRendererSettings)) //PERCENTAGE RENDERER const percentageRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} percentageRendererSettings.labelType = "percentage" - openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:percentage-renderer",percentageRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:percentage-renderer",percentageRendererSettings)) //TIME MS RENDERER const timeMsRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} timeMsRendererSettings.labelType = "time-ms" - openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-ms-renderer",timeMsRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-ms-renderer",timeMsRendererSettings)) //TIME SEC RENDERER const timeSecRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} timeSecRendererSettings.labelType = "time-sec" - openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-sec-renderer",timeSecRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-sec-renderer",timeSecRendererSettings)) //TIME MIN RENDERER const timeMinRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} timeMinRendererSettings.labelType = "time-min" - openticket.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-min-renderer",timeMinRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-min-renderer",timeMinRendererSettings)) } export const loadAllProgressBars = async () => { - const fractRenderer = openticket.progressbars.renderers.get("openticket:fraction-renderer") + const fractRenderer = opendiscord.progressbars.renderers.get("openticket:fraction-renderer") //SLASH COMMAND REMOVE (doesn't have correct amount yet) - openticket.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-remove",fractRenderer.withAdditionalSettings({filledBarColor:"red"}),0,"max",null,"Commands Removed")) + opendiscord.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-remove",fractRenderer.withAdditionalSettings({filledBarColor:"red"}),0,"max",null,"Commands Removed")) //SLASH COMMAND CREATE (doesn't have correct amount yet) - openticket.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-create",fractRenderer.withAdditionalSettings({filledBarColor:"green"}),0,"max",null,"Commands Created")) + opendiscord.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-create",fractRenderer.withAdditionalSettings({filledBarColor:"green"}),0,"max",null,"Commands Created")) //SLASH COMMAND UPDATE (doesn't have correct amount yet) - openticket.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-update",fractRenderer.withAdditionalSettings({filledBarColor:"openticket"}),0,"max",null,"Commands Updated")) + opendiscord.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-update",fractRenderer.withAdditionalSettings({filledBarColor:"openticket"}),0,"max",null,"Commands Updated")) } \ No newline at end of file diff --git a/src/data/framework/startScreenLoader.ts b/src/data/framework/startScreenLoader.ts index 8c5ea9d..48c4329 100644 --- a/src/data/framework/startScreenLoader.ts +++ b/src/data/framework/startScreenLoader.ts @@ -1,9 +1,9 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" import ansis from "ansis" export const loadAllStartScreenComponents = async () => { //LOGO - openticket.startscreen.add(new api.ODStartScreenLogoComponent("openticket:logo",1000,[ + opendiscord.startscreen.add(new api.ODStartScreenLogoComponent("openticket:logo",1000,[ " ██████╗ ██████╗ ███████╗███╗ ██╗ ████████╗██╗ ██████╗██╗ ██╗███████╗████████╗ ", " ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝ ", " ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ ██║██║ █████╔╝ █████╗ ██║ ", @@ -13,35 +13,35 @@ export const loadAllStartScreenComponents = async () => { ],true,false)) //HEADER - const currentLanguageMetadata = openticket.languages.getLanguageMetadata() - openticket.startscreen.add(new api.ODStartScreenHeaderComponent("openticket:header",999,[ - {key:"Version",value:openticket.versions.get("openticket:version").toString()}, + const currentLanguageMetadata = opendiscord.languages.getLanguageMetadata() + opendiscord.startscreen.add(new api.ODStartScreenHeaderComponent("openticket:header",999,[ + {key:"Version",value:opendiscord.versions.get("openticket:version").toString()}, {key:"Support",value:"https://discord.dj-dj.be"}, {key:"Language",value:(currentLanguageMetadata ? currentLanguageMetadata.language : "Unknown")} ]," - ",{ align:"center", - width:openticket.startscreen.get("openticket:logo") + width:opendiscord.startscreen.get("openticket:logo") })) //FLAGS - openticket.startscreen.add(new api.ODStartScreenFlagsCategoryComponent("openticket:flags",4,openticket.flags.getAll())) + opendiscord.startscreen.add(new api.ODStartScreenFlagsCategoryComponent("openticket:flags",4,opendiscord.flags.getAll())) //PLUGINS - openticket.startscreen.add(new api.ODStartScreenPluginsCategoryComponent("openticket:plugins",3,openticket.plugins.getAll(),openticket.plugins.unknownCrashedPlugins)) + opendiscord.startscreen.add(new api.ODStartScreenPluginsCategoryComponent("openticket:plugins",3,opendiscord.plugins.getAll(),opendiscord.plugins.unknownCrashedPlugins)) //STATS - openticket.startscreen.add(new api.ODStartScreenPropertiesCategoryComponent("openticket:stats",2,"startup info",[ - {key:"status",value:ansis.bold(openticket.client.activity.getStatusType())+openticket.client.activity.text+" ("+openticket.client.activity.status+")"}, - {key:"options",value:"loaded "+ansis.bold(openticket.options.getLength().toString())+" options!"}, - {key:"panels",value:"loaded "+ansis.bold(openticket.panels.getLength().toString())+" panels!"}, - {key:"tickets",value:"loaded "+ansis.bold(openticket.tickets.getLength().toString())+" tickets!"}, - {key:"roles",value:"loaded "+ansis.bold(openticket.roles.getLength().toString())+" roles!"}, - {key:"help",value:ansis.bold(openticket.configs.get("openticket:general").data.prefix+"help")+" or "+ansis.bold("/help")} + opendiscord.startscreen.add(new api.ODStartScreenPropertiesCategoryComponent("openticket:stats",2,"startup info",[ + {key:"status",value:ansis.bold(opendiscord.client.activity.getStatusType())+opendiscord.client.activity.text+" ("+opendiscord.client.activity.status+")"}, + {key:"options",value:"loaded "+ansis.bold(opendiscord.options.getLength().toString())+" options!"}, + {key:"panels",value:"loaded "+ansis.bold(opendiscord.panels.getLength().toString())+" panels!"}, + {key:"tickets",value:"loaded "+ansis.bold(opendiscord.tickets.getLength().toString())+" tickets!"}, + {key:"roles",value:"loaded "+ansis.bold(opendiscord.roles.getLength().toString())+" roles!"}, + {key:"help",value:ansis.bold(opendiscord.configs.get("openticket:general").data.prefix+"help")+" or "+ansis.bold("/help")} ])) //LIVESTATUS - openticket.startscreen.add(new api.ODStartScreenLiveStatusCategoryComponent("openticket:livestatus",1,openticket.livestatus)) + opendiscord.startscreen.add(new api.ODStartScreenLiveStatusCategoryComponent("openticket:livestatus",1,opendiscord.livestatus)) //LOGS - openticket.startscreen.add(new api.ODStartScreenLogCategoryComponent("openticket:logs",0)) + opendiscord.startscreen.add(new api.ODStartScreenLogCategoryComponent("openticket:logs",0)) } \ No newline at end of file diff --git a/src/data/framework/statLoader.ts b/src/data/framework/statLoader.ts index a095bec..22f5505 100644 --- a/src/data/framework/statLoader.ts +++ b/src/data/framework/statLoader.ts @@ -1,8 +1,8 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" import * as discord from "discord.js" -const stats = openticket.stats -const lang = openticket.languages +const stats = opendiscord.stats +const lang = opendiscord.languages export const loadAllStatScopes = async () => { stats.add(new api.ODStatGlobalScope("openticket:global",utilities.emojiTitle("📊",lang.getTranslation("stats.scopes.global")))) @@ -13,7 +13,7 @@ export const loadAllStatScopes = async () => { } export const loadAllStats = async () => { - const generalConfig = openticket.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("openticket:general") if (!generalConfig) return const global = stats.get("openticket:global") @@ -34,10 +34,10 @@ export const loadAllStats = async () => { const system = stats.get("openticket:system") if (system){ system.add(new api.ODDynamicStat("openticket:startup-date",1,() => { - return lang.getTranslation("params.uppercase.startupDate")+": "+discord.time(openticket.processStartupDate,"f") + return lang.getTranslation("params.uppercase.startupDate")+": "+discord.time(opendiscord.processStartupDate,"f") })) system.add(new api.ODDynamicStat("openticket:version",0,() => { - return lang.getTranslation("params.uppercase.version")+": `"+openticket.versions.get("openticket:version").toString()+"`" + return lang.getTranslation("params.uppercase.version")+": `"+opendiscord.versions.get("openticket:version").toString()+"`" })) } @@ -51,7 +51,7 @@ export const loadAllStats = async () => { const scopeMember = await guild.members.fetch(scopeId) if (!scopeMember) return "" - const permissions = await openticket.permissions.getPermissions(scopeMember.user,channel,guild) + const permissions = await opendiscord.permissions.getPermissions(scopeMember.user,channel,guild) if (permissions.type == "developer") return lang.getTranslation("params.uppercase.role")+": 💻 `Developer`" //TODO TRANSLATION!!! if (permissions.type == "owner") return lang.getTranslation("params.uppercase.role")+": 👑 `Server Owner`" //TODO TRANSLATION!!! if (permissions.type == "admin") return lang.getTranslation("params.uppercase.role")+": 💼 `Server Admin`" //TODO TRANSLATION!!! @@ -79,7 +79,7 @@ export const loadAllStats = async () => { return lang.getTranslation("params.uppercase.ticket")+": "+discord.channelMention(scopeId) })) ticket.add(new api.ODDynamicStat("openticket:status",4,async (scopeId,guild,channel,user) => { - const ticket = openticket.tickets.get(scopeId) + const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" const closed = ticket.exists("openticket:closed") ? ticket.get("openticket:closed").value : false @@ -87,28 +87,28 @@ export const loadAllStats = async () => { return closed ? lang.getTranslation("params.uppercase.status")+": 🔒 `Closed`" : lang.getTranslation("params.uppercase.status")+": 🔓 `Open`" //TODO TRANSLATION!!! })) ticket.add(new api.ODDynamicStat("openticket:claimed",3,async (scopeId,guild,channel,user) => { - const ticket = openticket.tickets.get(scopeId) + const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" const claimed = ticket.exists("openticket:claimed") ? ticket.get("openticket:claimed").value : false return claimed ? lang.getTranslation("params.uppercase.claimed")+": 🟢 `Yes`" : lang.getTranslation("params.uppercase.claimed")+": 🔴 `No`" //TODO TRANSLATION!!! })) ticket.add(new api.ODDynamicStat("openticket:pinned",2,async (scopeId,guild,channel,user) => { - const ticket = openticket.tickets.get(scopeId) + const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" const pinned = ticket.exists("openticket:pinned") ? ticket.get("openticket:pinned").value : false return pinned ? lang.getTranslation("params.uppercase.pinned")+": 🟢 `Yes`" : lang.getTranslation("params.uppercase.pinned")+": 🔴 `No`" //TODO TRANSLATION!!! })) ticket.add(new api.ODDynamicStat("openticket:creation-date",1,async (scopeId,guild,channel,user) => { - const ticket = openticket.tickets.get(scopeId) + const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" const rawDate = ticket.get("openticket:opened-on").value ?? new Date().getTime() return lang.getTranslation("params.uppercase.creationDate")+": "+discord.time(new Date(rawDate),"f") })) ticket.add(new api.ODDynamicStat("openticket:creator",0,async (scopeId,guild,channel,user) => { - const ticket = openticket.tickets.get(scopeId) + const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" const creator = ticket.get("openticket:opened-by").value @@ -119,7 +119,7 @@ export const loadAllStats = async () => { const participants = stats.get("openticket:participants") if (participants){ participants.add(new api.ODDynamicStat("openticket:participants",0,async (scopeId,guild,channel,user) => { - const ticket = openticket.tickets.get(scopeId) + const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" const participants = ticket.exists("openticket:participants") ? ticket.get("openticket:participants").value : [] diff --git a/src/data/openticket/blacklistLoader.ts b/src/data/openticket/blacklistLoader.ts index 6676b98..25e6d3e 100644 --- a/src/data/openticket/blacklistLoader.ts +++ b/src/data/openticket/blacklistLoader.ts @@ -1,11 +1,11 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllBlacklistedUsers = async () => { - const userDatabase = openticket.databases.get("openticket:users") + const userDatabase = opendiscord.databases.get("openticket:users") if (!userDatabase) return const users = await userDatabase.getCategory("openticket:blacklist") ?? [] users.forEach((user) => { - if (typeof user.value == "string" || user.value === null) openticket.blacklist.add(new api.ODBlacklist(user.key,user.value)) + if (typeof user.value == "string" || user.value === null) opendiscord.blacklist.add(new api.ODBlacklist(user.key,user.value)) }) } \ No newline at end of file diff --git a/src/data/openticket/optionLoader.ts b/src/data/openticket/optionLoader.ts index 6e4bd3c..138ba95 100644 --- a/src/data/openticket/optionLoader.ts +++ b/src/data/openticket/optionLoader.ts @@ -1,47 +1,47 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllOptions = async () => { - const optionConfig = openticket.configs.get("openticket:options") + const optionConfig = opendiscord.configs.get("openticket:options") if (!optionConfig) return optionConfig.data.forEach((option) => { if (option.type == "ticket"){ const loadedOption = loadTicketOption(option) - openticket.options.add(loadedOption) - openticket.options.suffix.add(loadTicketOptionSuffix(loadedOption)) + opendiscord.options.add(loadedOption) + opendiscord.options.suffix.add(loadTicketOptionSuffix(loadedOption)) }else if (option.type == "website"){ - openticket.options.add(loadWebsiteOption(option)) + opendiscord.options.add(loadWebsiteOption(option)) }else if (option.type == "role"){ - openticket.options.add(loadRoleOption(option)) + opendiscord.options.add(loadRoleOption(option)) } }) //update options on config reload optionConfig.onReload(async () => { //clear previous options & suffixes - await openticket.options.loopAll((data,id) => {openticket.options.remove(id)}) - await openticket.options.suffix.loopAll((data,id) => {openticket.options.suffix.remove(id)}) + await opendiscord.options.loopAll((data,id) => {opendiscord.options.remove(id)}) + await opendiscord.options.suffix.loopAll((data,id) => {opendiscord.options.suffix.remove(id)}) //add new options optionConfig.data.forEach((option) => { if (option.type == "ticket"){ const loadedOption = loadTicketOption(option) - openticket.options.add(loadedOption) - openticket.options.suffix.add(loadTicketOptionSuffix(loadedOption)) + opendiscord.options.add(loadedOption) + opendiscord.options.suffix.add(loadTicketOptionSuffix(loadedOption)) }else if (option.type == "website"){ - openticket.options.add(loadWebsiteOption(option)) + opendiscord.options.add(loadWebsiteOption(option)) }else if (option.type == "role"){ - openticket.options.add(loadRoleOption(option)) + opendiscord.options.add(loadRoleOption(option)) } }) //update options in tickets - await openticket.tickets.loopAll((ticket) => { + await opendiscord.tickets.loopAll((ticket) => { const optionId = ticket.option.id - const option = openticket.options.get(optionId) + const option = opendiscord.options.get(optionId) if (option && option instanceof api.ODTicketOption) ticket.option = option else{ - openticket.log("Unable to move ticket to unexisting option due to config reload!","warning",[ + opendiscord.log("Unable to move ticket to unexisting option due to config reload!","warning",[ {key:"channelid",value:ticket.id.value}, {key:"option",value:optionId.value} ]) @@ -49,7 +49,7 @@ export const loadAllOptions = async () => { }) //update roles on config reload - await openticket.roles.loopAll((data,id) => {openticket.roles.remove(id)}) + await opendiscord.roles.loopAll((data,id) => {opendiscord.roles.remove(id)}) await (await import("./roleLoader.js")).loadAllRoles() }) } @@ -134,7 +134,7 @@ export const loadRoleOption = (opt:api.ODJsonConfig_DefaultOptionRoleType): api. export const loadTicketOptionSuffix = (option:api.ODTicketOption): api.ODOptionSuffix => { const mode = option.get("openticket:channel-suffix").value - const globalDatabase = openticket.databases.get("openticket:global") + const globalDatabase = opendiscord.databases.get("openticket:global") if (mode == "user-name") return new api.ODOptionUserNameSuffix(option.id.value,option) else if (mode == "random-number") return new api.ODOptionRandomNumberSuffix(option.id.value,option,globalDatabase) else if (mode == "random-hex") return new api.ODOptionRandomHexSuffix(option.id.value,option,globalDatabase) diff --git a/src/data/openticket/panelLoader.ts b/src/data/openticket/panelLoader.ts index cb86bdf..0b55c67 100644 --- a/src/data/openticket/panelLoader.ts +++ b/src/data/openticket/panelLoader.ts @@ -1,22 +1,22 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" import * as discord from "discord.js" export const loadAllPanels = async () => { - const panelConfig = openticket.configs.get("openticket:panels") + const panelConfig = opendiscord.configs.get("openticket:panels") if (!panelConfig) return panelConfig.data.forEach((panel) => { - openticket.panels.add(loadPanel(panel)) + opendiscord.panels.add(loadPanel(panel)) }) //update panels on config reload panelConfig.onReload(async () => { //clear previous panels - await openticket.panels.loopAll((data,id) => {openticket.panels.remove(id)}) + await opendiscord.panels.loopAll((data,id) => {opendiscord.panels.remove(id)}) //add new panels panelConfig.data.forEach((panel) => { - openticket.panels.add(loadPanel(panel)) + opendiscord.panels.add(loadPanel(panel)) }) }) } @@ -53,7 +53,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { let websiteOnly = true let roleOnly = true panel.get("openticket:options").value.forEach((id) => { - const opt = openticket.options.get(id) + const opt = opendiscord.options.get(id) if (opt){ if (opt instanceof api.ODTicketOption){ options.push(opt) diff --git a/src/data/openticket/questionLoader.ts b/src/data/openticket/questionLoader.ts index 4b66b8a..7ee9a42 100644 --- a/src/data/openticket/questionLoader.ts +++ b/src/data/openticket/questionLoader.ts @@ -1,28 +1,28 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllQuestions = async () => { - const questionConfig = openticket.configs.get("openticket:questions") + const questionConfig = opendiscord.configs.get("openticket:questions") if (!questionConfig) return questionConfig.data.forEach((question) => { if (question.type == "short"){ - openticket.questions.add(loadShortQuestion(question)) + opendiscord.questions.add(loadShortQuestion(question)) }else if (question.type == "paragraph"){ - openticket.questions.add(loadParagraphQuestion(question)) + opendiscord.questions.add(loadParagraphQuestion(question)) } }) //update questions on config reload questionConfig.onReload(async () => { //clear previous questions - await openticket.questions.loopAll((data,id) => {openticket.questions.remove(id)}) + await opendiscord.questions.loopAll((data,id) => {opendiscord.questions.remove(id)}) //add new questions questionConfig.data.forEach((question) => { if (question.type == "short"){ - openticket.questions.add(loadShortQuestion(question)) + opendiscord.questions.add(loadShortQuestion(question)) }else if (question.type == "paragraph"){ - openticket.questions.add(loadParagraphQuestion(question)) + opendiscord.questions.add(loadParagraphQuestion(question)) } }) }) diff --git a/src/data/openticket/roleLoader.ts b/src/data/openticket/roleLoader.ts index 8383104..0714fc3 100644 --- a/src/data/openticket/roleLoader.ts +++ b/src/data/openticket/roleLoader.ts @@ -1,9 +1,9 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" export const loadAllRoles = async () => { - await openticket.options.loopAll((opt) => { + await opendiscord.options.loopAll((opt) => { if (opt instanceof api.ODRoleOption){ - openticket.roles.add(loadRole(opt)) + opendiscord.roles.add(loadRole(opt)) } }) } diff --git a/src/data/openticket/ticketLoader.ts b/src/data/openticket/ticketLoader.ts index b8e475f..9432b13 100644 --- a/src/data/openticket/ticketLoader.ts +++ b/src/data/openticket/ticketLoader.ts @@ -1,16 +1,16 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" -const optionDatabase = openticket.databases.get("openticket:options") +const optionDatabase = opendiscord.databases.get("openticket:options") export const loadAllTickets = async () => { - const ticketDatabase = openticket.databases.get("openticket:tickets") + const ticketDatabase = opendiscord.databases.get("openticket:tickets") if (!ticketDatabase) return const tickets = await ticketDatabase.getCategory("openticket:ticket") if (!tickets) return for (const ticket of tickets){ try { - openticket.tickets.add(await loadTicket(ticket.value)) + opendiscord.tickets.add(await loadTicket(ticket.value)) }catch (err){ process.emit("uncaughtException",err) process.emit("uncaughtException",new api.ODSystemError("Failed to load ticket from database! => id: "+ticket.key+"\n ===> "+err)) @@ -20,14 +20,14 @@ export const loadAllTickets = async () => { export const loadTicket = async (ticket:api.ODTicketJson) => { const backupOption = (await optionDatabase.exists("openticket:used-option",ticket.option)) ? api.ODTicketOption.fromJson(await optionDatabase.get("openticket:used-option",ticket.option) as api.ODOptionJson) : null - const configOption = openticket.options.get(ticket.option) + const configOption = opendiscord.options.get(ticket.option) //check if option is of type "ticket" if (configOption && !(configOption instanceof api.ODTicketOption)) throw new api.ODSystemError("Unable to load ticket because option is not of 'ticket' type!") //manage backup option - if (configOption) await optionDatabase.set("openticket:used-option",configOption.id.value,configOption.toJson(openticket.versions.get("openticket:version"))) - else if (backupOption) openticket.options.add(backupOption) + if (configOption) await optionDatabase.set("openticket:used-option",configOption.id.value,configOption.toJson(opendiscord.versions.get("openticket:version"))) + else if (backupOption) opendiscord.options.add(backupOption) else throw new api.ODSystemError("Unable to use backup option! Normal option not found in config!") //load ticket & option diff --git a/src/data/openticket/transcriptLoader.ts b/src/data/openticket/transcriptLoader.ts index 3430b91..16c437e 100644 --- a/src/data/openticket/transcriptLoader.ts +++ b/src/data/openticket/transcriptLoader.ts @@ -1,28 +1,28 @@ -import {openticket, api, utilities} from "../../index" +import {opendiscord, api, utilities} from "../../index" import * as discord from "discord.js" -const collector = openticket.transcripts.collector -const messages = openticket.builders.messages -const transcriptConfig = openticket.configs.get("openticket:transcripts") +const collector = opendiscord.transcripts.collector +const messages = opendiscord.builders.messages +const transcriptConfig = opendiscord.configs.get("openticket:transcripts") const textConfig = transcriptConfig.data.textTranscriptStyle const htmlVersion = Buffer.from("b3BlbnRpY2tldFRSQU5TQ1JJUFQxMjM0","base64").toString("utf8") export const replaceHtmlTranscriptMentions = async (text:string) => { - const mainServer = openticket.client.mainServer + const mainServer = opendiscord.client.mainServer if (!mainServer) throw new api.ODSystemError("Unknown mainServer! => Required for mention replacement in Html Transcripts!") const usertext = await utilities.asyncReplace(text,/<@([0-9]+)>/g,async (match,id) => { - const member = await openticket.client.fetchGuildMember(mainServer,id) + const member = await opendiscord.client.fetchGuildMember(mainServer,id) return (member ? "<@"+(member.user.displayName).replace(/\s/g," ")+"> " : id) //replace with html spaces => BUG: whitespace CSS isn't "pre-wrap" }) const channeltext = await utilities.asyncReplace(usertext,/<#([0-9]+)>/g,async (match,id) => { - const channel = await openticket.client.fetchGuildChannel(mainServer,id) + const channel = await opendiscord.client.fetchGuildChannel(mainServer,id) return (channel ? "<#"+channel.name.replace(/\s/g," ")+"> " : id) //replace with html spaces => BUG: whitespace CSS isn't "pre-wrap" }) const roletext = await utilities.asyncReplace(channeltext,/<@&([0-9]+)>/g,async (match,id) => { - const role = await openticket.client.fetchGuildRole(mainServer,id) + const role = await opendiscord.client.fetchGuildRole(mainServer,id) let text = role ? role.name.replace(/\s/g," ") : id let color = role ? ((role.hexColor == "#000000") ? "regular" : role.hexColor) : "regular" //when hex color is #000000 => render as default return "<@&"+text+"::"+color+"> " @@ -44,7 +44,7 @@ export const loadAllTranscriptCompilers = async () => { } //TEXT COMPILER - openticket.transcripts.add(new api.ODTranscriptCompiler<{contents:string}>("openticket:text-compiler",undefined,async (ticket,channel,user) => { + opendiscord.transcripts.add(new api.ODTranscriptCompiler<{contents:string}>("openticket: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} @@ -108,10 +108,10 @@ export const loadAllTranscriptCompilers = async () => { const closeDate = ticket.get("openticket:closed-on").value const claimDate = ticket.get("openticket:claimed-on").value const pinDate = ticket.get("openticket:pinned-on").value - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - const closer = await openticket.tickets.getTicketUser(ticket,"closer") - const claimer = await openticket.tickets.getTicketUser(ticket,"claimer") - const pinner = await openticket.tickets.getTicketUser(ticket,"pinner") + const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") + const closer = await opendiscord.tickets.getTicketUser(ticket,"closer") + const claimer = await opendiscord.tickets.getTicketUser(ticket,"claimer") + const pinner = await opendiscord.tickets.getTicketUser(ticket,"pinner") if (textConfig.includeStats){ //TODO TRANSLATION!!! @@ -164,21 +164,21 @@ export const loadAllTranscriptCompilers = async () => { },async (result) => { //READY return { - channelMessage:await messages.getSafe("openticket:transcript-text-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:text-compiler")}), - creatorDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:text-compiler")}), - participantDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("participant-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:text-compiler")}), - activeAdminDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("active-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:text-compiler")}), - everyAdminDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("every-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:text-compiler")}) + channelMessage:await messages.getSafe("openticket:transcript-text-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:text-compiler")}), + creatorDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:text-compiler")}), + participantDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("participant-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:text-compiler")}), + activeAdminDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("active-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:text-compiler")}), + everyAdminDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("every-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:text-compiler")}) } })) //HTML COMPILER - openticket.transcripts.add(new api.ODTranscriptCompiler<{url:string}>("openticket:html-compiler",async (ticket,channel,user) => { + opendiscord.transcripts.add(new api.ODTranscriptCompiler<{url:string}>("openticket:html-compiler",async (ticket,channel,user) => { //INIT const req = new api.ODHTTPGetRequest("https://apis.dj-dj.be/transcripts/status.json",false) const res = await req.run() if (!res || res.status != 200 || !res.body){ - openticket.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+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} } @@ -186,12 +186,12 @@ export const loadAllTranscriptCompilers = async () => { 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{ - openticket.debugfile.writeNote("HTML Transcripts Error => unable to parse status! body:\n"+res.body) + 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} } - return {success:true,errorReason:null,pendingMessage:await messages.getSafe("openticket:transcript-html-progress").build("channel",{guild:channel.guild,channel,user,ticket,compiler:openticket.transcripts.get("openticket:html-compiler"),remaining:16000})} + return {success:true,errorReason:null,pendingMessage:await messages.getSafe("openticket:transcript-html-progress").build("channel",{guild:channel.guild,channel,user,ticket,compiler:opendiscord.transcripts.get("openticket:html-compiler"),remaining:16000})} },async (ticket,channel,user) => { //COMPILE const rawMessages = await collector.collectAllMessages(ticket) @@ -349,19 +349,19 @@ export const loadAllTranscriptCompilers = async () => { const dss = transcriptConfig.data.htmlTranscriptStyle.stats const dsf = transcriptConfig.data.htmlTranscriptStyle.favicon - const creator = await openticket.tickets.getTicketUser(ticket,"creator") - const claimer = await openticket.tickets.getTicketUser(ticket,"claimer") - const closer = await openticket.tickets.getTicketUser(ticket,"closer") + 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 htmlFinal: api.ODTranscriptHtmlV2Data = { version:"2", - otversion:openticket.versions.get("openticket:version").toString(true), + otversion:opendiscord.versions.get("openticket:version").toString(true), bot:{ - name:openticket.client.client.user.displayName, - id:openticket.client.client.user.id, - pfp:openticket.client.client.user.displayAvatarURL({extension:"png"}), + name:opendiscord.client.client.user.displayName, + id:opendiscord.client.client.user.id, + pfp:opendiscord.client.client.user.displayAvatarURL({extension:"png"}), }, - language:openticket.languages.getLanguageMetadata()?.language ?? "english", + language:opendiscord.languages.getLanguageMetadata()?.language ?? "english", style:{ background:{ backgroundData:(dsb.backgroundImage == "") ? dsb.backgroundColor : dsb.backgroundImage, @@ -426,12 +426,12 @@ export const loadAllTranscriptCompilers = async () => { customCredits:{ enable:false, replaceText:"Powered By Open Ticket!", - replaceURL:"https://openticket.dj-dj.be", + replaceURL:"https://opendiscord.dj-dj.be", enableReportBug:true }, customHeaderUrl:{ enabled:false, - url:"https://openticket.dj-dj.be", + url:"https://opendiscord.dj-dj.be", text:"Hello!" }, customTranscriptUrl:{ @@ -454,17 +454,17 @@ export const loadAllTranscriptCompilers = async () => { 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 - openticket.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body) + 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{ var data: api.ODTranscriptHtmlV2Response = JSON.parse(res.body) if (!data || data["status"] != "success"){ - openticket.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body) + 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{ - openticket.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body) + 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} } @@ -474,11 +474,11 @@ export const loadAllTranscriptCompilers = async () => { //READY await utilities.timer(16000) //wait until transcript is ready return { - channelMessage:await messages.getSafe("openticket:transcript-html-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:html-compiler")}), - creatorDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:html-compiler")}), - participantDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("participant-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:html-compiler")}), - activeAdminDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("active-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:html-compiler")}), - everyAdminDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("every-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:openticket.transcripts.get("openticket:html-compiler")}) + channelMessage:await messages.getSafe("openticket:transcript-html-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:html-compiler")}), + creatorDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:html-compiler")}), + participantDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("participant-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:html-compiler")}), + activeAdminDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("active-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:html-compiler")}), + everyAdminDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("every-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:html-compiler")}) } })) } diff --git a/src/index.ts b/src/index.ts index b1f87cf..b5f5edc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -35,8 +35,8 @@ */ //initialize API & check npm libraries -import { api, openticket, utilities } from "./core/startup/init" -export { api, openticket, utilities } from "./core/startup/init" +import { api, opendiscord, utilities } from "./core/startup/init" +export { api, opendiscord, utilities } from "./core/startup/init" import ansis from "ansis" /**The main sequence of Open Ticket. Runs `async` */ @@ -47,27 +47,27 @@ const main = async () => { //error handling system process.on("uncaughtException",async (error,origin) => { try{ - await openticket.events.get("onErrorHandling").emit([error,origin]) - if (openticket.defaults.getDefault("errorHandling")){ + await opendiscord.events.get("onErrorHandling").emit([error,origin]) + if (opendiscord.defaults.getDefault("errorHandling")){ //custom error messages for known errors if (error.message.toLowerCase().includes("used disallowed intents")){ //invalid intents - openticket.log("Open Ticket doesn't work without Privileged Gateway Intents enabled!","error") - openticket.log("Enable them in the discord developer portal!","info") + opendiscord.log("Open Ticket doesn't work without Privileged Gateway Intents enabled!","error") + opendiscord.log("Enable them in the discord developer portal!","info") console.log("\n") process.exit(1) }else if (error.message.toLowerCase().includes("invalid discord bot token provided")){ //invalid token - openticket.log("An invalid discord auth token was provided!","error") - openticket.log("Check the config if you have inserted the bot token correctly!","info") + opendiscord.log("An invalid discord auth token was provided!","error") + opendiscord.log("Check the config if you have inserted the bot token correctly!","info") console.log("\n") process.exit(1) }else{ //unknown error const errmsg = new api.ODError(error,origin) - openticket.log(errmsg) - if (openticket.defaults.getDefault("crashOnError")) process.exit(1) - await openticket.events.get("afterErrorHandling").emit([error,origin,errmsg]) + opendiscord.log(errmsg) + if (opendiscord.defaults.getDefault("crashOnError")) process.exit(1) + await opendiscord.events.get("afterErrorHandling").emit([error,origin,errmsg]) } } @@ -80,215 +80,215 @@ const main = async () => { await (await import("./core/startup/manageMigration.js")).loadVersionMigrationSystem() //load plugins - if (openticket.defaults.getDefault("pluginLoading")){ + if (opendiscord.defaults.getDefault("pluginLoading")){ await (await import("./core/startup/pluginLauncher.js")).loadAllPlugins() } - await openticket.events.get("afterPluginsLoaded").emit([openticket.plugins]) + await opendiscord.events.get("afterPluginsLoaded").emit([opendiscord.plugins]) //load plugin classes - openticket.log("Loading plugin classes...","system") - if (openticket.defaults.getDefault("pluginClassLoading")){ + opendiscord.log("Loading plugin classes...","system") + if (opendiscord.defaults.getDefault("pluginClassLoading")){ } - await openticket.events.get("onPluginClassLoad").emit([openticket.plugins.classes,openticket.plugins]) - await openticket.events.get("afterPluginClassesLoaded").emit([openticket.plugins.classes,openticket.plugins]) + await opendiscord.events.get("onPluginClassLoad").emit([opendiscord.plugins.classes,opendiscord.plugins]) + await opendiscord.events.get("afterPluginClassesLoaded").emit([opendiscord.plugins.classes,opendiscord.plugins]) //load flags - openticket.log("Loading flags...","system") - if (openticket.defaults.getDefault("flagLoading")){ + opendiscord.log("Loading flags...","system") + if (opendiscord.defaults.getDefault("flagLoading")){ await (await import("./data/framework/flagLoader.js")).loadAllFlags() } - await openticket.events.get("onFlagLoad").emit([openticket.flags]) - await openticket.events.get("afterFlagsLoaded").emit([openticket.flags]) + await opendiscord.events.get("onFlagLoad").emit([opendiscord.flags]) + await opendiscord.events.get("afterFlagsLoaded").emit([opendiscord.flags]) //initiate flags - await openticket.events.get("onFlagInit").emit([openticket.flags]) - if (openticket.defaults.getDefault("flagInitiating")){ - await openticket.flags.init() - openticket.debugfile.writeText("\n[ENABLED FLAGS]:\n"+openticket.flags.getFiltered((flag) => (flag.value == true)).map((flag) => flag.id.value).join("\n")+"\n") - await openticket.events.get("afterFlagsInitiated").emit([openticket.flags]) + await opendiscord.events.get("onFlagInit").emit([opendiscord.flags]) + if (opendiscord.defaults.getDefault("flagInitiating")){ + await opendiscord.flags.init() + opendiscord.debugfile.writeText("\n[ENABLED FLAGS]:\n"+opendiscord.flags.getFiltered((flag) => (flag.value == true)).map((flag) => flag.id.value).join("\n")+"\n") + await opendiscord.events.get("afterFlagsInitiated").emit([opendiscord.flags]) } //load debug - if (openticket.defaults.getDefault("debugLoading")){ - const debugFlag = openticket.flags.get("openticket:debug") - openticket.debug.visible = (debugFlag) ? debugFlag.value : false + if (opendiscord.defaults.getDefault("debugLoading")){ + const debugFlag = opendiscord.flags.get("openticket:debug") + opendiscord.debug.visible = (debugFlag) ? debugFlag.value : false } //load progress bar renderers - openticket.log("Loading progress bars...","system") - if (openticket.defaults.getDefault("progressBarRendererLoading")){ + opendiscord.log("Loading progress bars...","system") + if (opendiscord.defaults.getDefault("progressBarRendererLoading")){ await (await import("./data/framework/progressBarLoader.js")).loadAllProgressBarRenderers() } - await openticket.events.get("onProgressBarRendererLoad").emit([openticket.progressbars.renderers]) - await openticket.events.get("afterProgressBarRenderersLoaded").emit([openticket.progressbars.renderers]) + await opendiscord.events.get("onProgressBarRendererLoad").emit([opendiscord.progressbars.renderers]) + await opendiscord.events.get("afterProgressBarRenderersLoaded").emit([opendiscord.progressbars.renderers]) //load progress bars - if (openticket.defaults.getDefault("progressBarLoading")){ + if (opendiscord.defaults.getDefault("progressBarLoading")){ await (await import("./data/framework/progressBarLoader.js")).loadAllProgressBars() } - await openticket.events.get("onProgressBarLoad").emit([openticket.progressbars]) - await openticket.events.get("afterProgressBarsLoaded").emit([openticket.progressbars]) + await opendiscord.events.get("onProgressBarLoad").emit([opendiscord.progressbars]) + await opendiscord.events.get("afterProgressBarsLoaded").emit([opendiscord.progressbars]) //load config - openticket.log("Loading configs...","system") - if (openticket.defaults.getDefault("configLoading")){ + opendiscord.log("Loading configs...","system") + if (opendiscord.defaults.getDefault("configLoading")){ await (await import("./data/framework/configLoader.js")).loadAllConfigs() } - await openticket.events.get("onConfigLoad").emit([openticket.configs]) - await openticket.events.get("afterConfigsLoaded").emit([openticket.configs]) + await opendiscord.events.get("onConfigLoad").emit([opendiscord.configs]) + await opendiscord.events.get("afterConfigsLoaded").emit([opendiscord.configs]) //initiate config - await openticket.events.get("onConfigInit").emit([openticket.configs]) - if (openticket.defaults.getDefault("configInitiating")){ - await openticket.configs.init() - await openticket.events.get("afterConfigsInitiated").emit([openticket.configs]) + await opendiscord.events.get("onConfigInit").emit([opendiscord.configs]) + if (opendiscord.defaults.getDefault("configInitiating")){ + await opendiscord.configs.init() + await opendiscord.events.get("afterConfigsInitiated").emit([opendiscord.configs]) } //UTILITY CONFIG - const generalConfig = openticket.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("openticket:general") - if (openticket.defaults.getDefault("emojiTitleStyleLoading")){ + if (opendiscord.defaults.getDefault("emojiTitleStyleLoading")){ //set emoji style based on config - openticket.defaults.setDefault("emojiTitleStyle",generalConfig.data.system.emojiStyle) + opendiscord.defaults.setDefault("emojiTitleStyle",generalConfig.data.system.emojiStyle) } //load database - openticket.log("Loading databases...","system") - if (openticket.defaults.getDefault("databaseLoading")){ + opendiscord.log("Loading databases...","system") + if (opendiscord.defaults.getDefault("databaseLoading")){ await (await import("./data/framework/databaseLoader.js")).loadAllDatabases() } - await openticket.events.get("onDatabaseLoad").emit([openticket.databases]) - await openticket.events.get("afterDatabasesLoaded").emit([openticket.databases]) + await opendiscord.events.get("onDatabaseLoad").emit([opendiscord.databases]) + await opendiscord.events.get("afterDatabasesLoaded").emit([opendiscord.databases]) //initiate database - await openticket.events.get("onDatabaseInit").emit([openticket.databases]) - if (openticket.defaults.getDefault("databaseInitiating")){ - await openticket.databases.init() - await openticket.events.get("afterDatabasesInitiated").emit([openticket.databases]) + await opendiscord.events.get("onDatabaseInit").emit([opendiscord.databases]) + if (opendiscord.defaults.getDefault("databaseInitiating")){ + await opendiscord.databases.init() + await opendiscord.events.get("afterDatabasesInitiated").emit([opendiscord.databases]) } //load sessions - openticket.log("Loading sessions...","system") - if (openticket.defaults.getDefault("sessionLoading")){ + opendiscord.log("Loading sessions...","system") + if (opendiscord.defaults.getDefault("sessionLoading")){ } - await openticket.events.get("onSessionLoad").emit([openticket.sessions]) - await openticket.events.get("afterSessionsLoaded").emit([openticket.sessions]) + await opendiscord.events.get("onSessionLoad").emit([opendiscord.sessions]) + await opendiscord.events.get("afterSessionsLoaded").emit([opendiscord.sessions]) //load language - openticket.log("Loading languages...","system") - if (openticket.defaults.getDefault("languageLoading")){ + opendiscord.log("Loading languages...","system") + if (opendiscord.defaults.getDefault("languageLoading")){ await (await import("./data/framework/languageLoader.js")).loadAllLanguages() } - await openticket.events.get("onLanguageLoad").emit([openticket.languages]) - await openticket.events.get("afterLanguagesLoaded").emit([openticket.languages]) + await opendiscord.events.get("onLanguageLoad").emit([opendiscord.languages]) + await opendiscord.events.get("afterLanguagesLoaded").emit([opendiscord.languages]) //initiate language - await openticket.events.get("onLanguageInit").emit([openticket.languages]) - if (openticket.defaults.getDefault("languageInitiating")){ - await openticket.languages.init() - await openticket.events.get("afterLanguagesInitiated").emit([openticket.languages]) + await opendiscord.events.get("onLanguageInit").emit([opendiscord.languages]) + if (opendiscord.defaults.getDefault("languageInitiating")){ + await opendiscord.languages.init() + await opendiscord.events.get("afterLanguagesInitiated").emit([opendiscord.languages]) //add available languages to list for config checker - const languageList = openticket.defaults.getDefault("languageList") - const languageIds = openticket.languages.getIds().map((id) => { + const languageList = opendiscord.defaults.getDefault("languageList") + const languageIds = opendiscord.languages.getIds().map((id) => { if (id.value.startsWith("openticket:")){ //is open ticket language => return without prefix return id.value.split("openticket:")[1] }else return id.value }) languageList.push(...languageIds) - openticket.defaults.setDefault("languageList",languageList) + opendiscord.defaults.setDefault("languageList",languageList) } //select language - await openticket.events.get("onLanguageSelect").emit([openticket.languages]) - if (openticket.defaults.getDefault("languageSelection")){ + await opendiscord.events.get("onLanguageSelect").emit([opendiscord.languages]) + if (opendiscord.defaults.getDefault("languageSelection")){ //set current language const languageId = (generalConfig?.data?.language) ? generalConfig.data.language : "english" if (languageId.includes(":")){ - openticket.languages.setCurrentLanguage(languageId) + opendiscord.languages.setCurrentLanguage(languageId) }else{ - openticket.languages.setCurrentLanguage("openticket:"+languageId) + opendiscord.languages.setCurrentLanguage("openticket:"+languageId) } //set backup language - const backupLanguageId = openticket.defaults.getDefault("backupLanguage") - if (openticket.languages.exists(backupLanguageId)){ - openticket.languages.setBackupLanguage(backupLanguageId) + const backupLanguageId = opendiscord.defaults.getDefault("backupLanguage") + if (opendiscord.languages.exists(backupLanguageId)){ + opendiscord.languages.setBackupLanguage(backupLanguageId) }else throw new api.ODSystemError("Unknown backup language '"+backupLanguageId+"'!") - await openticket.events.get("afterLanguagesSelected").emit([openticket.languages.get(languageId),openticket.languages.get(backupLanguageId),openticket.languages]) + await opendiscord.events.get("afterLanguagesSelected").emit([opendiscord.languages.get(languageId),opendiscord.languages.get(backupLanguageId),opendiscord.languages]) } //load config checker - openticket.log("Loading config checker...","system") - if (openticket.defaults.getDefault("checkerLoading")){ + opendiscord.log("Loading config checker...","system") + if (opendiscord.defaults.getDefault("checkerLoading")){ await (await import("./data/framework/checkerLoader.js")).loadAllConfigCheckers() } - await openticket.events.get("onCheckerLoad").emit([openticket.checkers]) - await openticket.events.get("afterCheckersLoaded").emit([openticket.checkers]) + await opendiscord.events.get("onCheckerLoad").emit([opendiscord.checkers]) + await opendiscord.events.get("afterCheckersLoaded").emit([opendiscord.checkers]) //load config checker functions - if (openticket.defaults.getDefault("checkerFunctionLoading")){ + if (opendiscord.defaults.getDefault("checkerFunctionLoading")){ await (await import("./data/framework/checkerLoader.js")).loadAllConfigCheckerFunctions() } - await openticket.events.get("onCheckerFunctionLoad").emit([openticket.checkers.functions,openticket.checkers]) - await openticket.events.get("afterCheckerFunctionsLoaded").emit([openticket.checkers.functions,openticket.checkers]) + await opendiscord.events.get("onCheckerFunctionLoad").emit([opendiscord.checkers.functions,opendiscord.checkers]) + await opendiscord.events.get("afterCheckerFunctionsLoaded").emit([opendiscord.checkers.functions,opendiscord.checkers]) //execute config checker - await openticket.events.get("onCheckerExecute").emit([openticket.checkers]) - if (openticket.defaults.getDefault("checkerExecution")){ - const result = openticket.checkers.checkAll(true) - await openticket.events.get("afterCheckersExecuted").emit([result,openticket.checkers]) + await opendiscord.events.get("onCheckerExecute").emit([opendiscord.checkers]) + if (opendiscord.defaults.getDefault("checkerExecution")){ + const result = opendiscord.checkers.checkAll(true) + await opendiscord.events.get("afterCheckersExecuted").emit([result,opendiscord.checkers]) } //load config checker translations - if (openticket.defaults.getDefault("checkerTranslationLoading")){ + if (opendiscord.defaults.getDefault("checkerTranslationLoading")){ await (await import("./data/framework/checkerLoader.js")).loadAllConfigCheckerTranslations() } - await openticket.events.get("onCheckerTranslationLoad").emit([openticket.checkers.translation,((generalConfig && generalConfig.data.system && generalConfig.data.system.useTranslatedConfigChecker) ? generalConfig.data.system.useTranslatedConfigChecker : false),openticket.checkers]) - await openticket.events.get("afterCheckerTranslationsLoaded").emit([openticket.checkers.translation,openticket.checkers]) + await opendiscord.events.get("onCheckerTranslationLoad").emit([opendiscord.checkers.translation,((generalConfig && generalConfig.data.system && generalConfig.data.system.useTranslatedConfigChecker) ? generalConfig.data.system.useTranslatedConfigChecker : false),opendiscord.checkers]) + await opendiscord.events.get("afterCheckerTranslationsLoaded").emit([opendiscord.checkers.translation,opendiscord.checkers]) //render config checker - const advancedCheckerFlag = openticket.flags.get("openticket:checker") - const disableCheckerFlag = openticket.flags.get("openticket:no-checker") + const advancedCheckerFlag = opendiscord.flags.get("openticket:checker") + const disableCheckerFlag = opendiscord.flags.get("openticket:no-checker") - await openticket.events.get("onCheckerRender").emit([openticket.checkers.renderer,openticket.checkers]) - if (openticket.defaults.getDefault("checkerRendering") && !(disableCheckerFlag ? disableCheckerFlag.value : false)){ + await opendiscord.events.get("onCheckerRender").emit([opendiscord.checkers.renderer,opendiscord.checkers]) + if (opendiscord.defaults.getDefault("checkerRendering") && !(disableCheckerFlag ? disableCheckerFlag.value : false)){ //check if there is a result (otherwise throw minor error) - const result = openticket.checkers.lastResult - if (!result) return openticket.log("Failed to render Config Checker! (couldn't fetch result)","error") + const result = opendiscord.checkers.lastResult + if (!result) return opendiscord.log("Failed to render Config Checker! (couldn't fetch result)","error") //get components & check if full mode enabled - const components = openticket.checkers.renderer.getComponents(!(advancedCheckerFlag ? advancedCheckerFlag.value : false),openticket.defaults.getDefault("checkerRenderEmpty"),openticket.checkers.translation,result) + const components = opendiscord.checkers.renderer.getComponents(!(advancedCheckerFlag ? advancedCheckerFlag.value : false),opendiscord.defaults.getDefault("checkerRenderEmpty"),opendiscord.checkers.translation,result) //render - openticket.debugfile.writeText("\n[CONFIG CHECKER RESULT]:\n"+ansis.strip(components.join("\n"))+"\n") - openticket.checkers.renderer.render(components) + opendiscord.debugfile.writeText("\n[CONFIG CHECKER RESULT]:\n"+ansis.strip(components.join("\n"))+"\n") + opendiscord.checkers.renderer.render(components) //wait 5 seconds when there are warnings (not for errors & info) if (result.messages.length > 0 && result.messages.some((msg) => msg.type == "warning") && result.messages.every((msg) => msg.type != "error")) await utilities.timer(5000) - await openticket.events.get("afterCheckersRendered").emit([openticket.checkers.renderer,openticket.checkers]) + await opendiscord.events.get("afterCheckersRendered").emit([opendiscord.checkers.renderer,opendiscord.checkers]) } //quit config checker (when required) - if (openticket.checkers.lastResult && !openticket.checkers.lastResult.valid && !(disableCheckerFlag ? disableCheckerFlag.value : false)){ - await openticket.events.get("onCheckerQuit").emit([openticket.checkers]) - if (openticket.defaults.getDefault("checkerQuit")){ + if (opendiscord.checkers.lastResult && !opendiscord.checkers.lastResult.valid && !(disableCheckerFlag ? disableCheckerFlag.value : false)){ + await opendiscord.events.get("onCheckerQuit").emit([opendiscord.checkers]) + if (opendiscord.defaults.getDefault("checkerQuit")){ process.exit(0) //there is no afterCheckerQuitted event :) } } //client configuration - openticket.log("Loading client...","system") - if (openticket.defaults.getDefault("clientLoading")){ + opendiscord.log("Loading client...","system") + if (opendiscord.defaults.getDefault("clientLoading")){ //add intents (for basic permissions) - openticket.client.intents.push( + opendiscord.client.intents.push( "Guilds", "GuildMessages", "DirectMessages", @@ -300,13 +300,13 @@ const main = async () => { ) //add privileged intents (required for transcripts) - openticket.client.privileges.push("MessageContent","GuildMembers") + opendiscord.client.privileges.push("MessageContent","GuildMembers") //add partials (required for DM messages) - openticket.client.partials.push("Channel","Message") + opendiscord.client.partials.push("Channel","Message") //add permissions (not required when Administrator) - openticket.client.permissions.push( + opendiscord.client.permissions.push( "AddReactions", "AttachFiles", "CreatePrivateThreads", @@ -330,24 +330,24 @@ const main = async () => { ) //get token from config or env - const configToken = openticket.configs.get("openticket:general").data.token ? openticket.configs.get("openticket:general").data.token : "" - const envToken = openticket.env.getVariable("TOKEN") ? openticket.env.getVariable("TOKEN") : "" - const token = openticket.configs.get("openticket:general").data.tokenFromENV ? envToken : configToken - openticket.client.token = token + const configToken = opendiscord.configs.get("openticket:general").data.token ? opendiscord.configs.get("openticket:general").data.token : "" + const envToken = opendiscord.env.getVariable("TOKEN") ? opendiscord.env.getVariable("TOKEN") : "" + const token = opendiscord.configs.get("openticket:general").data.tokenFromENV ? envToken : configToken + opendiscord.client.token = token } - await openticket.events.get("onClientLoad").emit([openticket.client]) - await openticket.events.get("afterClientLoaded").emit([openticket.client]) + await opendiscord.events.get("onClientLoad").emit([opendiscord.client]) + await opendiscord.events.get("afterClientLoaded").emit([opendiscord.client]) //client ready - openticket.client.readyListener = async () => { - openticket.log("Loading client setup...","system") - await openticket.events.get("onClientReady").emit([openticket.client]) - if (openticket.defaults.getDefault("clientReady")){ - const client = openticket.client + opendiscord.client.readyListener = async () => { + opendiscord.log("Loading client setup...","system") + await opendiscord.events.get("onClientReady").emit([opendiscord.client]) + if (opendiscord.defaults.getDefault("clientReady")){ + const client = opendiscord.client //check if all servers are valid const botServers = client.getGuilds() - const generalConfig = openticket.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("openticket:general") const serverId = generalConfig.data.serverId ? generalConfig.data.serverId : "" if (!serverId) throw new api.ODSystemError("Server Id Missing!") @@ -356,223 +356,223 @@ const main = async () => { //throw if bot isn't member of main server if (!mainServer || !client.checkBotInGuild(mainServer)){ console.log("\n") - openticket.log("The bot isn't a member of the server provided in the config!","error") - openticket.log("Please invite your bot to the server!","info") + opendiscord.log("The bot isn't a member of the server provided in the config!","error") + opendiscord.log("Please invite your bot to the server!","info") console.log("\n") process.exit(0) } //throw if bot doesn't have permissions in main server if (!client.checkGuildPerms(mainServer)){ console.log("\n") - openticket.log("The bot doesn't have the correct permissions in the server provided in the config!","error") - openticket.log("Please give the bot \"Administrator\" permissions or visit the documentation!","info") + opendiscord.log("The bot doesn't have the correct permissions in the server provided in the config!","error") + opendiscord.log("Please give the bot \"Administrator\" permissions or visit the documentation!","info") console.log("\n") process.exit(0) } - if (openticket.defaults.getDefault("clientMultiGuildWarning")){ + if (opendiscord.defaults.getDefault("clientMultiGuildWarning")){ //warn if bot is in multiple servers if (botServers.length > 1){ - openticket.log("This bot is part of multiple servers, but Open Ticket doesn't have support for it!","warning") - openticket.log("It may result in the bot crashing & glitching when used in these servers!","info") + opendiscord.log("This bot is part of multiple servers, but Open Ticket doesn't have support for it!","warning") + opendiscord.log("It may result in the bot crashing & glitching when used in these servers!","info") } botServers.forEach((server) => { //warn if bot doesn't have permissions in multiple servers - if (!client.checkGuildPerms(server)) openticket.log(`The bot doesn't have the correct permissions in the server "${server.name}"!`,"warning") + if (!client.checkGuildPerms(server)) opendiscord.log(`The bot doesn't have the correct permissions in the server "${server.name}"!`,"warning") }) } //load client activity - openticket.log("Loading client activity...","system") - if (openticket.defaults.getDefault("clientActivityLoading")){ + opendiscord.log("Loading client activity...","system") + if (opendiscord.defaults.getDefault("clientActivityLoading")){ //load config status - if (generalConfig.data.status && generalConfig.data.status.enabled) openticket.client.activity.setStatus(generalConfig.data.status.type,generalConfig.data.status.text,generalConfig.data.status.status) + if (generalConfig.data.status && generalConfig.data.status.enabled) opendiscord.client.activity.setStatus(generalConfig.data.status.type,generalConfig.data.status.text,generalConfig.data.status.status) } - await openticket.events.get("onClientActivityLoad").emit([openticket.client.activity,openticket.client]) - await openticket.events.get("afterClientActivityLoaded").emit([openticket.client.activity,openticket.client]) + await opendiscord.events.get("onClientActivityLoad").emit([opendiscord.client.activity,opendiscord.client]) + await opendiscord.events.get("afterClientActivityLoaded").emit([opendiscord.client.activity,opendiscord.client]) //initiate client activity - await openticket.events.get("onClientActivityInit").emit([openticket.client.activity,openticket.client]) - if (openticket.defaults.getDefault("clientActivityInitiating")){ - openticket.client.activity.initStatus() - await openticket.events.get("afterClientActivityInitiated").emit([openticket.client.activity,openticket.client]) + await opendiscord.events.get("onClientActivityInit").emit([opendiscord.client.activity,opendiscord.client]) + if (opendiscord.defaults.getDefault("clientActivityInitiating")){ + opendiscord.client.activity.initStatus() + await opendiscord.events.get("afterClientActivityInitiated").emit([opendiscord.client.activity,opendiscord.client]) } //load slash commands - openticket.log("Loading slash commands...","system") - if (openticket.defaults.getDefault("slashCommandLoading")){ + opendiscord.log("Loading slash commands...","system") + if (opendiscord.defaults.getDefault("slashCommandLoading")){ await (await import("./data/framework/commandLoader.js")).loadAllSlashCommands() } - await openticket.events.get("onSlashCommandLoad").emit([openticket.client.slashCommands,openticket.client]) - await openticket.events.get("afterSlashCommandsLoaded").emit([openticket.client.slashCommands,openticket.client]) + await opendiscord.events.get("onSlashCommandLoad").emit([opendiscord.client.slashCommands,opendiscord.client]) + await opendiscord.events.get("afterSlashCommandsLoaded").emit([opendiscord.client.slashCommands,opendiscord.client]) //register slash commands (create, update & remove) - if (openticket.defaults.getDefault("forceSlashCommandRegistration")) openticket.log("Forcing all slash commands to be re-registered...","system") - openticket.log("Registering slash commands... (this can take up to 2 minutes)","system") - await openticket.events.get("onSlashCommandRegister").emit([openticket.client.slashCommands,openticket.client]) - if (openticket.defaults.getDefault("slashCommandRegistering")){ + if (opendiscord.defaults.getDefault("forceSlashCommandRegistration")) opendiscord.log("Forcing all slash commands to be re-registered...","system") + opendiscord.log("Registering slash commands... (this can take up to 2 minutes)","system") + await opendiscord.events.get("onSlashCommandRegister").emit([opendiscord.client.slashCommands,opendiscord.client]) + if (opendiscord.defaults.getDefault("slashCommandRegistering")){ //get all commands that are already registered in the bot - const cmds = await openticket.client.slashCommands.getAllRegisteredCommands() + const cmds = await opendiscord.client.slashCommands.getAllRegisteredCommands() const removableCmds = cmds.unused.map((cmd) => cmd.cmd) const newCmds = cmds.unregistered.map((cmd) => cmd.instance) - const updatableCmds = cmds.registered.filter((cmd) => cmd.requiresUpdate || openticket.defaults.getDefault("forceSlashCommandRegistration")).map((cmd) => cmd.instance) + const updatableCmds = cmds.registered.filter((cmd) => cmd.requiresUpdate || opendiscord.defaults.getDefault("forceSlashCommandRegistration")).map((cmd) => cmd.instance) //init progress bars - const removeProgress = openticket.progressbars.get("openticket:slash-command-remove") - const createProgress = openticket.progressbars.get("openticket:slash-command-create") - const updateProgress = openticket.progressbars.get("openticket:slash-command-update") + const removeProgress = opendiscord.progressbars.get("openticket:slash-command-remove") + const createProgress = opendiscord.progressbars.get("openticket:slash-command-create") + const updateProgress = opendiscord.progressbars.get("openticket:slash-command-update") //remove unused cmds, create new cmds & update existing cmds - if (openticket.defaults.getDefault("allowSlashCommandRemoval")) await openticket.client.slashCommands.removeUnusedCommands(removableCmds,undefined,removeProgress) - await openticket.client.slashCommands.createNewCommands(newCmds,createProgress) - await openticket.client.slashCommands.updateExistingCommands(updatableCmds,updateProgress) + if (opendiscord.defaults.getDefault("allowSlashCommandRemoval")) await opendiscord.client.slashCommands.removeUnusedCommands(removableCmds,undefined,removeProgress) + await opendiscord.client.slashCommands.createNewCommands(newCmds,createProgress) + await opendiscord.client.slashCommands.updateExistingCommands(updatableCmds,updateProgress) - await openticket.events.get("afterSlashCommandsRegistered").emit([openticket.client.slashCommands,openticket.client]) + await opendiscord.events.get("afterSlashCommandsRegistered").emit([opendiscord.client.slashCommands,opendiscord.client]) } //load text commands - openticket.log("Loading text commands...","system") - if (openticket.defaults.getDefault("allowDumpCommand")){ + opendiscord.log("Loading text commands...","system") + if (opendiscord.defaults.getDefault("allowDumpCommand")){ (await import("./core/startup/dump.js")).loadDumpCommand() } - if (openticket.defaults.getDefault("textCommandLoading")){ + if (opendiscord.defaults.getDefault("textCommandLoading")){ await (await import("./data/framework/commandLoader.js")).loadAllTextCommands() } - await openticket.events.get("onTextCommandLoad").emit([openticket.client.textCommands,openticket.client]) - await openticket.events.get("afterTextCommandsLoaded").emit([openticket.client.textCommands,openticket.client]) + await opendiscord.events.get("onTextCommandLoad").emit([opendiscord.client.textCommands,opendiscord.client]) + await opendiscord.events.get("afterTextCommandsLoaded").emit([opendiscord.client.textCommands,opendiscord.client]) //client ready - await openticket.events.get("afterClientReady").emit([openticket.client]) + await opendiscord.events.get("afterClientReady").emit([opendiscord.client]) } } //client init (login) - openticket.log("Logging in...","system") - await openticket.events.get("onClientInit").emit([openticket.client]) - if (openticket.defaults.getDefault("clientInitiating")){ + opendiscord.log("Logging in...","system") + await opendiscord.events.get("onClientInit").emit([opendiscord.client]) + if (opendiscord.defaults.getDefault("clientInitiating")){ //init client - openticket.client.initClient() - await openticket.events.get("afterClientInitiated").emit([openticket.client]) + opendiscord.client.initClient() + await opendiscord.events.get("afterClientInitiated").emit([opendiscord.client]) //client login - await openticket.client.login().catch((reason) => process.emit("uncaughtException",new api.ODSystemError(reason))) - openticket.log("discord.js client ready!","info") + await opendiscord.client.login().catch((reason) => process.emit("uncaughtException",new api.ODSystemError(reason))) + opendiscord.log("discord.js client ready!","info") } //load questions - openticket.log("Loading questions...","system") - if (openticket.defaults.getDefault("questionLoading")){ + opendiscord.log("Loading questions...","system") + if (opendiscord.defaults.getDefault("questionLoading")){ await (await import("./data/openticket/questionLoader.js")).loadAllQuestions() } - await openticket.events.get("onQuestionLoad").emit([openticket.questions]) - await openticket.events.get("afterQuestionsLoaded").emit([openticket.questions]) + await opendiscord.events.get("onQuestionLoad").emit([opendiscord.questions]) + await opendiscord.events.get("afterQuestionsLoaded").emit([opendiscord.questions]) //load options - openticket.log("Loading options...","system") - if (openticket.defaults.getDefault("optionLoading")){ + opendiscord.log("Loading options...","system") + if (opendiscord.defaults.getDefault("optionLoading")){ await (await import("./data/openticket/optionLoader.js")).loadAllOptions() } - await openticket.events.get("onOptionLoad").emit([openticket.options]) - await openticket.events.get("afterOptionsLoaded").emit([openticket.options]) + await opendiscord.events.get("onOptionLoad").emit([opendiscord.options]) + await opendiscord.events.get("afterOptionsLoaded").emit([opendiscord.options]) //load panels - openticket.log("Loading panels...","system") - if (openticket.defaults.getDefault("panelLoading")){ + opendiscord.log("Loading panels...","system") + if (opendiscord.defaults.getDefault("panelLoading")){ await (await import("./data/openticket/panelLoader.js")).loadAllPanels() } - await openticket.events.get("onPanelLoad").emit([openticket.panels]) - await openticket.events.get("afterPanelsLoaded").emit([openticket.panels]) + await opendiscord.events.get("onPanelLoad").emit([opendiscord.panels]) + await opendiscord.events.get("afterPanelsLoaded").emit([opendiscord.panels]) //load tickets - openticket.log("Loading tickets...","system") - if (openticket.defaults.getDefault("ticketLoading")){ - openticket.tickets.useGuild(openticket.client.mainServer) + opendiscord.log("Loading tickets...","system") + if (opendiscord.defaults.getDefault("ticketLoading")){ + opendiscord.tickets.useGuild(opendiscord.client.mainServer) await (await import("./data/openticket/ticketLoader.js")).loadAllTickets() } - await openticket.events.get("onTicketLoad").emit([openticket.tickets]) - await openticket.events.get("afterTicketsLoaded").emit([openticket.tickets]) + await opendiscord.events.get("onTicketLoad").emit([opendiscord.tickets]) + await opendiscord.events.get("afterTicketsLoaded").emit([opendiscord.tickets]) //load roles - openticket.log("Loading roles...","system") - if (openticket.defaults.getDefault("roleLoading")){ + opendiscord.log("Loading roles...","system") + if (opendiscord.defaults.getDefault("roleLoading")){ await (await import("./data/openticket/roleLoader.js")).loadAllRoles() } - await openticket.events.get("onRoleLoad").emit([openticket.roles]) - await openticket.events.get("afterRolesLoaded").emit([openticket.roles]) + await opendiscord.events.get("onRoleLoad").emit([opendiscord.roles]) + await opendiscord.events.get("afterRolesLoaded").emit([opendiscord.roles]) //load blacklist - openticket.log("Loading blacklist...","system") - if (openticket.defaults.getDefault("blacklistLoading")){ + opendiscord.log("Loading blacklist...","system") + if (opendiscord.defaults.getDefault("blacklistLoading")){ await (await import("./data/openticket/blacklistLoader.js")).loadAllBlacklistedUsers() } - await openticket.events.get("onBlacklistLoad").emit([openticket.blacklist]) - await openticket.events.get("afterBlacklistLoaded").emit([openticket.blacklist]) + await opendiscord.events.get("onBlacklistLoad").emit([opendiscord.blacklist]) + await opendiscord.events.get("afterBlacklistLoaded").emit([opendiscord.blacklist]) //load transcript compilers - openticket.log("Loading transcripts...","system") - if (openticket.defaults.getDefault("transcriptCompilerLoading")){ + opendiscord.log("Loading transcripts...","system") + if (opendiscord.defaults.getDefault("transcriptCompilerLoading")){ await (await import("./data/openticket/transcriptLoader.js")).loadAllTranscriptCompilers() } - await openticket.events.get("onTranscriptCompilerLoad").emit([openticket.transcripts]) - await openticket.events.get("afterTranscriptCompilersLoaded").emit([openticket.transcripts]) + await opendiscord.events.get("onTranscriptCompilerLoad").emit([opendiscord.transcripts]) + await opendiscord.events.get("afterTranscriptCompilersLoaded").emit([opendiscord.transcripts]) //load transcript history - if (openticket.defaults.getDefault("transcriptHistoryLoading")){ + if (opendiscord.defaults.getDefault("transcriptHistoryLoading")){ await (await import("./data/openticket/transcriptLoader.js")).loadTranscriptHistory() } - await openticket.events.get("onTranscriptHistoryLoad").emit([openticket.transcripts]) - await openticket.events.get("afterTranscriptHistoryLoaded").emit([openticket.transcripts]) + await opendiscord.events.get("onTranscriptHistoryLoad").emit([opendiscord.transcripts]) + await opendiscord.events.get("afterTranscriptHistoryLoaded").emit([opendiscord.transcripts]) //load button builders - openticket.log("Loading buttons...","system") - if (openticket.defaults.getDefault("buttonBuildersLoading")){ + opendiscord.log("Loading buttons...","system") + if (opendiscord.defaults.getDefault("buttonBuildersLoading")){ await (await import("./builders/buttons.js")).registerAllButtons() } - await openticket.events.get("onButtonBuilderLoad").emit([openticket.builders.buttons,openticket.builders,openticket.actions]) - await openticket.events.get("afterButtonBuildersLoaded").emit([openticket.builders.buttons,openticket.builders,openticket.actions]) + await opendiscord.events.get("onButtonBuilderLoad").emit([opendiscord.builders.buttons,opendiscord.builders,opendiscord.actions]) + await opendiscord.events.get("afterButtonBuildersLoaded").emit([opendiscord.builders.buttons,opendiscord.builders,opendiscord.actions]) //load dropdown builders - openticket.log("Loading dropdowns...","system") - if (openticket.defaults.getDefault("dropdownBuildersLoading")){ + opendiscord.log("Loading dropdowns...","system") + if (opendiscord.defaults.getDefault("dropdownBuildersLoading")){ await (await import("./builders/dropdowns.js")).registerAllDropdowns() } - await openticket.events.get("onDropdownBuilderLoad").emit([openticket.builders.dropdowns,openticket.builders,openticket.actions]) - await openticket.events.get("afterDropdownBuildersLoaded").emit([openticket.builders.dropdowns,openticket.builders,openticket.actions]) + await opendiscord.events.get("onDropdownBuilderLoad").emit([opendiscord.builders.dropdowns,opendiscord.builders,opendiscord.actions]) + await opendiscord.events.get("afterDropdownBuildersLoaded").emit([opendiscord.builders.dropdowns,opendiscord.builders,opendiscord.actions]) //load file builders - openticket.log("Loading files...","system") - if (openticket.defaults.getDefault("fileBuildersLoading")){ + opendiscord.log("Loading files...","system") + if (opendiscord.defaults.getDefault("fileBuildersLoading")){ await (await import("./builders/files.js")).registerAllFiles() } - await openticket.events.get("onFileBuilderLoad").emit([openticket.builders.files,openticket.builders,openticket.actions]) - await openticket.events.get("afterFileBuildersLoaded").emit([openticket.builders.files,openticket.builders,openticket.actions]) + await opendiscord.events.get("onFileBuilderLoad").emit([opendiscord.builders.files,opendiscord.builders,opendiscord.actions]) + await opendiscord.events.get("afterFileBuildersLoaded").emit([opendiscord.builders.files,opendiscord.builders,opendiscord.actions]) //load embed builders - openticket.log("Loading embeds...","system") - if (openticket.defaults.getDefault("embedBuildersLoading")){ + opendiscord.log("Loading embeds...","system") + if (opendiscord.defaults.getDefault("embedBuildersLoading")){ await (await import("./builders/embeds.js")).registerAllEmbeds() } - await openticket.events.get("onEmbedBuilderLoad").emit([openticket.builders.embeds,openticket.builders,openticket.actions]) - await openticket.events.get("afterEmbedBuildersLoaded").emit([openticket.builders.embeds,openticket.builders,openticket.actions]) + await opendiscord.events.get("onEmbedBuilderLoad").emit([opendiscord.builders.embeds,opendiscord.builders,opendiscord.actions]) + await opendiscord.events.get("afterEmbedBuildersLoaded").emit([opendiscord.builders.embeds,opendiscord.builders,opendiscord.actions]) //load message builders - openticket.log("Loading messages...","system") - if (openticket.defaults.getDefault("messageBuildersLoading")){ + opendiscord.log("Loading messages...","system") + if (opendiscord.defaults.getDefault("messageBuildersLoading")){ await (await import("./builders/messages.js")).registerAllMessages() } - await openticket.events.get("onMessageBuilderLoad").emit([openticket.builders.messages,openticket.builders,openticket.actions]) - await openticket.events.get("afterMessageBuildersLoaded").emit([openticket.builders.messages,openticket.builders,openticket.actions]) + await opendiscord.events.get("onMessageBuilderLoad").emit([opendiscord.builders.messages,opendiscord.builders,opendiscord.actions]) + await opendiscord.events.get("afterMessageBuildersLoaded").emit([opendiscord.builders.messages,opendiscord.builders,opendiscord.actions]) //load modal builders - openticket.log("Loading modals...","system") - if (openticket.defaults.getDefault("modalBuildersLoading")){ + opendiscord.log("Loading modals...","system") + if (opendiscord.defaults.getDefault("modalBuildersLoading")){ await (await import("./builders/modals.js")).registerAllModals() } - await openticket.events.get("onModalBuilderLoad").emit([openticket.builders.modals,openticket.builders,openticket.actions]) - await openticket.events.get("afterModalBuildersLoaded").emit([openticket.builders.modals,openticket.builders,openticket.actions]) + await opendiscord.events.get("onModalBuilderLoad").emit([opendiscord.builders.modals,opendiscord.builders,opendiscord.actions]) + await opendiscord.events.get("afterModalBuildersLoaded").emit([opendiscord.builders.modals,opendiscord.builders,opendiscord.actions]) //load command responders - openticket.log("Loading command responders...","system") - if (openticket.defaults.getDefault("commandRespondersLoading")){ + opendiscord.log("Loading command responders...","system") + if (opendiscord.defaults.getDefault("commandRespondersLoading")){ await (await import("./commands/help.js")).registerCommandResponders() await (await import("./commands/stats.js")).registerCommandResponders() await (await import("./commands/panel.js")).registerCommandResponders() @@ -593,12 +593,12 @@ const main = async () => { await (await import("./commands/autoclose.js")).registerCommandResponders() await (await import("./commands/autodelete.js")).registerCommandResponders() } - await openticket.events.get("onCommandResponderLoad").emit([openticket.responders.commands,openticket.responders,openticket.actions]) - await openticket.events.get("afterCommandRespondersLoaded").emit([openticket.responders.commands,openticket.responders,openticket.actions]) + await opendiscord.events.get("onCommandResponderLoad").emit([opendiscord.responders.commands,opendiscord.responders,opendiscord.actions]) + await opendiscord.events.get("afterCommandRespondersLoaded").emit([opendiscord.responders.commands,opendiscord.responders,opendiscord.actions]) //load button responders - openticket.log("Loading button responders...","system") - if (openticket.defaults.getDefault("buttonRespondersLoading")){ + opendiscord.log("Loading button responders...","system") + if (opendiscord.defaults.getDefault("buttonRespondersLoading")){ await (await import("./actions/handleVerifyBar.js")).registerButtonResponders() await (await import("./actions/handleTranscriptErrors.js")).registerButtonResponders() await (await import("./commands/help.js")).registerButtonResponders() @@ -613,20 +613,20 @@ const main = async () => { await (await import("./commands/role.js")).registerButtonResponders() await (await import("./commands/clear.js")).registerButtonResponders() } - await openticket.events.get("onButtonResponderLoad").emit([openticket.responders.buttons,openticket.responders,openticket.actions]) - await openticket.events.get("afterButtonRespondersLoaded").emit([openticket.responders.buttons,openticket.responders,openticket.actions]) + await opendiscord.events.get("onButtonResponderLoad").emit([opendiscord.responders.buttons,opendiscord.responders,opendiscord.actions]) + await opendiscord.events.get("afterButtonRespondersLoaded").emit([opendiscord.responders.buttons,opendiscord.responders,opendiscord.actions]) //load dropdown responders - openticket.log("Loading dropdown responders...","system") - if (openticket.defaults.getDefault("dropdownRespondersLoading")){ + opendiscord.log("Loading dropdown responders...","system") + if (opendiscord.defaults.getDefault("dropdownRespondersLoading")){ await (await import("./commands/ticket.js")).registerDropdownResponders() } - await openticket.events.get("onDropdownResponderLoad").emit([openticket.responders.dropdowns,openticket.responders,openticket.actions]) - await openticket.events.get("afterDropdownRespondersLoaded").emit([openticket.responders.dropdowns,openticket.responders,openticket.actions]) + await opendiscord.events.get("onDropdownResponderLoad").emit([opendiscord.responders.dropdowns,opendiscord.responders,opendiscord.actions]) + await opendiscord.events.get("afterDropdownRespondersLoaded").emit([opendiscord.responders.dropdowns,opendiscord.responders,opendiscord.actions]) //load modal responders - openticket.log("Loading modal responders...","system") - if (openticket.defaults.getDefault("modalRespondersLoading")){ + opendiscord.log("Loading modal responders...","system") + if (opendiscord.defaults.getDefault("modalRespondersLoading")){ await (await import("./commands/ticket.js")).registerModalResponders() await (await import("./commands/close.js")).registerModalResponders() await (await import("./commands/reopen.js")).registerModalResponders() @@ -636,12 +636,12 @@ const main = async () => { await (await import("./commands/pin.js")).registerModalResponders() await (await import("./commands/unpin.js")).registerModalResponders() } - await openticket.events.get("onModalResponderLoad").emit([openticket.responders.modals,openticket.responders,openticket.actions]) - await openticket.events.get("afterModalRespondersLoaded").emit([openticket.responders.modals,openticket.responders,openticket.actions]) + await opendiscord.events.get("onModalResponderLoad").emit([opendiscord.responders.modals,opendiscord.responders,opendiscord.actions]) + await opendiscord.events.get("afterModalRespondersLoaded").emit([opendiscord.responders.modals,opendiscord.responders,opendiscord.actions]) //load actions - openticket.log("Loading actions...","system") - if (openticket.defaults.getDefault("actionsLoading")){ + opendiscord.log("Loading actions...","system") + if (opendiscord.defaults.getDefault("actionsLoading")){ await (await import("./actions/createTicketPermissions.js")).registerActions() await (await import("./actions/createTranscript.js")).registerActions() await (await import("./actions/createTicket.js")).registerActions() @@ -659,12 +659,12 @@ const main = async () => { await (await import("./actions/reactionRole.js")).registerActions() await (await import("./actions/clearTickets.js")).registerActions() } - await openticket.events.get("onActionLoad").emit([openticket.actions]) - await openticket.events.get("afterActionsLoaded").emit([openticket.actions]) + await opendiscord.events.get("onActionLoad").emit([opendiscord.actions]) + await opendiscord.events.get("afterActionsLoaded").emit([opendiscord.actions]) //load verifybars - openticket.log("Loading verifybars...","system") - if (openticket.defaults.getDefault("verifyBarsLoading")){ + opendiscord.log("Loading verifybars...","system") + if (opendiscord.defaults.getDefault("verifyBarsLoading")){ await (await import("./actions/closeTicket.js")).registerVerifyBars() await (await import("./actions/deleteTicket.js")).registerVerifyBars() await (await import("./actions/reopenTicket.js")).registerVerifyBars() @@ -673,136 +673,136 @@ const main = async () => { await (await import("./actions/pinTicket.js")).registerVerifyBars() await (await import("./actions/unpinTicket.js")).registerVerifyBars() } - await openticket.events.get("onVerifyBarLoad").emit([openticket.verifybars]) - await openticket.events.get("afterVerifyBarsLoaded").emit([openticket.verifybars]) + await opendiscord.events.get("onVerifyBarLoad").emit([opendiscord.verifybars]) + await opendiscord.events.get("afterVerifyBarsLoaded").emit([opendiscord.verifybars]) //load permissions - openticket.log("Loading permissions...","system") - if (openticket.defaults.getDefault("permissionsLoading")){ + opendiscord.log("Loading permissions...","system") + if (opendiscord.defaults.getDefault("permissionsLoading")){ await (await import("./data/framework/permissionLoader.js")).loadAllPermissions() } - await openticket.events.get("onPermissionLoad").emit([openticket.permissions]) - await openticket.events.get("afterPermissionsLoaded").emit([openticket.permissions]) + await opendiscord.events.get("onPermissionLoad").emit([opendiscord.permissions]) + await opendiscord.events.get("afterPermissionsLoaded").emit([opendiscord.permissions]) //load posts - openticket.log("Loading posts...","system") - if (openticket.defaults.getDefault("postsLoading")){ + opendiscord.log("Loading posts...","system") + if (opendiscord.defaults.getDefault("postsLoading")){ await (await import("./data/framework/postLoader.js")).loadAllPosts() } - await openticket.events.get("onPostLoad").emit([openticket.posts]) - await openticket.events.get("afterPostsLoaded").emit([openticket.posts]) + await opendiscord.events.get("onPostLoad").emit([opendiscord.posts]) + await opendiscord.events.get("afterPostsLoaded").emit([opendiscord.posts]) //init posts - await openticket.events.get("onPostInit").emit([openticket.posts]) - if (openticket.defaults.getDefault("postsInitiating")){ - if (openticket.client.mainServer) openticket.posts.init(openticket.client.mainServer) - await openticket.events.get("afterPostsInitiated").emit([openticket.posts]) + await opendiscord.events.get("onPostInit").emit([opendiscord.posts]) + if (opendiscord.defaults.getDefault("postsInitiating")){ + if (opendiscord.client.mainServer) opendiscord.posts.init(opendiscord.client.mainServer) + await opendiscord.events.get("afterPostsInitiated").emit([opendiscord.posts]) } //load cooldowns - openticket.log("Loading cooldowns...","system") - if (openticket.defaults.getDefault("cooldownsLoading")){ + opendiscord.log("Loading cooldowns...","system") + if (opendiscord.defaults.getDefault("cooldownsLoading")){ await (await import("./data/framework/cooldownLoader.js")).loadAllCooldowns() } - await openticket.events.get("onCooldownLoad").emit([openticket.cooldowns]) - await openticket.events.get("afterCooldownsLoaded").emit([openticket.cooldowns]) + await opendiscord.events.get("onCooldownLoad").emit([opendiscord.cooldowns]) + await opendiscord.events.get("afterCooldownsLoaded").emit([opendiscord.cooldowns]) //init cooldowns - await openticket.events.get("onCooldownInit").emit([openticket.cooldowns]) - if (openticket.defaults.getDefault("cooldownsInitiating")){ - await openticket.cooldowns.init() - await openticket.events.get("afterCooldownsInitiated").emit([openticket.cooldowns]) + await opendiscord.events.get("onCooldownInit").emit([opendiscord.cooldowns]) + if (opendiscord.defaults.getDefault("cooldownsInitiating")){ + await opendiscord.cooldowns.init() + await opendiscord.events.get("afterCooldownsInitiated").emit([opendiscord.cooldowns]) } //load help menu categories - openticket.log("Loading help menu...","system") - if (openticket.defaults.getDefault("helpMenuCategoryLoading")){ + opendiscord.log("Loading help menu...","system") + if (opendiscord.defaults.getDefault("helpMenuCategoryLoading")){ await (await import("./data/framework/helpMenuLoader.js")).loadAllHelpMenuCategories() } - await openticket.events.get("onHelpMenuCategoryLoad").emit([openticket.helpmenu]) - await openticket.events.get("afterHelpMenuCategoriesLoaded").emit([openticket.helpmenu]) + await opendiscord.events.get("onHelpMenuCategoryLoad").emit([opendiscord.helpmenu]) + await opendiscord.events.get("afterHelpMenuCategoriesLoaded").emit([opendiscord.helpmenu]) //load help menu components - if (openticket.defaults.getDefault("helpMenuComponentLoading")){ + if (opendiscord.defaults.getDefault("helpMenuComponentLoading")){ await (await import("./data/framework/helpMenuLoader.js")).loadAllHelpMenuComponents() } - await openticket.events.get("onHelpMenuComponentLoad").emit([openticket.helpmenu]) - await openticket.events.get("afterHelpMenuComponentsLoaded").emit([openticket.helpmenu]) + await opendiscord.events.get("onHelpMenuComponentLoad").emit([opendiscord.helpmenu]) + await opendiscord.events.get("afterHelpMenuComponentsLoaded").emit([opendiscord.helpmenu]) //load stat scopes - openticket.log("Loading stats...","system") - if (openticket.defaults.getDefault("statScopesLoading")){ - openticket.stats.useDatabase(openticket.databases.get("openticket:stats")) + opendiscord.log("Loading stats...","system") + if (opendiscord.defaults.getDefault("statScopesLoading")){ + opendiscord.stats.useDatabase(opendiscord.databases.get("openticket:stats")) await (await import("./data/framework/statLoader.js")).loadAllStatScopes() } - await openticket.events.get("onStatScopeLoad").emit([openticket.stats]) - await openticket.events.get("afterStatScopesLoaded").emit([openticket.stats]) + await opendiscord.events.get("onStatScopeLoad").emit([opendiscord.stats]) + await opendiscord.events.get("afterStatScopesLoaded").emit([opendiscord.stats]) //load stats - if (openticket.defaults.getDefault("statLoading")){ + if (opendiscord.defaults.getDefault("statLoading")){ await (await import("./data/framework/statLoader.js")).loadAllStats() } - await openticket.events.get("onStatLoad").emit([openticket.stats]) - await openticket.events.get("afterStatsLoaded").emit([openticket.stats]) + await opendiscord.events.get("onStatLoad").emit([opendiscord.stats]) + await opendiscord.events.get("afterStatsLoaded").emit([opendiscord.stats]) //init stats - await openticket.events.get("onStatInit").emit([openticket.stats]) - if (openticket.defaults.getDefault("statInitiating")){ - await openticket.stats.init() - await openticket.events.get("afterStatsInitiated").emit([openticket.stats]) + await opendiscord.events.get("onStatInit").emit([opendiscord.stats]) + if (opendiscord.defaults.getDefault("statInitiating")){ + await opendiscord.stats.init() + await opendiscord.events.get("afterStatsInitiated").emit([opendiscord.stats]) } //load code - openticket.log("Loading code...","system") - if (openticket.defaults.getDefault("codeLoading")){ + opendiscord.log("Loading code...","system") + if (opendiscord.defaults.getDefault("codeLoading")){ await (await import("./data/framework/codeLoader.js")).loadAllCode() } - await openticket.events.get("onCodeLoad").emit([openticket.code]) - await openticket.events.get("afterCodeLoaded").emit([openticket.code]) + await opendiscord.events.get("onCodeLoad").emit([opendiscord.code]) + await opendiscord.events.get("afterCodeLoaded").emit([opendiscord.code]) //execute code - await openticket.events.get("onCodeExecute").emit([openticket.code]) - if (openticket.defaults.getDefault("codeExecution")){ - await openticket.code.execute() - await openticket.events.get("afterCodeExecuted").emit([openticket.code]) + await opendiscord.events.get("onCodeExecute").emit([opendiscord.code]) + if (opendiscord.defaults.getDefault("codeExecution")){ + await opendiscord.code.execute() + await opendiscord.events.get("afterCodeExecuted").emit([opendiscord.code]) } //finish setup - openticket.log("Setup complete!","info") + opendiscord.log("Setup complete!","info") //load livestatus sources - openticket.log("Loading livestatus...","system") - if (openticket.defaults.getDefault("liveStatusLoading")){ + opendiscord.log("Loading livestatus...","system") + if (opendiscord.defaults.getDefault("liveStatusLoading")){ await (await import("./data/framework/liveStatusLoader.js")).loadAllLiveStatusSources() } - await openticket.events.get("onLiveStatusSourceLoad").emit([openticket.livestatus]) - await openticket.events.get("afterLiveStatusSourcesLoaded").emit([openticket.livestatus]) + await opendiscord.events.get("onLiveStatusSourceLoad").emit([opendiscord.livestatus]) + await opendiscord.events.get("afterLiveStatusSourcesLoaded").emit([opendiscord.livestatus]) //load startscreen - openticket.log("Loading startscreen...","system") - if (openticket.defaults.getDefault("startScreenLoading")){ + opendiscord.log("Loading startscreen...","system") + if (opendiscord.defaults.getDefault("startScreenLoading")){ await (await import("./data/framework/startScreenLoader.js")).loadAllStartScreenComponents() } - await openticket.events.get("onStartScreenLoad").emit([openticket.startscreen]) - await openticket.events.get("afterStartScreensLoaded").emit([openticket.startscreen]) + await opendiscord.events.get("onStartScreenLoad").emit([opendiscord.startscreen]) + await opendiscord.events.get("afterStartScreensLoaded").emit([opendiscord.startscreen]) //render startscreen - await openticket.events.get("onStartScreenRender").emit([openticket.startscreen]) - if (openticket.defaults.getDefault("startScreenRendering")){ - await openticket.startscreen.renderAllComponents() - if (openticket.languages.getLanguageMetadata(false)?.automated){ + await opendiscord.events.get("onStartScreenRender").emit([opendiscord.startscreen]) + if (opendiscord.defaults.getDefault("startScreenRendering")){ + await opendiscord.startscreen.renderAllComponents() + if (opendiscord.languages.getLanguageMetadata(false)?.automated){ console.log("===================") - openticket.log("You are currently using a language which has been translated by Google Translate!","warning") - openticket.log("Please help us improve the translation by contributing to our project!","warning") + opendiscord.log("You are currently using a language which has been translated by Google Translate!","warning") + opendiscord.log("Please help us improve the translation by contributing to our project!","warning") console.log("===================") } - await openticket.events.get("afterStartScreensRendered").emit([openticket.startscreen]) + await opendiscord.events.get("afterStartScreensRendered").emit([opendiscord.startscreen]) } //YIPPPIE!! //The startup of Open Ticket is completed :) - openticket.readyStartupDate = new Date() - await openticket.events.get("onReadyForUsage").emit([]) + opendiscord.readyStartupDate = new Date() + await opendiscord.events.get("onReadyForUsage").emit([]) } main() \ No newline at end of file From 6acbf74846d144a3d09f1a8085771ca6a49faed1 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 1 Feb 2025 10:29:35 +0100 Subject: [PATCH 132/157] BREAKING: changed all ids to "opendiscord:" --- src/actions/addTicketUser.ts | 34 +- src/actions/claimTicket.ts | 138 ++-- src/actions/clearTickets.ts | 18 +- src/actions/closeTicket.ts | 150 ++--- src/actions/createTicket.ts | 98 +-- src/actions/createTicketPermissions.ts | 30 +- src/actions/createTranscript.ts | 28 +- src/actions/deleteTicket.ts | 222 +++---- src/actions/handleTranscriptErrors.ts | 70 +- src/actions/handleVerifyBar.ts | 12 +- src/actions/moveTicket.ts | 66 +- src/actions/pinTicket.ts | 134 ++-- src/actions/reactionRole.ts | 14 +- src/actions/removeTicketUser.ts | 36 +- src/actions/renameTicket.ts | 30 +- src/actions/reopenTicket.ts | 206 +++--- src/actions/unclaimTicket.ts | 144 ++-- src/actions/unpinTicket.ts | 130 ++-- src/builders/buttons.ts | 164 ++--- src/builders/dropdowns.ts | 14 +- src/builders/embeds.ts | 438 ++++++------ src/builders/files.ts | 12 +- src/builders/messages.ts | 842 ++++++++++++------------ src/builders/modals.ts | 72 +- src/commands/add.ts | 36 +- src/commands/autoclose.ts | 48 +- src/commands/autodelete.ts | 44 +- src/commands/blacklist.ts | 44 +- src/commands/claim.ts | 68 +- src/commands/clear.ts | 64 +- src/commands/close.ts | 68 +- src/commands/delete.ts | 78 +-- src/commands/help.ts | 48 +- src/commands/move.ts | 38 +- src/commands/panel.ts | 34 +- src/commands/pin.ts | 68 +- src/commands/remove.ts | 36 +- src/commands/rename.ts | 34 +- src/commands/reopen.ts | 74 +-- src/commands/role.ts | 18 +- src/commands/stats.ts | 36 +- src/commands/ticket.ts | 146 ++-- src/commands/unclaim.ts | 68 +- src/commands/unpin.ts | 68 +- src/core/api/defaults/action.ts | 64 +- src/core/api/defaults/base.ts | 10 +- src/core/api/defaults/builder.ts | 322 ++++----- src/core/api/defaults/checker.ts | 190 +++--- src/core/api/defaults/client.ts | 92 +-- src/core/api/defaults/code.ts | 32 +- src/core/api/defaults/config.ts | 12 +- src/core/api/defaults/console.ts | 2 +- src/core/api/defaults/database.ts | 24 +- src/core/api/defaults/flag.ts | 28 +- src/core/api/defaults/helpmenu.ts | 76 +-- src/core/api/defaults/language.ts | 46 +- src/core/api/defaults/permission.ts | 2 +- src/core/api/defaults/post.ts | 4 +- src/core/api/defaults/progressbar.ts | 18 +- src/core/api/defaults/responder.ts | 90 +-- src/core/api/defaults/startscreen.ts | 14 +- src/core/api/defaults/stat.ts | 82 +-- src/core/api/defaults/verifybar.ts | 34 +- src/core/api/main.ts | 10 +- src/core/api/modules/base.ts | 3 - src/core/api/modules/builder.ts | 14 +- src/core/api/modules/checker.ts | 130 ++-- src/core/api/modules/console.ts | 4 +- src/core/api/modules/defaults.ts | 2 +- src/core/api/openticket/option.ts | 140 ++-- src/core/api/openticket/panel.ts | 26 +- src/core/api/openticket/question.ts | 34 +- src/core/api/openticket/role.ts | 8 +- src/core/api/openticket/ticket.ts | 66 +- src/core/api/openticket/transcript.ts | 6 +- src/core/startup/dump.ts | 2 +- src/core/startup/manageMigration.ts | 22 +- src/core/startup/migration.ts | 2 +- src/data/framework/checkerLoader.ts | 658 +++++++++--------- src/data/framework/codeLoader.ts | 192 +++--- src/data/framework/commandLoader.ts | 104 +-- src/data/framework/configLoader.ts | 12 +- src/data/framework/cooldownLoader.ts | 6 +- src/data/framework/databaseLoader.ts | 12 +- src/data/framework/flagLoader.ts | 28 +- src/data/framework/helpMenuLoader.ts | 82 +-- src/data/framework/languageLoader.ts | 46 +- src/data/framework/liveStatusLoader.ts | 2 +- src/data/framework/permissionLoader.ts | 34 +- src/data/framework/postLoader.ts | 8 +- src/data/framework/progressBarLoader.ts | 20 +- src/data/framework/startScreenLoader.ts | 20 +- src/data/framework/statLoader.ts | 98 +-- src/data/openticket/blacklistLoader.ts | 4 +- src/data/openticket/optionLoader.ts | 106 +-- src/data/openticket/panelLoader.ts | 100 +-- src/data/openticket/questionLoader.ts | 26 +- src/data/openticket/roleLoader.ts | 8 +- src/data/openticket/ticketLoader.ts | 10 +- src/data/openticket/transcriptLoader.ts | 40 +- src/index.ts | 28 +- 101 files changed, 3736 insertions(+), 3739 deletions(-) diff --git a/src/actions/addTicketUser.ts b/src/actions/addTicketUser.ts index 1ed7118..cf3cf0f 100644 --- a/src/actions/addTicketUser.ts +++ b/src/actions/addTicketUser.ts @@ -4,21 +4,21 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:add-ticket-user")) - opendiscord.actions.get("openticket:add-ticket-user").workers.add([ - new api.ODWorker("openticket:add-ticket-user",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:add-ticket-user")) + opendiscord.actions.get("opendiscord:add-ticket-user").workers.add([ + new api.ODWorker("opendiscord:add-ticket-user",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params if (channel.isThread()) throw new api.ODSystemError("Unable to add user to ticket! Open Ticket doesn't support threads!") await opendiscord.events.get("onTicketUserAdd").emit([ticket,user,data,channel,reason]) //update ticket - ticket.get("openticket:participants").value.push({type:"user",id:data.id}) - ticket.get("openticket:participants").refreshDatabase() - ticket.get("openticket:busy").value = true + ticket.get("opendiscord:participants").value.push({type:"user",id:data.id}) + ticket.get("opendiscord:participants").refreshDatabase() + ticket.get("opendiscord:busy").value = true //update channel permissions try{ @@ -38,7 +38,7 @@ export const registerActions = async () => { const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket user adding!","error",[ {key:"channel",value:"#"+channel.name}, @@ -51,24 +51,24 @@ export const registerActions = async () => { } //reply with new message - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:add-message").build(source,{guild,channel,user,ticket,reason,data})).message) - ticket.get("openticket:busy").value = false + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:add-message").build(source,{guild,channel,user,ticket,reason,data})).message) + ticket.get("opendiscord:busy").value = false await opendiscord.events.get("afterTicketUserAdded").emit([ticket,user,data,channel,reason]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.adding.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.adding.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) + if (creator && generalConfig.data.system.messages.adding.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket,data} = params opendiscord.log(user.displayName+" added "+data.displayName+" to a ticket!","info",[ @@ -81,8 +81,8 @@ export const registerActions = async () => { ]) }) ]) - opendiscord.actions.get("openticket:add-ticket-user").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:add-ticket-user").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false + params.ticket.get("opendiscord:busy").value = false }) } \ No newline at end of file diff --git a/src/actions/claimTicket.ts b/src/actions/claimTicket.ts index a70c28e..8900296 100644 --- a/src/actions/claimTicket.ts +++ b/src/actions/claimTicket.ts @@ -4,35 +4,35 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:claim-ticket")) - opendiscord.actions.get("openticket:claim-ticket").workers.add([ - new api.ODWorker("openticket:claim-ticket",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:claim-ticket")) + opendiscord.actions.get("opendiscord:claim-ticket").workers.add([ + new api.ODWorker("opendiscord:claim-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to claim ticket! Open Ticket doesn't support threads!") await opendiscord.events.get("onTicketClaim").emit([ticket,user,channel,reason]) //update ticket - ticket.get("openticket:claimed").value = true - ticket.get("openticket:claimed-by").value = user.id - ticket.get("openticket:claimed-on").value = new Date().getTime() - ticket.get("openticket:busy").value = true + ticket.get("opendiscord:claimed").value = true + ticket.get("opendiscord:claimed-by").value = user.id + ticket.get("opendiscord:claimed-on").value = new Date().getTime() + ticket.get("opendiscord:busy").value = true //update stats - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-claimed",1,"increase") - await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-claimed",user.id,1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-claimed",1,"increase") + await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-claimed",user.id,1,"increase") //update category - const rawClaimCategory = ticket.option.get("openticket:channel-categories-claimed").value.find((c) => c.user == user.id) + const rawClaimCategory = ticket.option.get("opendiscord:channel-categories-claimed").value.find((c) => c.user == user.id) const claimCategory = (rawClaimCategory) ? rawClaimCategory.category : null if (claimCategory){ try { channel.setParent(claimCategory,{lockPermissions:false}) - ticket.get("openticket:category-mode").value = "claimed" - ticket.get("openticket:category").value = claimCategory + ticket.get("opendiscord:category-mode").value = "claimed" + ticket.get("opendiscord:category").value = claimCategory }catch(e){ opendiscord.log("Unable to move ticket to 'claimed category'!","error",[ {key:"channel",value:"#"+channel.name}, @@ -47,7 +47,7 @@ export const registerActions = async () => { const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket claiming!","error",[ {key:"channel",value:"#"+channel.name}, @@ -60,24 +60,24 @@ export const registerActions = async () => { } //reply with new message - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:claim-message").build(source,{guild,channel,user,ticket,reason})).message) - ticket.get("openticket:busy").value = false + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("opendiscord:busy").value = false await opendiscord.events.get("afterTicketClaimed").emit([ticket,user,channel,reason]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.claiming.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) + if (creator && generalConfig.data.system.messages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params opendiscord.log(user.displayName+" claimed a ticket!","info",[ @@ -90,188 +90,188 @@ export const registerActions = async () => { ]) }) ]) - opendiscord.actions.get("openticket:claim-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:claim-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false + params.ticket.get("opendiscord:busy").value = false }) } export const registerVerifyBars = async () => { //CLAIM TICKET TICKET MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:claim-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:claim-ticket-ticket-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:claim-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:claim-ticket-ticket-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.claim if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already claimed - if (ticket.get("openticket:claimed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) + if (ticket.get("opendiscord:claimed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start claiming ticket if (params.data == "reason"){ //claim with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:claim-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:claim-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //claim without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:claim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:claim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - opendiscord.verifybars.get("openticket:claim-ticket-ticket-message").failure.add([ - new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:claim-ticket-ticket-message").failure.add([ + new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //CLAIM TICKET UNCLAIM MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:claim-ticket-unclaim-message",opendiscord.builders.messages.getSafe("openticket:verifybar-unclaim-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:claim-ticket-unclaim-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:claim-ticket-unclaim-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-unclaim-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.claim if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already claimed - if (ticket.get("openticket:claimed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) + if (ticket.get("opendiscord:claimed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start claiming ticket if (params.data == "reason"){ //claim with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:claim-ticket-reason").build("unclaim-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:claim-ticket-reason").build("unclaim-message",{guild,channel,user,ticket})) }else{ //claim without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:claim-ticket").run("unclaim-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:claim-message").build("unclaim-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("opendiscord:claim-ticket").run("unclaim-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("unclaim-message",{guild,channel,user,ticket,reason:null})) } }) ]) - opendiscord.verifybars.get("openticket:claim-ticket-unclaim-message").failure.add([ - new api.ODWorker("openticket:back-to-unclaim-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").failure.add([ + new api.ODWorker("opendiscord:back-to-unclaim-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:unclaim-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("other",{guild,channel,user,ticket,reason})) }) ]) } \ No newline at end of file diff --git a/src/actions/clearTickets.ts b/src/actions/clearTickets.ts index 03a5ff2..c654557 100644 --- a/src/actions/clearTickets.ts +++ b/src/actions/clearTickets.ts @@ -4,12 +4,12 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:clear-tickets")) - opendiscord.actions.get("openticket:clear-tickets").workers.add([ - new api.ODWorker("openticket:clear-tickets",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:clear-tickets")) + opendiscord.actions.get("opendiscord:clear-tickets").workers.add([ + new api.ODWorker("opendiscord:clear-tickets",2,async (instance,params,source,cancel) => { const {guild,channel,user,filter,list} = params await opendiscord.events.get("onTicketsClear").emit([list,user,channel,filter]) @@ -18,21 +18,21 @@ export const registerActions = async () => { const ticketChannel = await opendiscord.tickets.getTicketChannel(ticket) if (!ticketChannel) return nameList.push("#"+ticketChannel.name) - await opendiscord.actions.get("openticket:delete-ticket").run("clear",{guild,channel:ticketChannel,user,ticket,reason:"Cleared Ticket",sendMessage:true,withoutTranscript:false}) + await opendiscord.actions.get("opendiscord:delete-ticket").run("clear",{guild,channel:ticketChannel,user,ticket,reason:"Cleared Ticket",sendMessage:true,withoutTranscript:false}) } instance.list = nameList await opendiscord.events.get("afterTicketsCleared").emit([list,user,channel,filter]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,filter,list} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.deleting.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:clear-logs").build(source,{guild,channel,user,filter,list:instance.list ?? []})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:clear-logs").build(source,{guild,channel,user,filter,list:instance.list ?? []})) } }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,user,filter,list} = params opendiscord.log(user.displayName+" cleared "+list.length+" tickets!","info",[ {key:"user",value:user.username}, diff --git a/src/actions/closeTicket.ts b/src/actions/closeTicket.ts index b093b63..5481fb7 100644 --- a/src/actions/closeTicket.ts +++ b/src/actions/closeTicket.ts @@ -4,36 +4,36 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:close-ticket")) - opendiscord.actions.get("openticket:close-ticket").workers.add([ - new api.ODWorker("openticket:close-ticket",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:close-ticket")) + opendiscord.actions.get("opendiscord:close-ticket").workers.add([ + new api.ODWorker("opendiscord:close-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to close ticket! Open Ticket doesn't support threads!") await opendiscord.events.get("onTicketClose").emit([ticket,user,channel,reason]) //update ticket - ticket.get("openticket:closed").value = true - if (source == "autoclose") ticket.get("openticket:autoclosed").value = true - ticket.get("openticket:open").value = false - ticket.get("openticket:closed-by").value = user.id - ticket.get("openticket:closed-on").value = new Date().getTime() - ticket.get("openticket:busy").value = true + ticket.get("opendiscord:closed").value = true + if (source == "autoclose") ticket.get("opendiscord:autoclosed").value = true + ticket.get("opendiscord:open").value = false + ticket.get("opendiscord:closed-by").value = user.id + ticket.get("opendiscord:closed-on").value = new Date().getTime() + ticket.get("opendiscord:busy").value = true //update stats - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-closed",1,"increase") - await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-closed",user.id,1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-closed",1,"increase") + await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-closed",user.id,1,"increase") //update category - const closeCategory = ticket.option.get("openticket:channel-category-closed").value + const closeCategory = ticket.option.get("opendiscord:channel-category-closed").value if (closeCategory !== ""){ try { channel.setParent(closeCategory,{lockPermissions:false}) - ticket.get("openticket:category-mode").value = "closed" - ticket.get("openticket:category").value = closeCategory + ticket.get("opendiscord:category-mode").value = "closed" + ticket.get("opendiscord:category").value = closeCategory }catch(e){ opendiscord.log("Unable to move ticket to 'closed category'!","error",[ {key:"channel",value:"#"+channel.name}, @@ -51,9 +51,9 @@ export const registerActions = async () => { allow:[], deny:["ViewChannel","SendMessages","ReadMessageHistory"] }] - const globalAdmins = opendiscord.configs.get("openticket:general").data.globalAdmins - const optionAdmins = ticket.option.get("openticket:admins").value - const readonlyAdmins = ticket.option.get("openticket:admins-readonly").value + const globalAdmins = opendiscord.configs.get("opendiscord:general").data.globalAdmins + const optionAdmins = ticket.option.get("opendiscord:admins").value + const readonlyAdmins = ticket.option.get("opendiscord:admins-readonly").value globalAdmins.forEach((admin) => { permissions.push({ @@ -82,7 +82,7 @@ export const registerActions = async () => { deny:["SendMessages","AddReactions","AttachFiles","SendPolls"] }) }) - ticket.get("openticket:participants").value.forEach((participant) => { + ticket.get("opendiscord:participants").value.forEach((participant) => { //all participants that aren't roles/admins => readonly (OR non-viewable when enabled) if (participant.type == "user"){ if (generalConfig.data.system.removeParticipantsOnClose) permissions.push({ @@ -105,7 +105,7 @@ export const registerActions = async () => { const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket closing!","error",[ {key:"channel",value:"#"+channel.name}, @@ -118,24 +118,24 @@ export const registerActions = async () => { } //reply with new message - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:close-message").build(source,{guild,channel,user,ticket,reason})).message) - ticket.get("openticket:busy").value = false + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("opendiscord:busy").value = false await opendiscord.events.get("afterTicketClosed").emit([ticket,user,channel,reason]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.closing.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.closing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) + if (creator && generalConfig.data.system.messages.closing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params opendiscord.log(user.displayName+" closed a ticket!","info",[ @@ -148,188 +148,188 @@ export const registerActions = async () => { ]) }) ]) - opendiscord.actions.get("openticket:close-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:close-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false + params.ticket.get("opendiscord:busy").value = false }) } export const registerVerifyBars = async () => { //CLOSE TICKET TICKET MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:close-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:close-ticket-ticket-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:close-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:close-ticket-ticket-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.close if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:close-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already closed - if (ticket.get("openticket:closed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) + if (ticket.get("opendiscord:closed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start closing ticket if (params.data == "reason"){ //close with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:close-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:close-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //close without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:close-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:close-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - opendiscord.verifybars.get("openticket:close-ticket-ticket-message").failure.add([ - new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:close-ticket-ticket-message").failure.add([ + new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //CLOSE TICKET REOPEN MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:close-ticket-reopen-message",opendiscord.builders.messages.getSafe("openticket:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:close-ticket-reopen-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:close-ticket-reopen-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.close if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:close-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already closed - if (ticket.get("openticket:closed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) + if (ticket.get("opendiscord:closed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start closing ticket if (params.data == "reason"){ //close with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:close-ticket-reason").build("reopen-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:close-ticket-reason").build("reopen-message",{guild,channel,user,ticket})) }else{ //close without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:close-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:close-message").build("reopen-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("opendiscord:close-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("reopen-message",{guild,channel,user,ticket,reason:null})) } }) ]) - opendiscord.verifybars.get("openticket:close-ticket-reopen-message").failure.add([ - new api.ODWorker("openticket:back-to-reopen-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").failure.add([ + new api.ODWorker("opendiscord:back-to-reopen-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason})) }) ]) } \ No newline at end of file diff --git a/src/actions/createTicket.ts b/src/actions/createTicket.ts index 0815fd3..6c2cfab 100644 --- a/src/actions/createTicket.ts +++ b/src/actions/createTicket.ts @@ -4,22 +4,22 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:create-ticket")) - opendiscord.actions.get("openticket:create-ticket").workers.add([ - new api.ODWorker("openticket:create-ticket",3,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:create-ticket")) + opendiscord.actions.get("opendiscord:create-ticket").workers.add([ + new api.ODWorker("opendiscord:create-ticket",3,async (instance,params,source,cancel) => { const {guild,user,answers,option} = params await opendiscord.events.get("onTicketCreate").emit([user]) await opendiscord.events.get("onTicketChannelCreation").emit([option,user]) //get channel properties - const channelPrefix = option.get("openticket:channel-prefix").value - const channelCategory = option.get("openticket:channel-category").value - const channelBackupCategory = option.get("openticket:channel-category-backup").value - const channelDescription = option.get("openticket:channel-description").value + const channelPrefix = option.get("opendiscord:channel-prefix").value + const channelCategory = option.get("opendiscord:channel-category").value + const channelBackupCategory = option.get("opendiscord:channel-category-backup").value + const channelDescription = option.get("opendiscord:channel-description").value const channelSuffix = opendiscord.options.suffix.getSuffixFromOption(option,user) const channelName = channelPrefix+channelSuffix @@ -65,9 +65,9 @@ export const registerActions = async () => { allow:[], deny:["ViewChannel","SendMessages","ReadMessageHistory"] }] - const globalAdmins = opendiscord.configs.get("openticket:general").data.globalAdmins - const optionAdmins = option.get("openticket:admins").value - const readonlyAdmins = option.get("openticket:admins-readonly").value + const globalAdmins = opendiscord.configs.get("opendiscord:general").data.globalAdmins + const optionAdmins = option.get("opendiscord:admins").value + const readonlyAdmins = option.get("opendiscord:admins-readonly").value globalAdmins.forEach((admin) => { permissions.push({ @@ -127,40 +127,40 @@ export const registerActions = async () => { //create ticket const ticket = new api.ODTicket(channel.id,option,[ - new api.ODTicketData("openticket:busy",false), - new api.ODTicketData("openticket:ticket-message",null), - new api.ODTicketData("openticket:participants",participants), - new api.ODTicketData("openticket:channel-suffix",channelSuffix), + new api.ODTicketData("opendiscord:busy",false), + new api.ODTicketData("opendiscord:ticket-message",null), + new api.ODTicketData("opendiscord:participants",participants), + new api.ODTicketData("opendiscord:channel-suffix",channelSuffix), - new api.ODTicketData("openticket:open",true), - new api.ODTicketData("openticket:opened-by",user.id), - new api.ODTicketData("openticket:opened-on",new Date().getTime()), - new api.ODTicketData("openticket:closed",false), - new api.ODTicketData("openticket:closed-by",null), - new api.ODTicketData("openticket:closed-on",null), - new api.ODTicketData("openticket:claimed",false), - new api.ODTicketData("openticket:claimed-by",null), - new api.ODTicketData("openticket:claimed-on",null), - new api.ODTicketData("openticket:pinned",false), - new api.ODTicketData("openticket:pinned-by",null), - new api.ODTicketData("openticket:pinned-on",null), - new api.ODTicketData("openticket:for-deletion",false), + new api.ODTicketData("opendiscord:open",true), + new api.ODTicketData("opendiscord:opened-by",user.id), + new api.ODTicketData("opendiscord:opened-on",new Date().getTime()), + new api.ODTicketData("opendiscord:closed",false), + new api.ODTicketData("opendiscord:closed-by",null), + new api.ODTicketData("opendiscord:closed-on",null), + new api.ODTicketData("opendiscord:claimed",false), + new api.ODTicketData("opendiscord:claimed-by",null), + new api.ODTicketData("opendiscord:claimed-on",null), + new api.ODTicketData("opendiscord:pinned",false), + new api.ODTicketData("opendiscord:pinned-by",null), + new api.ODTicketData("opendiscord:pinned-on",null), + new api.ODTicketData("opendiscord:for-deletion",false), - new api.ODTicketData("openticket:category",category), - new api.ODTicketData("openticket:category-mode",categoryMode), + new api.ODTicketData("opendiscord:category",category), + new api.ODTicketData("opendiscord:category-mode",categoryMode), - new api.ODTicketData("openticket:autoclose-enabled",option.get("openticket:autoclose-enable-hours").value), - new api.ODTicketData("openticket:autoclose-hours",(option.get("openticket:autoclose-enable-hours").value ? option.get("openticket:autoclose-hours").value : 0)), - new api.ODTicketData("openticket:autoclosed",false), - new api.ODTicketData("openticket:autodelete-enabled",option.get("openticket:autodelete-enable-days").value), - new api.ODTicketData("openticket:autodelete-days",(option.get("openticket:autodelete-enable-days").value ? option.get("openticket:autodelete-days").value : 0)), + new api.ODTicketData("opendiscord:autoclose-enabled",option.get("opendiscord:autoclose-enable-hours").value), + new api.ODTicketData("opendiscord:autoclose-hours",(option.get("opendiscord:autoclose-enable-hours").value ? option.get("opendiscord:autoclose-hours").value : 0)), + new api.ODTicketData("opendiscord:autoclosed",false), + new api.ODTicketData("opendiscord:autodelete-enabled",option.get("opendiscord:autodelete-enable-days").value), + new api.ODTicketData("opendiscord:autodelete-days",(option.get("opendiscord:autodelete-enable-days").value ? option.get("opendiscord:autodelete-days").value : 0)), - new api.ODTicketData("openticket:answers",answers) + new api.ODTicketData("opendiscord:answers",answers) ]) //manage stats - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-created",1,"increase") - await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-created",user.id,1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-created",1,"increase") + await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-created",user.id,1,"increase") //manage bot permissions await opendiscord.events.get("onTicketPermissionsCreated").emit([option,opendiscord.permissions,channel,user]) @@ -172,7 +172,7 @@ export const registerActions = async () => { instance.ticket = ticket opendiscord.tickets.add(ticket) }), - new api.ODWorker("openticket:send-ticket-message",2,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:send-ticket-message",2,async (instance,params,source,cancel) => { const {guild,user,answers,option} = params const {ticket,channel} = instance @@ -180,37 +180,37 @@ export const registerActions = async () => { await opendiscord.events.get("onTicketMainMessageCreated").emit([ticket,channel,user]) //check if ticket message is enabled - if (!option.get("openticket:ticket-message-enabled").value) return + if (!option.get("opendiscord:ticket-message-enabled").value) return try { - const msg = await channel.send((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build(source,{guild,channel,user,ticket})).message) + const msg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build(source,{guild,channel,user,ticket})).message) - ticket.get("openticket:ticket-message").value = msg.id + ticket.get("opendiscord:ticket-message").value = msg.id //manage stats - await opendiscord.stats.get("openticket:ticket").setStat("openticket:messages-sent",ticket.id.value,1,"increase") + await opendiscord.stats.get("opendiscord:ticket").setStat("opendiscord:messages-sent",ticket.id.value,1,"increase") await opendiscord.events.get("afterTicketMainMessageCreated").emit([ticket,msg,channel,user]) }catch(err){ process.emit("uncaughtException",err) //something went wrong while sending the ticket message - channel.send((await opendiscord.builders.messages.getSafe("openticket:error").build("other",{guild,channel,user,error:"Ticket Message: Creation Error!\n=> Ticket Is Still Created Succesfully",layout:"advanced"})).message) + channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error").build("other",{guild,channel,user,error:"Ticket Message: Creation Error!\n=> Ticket Is Still Created Succesfully",layout:"advanced"})).message) } await opendiscord.events.get("afterTicketCreated").emit([ticket,user,channel]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,user,answers,option} = params const {ticket,channel} = instance //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.creation.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-created-logs").build(source,{guild,channel,user,ticket})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-logs").build(source,{guild,channel,user,ticket})) } //to dm - if (generalConfig.data.system.messages.creation.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("openticket:ticket-created-dm").build(source,{guild,channel,user,ticket})) + if (generalConfig.data.system.messages.creation.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-dm").build(source,{guild,channel,user,ticket})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,user,answers,option} = params const {ticket,channel} = instance diff --git a/src/actions/createTicketPermissions.ts b/src/actions/createTicketPermissions.ts index c5b4c33..2c1bb06 100644 --- a/src/actions/createTicketPermissions.ts +++ b/src/actions/createTicketPermissions.ts @@ -5,10 +5,10 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:create-ticket-permissions")) - opendiscord.actions.get("openticket:create-ticket-permissions").workers.add([ - new api.ODWorker("openticket:check-blacklist",4,(instance,params,source,cancel) => { - if (!params.option.get("openticket:allow-blacklisted-users").value && opendiscord.blacklist.exists(params.user.id)){ + opendiscord.actions.add(new api.ODAction("opendiscord:create-ticket-permissions")) + opendiscord.actions.get("opendiscord:create-ticket-permissions").workers.add([ + new api.ODWorker("opendiscord:check-blacklist",4,(instance,params,source,cancel) => { + if (!params.option.get("opendiscord:allow-blacklisted-users").value && opendiscord.blacklist.exists(params.user.id)){ instance.valid = false instance.reason = "blacklist" opendiscord.log(params.user.displayName+" tried to create a ticket but is blacklisted!","info",[ @@ -19,8 +19,8 @@ export const registerActions = async () => { return cancel() } }), - new api.ODWorker("openticket:check-cooldown",3,(instance,params,source,cancel) => { - const cooldown = opendiscord.cooldowns.get("openticket:option-cooldown_"+params.option.id.value) + new api.ODWorker("opendiscord:check-cooldown",3,(instance,params,source,cancel) => { + const cooldown = opendiscord.cooldowns.get("opendiscord:option-cooldown_"+params.option.id.value) if (cooldown && cooldown instanceof api.ODTimeoutCooldown && cooldown.use(params.user.id)){ instance.valid = false instance.reason = "cooldown" @@ -36,13 +36,13 @@ export const registerActions = async () => { return cancel() } }), - new api.ODWorker("openticket:check-global-limits",2,(instance,params,source,cancel) => { - const generalConfig = opendiscord.configs.get("openticket:general") + new api.ODWorker("opendiscord:check-global-limits",2,(instance,params,source,cancel) => { + const generalConfig = opendiscord.configs.get("opendiscord:general") if (!generalConfig.data.system.limits.enabled) return const allTickets = opendiscord.tickets.getAll() const globalTicketCount = allTickets.length - const userTickets = opendiscord.tickets.getFiltered((ticket) => ticket.exists("openticket:opened-by") && (ticket.get("openticket:opened-by").value == params.user.id)) + const userTickets = opendiscord.tickets.getFiltered((ticket) => ticket.exists("opendiscord:opened-by") && (ticket.get("opendiscord:opened-by").value == params.user.id)) const userTicketCount = userTickets.length if (globalTicketCount >= generalConfig.data.system.limits.globalMaximum){ @@ -67,15 +67,15 @@ export const registerActions = async () => { return cancel() } }), - new api.ODWorker("openticket:check-option-limits",1,(instance,params,source,cancel) => { - if (!params.option.exists("openticket:limits-enabled") || !params.option.get("openticket:limits-enabled").value) return + new api.ODWorker("opendiscord:check-option-limits",1,(instance,params,source,cancel) => { + if (!params.option.exists("opendiscord:limits-enabled") || !params.option.get("opendiscord:limits-enabled").value) return const allTickets = opendiscord.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value) const globalTicketCount = allTickets.length - const userTickets = opendiscord.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value && ticket.exists("openticket:opened-by") && (ticket.get("openticket:opened-by").value == params.user.id)) + const userTickets = opendiscord.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value && ticket.exists("opendiscord:opened-by") && (ticket.get("opendiscord:opened-by").value == params.user.id)) const userTicketCount = userTickets.length - if (globalTicketCount >= params.option.get("openticket:limits-maximum-global").value){ + if (globalTicketCount >= params.option.get("opendiscord:limits-maximum-global").value){ instance.valid = false instance.reason = "option-limit" opendiscord.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ @@ -85,7 +85,7 @@ export const registerActions = async () => { {key:"limit",value:"option"} ]) return cancel() - }else if (userTicketCount >= params.option.get("openticket:limits-maximum-user").value){ + }else if (userTicketCount >= params.option.get("opendiscord:limits-maximum-user").value){ instance.valid = false instance.reason = "option-user-limit" opendiscord.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[ @@ -97,7 +97,7 @@ export const registerActions = async () => { return cancel() } }), - new api.ODWorker("openticket:valid",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:valid",0,(instance,params,source,cancel) => { instance.valid = true instance.reason = null cancel() diff --git a/src/actions/createTranscript.ts b/src/actions/createTranscript.ts index 90e2d1f..07894b8 100644 --- a/src/actions/createTranscript.ts +++ b/src/actions/createTranscript.ts @@ -4,12 +4,12 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const transcriptConfig = opendiscord.configs.get("openticket:transcripts") +const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:create-transcript")) - opendiscord.actions.get("openticket:create-transcript").workers.add([ - new api.ODWorker("openticket:select-compiler",4,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:create-transcript")) + opendiscord.actions.get("opendiscord:create-transcript").workers.add([ + new api.ODWorker("opendiscord:select-compiler",4,async (instance,params,source,cancel) => { const {channel,user,ticket} = params if (channel.type != discord.ChannelType.GuildText) return cancel() if (!transcriptConfig.data.general.enabled) return cancel() @@ -26,10 +26,10 @@ export const registerActions = async () => { instance.participants = participants //select transcript compiler - if (transcriptConfig.data.general.mode == "text") instance.compiler = opendiscord.transcripts.get("openticket:text-compiler") - else if (transcriptConfig.data.general.mode == "html") instance.compiler = opendiscord.transcripts.get("openticket:html-compiler") + if (transcriptConfig.data.general.mode == "text") instance.compiler = opendiscord.transcripts.get("opendiscord:text-compiler") + else if (transcriptConfig.data.general.mode == "html") instance.compiler = opendiscord.transcripts.get("opendiscord:html-compiler") }), - new api.ODWorker("openticket:init-transcript",3,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:init-transcript",3,async (instance,params,source,cancel) => { const {channel,user,ticket} = params if (channel.type != discord.ChannelType.GuildText) return cancel() if (!transcriptConfig.data.general.enabled) return cancel() @@ -41,7 +41,7 @@ export const registerActions = async () => { const result = await instance.compiler.init(ticket,channel,user) if (result.success && result.pendingMessage && transcriptConfig.data.general.enableChannel){ //send init message to channel - const post = opendiscord.posts.get("openticket:transcripts") + const post = opendiscord.posts.get("opendiscord:transcripts") if (post){ instance.pendingMessage = await post.send(result.pendingMessage) } @@ -59,7 +59,7 @@ export const registerActions = async () => { } await opendiscord.events.get("afterTranscriptInitiated").emit([opendiscord.transcripts,ticket,channel,user]) }), - new api.ODWorker("openticket:compile-transcript",2,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:compile-transcript",2,async (instance,params,source,cancel) => { const {channel,user,ticket} = params if (channel.type != discord.ChannelType.GuildText) return cancel() if (!instance.compiler){ @@ -89,7 +89,7 @@ export const registerActions = async () => { } await opendiscord.events.get("afterTranscriptCompiled").emit([opendiscord.transcripts,ticket,channel,user]) }), - new api.ODWorker("openticket:ready-transcript",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:ready-transcript",1,async (instance,params,source,cancel) => { if (!instance.result){ instance.success = false cancel() @@ -110,7 +110,7 @@ export const registerActions = async () => { instance.pendingMessage.message.edit(channelMessage.message) }else{ //send ready message to channel - const post = opendiscord.posts.get("openticket:transcripts") + const post = opendiscord.posts.get("opendiscord:transcripts") if (post) await post.send(channelMessage) } } @@ -145,11 +145,11 @@ export const registerActions = async () => { }) //update stats - await opendiscord.stats.get("openticket:global").setStat("openticket:transcripts-created",1,"increase") - await opendiscord.stats.get("openticket:user").setStat("openticket:transcripts-created",params.user.id,1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:transcripts-created",1,"increase") + await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:transcripts-created",params.user.id,1,"increase") await opendiscord.events.get("afterTranscriptCreated").emit([opendiscord.transcripts,instance.result.ticket,instance.result.channel,instance.result.user]) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {user,channel,ticket} = params opendiscord.log(user.displayName+" created a transcript!","info",[ {key:"user",value:user.username}, diff --git a/src/actions/deleteTicket.ts b/src/actions/deleteTicket.ts index 72234bd..4c368b7 100644 --- a/src/actions/deleteTicket.ts +++ b/src/actions/deleteTicket.ts @@ -4,26 +4,26 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:delete-ticket")) - opendiscord.actions.get("openticket:delete-ticket").workers.add([ - new api.ODWorker("openticket:delete-ticket",3,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:delete-ticket")) + opendiscord.actions.get("opendiscord:delete-ticket").workers.add([ + new api.ODWorker("opendiscord:delete-ticket",3,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to delete ticket! Open Ticket doesn't support threads!") await opendiscord.events.get("onTicketDelete").emit([ticket,user,channel,reason]) //update ticket - ticket.get("openticket:for-deletion").value = true - ticket.get("openticket:busy").value = true + ticket.get("opendiscord:for-deletion").value = true + ticket.get("opendiscord:busy").value = true //update ticket message const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket deletion!","error",[ {key:"channel",value:"#"+channel.name}, @@ -35,20 +35,20 @@ export const registerActions = async () => { } } - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:delete-message").build(source,{guild,channel,user,ticket,reason})).message) + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(source,{guild,channel,user,ticket,reason})).message) //create transcript if (!params.withoutTranscript){ - const transcriptRes = await opendiscord.actions.get("openticket:create-transcript").run(source,{guild,channel,user,ticket}) + const transcriptRes = await opendiscord.actions.get("opendiscord:create-transcript").run(source,{guild,channel,user,ticket}) //transcript failure if (typeof transcriptRes.success == "boolean" && !transcriptRes.success && transcriptRes.compiler){ const {compiler} = transcriptRes - await channel.send((await opendiscord.builders.messages.getSafe("openticket:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason:transcriptRes.errorReason ?? null})).message) + await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason:transcriptRes.errorReason ?? null})).message) .catch((reason) => opendiscord.log("Unable to send transcript failure to ticket channel!","error",[{key:"id",value:channel.id}])) //undo deletion - ticket.get("openticket:for-deletion").value = false - ticket.get("openticket:busy").value = false + ticket.get("opendiscord:for-deletion").value = false + ticket.get("opendiscord:busy").value = false opendiscord.log("Canceled ticket deletion because of transcript system malfunction!","warning",[ {key:"compiler",value:compiler.id.value}, {key:"reason",value:transcriptRes.errorReason ?? "/"}, @@ -58,8 +58,8 @@ export const registerActions = async () => { } //update stats - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-deleted",1,"increase") - await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-deleted",user.id,1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-deleted",1,"increase") + await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-deleted",user.id,1,"increase") //delete ticket from manager opendiscord.tickets.remove(ticket.id) @@ -67,21 +67,21 @@ export const registerActions = async () => { //delete permissions from manager await (await import("../data/framework/permissionLoader.js")).removeTicketPermissions(ticket) }), - new api.ODWorker("openticket:discord-logs",2,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",2,async (instance,params,source,cancel) => { //logs before channel deletion => channel might still be used in log embeds const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.deleting.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.deleting.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) + if (creator && generalConfig.data.system.messages.deleting.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null})) }), - new api.ODWorker("openticket:delete-channel",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:delete-channel",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //delete channel & events await opendiscord.events.get("onTicketChannelDeletion").emit([ticket,channel,user]) @@ -93,7 +93,7 @@ export const registerActions = async () => { await opendiscord.events.get("afterTicketDeleted").emit([ticket,user,reason]) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params opendiscord.log(user.displayName+" deleted a ticket!","info",[ @@ -107,360 +107,360 @@ export const registerActions = async () => { ]) }) ]) - opendiscord.actions.get("openticket:delete-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:delete-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false - params.ticket.get("openticket:for-deletion").value = false + params.ticket.get("opendiscord:busy").value = false + params.ticket.get("opendiscord:for-deletion").value = false }) } export const registerVerifyBars = async () => { //DELETE TICKET TICKET MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:delete-ticket-ticket-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:delete-ticket-ticket-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket if (params.data == "reason"){ //delete with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:delete-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //delete without reason await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true,withoutTranscript:(params.data == "no-transcript")}) + opendiscord.actions.get("opendiscord:delete-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true,withoutTranscript:(params.data == "no-transcript")}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable - ticket.get("openticket:for-deletion").value = true - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + ticket.get("opendiscord:for-deletion").value = true + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - opendiscord.verifybars.get("openticket:delete-ticket-ticket-message").failure.add([ - new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:delete-ticket-ticket-message").failure.add([ + new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //DELETE TICKET CLOSE MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-close-message",opendiscord.builders.messages.getSafe("openticket:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:delete-ticket-close-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-close-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:delete-ticket-close-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket if (params.data == "reason"){ //delete with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:delete-ticket-reason").build("close-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("close-message",{guild,channel,user,ticket})) }else{ //delete without reason await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) + opendiscord.actions.get("opendiscord:delete-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable - ticket.get("openticket:for-deletion").value = true - await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("close-message",{guild,channel,user,ticket,reason:null})) + ticket.get("opendiscord:for-deletion").value = true + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("close-message",{guild,channel,user,ticket,reason:null})) } }) ]) - opendiscord.verifybars.get("openticket:delete-ticket-close-message").failure.add([ - new api.ODWorker("openticket:back-to-close-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:delete-ticket-close-message").failure.add([ + new api.ODWorker("opendiscord:back-to-close-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason})) }) ]) //DELETE TICKET REOPEN MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-reopen-message",opendiscord.builders.messages.getSafe("openticket:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:delete-ticket-reopen-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-reopen-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:delete-ticket-reopen-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket if (params.data == "reason"){ //delete with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:delete-ticket-reason").build("reopen-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("reopen-message",{guild,channel,user,ticket})) }else{ //delete without reason await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) + opendiscord.actions.get("opendiscord:delete-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable - ticket.get("openticket:for-deletion").value = true - await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("reopen-message",{guild,channel,user,ticket,reason:null})) + ticket.get("opendiscord:for-deletion").value = true + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("reopen-message",{guild,channel,user,ticket,reason:null})) } }) ]) - opendiscord.verifybars.get("openticket:delete-ticket-reopen-message").failure.add([ - new api.ODWorker("openticket:back-to-reopen-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:delete-ticket-reopen-message").failure.add([ + new api.ODWorker("opendiscord:back-to-reopen-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason})) }) ]) //DELETE TICKET AUTOCLOSE MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:delete-ticket-autoclose-message",opendiscord.builders.messages.getSafe("openticket:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:delete-ticket-autoclose-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-autoclose-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:delete-ticket-autoclose-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket if (params.data == "reason"){ //delete with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:delete-ticket-reason").build("autoclose-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("autoclose-message",{guild,channel,user,ticket})) }else{ //delete without reason await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) + opendiscord.actions.get("opendiscord:delete-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable - ticket.get("openticket:for-deletion").value = true - await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("autoclose-message",{guild,channel,user,ticket,reason:null})) + ticket.get("opendiscord:for-deletion").value = true + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("autoclose-message",{guild,channel,user,ticket,reason:null})) } }) ]) - opendiscord.verifybars.get("openticket:delete-ticket-autoclose-message").failure.add([ - new api.ODWorker("openticket:back-to-autoclose-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:delete-ticket-autoclose-message").failure.add([ + new api.ODWorker("opendiscord:back-to-autoclose-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await opendiscord.builders.messages.getSafe("openticket:autoclose-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("other",{guild,channel,user,ticket})) }) ]) } \ No newline at end of file diff --git a/src/actions/handleTranscriptErrors.ts b/src/actions/handleTranscriptErrors.ts index 2249e81..5c83ab1 100644 --- a/src/actions/handleTranscriptErrors.ts +++ b/src/actions/handleTranscriptErrors.ts @@ -3,75 +3,75 @@ /////////////////////////////////////// import {opendiscord, api, utilities} from "../index" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerButtonResponders = async () => { //TRANSCRIPT ERROR RETRY - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:transcript-error-retry",/^od:transcript-error-retry_([^_]+)/)) - opendiscord.responders.buttons.get("openticket:transcript-error-retry").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:transcript-error-retry",/^od:transcript-error-retry_([^_]+)/)) + opendiscord.responders.buttons.get("opendiscord:transcript-error-retry").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "slash" && originalSource != "text" && originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "other") return if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket (without reason) await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Retried)",sendMessage:false,withoutTranscript:false}) + opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Retried)",sendMessage:false,withoutTranscript:false}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable - ticket.get("openticket:for-deletion").value = true - await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Retried)"})) + ticket.get("opendiscord:for-deletion").value = true + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Retried)"})) }), - new api.ODWorker("openticket:logs",-1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,async (instance,params,source,cancel) => { const {user,channel} = instance if (channel.isDMBased()) return opendiscord.log(user.displayName+" retried deleting a ticket with transcript!","info",[ @@ -85,71 +85,71 @@ export const registerButtonResponders = async () => { ]) //TRANSCRIPT ERROR CONTINUE - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:transcript-error-continue",/^od:transcript-error-continue_([^_]+)/)) - opendiscord.responders.buttons.get("openticket:transcript-error-continue").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:transcript-error-continue",/^od:transcript-error-continue_([^_]+)/)) + opendiscord.responders.buttons.get("opendiscord:transcript-error-continue").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "slash" && originalSource != "text" && originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "other") return if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start deleting ticket (without reason) await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Continued)",sendMessage:false,withoutTranscript:true}) + opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Continued)",sendMessage:false,withoutTranscript:true}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable - ticket.get("openticket:for-deletion").value = true - await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Continued)"})) + ticket.get("opendiscord:for-deletion").value = true + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Continued)"})) }), - new api.ODWorker("openticket:logs",-1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,async (instance,params,source,cancel) => { const {user,channel} = instance if (channel.isDMBased()) return opendiscord.log(user.displayName+" continued deleting a ticket without transcript!","info",[ diff --git a/src/actions/handleVerifyBar.ts b/src/actions/handleVerifyBar.ts index c222db7..2794d71 100644 --- a/src/actions/handleVerifyBar.ts +++ b/src/actions/handleVerifyBar.ts @@ -5,9 +5,9 @@ import {opendiscord, api, utilities} from "../index" export const registerButtonResponders = async () => { //VERIFYBAR SUCCESS - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:verifybar-success",/^od:verifybar-success_([^_]+)/)) - opendiscord.responders.buttons.get("openticket:verifybar-success").workers.add( - new api.ODWorker("openticket:handle-verifybar",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:verifybar-success",/^od:verifybar-success_([^_]+)/)) + opendiscord.responders.buttons.get("opendiscord:verifybar-success").workers.add( + new api.ODWorker("opendiscord:handle-verifybar",0,async (instance,params,source,cancel) => { const id = instance.interaction.customId.split("_")[1] const customData = instance.interaction.customId.split("_")[2] as string|undefined @@ -18,9 +18,9 @@ export const registerButtonResponders = async () => { ) //VERIFYBAR FAILURE - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:verifybar-failure",/^od:verifybar-failure_([^_]+)/)) - opendiscord.responders.buttons.get("openticket:verifybar-failure").workers.add( - new api.ODWorker("openticket:handle-verifybar",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:verifybar-failure",/^od:verifybar-failure_([^_]+)/)) + opendiscord.responders.buttons.get("opendiscord:verifybar-failure").workers.add( + new api.ODWorker("opendiscord:handle-verifybar",0,async (instance,params,source,cancel) => { const id = instance.interaction.customId.split("_")[1] const customData = instance.interaction.customId.split("_")[2] as string|undefined diff --git a/src/actions/moveTicket.ts b/src/actions/moveTicket.ts index da4cbcd..11c21e3 100644 --- a/src/actions/moveTicket.ts +++ b/src/actions/moveTicket.ts @@ -4,12 +4,12 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:move-ticket")) - opendiscord.actions.get("openticket:move-ticket").workers.add([ - new api.ODWorker("openticket:move-ticket",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:move-ticket")) + opendiscord.actions.get("opendiscord:move-ticket").workers.add([ + new api.ODWorker("opendiscord:move-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params if (channel.isThread()) throw new api.ODSystemError("Unable to move ticket! Open Ticket doesn't support threads!") @@ -17,18 +17,18 @@ export const registerActions = async () => { ticket.option = data //update stats - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-moved",1,"increase") - await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-moved",user.id,1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-moved",1,"increase") + await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-moved",user.id,1,"increase") //get new channel properties - const channelPrefix = ticket.option.get("openticket:channel-prefix").value - const channelSuffix = ticket.get("openticket:channel-suffix").value - const channelCategory = ticket.option.get("openticket:channel-category").value - const channelBackupCategory = ticket.option.get("openticket:channel-category-backup").value - const rawClaimCategory = ticket.option.get("openticket:channel-categories-claimed").value.find((c) => c.user == user.id) + const channelPrefix = ticket.option.get("opendiscord:channel-prefix").value + const channelSuffix = ticket.get("opendiscord:channel-suffix").value + const channelCategory = ticket.option.get("opendiscord:channel-category").value + const channelBackupCategory = ticket.option.get("opendiscord:channel-category-backup").value + const rawClaimCategory = ticket.option.get("opendiscord:channel-categories-claimed").value.find((c) => c.user == user.id) const claimCategory = (rawClaimCategory) ? rawClaimCategory.category : null - const closeCategory = ticket.option.get("openticket:channel-category-closed").value - const channelDescription = ticket.option.get("openticket:channel-description").value + const closeCategory = ticket.option.get("opendiscord:channel-category-closed").value + const channelDescription = ticket.option.get("opendiscord:channel-description").value const channelName = channelPrefix+channelSuffix //handle category @@ -38,7 +38,7 @@ export const registerActions = async () => { //use claim category category = claimCategory categoryMode = "claimed" - }else if (closeCategory != "" && ticket.get("openticket:closed").value){ + }else if (closeCategory != "" && ticket.get("opendiscord:closed").value){ //use close category category = closeCategory categoryMode = "closed" @@ -79,8 +79,8 @@ export const registerActions = async () => { if (channel.parentId != category) await utilities.timedAwait(channel.setParent(category,{lockPermissions:false}),2500,(err) => { opendiscord.log("Failed to change channel category on ticket move","error") }) - ticket.get("openticket:category-mode").value = categoryMode - ticket.get("openticket:category").value = category + ticket.get("opendiscord:category-mode").value = categoryMode + ticket.get("opendiscord:category").value = category }catch(e){ opendiscord.log("Unable to move ticket to 'moved category'!","error",[ {key:"channel",value:"#"+channel.name}, @@ -97,9 +97,9 @@ export const registerActions = async () => { allow:[], deny:["ViewChannel","SendMessages","ReadMessageHistory"] }] - const globalAdmins = opendiscord.configs.get("openticket:general").data.globalAdmins - const optionAdmins = ticket.option.get("openticket:admins").value - const readonlyAdmins = ticket.option.get("openticket:admins-readonly").value + const globalAdmins = opendiscord.configs.get("opendiscord:general").data.globalAdmins + const optionAdmins = ticket.option.get("opendiscord:admins").value + const readonlyAdmins = ticket.option.get("opendiscord:admins-readonly").value globalAdmins.forEach((admin) => { permissions.push({ @@ -129,7 +129,7 @@ export const registerActions = async () => { }) }) //transfer all old user-participants over to the new ticket (creator & participants) - ticket.get("openticket:participants").value.forEach((p) => { + ticket.get("opendiscord:participants").value.forEach((p) => { if (p.type == "user") permissions.push({ type:discord.OverwriteType.Member, id:p.id, @@ -151,8 +151,8 @@ export const registerActions = async () => { const id = permission.id as string participants.push({type,id}) }) - ticket.get("openticket:participants").value = participants - ticket.get("openticket:participants").refreshDatabase() + ticket.get("opendiscord:participants").value = participants + ticket.get("opendiscord:participants").refreshDatabase() //rename channel (and give error when crashed) const originalName = channel.name @@ -161,7 +161,7 @@ export const registerActions = async () => { opendiscord.log("Failed to rename channel on ticket move","error") }) }catch(err){ - await channel.send((await opendiscord.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-move",{guild,channel,user,originalName,newName:channelName})).message) + await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-move",{guild,channel,user,originalName,newName:channelName})).message) } try{ if (channel.type == discord.ChannelType.GuildText) channel.setTopic(channelDescription) @@ -171,7 +171,7 @@ export const registerActions = async () => { const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket renaming!","error",[ {key:"channel",value:"#"+channel.name}, @@ -184,24 +184,24 @@ export const registerActions = async () => { } //reply with new message - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:move-message").build(source,{guild,channel,user,ticket,reason,data})).message) - ticket.get("openticket:busy").value = false + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:move-message").build(source,{guild,channel,user,ticket,reason,data})).message) + ticket.get("opendiscord:busy").value = false await opendiscord.events.get("afterTicketMoved").emit([ticket,user,channel,reason]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.moving.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.moving.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) + if (creator && generalConfig.data.system.messages.moving.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params opendiscord.log(user.displayName+" moved a ticket!","info",[ @@ -214,8 +214,8 @@ export const registerActions = async () => { ]) }) ]) - opendiscord.actions.get("openticket:move-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:move-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false + params.ticket.get("opendiscord:busy").value = false }) } \ No newline at end of file diff --git a/src/actions/pinTicket.ts b/src/actions/pinTicket.ts index dafc6fe..0ac9446 100644 --- a/src/actions/pinTicket.ts +++ b/src/actions/pinTicket.ts @@ -4,26 +4,26 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:pin-ticket")) - opendiscord.actions.get("openticket:pin-ticket").workers.add([ - new api.ODWorker("openticket:pin-ticket",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:pin-ticket")) + opendiscord.actions.get("opendiscord:pin-ticket").workers.add([ + new api.ODWorker("opendiscord:pin-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to pin ticket! Open Ticket doesn't support threads!") await opendiscord.events.get("onTicketPin").emit([ticket,user,channel,reason]) //update ticket - ticket.get("openticket:pinned").value = true - ticket.get("openticket:pinned-by").value = user.id - ticket.get("openticket:pinned-on").value = new Date().getTime() - ticket.get("openticket:busy").value = true + ticket.get("opendiscord:pinned").value = true + ticket.get("opendiscord:pinned-by").value = user.id + ticket.get("opendiscord:pinned-on").value = new Date().getTime() + ticket.get("opendiscord:busy").value = true //update stats - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-pinned",1,"increase") - await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-pinned",user.id,1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-pinned",1,"increase") + await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-pinned",user.id,1,"increase") //move to top of category if (channel.parent){ @@ -38,14 +38,14 @@ export const registerActions = async () => { opendiscord.log("Failed to rename channel on ticket pin","error") }) }catch(err){ - await channel.send((await opendiscord.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-pin",{guild,channel,user,originalName,newName})).message) + await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-pin",{guild,channel,user,originalName,newName})).message) } //update ticket message const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket pinning!","error",[ {key:"channel",value:"#"+channel.name}, @@ -58,24 +58,24 @@ export const registerActions = async () => { } //reply with new message - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:pin-message").build(source,{guild,channel,user,ticket,reason})).message) - ticket.get("openticket:busy").value = false + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("opendiscord:busy").value = false await opendiscord.events.get("afterTicketPinned").emit([ticket,user,channel,reason]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.pinning.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) + if (creator && generalConfig.data.system.messages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params opendiscord.log(user.displayName+" pinned a ticket!","info",[ @@ -92,184 +92,184 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //PIN TICKET TICKET MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:pin-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:pin-ticket-ticket-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:pin-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:pin-ticket-ticket-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.pin if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already pinned - if (ticket.get("openticket:pinned").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) + if (ticket.get("opendiscord:pinned").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start pinning ticket if (params.data == "reason"){ //pin with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:pin-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:pin-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //pin without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:pin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:pin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - opendiscord.verifybars.get("openticket:pin-ticket-ticket-message").failure.add([ - new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:pin-ticket-ticket-message").failure.add([ + new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //PIN TICKET UNPIN MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:pin-ticket-unpin-message",opendiscord.builders.messages.getSafe("openticket:verifybar-unpin-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:pin-ticket-unpin-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:pin-ticket-unpin-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-unpin-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.pin if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already pinned - if (ticket.get("openticket:pinned").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) + if (ticket.get("opendiscord:pinned").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start pinning ticket if (params.data == "reason"){ //pin with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:pin-ticket-reason").build("unpin-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:pin-ticket-reason").build("unpin-message",{guild,channel,user,ticket})) }else{ //pin without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:pin-ticket").run("unpin-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:pin-message").build("unpin-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("opendiscord:pin-ticket").run("unpin-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("unpin-message",{guild,channel,user,ticket,reason:null})) } }) ]) - opendiscord.verifybars.get("openticket:pin-ticket-unpin-message").failure.add([ - new api.ODWorker("openticket:back-to-unpin-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").failure.add([ + new api.ODWorker("opendiscord:back-to-unpin-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:unpin-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("other",{guild,channel,user,ticket,reason})) }) ]) - opendiscord.actions.get("openticket:pin-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:pin-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false + params.ticket.get("opendiscord:busy").value = false }) } \ No newline at end of file diff --git a/src/actions/reactionRole.ts b/src/actions/reactionRole.ts index 2400c85..80daaad 100644 --- a/src/actions/reactionRole.ts +++ b/src/actions/reactionRole.ts @@ -5,14 +5,14 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:reaction-role")) - opendiscord.actions.get("openticket:reaction-role").workers.add([ - new api.ODWorker("openticket:reaction-role",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:reaction-role")) + opendiscord.actions.get("opendiscord:reaction-role").workers.add([ + new api.ODWorker("opendiscord:reaction-role",2,async (instance,params,source,cancel) => { const {guild,user,option,overwriteMode} = params const role = opendiscord.roles.get(option.id) if (!role) throw new api.ODSystemError("ODAction(ot:reaction-role) => Unknown reaction role (ODRole)") instance.role = role - const mode = (overwriteMode) ? overwriteMode : role.get("openticket:mode").value + const mode = (overwriteMode) ? overwriteMode : role.get("opendiscord:mode").value await opendiscord.events.get("onRoleUpdate").emit([user,role]) @@ -21,7 +21,7 @@ export const registerActions = async () => { if (!member) throw new api.ODSystemError("ODAction(ot:reaction-role) => User isn't a member of the server!") //get all roles - const roleIds = role.get("openticket:roles").value + const roleIds = role.get("opendiscord:roles").value const roles: discord.Role[] = [] for (const id of roleIds){ const r = await opendiscord.client.fetchGuildRole(guild,id) @@ -55,7 +55,7 @@ export const registerActions = async () => { //get roles to remove on add if (result.find((r) => r.action == "added")){ //get all remove roles - const removeRoleIds = role.get("openticket:remove-roles-on-add").value + const removeRoleIds = role.get("opendiscord:remove-roles-on-add").value const removeRoles: discord.Role[] = [] for (const id of removeRoleIds){ const r = await opendiscord.client.fetchGuildRole(guild,id) @@ -81,7 +81,7 @@ export const registerActions = async () => { instance.result = result await opendiscord.events.get("afterRolesUpdated").emit([user,role]) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,user,option} = params opendiscord.log(user.displayName+" updated his roles!","info",[ {key:"user",value:user.username}, diff --git a/src/actions/removeTicketUser.ts b/src/actions/removeTicketUser.ts index d7908d1..489ec8b 100644 --- a/src/actions/removeTicketUser.ts +++ b/src/actions/removeTicketUser.ts @@ -4,23 +4,23 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:remove-ticket-user")) - opendiscord.actions.get("openticket:remove-ticket-user").workers.add([ - new api.ODWorker("openticket:remove-ticket-user",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:remove-ticket-user")) + opendiscord.actions.get("opendiscord:remove-ticket-user").workers.add([ + new api.ODWorker("opendiscord:remove-ticket-user",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params if (channel.isThread()) throw new api.ODSystemError("Unable to remove user from ticket! Open Ticket doesn't support threads!") await opendiscord.events.get("onTicketUserRemove").emit([ticket,user,data,channel,reason]) //update ticket - const index = ticket.get("openticket:participants").value.findIndex((p) => p.type == "user" && p.id == data.id) + const index = ticket.get("opendiscord:participants").value.findIndex((p) => p.type == "user" && p.id == data.id) if (index < 0) return cancel() - ticket.get("openticket:participants").value.splice(index,1) - ticket.get("openticket:participants").refreshDatabase() - ticket.get("openticket:busy").value = true + ticket.get("opendiscord:participants").value.splice(index,1) + ticket.get("opendiscord:participants").refreshDatabase() + ticket.get("opendiscord:busy").value = true //update channel permissions try{ @@ -33,7 +33,7 @@ export const registerActions = async () => { const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket user removal!","error",[ {key:"channel",value:channel.id}, @@ -45,24 +45,24 @@ export const registerActions = async () => { } //reply with new message - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:remove-message").build(source,{guild,channel,user,ticket,reason,data})).message) - ticket.get("openticket:busy").value = false + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:remove-message").build(source,{guild,channel,user,ticket,reason,data})).message) + ticket.get("opendiscord:busy").value = false await opendiscord.events.get("afterTicketUserRemoved").emit([ticket,user,data,channel,reason]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.removing.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.removing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) + if (creator && generalConfig.data.system.messages.removing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket,data} = params opendiscord.log(user.displayName+" removed "+data.displayName+" from a ticket!","info",[ @@ -75,8 +75,8 @@ export const registerActions = async () => { ]) }) ]) - opendiscord.actions.get("openticket:remove-ticket-user").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:remove-ticket-user").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false + params.ticket.get("opendiscord:busy").value = false }) } \ No newline at end of file diff --git a/src/actions/renameTicket.ts b/src/actions/renameTicket.ts index 331ad32..ee0a722 100644 --- a/src/actions/renameTicket.ts +++ b/src/actions/renameTicket.ts @@ -4,12 +4,12 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:rename-ticket")) - opendiscord.actions.get("openticket:rename-ticket").workers.add([ - new api.ODWorker("openticket:rename-ticket",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:rename-ticket")) + opendiscord.actions.get("opendiscord:rename-ticket").workers.add([ + new api.ODWorker("opendiscord:rename-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params if (channel.isThread()) throw new api.ODSystemError("Unable to rename ticket! Open Ticket doesn't support threads!") @@ -22,14 +22,14 @@ export const registerActions = async () => { opendiscord.log("Failed to rename channel on ticket rename","error") }) }catch(err){ - await channel.send((await opendiscord.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-rename",{guild,channel,user,originalName,newName:data})).message) + await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-rename",{guild,channel,user,originalName,newName:data})).message) } //update ticket message const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket renaming!","error",[ {key:"channel",value:"#"+channel.name}, @@ -42,24 +42,24 @@ export const registerActions = async () => { } //reply with new message - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:rename-message").build(source,{guild,channel,user,ticket,reason,data})).message) - ticket.get("openticket:busy").value = false + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:rename-message").build(source,{guild,channel,user,ticket,reason,data})).message) + ticket.get("opendiscord:busy").value = false await opendiscord.events.get("afterTicketRenamed").emit([ticket,user,channel,reason]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason,data} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.renaming.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.renaming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) + if (creator && generalConfig.data.system.messages.renaming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params opendiscord.log(user.displayName+" renamed a ticket!","info",[ @@ -72,8 +72,8 @@ export const registerActions = async () => { ]) }) ]) - opendiscord.actions.get("openticket:rename-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:rename-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false + params.ticket.get("opendiscord:busy").value = false }) } \ No newline at end of file diff --git a/src/actions/reopenTicket.ts b/src/actions/reopenTicket.ts index bf7dc70..70d3c36 100644 --- a/src/actions/reopenTicket.ts +++ b/src/actions/reopenTicket.ts @@ -4,32 +4,32 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:reopen-ticket")) - opendiscord.actions.get("openticket:reopen-ticket").workers.add([ - new api.ODWorker("openticket:reopen-ticket",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:reopen-ticket")) + opendiscord.actions.get("opendiscord:reopen-ticket").workers.add([ + new api.ODWorker("opendiscord:reopen-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to reopen ticket! Open Ticket doesn't support threads!") await opendiscord.events.get("onTicketReopen").emit([ticket,user,channel,reason]) //update ticket - ticket.get("openticket:closed").value = false - ticket.get("openticket:open").value = true - ticket.get("openticket:autoclosed").value = false - ticket.get("openticket:closed-by").value = null - ticket.get("openticket:closed-on").value = null - ticket.get("openticket:busy").value = true + ticket.get("opendiscord:closed").value = false + ticket.get("opendiscord:open").value = true + ticket.get("opendiscord:autoclosed").value = false + ticket.get("opendiscord:closed-by").value = null + ticket.get("opendiscord:closed-on").value = null + ticket.get("opendiscord:busy").value = true //update stats - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-reopened",1,"increase") - await opendiscord.stats.get("openticket:user").setStat("openticket:tickets-reopened",user.id,1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-reopened",1,"increase") + await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-reopened",user.id,1,"increase") //update category - const channelCategory = ticket.option.get("openticket:channel-category").value - const channelBackupCategory = ticket.option.get("openticket:channel-category-backup").value + const channelCategory = ticket.option.get("opendiscord:channel-category").value + const channelBackupCategory = ticket.option.get("opendiscord:channel-category-backup").value if (channelCategory !== ""){ //category enabled try { @@ -54,14 +54,14 @@ export const registerActions = async () => { }else{ //use backup category channel.setParent(backupCategory,{lockPermissions:false}) - ticket.get("openticket:category-mode").value = "backup" - ticket.get("openticket:category").value = backupCategory.id + ticket.get("opendiscord:category-mode").value = "backup" + ticket.get("opendiscord:category").value = backupCategory.id } }else{ //use default category channel.setParent(normalCategory,{lockPermissions:false}) - ticket.get("openticket:category-mode").value = "normal" - ticket.get("openticket:category").value = normalCategory.id + ticket.get("opendiscord:category-mode").value = "normal" + ticket.get("opendiscord:category").value = normalCategory.id } } }catch(e){ @@ -73,8 +73,8 @@ export const registerActions = async () => { } }else{ channel.setParent(null,{lockPermissions:false}) - ticket.get("openticket:category-mode").value = null - ticket.get("openticket:category").value = null + ticket.get("opendiscord:category-mode").value = null + ticket.get("opendiscord:category").value = null } //update permissions @@ -84,9 +84,9 @@ export const registerActions = async () => { allow:[], deny:["ViewChannel","SendMessages","ReadMessageHistory"] }] - const globalAdmins = opendiscord.configs.get("openticket:general").data.globalAdmins - const optionAdmins = ticket.option.get("openticket:admins").value - const readonlyAdmins = ticket.option.get("openticket:admins-readonly").value + const globalAdmins = opendiscord.configs.get("opendiscord:general").data.globalAdmins + const optionAdmins = ticket.option.get("opendiscord:admins").value + const readonlyAdmins = ticket.option.get("opendiscord:admins-readonly").value globalAdmins.forEach((admin) => { permissions.push({ @@ -115,7 +115,7 @@ export const registerActions = async () => { deny:["SendMessages","AddReactions","AttachFiles","SendPolls"] }) }) - ticket.get("openticket:participants").value.forEach((participant) => { + ticket.get("opendiscord:participants").value.forEach((participant) => { //all participants that aren't roles/admins if (participant.type == "user"){ permissions.push({ @@ -132,7 +132,7 @@ export const registerActions = async () => { const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket reopening!","error",[ {key:"channel",value:"#"+channel.name}, @@ -144,24 +144,24 @@ export const registerActions = async () => { } } - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:reopen-message").build(source,{guild,channel,user,ticket,reason})).message) - ticket.get("openticket:busy").value = false + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("opendiscord:busy").value = false await opendiscord.events.get("afterTicketReopened").emit([ticket,user,channel,reason]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.reopening.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.reopening.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) + if (creator && generalConfig.data.system.messages.reopening.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params opendiscord.log(user.displayName+" reopened a ticket!","info",[ @@ -178,272 +178,272 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //REOPEN TICKET TICKET MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:reopen-ticket-ticket-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:reopen-ticket-ticket-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.reopen if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not closed - if (!ticket.get("openticket:closed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + if (!ticket.get("opendiscord:closed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start reopening ticket if (params.data == "reason"){ //reopen with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:reopen-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //reopen without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:reopen-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:reopen-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - opendiscord.verifybars.get("openticket:reopen-ticket-ticket-message").failure.add([ - new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:reopen-ticket-ticket-message").failure.add([ + new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //REOPEN TICKET CLOSE MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-close-message",opendiscord.builders.messages.getSafe("openticket:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:reopen-ticket-close-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket-close-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:reopen-ticket-close-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.reopen if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not closed - if (!ticket.get("openticket:closed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + if (!ticket.get("opendiscord:closed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start reopening ticket if (params.data == "reason"){ //reopen with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:reopen-ticket-reason").build("close-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("close-message",{guild,channel,user,ticket})) }else{ //reopen without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:reopen-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("close-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("opendiscord:reopen-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("close-message",{guild,channel,user,ticket,reason:null})) } }) ]) - opendiscord.verifybars.get("openticket:reopen-ticket-close-message").failure.add([ - new api.ODWorker("openticket:back-to-close-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:reopen-ticket-close-message").failure.add([ + new api.ODWorker("opendiscord:back-to-close-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason})) }) ]) //REOPEN TICKET AUTOCLOSE MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:reopen-ticket-autoclose-message",opendiscord.builders.messages.getSafe("openticket:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:reopen-ticket-autoclose-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket-autoclose-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.reopen if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not closed - if (!ticket.get("openticket:closed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + if (!ticket.get("opendiscord:closed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start reopening ticket if (params.data == "reason"){ //reopen with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:reopen-ticket-reason").build("autoclose-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("autoclose-message",{guild,channel,user,ticket})) }else{ //reopen without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:reopen-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("autoclose-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("opendiscord:reopen-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("autoclose-message",{guild,channel,user,ticket,reason:null})) } }) ]) - opendiscord.verifybars.get("openticket:reopen-ticket-autoclose-message").failure.add([ - new api.ODWorker("openticket:back-to-autoclose-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").failure.add([ + new api.ODWorker("opendiscord:back-to-autoclose-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await opendiscord.builders.messages.getSafe("openticket:autoclose-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("other",{guild,channel,user,ticket})) }) ]) - opendiscord.actions.get("openticket:reopen-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:reopen-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false + params.ticket.get("opendiscord:busy").value = false }) } \ No newline at end of file diff --git a/src/actions/unclaimTicket.ts b/src/actions/unclaimTicket.ts index 9186427..8972228 100644 --- a/src/actions/unclaimTicket.ts +++ b/src/actions/unclaimTicket.ts @@ -4,26 +4,26 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:unclaim-ticket")) - opendiscord.actions.get("openticket:unclaim-ticket").workers.add([ - new api.ODWorker("openticket:unclaim-ticket",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:unclaim-ticket")) + opendiscord.actions.get("opendiscord:unclaim-ticket").workers.add([ + new api.ODWorker("opendiscord:unclaim-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to unclaim ticket! Open Ticket doesn't support threads!") await opendiscord.events.get("onTicketUnclaim").emit([ticket,user,channel,reason]) //update ticket - ticket.get("openticket:claimed").value = false - ticket.get("openticket:claimed-by").value = null - ticket.get("openticket:claimed-on").value = null - ticket.get("openticket:busy").value = true + ticket.get("opendiscord:claimed").value = false + ticket.get("opendiscord:claimed-by").value = null + ticket.get("opendiscord:claimed-on").value = null + ticket.get("opendiscord:busy").value = true //update category - const channelCategory = ticket.option.get("openticket:channel-category").value - const channelBackupCategory = ticket.option.get("openticket:channel-category-backup").value + const channelCategory = ticket.option.get("opendiscord:channel-category").value + const channelBackupCategory = ticket.option.get("opendiscord:channel-category-backup").value if (channelCategory !== ""){ //category enabled try { @@ -48,14 +48,14 @@ export const registerActions = async () => { }else{ //use backup category channel.setParent(backupCategory,{lockPermissions:false}) - ticket.get("openticket:category-mode").value = "backup" - ticket.get("openticket:category").value = backupCategory.id + ticket.get("opendiscord:category-mode").value = "backup" + ticket.get("opendiscord:category").value = backupCategory.id } }else{ //use default category channel.setParent(normalCategory,{lockPermissions:false}) - ticket.get("openticket:category-mode").value = "normal" - ticket.get("openticket:category").value = normalCategory.id + ticket.get("opendiscord:category-mode").value = "normal" + ticket.get("opendiscord:category").value = normalCategory.id } } @@ -68,15 +68,15 @@ export const registerActions = async () => { } }else{ channel.setParent(null,{lockPermissions:false}) - ticket.get("openticket:category-mode").value = null - ticket.get("openticket:category").value = null + ticket.get("opendiscord:category-mode").value = null + ticket.get("opendiscord:category").value = null } //update ticket message const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket unclaiming!","error",[ {key:"channel",value:"#"+channel.name}, @@ -89,24 +89,24 @@ export const registerActions = async () => { } //reply with new message - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:unclaim-message").build(source,{guild,channel,user,ticket,reason})).message) - ticket.get("openticket:busy").value = false + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("opendiscord:busy").value = false await opendiscord.events.get("afterTicketUnclaimed").emit([ticket,user,channel,reason]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.claiming.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) + if (creator && generalConfig.data.system.messages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params opendiscord.log(user.displayName+" unclaimed a ticket!","info",[ @@ -123,184 +123,184 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //UNCLAIM TICKET TICKET MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:unclaim-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:unclaim-ticket-ticket-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unclaim-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:unclaim-ticket-ticket-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unclaim if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not claimed - if (!ticket.get("openticket:claimed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) + if (!ticket.get("opendiscord:claimed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start unclaiming ticket if (params.data == "reason"){ //unclaim with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:unclaim-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unclaim-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //unclaim without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:unclaim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:unclaim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - opendiscord.verifybars.get("openticket:unclaim-ticket-ticket-message").failure.add([ - new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:unclaim-ticket-ticket-message").failure.add([ + new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //UNCLAIM TICKET CLAIM MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:unclaim-ticket-claim-message",opendiscord.builders.messages.getSafe("openticket:verifybar-claim-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:unclaim-ticket-claim-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unclaim-ticket-claim-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-claim-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unclaim if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not claimed - if (!ticket.get("openticket:claimed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) + if (!ticket.get("opendiscord:claimed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start unclaiming ticket if (params.data == "reason"){ //unclaim with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:unclaim-ticket-reason").build("claim-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unclaim-ticket-reason").build("claim-message",{guild,channel,user,ticket})) }else{ //unclaim without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:unclaim-ticket").run("claim-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:unclaim-message").build("claim-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("opendiscord:unclaim-ticket").run("claim-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("claim-message",{guild,channel,user,ticket,reason:null})) } }) ]) - opendiscord.verifybars.get("openticket:unclaim-ticket-claim-message").failure.add([ - new api.ODWorker("openticket:back-to-claim-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").failure.add([ + new api.ODWorker("opendiscord:back-to-claim-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:claim-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("other",{guild,channel,user,ticket,reason})) }) ]) - opendiscord.actions.get("openticket:unclaim-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:unclaim-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false + params.ticket.get("opendiscord:busy").value = false }) } \ No newline at end of file diff --git a/src/actions/unpinTicket.ts b/src/actions/unpinTicket.ts index 47c3793..4274e05 100644 --- a/src/actions/unpinTicket.ts +++ b/src/actions/unpinTicket.ts @@ -4,22 +4,22 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerActions = async () => { - opendiscord.actions.add(new api.ODAction("openticket:unpin-ticket")) - opendiscord.actions.get("openticket:unpin-ticket").workers.add([ - new api.ODWorker("openticket:unpin-ticket",2,async (instance,params,source,cancel) => { + opendiscord.actions.add(new api.ODAction("opendiscord:unpin-ticket")) + opendiscord.actions.get("opendiscord:unpin-ticket").workers.add([ + new api.ODWorker("opendiscord:unpin-ticket",2,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params if (channel.isThread()) throw new api.ODSystemError("Unable to unpin ticket! Open Ticket doesn't support threads!") await opendiscord.events.get("onTicketUnpin").emit([ticket,user,channel,reason]) //update ticket - ticket.get("openticket:pinned").value = false - ticket.get("openticket:pinned-by").value = null - ticket.get("openticket:pinned-on").value = null - ticket.get("openticket:busy").value = true + ticket.get("opendiscord:pinned").value = false + ticket.get("opendiscord:pinned-by").value = null + ticket.get("opendiscord:pinned-on").value = null + ticket.get("opendiscord:busy").value = true //rename channel (and give error when crashed) const originalName = channel.name @@ -30,7 +30,7 @@ export const registerActions = async () => { opendiscord.log("Failed to rename channel on ticket unpin","error") }) }catch(err){ - await channel.send((await opendiscord.builders.messages.getSafe("openticket:error-channel-rename").build("ticket-unpin",{guild,channel,user,originalName,newName})).message) + await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-unpin",{guild,channel,user,originalName,newName})).message) } } @@ -38,7 +38,7 @@ export const registerActions = async () => { const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on ticket unpinning!","error",[ {key:"channel",value:"#"+channel.name}, @@ -51,24 +51,24 @@ export const registerActions = async () => { } //reply with new message - if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("openticket:unpin-message").build(source,{guild,channel,user,ticket,reason})).message) - ticket.get("openticket:busy").value = false + if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(source,{guild,channel,user,ticket,reason})).message) + ticket.get("opendiscord:busy").value = false await opendiscord.events.get("afterTicketUnpinned").emit([ticket,user,channel,reason]) }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user,ticket,reason} = params //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.pinning.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) } //to dm const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") - if (creator && generalConfig.data.system.messages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) + if (creator && generalConfig.data.system.messages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null})) }), - new api.ODWorker("openticket:logs",0,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => { const {guild,channel,user,ticket} = params opendiscord.log(user.displayName+" unpinned a ticket!","info",[ @@ -85,184 +85,184 @@ export const registerActions = async () => { export const registerVerifyBars = async () => { //UNPIN TICKET TICKET MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:unpin-ticket-ticket-message",opendiscord.builders.messages.getSafe("openticket:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:unpin-ticket-ticket-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unpin-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:unpin-ticket-ticket-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unpin if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not pinned - if (!ticket.get("openticket:pinned").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) + if (!ticket.get("opendiscord:pinned").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start unpining ticket if (params.data == "reason"){ //unpin with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:unpin-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unpin-ticket-reason").build("ticket-message",{guild,channel,user,ticket})) }else{ //unpin without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:unpin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:unpin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) } }) ]) - opendiscord.verifybars.get("openticket:unpin-ticket-ticket-message").failure.add([ - new api.ODWorker("openticket:back-to-ticket-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:unpin-ticket-ticket-message").failure.add([ + new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }) ]) //UNPIN TICKET PIN MESSAGE - opendiscord.verifybars.add(new api.ODVerifyBar("openticket:unpin-ticket-pin-message",opendiscord.builders.messages.getSafe("openticket:verifybar-pin-message"),!generalConfig.data.system.disableVerifyBars)) - opendiscord.verifybars.get("openticket:unpin-ticket-pin-message").success.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unpin-ticket-pin-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-pin-message"),!generalConfig.data.system.disableVerifyBars)) + opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").success.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unpin if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not pinned - if (!ticket.get("openticket:pinned").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) + if (!ticket.get("opendiscord:pinned").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } //start unpinning ticket if (params.data == "reason"){ //unpin with reason - instance.modal(await opendiscord.builders.modals.getSafe("openticket:unpin-ticket-reason").build("pin-message",{guild,channel,user,ticket})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unpin-ticket-reason").build("pin-message",{guild,channel,user,ticket})) }else{ //unpin without reason await instance.defer("update",false) - await opendiscord.actions.get("openticket:unpin-ticket").run("pin-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:unpin-message").build("pin-message",{guild,channel,user,ticket,reason:null})) + await opendiscord.actions.get("opendiscord:unpin-ticket").run("pin-message",{guild,channel,user,ticket,reason:null,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("pin-message",{guild,channel,user,ticket,reason:null})) } }) ]) - opendiscord.verifybars.get("openticket:unpin-ticket-pin-message").failure.add([ - new api.ODWorker("openticket:back-to-pin-message",0,async (instance,params,source,cancel) => { + opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").failure.add([ + new api.ODWorker("opendiscord:back-to-pin-message",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance const {verifybarMessage} = params if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:pin-message").build("other",{guild,channel,user,ticket,reason})) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("other",{guild,channel,user,ticket,reason})) }) ]) - opendiscord.actions.get("openticket:unpin-ticket").workers.backupWorker = new api.ODWorker("openticket:cancel-busy",0,(instance,params) => { + opendiscord.actions.get("opendiscord:unpin-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => { //set busy to false in case of crash or cancel - params.ticket.get("openticket:busy").value = false + params.ticket.get("opendiscord:busy").value = false }) } \ No newline at end of file diff --git a/src/builders/buttons.ts b/src/builders/buttons.ts index b4ee648..fcdc172 100644 --- a/src/builders/buttons.ts +++ b/src/builders/buttons.ts @@ -6,7 +6,7 @@ import * as discord from "discord.js" const buttons = opendiscord.builders.buttons const lang = opendiscord.languages -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerAllButtons = async () => { verifybarButtons() @@ -20,12 +20,12 @@ export const registerAllButtons = async () => { const verifybarButtons = () => { //VERIFYBAR SUCCESS - buttons.add(new api.ODButton("openticket:verifybar-success")) - buttons.get("openticket:verifybar-success").workers.add( - new api.ODWorker("openticket:verifybar-success",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:verifybar-success")) + buttons.get("opendiscord:verifybar-success").workers.add( + new api.ODWorker("opendiscord:verifybar-success",0,async (instance,params) => { const {verifybar,customData,customColor,customLabel,customEmoji} = params - if (customData && customData.length > 40) throw new api.ODSystemError("ODButton:openticket:verifybar-success => customData exceeds 40 characters limit!") + if (customData && customData.length > 40) throw new api.ODSystemError("ODButton:opendiscord:verifybar-success => customData exceeds 40 characters limit!") const newData = (customData) ? "_"+customData : "" const newColor = customColor ?? "gray" @@ -41,12 +41,12 @@ const verifybarButtons = () => { ) //VERIFYBAR FAILURE - buttons.add(new api.ODButton("openticket:verifybar-failure")) - buttons.get("openticket:verifybar-failure").workers.add( - new api.ODWorker("openticket:verifybar-failure",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:verifybar-failure")) + buttons.get("opendiscord:verifybar-failure").workers.add( + new api.ODWorker("opendiscord:verifybar-failure",0,async (instance,params) => { const {verifybar,customData,customColor,customLabel,customEmoji} = params - if (customData && customData.length > 40) throw new api.ODSystemError("ODButton:openticket:verifybar-success => customData exceeds 40 characters limit!") + if (customData && customData.length > 40) throw new api.ODSystemError("ODButton:opendiscord:verifybar-success => customData exceeds 40 characters limit!") const newData = (customData) ? "_"+customData : "" const newColor = customColor ?? "gray" @@ -64,9 +64,9 @@ const verifybarButtons = () => { const errorButtons = () => { //ERROR TICKET DEPRECATED TRANSCRIPT - buttons.add(new api.ODButton("openticket:error-ticket-deprecated-transcript")) - buttons.get("openticket:error-ticket-deprecated-transcript").workers.add( - new api.ODWorker("openticket:error-ticket-deprecated-transcript",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:error-ticket-deprecated-transcript")) + buttons.get("opendiscord:error-ticket-deprecated-transcript").workers.add( + new api.ODWorker("opendiscord:error-ticket-deprecated-transcript",0,async (instance,params) => { instance.setCustomId("od:error-ticket-deprecated-transcript") instance.setMode("button") @@ -79,9 +79,9 @@ const errorButtons = () => { const helpMenuButtons = () => { //HELP MENU PAGE - buttons.add(new api.ODButton("openticket:help-menu-page")) - buttons.get("openticket:help-menu-page").workers.add( - new api.ODWorker("openticket:help-menu-page",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:help-menu-page")) + buttons.get("opendiscord:help-menu-page").workers.add( + new api.ODWorker("opendiscord:help-menu-page",0,async (instance,params) => { const {mode,page} = params const totalPages = (await opendiscord.helpmenu.render(mode)).length const pageText = (page+1).toString()+"/"+totalPages.toString() @@ -95,9 +95,9 @@ const helpMenuButtons = () => { ) //HELP MENU SWITCH - buttons.add(new api.ODButton("openticket:help-menu-switch")) - buttons.get("openticket:help-menu-switch").workers.add( - new api.ODWorker("openticket:help-menu-switch",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:help-menu-switch")) + buttons.get("opendiscord:help-menu-switch").workers.add( + new api.ODWorker("opendiscord:help-menu-switch",0,async (instance,params) => { const {mode} = params instance.setCustomId("od:help-menu-switch_"+mode) @@ -109,9 +109,9 @@ const helpMenuButtons = () => { ) //HELP MENU PREVIOUS - buttons.add(new api.ODButton("openticket:help-menu-previous")) - buttons.get("openticket:help-menu-previous").workers.add( - new api.ODWorker("openticket:help-menu-previous",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:help-menu-previous")) + buttons.get("opendiscord:help-menu-previous").workers.add( + new api.ODWorker("opendiscord:help-menu-previous",0,async (instance,params) => { const {page} = params instance.setCustomId("od:help-menu-previous") @@ -123,9 +123,9 @@ const helpMenuButtons = () => { ) //HELP MENU NEXT - buttons.add(new api.ODButton("openticket:help-menu-next")) - buttons.get("openticket:help-menu-next").workers.add( - new api.ODWorker("openticket:help-menu-next",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:help-menu-next")) + buttons.get("opendiscord:help-menu-next").workers.add( + new api.ODWorker("opendiscord:help-menu-next",0,async (instance,params) => { const {mode,page} = params const totalPages = (await opendiscord.helpmenu.render(mode)).length @@ -140,55 +140,55 @@ const helpMenuButtons = () => { const panelButtons = () => { //TICKET OPTION - buttons.add(new api.ODButton("openticket:ticket-option")) - buttons.get("openticket:ticket-option").workers.add( - new api.ODWorker("openticket:ticket-option",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:ticket-option")) + buttons.get("opendiscord:ticket-option").workers.add( + new api.ODWorker("opendiscord:ticket-option",0,async (instance,params) => { const {panel,option} = params instance.setCustomId("od:ticket-option_"+panel.id.value+"_"+option.id.value) instance.setMode("button") - instance.setColor(option.get("openticket:button-color").value) - if (option.get("openticket:button-emoji").value) instance.setEmoji(option.get("openticket:button-emoji").value) - if (option.get("openticket:button-label").value) instance.setLabel(option.get("openticket:button-label").value) - if (!option.get("openticket:button-emoji").value && !option.get("openticket:button-label").value) instance.setLabel("<"+option.id.value+">") + instance.setColor(option.get("opendiscord:button-color").value) + if (option.get("opendiscord:button-emoji").value) instance.setEmoji(option.get("opendiscord:button-emoji").value) + if (option.get("opendiscord:button-label").value) instance.setLabel(option.get("opendiscord:button-label").value) + if (!option.get("opendiscord:button-emoji").value && !option.get("opendiscord:button-label").value) instance.setLabel("<"+option.id.value+">") }) ) //WEBSITE OPTION - buttons.add(new api.ODButton("openticket:website-option")) - buttons.get("openticket:website-option").workers.add( - new api.ODWorker("openticket:website-option",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:website-option")) + buttons.get("opendiscord:website-option").workers.add( + new api.ODWorker("opendiscord:website-option",0,async (instance,params) => { const {panel,option} = params instance.setMode("url") - instance.setUrl(option.get("openticket:url").value) - if (option.get("openticket:button-emoji").value) instance.setEmoji(option.get("openticket:button-emoji").value) - if (option.get("openticket:button-label").value) instance.setLabel(option.get("openticket:button-label").value) - if (!option.get("openticket:button-emoji").value && !option.get("openticket:button-label").value) instance.setLabel("<"+option.id.value+">") + instance.setUrl(option.get("opendiscord:url").value) + if (option.get("opendiscord:button-emoji").value) instance.setEmoji(option.get("opendiscord:button-emoji").value) + if (option.get("opendiscord:button-label").value) instance.setLabel(option.get("opendiscord:button-label").value) + if (!option.get("opendiscord:button-emoji").value && !option.get("opendiscord:button-label").value) instance.setLabel("<"+option.id.value+">") }) ) //ROLE OPTION - buttons.add(new api.ODButton("openticket:role-option")) - buttons.get("openticket:role-option").workers.add( - new api.ODWorker("openticket:role-option",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:role-option")) + buttons.get("opendiscord:role-option").workers.add( + new api.ODWorker("opendiscord:role-option",0,async (instance,params) => { const {panel,option} = params instance.setCustomId("od:role-option_"+panel.id.value+"_"+option.id.value) instance.setMode("button") - instance.setColor(option.get("openticket:button-color").value) - if (option.get("openticket:button-emoji").value) instance.setEmoji(option.get("openticket:button-emoji").value) - if (option.get("openticket:button-label").value) instance.setLabel(option.get("openticket:button-label").value) - if (!option.get("openticket:button-emoji").value && !option.get("openticket:button-label").value) instance.setLabel("<"+option.id.value+">") + instance.setColor(option.get("opendiscord:button-color").value) + if (option.get("opendiscord:button-emoji").value) instance.setEmoji(option.get("opendiscord:button-emoji").value) + if (option.get("opendiscord:button-label").value) instance.setLabel(option.get("opendiscord:button-label").value) + if (!option.get("opendiscord:button-emoji").value && !option.get("opendiscord:button-label").value) instance.setLabel("<"+option.id.value+">") }) ) } const ticketButtons = () => { //VISIT TICKET - buttons.add(new api.ODButton("openticket:visit-ticket")) - buttons.get("openticket:visit-ticket").workers.add( - new api.ODWorker("openticket:visit-ticket",0,async (instance,params) => { + buttons.add(new api.ODButton("opendiscord:visit-ticket")) + buttons.get("opendiscord:visit-ticket").workers.add( + new api.ODWorker("opendiscord:visit-ticket",0,async (instance,params) => { const {guild,channel,ticket} = params instance.setMode("url") @@ -199,9 +199,9 @@ const ticketButtons = () => { ) //CLOSE TICKET - buttons.add(new api.ODButton("openticket:close-ticket")) - buttons.get("openticket:close-ticket").workers.add( - new api.ODWorker("openticket:close-ticket",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:close-ticket")) + buttons.get("opendiscord:close-ticket").workers.add( + new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source) => { const {guild,channel,ticket} = params instance.setMode("button") @@ -213,9 +213,9 @@ const ticketButtons = () => { ) //DELETE TICKET - buttons.add(new api.ODButton("openticket:delete-ticket")) - buttons.get("openticket:delete-ticket").workers.add( - new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:delete-ticket")) + buttons.get("opendiscord:delete-ticket").workers.add( + new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source) => { const {guild,channel,ticket} = params instance.setMode("button") @@ -227,9 +227,9 @@ const ticketButtons = () => { ) //REOPEN TICKET - buttons.add(new api.ODButton("openticket:reopen-ticket")) - buttons.get("openticket:reopen-ticket").workers.add( - new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:reopen-ticket")) + buttons.get("opendiscord:reopen-ticket").workers.add( + new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source) => { const {guild,channel,ticket} = params instance.setMode("button") @@ -241,9 +241,9 @@ const ticketButtons = () => { ) //CLAIM TICKET - buttons.add(new api.ODButton("openticket:claim-ticket")) - buttons.get("openticket:claim-ticket").workers.add( - new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:claim-ticket")) + buttons.get("opendiscord:claim-ticket").workers.add( + new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source) => { const {guild,channel,ticket} = params instance.setMode("button") @@ -255,9 +255,9 @@ const ticketButtons = () => { ) //UNCLAIM TICKET - buttons.add(new api.ODButton("openticket:unclaim-ticket")) - buttons.get("openticket:unclaim-ticket").workers.add( - new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:unclaim-ticket")) + buttons.get("opendiscord:unclaim-ticket").workers.add( + new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source) => { const {guild,channel,ticket} = params instance.setMode("button") @@ -269,9 +269,9 @@ const ticketButtons = () => { ) //PIN TICKET - buttons.add(new api.ODButton("openticket:pin-ticket")) - buttons.get("openticket:pin-ticket").workers.add( - new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:pin-ticket")) + buttons.get("opendiscord:pin-ticket").workers.add( + new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source) => { const {guild,channel,ticket} = params instance.setMode("button") @@ -283,9 +283,9 @@ const ticketButtons = () => { ) //UNPIN TICKET - buttons.add(new api.ODButton("openticket:unpin-ticket")) - buttons.get("openticket:unpin-ticket").workers.add( - new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:unpin-ticket")) + buttons.get("opendiscord:unpin-ticket").workers.add( + new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source) => { const {guild,channel,ticket} = params instance.setMode("button") @@ -299,22 +299,22 @@ const ticketButtons = () => { const transcriptButtons = () => { //TRANSCRIPT HTML VISIT - buttons.add(new api.ODButton("openticket:transcript-html-visit")) - buttons.get("openticket:transcript-html-visit").workers.add( - new api.ODWorker("openticket:transcript-html-visit",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:transcript-html-visit")) + buttons.get("opendiscord:transcript-html-visit").workers.add( + new api.ODWorker("opendiscord:transcript-html-visit",0,async (instance,params,source) => { const {result} = params instance.setMode("url") if (result.data) instance.setUrl(result.data.url) - else throw new api.ODSystemError("ODButton:openticket:transcript-html-visit => Missing Transcript Result Data!") + else throw new api.ODSystemError("ODButton:opendiscord:transcript-html-visit => Missing Transcript Result Data!") instance.setEmoji("📄") instance.setLabel(lang.getTranslation("transcripts.success.visit")) }) ) //TRANSCRIPT ERROR RETRY - buttons.add(new api.ODButton("openticket:transcript-error-retry")) - buttons.get("openticket:transcript-error-retry").workers.add( - new api.ODWorker("openticket:transcript-error-retry",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:transcript-error-retry")) + buttons.get("opendiscord:transcript-error-retry").workers.add( + new api.ODWorker("opendiscord:transcript-error-retry",0,async (instance,params,source) => { instance.setMode("button") instance.setCustomId("od:transcript-error-retry_"+source) instance.setColor("gray") @@ -324,9 +324,9 @@ const transcriptButtons = () => { ) //TRANSCRIPT ERROR CONTINUE - buttons.add(new api.ODButton("openticket:transcript-error-continue")) - buttons.get("openticket:transcript-error-continue").workers.add( - new api.ODWorker("openticket:transcript-error-continue",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:transcript-error-continue")) + buttons.get("opendiscord:transcript-error-continue").workers.add( + new api.ODWorker("opendiscord:transcript-error-continue",0,async (instance,params,source) => { instance.setMode("button") instance.setCustomId("od:transcript-error-continue_"+source) instance.setColor("red") @@ -338,9 +338,9 @@ const transcriptButtons = () => { const clearButtons = () => { //CLEAR CONTINUE - buttons.add(new api.ODButton("openticket:clear-continue")) - buttons.get("openticket:clear-continue").workers.add( - new api.ODWorker("openticket:clear-continue",0,async (instance,params,source) => { + buttons.add(new api.ODButton("opendiscord:clear-continue")) + buttons.get("opendiscord:clear-continue").workers.add( + new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,source) => { instance.setMode("button") instance.setCustomId("od:clear-continue_"+source+"_"+params.filter) instance.setColor("red") diff --git a/src/builders/dropdowns.ts b/src/builders/dropdowns.ts index 76c94d8..e23da85 100644 --- a/src/builders/dropdowns.ts +++ b/src/builders/dropdowns.ts @@ -12,16 +12,16 @@ export const registerAllDropdowns = async () => { const panelDropdowns = () => { //TICKET OPTION - dropdowns.add(new api.ODDropdown("openticket:panel-dropdown-tickets")) - dropdowns.get("openticket:panel-dropdown-tickets").workers.add( - new api.ODWorker("openticket:panel-dropdown-tickets",0,async (instance,params) => { + dropdowns.add(new api.ODDropdown("opendiscord:panel-dropdown-tickets")) + dropdowns.get("opendiscord:panel-dropdown-tickets").workers.add( + new api.ODWorker("opendiscord:panel-dropdown-tickets",0,async (instance,params) => { const {panel,options} = params const parsedOptions: api.ODDropdownData["options"] = options.map((option) => { - const desc = option.get("openticket:description").value.substring(0,100) - const emoji = option.get("openticket:button-emoji").value + const desc = option.get("opendiscord:description").value.substring(0,100) + const emoji = option.get("opendiscord:button-emoji").value return { - label:option.get("openticket:button-label").value.substring(0,100), + label:option.get("opendiscord:button-label").value.substring(0,100), value:"od:ticket-option_"+panel.id.value+"_"+option.id.value, emoji:(emoji.length > 0) ? emoji : undefined, description:(desc.length > 0) ? desc : undefined, @@ -33,7 +33,7 @@ const panelDropdowns = () => { instance.setType("string") instance.setMaxValues(1) instance.setMinValues(0) - instance.setPlaceholder(panel.get("openticket:dropdown-placeholder").value) + instance.setPlaceholder(panel.get("opendiscord:dropdown-placeholder").value) instance.setOptions(parsedOptions) }) ) diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts index 4e9ea38..67d4373 100644 --- a/src/builders/embeds.ts +++ b/src/builders/embeds.ts @@ -7,7 +7,7 @@ import nodepath from "path" const embeds = opendiscord.builders.embeds const lang = opendiscord.languages -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerAllEmbeds = async () => { errorEmbeds() @@ -34,9 +34,9 @@ const getMethodFromSource = (source:"slash"|"text"|"button"|"dropdown"|"modal"|" const errorEmbeds = () => { //ERROR - embeds.add(new api.ODEmbed("openticket:error")) - embeds.get("openticket:error").workers.add( - new api.ODWorker("openticket:error",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error")) + embeds.get("opendiscord:error").workers.add( + new api.ODWorker("opendiscord:error",0,async (instance,params,source) => { const {user,error,layout} = params const method = getMethodFromSource(source) @@ -51,9 +51,9 @@ const errorEmbeds = () => { ) //ERROR OPTION MISSING - embeds.add(new api.ODEmbed("openticket:error-option-missing")) - embeds.get("openticket:error-option-missing").workers.add( - new api.ODWorker("openticket:error-option-missing",0,async (instance,params) => { + embeds.add(new api.ODEmbed("opendiscord:error-option-missing")) + embeds.get("opendiscord:error-option-missing").workers.add( + new api.ODWorker("opendiscord:error-option-missing",0,async (instance,params) => { const {user,error} = params const options = error.command.builder.options ?? [] @@ -83,9 +83,9 @@ const errorEmbeds = () => { ) //ERROR OPTION INVALID - embeds.add(new api.ODEmbed("openticket:error-option-invalid")) - embeds.get("openticket:error-option-invalid").workers.add( - new api.ODWorker("openticket:error-option-invalid",0,async (instance,params) => { + embeds.add(new api.ODEmbed("opendiscord:error-option-invalid")) + embeds.get("opendiscord:error-option-invalid").workers.add( + new api.ODWorker("opendiscord:error-option-invalid",0,async (instance,params) => { const {user,error} = params const options = error.command.builder.options ?? [] @@ -138,9 +138,9 @@ const errorEmbeds = () => { ) //ERROR UNKNOWN COMMAND - embeds.add(new api.ODEmbed("openticket:error-unknown-command")) - embeds.get("openticket:error-unknown-command").workers.add( - new api.ODWorker("openticket:error-unknown-command",0,async (instance,params) => { + embeds.add(new api.ODEmbed("opendiscord:error-unknown-command")) + embeds.get("opendiscord:error-unknown-command").workers.add( + new api.ODWorker("opendiscord:error-unknown-command",0,async (instance,params) => { const {user} = params instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) @@ -151,9 +151,9 @@ const errorEmbeds = () => { ) //ERROR NO PERMISSIONS - embeds.add(new api.ODEmbed("openticket:error-no-permissions")) - embeds.get("openticket:error-no-permissions").workers.add( - new api.ODWorker("openticket:error-no-permissions",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-no-permissions")) + embeds.get("opendiscord:error-no-permissions").workers.add( + new api.ODWorker("opendiscord:error-no-permissions",0,async (instance,params,source) => { const {user,permissions} = params const method = getMethodFromSource(source) @@ -177,9 +177,9 @@ const errorEmbeds = () => { ) //ERROR NO PERMISSIONS COOLDOWN - embeds.add(new api.ODEmbed("openticket:error-no-permissions-cooldown")) - embeds.get("openticket:error-no-permissions-cooldown").workers.add( - new api.ODWorker("openticket:error-no-permissions-cooldown",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-no-permissions-cooldown")) + embeds.get("opendiscord:error-no-permissions-cooldown").workers.add( + new api.ODWorker("opendiscord:error-no-permissions-cooldown",0,async (instance,params,source) => { const {user} = params const method = getMethodFromSource(source) @@ -193,9 +193,9 @@ const errorEmbeds = () => { ) //ERROR NO PERMISSIONS BLACKLISTED - embeds.add(new api.ODEmbed("openticket:error-no-permissions-blacklisted")) - embeds.get("openticket:error-no-permissions-blacklisted").workers.add( - new api.ODWorker("openticket:error-no-permissions-blacklisted",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-no-permissions-blacklisted")) + embeds.get("opendiscord:error-no-permissions-blacklisted").workers.add( + new api.ODWorker("opendiscord:error-no-permissions-blacklisted",0,async (instance,params,source) => { const {user} = params const method = getMethodFromSource(source) @@ -208,9 +208,9 @@ const errorEmbeds = () => { ) //ERROR NO PERMISSIONS LIMITS - embeds.add(new api.ODEmbed("openticket:error-no-permissions-limits")) - embeds.get("openticket:error-no-permissions-limits").workers.add( - new api.ODWorker("openticket:error-no-permissions-limits",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-no-permissions-limits")) + embeds.get("opendiscord:error-no-permissions-limits").workers.add( + new api.ODWorker("opendiscord:error-no-permissions-limits",0,async (instance,params,source) => { const {user,limit} = params instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) @@ -224,9 +224,9 @@ const errorEmbeds = () => { ) //ERROR RESPONDER TIMEOUT - embeds.add(new api.ODEmbed("openticket:error-responder-timeout")) - embeds.get("openticket:error-responder-timeout").workers.add( - new api.ODWorker("openticket:error-responder-timeout",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-responder-timeout")) + embeds.get("opendiscord:error-responder-timeout").workers.add( + new api.ODWorker("opendiscord:error-responder-timeout",0,async (instance,params,source) => { const {user} = params const method = getMethodFromSource(source) @@ -241,9 +241,9 @@ const errorEmbeds = () => { ) //ERROR TICKET UNKNOWN - embeds.add(new api.ODEmbed("openticket:error-ticket-unknown")) - embeds.get("openticket:error-ticket-unknown").workers.add( - new api.ODWorker("openticket:error-ticket-unknown",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-ticket-unknown")) + embeds.get("opendiscord:error-ticket-unknown").workers.add( + new api.ODWorker("opendiscord:error-ticket-unknown",0,async (instance,params,source) => { const {user} = params instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) @@ -255,9 +255,9 @@ const errorEmbeds = () => { ) //ERROR TICKET DEPRECATED - embeds.add(new api.ODEmbed("openticket:error-ticket-deprecated")) - embeds.get("openticket:error-ticket-deprecated").workers.add( - new api.ODWorker("openticket:error-ticket-deprecated",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-ticket-deprecated")) + embeds.get("opendiscord:error-ticket-deprecated").workers.add( + new api.ODWorker("opendiscord:error-ticket-deprecated",0,async (instance,params,source) => { const {user} = params instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) @@ -269,14 +269,14 @@ const errorEmbeds = () => { ) //ERROR OPTION UNKNOWN - embeds.add(new api.ODEmbed("openticket:error-option-unknown")) - embeds.get("openticket:error-option-unknown").workers.add( - new api.ODWorker("openticket:error-option-unknown",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-option-unknown")) + embeds.get("opendiscord:error-option-unknown").workers.add( + new api.ODWorker("opendiscord:error-option-unknown",0,async (instance,params,source) => { const {user} = params const renderedTicketOptions = opendiscord.options.getAll().map((option) => { - if (option instanceof api.ODTicketOption && option.exists("openticket:name")){ - return "- **"+option.get("openticket:name").value+":** `"+option.id.value+"`" + if (option instanceof api.ODTicketOption && option.exists("opendiscord:name")){ + return "- **"+option.get("opendiscord:name").value+":** `"+option.id.value+"`" }else return "- `"+option.id.value+"`" }).join("\n") @@ -289,14 +289,14 @@ const errorEmbeds = () => { ) //ERROR PANEL UNKNOWN - embeds.add(new api.ODEmbed("openticket:error-panel-unknown")) - embeds.get("openticket:error-panel-unknown").workers.add( - new api.ODWorker("openticket:error-panel-unknown",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-panel-unknown")) + embeds.get("opendiscord:error-panel-unknown").workers.add( + new api.ODWorker("opendiscord:error-panel-unknown",0,async (instance,params,source) => { const {user} = params const renderedPanels = opendiscord.panels.getAll().map((panel) => { - if (panel.exists("openticket:name")){ - return "- **"+panel.get("openticket:name").value+":** `"+panel.id.value+"`" + if (panel.exists("opendiscord:name")){ + return "- **"+panel.get("opendiscord:name").value+":** `"+panel.id.value+"`" }else return "- `"+panel.id.value+"`" }).join("\n") @@ -309,9 +309,9 @@ const errorEmbeds = () => { ) //ERROR NOT IN GUILD - embeds.add(new api.ODEmbed("openticket:error-not-in-guild")) - embeds.get("openticket:error-not-in-guild").workers.add( - new api.ODWorker("openticket:error-not-in-guild",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-not-in-guild")) + embeds.get("opendiscord:error-not-in-guild").workers.add( + new api.ODWorker("opendiscord:error-not-in-guild",0,async (instance,params,source) => { const {user} = params const method = getMethodFromSource(source) @@ -324,9 +324,9 @@ const errorEmbeds = () => { ) //ERROR CHANNEL RENAME - embeds.add(new api.ODEmbed("openticket:error-channel-rename")) - embeds.get("openticket:error-channel-rename").workers.add( - new api.ODWorker("openticket:error-channel-rename",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-channel-rename")) + embeds.get("opendiscord:error-channel-rename").workers.add( + new api.ODWorker("opendiscord:error-channel-rename",0,async (instance,params,source) => { const {channel,user,originalName,newName} = params const method = (source == "ticket-move" || source == "ticket-pin" || source == "ticket-rename" || source == "ticket-unpin") ? source : getMethodFromSource(source) @@ -344,9 +344,9 @@ const errorEmbeds = () => { ) //ERROR TICKET BUSY - embeds.add(new api.ODEmbed("openticket:error-ticket-busy")) - embeds.get("openticket:error-ticket-busy").workers.add( - new api.ODWorker("openticket:error-ticket-busy",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:error-ticket-busy")) + embeds.get("opendiscord:error-ticket-busy").workers.add( + new api.ODWorker("opendiscord:error-ticket-busy",0,async (instance,params,source) => { const {user} = params const method = getMethodFromSource(source) @@ -362,9 +362,9 @@ const errorEmbeds = () => { const helpMenuEmbeds = () => { //HELP MENU - embeds.add(new api.ODEmbed("openticket:help-menu")) - embeds.get("openticket:help-menu").workers.add( - new api.ODWorker("openticket:help-menu",0,async (instance,params) => { + embeds.add(new api.ODEmbed("opendiscord:help-menu")) + embeds.get("opendiscord:help-menu").workers.add( + new api.ODWorker("opendiscord:help-menu",0,async (instance,params) => { const {mode,page} = params instance.setColor(generalConfig.data.mainColor) @@ -381,12 +381,12 @@ const helpMenuEmbeds = () => { const statsEmbeds = () => { //STATS GLOBAL - embeds.add(new api.ODEmbed("openticket:stats-global")) - embeds.get("openticket:stats-global").workers.add( - new api.ODWorker("openticket:stats-global",0,async (instance,params) => { + embeds.add(new api.ODEmbed("opendiscord:stats-global")) + embeds.get("opendiscord:stats-global").workers.add( + new api.ODWorker("opendiscord:stats-global",0,async (instance,params) => { const {guild,channel,user} = params - const scope = opendiscord.stats.get("openticket:global") + const scope = opendiscord.stats.get("opendiscord:global") if (!scope) return const data = await scope.render("GLOBAL",guild,channel,user) @@ -396,7 +396,7 @@ const statsEmbeds = () => { if (opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(user,channel,guild))){ //show system data when owner or developer - const systemScope = opendiscord.stats.get("openticket:system") + const systemScope = opendiscord.stats.get("opendiscord:system") if (!systemScope) return const systemData = await systemScope.render("GLOBAL",guild,channel,user) instance.addFields({name:systemScope.name,value:systemData,inline:false}) @@ -405,13 +405,13 @@ const statsEmbeds = () => { ) //STATS TICKET - embeds.add(new api.ODEmbed("openticket:stats-ticket")) - embeds.get("openticket:stats-ticket").workers.add( - new api.ODWorker("openticket:stats-ticket",0,async (instance,params) => { + embeds.add(new api.ODEmbed("opendiscord:stats-ticket")) + embeds.get("opendiscord:stats-ticket").workers.add( + new api.ODWorker("opendiscord:stats-ticket",0,async (instance,params) => { const {guild,channel,user,scopeData} = params - const scope = opendiscord.stats.get("openticket:ticket") - const participantsScope = opendiscord.stats.get("openticket:participants") + const scope = opendiscord.stats.get("opendiscord:ticket") + const participantsScope = opendiscord.stats.get("opendiscord:participants") if (!scope || !participantsScope) return const data = await scope.render(scopeData.id.value,guild,channel,user) const participantsData = await participantsScope.render(scopeData.id.value,guild,channel,user) @@ -424,12 +424,12 @@ const statsEmbeds = () => { ) //STATS USER - embeds.add(new api.ODEmbed("openticket:stats-user")) - embeds.get("openticket:stats-user").workers.add([ - new api.ODWorker("openticket:stats-user",0,async (instance,params) => { + embeds.add(new api.ODEmbed("opendiscord:stats-user")) + embeds.get("opendiscord:stats-user").workers.add([ + new api.ODWorker("opendiscord:stats-user",0,async (instance,params) => { const {guild,channel,user,scopeData} = params - const scope = opendiscord.stats.get("openticket:user") + const scope = opendiscord.stats.get("opendiscord:user") if (!scope) return const data = await scope.render(scopeData.id,guild,channel,user) @@ -438,9 +438,9 @@ const statsEmbeds = () => { instance.setDescription(data) instance.setThumbnail(scopeData.displayAvatarURL()) }), - new api.ODWorker("openticket:easter-egg",-1,async (instance,params) => { - if (!opendiscord.flags.exists("openticket:no-easter")) return - const easterFlag = opendiscord.flags.get("openticket:no-easter") + new api.ODWorker("opendiscord:easter-egg",-1,async (instance,params) => { + if (!opendiscord.flags.exists("opendiscord:no-easter")) return + const easterFlag = opendiscord.flags.get("opendiscord:no-easter") if (!easterFlag.value){ //🥚 add easter egg 🥚 const {user} = params @@ -454,9 +454,9 @@ const statsEmbeds = () => { ]) //STATS RESET - embeds.add(new api.ODEmbed("openticket:stats-reset")) - embeds.get("openticket:stats-reset").workers.add( - new api.ODWorker("openticket:stats-reset",0,async (instance,params) => { + embeds.add(new api.ODEmbed("opendiscord:stats-reset")) + embeds.get("opendiscord:stats-reset").workers.add( + new api.ODWorker("opendiscord:stats-reset",0,async (instance,params) => { const {user,reason} = params instance.setColor(generalConfig.data.mainColor) @@ -468,9 +468,9 @@ const statsEmbeds = () => { ) //STATS TICKET UNKNOWN - embeds.add(new api.ODEmbed("openticket:stats-ticket-unknown")) - embeds.get("openticket:stats-ticket-unknown").workers.add( - new api.ODWorker("openticket:stats-ticket-unknown",0,async (instance,params) => { + embeds.add(new api.ODEmbed("opendiscord:stats-ticket-unknown")) + embeds.get("opendiscord:stats-ticket-unknown").workers.add( + new api.ODWorker("opendiscord:stats-ticket-unknown",0,async (instance,params) => { const {user,id} = params instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) @@ -483,12 +483,12 @@ const statsEmbeds = () => { const panelEmbeds = () => { //PANEL - embeds.add(new api.ODEmbed("openticket:panel")) - embeds.get("openticket:panel").workers.add( - new api.ODWorker("openticket:panel",0,async (instance,params) => { + embeds.add(new api.ODEmbed("opendiscord:panel")) + embeds.get("opendiscord:panel").workers.add( + new api.ODWorker("opendiscord:panel",0,async (instance,params) => { const {panel} = params - if (!panel.exists("openticket:embed")) return - const embedOptions = panel.get("openticket:embed").value + if (!panel.exists("opendiscord:embed")) return + const embedOptions = panel.get("opendiscord:embed").value instance.setColor(embedOptions.customColor ? embedOptions.customColor : generalConfig.data.mainColor) instance.setTitle(embedOptions.title) @@ -498,7 +498,7 @@ const panelEmbeds = () => { if (embedOptions.footer) instance.setFooter(embedOptions.footer) if (embedOptions.timestamp) instance.setTimestamp(new Date()) - if (panel.get("openticket:describe-options-in-embed-description").value){ + if (panel.get("opendiscord:describe-options-in-embed-description").value){ //describe options in description const text = (await import("../data/openticket/panelLoader.js")).describePanelOptions("text",panel) instance.setDescription(embedOptions.description+"\n\n"+text) @@ -506,11 +506,11 @@ const panelEmbeds = () => { instance.setDescription(embedOptions.description) } - if (panel.get("openticket:enable-max-tickets-warning-embed").value && generalConfig.data.system.limits.enabled){ + if (panel.get("opendiscord:enable-max-tickets-warning-embed").value && generalConfig.data.system.limits.enabled){ instance.setDescription(instance.data.description+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.system.limits.userMaximum.toString()])+"*") } - if (panel.get("openticket:describe-options-in-embed-fields").value){ + if (panel.get("opendiscord:describe-options-in-embed-fields").value){ //describe options in fields const fields = (await import("../data/openticket/panelLoader.js")).describePanelOptions("fields",panel) instance.setFields(fields) @@ -523,9 +523,9 @@ const panelEmbeds = () => { const ticketEmbeds = () => { //TICKET CREATED - embeds.add(new api.ODEmbed("openticket:ticket-created")) - embeds.get("openticket:ticket-created").workers.add( - new api.ODWorker("openticket:ticket-created",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:ticket-created")) + embeds.get("opendiscord:ticket-created").workers.add( + new api.ODWorker("opendiscord:ticket-created",0,async (instance,params,source) => { const {user} = params instance.setColor(generalConfig.data.mainColor) @@ -537,11 +537,11 @@ const ticketEmbeds = () => { ) //TICKET CREATED DM - embeds.add(new api.ODEmbed("openticket:ticket-created-dm")) - embeds.get("openticket:ticket-created-dm").workers.add( - new api.ODWorker("openticket:ticket-created-dm",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:ticket-created-dm")) + embeds.get("opendiscord:ticket-created-dm").workers.add( + new api.ODWorker("opendiscord:ticket-created-dm",0,async (instance,params,source) => { const {user,ticket} = params - const embedOptions = ticket.option.get("openticket:dm-message-embed").value + const embedOptions = ticket.option.get("opendiscord:dm-message-embed").value instance.setColor(embedOptions.customColor ? (embedOptions.customColor as discord.ColorResolvable) : generalConfig.data.mainColor) instance.setTitle(embedOptions.title) @@ -551,15 +551,15 @@ const ticketEmbeds = () => { if (embedOptions.description) instance.setDescription(embedOptions.description) if (embedOptions.fields) instance.setFields(embedOptions.fields) - if (ticket.get("openticket:closed").value && ticket.get("openticket:autodelete-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutodelete",[ticket.option.get("openticket:autodelete-days").value.toString()])) - else if (!ticket.get("openticket:closed").value && ticket.get("openticket:autoclose-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutoclose",[ticket.option.get("openticket:autoclose-hours").value.toString()])) + 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()])) }) ) //TICKET CREATED LOGS - embeds.add(new api.ODEmbed("openticket:ticket-created-logs")) - embeds.get("openticket:ticket-created-logs").workers.add( - new api.ODWorker("openticket:ticket-created-logs",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:ticket-created-logs")) + embeds.get("opendiscord:ticket-created-logs").workers.add( + new api.ODWorker("opendiscord:ticket-created-logs",0,async (instance,params,source) => { const {user,ticket} = params const method = (source == "panel-button" || source == "panel-dropdown") ? lang.getTranslation("params.uppercase.panel") : (source == "slash" || source == "text") ? lang.getTranslation("params.uppercase.command") : lang.getTranslation("params.uppercase.system") @@ -572,7 +572,7 @@ const ticketEmbeds = () => { instance.setTimestamp(new Date()) instance.setDescription(lang.getTranslationWithParams("actions.logs.createLog",[discord.userMention(user.id)])) instance.addFields( - {name:lang.getTranslation("params.uppercase.type")+":",value:"```"+ticket.option.get("openticket:name").value+"```",inline:false}, + {name:lang.getTranslation("params.uppercase.type")+":",value:"```"+ticket.option.get("opendiscord:name").value+"```",inline:false}, {name:lang.getTranslation("params.uppercase.method")+":",value:"```"+method+"```",inline:true}, {name:lang.getTranslation("params.uppercase.blacklisted")+":",value:"```"+blacklisted+"```", inline:true} ) @@ -580,11 +580,11 @@ const ticketEmbeds = () => { ) //TICKET MESSAGE - embeds.add(new api.ODEmbed("openticket:ticket-message")) - embeds.get("openticket:ticket-message").workers.add( - new api.ODWorker("openticket:ticket-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:ticket-message")) + embeds.get("opendiscord:ticket-message").workers.add( + new api.ODWorker("opendiscord:ticket-message",0,async (instance,params,source) => { const {user,ticket} = params - const embedOptions = ticket.option.get("openticket:ticket-message-embed").value + const embedOptions = ticket.option.get("opendiscord:ticket-message-embed").value instance.setColor(embedOptions.customColor ? embedOptions.customColor : generalConfig.data.mainColor) if (embedOptions.title) instance.setTitle(embedOptions.title) @@ -593,8 +593,8 @@ const ticketEmbeds = () => { if (embedOptions.timestamp) instance.setTimestamp(new Date()) if (embedOptions.description) instance.setDescription(embedOptions.description) - if (ticket.option.get("openticket:questions").value.length > 0){ - const answers = ticket.get("openticket:answers").value + if (ticket.option.get("opendiscord:questions").value.length > 0){ + const answers = ticket.get("opendiscord:answers").value answers.forEach((answer) => { if (!answer.value || answer.value.length == 0) return if (generalConfig.data.system.questionFieldsInCodeBlock) instance.addFields({name:answer.name,value:"```"+answer.value+"```",inline:false}) @@ -604,10 +604,10 @@ const ticketEmbeds = () => { instance.setFields(embedOptions.fields) } - if (ticket.get("openticket:closed").value && ticket.get("openticket:autodelete-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutodelete",[ticket.option.get("openticket:autodelete-days").value.toString()])) - else if (!ticket.get("openticket:closed").value && ticket.get("openticket:autoclose-enabled").value) instance.setFooter("⏱️ "+lang.getTranslationWithParams("actions.descriptions.ticketMessageAutoclose",[ticket.option.get("openticket:autoclose-hours").value.toString()])) + 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("openticket:claimed").value){ + if (ticket.get("opendiscord:claimed").value){ const claimUser = await opendiscord.tickets.getTicketUser(ticket,"claimer") if (!claimUser) return instance.setAuthor(lang.getTranslationWithParams("params.uppercase.claimedBy",[claimUser.displayName]),claimUser.displayAvatarURL()) @@ -616,9 +616,9 @@ const ticketEmbeds = () => { ) //TICKET CLOSED - embeds.add(new api.ODEmbed("openticket:close-message")) - embeds.get("openticket:close-message").workers.add( - new api.ODWorker("openticket:close-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:close-message")) + embeds.get("opendiscord:close-message").workers.add( + new api.ODWorker("opendiscord:close-message",0,async (instance,params,source) => { const {user,ticket,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -630,9 +630,9 @@ const ticketEmbeds = () => { ) //TICKET REOPENED - embeds.add(new api.ODEmbed("openticket:reopen-message")) - embeds.get("openticket:reopen-message").workers.add( - new api.ODWorker("openticket:reopen-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:reopen-message")) + embeds.get("opendiscord:reopen-message").workers.add( + new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,source) => { const {user,ticket,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -644,9 +644,9 @@ const ticketEmbeds = () => { ) //TICKET DELETED - embeds.add(new api.ODEmbed("openticket:delete-message")) - embeds.get("openticket:delete-message").workers.add( - new api.ODWorker("openticket:delete-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:delete-message")) + embeds.get("opendiscord:delete-message").workers.add( + new api.ODWorker("opendiscord:delete-message",0,async (instance,params,source) => { const {user,ticket,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -658,9 +658,9 @@ const ticketEmbeds = () => { ) //TICKET CLAIMED - embeds.add(new api.ODEmbed("openticket:claim-message")) - embeds.get("openticket:claim-message").workers.add( - new api.ODWorker("openticket:claim-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:claim-message")) + embeds.get("opendiscord:claim-message").workers.add( + new api.ODWorker("opendiscord:claim-message",0,async (instance,params,source) => { const {user,ticket,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -672,9 +672,9 @@ const ticketEmbeds = () => { ) //TICKET UNCLAIMED - embeds.add(new api.ODEmbed("openticket:unclaim-message")) - embeds.get("openticket:unclaim-message").workers.add( - new api.ODWorker("openticket:unclaim-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:unclaim-message")) + embeds.get("opendiscord:unclaim-message").workers.add( + new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,source) => { const {user,ticket,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -686,9 +686,9 @@ const ticketEmbeds = () => { ) //TICKET PINNED - embeds.add(new api.ODEmbed("openticket:pin-message")) - embeds.get("openticket:pin-message").workers.add( - new api.ODWorker("openticket:pin-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:pin-message")) + embeds.get("opendiscord:pin-message").workers.add( + new api.ODWorker("opendiscord:pin-message",0,async (instance,params,source) => { const {user,ticket,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -700,9 +700,9 @@ const ticketEmbeds = () => { ) //TICKET UNPINNED - embeds.add(new api.ODEmbed("openticket:unpin-message")) - embeds.get("openticket:unpin-message").workers.add( - new api.ODWorker("openticket:unpin-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:unpin-message")) + embeds.get("opendiscord:unpin-message").workers.add( + new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,source) => { const {user,ticket,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -714,9 +714,9 @@ const ticketEmbeds = () => { ) //TICKET RENAMED - embeds.add(new api.ODEmbed("openticket:rename-message")) - embeds.get("openticket:rename-message").workers.add( - new api.ODWorker("openticket:rename-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:rename-message")) + embeds.get("opendiscord:rename-message").workers.add( + new api.ODWorker("opendiscord:rename-message",0,async (instance,params,source) => { const {user,ticket,reason,data} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -728,23 +728,23 @@ const ticketEmbeds = () => { ) //TICKET MOVED - embeds.add(new api.ODEmbed("openticket:move-message")) - embeds.get("openticket:move-message").workers.add( - new api.ODWorker("openticket:move-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:move-message")) + embeds.get("opendiscord:move-message").workers.add( + new api.ODWorker("opendiscord:move-message",0,async (instance,params,source) => { const {user,ticket,reason,data} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) instance.setColor(generalConfig.data.mainColor) instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.move"))) - instance.setDescription(lang.getTranslationWithParams("actions.descriptions.move",["`"+data.get("openticket:name").value+"`"])) + instance.setDescription(lang.getTranslationWithParams("actions.descriptions.move",["`"+data.get("opendiscord:name").value+"`"])) if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) }) ) //TICKET USER ADDED - embeds.add(new api.ODEmbed("openticket:add-message")) - embeds.get("openticket:add-message").workers.add( - new api.ODWorker("openticket:add-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:add-message")) + embeds.get("opendiscord:add-message").workers.add( + new api.ODWorker("opendiscord:add-message",0,async (instance,params,source) => { const {user,ticket,reason,data} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -756,9 +756,9 @@ const ticketEmbeds = () => { ) //TICKET USER REMOVED - embeds.add(new api.ODEmbed("openticket:remove-message")) - embeds.get("openticket:remove-message").workers.add( - new api.ODWorker("openticket:remove-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:remove-message")) + embeds.get("opendiscord:remove-message").workers.add( + new api.ODWorker("opendiscord:remove-message",0,async (instance,params,source) => { const {user,ticket,reason,data} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -770,9 +770,9 @@ const ticketEmbeds = () => { ) //TICKET ACTION DM - embeds.add(new api.ODEmbed("openticket:ticket-action-dm")) - embeds.get("openticket:ticket-action-dm").workers.add( - new api.ODWorker("openticket:ticket-action-dm",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:ticket-action-dm")) + embeds.get("opendiscord:ticket-action-dm").workers.add( + new api.ODWorker("opendiscord:ticket-action-dm",0,async (instance,params,source) => { const {user,mode,ticket,reason,additionalData} = params const channel = await opendiscord.tickets.getTicketChannel(ticket) @@ -807,7 +807,7 @@ const ticketEmbeds = () => { instance.setDescription(lang.getTranslationWithParams("actions.logs.renameDm",["`#"+(typeof additionalData == "string" ? additionalData : "")+"`"])) }else if (mode == "move"){ instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.move"))) - instance.setDescription(lang.getTranslationWithParams("actions.logs.moveDm",["`"+(additionalData instanceof api.ODTicketOption ? additionalData.get("openticket:name").value : "")+"`"])) + instance.setDescription(lang.getTranslationWithParams("actions.logs.moveDm",["`"+(additionalData instanceof api.ODTicketOption ? additionalData.get("opendiscord:name").value : "")+"`"])) }else if (mode == "add"){ instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.add"))) instance.setDescription(lang.getTranslationWithParams("actions.logs.addDm",[(additionalData instanceof discord.User ? discord.userMention(additionalData.id) : "")])) @@ -819,9 +819,9 @@ const ticketEmbeds = () => { ) //TICKET ACTION LOGS - embeds.add(new api.ODEmbed("openticket:ticket-action-logs")) - embeds.get("openticket:ticket-action-logs").workers.add( - new api.ODWorker("openticket:ticket-action-logs",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:ticket-action-logs")) + embeds.get("opendiscord:ticket-action-logs").workers.add( + new api.ODWorker("opendiscord:ticket-action-logs",0,async (instance,params,source) => { const {user,mode,ticket,reason,additionalData} = params const channel = await opendiscord.tickets.getTicketChannel(ticket) @@ -832,7 +832,7 @@ const ticketEmbeds = () => { instance.addFields( {name:lang.getTranslation("params.uppercase.ticket")+":",value:"```#"+(channel ? channel.name : "")+"```",inline:false}, //TODO TRANSLATION!!! - {name:"Option"+":",value:"```"+(ticket.option.get("openticket:name").value)+"```",inline:false}, + {name:"Option"+":",value:"```"+(ticket.option.get("opendiscord:name").value)+"```",inline:false}, ) if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```",inline:false}) @@ -862,7 +862,7 @@ const ticketEmbeds = () => { instance.setDescription(lang.getTranslationWithParams("actions.logs.renameLog",["`#"+(typeof additionalData == "string" ? additionalData : "")+"`",discord.userMention(user.id)])) }else if (mode == "move"){ instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.move"))) - instance.setDescription(lang.getTranslationWithParams("actions.logs.moveLog",["`"+(additionalData instanceof api.ODTicketOption ? additionalData.get("openticket:name").value : "")+"`",discord.userMention(user.id)])) + instance.setDescription(lang.getTranslationWithParams("actions.logs.moveLog",["`"+(additionalData instanceof api.ODTicketOption ? additionalData.get("opendiscord:name").value : "")+"`",discord.userMention(user.id)])) }else if (mode == "add"){ instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.add"))) instance.setDescription(lang.getTranslationWithParams("actions.logs.addLog",[(additionalData instanceof discord.User ? discord.userMention(additionalData.id) : ""),discord.userMention(user.id)])) @@ -876,9 +876,9 @@ const ticketEmbeds = () => { const blacklistEmbeds = () => { //BLACKLIST VIEW - embeds.add(new api.ODEmbed("openticket:blacklist-view")) - embeds.get("openticket:blacklist-view").workers.add( - new api.ODWorker("openticket:blacklist-view",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:blacklist-view")) + embeds.get("opendiscord:blacklist-view").workers.add( + new api.ODWorker("opendiscord:blacklist-view",0,async (instance,params,source) => { const {user} = params const renderedUsers: string[] = [] @@ -896,9 +896,9 @@ const blacklistEmbeds = () => { }) ) //BLACKLIST GET - embeds.add(new api.ODEmbed("openticket:blacklist-get")) - embeds.get("openticket:blacklist-get").workers.add( - new api.ODWorker("openticket:blacklist-get",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:blacklist-get")) + embeds.get("opendiscord:blacklist-get").workers.add( + new api.ODWorker("opendiscord:blacklist-get",0,async (instance,params,source) => { const {user,data} = params const blacklist = opendiscord.blacklist.get(data.id) @@ -915,9 +915,9 @@ const blacklistEmbeds = () => { ) //BLACKLIST ADD - embeds.add(new api.ODEmbed("openticket:blacklist-add")) - embeds.get("openticket:blacklist-add").workers.add( - new api.ODWorker("openticket:blacklist-add",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:blacklist-add")) + embeds.get("opendiscord:blacklist-add").workers.add( + new api.ODWorker("opendiscord:blacklist-add",0,async (instance,params,source) => { const {user,data,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -929,9 +929,9 @@ const blacklistEmbeds = () => { ) //BLACKLIST REMOVE - embeds.add(new api.ODEmbed("openticket:blacklist-remove")) - embeds.get("openticket:blacklist-remove").workers.add( - new api.ODWorker("openticket:blacklist-remove",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:blacklist-remove")) + embeds.get("opendiscord:blacklist-remove").workers.add( + new api.ODWorker("opendiscord:blacklist-remove",0,async (instance,params,source) => { const {user,data,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -943,9 +943,9 @@ const blacklistEmbeds = () => { ) //BLACKLIST DM - embeds.add(new api.ODEmbed("openticket:blacklist-dm")) - embeds.get("openticket:blacklist-dm").workers.add( - new api.ODWorker("openticket:blacklist-dm",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:blacklist-dm")) + embeds.get("opendiscord:blacklist-dm").workers.add( + new api.ODWorker("opendiscord:blacklist-dm",0,async (instance,params,source) => { const {user,mode,data,reason} = params const title = (mode == "add") ? lang.getTranslation("actions.titles.blacklistAddDm") : lang.getTranslation("actions.titles.blacklistRemoveDm") @@ -960,9 +960,9 @@ const blacklistEmbeds = () => { ) //BLACKLIST LOGS - embeds.add(new api.ODEmbed("openticket:blacklist-logs")) - embeds.get("openticket:blacklist-logs").workers.add( - new api.ODWorker("openticket:blacklist-logs",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:blacklist-logs")) + embeds.get("opendiscord:blacklist-logs").workers.add( + new api.ODWorker("opendiscord:blacklist-logs",0,async (instance,params,source) => { const {user,mode,data,reason} = params const title = (mode == "add") ? lang.getTranslation("actions.titles.blacklistAdd") : lang.getTranslation("actions.titles.blacklistRemove") @@ -981,18 +981,18 @@ const blacklistEmbeds = () => { const transcriptEmbeds = () => { //TRANSCRIPT TEXT READY - embeds.add(new api.ODEmbed("openticket:transcript-text-ready")) - embeds.get("openticket:transcript-text-ready").workers.add( - new api.ODWorker("openticket:transcript-text-ready",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:transcript-text-ready")) + embeds.get("opendiscord:transcript-text-ready").workers.add( + new api.ODWorker("opendiscord:transcript-text-ready",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler} = params - const transcriptConfig = opendiscord.configs.get("openticket:transcripts") + const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts") instance.setColor(transcriptConfig.data.embedSettings.customColor ? transcriptConfig.data.embedSettings.customColor : generalConfig.data.mainColor) instance.setTitle(utilities.emojiTitle("📄",lang.getTranslation("transcripts.success.ready"))) instance.setTimestamp(new Date()) instance.addFields({name:lang.getTranslation("params.uppercase.ticket")+":",value:"#"+channel.name,inline:false}) - const creatorId = ticket.get("openticket:opened-by").value + const creatorId = ticket.get("opendiscord:opened-by").value if (creatorId){ try{ const creator = await channel.client.users.fetch(creatorId) @@ -1011,11 +1011,11 @@ const transcriptEmbeds = () => { ) //TRANSCRIPT HTML READY - embeds.add(new api.ODEmbed("openticket:transcript-html-ready")) - embeds.get("openticket:transcript-html-ready").workers.add( - new api.ODWorker("openticket:transcript-html-ready",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:transcript-html-ready")) + embeds.get("opendiscord:transcript-html-ready").workers.add( + new api.ODWorker("opendiscord:transcript-html-ready",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler,result} = params - const transcriptConfig = opendiscord.configs.get("openticket:transcripts") + const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts") instance.setColor(transcriptConfig.data.embedSettings.customColor ? transcriptConfig.data.embedSettings.customColor : generalConfig.data.mainColor) instance.setTitle(utilities.emojiTitle("📄",lang.getTranslation("transcripts.success.ready"))) @@ -1023,7 +1023,7 @@ const transcriptEmbeds = () => { instance.addFields({name:lang.getTranslation("params.uppercase.ticket")+":",value:"#"+channel.name,inline:false}) if (result.data) instance.setUrl(result.data.url) - const creatorId = ticket.get("openticket:opened-by").value + const creatorId = ticket.get("opendiscord:opened-by").value if (creatorId){ try{ const creator = await channel.client.users.fetch(creatorId) @@ -1042,9 +1042,9 @@ const transcriptEmbeds = () => { ) //TRANSCRIPT HTML PROGRESS - embeds.add(new api.ODEmbed("openticket:transcript-html-progress")) - embeds.get("openticket:transcript-html-progress").workers.add( - new api.ODWorker("openticket:transcript-html-progress",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:transcript-html-progress")) + embeds.get("opendiscord:transcript-html-progress").workers.add( + new api.ODWorker("opendiscord:transcript-html-progress",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler,remaining} = params const remainingDate = new Date(new Date().getTime()+remaining) @@ -1056,7 +1056,7 @@ const transcriptEmbeds = () => { instance.addFields({name:lang.getTranslation("params.uppercase.remaining")+":",value:discord.time(remainingDate,"R"),inline:false}) instance.addFields({name:lang.getTranslation("params.uppercase.ticket")+":",value:"#"+channel.name,inline:false}) - const creatorId = ticket.get("openticket:opened-by").value + const creatorId = ticket.get("opendiscord:opened-by").value if (creatorId){ try{ const creator = await channel.client.users.fetch(creatorId) @@ -1068,9 +1068,9 @@ const transcriptEmbeds = () => { ) //TRANSCRIPT ERROR - embeds.add(new api.ODEmbed("openticket:transcript-error")) - embeds.get("openticket:transcript-error").workers.add( - new api.ODWorker("openticket:transcript-error",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:transcript-error")) + embeds.get("opendiscord:transcript-error").workers.add( + new api.ODWorker("opendiscord:transcript-error",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler,reason} = params instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) @@ -1085,9 +1085,9 @@ const transcriptEmbeds = () => { const roleEmbeds = () => { //REACTION ROLE - embeds.add(new api.ODEmbed("openticket:reaction-role")) - embeds.get("openticket:reaction-role").workers.add( - new api.ODWorker("openticket:reaction-role",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:reaction-role")) + embeds.get("opendiscord:reaction-role").workers.add( + new api.ODWorker("opendiscord:reaction-role",0,async (instance,params,source) => { const {guild,user,role,result} = params instance.setColor(generalConfig.data.mainColor) @@ -1111,9 +1111,9 @@ const roleEmbeds = () => { const clearEmbeds = () => { //CLEAR VERIFY MESSAGE - embeds.add(new api.ODEmbed("openticket:clear-verify-message")) - embeds.get("openticket:clear-verify-message").workers.add( - new api.ODWorker("openticket:clear-verify-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:clear-verify-message")) + embeds.get("opendiscord:clear-verify-message").workers.add( + new api.ODWorker("opendiscord:clear-verify-message",0,async (instance,params,source) => { const {guild,channel,user,filter,list} = params instance.setColor(generalConfig.data.mainColor) @@ -1129,9 +1129,9 @@ const clearEmbeds = () => { ) //CLEAR MESSAGE - embeds.add(new api.ODEmbed("openticket:clear-message")) - embeds.get("openticket:clear-message").workers.add( - new api.ODWorker("openticket:clear-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:clear-message")) + embeds.get("opendiscord:clear-message").workers.add( + new api.ODWorker("opendiscord:clear-message",0,async (instance,params,source) => { const {guild,channel,user,filter,list} = params instance.setColor(generalConfig.data.mainColor) @@ -1146,9 +1146,9 @@ const clearEmbeds = () => { ) //CLEAR LOGS - embeds.add(new api.ODEmbed("openticket:clear-logs")) - embeds.get("openticket:clear-logs").workers.add( - new api.ODWorker("openticket:clear-logs",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:clear-logs")) + embeds.get("opendiscord:clear-logs").workers.add( + new api.ODWorker("opendiscord:clear-logs",0,async (instance,params,source) => { const {guild,channel,user,filter,list} = params instance.setColor(generalConfig.data.mainColor) @@ -1166,11 +1166,11 @@ const clearEmbeds = () => { const autoEmbeds = () => { //AUTOCLOSE MESSAGE - embeds.add(new api.ODEmbed("openticket:autoclose-message")) - embeds.get("openticket:autoclose-message").workers.add( - new api.ODWorker("openticket:autoclose-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:autoclose-message")) + embeds.get("opendiscord:autoclose-message").workers.add( + new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,source) => { const {user,ticket} = params - const hours: number = ticket.get("openticket:autoclose-hours").value + const hours: number = ticket.get("opendiscord:autoclose-hours").value const description = (source == "leave") ? lang.getTranslation("actions.descriptions.autocloseLeave") : lang.getTranslationWithParams("actions.descriptions.autocloseTimeout",[hours.toString()]) instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -1182,11 +1182,11 @@ const autoEmbeds = () => { ) //AUTODELETE MESSAGE - embeds.add(new api.ODEmbed("openticket:autodelete-message")) - embeds.get("openticket:autodelete-message").workers.add( - new api.ODWorker("openticket:autodelete-message",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:autodelete-message")) + embeds.get("opendiscord:autodelete-message").workers.add( + new api.ODWorker("opendiscord:autodelete-message",0,async (instance,params,source) => { const {user,ticket} = params - const days: number = ticket.get("openticket:autodelete-days").value + const days: number = ticket.get("opendiscord:autodelete-days").value const description = (source == "leave") ? lang.getTranslation("actions.descriptions.autodeleteLeave") : lang.getTranslationWithParams("actions.descriptions.autodeleteTimeout",[days.toString()]) instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -1198,9 +1198,9 @@ const autoEmbeds = () => { ) //AUTOCLOSE ENABLE - embeds.add(new api.ODEmbed("openticket:autoclose-enable")) - embeds.get("openticket:autoclose-enable").workers.add( - new api.ODWorker("openticket:autoclose-enable",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:autoclose-enable")) + embeds.get("opendiscord:autoclose-enable").workers.add( + new api.ODWorker("opendiscord:autoclose-enable",0,async (instance,params,source) => { const {user,ticket,reason,time} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -1212,9 +1212,9 @@ const autoEmbeds = () => { ) //AUTODELETE ENABLE - embeds.add(new api.ODEmbed("openticket:autodelete-enable")) - embeds.get("openticket:autodelete-enable").workers.add( - new api.ODWorker("openticket:autodelete-enable",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:autodelete-enable")) + embeds.get("opendiscord:autodelete-enable").workers.add( + new api.ODWorker("opendiscord:autodelete-enable",0,async (instance,params,source) => { const {user,ticket,reason,time} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -1226,9 +1226,9 @@ const autoEmbeds = () => { ) //AUTOCLOSE DISABLE - embeds.add(new api.ODEmbed("openticket:autoclose-disable")) - embeds.get("openticket:autoclose-disable").workers.add( - new api.ODWorker("openticket:autoclose-disable",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:autoclose-disable")) + embeds.get("opendiscord:autoclose-disable").workers.add( + new api.ODWorker("opendiscord:autoclose-disable",0,async (instance,params,source) => { const {user,ticket,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) @@ -1240,9 +1240,9 @@ const autoEmbeds = () => { ) //AUTODELETE DISABLE - embeds.add(new api.ODEmbed("openticket:autodelete-disable")) - embeds.get("openticket:autodelete-disable").workers.add( - new api.ODWorker("openticket:autodelete-disable",0,async (instance,params,source) => { + embeds.add(new api.ODEmbed("opendiscord:autodelete-disable")) + embeds.get("opendiscord:autodelete-disable").workers.add( + new api.ODWorker("opendiscord:autodelete-disable",0,async (instance,params,source) => { const {user,ticket,reason} = params instance.setAuthor(user.displayName,user.displayAvatarURL()) diff --git a/src/builders/files.ts b/src/builders/files.ts index c23daa0..9a30548 100644 --- a/src/builders/files.ts +++ b/src/builders/files.ts @@ -6,7 +6,7 @@ import * as discord from "discord.js" const files = opendiscord.builders.files const lang = opendiscord.languages -const transcriptConfig = opendiscord.configs.get("openticket:transcripts") +const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts") export const registerAllFiles = async () => { transcriptFiles() @@ -15,15 +15,15 @@ export const registerAllFiles = async () => { const transcriptFiles = () => { //TEXT TRANSCRIPT - files.add(new api.ODFile("openticket:text-transcript")) - files.get("openticket:text-transcript").workers.add( - new api.ODWorker("openticket:text-transcript",0,async (instance,params,source) => { + files.add(new api.ODFile("opendiscord:text-transcript")) + files.get("opendiscord:text-transcript").workers.add( + new api.ODWorker("opendiscord:text-transcript",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler,result} = params const fileMode = transcriptConfig.data.textTranscriptStyle.fileMode const customName = transcriptConfig.data.textTranscriptStyle.customFileName - const creatorId = ticket.get("openticket:opened-by").value ?? "unknown-creator-id" + const creatorId = ticket.get("opendiscord:opened-by").value ?? "unknown-creator-id" const creator = (await opendiscord.tickets.getTicketUser(ticket,"creator")) if (fileMode == "custom") instance.setName(customName.split(".")[0]+".txt") @@ -35,7 +35,7 @@ const transcriptFiles = () => { instance.setDescription(lang.getTranslation("transcripts.success.textFileDescription")) - if (compiler.id.value != "openticket:text-compiler" || !result.data || typeof result.data.contents != "string"){ + if (compiler.id.value != "opendiscord:text-compiler" || !result.data || typeof result.data.contents != "string"){ instance.setContents("") return } diff --git a/src/builders/messages.ts b/src/builders/messages.ts index 0bdb0c5..d0353a2 100644 --- a/src/builders/messages.ts +++ b/src/builders/messages.ts @@ -10,7 +10,7 @@ const dropdowns = opendiscord.builders.dropdowns const files = opendiscord.builders.files const embeds = opendiscord.builders.embeds const lang = opendiscord.languages -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerAllMessages = async () => { verifyBarMessages() @@ -28,25 +28,25 @@ export const registerAllMessages = async () => { const verifyBarMessages = () => { //VERIFYBAR TICKET MESSAGE - messages.add(new api.ODMessage("openticket:verifybar-ticket-message")) - messages.get("openticket:verifybar-ticket-message").workers.add( - new api.ODWorker("openticket:verifybar-ticket-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:verifybar-ticket-message")) + messages.get("opendiscord:verifybar-ticket-message").workers.add( + new api.ODWorker("opendiscord:verifybar-ticket-message",0,async (instance,params,source) => { const {guild,channel,user,verifybar} = params if (!guild){ - instance.setContent("ODError: Not In Guild => `openticket:verifybar-ticket-message`") + instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-ticket-message`") return } const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ - instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-ticket-message`") + instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-ticket-message`") return } const option = ticket.option //add pings - const pingOptions = option.get("openticket:ticket-message-ping").value + const pingOptions = option.get("opendiscord:ticket-message-ping").value const pings: string[] = [] - const creator = ticket.get("openticket:opened-by").value + const creator = ticket.get("opendiscord:opened-by").value if (creator) pings.push(discord.userMention(creator)) if (pingOptions["@everyone"]) pings.push("@everyone") if (pingOptions["@here"]) pings.push("@here") @@ -54,65 +54,65 @@ const verifyBarMessages = () => { const pingText = (pings.length > 0) ? pings.join(" ")+"\n" : "" //add text - const text = option.get("openticket:ticket-message-text").value + const text = option.get("opendiscord:ticket-message-text").value if (text !== "") instance.setContent(pingText+text) else instance.setContent(pingText) //add embed - if (option.get("openticket:ticket-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + if (option.get("opendiscord:ticket-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) //add verifybar components - if (verifybar.id.value == "openticket:claim-ticket-ticket-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (verifybar.id.value == "opendiscord:claim-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - }else if (verifybar.id.value == "openticket:unclaim-ticket-ticket-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + }else if (verifybar.id.value == "opendiscord:unclaim-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - }else if (verifybar.id.value == "openticket:pin-ticket-ticket-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + }else if (verifybar.id.value == "opendiscord:pin-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - }else if (verifybar.id.value == "openticket:unpin-ticket-ticket-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + }else if (verifybar.id.value == "opendiscord:unpin-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - }else if (verifybar.id.value == "openticket:close-ticket-ticket-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + }else if (verifybar.id.value == "opendiscord:close-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - }else if (verifybar.id.value == "openticket:reopen-ticket-ticket-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + }else if (verifybar.id.value == "opendiscord:reopen-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - }else if (verifybar.id.value == "openticket:delete-ticket-ticket-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) + }else if (verifybar.id.value == "opendiscord:delete-ticket-ticket-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) } }) ) //TICKET CLOSED - messages.add(new api.ODMessage("openticket:verifybar-close-message")) - messages.get("openticket:verifybar-close-message").workers.add( - new api.ODWorker("openticket:verifybar-close-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:verifybar-close-message")) + messages.get("opendiscord:verifybar-close-message").workers.add( + new api.ODWorker("opendiscord:verifybar-close-message",0,async (instance,params,source) => { const {guild,channel,user,verifybar,originalMessage} = params if (!guild){ - instance.setContent("ODError: Not In Guild => `openticket:verifybar-close-message`") + instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-close-message`") return } const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ - instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-close-message`") + instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-close-message`") return } @@ -120,35 +120,35 @@ const verifyBarMessages = () => { const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) //add embed - instance.addEmbed(await embeds.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason})) //add verifybar components - if (verifybar.id.value == "openticket:reopen-ticket-close-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (verifybar.id.value == "opendiscord:reopen-ticket-close-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - }else if (verifybar.id.value == "openticket:delete-ticket-close-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) + }else if (verifybar.id.value == "opendiscord:delete-ticket-close-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) } }) ) //TICKET REOPENED - messages.add(new api.ODMessage("openticket:verifybar-reopen-message")) - messages.get("openticket:verifybar-reopen-message").workers.add( - new api.ODWorker("openticket:verifybar-reopen-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:verifybar-reopen-message")) + messages.get("opendiscord:verifybar-reopen-message").workers.add( + new api.ODWorker("opendiscord:verifybar-reopen-message",0,async (instance,params,source) => { const {guild,channel,user,verifybar,originalMessage} = params if (!guild){ - instance.setContent("ODError: Not In Guild => `openticket:verifybar-reopen-message`") + instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-reopen-message`") return } const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ - instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-reopen-message`") + instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-reopen-message`") return } @@ -156,35 +156,35 @@ const verifyBarMessages = () => { const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) //add embed - instance.addEmbed(await embeds.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason})) //add verifybar components - if (verifybar.id.value == "openticket:close-ticket-reopen-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (verifybar.id.value == "opendiscord:close-ticket-reopen-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - }else if (verifybar.id.value == "openticket:delete-ticket-reopen-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) + }else if (verifybar.id.value == "opendiscord:delete-ticket-reopen-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) } }) ) //TICKET CLAIM - messages.add(new api.ODMessage("openticket:verifybar-claim-message")) - messages.get("openticket:verifybar-claim-message").workers.add( - new api.ODWorker("openticket:verifybar-claim-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:verifybar-claim-message")) + messages.get("opendiscord:verifybar-claim-message").workers.add( + new api.ODWorker("opendiscord:verifybar-claim-message",0,async (instance,params,source) => { const {guild,channel,user,verifybar,originalMessage} = params if (!guild){ - instance.setContent("ODError: Not In Guild => `openticket:verifybar-claim-message`") + instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-claim-message`") return } const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ - instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-claim-message`") + instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-claim-message`") return } @@ -192,29 +192,29 @@ const verifyBarMessages = () => { const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) //add embed - instance.addEmbed(await embeds.getSafe("openticket:claim-message").build("other",{guild,channel,user,ticket,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:claim-message").build("other",{guild,channel,user,ticket,reason})) //add verifybar components - if (verifybar.id.value == "openticket:unclaim-ticket-claim-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (verifybar.id.value == "opendiscord:unclaim-ticket-claim-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) } }) ) //TICKET UNCLAIM - messages.add(new api.ODMessage("openticket:verifybar-unclaim-message")) - messages.get("openticket:verifybar-unclaim-message").workers.add( - new api.ODWorker("openticket:verifybar-unclaim-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:verifybar-unclaim-message")) + messages.get("opendiscord:verifybar-unclaim-message").workers.add( + new api.ODWorker("opendiscord:verifybar-unclaim-message",0,async (instance,params,source) => { const {guild,channel,user,verifybar,originalMessage} = params if (!guild){ - instance.setContent("ODError: Not In Guild => `openticket:verifybar-unclaim-message`") + instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-unclaim-message`") return } const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ - instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-unclaim-message`") + instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-unclaim-message`") return } @@ -222,29 +222,29 @@ const verifyBarMessages = () => { const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) //add embed - instance.addEmbed(await embeds.getSafe("openticket:unclaim-message").build("other",{guild,channel,user,ticket,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:unclaim-message").build("other",{guild,channel,user,ticket,reason})) //add verifybar components - if (verifybar.id.value == "openticket:claim-ticket-unclaim-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (verifybar.id.value == "opendiscord:claim-ticket-unclaim-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) } }) ) //TICKET PIN - messages.add(new api.ODMessage("openticket:verifybar-pin-message")) - messages.get("openticket:verifybar-pin-message").workers.add( - new api.ODWorker("openticket:verifybar-pin-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:verifybar-pin-message")) + messages.get("opendiscord:verifybar-pin-message").workers.add( + new api.ODWorker("opendiscord:verifybar-pin-message",0,async (instance,params,source) => { const {guild,channel,user,verifybar,originalMessage} = params if (!guild){ - instance.setContent("ODError: Not In Guild => `openticket:verifybar-pin-message`") + instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-pin-message`") return } const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ - instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-pin-message`") + instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-pin-message`") return } @@ -252,29 +252,29 @@ const verifyBarMessages = () => { const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) //add embed - instance.addEmbed(await embeds.getSafe("openticket:pin-message").build("other",{guild,channel,user,ticket,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:pin-message").build("other",{guild,channel,user,ticket,reason})) //add verifybar components - if (verifybar.id.value == "openticket:unpin-ticket-pin-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (verifybar.id.value == "opendiscord:unpin-ticket-pin-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) } }) ) //TICKET UNPIN - messages.add(new api.ODMessage("openticket:verifybar-unpin-message")) - messages.get("openticket:verifybar-unpin-message").workers.add( - new api.ODWorker("openticket:verifybar-unpin-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:verifybar-unpin-message")) + messages.get("opendiscord:verifybar-unpin-message").workers.add( + new api.ODWorker("opendiscord:verifybar-unpin-message",0,async (instance,params,source) => { const {guild,channel,user,verifybar,originalMessage} = params if (!guild){ - instance.setContent("ODError: Not In Guild => `openticket:verifybar-unpin-message`") + instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-unpin-message`") return } const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ - instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-unpin-message`") + instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-unpin-message`") return } @@ -282,46 +282,46 @@ const verifyBarMessages = () => { const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3) //add embed - instance.addEmbed(await embeds.getSafe("openticket:unpin-message").build("other",{guild,channel,user,ticket,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:unpin-message").build("other",{guild,channel,user,ticket,reason})) //add verifybar components - if (verifybar.id.value == "openticket:pin-ticket-unpin-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (verifybar.id.value == "opendiscord:pin-ticket-unpin-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) } }) ) //TICKET AUTOCLOSED - messages.add(new api.ODMessage("openticket:verifybar-autoclose-message")) - messages.get("openticket:verifybar-autoclose-message").workers.add( - new api.ODWorker("openticket:verifybar-autoclose-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:verifybar-autoclose-message")) + messages.get("opendiscord:verifybar-autoclose-message").workers.add( + new api.ODWorker("opendiscord:verifybar-autoclose-message",0,async (instance,params,source) => { const {guild,channel,user,verifybar,originalMessage} = params if (!guild || channel.isDMBased()){ - instance.setContent("ODError: Not In Guild => `openticket:verifybar-autoclose-message`") + instance.setContent("ODError: Not In Guild => `opendiscord:verifybar-autoclose-message`") return } const ticket = opendiscord.tickets.get(channel.id) if (!ticket){ - instance.setContent("ODError: Unknown Ticket => `openticket:verifybar-autoclose-message`") + instance.setContent("ODError: Unknown Ticket => `opendiscord:verifybar-autoclose-message`") return } //add embed - instance.addEmbed(await embeds.getSafe("openticket:autoclose-message").build("other",{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-message").build("other",{guild,channel,user,ticket})) //add verifybar components - if (verifybar.id.value == "openticket:reopen-ticket-autoclose-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (verifybar.id.value == "opendiscord:reopen-ticket-autoclose-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - }else if (verifybar.id.value == "openticket:delete-ticket-autoclose-message"){ - instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) - instance.addComponent(await buttons.getSafe("openticket:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) - if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) - if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("openticket:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) + }else if (verifybar.id.value == "opendiscord:delete-ticket-autoclose-message"){ + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar})) + instance.addComponent(await buttons.getSafe("opendiscord:verifybar-failure").build("verifybar",{guild,channel,user,verifybar})) + if (generalConfig.data.system.enableTicketActionWithReason) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"reason",customEmoji:"✏️",customLabel:lang.getTranslation("actions.buttons.withReason"),customColor:"blue"})) + if (generalConfig.data.system.enableDeleteWithoutTranscript) instance.addComponent(await buttons.getSafe("opendiscord:verifybar-success").build("verifybar",{guild,channel,user,verifybar,customData:"no-transcript",customEmoji:"📄",customLabel:lang.getTranslation("actions.buttons.withoutTranscript"),customColor:"red"})) } }) ) @@ -329,162 +329,162 @@ const verifyBarMessages = () => { const errorMessages = () => { //ERROR - messages.add(new api.ODMessage("openticket:error")) - messages.get("openticket:error").workers.add( - new api.ODWorker("openticket:error",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error")) + messages.get("opendiscord:error").workers.add( + new api.ODWorker("opendiscord:error",0,async (instance,params,source) => { const {guild,channel,user,error,layout} = params - instance.addEmbed(await embeds.getSafe("openticket:error").build(source,{guild,channel,user,error,layout})) + instance.addEmbed(await embeds.getSafe("opendiscord:error").build(source,{guild,channel,user,error,layout})) instance.setEphemeral(true) }) ) //ERROR OPTION MISSING - messages.add(new api.ODMessage("openticket:error-option-missing")) - messages.get("openticket:error-option-missing").workers.add( - new api.ODWorker("openticket:error-option-missing",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-option-missing")) + messages.get("opendiscord:error-option-missing").workers.add( + new api.ODWorker("opendiscord:error-option-missing",0,async (instance,params,source) => { const {guild,channel,user,error} = params - instance.addEmbed(await embeds.getSafe("openticket:error-option-missing").build(source,{guild,channel,user,error})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-option-missing").build(source,{guild,channel,user,error})) instance.setEphemeral(true) }) ) //ERROR OPTION INVALID - messages.add(new api.ODMessage("openticket:error-option-invalid")) - messages.get("openticket:error-option-invalid").workers.add( - new api.ODWorker("openticket:error-option-invalid",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-option-invalid")) + messages.get("opendiscord:error-option-invalid").workers.add( + new api.ODWorker("opendiscord:error-option-invalid",0,async (instance,params,source) => { const {guild,channel,user,error} = params - instance.addEmbed(await embeds.getSafe("openticket:error-option-invalid").build(source,{guild,channel,user,error})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-option-invalid").build(source,{guild,channel,user,error})) instance.setEphemeral(true) }) ) //ERROR UNKNOWN COMMAND - messages.add(new api.ODMessage("openticket:error-unknown-command")) - messages.get("openticket:error-unknown-command").workers.add( - new api.ODWorker("openticket:error-unknown-command",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-unknown-command")) + messages.get("opendiscord:error-unknown-command").workers.add( + new api.ODWorker("opendiscord:error-unknown-command",0,async (instance,params,source) => { const {guild,channel,user,error} = params - instance.addEmbed(await embeds.getSafe("openticket:error-unknown-command").build(source,{guild,channel,user,error})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-unknown-command").build(source,{guild,channel,user,error})) instance.setEphemeral(true) }) ) //ERROR NO PERMISSIONS - messages.add(new api.ODMessage("openticket:error-no-permissions")) - messages.get("openticket:error-no-permissions").workers.add( - new api.ODWorker("openticket:error-no-permissions",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-no-permissions")) + messages.get("opendiscord:error-no-permissions").workers.add( + new api.ODWorker("opendiscord:error-no-permissions",0,async (instance,params,source) => { const {guild,channel,user,permissions} = params - instance.addEmbed(await embeds.getSafe("openticket:error-no-permissions").build(source,{guild,channel,user,permissions})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions").build(source,{guild,channel,user,permissions})) instance.setEphemeral(true) }) ) //ERROR NO PERMISSIONS COOLDOWN - messages.add(new api.ODMessage("openticket:error-no-permissions-cooldown")) - messages.get("openticket:error-no-permissions-cooldown").workers.add( - new api.ODWorker("openticket:error-no-permissions-cooldown",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-no-permissions-cooldown")) + messages.get("opendiscord:error-no-permissions-cooldown").workers.add( + new api.ODWorker("opendiscord:error-no-permissions-cooldown",0,async (instance,params,source) => { const {guild,channel,user,until} = params - instance.addEmbed(await embeds.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild,channel,user,until})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions-cooldown").build(source,{guild,channel,user,until})) instance.setEphemeral(true) }) ) //ERROR NO PERMISSIONS BLACKLISTED - messages.add(new api.ODMessage("openticket:error-no-permissions-blacklisted")) - messages.get("openticket:error-no-permissions-blacklisted").workers.add( - new api.ODWorker("openticket:error-no-permissions-blacklisted",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-no-permissions-blacklisted")) + messages.get("opendiscord:error-no-permissions-blacklisted").workers.add( + new api.ODWorker("opendiscord:error-no-permissions-blacklisted",0,async (instance,params,source) => { const {guild,channel,user} = params - instance.addEmbed(await embeds.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild,channel,user})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions-blacklisted").build(source,{guild,channel,user})) instance.setEphemeral(true) }) ) //ERROR NO PERMISSIONS LIMITS - messages.add(new api.ODMessage("openticket:error-no-permissions-limits")) - messages.get("openticket:error-no-permissions-limits").workers.add( - new api.ODWorker("openticket:error-no-permissions-limits",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-no-permissions-limits")) + messages.get("opendiscord:error-no-permissions-limits").workers.add( + new api.ODWorker("opendiscord:error-no-permissions-limits",0,async (instance,params,source) => { const {guild,channel,user,limit} = params - instance.addEmbed(await embeds.getSafe("openticket:error-no-permissions-limits").build(source,{guild,channel,user,limit})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild,channel,user,limit})) instance.setEphemeral(true) }) ) //ERROR RESPONDER TIMEOUT - messages.add(new api.ODMessage("openticket:error-responder-timeout")) - messages.get("openticket:error-responder-timeout").workers.add( - new api.ODWorker("openticket:error-responder-timeout",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-responder-timeout")) + messages.get("opendiscord:error-responder-timeout").workers.add( + new api.ODWorker("opendiscord:error-responder-timeout",0,async (instance,params,source) => { const {guild,channel,user} = params - instance.addEmbed(await embeds.getSafe("openticket:error-responder-timeout").build(source,{guild,channel,user})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-responder-timeout").build(source,{guild,channel,user})) instance.setEphemeral(true) }) ) //ERROR TICKET UNKNOWN - messages.add(new api.ODMessage("openticket:error-ticket-unknown")) - messages.get("openticket:error-ticket-unknown").workers.add( - new api.ODWorker("openticket:error-ticket-unknown",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-ticket-unknown")) + messages.get("opendiscord:error-ticket-unknown").workers.add( + new api.ODWorker("opendiscord:error-ticket-unknown",0,async (instance,params,source) => { const {guild,channel,user} = params - instance.addEmbed(await embeds.getSafe("openticket:error-ticket-unknown").build(source,{guild,channel,user})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-ticket-unknown").build(source,{guild,channel,user})) instance.setEphemeral(true) }) ) //ERROR TICKET DEPRECATED - messages.add(new api.ODMessage("openticket:error-ticket-deprecated")) - messages.get("openticket:error-ticket-deprecated").workers.add( - new api.ODWorker("openticket:error-ticket-deprecated",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-ticket-deprecated")) + messages.get("opendiscord:error-ticket-deprecated").workers.add( + new api.ODWorker("opendiscord:error-ticket-deprecated",0,async (instance,params,source) => { const {guild,channel,user} = params - instance.addEmbed(await embeds.getSafe("openticket:error-ticket-deprecated").build(source,{guild,channel,user})) - instance.addComponent(await buttons.getSafe("openticket:error-ticket-deprecated-transcript").build(source,{})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-ticket-deprecated").build(source,{guild,channel,user})) + instance.addComponent(await buttons.getSafe("opendiscord:error-ticket-deprecated-transcript").build(source,{})) instance.setEphemeral(true) }) ) //ERROR OPTION UNKNOWN - messages.add(new api.ODMessage("openticket:error-option-unknown")) - messages.get("openticket:error-option-unknown").workers.add( - new api.ODWorker("openticket:error-option-unknown",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-option-unknown")) + messages.get("opendiscord:error-option-unknown").workers.add( + new api.ODWorker("opendiscord:error-option-unknown",0,async (instance,params,source) => { const {guild,channel,user} = params - instance.addEmbed(await embeds.getSafe("openticket:error-option-unknown").build(source,{guild,channel,user})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-option-unknown").build(source,{guild,channel,user})) instance.setEphemeral(true) }) ) //ERROR PANEL UNKNOWN - messages.add(new api.ODMessage("openticket:error-panel-unknown")) - messages.get("openticket:error-panel-unknown").workers.add( - new api.ODWorker("openticket:error-panel-unknown",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-panel-unknown")) + messages.get("opendiscord:error-panel-unknown").workers.add( + new api.ODWorker("opendiscord:error-panel-unknown",0,async (instance,params,source) => { const {guild,channel,user} = params - instance.addEmbed(await embeds.getSafe("openticket:error-panel-unknown").build(source,{guild,channel,user})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-panel-unknown").build(source,{guild,channel,user})) instance.setEphemeral(true) }) ) //ERROR NOD IN GUILD - messages.add(new api.ODMessage("openticket:error-not-in-guild")) - messages.get("openticket:error-not-in-guild").workers.add( - new api.ODWorker("openticket:error-not-in-guild",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-not-in-guild")) + messages.get("opendiscord:error-not-in-guild").workers.add( + new api.ODWorker("opendiscord:error-not-in-guild",0,async (instance,params,source) => { const {channel,user} = params - instance.addEmbed(await embeds.getSafe("openticket:error-not-in-guild").build(source,{channel,user})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user})) instance.setEphemeral(true) }) ) //ERROR CHANNEL RENAME - messages.add(new api.ODMessage("openticket:error-channel-rename")) - messages.get("openticket:error-channel-rename").workers.add( - new api.ODWorker("openticket:error-channel-rename",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-channel-rename")) + messages.get("opendiscord:error-channel-rename").workers.add( + new api.ODWorker("opendiscord:error-channel-rename",0,async (instance,params,source) => { const {guild,channel,user,originalName,newName} = params - instance.addEmbed(await embeds.getSafe("openticket:error-channel-rename").build(source,{guild,channel,user,originalName,newName})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-channel-rename").build(source,{guild,channel,user,originalName,newName})) instance.setEphemeral(true) }) ) //ERROR TICKET BUSY - messages.add(new api.ODMessage("openticket:error-ticket-busy")) - messages.get("openticket:error-ticket-busy").workers.add( - new api.ODWorker("openticket:error-ticket-busy",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:error-ticket-busy")) + messages.get("opendiscord:error-ticket-busy").workers.add( + new api.ODWorker("opendiscord:error-ticket-busy",0,async (instance,params,source) => { const {guild,channel,user} = params - instance.addEmbed(await embeds.getSafe("openticket:error-ticket-busy").build(source,{guild,channel,user})) + instance.addEmbed(await embeds.getSafe("opendiscord:error-ticket-busy").build(source,{guild,channel,user})) instance.setEphemeral(true) }) ) @@ -492,69 +492,69 @@ const errorMessages = () => { const helpMenuMessages = () => { //HELP MENU - messages.add(new api.ODMessage("openticket:help-menu")) - messages.get("openticket:help-menu").workers.add( - new api.ODWorker("openticket:help-menu",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:help-menu")) + messages.get("opendiscord:help-menu").workers.add( + new api.ODWorker("opendiscord:help-menu",0,async (instance,params,source) => { const {mode,page} = params const totalPages = (await opendiscord.helpmenu.render(mode)).length - const embed = await embeds.getSafe("openticket:help-menu").build(source,{mode,page}) + const embed = await embeds.getSafe("opendiscord:help-menu").build(source,{mode,page}) instance.addEmbed(embed) if (totalPages > 1){ //when more than 1 page - instance.addComponent(await buttons.getSafe("openticket:help-menu-previous").build(source,{mode,page})) - instance.addComponent(await buttons.getSafe("openticket:help-menu-page").build(source,{mode,page})) - instance.addComponent(await buttons.getSafe("openticket:help-menu-next").build(source,{mode,page})) - instance.addComponent(buttons.getNewLine("openticket:help-menu-divider")) + instance.addComponent(await buttons.getSafe("opendiscord:help-menu-previous").build(source,{mode,page})) + instance.addComponent(await buttons.getSafe("opendiscord:help-menu-page").build(source,{mode,page})) + instance.addComponent(await buttons.getSafe("opendiscord:help-menu-next").build(source,{mode,page})) + instance.addComponent(buttons.getNewLine("opendiscord:help-menu-divider")) } - if (generalConfig.data.textCommands && generalConfig.data.slashCommands) instance.addComponent(await buttons.get("openticket:help-menu-switch").build(source,{mode,page})) + if (generalConfig.data.textCommands && generalConfig.data.slashCommands) instance.addComponent(await buttons.get("opendiscord:help-menu-switch").build(source,{mode,page})) }) ) } const statsMessages = () => { //STATS GLOBAL - messages.add(new api.ODMessage("openticket:stats-global")) - messages.get("openticket:stats-global").workers.add( - new api.ODWorker("openticket:stats-global",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:stats-global")) + messages.get("opendiscord:stats-global").workers.add( + new api.ODWorker("opendiscord:stats-global",0,async (instance,params,source) => { const {guild,channel,user} = params - instance.addEmbed(await embeds.getSafe("openticket:stats-global").build(source,{guild,channel,user})) + instance.addEmbed(await embeds.getSafe("opendiscord:stats-global").build(source,{guild,channel,user})) }) ) //STATS TICKET - messages.add(new api.ODMessage("openticket:stats-ticket")) - messages.get("openticket:stats-ticket").workers.add( - new api.ODWorker("openticket:stats-ticket",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:stats-ticket")) + messages.get("opendiscord:stats-ticket").workers.add( + new api.ODWorker("opendiscord:stats-ticket",0,async (instance,params,source) => { const {guild,channel,user,scopeData} = params - instance.addEmbed(await embeds.getSafe("openticket:stats-ticket").build(source,{guild,channel,user,scopeData})) + instance.addEmbed(await embeds.getSafe("opendiscord:stats-ticket").build(source,{guild,channel,user,scopeData})) }) ) //STATS USER - messages.add(new api.ODMessage("openticket:stats-user")) - messages.get("openticket:stats-user").workers.add( - new api.ODWorker("openticket:stats-user",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:stats-user")) + messages.get("opendiscord:stats-user").workers.add( + new api.ODWorker("opendiscord:stats-user",0,async (instance,params,source) => { const {guild,channel,user,scopeData} = params - instance.addEmbed(await embeds.getSafe("openticket:stats-user").build(source,{guild,channel,user,scopeData})) + instance.addEmbed(await embeds.getSafe("opendiscord:stats-user").build(source,{guild,channel,user,scopeData})) }) ) //STATS RESET - messages.add(new api.ODMessage("openticket:stats-reset")) - messages.get("openticket:stats-reset").workers.add( - new api.ODWorker("openticket:stats-reset",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:stats-reset")) + messages.get("opendiscord:stats-reset").workers.add( + new api.ODWorker("opendiscord:stats-reset",0,async (instance,params,source) => { const {guild,channel,user,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:stats-reset").build(source,{guild,channel,user,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:stats-reset").build(source,{guild,channel,user,reason})) }) ) //STATS TICKET UNKNOWN - messages.add(new api.ODMessage("openticket:stats-ticket-unknown")) - messages.get("openticket:stats-ticket-unknown").workers.add( - new api.ODWorker("openticket:stats-ticket-unknown",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:stats-ticket-unknown")) + messages.get("opendiscord:stats-ticket-unknown").workers.add( + new api.ODWorker("opendiscord:stats-ticket-unknown",0,async (instance,params,source) => { const {guild,channel,user,id} = params - instance.addEmbed(await embeds.getSafe("openticket:stats-ticket-unknown").build(source,{guild,channel,user,id})) + instance.addEmbed(await embeds.getSafe("opendiscord:stats-ticket-unknown").build(source,{guild,channel,user,id})) instance.setEphemeral(true) }) ) @@ -562,14 +562,14 @@ const statsMessages = () => { const panelMessages = () => { //PANEL - messages.add(new api.ODMessage("openticket:panel")) - messages.get("openticket:panel").workers.add([ - new api.ODWorker("openticket:panel-layout",1,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:panel")) + messages.get("opendiscord:panel").workers.add([ + new api.ODWorker("opendiscord:panel-layout",1,async (instance,params,source) => { const {guild,channel,user,panel} = params //add text - const text = panel.get("openticket:text").value - if (panel.get("openticket:describe-options-in-text").value){ + const text = panel.get("opendiscord:text").value + if (panel.get("opendiscord:describe-options-in-text").value){ //describe options in text const describeText = (await import("../data/openticket/panelLoader.js")).describePanelOptions("text",panel) instance.setContent(text+"\n\n"+describeText) @@ -577,44 +577,44 @@ const panelMessages = () => { instance.setContent(text) } - if (panel.get("openticket:enable-max-tickets-warning-text").value && generalConfig.data.system.limits.enabled){ + if (panel.get("opendiscord:enable-max-tickets-warning-text").value && generalConfig.data.system.limits.enabled){ instance.setContent(instance.data.content+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.system.limits.userMaximum.toString()])+"*") } //add embed - const embedOptions = panel.get("openticket:embed").value - if (embedOptions.enabled) instance.addEmbed(await embeds.getSafe("openticket:panel").build(source,{guild,channel,user,panel})) + const embedOptions = panel.get("opendiscord:embed").value + if (embedOptions.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:panel").build(source,{guild,channel,user,panel})) }), - new api.ODWorker("openticket:panel-components",0,async (instance,params,source) => { + new api.ODWorker("opendiscord:panel-components",0,async (instance,params,source) => { const {guild,channel,user,panel} = params const options: api.ODOption[] = [] - panel.get("openticket:options").value.forEach((id) => { + panel.get("opendiscord:options").value.forEach((id) => { const opt = opendiscord.options.get(id) if (opt) options.push(opt) }) - if (panel.get("openticket:dropdown").value){ + if (panel.get("opendiscord:dropdown").value){ //dropdown const ticketOptions: api.ODTicketOption[] = [] options.forEach((option) => { if (option instanceof api.ODTicketOption) ticketOptions.push(option) }) - instance.addComponent(await dropdowns.getSafe("openticket:panel-dropdown-tickets").build(source,{guild,channel,user,panel,options:ticketOptions})) + instance.addComponent(await dropdowns.getSafe("opendiscord:panel-dropdown-tickets").build(source,{guild,channel,user,panel,options:ticketOptions})) }else{ //buttons for (const option of options){ - if (option instanceof api.ODTicketOption) instance.addComponent(await buttons.getSafe("openticket:ticket-option").build(source,{guild,channel,user,panel,option})) - else if (option instanceof api.ODWebsiteOption) instance.addComponent(await buttons.getSafe("openticket:website-option").build(source,{guild,channel,user,panel,option})) - else if (option instanceof api.ODRoleOption) instance.addComponent(await buttons.getSafe("openticket:role-option").build(source,{guild,channel,user,panel,option})) + if (option instanceof api.ODTicketOption) instance.addComponent(await buttons.getSafe("opendiscord:ticket-option").build(source,{guild,channel,user,panel,option})) + else if (option instanceof api.ODWebsiteOption) instance.addComponent(await buttons.getSafe("opendiscord:website-option").build(source,{guild,channel,user,panel,option})) + else if (option instanceof api.ODRoleOption) instance.addComponent(await buttons.getSafe("opendiscord:role-option").build(source,{guild,channel,user,panel,option})) } } }) ]) //PANEL READY - messages.add(new api.ODMessage("openticket:panel-ready")) - messages.get("openticket:panel-ready").workers.add( - new api.ODWorker("openticket:panel-ready",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:panel-ready")) + messages.get("opendiscord:panel-ready").workers.add( + new api.ODWorker("opendiscord:panel-ready",0,async (instance,params,source) => { instance.setContent("## "+lang.getTranslation("actions.descriptions.panelReady")) instance.setEphemeral(true) }) @@ -623,56 +623,56 @@ const panelMessages = () => { const ticketMessages = () => { //TICKET CREATED - messages.add(new api.ODMessage("openticket:ticket-created")) - messages.get("openticket:ticket-created").workers.add( - new api.ODWorker("openticket:ticket-created",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:ticket-created")) + messages.get("opendiscord:ticket-created").workers.add( + new api.ODWorker("opendiscord:ticket-created",0,async (instance,params,source) => { const {guild,channel,user,ticket} = params - instance.addEmbed(await embeds.getSafe("openticket:ticket-created").build(source,{guild,channel,user,ticket})) - instance.addComponent(await buttons.getSafe("openticket:visit-ticket").build("ticket-created",{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:ticket-created").build(source,{guild,channel,user,ticket})) + instance.addComponent(await buttons.getSafe("opendiscord:visit-ticket").build("ticket-created",{guild,channel,user,ticket})) instance.setEphemeral(true) }) ) //TICKET CREATED DM - messages.add(new api.ODMessage("openticket:ticket-created-dm")) - messages.get("openticket:ticket-created-dm").workers.add( - new api.ODWorker("openticket:ticket-created-dm",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:ticket-created-dm")) + messages.get("opendiscord:ticket-created-dm").workers.add( + new api.ODWorker("opendiscord:ticket-created-dm",0,async (instance,params,source) => { const {guild,channel,user,ticket} = params //add text - const text = ticket.option.get("openticket:dm-message-text").value + const text = ticket.option.get("opendiscord:dm-message-text").value if (text !== "") instance.setContent(text) //add embed - if (ticket.option.get("openticket:dm-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("openticket:ticket-created-dm").build(source,{guild,channel,user,ticket})) + if (ticket.option.get("opendiscord:dm-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:ticket-created-dm").build(source,{guild,channel,user,ticket})) //add components - instance.addComponent(await buttons.getSafe("openticket:visit-ticket").build("ticket-created",{guild,channel,user,ticket})) + instance.addComponent(await buttons.getSafe("opendiscord:visit-ticket").build("ticket-created",{guild,channel,user,ticket})) }) ) //TICKET CREATED LOGS - messages.add(new api.ODMessage("openticket:ticket-created-logs")) - messages.get("openticket:ticket-created-logs").workers.add( - new api.ODWorker("openticket:ticket-created-logs",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:ticket-created-logs")) + messages.get("opendiscord:ticket-created-logs").workers.add( + new api.ODWorker("opendiscord:ticket-created-logs",0,async (instance,params,source) => { const {guild,channel,user,ticket} = params - instance.addEmbed(await embeds.getSafe("openticket:ticket-created-logs").build(source,{guild,channel,user,ticket})) - instance.addComponent(await buttons.getSafe("openticket:visit-ticket").build("ticket-created",{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:ticket-created-logs").build(source,{guild,channel,user,ticket})) + instance.addComponent(await buttons.getSafe("opendiscord:visit-ticket").build("ticket-created",{guild,channel,user,ticket})) }) ) //TICKET MESSAGE - messages.add(new api.ODMessage("openticket:ticket-message")) - messages.get("openticket:ticket-message").workers.add([ - new api.ODWorker("openticket:ticket-message-layout",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:ticket-message")) + messages.get("opendiscord:ticket-message").workers.add([ + new api.ODWorker("opendiscord:ticket-message-layout",0,async (instance,params,source) => { const {guild,channel,user,ticket} = params //add pings - const pingOptions = ticket.option.get("openticket:ticket-message-ping").value + const pingOptions = ticket.option.get("opendiscord:ticket-message-ping").value const pings: string[] = [] - const creator = ticket.get("openticket:opened-by").value + const creator = ticket.get("opendiscord:opened-by").value if (creator) pings.push(discord.userMention(creator)) if (pingOptions["@everyone"]) pings.push("@everyone") if (pingOptions["@here"]) pings.push("@here") @@ -680,46 +680,46 @@ const ticketMessages = () => { const pingText = (pings.length > 0) ? pings.join(" ")+"\n" : "" //add text - const text = ticket.option.get("openticket:ticket-message-text").value + const text = ticket.option.get("opendiscord:ticket-message-text").value if (text !== "") instance.setContent(pingText+text) else instance.setContent(pingText) //add embed - if (ticket.option.get("openticket:ticket-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("openticket:ticket-message").build(source,{guild,channel,user,ticket})) + if (ticket.option.get("opendiscord:ticket-message-embed").value.enabled) instance.addEmbed(await embeds.getSafe("opendiscord:ticket-message").build(source,{guild,channel,user,ticket})) }), - new api.ODWorker("openticket:ticket-message-components",1,async (instance,params,source) => { + new api.ODWorker("opendiscord:ticket-message-components",1,async (instance,params,source) => { const {guild,channel,user,ticket} = params //add components - if (generalConfig.data.system.enableTicketClaimButtons && !ticket.get("openticket:closed").value){ + if (generalConfig.data.system.enableTicketClaimButtons && !ticket.get("opendiscord:closed").value){ //enable ticket claiming - if (ticket.get("openticket:claimed").value){ - instance.addComponent(await buttons.getSafe("openticket:unclaim-ticket").build("ticket-message",{guild,channel,user,ticket})) + if (ticket.get("opendiscord:claimed").value){ + instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("ticket-message",{guild,channel,user,ticket})) }else{ - instance.addComponent(await buttons.getSafe("openticket:claim-ticket").build("ticket-message",{guild,channel,user,ticket})) + instance.addComponent(await buttons.getSafe("opendiscord:claim-ticket").build("ticket-message",{guild,channel,user,ticket})) } } - if (generalConfig.data.system.enableTicketPinButtons && !ticket.get("openticket:closed").value){ + if (generalConfig.data.system.enableTicketPinButtons && !ticket.get("opendiscord:closed").value){ //enable ticket pinning - if (ticket.get("openticket:pinned").value){ - instance.addComponent(await buttons.getSafe("openticket:unpin-ticket").build("ticket-message",{guild,channel,user,ticket})) + if (ticket.get("opendiscord:pinned").value){ + instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("ticket-message",{guild,channel,user,ticket})) }else{ - instance.addComponent(await buttons.getSafe("openticket:pin-ticket").build("ticket-message",{guild,channel,user,ticket})) + instance.addComponent(await buttons.getSafe("opendiscord:pin-ticket").build("ticket-message",{guild,channel,user,ticket})) } } if (generalConfig.data.system.enableTicketCloseButtons){ //enable ticket closing - if (ticket.get("openticket:closed").value){ - instance.addComponent(await buttons.getSafe("openticket:reopen-ticket").build("ticket-message",{guild,channel,user,ticket})) + if (ticket.get("opendiscord:closed").value){ + instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("ticket-message",{guild,channel,user,ticket})) }else{ - instance.addComponent(await buttons.getSafe("openticket:close-ticket").build("ticket-message",{guild,channel,user,ticket})) + instance.addComponent(await buttons.getSafe("opendiscord:close-ticket").build("ticket-message",{guild,channel,user,ticket})) } } //enable ticket deletion - if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("openticket:delete-ticket").build("ticket-message",{guild,channel,user,ticket})) + if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("ticket-message",{guild,channel,user,ticket})) }), - new api.ODWorker("openticket:ticket-message-disable-components",2,async (instance,params,source) => { + new api.ODWorker("opendiscord:ticket-message-disable-components",2,async (instance,params,source) => { const {ticket} = params - if (ticket.get("openticket:for-deletion").value){ + if (ticket.get("opendiscord:for-deletion").value){ //disable all buttons when ticket is being prepared for deletion instance.data.components.forEach((component) => { if ((component.component instanceof discord.ButtonBuilder) || (component.component instanceof discord.BaseSelectMenuBuilder)){ @@ -731,236 +731,236 @@ const ticketMessages = () => { ]) //TICKET CLOSED - messages.add(new api.ODMessage("openticket:close-message")) - messages.get("openticket:close-message").workers.add( - new api.ODWorker("openticket:close-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:close-message")) + messages.get("opendiscord:close-message").workers.add( + new api.ODWorker("opendiscord:close-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:close-message").build(source,{guild,channel,user,ticket,reason})) - if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("openticket:reopen-ticket").build("close-message",{guild,channel,user,ticket})) - if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("openticket:delete-ticket").build("close-message",{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:close-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("close-message",{guild,channel,user,ticket})) + if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("close-message",{guild,channel,user,ticket})) }) ) //TICKET REOPENED - messages.add(new api.ODMessage("openticket:reopen-message")) - messages.get("openticket:reopen-message").workers.add( - new api.ODWorker("openticket:reopen-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:reopen-message")) + messages.get("opendiscord:reopen-message").workers.add( + new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:reopen-message").build(source,{guild,channel,user,ticket,reason})) - if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("openticket:close-ticket").build("reopen-message",{guild,channel,user,ticket})) - if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("openticket:delete-ticket").build("reopen-message",{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:reopen-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:close-ticket").build("reopen-message",{guild,channel,user,ticket})) + if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("reopen-message",{guild,channel,user,ticket})) }) ) //TICKET DELETED - messages.add(new api.ODMessage("openticket:delete-message")) - messages.get("openticket:delete-message").workers.add( - new api.ODWorker("openticket:delete-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:delete-message")) + messages.get("opendiscord:delete-message").workers.add( + new api.ODWorker("opendiscord:delete-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:delete-message").build(source,{guild,channel,user,ticket,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:delete-message").build(source,{guild,channel,user,ticket,reason})) }) ) //TICKET CLAIMED - messages.add(new api.ODMessage("openticket:claim-message")) - messages.get("openticket:claim-message").workers.add( - new api.ODWorker("openticket:claim-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:claim-message")) + messages.get("opendiscord:claim-message").workers.add( + new api.ODWorker("opendiscord:claim-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:claim-message").build(source,{guild,channel,user,ticket,reason})) - if (generalConfig.data.system.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("openticket:unclaim-ticket").build("claim-message",{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:claim-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("claim-message",{guild,channel,user,ticket})) }) ) //TICKET UNCLAIMED - messages.add(new api.ODMessage("openticket:unclaim-message")) - messages.get("openticket:unclaim-message").workers.add( - new api.ODWorker("openticket:unclaim-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:unclaim-message")) + messages.get("opendiscord:unclaim-message").workers.add( + new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:unclaim-message").build(source,{guild,channel,user,ticket,reason})) - if (generalConfig.data.system.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("openticket:claim-ticket").build("unclaim-message",{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:unclaim-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:claim-ticket").build("unclaim-message",{guild,channel,user,ticket})) }) ) //TICKET PINNED - messages.add(new api.ODMessage("openticket:pin-message")) - messages.get("openticket:pin-message").workers.add( - new api.ODWorker("openticket:pin-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:pin-message")) + messages.get("opendiscord:pin-message").workers.add( + new api.ODWorker("opendiscord:pin-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:pin-message").build(source,{guild,channel,user,ticket,reason})) - if (generalConfig.data.system.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("openticket:unpin-ticket").build("pin-message",{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:pin-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("pin-message",{guild,channel,user,ticket})) }) ) //TICKET UNPINNED - messages.add(new api.ODMessage("openticket:unpin-message")) - messages.get("openticket:unpin-message").workers.add( - new api.ODWorker("openticket:unpin-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:unpin-message")) + messages.get("opendiscord:unpin-message").workers.add( + new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:unpin-message").build(source,{guild,channel,user,ticket,reason})) - if (generalConfig.data.system.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("openticket:pin-ticket").build("unpin-message",{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:unpin-message").build(source,{guild,channel,user,ticket,reason})) + if (generalConfig.data.system.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:pin-ticket").build("unpin-message",{guild,channel,user,ticket})) }) ) //TICKET RENAMED - messages.add(new api.ODMessage("openticket:rename-message")) - messages.get("openticket:rename-message").workers.add( - new api.ODWorker("openticket:rename-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:rename-message")) + messages.get("opendiscord:rename-message").workers.add( + new api.ODWorker("opendiscord:rename-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason,data} = params - instance.addEmbed(await embeds.getSafe("openticket:rename-message").build(source,{guild,channel,user,ticket,reason,data})) + instance.addEmbed(await embeds.getSafe("opendiscord:rename-message").build(source,{guild,channel,user,ticket,reason,data})) }) ) //TICKET MOVED - messages.add(new api.ODMessage("openticket:move-message")) - messages.get("openticket:move-message").workers.add( - new api.ODWorker("openticket:move-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:move-message")) + messages.get("opendiscord:move-message").workers.add( + new api.ODWorker("opendiscord:move-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason,data} = params - instance.addEmbed(await embeds.getSafe("openticket:move-message").build(source,{guild,channel,user,ticket,reason,data})) + instance.addEmbed(await embeds.getSafe("opendiscord:move-message").build(source,{guild,channel,user,ticket,reason,data})) }) ) //TICKET USER ADDED - messages.add(new api.ODMessage("openticket:add-message")) - messages.get("openticket:add-message").workers.add( - new api.ODWorker("openticket:add-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:add-message")) + messages.get("opendiscord:add-message").workers.add( + new api.ODWorker("opendiscord:add-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason,data} = params - instance.addEmbed(await embeds.getSafe("openticket:add-message").build(source,{guild,channel,user,ticket,reason,data})) + instance.addEmbed(await embeds.getSafe("opendiscord:add-message").build(source,{guild,channel,user,ticket,reason,data})) }) ) //TICKET USER REMOVED - messages.add(new api.ODMessage("openticket:remove-message")) - messages.get("openticket:remove-message").workers.add( - new api.ODWorker("openticket:remove-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:remove-message")) + messages.get("opendiscord:remove-message").workers.add( + new api.ODWorker("opendiscord:remove-message",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason,data} = params - instance.addEmbed(await embeds.getSafe("openticket:remove-message").build(source,{guild,channel,user,ticket,reason,data})) + instance.addEmbed(await embeds.getSafe("opendiscord:remove-message").build(source,{guild,channel,user,ticket,reason,data})) }) ) //TICKET ACTION DM - messages.add(new api.ODMessage("openticket:ticket-action-dm")) - messages.get("openticket:ticket-action-dm").workers.add( - new api.ODWorker("openticket:ticket-action-dm",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:ticket-action-dm")) + messages.get("opendiscord:ticket-action-dm").workers.add( + new api.ODWorker("opendiscord:ticket-action-dm",0,async (instance,params,source) => { const {guild,channel,user,mode,ticket,reason,additionalData} = params - instance.addEmbed(await embeds.getSafe("openticket:ticket-action-dm").build(source,{guild,channel,user,mode,ticket,reason,additionalData})) + instance.addEmbed(await embeds.getSafe("opendiscord:ticket-action-dm").build(source,{guild,channel,user,mode,ticket,reason,additionalData})) }) ) //TICKET ACTION LOGS - messages.add(new api.ODMessage("openticket:ticket-action-logs")) - messages.get("openticket:ticket-action-logs").workers.add( - new api.ODWorker("openticket:ticket-action-logs",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:ticket-action-logs")) + messages.get("opendiscord:ticket-action-logs").workers.add( + new api.ODWorker("opendiscord:ticket-action-logs",0,async (instance,params,source) => { const {guild,channel,user,mode,ticket,reason,additionalData} = params - instance.addEmbed(await embeds.getSafe("openticket:ticket-action-logs").build(source,{guild,channel,user,mode,ticket,reason,additionalData})) + instance.addEmbed(await embeds.getSafe("opendiscord:ticket-action-logs").build(source,{guild,channel,user,mode,ticket,reason,additionalData})) }) ) } const blacklistMessages = () => { //BLACKLIST VIEW - messages.add(new api.ODMessage("openticket:blacklist-view")) - messages.get("openticket:blacklist-view").workers.add( - new api.ODWorker("openticket:blacklist-view",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:blacklist-view")) + messages.get("opendiscord:blacklist-view").workers.add( + new api.ODWorker("opendiscord:blacklist-view",0,async (instance,params,source) => { const {guild,channel,user} = params - instance.addEmbed(await embeds.getSafe("openticket:blacklist-view").build(source,{guild,channel,user})) + instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-view").build(source,{guild,channel,user})) }) ) //BLACKLIST GET - messages.add(new api.ODMessage("openticket:blacklist-get")) - messages.get("openticket:blacklist-get").workers.add( - new api.ODWorker("openticket:blacklist-get",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:blacklist-get")) + messages.get("opendiscord:blacklist-get").workers.add( + new api.ODWorker("opendiscord:blacklist-get",0,async (instance,params,source) => { const {guild,channel,user,data} = params - instance.addEmbed(await embeds.getSafe("openticket:blacklist-get").build(source,{guild,channel,user,data})) + instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-get").build(source,{guild,channel,user,data})) }) ) //BLACKLIST ADD - messages.add(new api.ODMessage("openticket:blacklist-add")) - messages.get("openticket:blacklist-add").workers.add( - new api.ODWorker("openticket:blacklist-add",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:blacklist-add")) + messages.get("opendiscord:blacklist-add").workers.add( + new api.ODWorker("opendiscord:blacklist-add",0,async (instance,params,source) => { const {guild,channel,user,data,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:blacklist-add").build(source,{guild,channel,user,data,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-add").build(source,{guild,channel,user,data,reason})) }) ) //BLACKLIST REMOVE - messages.add(new api.ODMessage("openticket:blacklist-remove")) - messages.get("openticket:blacklist-remove").workers.add( - new api.ODWorker("openticket:blacklist-remove",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:blacklist-remove")) + messages.get("opendiscord:blacklist-remove").workers.add( + new api.ODWorker("opendiscord:blacklist-remove",0,async (instance,params,source) => { const {guild,channel,user,data,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:blacklist-remove").build(source,{guild,channel,user,data,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-remove").build(source,{guild,channel,user,data,reason})) }) ) //BLACKLIST DM - messages.add(new api.ODMessage("openticket:blacklist-dm")) - messages.get("openticket:blacklist-dm").workers.add( - new api.ODWorker("openticket:blacklist-dm",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:blacklist-dm")) + messages.get("opendiscord:blacklist-dm").workers.add( + new api.ODWorker("opendiscord:blacklist-dm",0,async (instance,params,source) => { const {guild,channel,user,mode,data,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:blacklist-dm").build(source,{guild,channel,user,mode,data,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-dm").build(source,{guild,channel,user,mode,data,reason})) }) ) //BLACKLIST LOGS - messages.add(new api.ODMessage("openticket:blacklist-logs")) - messages.get("openticket:blacklist-logs").workers.add( - new api.ODWorker("openticket:blacklist-logs",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:blacklist-logs")) + messages.get("opendiscord:blacklist-logs").workers.add( + new api.ODWorker("opendiscord:blacklist-logs",0,async (instance,params,source) => { const {guild,channel,user,mode,data,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:blacklist-logs").build(source,{guild,channel,user,mode,data,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:blacklist-logs").build(source,{guild,channel,user,mode,data,reason})) }) ) } const transcriptMessages = () => { //TRANSCRIPT TEXT READY - messages.add(new api.ODMessage("openticket:transcript-text-ready")) - messages.get("openticket:transcript-text-ready").workers.add( - new api.ODWorker("openticket:transcript-text-ready",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:transcript-text-ready")) + messages.get("opendiscord:transcript-text-ready").workers.add( + new api.ODWorker("opendiscord:transcript-text-ready",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler,result} = params - instance.addEmbed(await embeds.getSafe("openticket:transcript-text-ready").build(source,{guild,channel,user,ticket,compiler,result})) - instance.addFile(await files.getSafe("openticket:text-transcript").build(source,{guild,channel,user,ticket,compiler,result})) + instance.addEmbed(await embeds.getSafe("opendiscord:transcript-text-ready").build(source,{guild,channel,user,ticket,compiler,result})) + instance.addFile(await files.getSafe("opendiscord:text-transcript").build(source,{guild,channel,user,ticket,compiler,result})) }) ) //TRANSCRIPT HTML READY - messages.add(new api.ODMessage("openticket:transcript-html-ready")) - messages.get("openticket:transcript-html-ready").workers.add( - new api.ODWorker("openticket:transcript-html-ready",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:transcript-html-ready")) + messages.get("opendiscord:transcript-html-ready").workers.add( + new api.ODWorker("opendiscord:transcript-html-ready",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler,result} = params - instance.addEmbed(await embeds.getSafe("openticket:transcript-html-ready").build(source,{guild,channel,user,ticket,compiler,result})) - instance.addComponent(await buttons.getSafe("openticket:transcript-html-visit").build(source,{guild,channel,user,ticket,compiler,result})) + instance.addEmbed(await embeds.getSafe("opendiscord:transcript-html-ready").build(source,{guild,channel,user,ticket,compiler,result})) + instance.addComponent(await buttons.getSafe("opendiscord:transcript-html-visit").build(source,{guild,channel,user,ticket,compiler,result})) }) ) //TRANSCRIPT HTML PROGRESS - messages.add(new api.ODMessage("openticket:transcript-html-progress")) - messages.get("openticket:transcript-html-progress").workers.add( - new api.ODWorker("openticket:transcript-html-progress",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:transcript-html-progress")) + messages.get("opendiscord:transcript-html-progress").workers.add( + new api.ODWorker("opendiscord:transcript-html-progress",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler,remaining} = params - instance.addEmbed(await embeds.getSafe("openticket:transcript-html-progress").build(source,{guild,channel,user,ticket,compiler,remaining})) + instance.addEmbed(await embeds.getSafe("opendiscord:transcript-html-progress").build(source,{guild,channel,user,ticket,compiler,remaining})) }) ) //TRANSCRIPT ERROR - messages.add(new api.ODMessage("openticket:transcript-error")) - messages.get("openticket:transcript-error").workers.add( - new api.ODWorker("openticket:transcript-error",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:transcript-error")) + messages.get("opendiscord:transcript-error").workers.add( + new api.ODWorker("opendiscord:transcript-error",0,async (instance,params,source) => { const {guild,channel,user,ticket,compiler,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason})) - instance.addComponent(await buttons.getSafe("openticket:transcript-error-retry").build(source,{guild,channel,user,ticket,compiler,reason})) - instance.addComponent(await buttons.getSafe("openticket:transcript-error-continue").build(source,{guild,channel,user,ticket,compiler,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason})) + instance.addComponent(await buttons.getSafe("opendiscord:transcript-error-retry").build(source,{guild,channel,user,ticket,compiler,reason})) + instance.addComponent(await buttons.getSafe("opendiscord:transcript-error-continue").build(source,{guild,channel,user,ticket,compiler,reason})) }) ) } const roleMessages = () => { //REACTION ROLE - messages.add(new api.ODMessage("openticket:reaction-role")) - messages.get("openticket:reaction-role").workers.add( - new api.ODWorker("openticket:reaction-role",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:reaction-role")) + messages.get("opendiscord:reaction-role").workers.add( + new api.ODWorker("opendiscord:reaction-role",0,async (instance,params,source) => { const {guild,user,role,result} = params - instance.addEmbed(await embeds.getSafe("openticket:reaction-role").build(source,{guild,user,role,result})) + instance.addEmbed(await embeds.getSafe("opendiscord:reaction-role").build(source,{guild,user,role,result})) instance.setEphemeral(true) }) ) @@ -968,90 +968,90 @@ const roleMessages = () => { const clearMessages = () => { //CLEAR VERIFY MESSAGE - messages.add(new api.ODMessage("openticket:clear-verify-message")) - messages.get("openticket:clear-verify-message").workers.add( - new api.ODWorker("openticket:clear-verify-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:clear-verify-message")) + messages.get("opendiscord:clear-verify-message").workers.add( + new api.ODWorker("opendiscord:clear-verify-message",0,async (instance,params,source) => { const {guild,channel,user,filter,list} = params - instance.addEmbed(await embeds.getSafe("openticket:clear-verify-message").build(source,{guild,channel,user,filter,list})) - instance.addComponent(await buttons.getSafe("openticket:clear-continue").build(source,{guild,channel,user,filter,list})) + instance.addEmbed(await embeds.getSafe("opendiscord:clear-verify-message").build(source,{guild,channel,user,filter,list})) + instance.addComponent(await buttons.getSafe("opendiscord:clear-continue").build(source,{guild,channel,user,filter,list})) instance.setEphemeral(true) }) ) //CLEAR MESSAGE - messages.add(new api.ODMessage("openticket:clear-message")) - messages.get("openticket:clear-message").workers.add( - new api.ODWorker("openticket:clear-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:clear-message")) + messages.get("opendiscord:clear-message").workers.add( + new api.ODWorker("opendiscord:clear-message",0,async (instance,params,source) => { const {guild,channel,user,filter,list} = params - instance.addEmbed(await embeds.getSafe("openticket:clear-message").build(source,{guild,channel,user,filter,list})) + instance.addEmbed(await embeds.getSafe("opendiscord:clear-message").build(source,{guild,channel,user,filter,list})) instance.setEphemeral(true) }) ) //CLEAR LOGS - messages.add(new api.ODMessage("openticket:clear-logs")) - messages.get("openticket:clear-logs").workers.add( - new api.ODWorker("openticket:clear-logs",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:clear-logs")) + messages.get("opendiscord:clear-logs").workers.add( + new api.ODWorker("opendiscord:clear-logs",0,async (instance,params,source) => { const {guild,channel,user,filter,list} = params - instance.addEmbed(await embeds.getSafe("openticket:clear-logs").build(source,{guild,channel,user,filter,list})) + instance.addEmbed(await embeds.getSafe("opendiscord:clear-logs").build(source,{guild,channel,user,filter,list})) }) ) } const autoMessages = () => { //AUTOCLOSE MESSAGE - messages.add(new api.ODMessage("openticket:autoclose-message")) - messages.get("openticket:autoclose-message").workers.add( - new api.ODWorker("openticket:autoclose-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:autoclose-message")) + messages.get("opendiscord:autoclose-message").workers.add( + new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,source) => { const {guild,channel,user,ticket} = params - instance.addEmbed(await embeds.getSafe("openticket:autoclose-message").build(source,{guild,channel,user,ticket})) - if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("openticket:reopen-ticket").build("autoclose-message",{guild,channel,user,ticket})) - if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("openticket:delete-ticket").build("autoclose-message",{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-message").build(source,{guild,channel,user,ticket})) + if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("autoclose-message",{guild,channel,user,ticket})) + if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("autoclose-message",{guild,channel,user,ticket})) }) ) //AUTODELETE MESSAGE - messages.add(new api.ODMessage("openticket:autodelete-message")) - messages.get("openticket:autodelete-message").workers.add( - new api.ODWorker("openticket:autodelete-message",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:autodelete-message")) + messages.get("opendiscord:autodelete-message").workers.add( + new api.ODWorker("opendiscord:autodelete-message",0,async (instance,params,source) => { const {guild,channel,user,ticket} = params - instance.addEmbed(await embeds.getSafe("openticket:autodelete-message").build(source,{guild,channel,user,ticket})) + instance.addEmbed(await embeds.getSafe("opendiscord:autodelete-message").build(source,{guild,channel,user,ticket})) }) ) //AUTOCLOSE ENABLE - messages.add(new api.ODMessage("openticket:autoclose-enable")) - messages.get("openticket:autoclose-enable").workers.add( - new api.ODWorker("openticket:autoclose-enable",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:autoclose-enable")) + messages.get("opendiscord:autoclose-enable").workers.add( + new api.ODWorker("opendiscord:autoclose-enable",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason,time} = params - instance.addEmbed(await embeds.getSafe("openticket:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time})) + instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time})) }) ) //AUTODELETE ENABLE - messages.add(new api.ODMessage("openticket:autodelete-enable")) - messages.get("openticket:autodelete-enable").workers.add( - new api.ODWorker("openticket:autodelete-enable",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:autodelete-enable")) + messages.get("opendiscord:autodelete-enable").workers.add( + new api.ODWorker("opendiscord:autodelete-enable",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason,time} = params - instance.addEmbed(await embeds.getSafe("openticket:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time})) + instance.addEmbed(await embeds.getSafe("opendiscord:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time})) }) ) //AUTOCLOSE DISABLE - messages.add(new api.ODMessage("openticket:autoclose-disable")) - messages.get("openticket:autoclose-disable").workers.add( - new api.ODWorker("openticket:autoclose-disable",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:autoclose-disable")) + messages.get("opendiscord:autoclose-disable").workers.add( + new api.ODWorker("opendiscord:autoclose-disable",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:autoclose-disable").build(source,{guild,channel,user,ticket,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-disable").build(source,{guild,channel,user,ticket,reason})) }) ) //AUTODELETE DISABLE - messages.add(new api.ODMessage("openticket:autodelete-disable")) - messages.get("openticket:autodelete-disable").workers.add( - new api.ODWorker("openticket:autodelete-disable",0,async (instance,params,source) => { + messages.add(new api.ODMessage("opendiscord:autodelete-disable")) + messages.get("opendiscord:autodelete-disable").workers.add( + new api.ODWorker("opendiscord:autodelete-disable",0,async (instance,params,source) => { const {guild,channel,user,ticket,reason} = params - instance.addEmbed(await embeds.getSafe("openticket:autodelete-disable").build(source,{guild,channel,user,ticket,reason})) + instance.addEmbed(await embeds.getSafe("opendiscord:autodelete-disable").build(source,{guild,channel,user,ticket,reason})) }) ) } \ No newline at end of file diff --git a/src/builders/modals.ts b/src/builders/modals.ts index fef8aa0..df7d222 100644 --- a/src/builders/modals.ts +++ b/src/builders/modals.ts @@ -12,43 +12,43 @@ export const registerAllModals = async () => { } const ticketModals = () => { //TICKET QUESTIONS - modals.add(new api.ODModal("openticket:ticket-questions")) - modals.get("openticket:ticket-questions").workers.add( - new api.ODWorker("openticket:ticket-questions",0,async (instance,params,source) => { + modals.add(new api.ODModal("opendiscord:ticket-questions")) + modals.get("opendiscord:ticket-questions").workers.add( + new api.ODWorker("opendiscord:ticket-questions",0,async (instance,params,source) => { const {option} = params instance.setCustomId("od:ticket-questions_"+option.id.value+"_"+source) - instance.setTitle(option.exists("openticket:name") ? option.get("openticket:name").value : option.id.value) - const questionIds = option.get("openticket:questions").value + instance.setTitle(option.exists("opendiscord:name") ? option.get("opendiscord:name").value : option.id.value) + const questionIds = option.get("opendiscord:questions").value questionIds.forEach((id) => { const question = opendiscord.questions.get(id) if (!question) return if (question instanceof api.ODShortQuestion) instance.addQuestion({ customId:question.id.value, - label:question.get("openticket:name").value, + label:question.get("opendiscord:name").value, style:"short", - required:question.get("openticket:required").value, - placeholder:(question.get("openticket:placeholder").value) ? question.get("openticket:placeholder").value : undefined, - minLength:(question.get("openticket:length-enabled").value) ? question.get("openticket:length-min").value : undefined, - maxLength:(question.get("openticket:length-enabled").value) ? question.get("openticket:length-max").value : undefined + required:question.get("opendiscord:required").value, + placeholder:(question.get("opendiscord:placeholder").value) ? question.get("opendiscord:placeholder").value : undefined, + minLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-min").value : undefined, + maxLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-max").value : undefined }) else if (question instanceof api.ODParagraphQuestion) instance.addQuestion({ customId:question.id.value, - label:question.get("openticket:name").value, + label:question.get("opendiscord:name").value, style:"paragraph", - required:question.get("openticket:required").value, - placeholder:(question.get("openticket:placeholder").value) ? question.get("openticket:placeholder").value : undefined, - minLength:(question.get("openticket:length-enabled").value) ? question.get("openticket:length-min").value : undefined, - maxLength:(question.get("openticket:length-enabled").value) ? question.get("openticket:length-max").value : undefined + required:question.get("opendiscord:required").value, + placeholder:(question.get("opendiscord:placeholder").value) ? question.get("opendiscord:placeholder").value : undefined, + minLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-min").value : undefined, + maxLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-max").value : undefined }) }) }) ) //CLOSE TICKET REASON - modals.add(new api.ODModal("openticket:close-ticket-reason")) - modals.get("openticket:close-ticket-reason").workers.add( - new api.ODWorker("openticket:close-ticket-reason",0,async (instance,params,source) => { + modals.add(new api.ODModal("opendiscord:close-ticket-reason")) + modals.get("opendiscord:close-ticket-reason").workers.add( + new api.ODWorker("opendiscord:close-ticket-reason",0,async (instance,params,source) => { const {ticket} = params instance.setCustomId("od:close-ticket-reason_"+ticket.id.value+"_"+source) @@ -64,9 +64,9 @@ const ticketModals = () => { ) //REOPEN TICKET REASON - modals.add(new api.ODModal("openticket:reopen-ticket-reason")) - modals.get("openticket:reopen-ticket-reason").workers.add( - new api.ODWorker("openticket:reopen-ticket-reason",0,async (instance,params,source) => { + modals.add(new api.ODModal("opendiscord:reopen-ticket-reason")) + modals.get("opendiscord:reopen-ticket-reason").workers.add( + new api.ODWorker("opendiscord:reopen-ticket-reason",0,async (instance,params,source) => { const {ticket} = params instance.setCustomId("od:reopen-ticket-reason_"+ticket.id.value+"_"+source) @@ -82,9 +82,9 @@ const ticketModals = () => { ) //DELETE TICKET REASON - modals.add(new api.ODModal("openticket:delete-ticket-reason")) - modals.get("openticket:delete-ticket-reason").workers.add( - new api.ODWorker("openticket:delete-ticket-reason",0,async (instance,params,source) => { + modals.add(new api.ODModal("opendiscord:delete-ticket-reason")) + modals.get("opendiscord:delete-ticket-reason").workers.add( + new api.ODWorker("opendiscord:delete-ticket-reason",0,async (instance,params,source) => { const {ticket} = params instance.setCustomId("od:delete-ticket-reason_"+ticket.id.value+"_"+source) @@ -100,9 +100,9 @@ const ticketModals = () => { ) //CLAIM TICKET REASON - modals.add(new api.ODModal("openticket:claim-ticket-reason")) - modals.get("openticket:claim-ticket-reason").workers.add( - new api.ODWorker("openticket:claim-ticket-reason",0,async (instance,params,source) => { + modals.add(new api.ODModal("opendiscord:claim-ticket-reason")) + modals.get("opendiscord:claim-ticket-reason").workers.add( + new api.ODWorker("opendiscord:claim-ticket-reason",0,async (instance,params,source) => { const {ticket} = params instance.setCustomId("od:claim-ticket-reason_"+ticket.id.value+"_"+source) @@ -118,9 +118,9 @@ const ticketModals = () => { ) //UNCLAIM TICKET REASON - modals.add(new api.ODModal("openticket:unclaim-ticket-reason")) - modals.get("openticket:unclaim-ticket-reason").workers.add( - new api.ODWorker("openticket:unclaim-ticket-reason",0,async (instance,params,source) => { + modals.add(new api.ODModal("opendiscord:unclaim-ticket-reason")) + modals.get("opendiscord:unclaim-ticket-reason").workers.add( + new api.ODWorker("opendiscord:unclaim-ticket-reason",0,async (instance,params,source) => { const {ticket} = params instance.setCustomId("od:unclaim-ticket-reason_"+ticket.id.value+"_"+source) @@ -136,9 +136,9 @@ const ticketModals = () => { ) //PIN TICKET REASON - modals.add(new api.ODModal("openticket:pin-ticket-reason")) - modals.get("openticket:pin-ticket-reason").workers.add( - new api.ODWorker("openticket:pin-ticket-reason",0,async (instance,params,source) => { + modals.add(new api.ODModal("opendiscord:pin-ticket-reason")) + modals.get("opendiscord:pin-ticket-reason").workers.add( + new api.ODWorker("opendiscord:pin-ticket-reason",0,async (instance,params,source) => { const {ticket} = params instance.setCustomId("od:pin-ticket-reason_"+ticket.id.value+"_"+source) @@ -154,9 +154,9 @@ const ticketModals = () => { ) //UNPIN TICKET REASON - modals.add(new api.ODModal("openticket:unpin-ticket-reason")) - modals.get("openticket:unpin-ticket-reason").workers.add( - new api.ODWorker("openticket:unpin-ticket-reason",0,async (instance,params,source) => { + modals.add(new api.ODModal("opendiscord:unpin-ticket-reason")) + modals.get("opendiscord:unpin-ticket-reason").workers.add( + new api.ODWorker("opendiscord:unpin-ticket-reason",0,async (instance,params,source) => { const {ticket} = params instance.setCustomId("od:unpin-ticket-reason_"+ticket.id.value+"_"+source) diff --git a/src/commands/add.ts b/src/commands/add.ts index 73cb34b..ab68104 100644 --- a/src/commands/add.ts +++ b/src/commands/add.ts @@ -4,59 +4,59 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //ADD COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:add",generalConfig.data.prefix,"add")) - opendiscord.responders.commands.get("openticket:add").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:add",generalConfig.data.prefix,"add")) + opendiscord.responders.commands.get("opendiscord:add").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.add if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:add",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:add",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -66,16 +66,16 @@ export const registerCommandResponders = async () => { //return when user already added to ticket const participants = await opendiscord.tickets.getAllTicketParticipants(ticket) if (!participants || participants.find((p) => p.user.id == data.id)){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.add"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.add"),layout:"simple"})) return cancel() } //start adding user to ticket await instance.defer(false) - await opendiscord.actions.get("openticket:add-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data}) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:add-message").build(source,{guild,channel,user,ticket,reason,data})) + await opendiscord.actions.get("opendiscord:add-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:add-message").build(source,{guild,channel,user,ticket,reason,data})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'add' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, diff --git a/src/commands/autoclose.ts b/src/commands/autoclose.ts index 3a38a93..6200479 100644 --- a/src/commands/autoclose.ts +++ b/src/commands/autoclose.ts @@ -4,65 +4,65 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //AUTOCLOSE COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:autoclose",generalConfig.data.prefix,/^autoclose/)) - opendiscord.responders.commands.get("openticket:autoclose").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:autoclose",generalConfig.data.prefix,/^autoclose/)) + opendiscord.responders.commands.get("opendiscord:autoclose").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.autoclose if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:autoclose",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:autoclose",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return } //return when already closed - if (ticket.get("openticket:closed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) + if (ticket.get("opendiscord:closed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -71,23 +71,23 @@ export const registerCommandResponders = async () => { if (scope == "disable"){ const reason = instance.options.getString("reason",false) - ticket.get("openticket:autoclose-enabled").value = false - ticket.get("openticket:autoclose-hours").value = 0 - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:autoclose-disable").build(source,{guild,channel,user,ticket,reason})) + ticket.get("opendiscord:autoclose-enabled").value = false + ticket.get("opendiscord:autoclose-hours").value = 0 + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-disable").build(source,{guild,channel,user,ticket,reason})) }else if (scope == "enable"){ const time = instance.options.getNumber("time",true) const reason = instance.options.getString("reason",false) - ticket.get("openticket:autoclose-enabled").value = true - ticket.get("openticket:autoclose-hours").value = time - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time})) + ticket.get("opendiscord:autoclose-enabled").value = true + ticket.get("opendiscord:autoclose-hours").value = time + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time})) } //update ticket message const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on autoclose "+scope+"!","error",[ {key:"channel",value:"#"+channel.name}, @@ -99,7 +99,7 @@ export const registerCommandResponders = async () => { } } }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { const scope = instance.options.getSubCommand() const reason = instance.options.getString("reason",false) opendiscord.log(instance.user.displayName+" used the 'autoclose "+scope+"' command!","info",[ diff --git a/src/commands/autodelete.ts b/src/commands/autodelete.ts index 939a94a..acf4941 100644 --- a/src/commands/autodelete.ts +++ b/src/commands/autodelete.ts @@ -4,60 +4,60 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //AUTODELETE COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:autodelete",generalConfig.data.prefix,/^autodelete/)) - opendiscord.responders.commands.get("openticket:autodelete").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:autodelete",generalConfig.data.prefix,/^autodelete/)) + opendiscord.responders.commands.get("opendiscord:autodelete").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.autodelete if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:autodelete",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:autodelete",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -66,23 +66,23 @@ export const registerCommandResponders = async () => { if (scope == "disable"){ const reason = instance.options.getString("reason",false) - ticket.get("openticket:autodelete-enabled").value = false - ticket.get("openticket:autodelete-days").value = 0 - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:autodelete-disable").build(source,{guild,channel,user,ticket,reason})) + ticket.get("opendiscord:autodelete-enabled").value = false + ticket.get("opendiscord:autodelete-days").value = 0 + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autodelete-disable").build(source,{guild,channel,user,ticket,reason})) }else if (scope == "enable"){ const time = instance.options.getNumber("time",true) const reason = instance.options.getString("reason",false) - ticket.get("openticket:autodelete-enabled").value = true - ticket.get("openticket:autodelete-days").value = time - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time})) + ticket.get("opendiscord:autodelete-enabled").value = true + ticket.get("opendiscord:autodelete-days").value = time + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time})) } //update ticket message const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket) if (ticketMessage){ try{ - ticketMessage.edit((await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})).message) + ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message) }catch(e){ opendiscord.log("Unable to edit ticket message on autodelete "+scope+"!","error",[ {key:"channel",value:"#"+channel.name}, @@ -94,7 +94,7 @@ export const registerCommandResponders = async () => { } } }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { const scope = instance.options.getSubCommand() const reason = instance.options.getString("reason",false) opendiscord.log(instance.user.displayName+" used the 'autodelete "+scope+"' command!","info",[ diff --git a/src/commands/blacklist.ts b/src/commands/blacklist.ts index 5f50105..b33c3fe 100644 --- a/src/commands/blacklist.ts +++ b/src/commands/blacklist.ts @@ -4,61 +4,61 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //BLACKLIST COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:blacklist",generalConfig.data.prefix,/^blacklist/)) - opendiscord.responders.commands.get("openticket:blacklist").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:blacklist",generalConfig.data.prefix,/^blacklist/)) + opendiscord.responders.commands.get("opendiscord:blacklist").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.blacklist if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:blacklist",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:blacklist",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } const scope = instance.options.getSubCommand() if (!scope || (scope != "add" && scope != "get" && scope != "remove" && scope != "view")) return if (scope == "view"){ - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:blacklist-view").build(source,{guild,channel,user})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-view").build(source,{guild,channel,user})) }else if (scope == "get"){ const data = instance.options.getUser("user",true) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:blacklist-get").build(source,{guild,channel,user,data})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-get").build(source,{guild,channel,user,data})) }else if (scope == "add"){ const data = instance.options.getUser("user",true) @@ -74,10 +74,10 @@ export const registerCommandResponders = async () => { ]) //manage stats - await opendiscord.stats.get("openticket:global").setStat("openticket:users-blacklisted",1,"increase") - await opendiscord.stats.get("openticket:user").setStat("openticket:users-blacklisted",user.id,1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:users-blacklisted",1,"increase") + await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:users-blacklisted",user.id,1,"increase") - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:blacklist-add").build(source,{guild,channel,user,data,reason})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-add").build(source,{guild,channel,user,data,reason})) }else if (scope == "remove"){ const data = instance.options.getUser("user",true) @@ -92,10 +92,10 @@ export const registerCommandResponders = async () => { {key:"reason",value:reason ?? "/"} ]) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:blacklist-remove").build(source,{guild,channel,user,data,reason})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-remove").build(source,{guild,channel,user,data,reason})) } }), - new api.ODWorker("openticket:discord-logs",1,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild) return @@ -107,14 +107,14 @@ export const registerCommandResponders = async () => { //to logs if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.blacklisting.logs){ - const logChannel = opendiscord.posts.get("openticket:logs") - if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("openticket:blacklist-logs").build(source,{guild,channel,user,mode:scope,data,reason})) + const logChannel = opendiscord.posts.get("opendiscord:logs") + if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-logs").build(source,{guild,channel,user,mode:scope,data,reason})) } //to dm - if (generalConfig.data.system.messages.blacklisting.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("openticket:blacklist-dm").build(source,{guild,channel,user,mode:scope,data,reason})) + if (generalConfig.data.system.messages.blacklisting.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:blacklist-dm").build(source,{guild,channel,user,mode:scope,data,reason})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { const scope = instance.options.getSubCommand() opendiscord.log(instance.user.displayName+" used the 'blacklist "+scope+"' command!","info",[ {key:"user",value:instance.user.username}, diff --git a/src/commands/claim.ts b/src/commands/claim.ts index 1a4a236..50981e1 100644 --- a/src/commands/claim.ts +++ b/src/commands/claim.ts @@ -4,64 +4,64 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //CLAIM COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:claim",generalConfig.data.prefix,"claim")) - opendiscord.responders.commands.get("openticket:claim").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:claim",generalConfig.data.prefix,"claim")) + opendiscord.responders.commands.get("opendiscord:claim").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.claim if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:claim",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:claim",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already claimed - if (ticket.get("openticket:claimed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) + if (ticket.get("opendiscord:claimed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -70,10 +70,10 @@ export const registerCommandResponders = async () => { //start claiming ticket await instance.defer(false) - await opendiscord.actions.get("openticket:claim-ticket").run(source,{guild,channel,user:claimUser,ticket,reason,sendMessage:false}) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:claim-message").build(source,{guild,channel,user:claimUser,ticket,reason})) + await opendiscord.actions.get("opendiscord:claim-ticket").run(source,{guild,channel,user:claimUser,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(source,{guild,channel,user:claimUser,ticket,reason})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'claim' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, @@ -86,33 +86,33 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //CLAIM TICKET BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:claim-ticket",/^od:claim-ticket/)) - opendiscord.responders.buttons.get("openticket:claim-ticket").workers.add( - new api.ODWorker("openticket:claim-ticket",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:claim-ticket",/^od:claim-ticket/)) + opendiscord.responders.buttons.get("opendiscord:claim-ticket").workers.add( + new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "unclaim-message") return - if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:claim-ticket-ticket-message").activate(instance) - else await opendiscord.verifybars.get("openticket:claim-ticket-unclaim-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:claim-ticket-ticket-message").activate(instance) + else await opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").activate(instance) }) ) } export const registerModalResponders = async () => { //CLAIM WITH REASON MODAL RESPONDER - opendiscord.responders.modals.add(new api.ODModalResponder("openticket:claim-ticket-reason",/^od:claim-ticket-reason_/)) - opendiscord.responders.modals.get("openticket:claim-ticket-reason").workers.add([ - new api.ODWorker("openticket:claim-ticket-reason",0,async (instance,params,source,cancel) => { + opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:claim-ticket-reason",/^od:claim-ticket-reason_/)) + opendiscord.responders.modals.get("opendiscord:claim-ticket-reason").workers.add([ + new api.ODWorker("opendiscord:claim-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -122,15 +122,15 @@ export const registerModalResponders = async () => { //claim with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "unclaim-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:claim-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) diff --git a/src/commands/clear.ts b/src/commands/clear.ts index 4c415ed..8541903 100644 --- a/src/commands/clear.ts +++ b/src/commands/clear.ts @@ -4,50 +4,50 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //CLEAR COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:clear",generalConfig.data.prefix,"clear")) - opendiscord.responders.commands.get("openticket:clear").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:clear",generalConfig.data.prefix,"clear")) + opendiscord.responders.commands.get("opendiscord:clear").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.clear if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ //only allow global admins (ticket admins aren't allowed to clear tickets) if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild,{allowChannelUserScope:false,allowChannelRoleScope:false}))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:clear",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:clear",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } @@ -56,13 +56,13 @@ export const registerCommandResponders = async () => { const list: string[] = [] const ticketList = opendiscord.tickets.getAll().filter((ticket) => { if (filter == "all") return true - else if (filter == "open" && ticket.get("openticket:open").value) return true - else if (filter == "closed" && ticket.get("openticket:closed").value) return true - else if (filter == "claimed" && ticket.get("openticket:claimed").value) return true - else if (filter == "pinned" && ticket.get("openticket:pinned").value) return true - else if (filter == "unclaimed" && !ticket.get("openticket:claimed").value) return true - else if (filter == "unpinned" && !ticket.get("openticket:pinned").value) return true - else if (filter == "autoclosed" && ticket.get("openticket:closed").value) return true + else if (filter == "open" && ticket.get("opendiscord:open").value) return true + else if (filter == "closed" && ticket.get("opendiscord:closed").value) return true + else if (filter == "claimed" && ticket.get("opendiscord:claimed").value) return true + else if (filter == "pinned" && ticket.get("opendiscord:pinned").value) return true + else if (filter == "unclaimed" && !ticket.get("opendiscord:claimed").value) return true + else if (filter == "unpinned" && !ticket.get("opendiscord:pinned").value) return true + else if (filter == "autoclosed" && ticket.get("opendiscord:closed").value) return true else return false }) for (const ticket of ticketList){ @@ -72,9 +72,9 @@ export const registerCommandResponders = async () => { //reply with clear verify await instance.defer(true) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:clear-verify-message").build(source,{guild,channel,user,filter,list})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:clear-verify-message").build(source,{guild,channel,user,filter,list})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'clear' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, @@ -87,9 +87,9 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //CLEAR CONTINUE BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:clear-continue",/^od:clear-continue_/)) - opendiscord.responders.buttons.get("openticket:clear-continue").workers.add( - new api.ODWorker("openticket:clear-continue",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:clear-continue",/^od:clear-continue_/)) + opendiscord.responders.buttons.get("opendiscord:clear-continue").workers.add( + new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild || channel.isDMBased()) return const originalSource = instance.interaction.customId.split("_")[1] @@ -101,13 +101,13 @@ export const registerButtonResponders = async () => { const list: string[] = [] const ticketList = opendiscord.tickets.getAll().filter((ticket) => { if (filter == "all") return true - else if (filter == "open" && ticket.get("openticket:open").value) return true - else if (filter == "closed" && ticket.get("openticket:closed").value) return true - else if (filter == "claimed" && ticket.get("openticket:claimed").value) return true - else if (filter == "pinned" && ticket.get("openticket:pinned").value) return true - else if (filter == "unclaimed" && !ticket.get("openticket:claimed").value) return true - else if (filter == "unpinned" && !ticket.get("openticket:pinned").value) return true - else if (filter == "autoclosed" && ticket.get("openticket:closed").value) return true + else if (filter == "open" && ticket.get("opendiscord:open").value) return true + else if (filter == "closed" && ticket.get("opendiscord:closed").value) return true + else if (filter == "claimed" && ticket.get("opendiscord:claimed").value) return true + else if (filter == "pinned" && ticket.get("opendiscord:pinned").value) return true + else if (filter == "unclaimed" && !ticket.get("opendiscord:claimed").value) return true + else if (filter == "unpinned" && !ticket.get("opendiscord:pinned").value) return true + else if (filter == "autoclosed" && ticket.get("opendiscord:closed").value) return true else return false }) for (const ticket of ticketList){ @@ -115,8 +115,8 @@ export const registerButtonResponders = async () => { if (ticketChannel) list.push("#"+ticketChannel.name) } - await opendiscord.actions.get("openticket:clear-tickets").run(originalSource,{guild,channel,user,filter,list:ticketList}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:clear-message").build(originalSource,{guild,channel,user,filter,list})) + await opendiscord.actions.get("opendiscord:clear-tickets").run(originalSource,{guild,channel,user,filter,list:ticketList}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:clear-message").build(originalSource,{guild,channel,user,filter,list})) }) ) } \ No newline at end of file diff --git a/src/commands/close.ts b/src/commands/close.ts index 14a2cbd..75cc683 100644 --- a/src/commands/close.ts +++ b/src/commands/close.ts @@ -4,64 +4,64 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //CLOSE COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:close",generalConfig.data.prefix,"close")) - opendiscord.responders.commands.get("openticket:close").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:close",generalConfig.data.prefix,"close")) + opendiscord.responders.commands.get("opendiscord:close").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.close if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:close",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:close",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already closed - if (ticket.get("openticket:closed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) + if (ticket.get("opendiscord:closed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -69,10 +69,10 @@ export const registerCommandResponders = async () => { //start closing ticket await instance.defer(false) - await opendiscord.actions.get("openticket:close-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:close-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:close-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(source,{guild,channel,user,ticket,reason})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'close' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, @@ -85,33 +85,33 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //CLOSE TICKET BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:close-ticket",/^od:close-ticket_/)) - opendiscord.responders.buttons.get("openticket:close-ticket").workers.add( - new api.ODWorker("openticket:close-ticket",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:close-ticket",/^od:close-ticket_/)) + opendiscord.responders.buttons.get("opendiscord:close-ticket").workers.add( + new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "reopen-message") return - if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:close-ticket-ticket-message").activate(instance) - else await opendiscord.verifybars.get("openticket:close-ticket-reopen-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:close-ticket-ticket-message").activate(instance) + else await opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").activate(instance) }) ) } export const registerModalResponders = async () => { //CLOSE WITH REASON MODAL RESPONDER - opendiscord.responders.modals.add(new api.ODModalResponder("openticket:close-ticket-reason",/^od:close-ticket-reason_/)) - opendiscord.responders.modals.get("openticket:close-ticket-reason").workers.add([ - new api.ODWorker("openticket:close-ticket-reason",0,async (instance,params,source,cancel) => { + opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:close-ticket-reason",/^od:close-ticket-reason_/)) + opendiscord.responders.modals.get("opendiscord:close-ticket-reason").workers.add([ + new api.ODWorker("opendiscord:close-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -121,15 +121,15 @@ export const registerModalResponders = async () => { //close with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "reopen-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:close-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) diff --git a/src/commands/delete.ts b/src/commands/delete.ts index d98d0a7..3a36efe 100644 --- a/src/commands/delete.ts +++ b/src/commands/delete.ts @@ -4,59 +4,59 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //DELETE COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:delete",generalConfig.data.prefix,"delete")) - opendiscord.responders.commands.get("openticket:delete").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:delete",generalConfig.data.prefix,"delete")) + opendiscord.responders.commands.get("opendiscord:delete").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.delete if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:delete",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:delete",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -65,10 +65,10 @@ export const registerCommandResponders = async () => { //start deleting ticket await instance.defer(false) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:delete-message").build(source,{guild,channel,user,ticket,reason})) - await opendiscord.actions.get("openticket:delete-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:delete-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript}) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'delete' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, @@ -81,35 +81,35 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //DELETE TICKET BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:delete-ticket",/^od:delete-ticket/)) - opendiscord.responders.buttons.get("openticket:delete-ticket").workers.add( - new api.ODWorker("openticket:delete-ticket",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:delete-ticket",/^od:delete-ticket/)) + opendiscord.responders.buttons.get("opendiscord:delete-ticket").workers.add( + new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "autoclose-message") return - if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:delete-ticket-ticket-message").activate(instance) - else if (originalSource == "close-message") await opendiscord.verifybars.get("openticket:delete-ticket-close-message").activate(instance) - else if (originalSource == "reopen-message") await opendiscord.verifybars.get("openticket:delete-ticket-reopen-message").activate(instance) - else if (originalSource == "autoclose-message") await opendiscord.verifybars.get("openticket:delete-ticket-autoclose-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-ticket-message").activate(instance) + else if (originalSource == "close-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-close-message").activate(instance) + else if (originalSource == "reopen-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-reopen-message").activate(instance) + else if (originalSource == "autoclose-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-autoclose-message").activate(instance) }) ) } export const registerModalResponders = async () => { //REOPEN WITH REASON MODAL RESPONDER - opendiscord.responders.modals.add(new api.ODModalResponder("openticket:delete-ticket-reason",/^od:delete-ticket-reason_/)) - opendiscord.responders.modals.get("openticket:delete-ticket-reason").workers.add([ - new api.ODWorker("openticket:delete-ticket-reason",0,async (instance,params,source,cancel) => { + opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:delete-ticket-reason",/^od:delete-ticket-reason_/)) + opendiscord.responders.modals.get("opendiscord:delete-ticket-reason").workers.add([ + new api.ODWorker("opendiscord:delete-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -120,29 +120,29 @@ export const registerModalResponders = async () => { if (originalSource == "ticket-message"){ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) + opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) //update ticket (for ticket message) => no-await doesn't wait for the action to set this variable - ticket.get("openticket:for-deletion").value = true - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + ticket.get("opendiscord:for-deletion").value = true + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "close-message"){ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) + opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "reopen-message"){ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) + opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "autoclose-message"){ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:delete-message").build("other",{guild,channel,user,ticket,reason})) + opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted - opendiscord.actions.get("openticket:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) + opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) } }) ]) diff --git a/src/commands/help.ts b/src/commands/help.ts index a23ab8c..3679785 100644 --- a/src/commands/help.ts +++ b/src/commands/help.ts @@ -4,46 +4,46 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //HELP COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:help",generalConfig.data.prefix,"help")) - opendiscord.responders.commands.get("openticket:help").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:help",generalConfig.data.prefix,"help")) + opendiscord.responders.commands.get("opendiscord:help").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.help if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:help",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:help",0,async (instance,params,source,cancel) => { const preferSlashOverText = generalConfig.data.system.preferSlashOverText let mode: "slash"|"text" @@ -53,9 +53,9 @@ export const registerCommandResponders = async () => { }else if (!generalConfig.data.slashCommands) mode = "text" else mode = "slash" - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:help-menu").build(source,{mode,page:0})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:help-menu").build(source,{mode,page:0})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'help' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, @@ -68,44 +68,44 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //HELP MENU SWITCH BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-switch",/^od:help-menu-switch_(slash|text)/)) - opendiscord.responders.buttons.get("openticket:help-menu-switch").workers.add( - new api.ODWorker("openticket:update-help-menu",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:help-menu-switch",/^od:help-menu-switch_(slash|text)/)) + opendiscord.responders.buttons.get("opendiscord:help-menu-switch").workers.add( + new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,source,cancel) => { const mode = instance.interaction.customId.split("_")[1] as "slash"|"text" const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/) const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0 const newMode = (mode == "slash") ? "text" : "slash" - const msg = await opendiscord.builders.messages.getSafe("openticket:help-menu").build("button",{mode:newMode,page:currentPage}) + const msg = await opendiscord.builders.messages.getSafe("opendiscord:help-menu").build("button",{mode:newMode,page:currentPage}) await instance.update(msg) }) ) //HELP MENU PREVIOUS BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-previous",/^od:help-menu-previous/)) - opendiscord.responders.buttons.get("openticket:help-menu-previous").workers.add( - new api.ODWorker("openticket:update-help-menu",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:help-menu-previous",/^od:help-menu-previous/)) + opendiscord.responders.buttons.get("opendiscord:help-menu-previous").workers.add( + new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,source,cancel) => { const switchButton = instance.getMessageComponent("button",/^od:help-menu-switch_(slash|text)/) const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/) const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0 const currentMode = (switchButton && switchButton.customId) ? switchButton.customId.split("_")[1] as "text"|"slash" : "slash" - const msg = await opendiscord.builders.messages.getSafe("openticket:help-menu").build("button",{mode:currentMode,page:currentPage-1}) + const msg = await opendiscord.builders.messages.getSafe("opendiscord:help-menu").build("button",{mode:currentMode,page:currentPage-1}) await instance.update(msg) }) ) //HELP MENU NEXT BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:help-menu-next",/^od:help-menu-next/)) - opendiscord.responders.buttons.get("openticket:help-menu-next").workers.add( - new api.ODWorker("openticket:update-help-menu",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:help-menu-next",/^od:help-menu-next/)) + opendiscord.responders.buttons.get("opendiscord:help-menu-next").workers.add( + new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,source,cancel) => { const switchButton = instance.getMessageComponent("button",/^od:help-menu-switch_(slash|text)/) const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/) const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0 const currentMode = (switchButton && switchButton.customId) ? switchButton.customId.split("_")[1] as "text"|"slash" : "slash" - const msg = await opendiscord.builders.messages.getSafe("openticket:help-menu").build("button",{mode:currentMode,page:currentPage+1}) + const msg = await opendiscord.builders.messages.getSafe("opendiscord:help-menu").build("button",{mode:currentMode,page:currentPage+1}) await instance.update(msg) }) ) diff --git a/src/commands/move.ts b/src/commands/move.ts index 9fd61a0..3a63498 100644 --- a/src/commands/move.ts +++ b/src/commands/move.ts @@ -4,59 +4,59 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //MOVE COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:move",generalConfig.data.prefix,"move")) - opendiscord.responders.commands.get("openticket:move").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:move",generalConfig.data.prefix,"move")) + opendiscord.responders.commands.get("opendiscord:move").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.move if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:move",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:move",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -66,21 +66,21 @@ export const registerCommandResponders = async () => { const option = opendiscord.options.get(id) //return if unknown option if (!option || !(option instanceof api.ODTicketOption)){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.titles.unknownOption"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.titles.unknownOption"),layout:"simple"})) return cancel() } //return if option is the same if (ticket.option.id.value == option.id.value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:"This ticket is already the same as the chosen option!",layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:"This ticket is already the same as the chosen option!",layout:"simple"})) return cancel() } //start moving ticket await instance.defer(false) - await opendiscord.actions.get("openticket:move-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:option}) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:move-message").build(source,{guild,channel,user,ticket,reason,data:option})) + await opendiscord.actions.get("opendiscord:move-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:option}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:move-message").build(source,{guild,channel,user,ticket,reason,data:option})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'move' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, diff --git a/src/commands/panel.ts b/src/commands/panel.ts index 5589323..74b44e6 100644 --- a/src/commands/panel.ts +++ b/src/commands/panel.ts @@ -4,51 +4,51 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //PANEL COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:panel",generalConfig.data.prefix,/^panel/)) - opendiscord.responders.commands.get("openticket:panel").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:panel",generalConfig.data.prefix,/^panel/)) + opendiscord.responders.commands.get("opendiscord:panel").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.panel //command is disabled if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:panel",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:panel",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild || instance.channel.type == discord.ChannelType.GroupDM){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } @@ -57,20 +57,20 @@ export const registerCommandResponders = async () => { if (!panel){ //invalid panel - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-panel-unknown").build(source,{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-panel-unknown").build(source,{guild,channel,user})) return cancel() } - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:panel-ready").build(source,{guild,channel,user,panel})) - const panelMessage = await instance.channel.send((await opendiscord.builders.messages.getSafe("openticket:panel").build(source,{guild,channel,user,panel})).message) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:panel-ready").build(source,{guild,channel,user,panel})) + const panelMessage = await instance.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:panel").build(source,{guild,channel,user,panel})).message) //add panel to database on auto-update if (instance.options.getBoolean("auto-update",false)){ - const globalDatabase = opendiscord.databases.get("openticket:global") - await globalDatabase.set("openticket:panel-update",panelMessage.channel.id+"_"+panelMessage.id,panel.id.value) + const globalDatabase = opendiscord.databases.get("opendiscord:global") + await globalDatabase.set("opendiscord:panel-update",panelMessage.channel.id+"_"+panelMessage.id,panel.id.value) } }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'panel' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, diff --git a/src/commands/pin.ts b/src/commands/pin.ts index ed1460b..ac63a59 100644 --- a/src/commands/pin.ts +++ b/src/commands/pin.ts @@ -4,64 +4,64 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //PIN COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:pin",generalConfig.data.prefix,"pin")) - opendiscord.responders.commands.get("openticket:pin").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:pin",generalConfig.data.prefix,"pin")) + opendiscord.responders.commands.get("opendiscord:pin").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.pin if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:pin",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:pin",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when already pinned - if (ticket.get("openticket:pinned").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) + if (ticket.get("opendiscord:pinned").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -69,10 +69,10 @@ export const registerCommandResponders = async () => { //start pinning ticket await instance.defer(false) - await opendiscord.actions.get("openticket:pin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:pin-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:pin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(source,{guild,channel,user,ticket,reason})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'pin' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, @@ -85,33 +85,33 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //PIN TICKET BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:pin-ticket",/^od:pin-ticket/)) - opendiscord.responders.buttons.get("openticket:pin-ticket").workers.add( - new api.ODWorker("openticket:pin-ticket",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:pin-ticket",/^od:pin-ticket/)) + opendiscord.responders.buttons.get("opendiscord:pin-ticket").workers.add( + new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "unpin-message") return - if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:pin-ticket-ticket-message").activate(instance) - else await opendiscord.verifybars.get("openticket:pin-ticket-unpin-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:pin-ticket-ticket-message").activate(instance) + else await opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").activate(instance) }) ) } export const registerModalResponders = async () => { //PIN WITH REASON MODAL RESPONDER - opendiscord.responders.modals.add(new api.ODModalResponder("openticket:pin-ticket-reason",/^od:pin-ticket-reason_/)) - opendiscord.responders.modals.get("openticket:pin-ticket-reason").workers.add([ - new api.ODWorker("openticket:pin-ticket-reason",0,async (instance,params,source,cancel) => { + opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:pin-ticket-reason",/^od:pin-ticket-reason_/)) + opendiscord.responders.modals.get("opendiscord:pin-ticket-reason").workers.add([ + new api.ODWorker("opendiscord:pin-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -121,15 +121,15 @@ export const registerModalResponders = async () => { //pin with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "unpin-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:pin-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) diff --git a/src/commands/remove.ts b/src/commands/remove.ts index 89cccc1..6e71533 100644 --- a/src/commands/remove.ts +++ b/src/commands/remove.ts @@ -4,59 +4,59 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //REMOVE COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:remove",generalConfig.data.prefix,"remove")) - opendiscord.responders.commands.get("openticket:remove").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:remove",generalConfig.data.prefix,"remove")) + opendiscord.responders.commands.get("opendiscord:remove").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.remove if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:remove",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:remove",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -66,16 +66,16 @@ export const registerCommandResponders = async () => { //return when user is not a participant of the ticket (admins & creator can't be removed) const participants = await opendiscord.tickets.getAllTicketParticipants(ticket) if (!participants || !participants.find((p) => p.user.id == data.id && p.role == "participant")){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.remove"),layout:"simple"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.remove"),layout:"simple"})) return cancel() } //start removing user from ticket await instance.defer(false) - await opendiscord.actions.get("openticket:remove-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data}) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:remove-message").build(source,{guild,channel,user,ticket,reason,data})) + await opendiscord.actions.get("opendiscord:remove-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:remove-message").build(source,{guild,channel,user,ticket,reason,data})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'remove' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, diff --git a/src/commands/rename.ts b/src/commands/rename.ts index 39f560a..f84740d 100644 --- a/src/commands/rename.ts +++ b/src/commands/rename.ts @@ -4,59 +4,59 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //RENAME COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:rename",generalConfig.data.prefix,"rename")) - opendiscord.responders.commands.get("openticket:rename").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:rename",generalConfig.data.prefix,"rename")) + opendiscord.responders.commands.get("opendiscord:rename").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.rename if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:rename",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:rename",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -65,10 +65,10 @@ export const registerCommandResponders = async () => { //start renaming ticket await instance.defer(false) - await opendiscord.actions.get("openticket:rename-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:name}) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:rename-message").build(source,{guild,channel,user,ticket,reason,data:name})) + await opendiscord.actions.get("opendiscord:rename-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:name}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:rename-message").build(source,{guild,channel,user,ticket,reason,data:name})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'rename' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, diff --git a/src/commands/reopen.ts b/src/commands/reopen.ts index a7d31e5..6fe30c9 100644 --- a/src/commands/reopen.ts +++ b/src/commands/reopen.ts @@ -4,64 +4,64 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //REOPEN COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:reopen",generalConfig.data.prefix,"reopen")) - opendiscord.responders.commands.get("openticket:reopen").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:reopen",generalConfig.data.prefix,"reopen")) + opendiscord.responders.commands.get("opendiscord:reopen").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.reopen if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:reopen",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:reopen",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not closed - if (!ticket.get("openticket:closed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) + if (!ticket.get("opendiscord:closed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -69,10 +69,10 @@ export const registerCommandResponders = async () => { //start reopening ticket await instance.defer(false) - await opendiscord.actions.get("openticket:reopen-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:reopen-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(source,{guild,channel,user,ticket,reason})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'reopen' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, @@ -85,34 +85,34 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //REOPEN TICKET BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:reopen-ticket",/^od:reopen-ticket/)) - opendiscord.responders.buttons.get("openticket:reopen-ticket").workers.add( - new api.ODWorker("openticket:reopen-ticket",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:reopen-ticket",/^od:reopen-ticket/)) + opendiscord.responders.buttons.get("opendiscord:reopen-ticket").workers.add( + new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "close-message" && originalSource != "autoclose-message") return - if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:reopen-ticket-ticket-message").activate(instance) - else if (originalSource == "close-message") await opendiscord.verifybars.get("openticket:reopen-ticket-close-message").activate(instance) - else await opendiscord.verifybars.get("openticket:reopen-ticket-autoclose-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-ticket-message").activate(instance) + else if (originalSource == "close-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-close-message").activate(instance) + else await opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").activate(instance) }) ) } export const registerModalResponders = async () => { //REOPEN WITH REASON MODAL RESPONDER - opendiscord.responders.modals.add(new api.ODModalResponder("openticket:reopen-ticket-reason",/^od:reopen-ticket-reason_/)) - opendiscord.responders.modals.get("openticket:reopen-ticket-reason").workers.add([ - new api.ODWorker("openticket:reopen-ticket-reason",0,async (instance,params,source,cancel) => { + opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:reopen-ticket-reason",/^od:reopen-ticket-reason_/)) + opendiscord.responders.modals.get("opendiscord:reopen-ticket-reason").workers.add([ + new api.ODWorker("opendiscord:reopen-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -122,19 +122,19 @@ export const registerModalResponders = async () => { //reopen with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "close-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "autoclose-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:reopen-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) diff --git a/src/commands/role.ts b/src/commands/role.ts index b826b50..0081df6 100644 --- a/src/commands/role.ts +++ b/src/commands/role.ts @@ -4,17 +4,17 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerButtonResponders = async () => { //ROLE OPTION BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:role-option",/^od:role-option_/)) - opendiscord.responders.buttons.get("openticket:role-option").workers.add( - new api.ODWorker("openticket:role-option",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:role-option",/^od:role-option_/)) + opendiscord.responders.buttons.get("opendiscord:role-option").workers.add( + new api.ODWorker("opendiscord:role-option",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } @@ -23,19 +23,19 @@ export const registerButtonResponders = async () => { const option = opendiscord.options.get(optionId) if (!option || !(option instanceof api.ODRoleOption)){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) return cancel() } //reaction role await instance.defer("reply",true) - const res = await opendiscord.actions.get("openticket:reaction-role").run("panel-button",{guild,user,option,overwriteMode:null}) + const res = await opendiscord.actions.get("opendiscord:reaction-role").run("panel-button",{guild,user,option,overwriteMode:null}) if (!res.result || !res.role){ //error - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive role update data from worker!",layout:"advanced"})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive role update data from worker!",layout:"advanced"})) return cancel() } - if (generalConfig.data.system.replyOnReactionRole) await instance.reply(await opendiscord.builders.messages.getSafe("openticket:reaction-role").build("panel-button",{guild,user,role:res.role,result:res.result})) + if (generalConfig.data.system.replyOnReactionRole) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:reaction-role").build("panel-button",{guild,user,role:res.role,result:res.result})) }) ) } \ No newline at end of file diff --git a/src/commands/stats.ts b/src/commands/stats.ts index b01811f..c308c3f 100644 --- a/src/commands/stats.ts +++ b/src/commands/stats.ts @@ -4,19 +4,19 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //STATS COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:stats",generalConfig.data.prefix,/^stats/)) - opendiscord.responders.commands.get("openticket:stats").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:stats",generalConfig.data.prefix,/^stats/)) + opendiscord.responders.commands.get("opendiscord:stats").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.stats //command is disabled if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() } @@ -24,7 +24,7 @@ export const registerCommandResponders = async () => { if (instance.options.getSubCommand() == "reset"){ if (!opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]})) return cancel() }else return } @@ -34,60 +34,60 @@ export const registerCommandResponders = async () => { else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:stats",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:stats",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } const scope = instance.options.getSubCommand() if (!scope || (scope != "global" && scope != "ticket" && scope != "user" && scope != "reset")) return if (scope == "global"){ - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:stats-global").build(source,{guild,channel,user})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-global").build(source,{guild,channel,user})) }else if (scope == "ticket"){ const id = instance.options.getChannel("ticket",false)?.id ?? channel.id const ticket = opendiscord.tickets.get(id) - if (ticket) await instance.reply(await opendiscord.builders.messages.getSafe("openticket:stats-ticket").build(source,{guild,channel,user,scopeData:ticket})) - else await instance.reply(await opendiscord.builders.messages.getSafe("openticket:stats-ticket-unknown").build(source,{guild,channel,user,id})) + if (ticket) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-ticket").build(source,{guild,channel,user,scopeData:ticket})) + else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-ticket-unknown").build(source,{guild,channel,user,id})) }else if (scope == "user"){ const statsUser = instance.options.getUser("user",false) ?? user - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:stats-user").build(source,{guild,channel,user,scopeData:statsUser})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-user").build(source,{guild,channel,user,scopeData:statsUser})) }else if (scope == "reset"){ const reason = instance.options.getString("reason",false) opendiscord.stats.reset() - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:stats-reset").build(source,{guild,channel,user,reason})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-reset").build(source,{guild,channel,user,reason})) } }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { const scope = instance.options.getSubCommand() let data: string if (scope == "ticket"){ diff --git a/src/commands/ticket.ts b/src/commands/ticket.ts index 13e6432..1265d79 100644 --- a/src/commands/ticket.ts +++ b/src/commands/ticket.ts @@ -4,50 +4,50 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //TICKET COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:ticket",generalConfig.data.prefix,/^ticket/)) - opendiscord.responders.commands.get("openticket:ticket").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:ticket",generalConfig.data.prefix,/^ticket/)) + opendiscord.responders.commands.get("opendiscord:ticket").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.ticket if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:ticket",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } @@ -56,41 +56,41 @@ export const registerCommandResponders = async () => { const option = opendiscord.options.get(optionId) if (!option || !(option instanceof api.ODTicketOption)){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) return cancel() } //check ticket permissions - const res = await opendiscord.actions.get("openticket:create-ticket-permissions").run(source,{guild,user,option}) + const res = await opendiscord.actions.get("opendiscord:create-ticket-permissions").run(source,{guild,user,option}) if (!res.valid){ //error - if (res.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) - else if (res.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) - else if (res.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) - else if (res.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) - else if (res.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) - else if (res.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) - else instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) + if (res.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + else if (res.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) + else if (res.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) + else if (res.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) + else if (res.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) + else if (res.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) + else instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) return cancel() } //start ticket creation - if (option.exists("openticket:questions") && option.get("openticket:questions").value.length > 0){ + if (option.exists("opendiscord:questions") && option.get("opendiscord:questions").value.length > 0){ //send modal - instance.modal(await opendiscord.builders.modals.getSafe("openticket:ticket-questions").build(source,{guild,channel,user,option})) + instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build(source,{guild,channel,user,option})) }else{ //create ticket await instance.defer(true) - const res = await opendiscord.actions.get("openticket:create-ticket").run(source,{guild,user,answers:[],option}) + const res = await opendiscord.actions.get("opendiscord:create-ticket").run(source,{guild,user,answers:[],option}) if (!res.channel || !res.ticket){ //error - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) return cancel() } - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:ticket-created").build(source,{guild,channel:res.channel,user,ticket:res.ticket})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(source,{guild,channel:res.channel,user,ticket:res.ticket})) } }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'ticket' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, @@ -103,13 +103,13 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //TICKET OPTION BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:ticket-option",/^od:ticket-option_/)) - opendiscord.responders.buttons.get("openticket:ticket-option").workers.add( - new api.ODWorker("openticket:ticket-option",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:ticket-option",/^od:ticket-option_/)) + opendiscord.responders.buttons.get("opendiscord:ticket-option").workers.add( + new api.ODWorker("opendiscord:ticket-option",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } @@ -118,38 +118,38 @@ export const registerButtonResponders = async () => { const option = opendiscord.options.get(optionId) if (!option || !(option instanceof api.ODTicketOption)){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) return cancel() } //check ticket permissions - const res = await opendiscord.actions.get("openticket:create-ticket-permissions").run("panel-button",{guild,user,option}) + const res = await opendiscord.actions.get("opendiscord:create-ticket-permissions").run("panel-button",{guild,user,option}) if (!res.valid){ //error - if (res.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) - else if (res.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) - else if (res.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) - else if (res.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) - else if (res.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) - else if (res.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) - else instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) + if (res.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + else if (res.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) + else if (res.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) + else if (res.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) + else if (res.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) + else if (res.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) + else instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) return cancel() } //start ticket creation - if (option.exists("openticket:questions") && option.get("openticket:questions").value.length > 0){ + if (option.exists("opendiscord:questions") && option.get("opendiscord:questions").value.length > 0){ //send modal - instance.modal(await opendiscord.builders.modals.getSafe("openticket:ticket-questions").build("panel-button",{guild,channel,user,option})) + 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) - const res = await opendiscord.actions.get("openticket:create-ticket").run("panel-button",{guild,user,answers:[],option}) + const res = await opendiscord.actions.get("opendiscord:create-ticket").run("panel-button",{guild,user,answers:[],option}) if (!res.channel || !res.ticket){ //error - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) return cancel() } - if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("openticket:ticket-created").build("panel-button",{guild,channel:res.channel,user,ticket:res.ticket})) + if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build("panel-button",{guild,channel:res.channel,user,ticket:res.ticket})) } }) ) @@ -157,13 +157,13 @@ export const registerButtonResponders = async () => { export const registerDropdownResponders = async () => { //PANEL DROPDOWN TICKETS DROPDOWN RESPONDER - opendiscord.responders.dropdowns.add(new api.ODDropdownResponder("openticket:panel-dropdown-tickets",/^od:panel-dropdown_/)) - opendiscord.responders.dropdowns.get("openticket:panel-dropdown-tickets").workers.add( - new api.ODWorker("openticket:panel-dropdown-tickets",0,async (instance,params,source,cancel) => { + opendiscord.responders.dropdowns.add(new api.ODDropdownResponder("opendiscord:panel-dropdown-tickets",/^od:panel-dropdown_/)) + opendiscord.responders.dropdowns.get("opendiscord:panel-dropdown-tickets").workers.add( + new api.ODWorker("opendiscord:panel-dropdown-tickets",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user})) return cancel() } @@ -172,38 +172,38 @@ export const registerDropdownResponders = async () => { const option = opendiscord.options.get(optionId) if (!option || !(option instanceof api.ODTicketOption)){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) return cancel() } //check ticket permissions - const res = await opendiscord.actions.get("openticket:create-ticket-permissions").run("panel-dropdown",{guild,user,option}) + const res = await opendiscord.actions.get("opendiscord:create-ticket-permissions").run("panel-dropdown",{guild,user,option}) if (!res.valid){ //error - if (res.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) - else if (res.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) - else if (res.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) - else if (res.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) - else if (res.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) - else if (res.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) - else instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) + if (res.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-blacklisted").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + else if (res.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-cooldown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,until:res.cooldownUntil})) + else if (res.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"})) + else if (res.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"})) + else if (res.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"})) + else if (res.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"})) + else instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"})) return cancel() } //start ticket creation - if (option.exists("openticket:questions") && option.get("openticket:questions").value.length > 0){ + if (option.exists("opendiscord:questions") && option.get("opendiscord:questions").value.length > 0){ //send modal - instance.modal(await opendiscord.builders.modals.getSafe("openticket:ticket-questions").build("panel-dropdown",{guild,channel,user,option})) + 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) - const res = await opendiscord.actions.get("openticket:create-ticket").run("panel-dropdown",{guild,user,answers:[],option}) + const res = await opendiscord.actions.get("opendiscord:create-ticket").run("panel-dropdown",{guild,user,answers:[],option}) if (!res.channel || !res.ticket){ //error - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"})) return cancel() } - if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("openticket:ticket-created").build("panel-dropdown",{guild,channel:res.channel,user,ticket:res.ticket})) + if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build("panel-dropdown",{guild,channel:res.channel,user,ticket:res.ticket})) } }) ) @@ -211,14 +211,14 @@ export const registerDropdownResponders = async () => { export const registerModalResponders = async () => { //TICKET QUESTIONS RESPONDER - opendiscord.responders.modals.add(new api.ODModalResponder("openticket:ticket-questions",/^od:ticket-questions_/)) - opendiscord.responders.modals.get("openticket:ticket-questions").workers.add([ - new api.ODWorker("openticket:ticket-questions",0,async (instance,params,source,cancel) => { + opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:ticket-questions",/^od:ticket-questions_/)) + opendiscord.responders.modals.get("opendiscord:ticket-questions").workers.add([ + new api.ODWorker("opendiscord:ticket-questions",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) throw new api.ODSystemError("The 'Ticket Questions' modal requires a channel for responding!") if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } @@ -229,26 +229,26 @@ export const registerModalResponders = async () => { const option = opendiscord.options.get(optionId) if (!option || !(option instanceof api.ODTicketOption)){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-option-unknown").build(source,{guild:instance.guild,channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel,user:instance.user})) return cancel() } //get answers const answers: {id:string,name:string,type:"short"|"paragraph",value:string|null}[] = [] - option.get("openticket:questions").value.forEach((id) => { + option.get("opendiscord:questions").value.forEach((id) => { const question = opendiscord.questions.get(id) if (!question) return if (question instanceof api.ODShortQuestion){ answers.push({ id, - name:question.exists("openticket:name") ? question.get("openticket:name")?.value : id, + name:question.exists("opendiscord:name") ? question.get("opendiscord:name")?.value : id, type:"short", value:instance.values.getTextField(id,false) }) }else if (question instanceof api.ODParagraphQuestion){ answers.push({ id, - name:question.exists("openticket:name") ? question.get("openticket:name")?.value : id, + name:question.exists("opendiscord:name") ? question.get("opendiscord:name")?.value : id, type:"paragraph", value:instance.values.getTextField(id,false) }) @@ -257,13 +257,13 @@ export const registerModalResponders = async () => { //create ticket await instance.defer("reply",true) - const res = await opendiscord.actions.get("openticket:create-ticket").run(originalSource,{guild,user,answers,option}) + const res = await opendiscord.actions.get("opendiscord:create-ticket").run(originalSource,{guild,user,answers,option}) if (!res.channel || !res.ticket){ //error - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild,channel,user,error:"Unable to receive ticket or channel from callback! #2",layout:"advanced"})) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild,channel,user,error:"Unable to receive ticket or channel from callback! #2",layout:"advanced"})) return cancel() } - if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("openticket:ticket-created").build(originalSource,{guild,channel:res.channel,user,ticket:res.ticket})) + if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(originalSource,{guild,channel:res.channel,user,ticket:res.ticket})) }) ]) } \ No newline at end of file diff --git a/src/commands/unclaim.ts b/src/commands/unclaim.ts index 7a785e5..37692f3 100644 --- a/src/commands/unclaim.ts +++ b/src/commands/unclaim.ts @@ -4,64 +4,64 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //UNCLAIM COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:unclaim",generalConfig.data.prefix,"unclaim")) - opendiscord.responders.commands.get("openticket:unclaim").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:unclaim",generalConfig.data.prefix,"unclaim")) + opendiscord.responders.commands.get("opendiscord:unclaim").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unclaim if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:unclaim",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:unclaim",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not claimed - if (!ticket.get("openticket:claimed").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) + if (!ticket.get("opendiscord:claimed").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -69,10 +69,10 @@ export const registerCommandResponders = async () => { //start unclaiming ticket await instance.defer(false) - await opendiscord.actions.get("openticket:unclaim-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:unclaim-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:unclaim-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(source,{guild,channel,user,ticket,reason})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'unclaim' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, @@ -85,33 +85,33 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //UNCLAIM TICKET BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:unclaim-ticket",/^od:unclaim-ticket/)) - opendiscord.responders.buttons.get("openticket:unclaim-ticket").workers.add( - new api.ODWorker("openticket:unclaim-ticket",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:unclaim-ticket",/^od:unclaim-ticket/)) + opendiscord.responders.buttons.get("opendiscord:unclaim-ticket").workers.add( + new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "claim-message") return - if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:unclaim-ticket-ticket-message").activate(instance) - else await opendiscord.verifybars.get("openticket:unclaim-ticket-claim-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:unclaim-ticket-ticket-message").activate(instance) + else await opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").activate(instance) }) ) } export const registerModalResponders = async () => { //UNCLAIM WITH REASON MODAL RESPONDER - opendiscord.responders.modals.add(new api.ODModalResponder("openticket:unclaim-ticket-reason",/^od:unclaim-ticket-reason_/)) - opendiscord.responders.modals.get("openticket:unclaim-ticket-reason").workers.add([ - new api.ODWorker("openticket:unclaim-ticket-reason",0,async (instance,params,source,cancel) => { + opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:unclaim-ticket-reason",/^od:unclaim-ticket-reason_/)) + opendiscord.responders.modals.get("opendiscord:unclaim-ticket-reason").workers.add([ + new api.ODWorker("opendiscord:unclaim-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -121,15 +121,15 @@ export const registerModalResponders = async () => { //unclaim with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "claim-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:unclaim-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) ]) diff --git a/src/commands/unpin.ts b/src/commands/unpin.ts index 60fb092..9160d8a 100644 --- a/src/commands/unpin.ts +++ b/src/commands/unpin.ts @@ -4,64 +4,64 @@ import {opendiscord, api, utilities} from "../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const registerCommandResponders = async () => { //UNPIN COMMAND RESPONDER - opendiscord.responders.commands.add(new api.ODCommandResponder("openticket:unpin",generalConfig.data.prefix,"unpin")) - opendiscord.responders.commands.get("openticket:unpin").workers.add([ - new api.ODWorker("openticket:permissions",1,async (instance,params,source,cancel) => { + opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:unpin",generalConfig.data.prefix,"unpin")) + opendiscord.responders.commands.get("opendiscord:unpin").workers.add([ + new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => { const permissionMode = generalConfig.data.system.permissions.unpin if (permissionMode == "none"){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else if (permissionMode == "everyone") return else if (permissionMode == "admin"){ if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]})) return cancel() }else return }else{ if (!instance.guild || !instance.member){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"})) return cancel() } const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode) if (!role){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"})) return cancel() } if (!role.members.has(instance.member.id)){ //no permissions - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]})) return cancel() }else return } }), - new api.ODWorker("openticket:unpin",0,async (instance,params,source,cancel) => { + new api.ODWorker("opendiscord:unpin",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build("button",{channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) return cancel() } const ticket = opendiscord.tickets.get(channel.id) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return cancel() } //return when not pinned yet - if (!ticket.get("openticket:pinned").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) + if (!ticket.get("opendiscord:pinned").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"})) return cancel() } //return when busy - if (ticket.get("openticket:busy").value){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-busy").build("button",{guild,channel,user})) + if (ticket.get("opendiscord:busy").value){ + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user})) return cancel() } @@ -69,10 +69,10 @@ export const registerCommandResponders = async () => { //start unpinning ticket await instance.defer(false) - await opendiscord.actions.get("openticket:unpin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.reply(await opendiscord.builders.messages.getSafe("openticket:unpin-message").build(source,{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:unpin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(source,{guild,channel,user,ticket,reason})) }), - new api.ODWorker("openticket:logs",-1,(instance,params,source,cancel) => { + new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => { opendiscord.log(instance.user.displayName+" used the 'unpin' command!","info",[ {key:"user",value:instance.user.username}, {key:"userid",value:instance.user.id,hidden:true}, @@ -85,33 +85,33 @@ export const registerCommandResponders = async () => { export const registerButtonResponders = async () => { //UNPIN TICKET BUTTON RESPONDER - opendiscord.responders.buttons.add(new api.ODButtonResponder("openticket:unpin-ticket",/^od:unpin-ticket/)) - opendiscord.responders.buttons.get("openticket:unpin-ticket").workers.add( - new api.ODWorker("openticket:unpin-ticket",0,async (instance,params,source,cancel) => { + opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:unpin-ticket",/^od:unpin-ticket/)) + opendiscord.responders.buttons.get("opendiscord:unpin-ticket").workers.add( + new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source,cancel) => { const originalSource = instance.interaction.customId.split("_")[1] if (originalSource != "ticket-message" && originalSource != "pin-message") return - if (originalSource == "ticket-message") await opendiscord.verifybars.get("openticket:unpin-ticket-ticket-message").activate(instance) - else await opendiscord.verifybars.get("openticket:unpin-ticket-pin-message").activate(instance) + if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:unpin-ticket-ticket-message").activate(instance) + else await opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").activate(instance) }) ) } export const registerModalResponders = async () => { //UNPIN WITH REASON MODAL RESPONDER - opendiscord.responders.modals.add(new api.ODModalResponder("openticket:unpin-ticket-reason",/^od:unpin-ticket-reason_/)) - opendiscord.responders.modals.get("openticket:unpin-ticket-reason").workers.add([ - new api.ODWorker("openticket:unpin-ticket-reason",0,async (instance,params,source,cancel) => { + opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:unpin-ticket-reason",/^od:unpin-ticket-reason_/)) + opendiscord.responders.modals.get("opendiscord:unpin-ticket-reason").workers.add([ + new api.ODWorker("opendiscord:unpin-ticket-reason",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!channel) return if (!guild){ //error - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-not-in-guild").build(source,{channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user})) return cancel() } const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1]) if (!ticket || channel.isDMBased()){ - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-ticket-unknown").build("button",{guild,channel,user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user})) return } @@ -121,15 +121,15 @@ export const registerModalResponders = async () => { //unpin with reason if (originalSource == "ticket-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:ticket-message").build("other",{guild,channel,user,ticket})) + await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})) }else if (originalSource == "pin-message"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) - await instance.update(await opendiscord.builders.messages.getSafe("openticket:unpin-message").build("other",{guild,channel,user,ticket,reason})) + await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) + await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("other",{guild,channel,user,ticket,reason})) }else if (originalSource == "other"){ await instance.defer("update",false) - await opendiscord.actions.get("openticket:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) + await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } }) ]) diff --git a/src/core/api/defaults/action.ts b/src/core/api/defaults/action.ts index 2f9aaaa..808724e 100644 --- a/src/core/api/defaults/action.ts +++ b/src/core/api/defaults/action.ts @@ -16,101 +16,101 @@ import { ODRole, ODRoleUpdateMode, ODRoleUpdateResult } from "../openticket/role * It's used to generate typescript declarations for this class. */ export interface ODActionManagerIds_Default { - "openticket:create-ticket-permissions":{ + "opendiscord:create-ticket-permissions":{ source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other", params:{guild:discord.Guild,user:discord.User,option:ODTicketOption}, result:{valid:boolean,reason:"blacklist"|"cooldown"|"global-limit"|"global-user-limit"|"option-limit"|"option-user-limit"|null,cooldownUntil?:Date}, - workers:"openticket:check-blacklist"|"openticket:check-cooldown"|"openticket:check-global-limits"|"openticket:check-option-limits"|"openticket:valid" + workers:"opendiscord:check-blacklist"|"opendiscord:check-cooldown"|"opendiscord:check-global-limits"|"opendiscord:check-option-limits"|"opendiscord:valid" }, - "openticket:create-transcript":{ + "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, success:boolean, result:ODTranscriptCompilerCompileResult, errorReason:string|null, pendingMessage:ODMessageBuildSentResult|null, participants:{user:discord.User,role:"creator"|"participant"|"admin"}[]}, - workers:"openticket:select-compiler"|"openticket:init-transcript"|"openticket:compile-transcript"|"openticket:ready-transcript"|"openticket:logs" + workers:"opendiscord:select-compiler"|"opendiscord:init-transcript"|"opendiscord:compile-transcript"|"opendiscord:ready-transcript"|"opendiscord:logs" }, - "openticket:create-ticket":{ + "opendiscord:create-ticket":{ source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other", params:{guild:discord.Guild,user:discord.User,option:ODTicketOption,answers:{id:string,name:string,type:"short"|"paragraph",value:string|null}[]}, result:{channel:discord.GuildTextBasedChannel,ticket:ODTicket}, - workers:"openticket:create-ticket"|"openticket:send-ticket-message"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:create-ticket"|"opendiscord:send-ticket-message"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:close-ticket":{ + "opendiscord:close-ticket":{ source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, result:{}, - workers:"openticket:close-ticket"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:close-ticket"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:delete-ticket":{ + "opendiscord:delete-ticket":{ 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,reason:string|null,sendMessage:boolean,withoutTranscript:boolean}, result:{}, - workers:"openticket:delete-ticket"|"openticket:discord-logs"|"openticket:delete-channel"|"openticket:logs" + workers:"opendiscord:delete-ticket"|"opendiscord:discord-logs"|"opendiscord:delete-channel"|"opendiscord:logs" }, - "openticket:reopen-ticket":{ + "opendiscord:reopen-ticket":{ source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, result:{}, - workers:"openticket:reopen-ticket"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:reopen-ticket"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:claim-ticket":{ + "opendiscord:claim-ticket":{ source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, result:{}, - workers:"openticket:claim-ticket"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:claim-ticket"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:unclaim-ticket":{ + "opendiscord:unclaim-ticket":{ source:"slash"|"text"|"ticket-message"|"claim-message"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, result:{}, - workers:"openticket:unclaim-ticket"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:unclaim-ticket"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:pin-ticket":{ + "opendiscord:pin-ticket":{ source:"slash"|"text"|"ticket-message"|"unpin-message"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, result:{}, - workers:"openticket:pin-ticket"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:pin-ticket"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:unpin-ticket":{ + "opendiscord:unpin-ticket":{ source:"slash"|"text"|"ticket-message"|"pin-message"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean}, result:{}, - workers:"openticket:unpin-ticket"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:unpin-ticket"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:rename-ticket":{ + "opendiscord:rename-ticket":{ source:"slash"|"text"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:string}, result:{}, - workers:"openticket:rename-ticket"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:rename-ticket"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:move-ticket":{ + "opendiscord:move-ticket":{ source:"slash"|"text"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:ODTicketOption}, result:{}, - workers:"openticket:move-ticket"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:move-ticket"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:add-ticket-user":{ + "opendiscord:add-ticket-user":{ source:"slash"|"text"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:discord.User}, result:{}, - workers:"openticket:add-ticket-user"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:add-ticket-user"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:remove-ticket-user":{ + "opendiscord:remove-ticket-user":{ source:"slash"|"text"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,sendMessage:boolean,data:discord.User}, result:{}, - workers:"openticket:remove-ticket-user"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:remove-ticket-user"|"opendiscord:discord-logs"|"opendiscord:logs" }, - "openticket:reaction-role":{ + "opendiscord:reaction-role":{ source:"panel-button"|"other", params:{guild:discord.Guild,user:discord.User,option:ODRoleOption,overwriteMode:ODRoleUpdateMode|null}, result:{result:ODRoleUpdateResult[],role:ODRole}, - workers:"openticket:reaction-role"|"openticket:logs" + workers:"opendiscord:reaction-role"|"opendiscord:logs" }, - "openticket:clear-tickets":{ + "opendiscord:clear-tickets":{ source:"slash"|"text"|"other", params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:ODTicket[]}, result:{list:string[]}, - workers:"openticket:clear-tickets"|"openticket:discord-logs"|"openticket:logs" + workers:"opendiscord:clear-tickets"|"opendiscord:discord-logs"|"opendiscord:logs" } } diff --git a/src/core/api/defaults/base.ts b/src/core/api/defaults/base.ts index 532a9f9..2cfa279 100644 --- a/src/core/api/defaults/base.ts +++ b/src/core/api/defaults/base.ts @@ -8,11 +8,11 @@ import { ODVersion, ODVersionManager, ODValidId } from "../modules/base" * It's used to generate typescript declarations for this class. */ export interface ODVersionManagerIds_Default { - "openticket:version":ODVersion, - "openticket:last-version":ODVersion, - "openticket:api":ODVersion, - "openticket:transcripts":ODVersion, - "openticket:livestatus":ODVersion + "opendiscord:version":ODVersion, + "opendiscord:last-version":ODVersion, + "opendiscord:api":ODVersion, + "opendiscord:transcripts":ODVersion, + "opendiscord:livestatus":ODVersion } /**## ODFlagManager_Default `default_class` diff --git a/src/core/api/defaults/builder.ts b/src/core/api/defaults/builder.ts index 6e3bfe7..97cb2ec 100644 --- a/src/core/api/defaults/builder.ts +++ b/src/core/api/defaults/builder.ts @@ -34,35 +34,35 @@ export class ODBuilderManager_Default extends ODBuilderManager { * It's used to generate typescript declarations for this class. */ export interface ODButtonManagerIds_Default { - "openticket:verifybar-success":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"openticket:verifybar-success"}, - "openticket:verifybar-failure":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"openticket:verifybar-failure"}, + "opendiscord:verifybar-success":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"opendiscord:verifybar-success"}, + "opendiscord:verifybar-failure":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"opendiscord:verifybar-failure"}, - "openticket:error-ticket-deprecated-transcript":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{},workers:"openticket:error-ticket-deprecated-transcript"}, + "opendiscord:error-ticket-deprecated-transcript":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{},workers:"opendiscord:error-ticket-deprecated-transcript"}, - "openticket:help-menu-previous":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-previous"}, - "openticket:help-menu-next":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-next"}, - "openticket:help-menu-page":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-page"} - "openticket:help-menu-switch":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu-switch"}, + "opendiscord:help-menu-previous":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-previous"}, + "opendiscord:help-menu-next":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-next"}, + "opendiscord:help-menu-page":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-page"} + "opendiscord:help-menu-switch":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-switch"}, - "openticket:ticket-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODTicketOption},workers:"openticket:ticket-option"}, - "openticket:website-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODWebsiteOption},workers:"openticket:website-option"}, - "openticket:role-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODRoleOption},workers:"openticket:role-option"} + "opendiscord:ticket-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODTicketOption},workers:"opendiscord:ticket-option"}, + "opendiscord:website-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODWebsiteOption},workers:"opendiscord:website-option"}, + "opendiscord:role-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODRoleOption},workers:"opendiscord:role-option"} - "openticket:visit-ticket":{source:"ticket-created"|"dm"|"logs"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:visit-ticket"}, + "opendiscord:visit-ticket":{source:"ticket-created"|"dm"|"logs"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:visit-ticket"}, - "openticket:close-ticket":{source:"ticket-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:close-ticket"}, - "openticket:delete-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:delete-ticket"}, - "openticket:reopen-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:reopen-ticket"}, - "openticket:claim-ticket":{source:"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:claim-ticket"}, - "openticket:unclaim-ticket":{source:"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:unclaim-ticket"}, - "openticket:pin-ticket":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:pin-ticket"}, - "openticket:unpin-ticket":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:unpin-ticket"}, + "opendiscord:close-ticket":{source:"ticket-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:close-ticket"}, + "opendiscord:delete-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:delete-ticket"}, + "opendiscord:reopen-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:reopen-ticket"}, + "opendiscord:claim-ticket":{source:"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:claim-ticket"}, + "opendiscord:unclaim-ticket":{source:"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unclaim-ticket"}, + "opendiscord:pin-ticket":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:pin-ticket"}, + "opendiscord:unpin-ticket":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unpin-ticket"}, - "openticket: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:"openticket:transcript-html-visit"}, - "openticket:transcript-error-retry":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"openticket:transcript-error-retry"}, - "openticket:transcript-error-continue":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"openticket: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}>,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,reason:string|null},workers:"opendiscord:transcript-error-retry"}, + "opendiscord:transcript-error-continue":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"opendiscord:transcript-error-continue"}, - "openticket:clear-continue":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-continue"}, + "opendiscord:clear-continue":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-continue"}, } /**## ODButtonManager_Default `default_class` @@ -116,7 +116,7 @@ export class ODButton_Default,result:ODTranscriptCompilerCompileResult},workers:"openticket: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,result:ODTranscriptCompilerCompileResult},workers:"opendiscord:text-transcript"} } /**## ODFileManager_Default `default_class` @@ -224,73 +224,73 @@ export class ODFile_Default,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"openticket:transcript-text-ready"}, - "openticket: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:"openticket:transcript-html-ready"}, - "openticket: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:"openticket:transcript-html-progress"}, - "openticket:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"openticket: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}>,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,reason:string|null},workers:"opendiscord:transcript-error"}, - "openticket:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"openticket:reaction-role"}, - "openticket:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-verify-message"}, - "openticket:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-message"}, - "openticket:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-logs"}, + "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"}, + "opendiscord:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-message"}, + "opendiscord:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-logs"}, - "openticket:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autoclose-message"}, - "openticket:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autodelete-message"}, - "openticket:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autoclose-enable"}, - "openticket:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autodelete-enable"}, - "openticket:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autoclose-disable"}, - "openticket:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autodelete-disable"}, + "opendiscord:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autoclose-message"}, + "opendiscord:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autodelete-message"}, + "opendiscord:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autoclose-enable"}, + "opendiscord:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autodelete-enable"}, + "opendiscord:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autoclose-disable"}, + "opendiscord:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autodelete-disable"}, } /**## ODEmbedManager_Default `default_class` @@ -344,84 +344,84 @@ export class ODEmbed_Default},workers:"openticket:verifybar-ticket-message"}, - "openticket:verifybar-close-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-close-message"}, - "openticket:verifybar-reopen-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-reopen-message"}, - "openticket:verifybar-claim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-claim-message"}, - "openticket:verifybar-unclaim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-unclaim-message"}, - "openticket:verifybar-pin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-pin-message"}, - "openticket:verifybar-unpin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-unpin-message"} - "openticket:verifybar-autoclose-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"openticket:verifybar-autoclose-message"} + "opendiscord:verifybar-ticket-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-ticket-message"}, + "opendiscord:verifybar-close-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-close-message"}, + "opendiscord:verifybar-reopen-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-reopen-message"}, + "opendiscord:verifybar-claim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-claim-message"}, + "opendiscord:verifybar-unclaim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-unclaim-message"}, + "opendiscord:verifybar-pin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-pin-message"}, + "opendiscord:verifybar-unpin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-unpin-message"} + "opendiscord:verifybar-autoclose-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message},workers:"opendiscord:verifybar-autoclose-message"} - "openticket:error":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:string,layout:"simple"|"advanced"},workers:"openticket:error"}, - "openticket:error-option-missing":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorMissingOption},workers:"openticket:error-option-missing"}, - "openticket:error-option-invalid":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorInvalidOption},workers:"openticket:error-option-invalid"}, - "openticket:error-unknown-command":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorUnknownCommand},workers:"openticket:error-unknown-command"}, - "openticket:error-no-permissions":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,permissions:ODPermissionEmbedType[]},workers:"openticket:error-no-permissions"}, - "openticket:error-no-permissions-cooldown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,until?:Date},workers:"openticket:error-no-permissions-cooldown"}, - "openticket:error-no-permissions-blacklisted":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-no-permissions-blacklisted"}, - "openticket:error-no-permissions-limits":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,limit:"global"|"global-user"|"option"|"option-user"},workers:"openticket:error-no-permissions-limits"}, - "openticket:error-responder-timeout":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-responder-timeout"}, - "openticket:error-ticket-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-unknown"}, - "openticket:error-ticket-deprecated":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-deprecated"}, - "openticket:error-option-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-option-unknown"}, - "openticket:error-panel-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-panel-unknown"}, - "openticket:error-not-in-guild":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-not-in-guild"}, - "openticket:error-channel-rename":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"ticket-pin"|"ticket-unpin"|"ticket-rename"|"ticket-move"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"openticket:error-channel-rename"}, - "openticket:error-ticket-busy":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:error-ticket-busy"}, + "opendiscord:error":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:string,layout:"simple"|"advanced"},workers:"opendiscord:error"}, + "opendiscord:error-option-missing":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorMissingOption},workers:"opendiscord:error-option-missing"}, + "opendiscord:error-option-invalid":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorInvalidOption},workers:"opendiscord:error-option-invalid"}, + "opendiscord:error-unknown-command":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorUnknownCommand},workers:"opendiscord:error-unknown-command"}, + "opendiscord:error-no-permissions":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,permissions:ODPermissionEmbedType[]},workers:"opendiscord:error-no-permissions"}, + "opendiscord:error-no-permissions-cooldown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,until?:Date},workers:"opendiscord:error-no-permissions-cooldown"}, + "opendiscord:error-no-permissions-blacklisted":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-no-permissions-blacklisted"}, + "opendiscord:error-no-permissions-limits":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,limit:"global"|"global-user"|"option"|"option-user"},workers:"opendiscord:error-no-permissions-limits"}, + "opendiscord:error-responder-timeout":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-responder-timeout"}, + "opendiscord:error-ticket-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-unknown"}, + "opendiscord:error-ticket-deprecated":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-deprecated"}, + "opendiscord:error-option-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-option-unknown"}, + "opendiscord:error-panel-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-panel-unknown"}, + "opendiscord:error-not-in-guild":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-not-in-guild"}, + "opendiscord:error-channel-rename":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"ticket-pin"|"ticket-unpin"|"ticket-rename"|"ticket-move"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"opendiscord:error-channel-rename"}, + "opendiscord:error-ticket-busy":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-busy"}, - "openticket:help-menu":{source:"slash"|"text"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"openticket:help-menu"}, + "opendiscord:help-menu":{source:"slash"|"text"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu"}, - "openticket:stats-global":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:stats-global"}, - "openticket:stats-ticket":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:ODTicket},workers:"openticket:stats-ticket"}, - "openticket:stats-user":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:discord.User},workers:"openticket:stats-user"|"openticket:easter-egg"}, - "openticket:stats-reset":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,reason:string|null},workers:"openticket:stats-reset"}, - "openticket:stats-ticket-unknown":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,id:string},workers:"openticket:stats-ticket-unknown"}, + "opendiscord:stats-global":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:stats-global"}, + "opendiscord:stats-ticket":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:ODTicket},workers:"opendiscord:stats-ticket"}, + "opendiscord:stats-user":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:discord.User},workers:"opendiscord:stats-user"|"opendiscord:easter-egg"}, + "opendiscord:stats-reset":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,reason:string|null},workers:"opendiscord:stats-reset"}, + "opendiscord:stats-ticket-unknown":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,id:string},workers:"opendiscord:stats-ticket-unknown"}, - "openticket:panel":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"openticket:panel-layout"|"openticket:panel-components"}, - "openticket:panel-ready":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"openticket:panel-ready"}, + "opendiscord:panel":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"opendiscord:panel-layout"|"opendiscord:panel-components"}, + "opendiscord:panel-ready":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"opendiscord:panel-ready"}, - "openticket:ticket-created":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created"}, - "openticket:ticket-created-dm":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created-dm"}, - "openticket:ticket-created-logs":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-created-logs"}, - "openticket:ticket-message":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:ticket-message-layout"|"openticket:ticket-message-components"|"openticket:ticket-message-disable-components"}, - "openticket:close-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:close-message"}, - "openticket:reopen-message":{source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:reopen-message"}, - "openticket:delete-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:delete-message"}, - "openticket:claim-message":{source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:claim-message"}, - "openticket:unclaim-message":{source:"slash"|"text"|"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:unclaim-message"}, - "openticket:pin-message":{source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:pin-message"}, - "openticket:unpin-message":{source:"slash"|"text"|"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:unpin-message"}, - "openticket:rename-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:string},workers:"openticket:rename-message"}, - "openticket:move-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:ODTicketOption},workers:"openticket:move-message"}, - "openticket:add-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"openticket:add-message"}, - "openticket:remove-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"openticket:remove-message"}, - "openticket:ticket-action-dm":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"openticket:ticket-action-dm"}, - "openticket:ticket-action-logs":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"openticket:ticket-action-logs"}, + "opendiscord:ticket-created":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created"}, + "opendiscord:ticket-created-dm":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created-dm"}, + "opendiscord:ticket-created-logs":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created-logs"}, + "opendiscord:ticket-message":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-message-layout"|"opendiscord:ticket-message-components"|"opendiscord:ticket-message-disable-components"}, + "opendiscord:close-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:close-message"}, + "opendiscord:reopen-message":{source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:reopen-message"}, + "opendiscord:delete-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:delete-message"}, + "opendiscord:claim-message":{source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:claim-message"}, + "opendiscord:unclaim-message":{source:"slash"|"text"|"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:unclaim-message"}, + "opendiscord:pin-message":{source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:pin-message"}, + "opendiscord:unpin-message":{source:"slash"|"text"|"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:unpin-message"}, + "opendiscord:rename-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:string},workers:"opendiscord:rename-message"}, + "opendiscord:move-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:ODTicketOption},workers:"opendiscord:move-message"}, + "opendiscord:add-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"opendiscord:add-message"}, + "opendiscord:remove-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"opendiscord:remove-message"}, + "opendiscord:ticket-action-dm":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"opendiscord:ticket-action-dm"}, + "opendiscord:ticket-action-logs":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"opendiscord:ticket-action-logs"}, - "openticket:blacklist-view":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"openticket:blacklist-view"}, - "openticket:blacklist-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User},workers:"openticket:blacklist-get"}, - "openticket:blacklist-add":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"openticket:blacklist-add"}, - "openticket:blacklist-remove":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"openticket:blacklist-remove"}, - "openticket: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:"openticket:blacklist-dm"}, - "openticket: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:"openticket:blacklist-logs"}, + "opendiscord:blacklist-view":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:blacklist-view"}, + "opendiscord:blacklist-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User},workers:"opendiscord:blacklist-get"}, + "opendiscord:blacklist-add":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"opendiscord:blacklist-add"}, + "opendiscord:blacklist-remove":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"opendiscord:blacklist-remove"}, + "opendiscord:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-dm"}, + "opendiscord:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-logs"}, - "openticket: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:"openticket:transcript-text-ready"}, - "openticket: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:"openticket:transcript-html-ready"}, - "openticket: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:"openticket:transcript-html-progress"}, - "openticket:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler,reason:string|null},workers:"openticket: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}>,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,reason:string|null},workers:"opendiscord:transcript-error"}, - "openticket:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"openticket:reaction-role"}, - "openticket:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-verify-message"}, - "openticket:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-message"}, - "openticket:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"openticket:clear-logs"}, + "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"}, + "opendiscord:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-message"}, + "opendiscord:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-logs"}, - "openticket:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autoclose-message"}, - "openticket:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"openticket:autodelete-message"}, - "openticket:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autoclose-enable"}, - "openticket:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"openticket:autodelete-enable"}, - "openticket:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autoclose-disable"}, - "openticket:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"openticket:autodelete-disable"}, + "opendiscord:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autoclose-message"}, + "opendiscord:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autodelete-message"}, + "opendiscord:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autoclose-enable"}, + "opendiscord:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autodelete-enable"}, + "opendiscord:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autoclose-disable"}, + "opendiscord:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autodelete-disable"}, } /**## ODMessageManager_Default `default_class` @@ -475,14 +475,14 @@ export class ODMessage_Default m.type == "error").length > 0 const hasWarnings = data.messages.filter((m) => m.type == "warning").length > 0 @@ -213,19 +213,19 @@ export class ODCheckerRenderer_Default extends ODCheckerRenderer { * It's used to generate typescript declarations for this class. */ export type ODCheckerTranslationRegisterOtherIds_Default = ( - "openticket:header-openticket"| - "openticket:header-configchecker"| - "openticket:header-description"| - "openticket:type-error"| - "openticket:type-warning"| - "openticket:type-info"| - "openticket:data-path"| - "openticket:data-docs"| - "openticket:data-message"| - "openticket:compact-information"| - "openticket:footer-error"| - "openticket:footer-warning"| - "openticket:footer-support" + "opendiscord:header-openticket"| + "opendiscord:header-configchecker"| + "opendiscord:header-description"| + "opendiscord:type-error"| + "opendiscord:type-warning"| + "opendiscord:type-info"| + "opendiscord:data-path"| + "opendiscord:data-docs"| + "opendiscord:data-message"| + "opendiscord:compact-information"| + "opendiscord:footer-error"| + "opendiscord:footer-warning"| + "opendiscord:footer-support" ) /**## ODCheckerTranslationRegisterMessageIds_Default `interface` @@ -233,73 +233,73 @@ export type ODCheckerTranslationRegisterOtherIds_Default = ( * It's used to generate typescript declarations for this class. */ export type ODCheckerTranslationRegisterMessageIds_Default = ( - "openticket:invalid-type"| - "openticket:property-missing"| - "openticket:property-optional"| - "openticket:object-disabled"| - "openticket:null-invalid"| - "openticket:switch-invalid-type"| - "openticket:object-switch-invalid-type"| + "opendiscord:invalid-type"| + "opendiscord:property-missing"| + "opendiscord:property-optional"| + "opendiscord:object-disabled"| + "opendiscord:null-invalid"| + "opendiscord:switch-invalid-type"| + "opendiscord:object-switch-invalid-type"| - "openticket:string-too-short"| - "openticket:string-too-long"| - "openticket:string-length-invalid"| - "openticket:string-starts-with"| - "openticket:string-ends-with"| - "openticket:string-contains"| - "openticket:string-choices"| - "openticket:string-regex"| + "opendiscord:string-too-short"| + "opendiscord:string-too-long"| + "opendiscord:string-length-invalid"| + "opendiscord:string-starts-with"| + "opendiscord:string-ends-with"| + "opendiscord:string-contains"| + "opendiscord:string-choices"| + "opendiscord:string-regex"| - "openticket:number-too-short"| - "openticket:number-too-long"| - "openticket:number-length-invalid"| - "openticket:number-too-small"| - "openticket:number-too-large"| - "openticket:number-not-equal"| - "openticket:number-step"| - "openticket:number-step-offset"| - "openticket:number-starts-with"| - "openticket:number-ends-with"| - "openticket:number-contains"| - "openticket:number-choices"| - "openticket:number-float"| - "openticket:number-negative"| - "openticket:number-positive"| - "openticket:number-zero"| + "opendiscord:number-too-short"| + "opendiscord:number-too-long"| + "opendiscord:number-length-invalid"| + "opendiscord:number-too-small"| + "opendiscord:number-too-large"| + "opendiscord:number-not-equal"| + "opendiscord:number-step"| + "opendiscord:number-step-offset"| + "opendiscord:number-starts-with"| + "opendiscord:number-ends-with"| + "opendiscord:number-contains"| + "opendiscord:number-choices"| + "opendiscord:number-float"| + "opendiscord:number-negative"| + "opendiscord:number-positive"| + "opendiscord:number-zero"| - "openticket:boolean-true"| - "openticket:boolean-false"| + "opendiscord:boolean-true"| + "opendiscord:boolean-false"| - "openticket:array-empty-disabled"| - "openticket:array-empty-required"| - "openticket:array-too-short"| - "openticket:array-too-long"| - "openticket:array-length-invalid"| - "openticket:array-invalid-types"| - "openticket:array-double"| + "opendiscord:array-empty-disabled"| + "opendiscord:array-empty-required"| + "opendiscord:array-too-short"| + "opendiscord:array-too-long"| + "opendiscord:array-length-invalid"| + "opendiscord:array-invalid-types"| + "opendiscord:array-double"| - "openticket:discord-invalid-id"| - "openticket:discord-invalid-id-options"| - "openticket:discord-invalid-token"| - "openticket:color-invalid"| - "openticket:emoji-too-short"| - "openticket:emoji-too-long"| - "openticket:emoji-custom"| - "openticket:emoji-invalid"| - "openticket:url-invalid"| - "openticket:url-invalid-http"| - "openticket:url-invalid-protocol"| - "openticket:url-invalid-hostname"| - "openticket:url-invalid-extension"| - "openticket:url-invalid-path"| - "openticket:id-not-unique"| - "openticket:id-non-existent"| + "opendiscord:discord-invalid-id"| + "opendiscord:discord-invalid-id-options"| + "opendiscord:discord-invalid-token"| + "opendiscord:color-invalid"| + "opendiscord:emoji-too-short"| + "opendiscord:emoji-too-long"| + "opendiscord:emoji-custom"| + "opendiscord:emoji-invalid"| + "opendiscord:url-invalid"| + "opendiscord:url-invalid-http"| + "opendiscord:url-invalid-protocol"| + "opendiscord:url-invalid-hostname"| + "opendiscord:url-invalid-extension"| + "opendiscord:url-invalid-path"| + "opendiscord:id-not-unique"| + "opendiscord:id-non-existent"| - "openticket:invalid-language"| - "openticket:invalid-button"| - "openticket:unused-option"| - "openticket:unused-question"| - "openticket:dropdown-option" + "opendiscord:invalid-language"| + "opendiscord:invalid-button"| + "opendiscord:unused-option"| + "opendiscord:unused-question"| + "opendiscord:dropdown-option" ) /**## ODCheckerTranslationRegister_Default `default_class` @@ -346,9 +346,9 @@ export class ODCheckerTranslationRegister_Default extends ODCheckerTranslationRe * It's used to generate typescript declarations for this class. */ export interface ODCheckerFunctionManagerIds_Default { - "openticket:unused-options":ODCheckerFunction, - "openticket:unused-questions":ODCheckerFunction, - "openticket:dropdown-options":ODCheckerFunction + "opendiscord:unused-options":ODCheckerFunction, + "opendiscord:unused-questions":ODCheckerFunction, + "opendiscord:dropdown-options":ODCheckerFunction } /**## ODCheckerFunctionManager_Default `default_class` diff --git a/src/core/api/defaults/client.ts b/src/core/api/defaults/client.ts index 90d8a22..d451afa 100644 --- a/src/core/api/defaults/client.ts +++ b/src/core/api/defaults/client.ts @@ -20,25 +20,25 @@ export class ODClientManager_Default extends ODClientManager { * It's used to generate typescript declarations for this class. */ export interface ODSlashCommandManagerIds_Default { - "openticket:help":ODSlashCommand, - "openticket:panel":ODSlashCommand, - "openticket:ticket":ODSlashCommand, - "openticket:close":ODSlashCommand, - "openticket:delete":ODSlashCommand, - "openticket:reopen":ODSlashCommand, - "openticket:claim":ODSlashCommand, - "openticket:unclaim":ODSlashCommand, - "openticket:pin":ODSlashCommand, - "openticket:unpin":ODSlashCommand, - "openticket:move":ODSlashCommand, - "openticket:rename":ODSlashCommand, - "openticket:add":ODSlashCommand, - "openticket:remove":ODSlashCommand, - "openticket:blacklist":ODSlashCommand, - "openticket:stats":ODSlashCommand, - "openticket:clear":ODSlashCommand, - "openticket:autoclose":ODSlashCommand, - "openticket:autodelete":ODSlashCommand, + "opendiscord:help":ODSlashCommand, + "opendiscord:panel":ODSlashCommand, + "opendiscord:ticket":ODSlashCommand, + "opendiscord:close":ODSlashCommand, + "opendiscord:delete":ODSlashCommand, + "opendiscord:reopen":ODSlashCommand, + "opendiscord:claim":ODSlashCommand, + "opendiscord:unclaim":ODSlashCommand, + "opendiscord:pin":ODSlashCommand, + "opendiscord:unpin":ODSlashCommand, + "opendiscord:move":ODSlashCommand, + "opendiscord:rename":ODSlashCommand, + "opendiscord:add":ODSlashCommand, + "opendiscord:remove":ODSlashCommand, + "opendiscord:blacklist":ODSlashCommand, + "opendiscord:stats":ODSlashCommand, + "opendiscord:clear":ODSlashCommand, + "opendiscord:autoclose":ODSlashCommand, + "opendiscord:autodelete":ODSlashCommand, } /**## ODSlashCommandManager_Default `default_class` @@ -82,33 +82,33 @@ export class ODSlashCommandManager_Default extends ODSlashCommandManager { * It's used to generate typescript declarations for this class. */ export interface ODTextCommandManagerIds_Default { - "openticket:dump":ODTextCommand, - "openticket:help":ODTextCommand, - "openticket:panel":ODTextCommand, - "openticket:close":ODTextCommand, - "openticket:delete":ODTextCommand, - "openticket:reopen":ODTextCommand, - "openticket:claim":ODTextCommand, - "openticket:unclaim":ODTextCommand, - "openticket:pin":ODTextCommand, - "openticket:unpin":ODTextCommand, - "openticket:move":ODTextCommand, - "openticket:rename":ODTextCommand, - "openticket:add":ODTextCommand, - "openticket:remove":ODTextCommand, - "openticket:blacklist-view":ODTextCommand, - "openticket:blacklist-add":ODTextCommand, - "openticket:blacklist-remove":ODTextCommand, - "openticket:blacklist-get":ODTextCommand, - "openticket:stats-global":ODTextCommand, - "openticket:stats-reset":ODTextCommand, - "openticket:stats-ticket":ODTextCommand, - "openticket:stats-user":ODTextCommand, - "openticket:clear":ODTextCommand, - "openticket:autoclose-disable":ODTextCommand, - "openticket:autoclose-enable":ODTextCommand, - "openticket:autodelete-disable":ODTextCommand, - "openticket:autodelete-enable":ODTextCommand + "opendiscord:dump":ODTextCommand, + "opendiscord:help":ODTextCommand, + "opendiscord:panel":ODTextCommand, + "opendiscord:close":ODTextCommand, + "opendiscord:delete":ODTextCommand, + "opendiscord:reopen":ODTextCommand, + "opendiscord:claim":ODTextCommand, + "opendiscord:unclaim":ODTextCommand, + "opendiscord:pin":ODTextCommand, + "opendiscord:unpin":ODTextCommand, + "opendiscord:move":ODTextCommand, + "opendiscord:rename":ODTextCommand, + "opendiscord:add":ODTextCommand, + "opendiscord:remove":ODTextCommand, + "opendiscord:blacklist-view":ODTextCommand, + "opendiscord:blacklist-add":ODTextCommand, + "opendiscord:blacklist-remove":ODTextCommand, + "opendiscord:blacklist-get":ODTextCommand, + "opendiscord:stats-global":ODTextCommand, + "opendiscord:stats-reset":ODTextCommand, + "opendiscord:stats-ticket":ODTextCommand, + "opendiscord:stats-user":ODTextCommand, + "opendiscord:clear":ODTextCommand, + "opendiscord:autoclose-disable":ODTextCommand, + "opendiscord:autoclose-enable":ODTextCommand, + "opendiscord:autodelete-disable":ODTextCommand, + "opendiscord:autodelete-enable":ODTextCommand } /**## ODTextCommandManager_Default `default_class` diff --git a/src/core/api/defaults/code.ts b/src/core/api/defaults/code.ts index 508ff26..7ef19a8 100644 --- a/src/core/api/defaults/code.ts +++ b/src/core/api/defaults/code.ts @@ -9,22 +9,22 @@ import { ODCode, ODCodeManager } from "../modules/code" * It's used to generate typescript declarations for this class. */ export interface ODCodeManagerIds_Default { - "openticket:command-error-handling":ODCode, - "openticket:start-listening-interactions":ODCode, - "openticket:panel-database-cleaner":ODCode, - "openticket:suffix-database-cleaner":ODCode, - "openticket:option-database-cleaner":ODCode, - "openticket:user-database-cleaner":ODCode, - "openticket:ticket-database-cleaner":ODCode, - "openticket:panel-auto-update":ODCode, - "openticket:ticket-saver":ODCode, - "openticket:blacklist-saver":ODCode, - "openticket:auto-role-on-join":ODCode, - "openticket:autoclose-timeout":ODCode, - "openticket:autoclose-leave":ODCode, - "openticket:autodelete-timeout":ODCode, - "openticket:autodelete-leave":ODCode, - "openticket:ticket-anti-busy":ODCode, + "opendiscord:command-error-handling":ODCode, + "opendiscord:start-listening-interactions":ODCode, + "opendiscord:panel-database-cleaner":ODCode, + "opendiscord:suffix-database-cleaner":ODCode, + "opendiscord:option-database-cleaner":ODCode, + "opendiscord:user-database-cleaner":ODCode, + "opendiscord:ticket-database-cleaner":ODCode, + "opendiscord:panel-auto-update":ODCode, + "opendiscord:ticket-saver":ODCode, + "opendiscord:blacklist-saver":ODCode, + "opendiscord:auto-role-on-join":ODCode, + "opendiscord:autoclose-timeout":ODCode, + "opendiscord:autoclose-leave":ODCode, + "opendiscord:autodelete-timeout":ODCode, + "opendiscord:autodelete-leave":ODCode, + "opendiscord:ticket-anti-busy":ODCode, } /**## ODCodeManager_Default `default_class` diff --git a/src/core/api/defaults/config.ts b/src/core/api/defaults/config.ts index 0936bd2..ccdcfd0 100644 --- a/src/core/api/defaults/config.ts +++ b/src/core/api/defaults/config.ts @@ -12,11 +12,11 @@ import { ODRoleUpdateMode } from "../openticket/role" * It's used to generate typescript declarations for this class. */ export interface ODConfigManagerIds_Default { - "openticket:general":ODJsonConfig_DefaultGeneral, - "openticket:options":ODJsonConfig_DefaultOptions, - "openticket:panels":ODJsonConfig_DefaultPanels, - "openticket:questions":ODJsonConfig_DefaultQuestions, - "openticket:transcripts":ODJsonConfig_DefaultTranscripts + "opendiscord:general":ODJsonConfig_DefaultGeneral, + "opendiscord:options":ODJsonConfig_DefaultOptions, + "opendiscord:panels":ODJsonConfig_DefaultPanels, + "opendiscord:questions":ODJsonConfig_DefaultQuestions, + "opendiscord:transcripts":ODJsonConfig_DefaultTranscripts } /**## ODConfigManager_Default `default_class` @@ -102,7 +102,7 @@ export class ODJsonConfig_DefaultGeneral extends ODJsonConfig { /**The main (hex) color used in almost every embed in the bot. */ mainColor:discord.ColorResolvable, - /**The language to use. Can be the id of the language or the id without the prefix when using `openticket:...`. */ + /**The language to use. Can be the id of the language or the id without the prefix when using `opendiscord:...`. */ language:string, /**The prefix used in all text-commands. */ prefix:string, diff --git a/src/core/api/defaults/console.ts b/src/core/api/defaults/console.ts index d824fce..6b4d0da 100644 --- a/src/core/api/defaults/console.ts +++ b/src/core/api/defaults/console.ts @@ -9,7 +9,7 @@ import { ODLiveStatusUrlSource, ODLiveStatusManager, ODLiveStatusSource } from " * It's used to generate typescript declarations for this class. */ export interface ODLiveStatusManagerIds_Default { - "openticket:default-djdj-dev":ODLiveStatusUrlSource + "opendiscord:default-djdj-dev":ODLiveStatusUrlSource } /**## ODLiveStatusManager_Default `default_class` diff --git a/src/core/api/defaults/database.ts b/src/core/api/defaults/database.ts index 012be40..9dd3bcc 100644 --- a/src/core/api/defaults/database.ts +++ b/src/core/api/defaults/database.ts @@ -11,11 +11,11 @@ import { ODOptionJson } from "../openticket/option" * It's used to generate typescript declarations for this class. */ export interface ODDatabaseManagerIds_Default { - "openticket:global":ODFormattedJsonDatabase_DefaultGlobal, - "openticket:stats":ODFormattedJsonDatabase, - "openticket:tickets":ODFormattedJsonDatabase_DefaultTickets, - "openticket:users":ODFormattedJsonDatabase_DefaultUsers, - "openticket:options":ODFormattedJsonDatabase_DefaultOptions, + "opendiscord:global":ODFormattedJsonDatabase_DefaultGlobal, + "opendiscord:stats":ODFormattedJsonDatabase, + "opendiscord:tickets":ODFormattedJsonDatabase_DefaultTickets, + "opendiscord:users":ODFormattedJsonDatabase_DefaultUsers, + "opendiscord:options":ODFormattedJsonDatabase_DefaultOptions, } /**## ODDatabaseManager_Default `default_class` @@ -52,10 +52,10 @@ export class ODDatabaseManager_Default extends ODDatabaseManager { * It's used to generate typescript declarations for this class. */ export interface ODFormattedJsonDatabaseIds_DefaultGlobal { - "openticket:panel-update":string, - "openticket:option-suffix-counter":number, - "openticket:option-suffix-history":string[], - "openticket:last-version":string + "opendiscord:panel-update":string, + "opendiscord:option-suffix-counter":number, + "opendiscord:option-suffix-history":string[], + "opendiscord:last-version":string } /**## ODFormattedJsonDatabase_DefaultGlobal `default_class` @@ -106,7 +106,7 @@ export class ODFormattedJsonDatabase_DefaultGlobal extends ODFormattedJsonDataba * It's used to generate typescript declarations for this class. */ export interface ODFormattedJsonDatabaseIds_DefaultTickets { - "openticket:ticket":ODTicketJson + "opendiscord:ticket":ODTicketJson } /**## ODFormattedJsonDatabase_DefaultTickets `default_class` @@ -157,7 +157,7 @@ export class ODFormattedJsonDatabase_DefaultTickets extends ODFormattedJsonDatab * It's used to generate typescript declarations for this class. */ export interface ODFormattedJsonDatabaseIds_DefaultUsers { - "openticket:blacklist":ODTicketJson + "opendiscord:blacklist":ODTicketJson } /**## ODFormattedJsonDatabase_DefaultUsers `default_class` @@ -209,7 +209,7 @@ export class ODFormattedJsonDatabase_DefaultUsers extends ODFormattedJsonDatabas * It's used to generate typescript declarations for this class. */ export interface ODFormattedJsonDatabaseIds_DefaultOptions { - "openticket:used-option":ODOptionJson + "opendiscord:used-option":ODOptionJson } /**## ODFormattedJsonDatabase_DefaultOptions `default_class` diff --git a/src/core/api/defaults/flag.ts b/src/core/api/defaults/flag.ts index dbc066f..bf2d5eb 100644 --- a/src/core/api/defaults/flag.ts +++ b/src/core/api/defaults/flag.ts @@ -9,20 +9,20 @@ import { ODFlagManager, ODFlag } from "../modules/flag" * It's used to generate typescript declarations for this class. */ export interface ODFlagManagerIds_Default { - "openticket:no-migration":ODFlag, - "openticket:dev-config":ODFlag, - "openticket:dev-database":ODFlag, - "openticket:debug":ODFlag, - "openticket:crash":ODFlag, - "openticket:no-transcripts":ODFlag, - "openticket:no-checker":ODFlag, - "openticket:checker":ODFlag, - "openticket:no-easter":ODFlag, - "openticket:no-plugins":ODFlag, - "openticket:soft-plugins":ODFlag, - "openticket:force-slash-update":ODFlag, - "openticket:no-compile":ODFlag, - "openticket:compile-only":ODFlag, + "opendiscord:no-migration":ODFlag, + "opendiscord:dev-config":ODFlag, + "opendiscord:dev-database":ODFlag, + "opendiscord:debug":ODFlag, + "opendiscord:crash":ODFlag, + "opendiscord:no-transcripts":ODFlag, + "opendiscord:no-checker":ODFlag, + "opendiscord:checker":ODFlag, + "opendiscord:no-easter":ODFlag, + "opendiscord:no-plugins":ODFlag, + "opendiscord:soft-plugins":ODFlag, + "opendiscord:force-slash-update":ODFlag, + "opendiscord:no-compile":ODFlag, + "opendiscord:compile-only":ODFlag, } /**## ODFlagManager_Default `default_class` diff --git a/src/core/api/defaults/helpmenu.ts b/src/core/api/defaults/helpmenu.ts index 50624fc..a8a986d 100644 --- a/src/core/api/defaults/helpmenu.ts +++ b/src/core/api/defaults/helpmenu.ts @@ -9,13 +9,13 @@ import { ODHelpMenuCategory, ODHelpMenuCommandComponent, ODHelpMenuComponent, OD * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerIds_Default { - "openticket:general":ODHelpMenuCategory_DefaultGeneral, - "openticket:ticket-basic":ODHelpMenuCategory_DefaultTicketBasic, - "openticket:ticket-advanced":ODHelpMenuCategory_DefaultTicketAdvanced, - "openticket:ticket-user":ODHelpMenuCategory_DefaultTicketUser, - "openticket:admin":ODHelpMenuCategory_DefaultAdmin, - "openticket:advanced":ODHelpMenuCategory_DefaultAdvanced, - "openticket:extra":ODHelpMenuCategory_DefaultExtra + "opendiscord:general":ODHelpMenuCategory_DefaultGeneral, + "opendiscord:ticket-basic":ODHelpMenuCategory_DefaultTicketBasic, + "opendiscord:ticket-advanced":ODHelpMenuCategory_DefaultTicketAdvanced, + "opendiscord:ticket-user":ODHelpMenuCategory_DefaultTicketUser, + "opendiscord:admin":ODHelpMenuCategory_DefaultAdmin, + "opendiscord:advanced":ODHelpMenuCategory_DefaultAdvanced, + "opendiscord:extra":ODHelpMenuCategory_DefaultExtra } /**## ODHelpMenuManager_Default `default_class` @@ -52,15 +52,15 @@ export class ODHelpMenuManager_Default extends ODHelpMenuManager { * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultGeneral { - "openticket:help":ODHelpMenuCommandComponent, - "openticket:ticket":ODHelpMenuCommandComponent|null + "opendiscord:help":ODHelpMenuCommandComponent, + "opendiscord:ticket":ODHelpMenuCommandComponent|null } /**## ODHelpMenuCategory_DefaultGeneral `default_class` * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:general` category in `opendiscord.helpmenu`! + * This default class is made for the `opendiscord:general` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultGeneral extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultGeneral[HelpMenuCategoryId] @@ -90,16 +90,16 @@ export class ODHelpMenuCategory_DefaultGeneral extends ODHelpMenuCategory { * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultTicketBasic { - "openticket:close":ODHelpMenuCommandComponent, - "openticket:delete":ODHelpMenuCommandComponent, - "openticket:reopen":ODHelpMenuCommandComponent + "opendiscord:close":ODHelpMenuCommandComponent, + "opendiscord:delete":ODHelpMenuCommandComponent, + "opendiscord:reopen":ODHelpMenuCommandComponent } /**## ODHelpMenuCategory_DefaultTicketBasic `default_class` * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:ticket` category in `opendiscord.helpmenu`! + * This default class is made for the `opendiscord:ticket` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultTicketBasic extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketBasic[HelpMenuCategoryId] @@ -129,17 +129,17 @@ export class ODHelpMenuCategory_DefaultTicketBasic extends ODHelpMenuCategory { * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced { - "openticket:pin":ODHelpMenuCommandComponent, - "openticket:unpin":ODHelpMenuCommandComponent, - "openticket:move":ODHelpMenuCommandComponent, - "openticket:rename":ODHelpMenuCommandComponent + "opendiscord:pin":ODHelpMenuCommandComponent, + "opendiscord:unpin":ODHelpMenuCommandComponent, + "opendiscord:move":ODHelpMenuCommandComponent, + "opendiscord:rename":ODHelpMenuCommandComponent } /**## ODHelpMenuCategory_DefaultTicketAdvanced `default_class` * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:ticket` category in `opendiscord.helpmenu`! + * This default class is made for the `opendiscord:ticket` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultTicketAdvanced extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced[HelpMenuCategoryId] @@ -169,17 +169,17 @@ export class ODHelpMenuCategory_DefaultTicketAdvanced extends ODHelpMenuCategory * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultTicketUser { - "openticket:claim":ODHelpMenuCommandComponent, - "openticket:unclaim":ODHelpMenuCommandComponent, - "openticket:add":ODHelpMenuCommandComponent, - "openticket:remove":ODHelpMenuCommandComponent + "opendiscord:claim":ODHelpMenuCommandComponent, + "opendiscord:unclaim":ODHelpMenuCommandComponent, + "opendiscord:add":ODHelpMenuCommandComponent, + "opendiscord:remove":ODHelpMenuCommandComponent } /**## ODHelpMenuCategory_DefaultTicketUser `default_class` * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:ticket` category in `opendiscord.helpmenu`! + * This default class is made for the `opendiscord:ticket` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultTicketUser extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketUser[HelpMenuCategoryId] @@ -209,18 +209,18 @@ export class ODHelpMenuCategory_DefaultTicketUser extends ODHelpMenuCategory { * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultAdmin { - "openticket:panel":ODHelpMenuCommandComponent, - "openticket:blacklist-view":ODHelpMenuCommandComponent, - "openticket:blacklist-add":ODHelpMenuCommandComponent, - "openticket:blacklist-remove":ODHelpMenuCommandComponent, - "openticket:blacklist-get":ODHelpMenuCommandComponent + "opendiscord:panel":ODHelpMenuCommandComponent, + "opendiscord:blacklist-view":ODHelpMenuCommandComponent, + "opendiscord:blacklist-add":ODHelpMenuCommandComponent, + "opendiscord:blacklist-remove":ODHelpMenuCommandComponent, + "opendiscord:blacklist-get":ODHelpMenuCommandComponent } /**## ODHelpMenuCategory_DefaultAdmin `default_class` * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:admin` category in `opendiscord.helpmenu`! + * This default class is made for the `opendiscord:admin` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultAdmin extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdmin[HelpMenuCategoryId] @@ -250,19 +250,19 @@ export class ODHelpMenuCategory_DefaultAdmin extends ODHelpMenuCategory { * It's used to generate typescript declarations for this class. */ export interface ODHelpMenuManagerCategoryIds_DefaultAdvanced { - "openticket:stats-global":ODHelpMenuCommandComponent, - "openticket:stats-reset":ODHelpMenuCommandComponent, - "openticket:stats-ticket":ODHelpMenuCommandComponent, - "openticket:stats-user":ODHelpMenuCommandComponent, - "openticket:autoclose-disable":ODHelpMenuCommandComponent, - "openticket:autoclose-enable":ODHelpMenuCommandComponent + "opendiscord:stats-global":ODHelpMenuCommandComponent, + "opendiscord:stats-reset":ODHelpMenuCommandComponent, + "opendiscord:stats-ticket":ODHelpMenuCommandComponent, + "opendiscord:stats-user":ODHelpMenuCommandComponent, + "opendiscord:autoclose-disable":ODHelpMenuCommandComponent, + "opendiscord:autoclose-enable":ODHelpMenuCommandComponent } /**## ODHelpMenuCategory_DefaultAdvanced `default_class` * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:advanced` category in `opendiscord.helpmenu`! + * This default class is made for the `opendiscord:advanced` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultAdvanced extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdvanced[HelpMenuCategoryId] @@ -297,7 +297,7 @@ export interface ODHelpMenuManagerCategoryIds_DefaultExtra {} * This is a special class that adds type definitions & typescript to the ODHelpMenuManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:general` category in `opendiscord.helpmenu`! + * This default class is made for the `opendiscord:general` category in `opendiscord.helpmenu`! */ export class ODHelpMenuCategory_DefaultExtra extends ODHelpMenuCategory { get(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultExtra[HelpMenuCategoryId] diff --git a/src/core/api/defaults/language.ts b/src/core/api/defaults/language.ts index e6849a5..49c4771 100644 --- a/src/core/api/defaults/language.ts +++ b/src/core/api/defaults/language.ts @@ -444,29 +444,29 @@ export type ODLanguageManagerTranslations_Default = ( * It's used to generate typescript declarations for this class. */ export interface ODLanguageManagerIds_Default { - "openticket:custom":ODLanguage, - "openticket:english":ODLanguage, - "openticket:dutch":ODLanguage, - "openticket:portuguese":ODLanguage, - "openticket:czech":ODLanguage, - "openticket:german":ODLanguage, - "openticket:catalan":ODLanguage, - "openticket:hungarian":ODLanguage, - "openticket:spanish":ODLanguage, - "openticket:romanian":ODLanguage, - "openticket:ukrainian":ODLanguage, - "openticket:indonesian":ODLanguage, - "openticket:italian":ODLanguage, - "openticket:estonian":ODLanguage, - "openticket:finnish":ODLanguage, - "openticket:danish":ODLanguage, - "openticket:thai":ODLanguage, - "openticket:turkish":ODLanguage, - "openticket:french":ODLanguage, - "openticket:arabic":ODLanguage, - "openticket:hindi":ODLanguage, - "openticket:lithuanian":ODLanguage, - "openticket:polish":ODLanguage, + "opendiscord:custom":ODLanguage, + "opendiscord:english":ODLanguage, + "opendiscord:dutch":ODLanguage, + "opendiscord:portuguese":ODLanguage, + "opendiscord:czech":ODLanguage, + "opendiscord:german":ODLanguage, + "opendiscord:catalan":ODLanguage, + "opendiscord:hungarian":ODLanguage, + "opendiscord:spanish":ODLanguage, + "opendiscord:romanian":ODLanguage, + "opendiscord:ukrainian":ODLanguage, + "opendiscord:indonesian":ODLanguage, + "opendiscord:italian":ODLanguage, + "opendiscord:estonian":ODLanguage, + "opendiscord:finnish":ODLanguage, + "opendiscord:danish":ODLanguage, + "opendiscord:thai":ODLanguage, + "opendiscord:turkish":ODLanguage, + "opendiscord:french":ODLanguage, + "opendiscord:arabic":ODLanguage, + "opendiscord:hindi":ODLanguage, + "opendiscord:lithuanian":ODLanguage, + "opendiscord:polish":ODLanguage, //ADD NEW LANGUAGES HERE!!! } diff --git a/src/core/api/defaults/permission.ts b/src/core/api/defaults/permission.ts index 5a3f3d7..23b4b02 100644 --- a/src/core/api/defaults/permission.ts +++ b/src/core/api/defaults/permission.ts @@ -17,7 +17,7 @@ export class ODPermissionManager_Default extends ODPermissionManager { } /**## ODPermissionEmbedType `type` - * This type contains all types available in the `openticket:no-permissions` embed. + * This type contains all types available in the `opendiscord:no-permissions` embed. */ export type ODPermissionEmbedType = ( "developer"| diff --git a/src/core/api/defaults/post.ts b/src/core/api/defaults/post.ts index 1776b0b..bdc64db 100644 --- a/src/core/api/defaults/post.ts +++ b/src/core/api/defaults/post.ts @@ -10,8 +10,8 @@ import * as discord from "discord.js" * It's used to generate typescript declarations for this class. */ export interface ODPostManagerIds_Default { - "openticket:logs":ODPost|null, - "openticket:transcripts":ODPost|null + "opendiscord:logs":ODPost|null, + "opendiscord:transcripts":ODPost|null } /**## ODPostManager_Default `default_class` diff --git a/src/core/api/defaults/progressbar.ts b/src/core/api/defaults/progressbar.ts index e0e46fe..2d1b3f1 100644 --- a/src/core/api/defaults/progressbar.ts +++ b/src/core/api/defaults/progressbar.ts @@ -89,12 +89,12 @@ export class ODProgressBarRenderer_Default extends ODProgressBarRenderer(id:StatsId): ODStatGlobalScopeIds_DefaultGlobal[StatsId] @@ -119,15 +119,15 @@ export class ODStatGlobalScope_DefaultGlobal extends ODStatGlobalScope { * It's used to generate typescript declarations for this class. */ export interface ODStatGlobalScopeIds_DefaultSystem { - "openticket:startup-date":ODDynamicStat, - "openticket:version":ODDynamicStat + "opendiscord:startup-date":ODDynamicStat, + "opendiscord:version":ODDynamicStat } /**## ODStatGlobalScope_DefaultSystem `default_class` * This is a special class that adds type definitions & typescript to the ODStatsManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:system` category in `opendiscord.stats`! + * This default class is made for the `opendiscord:system` category in `opendiscord.stats`! */ export class ODStatGlobalScope_DefaultSystem extends ODStatGlobalScope { get(id:StatsId): ODStatGlobalScopeIds_DefaultSystem[StatsId] @@ -178,24 +178,24 @@ export class ODStatGlobalScope_DefaultSystem extends ODStatGlobalScope { * It's used to generate typescript declarations for this class. */ export interface ODStatScopeIds_DefaultUser { - "openticket:name":ODDynamicStat, - "openticket:role":ODDynamicStat, - "openticket:tickets-created":ODBasicStat, - "openticket:tickets-closed":ODBasicStat, - "openticket:tickets-deleted":ODBasicStat, - "openticket:tickets-reopened":ODBasicStat, - "openticket:tickets-claimed":ODBasicStat, - "openticket:tickets-pinned":ODBasicStat, - "openticket:tickets-moved":ODBasicStat, - "openticket:users-blacklisted":ODBasicStat, - "openticket:transcripts-created":ODBasicStat + "opendiscord:name":ODDynamicStat, + "opendiscord:role":ODDynamicStat, + "opendiscord:tickets-created":ODBasicStat, + "opendiscord:tickets-closed":ODBasicStat, + "opendiscord:tickets-deleted":ODBasicStat, + "opendiscord:tickets-reopened":ODBasicStat, + "opendiscord:tickets-claimed":ODBasicStat, + "opendiscord:tickets-pinned":ODBasicStat, + "opendiscord:tickets-moved":ODBasicStat, + "opendiscord:users-blacklisted":ODBasicStat, + "opendiscord:transcripts-created":ODBasicStat } /**## ODStatScope_DefaultUser `default_class` * This is a special class that adds type definitions & typescript to the ODStatsManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:user` category in `opendiscord.stats`! + * This default class is made for the `opendiscord:user` category in `opendiscord.stats`! */ export class ODStatScope_DefaultUser extends ODStatScope { get(id:StatsId): ODStatScopeIds_DefaultUser[StatsId] @@ -246,19 +246,19 @@ export class ODStatScope_DefaultUser extends ODStatScope { * It's used to generate typescript declarations for this class. */ export interface ODStatScopeIds_DefaultTicket { - "openticket:name":ODDynamicStat, - "openticket:status":ODDynamicStat, - "openticket:claimed":ODDynamicStat, - "openticket:pinned":ODDynamicStat, - "openticket:creation-date":ODDynamicStat, - "openticket:creator":ODDynamicStat + "opendiscord:name":ODDynamicStat, + "opendiscord:status":ODDynamicStat, + "opendiscord:claimed":ODDynamicStat, + "opendiscord:pinned":ODDynamicStat, + "opendiscord:creation-date":ODDynamicStat, + "opendiscord:creator":ODDynamicStat } /**## ODStatScope_DefaultTicket `default_class` * This is a special class that adds type definitions & typescript to the ODStatsManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:ticket` category in `opendiscord.stats`! + * This default class is made for the `opendiscord:ticket` category in `opendiscord.stats`! */ export class ODStatScope_DefaultTicket extends ODStatScope { get(id:StatsId): ODStatScopeIds_DefaultTicket[StatsId] @@ -309,14 +309,14 @@ export class ODStatScope_DefaultTicket extends ODStatScope { * It's used to generate typescript declarations for this class. */ export interface ODStatScopeIds_DefaultParticipants { - "openticket:participants":ODDynamicStat + "opendiscord:participants":ODDynamicStat } /**## ODStatScope_DefaultParticipants `default_class` * This is a special class that adds type definitions & typescript to the ODStatsManager class. * It doesn't add any extra features! * - * This default class is made for the `openticket:participants` category in `opendiscord.stats`! + * This default class is made for the `opendiscord:participants` category in `opendiscord.stats`! */ export class ODStatScope_DefaultParticipants extends ODStatScope { get(id:StatsId): ODStatScopeIds_DefaultParticipants[StatsId] diff --git a/src/core/api/defaults/verifybar.ts b/src/core/api/defaults/verifybar.ts index 280eca8..7ee623b 100644 --- a/src/core/api/defaults/verifybar.ts +++ b/src/core/api/defaults/verifybar.ts @@ -12,23 +12,23 @@ import * as discord from "discord.js" * It's used to generate typescript declarations for this class. */ export interface ODVerifyBarManagerIds_Default { - "openticket:claim-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:claim-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, - "openticket:claim-ticket-unclaim-message":{successWorkerIds:"openticket:permissions"|"openticket:claim-ticket",failureWorkerIds:"openticket:back-to-unclaim-message"}, - "openticket:unclaim-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:unclaim-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, - "openticket:unclaim-ticket-claim-message":{successWorkerIds:"openticket:permissions"|"openticket:unclaim-ticket",failureWorkerIds:"openticket:back-to-claim-message"}, - "openticket:pin-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:pin-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, - "openticket:pin-ticket-unpin-message":{successWorkerIds:"openticket:permissions"|"openticket:pin-ticket",failureWorkerIds:"openticket:back-to-unpin-message"}, - "openticket:unpin-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:unpin-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, - "openticket:unpin-ticket-pin-message":{successWorkerIds:"openticket:permissions"|"openticket:unpin-ticket",failureWorkerIds:"openticket:back-to-pin-message"}, - "openticket:close-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:close-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, - "openticket:close-ticket-reopen-message":{successWorkerIds:"openticket:permissions"|"openticket:close-ticket",failureWorkerIds:"openticket:back-to-reopen-message"}, - "openticket:reopen-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:reopen-ticket",failureWorkerIds:"openticket:back-to-ticket-message"}, - "openticket:reopen-ticket-close-message":{successWorkerIds:"openticket:permissions"|"openticket:reopen-ticket",failureWorkerIds:"openticket:back-to-close-message"}, - "openticket:reopen-ticket-autoclose-message":{successWorkerIds:"openticket:permissions"|"openticket:reopen-ticket",failureWorkerIds:"openticket:back-to-autoclose-message"}, - "openticket:delete-ticket-ticket-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-ticket-message"} - "openticket:delete-ticket-close-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-close-message"} - "openticket:delete-ticket-reopen-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-reopen-message"} - "openticket:delete-ticket-autoclose-message":{successWorkerIds:"openticket:permissions"|"openticket:delete-ticket",failureWorkerIds:"openticket:back-to-autoclose-message"} + "opendiscord:claim-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:claim-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"}, + "opendiscord:claim-ticket-unclaim-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:claim-ticket",failureWorkerIds:"opendiscord:back-to-unclaim-message"}, + "opendiscord:unclaim-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:unclaim-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"}, + "opendiscord:unclaim-ticket-claim-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:unclaim-ticket",failureWorkerIds:"opendiscord:back-to-claim-message"}, + "opendiscord:pin-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:pin-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"}, + "opendiscord:pin-ticket-unpin-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:pin-ticket",failureWorkerIds:"opendiscord:back-to-unpin-message"}, + "opendiscord:unpin-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:unpin-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"}, + "opendiscord:unpin-ticket-pin-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:unpin-ticket",failureWorkerIds:"opendiscord:back-to-pin-message"}, + "opendiscord:close-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:close-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"}, + "opendiscord:close-ticket-reopen-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:close-ticket",failureWorkerIds:"opendiscord:back-to-reopen-message"}, + "opendiscord:reopen-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:reopen-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"}, + "opendiscord:reopen-ticket-close-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:reopen-ticket",failureWorkerIds:"opendiscord:back-to-close-message"}, + "opendiscord:reopen-ticket-autoclose-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:reopen-ticket",failureWorkerIds:"opendiscord:back-to-autoclose-message"}, + "opendiscord:delete-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:delete-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"} + "opendiscord:delete-ticket-close-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:delete-ticket",failureWorkerIds:"opendiscord:back-to-close-message"} + "opendiscord:delete-ticket-reopen-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:delete-ticket",failureWorkerIds:"opendiscord:back-to-reopen-message"} + "opendiscord:delete-ticket-autoclose-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:delete-ticket",failureWorkerIds:"opendiscord:back-to-autoclose-message"} } /**## ODVerifyBarManager_Default `default_class` diff --git a/src/core/api/main.ts b/src/core/api/main.ts index 9ca7165..a248982 100644 --- a/src/core/api/main.ts +++ b/src/core/api/main.ts @@ -130,12 +130,12 @@ export class ODMain { constructor(){ this.versions = new ODVersionManager_Default() - this.versions.add(ODVersion.fromString("openticket:version","v4.0.0")) - this.versions.add(ODVersion.fromString("openticket:api","v1.0.0")) - this.versions.add(ODVersion.fromString("openticket:transcripts","v2.0.0")) - this.versions.add(ODVersion.fromString("openticket:livestatus","v2.0.0")) + this.versions.add(ODVersion.fromString("opendiscord:version","v4.0.0")) + 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")) - this.debugfile = new ODDebugFileManager("./","otdebug.txt",5000,this.versions.get("openticket:version")) + this.debugfile = new ODDebugFileManager("./","otdebug.txt",5000,this.versions.get("opendiscord:version")) this.console = new ODConsoleManager(100,this.debugfile) this.debug = new ODDebugger(this.console) this.events = new ODEventManager_Default(this.debug) diff --git a/src/core/api/modules/base.ts b/src/core/api/modules/base.ts index fda578e..368f237 100644 --- a/src/core/api/modules/base.ts +++ b/src/core/api/modules/base.ts @@ -46,9 +46,6 @@ export type ODInterfaceWithPartialProperty> { constructor(debug:ODDebugger){ super(() => { - return new ODButton("openticket:unknown-button",(instance,params,source,cancel) => { + return new ODButton("opendiscord:unknown-button",(instance,params,source,cancel) => { instance.setCustomId("od:unknown-button") instance.setMode("button") instance.setColor("red") @@ -255,7 +255,7 @@ export class ODButton extends ODBuilderImplementat export class ODDropdownManager extends ODManagerWithSafety> { constructor(debug:ODDebugger){ super(() => { - return new ODDropdown("openticket:unknown-dropdown",(instance,params,source,cancel) => { + return new ODDropdown("opendiscord:unknown-dropdown",(instance,params,source,cancel) => { instance.setCustomId("od:unknown-dropdown") instance.setType("string") instance.setPlaceholder("❌ ") @@ -509,7 +509,7 @@ export class ODDropdown extends ODBuilderImplement export class ODFileManager extends ODManagerWithSafety> { constructor(debug:ODDebugger){ super(() => { - return new ODFile("openticket:unknown-file",(instance,params,source,cancel) => { + return new ODFile("opendiscord:unknown-file",(instance,params,source,cancel) => { instance.setName("openticket_unknown-file.txt") instance.setDescription("❌ ") instance.setContents("Couldn't find file in registery `opendiscord.builders.files`") @@ -632,8 +632,8 @@ export class ODFile extends ODBuilderImplementatio export class ODEmbedManager extends ODManagerWithSafety> { constructor(debug:ODDebugger){ super(() => { - return new ODEmbed("openticket:unknown-embed",(instance,params,source,cancel) => { - instance.setFooter("openticket:unknown-embed") + return new ODEmbed("opendiscord:unknown-embed",(instance,params,source,cancel) => { + instance.setFooter("opendiscord:unknown-embed") instance.setColor("#ff0000") instance.setTitle("❌ ") instance.setDescription("Couldn't find embed in registery `opendiscord.builders.embeds`") @@ -846,7 +846,7 @@ export class ODEmbed extends ODBuilderImplementati export class ODMessageManager extends ODManagerWithSafety> { constructor(debug:ODDebugger){ super(() => { - return new ODMessage("openticket:unknown-message",(instance,params,source,cancel) => { + return new ODMessage("opendiscord:unknown-message",(instance,params,source,cancel) => { instance.setContent("**❌ **\nCouldn't find message in registery `opendiscord.builders.messages`") cancel() }) @@ -1087,7 +1087,7 @@ export class ODMessage extends ODBuilderImplementa export class ODModalManager extends ODManagerWithSafety> { constructor(debug:ODDebugger){ super(() => { - return new ODModal("openticket:unknown-modal",(instance,params,source,cancel) => { + return new ODModal("opendiscord:unknown-modal",(instance,params,source,cancel) => { instance.setCustomId("od:unknown-modal") instance.setTitle("❌ ") instance.setQuestions( diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 641766b..0e172cf 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -442,7 +442,7 @@ export class ODCheckerObjectStructure extends ODCheckerStructure { //check type & options if (typeof value != "object"){ - checker.createMessage("openticket:invalid-type","error","This property needs to be the type: object!",lt,null,["object"],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:invalid-type","error","This property needs to be the type: object!",lt,null,["object"],this.id,(this.options.docs ?? null)) return false } @@ -463,9 +463,9 @@ export class ODCheckerObjectStructure extends ODCheckerStructure { if (typeof value[child.key] == "undefined"){ if (!child.optional){ localQuit = true - checker.createMessage("openticket:property-missing","error",`The property "${child.key}" is mising from this object!`,lt,null,[`"${child.key}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:property-missing","error",`The property "${child.key}" is mising from this object!`,lt,null,[`"${child.key}"`],this.id,(this.options.docs ?? null)) }else{ - checker.createMessage("openticket:property-optional","info",`The property "${child.key}" is optional in this object!`,lt,null,[`"${child.key}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:property-optional","info",`The property "${child.key}" is optional in this object!`,lt,null,[`"${child.key}"`],this.id,(this.options.docs ?? null)) } }else if (!child.checker.check(checker,value[child.key],localLt)) localQuit = true }) @@ -515,31 +515,31 @@ export class ODCheckerStringStructure extends ODCheckerStructure { //check type & options if (typeof value != "string"){ - checker.createMessage("openticket:invalid-type","error","This property needs to be the type: string!",lt,null,["string"],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:invalid-type","error","This property needs to be the type: string!",lt,null,["string"],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.minLength != "undefined" && value.length < this.options.minLength){ - checker.createMessage("openticket:string-too-short","error",`This string can't be shorter than ${this.options.minLength} characters!`,lt,null,[this.options.minLength.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:string-too-short","error",`This string can't be shorter than ${this.options.minLength} characters!`,lt,null,[this.options.minLength.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.maxLength != "undefined" && value.length > this.options.maxLength){ - checker.createMessage("openticket:string-too-long","error",`This string can't be longer than ${this.options.maxLength} characters!`,lt,null,[this.options.maxLength.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:string-too-long","error",`This string can't be longer than ${this.options.maxLength} characters!`,lt,null,[this.options.maxLength.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.length != "undefined" && value.length !== this.options.length){ - checker.createMessage("openticket:string-length-invalid","error",`This string needs to be ${this.options.length} characters long!`,lt,null,[this.options.length.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:string-length-invalid","error",`This string needs to be ${this.options.length} characters long!`,lt,null,[this.options.length.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.startsWith != "undefined" && !value.startsWith(this.options.startsWith)){ - checker.createMessage("openticket:string-starts-with","error",`This string needs to start with "${this.options.startsWith}"!`,lt,null,[`"${this.options.startsWith}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:string-starts-with","error",`This string needs to start with "${this.options.startsWith}"!`,lt,null,[`"${this.options.startsWith}"`],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.endsWith != "undefined" && !value.endsWith(this.options.endsWith)){ - checker.createMessage("openticket:string-ends-with","error",`This string needs to end with "${this.options.endsWith}"!`,lt,null,[`"${this.options.endsWith}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:string-ends-with","error",`This string needs to end with "${this.options.endsWith}"!`,lt,null,[`"${this.options.endsWith}"`],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.contains != "undefined" && !value.includes(this.options.contains)){ - checker.createMessage("openticket:string-contains","error",`This string needs to contain "${this.options.contains}"!`,lt,null,[`"${this.options.contains}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:string-contains","error",`This string needs to contain "${this.options.contains}"!`,lt,null,[`"${this.options.contains}"`],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.choices != "undefined" && !this.options.choices.includes(value)){ - checker.createMessage("openticket:string-choices","error",`This string can only be one of the following values: "${this.options.choices.join(`", "`)}"!`,lt,null,[`"${this.options.choices.join(`", "`)}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:string-choices","error",`This string can only be one of the following values: "${this.options.choices.join(`", "`)}"!`,lt,null,[`"${this.options.choices.join(`", "`)}"`],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.regex != "undefined" && !this.options.regex.test(value)){ - checker.createMessage("openticket:string-regex","error","This string is invalid!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:string-regex","error","This string is invalid!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else return super.check(checker,value,locationTrace) } @@ -603,53 +603,53 @@ export class ODCheckerNumberStructure extends ODCheckerStructure { //check type & options if (typeof value != "number"){ - checker.createMessage("openticket:invalid-type","error","This property needs to be the type: number!",lt,null,["number"],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:invalid-type","error","This property needs to be the type: number!",lt,null,["number"],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.minLength != "undefined" && value.toString().length < this.options.minLength){ - checker.createMessage("openticket:number-too-short","error",`This number can't be shorter than ${this.options.minLength} characters!`,lt,null,[this.options.minLength.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-too-short","error",`This number can't be shorter than ${this.options.minLength} characters!`,lt,null,[this.options.minLength.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.maxLength != "undefined" && value.toString().length > this.options.maxLength){ - checker.createMessage("openticket:number-too-long","error",`This number can't be longer than ${this.options.maxLength} characters!`,lt,null,[this.options.maxLength.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-too-long","error",`This number can't be longer than ${this.options.maxLength} characters!`,lt,null,[this.options.maxLength.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.length != "undefined" && value.toString().length !== this.options.length){ - checker.createMessage("openticket:number-length-invalid","error",`This number needs to be ${this.options.length} characters long!`,lt,null,[this.options.length.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-length-invalid","error",`This number needs to be ${this.options.length} characters long!`,lt,null,[this.options.length.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.min != "undefined" && value < this.options.min){ - checker.createMessage("openticket:number-too-small","error",`This number needs to be at least ${this.options.min}!`,lt,null,[this.options.min.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-too-small","error",`This number needs to be at least ${this.options.min}!`,lt,null,[this.options.min.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.max != "undefined" && value > this.options.max){ - checker.createMessage("openticket:number-too-large","error",`This number needs to be at most ${this.options.max}!`,lt,null,[this.options.max.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-too-large","error",`This number needs to be at most ${this.options.max}!`,lt,null,[this.options.max.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.is != "undefined" && value == this.options.is){ - checker.createMessage("openticket:number-not-equal","error",`This number needs to be ${this.options.is}!`,lt,null,[this.options.is.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-not-equal","error",`This number needs to be ${this.options.is}!`,lt,null,[this.options.is.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.step != "undefined" && ((value - stepOffset) % this.options.step) !== 0){ - if (stepOffset > 0) checker.createMessage("openticket:number-step-offset","error",`This number needs to be a multiple of ${this.options.step} starting with ${stepOffset}!`,lt,null,[this.options.step.toString(),stepOffset.toString()],this.id,(this.options.docs ?? null)) - else checker.createMessage("openticket:number-step","error",`This number needs to be a multiple of ${this.options.step}!`,lt,null,[this.options.step.toString()],this.id,(this.options.docs ?? null)) + if (stepOffset > 0) checker.createMessage("opendiscord:number-step-offset","error",`This number needs to be a multiple of ${this.options.step} starting with ${stepOffset}!`,lt,null,[this.options.step.toString(),stepOffset.toString()],this.id,(this.options.docs ?? null)) + else checker.createMessage("opendiscord:number-step","error",`This number needs to be a multiple of ${this.options.step}!`,lt,null,[this.options.step.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.startsWith != "undefined" && !value.toString().startsWith(this.options.startsWith)){ - checker.createMessage("openticket:number-starts-with","error",`This number needs to start with "${this.options.startsWith}"!`,lt,null,[`"${this.options.startsWith}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-starts-with","error",`This number needs to start with "${this.options.startsWith}"!`,lt,null,[`"${this.options.startsWith}"`],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.endsWith != "undefined" && !value.toString().endsWith(this.options.endsWith)){ - checker.createMessage("openticket:number-ends-with","error",`This number needs to end with "${this.options.endsWith}"!`,lt,null,[`"${this.options.endsWith}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-ends-with","error",`This number needs to end with "${this.options.endsWith}"!`,lt,null,[`"${this.options.endsWith}"`],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.contains != "undefined" && !value.toString().includes(this.options.contains)){ - checker.createMessage("openticket:number-contains","error",`This number needs to contain "${this.options.contains}"!`,lt,null,[`"${this.options.contains}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-contains","error",`This number needs to contain "${this.options.contains}"!`,lt,null,[`"${this.options.contains}"`],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.choices != "undefined" && !this.options.choices.includes(value)){ - checker.createMessage("openticket:number-choices","error",`This number can only be one of the following values: "${this.options.choices.join(`", "`)}"!`,lt,null,[`"${this.options.choices.join(`", "`)}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-choices","error",`This number can only be one of the following values: "${this.options.choices.join(`", "`)}"!`,lt,null,[`"${this.options.choices.join(`", "`)}"`],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.floatAllowed != "undefined" && !this.options.floatAllowed && (value % 1) !== 0){ - checker.createMessage("openticket:number-float","error","This number can't be a decimal!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-float","error","This number can't be a decimal!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.negativeAllowed != "undefined" && value < 0){ - checker.createMessage("openticket:number-negative","error","This number can't be negative!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-negative","error","This number can't be negative!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.positiveAllowed != "undefined" && value > 0){ - checker.createMessage("openticket:number-positive","error","This number can't be positive!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-positive","error","This number can't be positive!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.zeroAllowed != "undefined" && value === 0){ - checker.createMessage("openticket:number-zero","error","This number can't be zero!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:number-zero","error","This number can't be zero!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else return super.check(checker,value,locationTrace) } @@ -682,13 +682,13 @@ export class ODCheckerBooleanStructure extends ODCheckerStructure { //check type & options if (typeof value != "boolean"){ - checker.createMessage("openticket:invalid-type","error","This property needs to be the type: boolean!",lt,null,["boolean"],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:invalid-type","error","This property needs to be the type: boolean!",lt,null,["boolean"],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.trueAllowed != "undefined" && !this.options.trueAllowed && value == true){ - checker.createMessage("openticket:boolean-true","error","This boolean can't be true!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:boolean-true","error","This boolean can't be true!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.falseAllowed != "undefined" && !this.options.falseAllowed && value == false){ - checker.createMessage("openticket:boolean-false","error","This boolean can't be false!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:boolean-false","error","This boolean can't be false!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else return super.check(checker,value,locationTrace) } @@ -732,28 +732,28 @@ export class ODCheckerArrayStructure extends ODCheckerStructure { const lt = checker.locationTraceDeref(locationTrace) if (!Array.isArray(value)){ - checker.createMessage("openticket:invalid-type","error","This property needs to be the type: array!",lt,null,["array"],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:invalid-type","error","This property needs to be the type: array!",lt,null,["array"],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.disableEmpty != "undefined" && this.options.disableEmpty && value.length == 0){ - checker.createMessage("openticket:array-empty-disabled","error","This array isn't allowed to be empty!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:array-empty-disabled","error","This array isn't allowed to be empty!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.emptyRequired != "undefined" && this.options.emptyRequired && value.length != 0){ - checker.createMessage("openticket:array-empty-required","error","This array is required to be empty!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:array-empty-required","error","This array is required to be empty!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.minLength != "undefined" && value.length < this.options.minLength){ - checker.createMessage("openticket:array-too-short","error",`This array needs to have a length of at least ${this.options.minLength}!`,lt,null,[this.options.minLength.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:array-too-short","error",`This array needs to have a length of at least ${this.options.minLength}!`,lt,null,[this.options.minLength.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.maxLength != "undefined" && value.length > this.options.maxLength){ - checker.createMessage("openticket:array-too-long","error",`This array needs to have a length of at most ${this.options.maxLength}!`,lt,null,[this.options.maxLength.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:array-too-long","error",`This array needs to have a length of at most ${this.options.maxLength}!`,lt,null,[this.options.maxLength.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.length != "undefined" && value.length == this.options.length){ - checker.createMessage("openticket:array-length-invalid","error",`This array needs to have a length of ${this.options.length}!`,lt,null,[this.options.length.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:array-length-invalid","error",`This array needs to have a length of ${this.options.length}!`,lt,null,[this.options.length.toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.allowedTypes != "undefined" && !this.#arrayAllowedTypesCheck(value,this.options.allowedTypes)){ - checker.createMessage("openticket:array-invalid-types","error",`This array can only contain the following types: ${this.options.allowedTypes.join(", ")}!`,lt,null,[this.options.allowedTypes.join(", ").toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:array-invalid-types","error",`This array can only contain the following types: ${this.options.allowedTypes.join(", ")}!`,lt,null,[this.options.allowedTypes.join(", ").toString()],this.id,(this.options.docs ?? null)) return false }else if (typeof this.options.allowDoubles != "undefined" && !this.options.allowDoubles && this.#arrayHasDoubles(value)){ - checker.createMessage("openticket:array-double","error","This array doesn't allow the same value twice!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:array-double","error","This array doesn't allow the same value twice!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else{ //check all properties @@ -836,10 +836,10 @@ export class ODCheckerNullStructure extends ODCheckerStructure { //check type & options if (typeof this.options.nullAllowed != "undefined" && !this.options.nullAllowed && value == null){ - checker.createMessage("openticket:null-invalid","error","This property can't be null!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:null-invalid","error","This property can't be null!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (value !== null){ - checker.createMessage("openticket:invalid-type","error","This property needs to be the type: null!",lt,null,["null"],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:invalid-type","error","This property needs to be the type: null!",lt,null,["null"],this.id,(this.options.docs ?? null)) return false }else return super.check(checker,value,locationTrace) } @@ -909,7 +909,7 @@ export class ODCheckerTypeSwitchStructure extends ODCheckerStructure { return this.options.other.check(checker,value,lt) }else if (this.options.allowedTypes && this.options.allowedTypes.length > 0){ - checker.createMessage("openticket:switch-invalid-type","error",`This needs to be one of the following types: ${this.options.allowedTypes.join(", ")}!`,lt,null,[this.options.allowedTypes.join(", ")],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:switch-invalid-type","error",`This needs to be one of the following types: ${this.options.allowedTypes.join(", ")}!`,lt,null,[this.options.allowedTypes.join(", ")],this.id,(this.options.docs ?? null)) return false }else return super.check(checker,value,locationTrace) } @@ -950,7 +950,7 @@ export class ODCheckerObjectSwitchStructure extends ODCheckerStructure { if (this.options.objects){ //check type & options if (typeof value != "object"){ - checker.createMessage("openticket:invalid-type","error","This property needs to be the type: object!",lt,null,["object"],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:invalid-type","error","This property needs to be the type: object!",lt,null,["object"],this.id,(this.options.docs ?? null)) return false } @@ -974,7 +974,7 @@ export class ODCheckerObjectSwitchStructure extends ODCheckerStructure { //do local quit or check custom function if (!didSelectObject){ - checker.createMessage("openticket:object-switch-invalid-type","error",`This object needs to be one of the following types: ${this.options.objects.map((obj) => obj.name).join(", ")}!`,lt,null,[this.options.objects.map((obj) => obj.name).join(", ")],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:object-switch-invalid-type","error",`This object needs to be one of the following types: ${this.options.objects.map((obj) => obj.name).join(", ")}!`,lt,null,[this.options.objects.map((obj) => obj.name).join(", ")],this.id,(this.options.docs ?? null)) return false }else if (localQuit){ return false @@ -1012,12 +1012,12 @@ export class ODCheckerEnabledObjectStructure extends ODCheckerStructure { if (typeof value != "object"){ //value isn't an object - checker.createMessage("openticket:invalid-type","error","This property needs to be the type: object!",lt,null,["object"],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:invalid-type","error","This property needs to be the type: object!",lt,null,["object"],this.id,(this.options.docs ?? null)) return false }else if (this.options.property && typeof value[this.options.property] == "undefined"){ //property doesn't exist - checker.createMessage("openticket:property-missing","error",`The property "${this.options.property}" is mising from this object!`,lt,null,[`"${this.options.property}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:property-missing","error",`The property "${this.options.property}" is mising from this object!`,lt,null,[`"${this.options.property}"`],this.id,(this.options.docs ?? null)) return false }else if (this.options.property && value[this.options.property] === (typeof this.options.enabledValue == "undefined" ? true : this.options.enabledValue)){ @@ -1027,7 +1027,7 @@ export class ODCheckerEnabledObjectStructure extends ODCheckerStructure { }else{ //this object is disabled - if (this.options.property) checker.createMessage("openticket:object-disabled","info",`This object is disabled, enable it using "${this.options.property}"!`,lt,null,[`"${this.options.property}"`],this.id,(this.options.docs ?? null)) + if (this.options.property) checker.createMessage("opendiscord:object-disabled","info",`This object is disabled, enable it using "${this.options.property}"!`,lt,null,[`"${this.options.property}"`],this.id,(this.options.docs ?? null)) return super.check(checker,value,locationTrace) } } @@ -1059,8 +1059,8 @@ export class ODCheckerCustomStructure_DiscordId extends ODCheckerStringStructure else if ((!emptyAllowed && value.length < 15) || value.length > 50 || !/^[0-9]*$/.test(value)){ if (!(extraOptions.length > 0 && extraOptions.some((opt) => opt == value))){ //value is not an id & not one of the extra options - if (extraOptions.length > 0) checker.createMessage("openticket:discord-invalid-id-options","error",`This is an invalid discord ${type} id! You can also use one of these: ${extraOptions.join(", ")}!`,lt,null,[type,extraOptions.join(", ")],this.id,(this.options.docs ?? null)) - else checker.createMessage("openticket:discord-invalid-id","error",`This is an invalid discord ${type} id!`,lt,null,[type],this.id,(this.options.docs ?? null)) + if (extraOptions.length > 0) checker.createMessage("opendiscord:discord-invalid-id-options","error",`This is an invalid discord ${type} id! You can also use one of these: ${extraOptions.join(", ")}!`,lt,null,[type,extraOptions.join(", ")],this.id,(this.options.docs ?? null)) + else checker.createMessage("opendiscord:discord-invalid-id","error",`This is an invalid discord ${type} id!`,lt,null,[type],this.id,(this.options.docs ?? null)) return false }else return true } @@ -1113,7 +1113,7 @@ export class ODCheckerCustomStructure_DiscordToken extends ODCheckerStringStruct const lt = checker.locationTraceDeref(locationTrace) if (typeof value != "string" || !/^[A-Za-z0-9-_\.]+$/.test(value)){ - checker.createMessage("openticket:discord-invalid-token","error","This is an invalid discord token (syntactically)!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:discord-invalid-token","error","This is an invalid discord token (syntactically)!",lt,null,[],this.id,(this.options.docs ?? null)) return false } return true @@ -1146,7 +1146,7 @@ export class ODCheckerCustomStructure_HexColor extends ODCheckerStringStructure else if (emptyAllowed && value.length == 0){ return true }else if ((!allowShortForm && !/^#[a-fA-F0-9]{6}$/.test(value)) || (allowShortForm && !/^#[a-fA-F0-9]{6}$/.test(value) && !/^#[a-fA-F0-9]{3}$/.test(value))){ - checker.createMessage("openticket:color-invalid","error","This is an invalid hex color!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:color-invalid","error","This is an invalid hex color!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else return true } @@ -1186,16 +1186,16 @@ export class ODCheckerCustomStructure_EmojiString extends ODCheckerStringStructu const emojiAmount = discordEmojiAmount+unicodeEmojiAmount if (emojiAmount < minLength){ - checker.createMessage("openticket:emoji-too-short","error",`This string needs to have at least ${minLength} emoji's!`,lt,null,[maxLength.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:emoji-too-short","error",`This string needs to have at least ${minLength} emoji's!`,lt,null,[maxLength.toString()],this.id,(this.options.docs ?? null)) return false }else if (emojiAmount > maxLength){ - checker.createMessage("openticket:emoji-too-long","error",`This string needs to have at most ${maxLength} emoji's!`,lt,null,[maxLength.toString()],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:emoji-too-long","error",`This string needs to have at most ${maxLength} emoji's!`,lt,null,[maxLength.toString()],this.id,(this.options.docs ?? null)) return false }else if (!allowCustomDiscordEmoji && //.test(value)){ - checker.createMessage("openticket:emoji-custom","error",`This emoji can't be a custom discord emoji!`,lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:emoji-custom","error",`This emoji can't be a custom discord emoji!`,lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (!/^(?:\p{Emoji}|\p{Emoji_Component}|(?:))*$/u.test(value)){ - checker.createMessage("openticket:emoji-invalid","error","This is an invalid emoji!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:emoji-invalid","error","This is an invalid emoji!",lt,null,[],this.id,(this.options.docs ?? null)) return false } return true @@ -1247,25 +1247,25 @@ export class ODCheckerCustomStructure_UrlString extends ODCheckerStringStructure else if (emptyAllowed && value.length == 0){ return true }else if (!this.#urlIsValid(value)){ - checker.createMessage("openticket:url-invalid","error","This url is invalid!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:url-invalid","error","This url is invalid!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (typeof this.urlSettings.allowHttp != "undefined" && !this.urlSettings.allowHttp && !/^(https:\/\/)/.test(value)){ - checker.createMessage("openticket:url-invalid-http","error","This url can only use the https:// protocol!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:url-invalid-http","error","This url can only use the https:// protocol!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (!/^(http(s)?:\/\/)/.test(value)){ - checker.createMessage("openticket:url-invalid-protocol","error","This url can only use the http:// & https:// protocols!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:url-invalid-protocol","error","This url can only use the http:// & https:// protocols!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (typeof this.urlSettings.allowedHostnames != "undefined" && !this.#urlHasValidHostname(value,this.urlSettings.allowedHostnames)){ - checker.createMessage("openticket:url-invalid-hostname","error","This url has a disallowed hostname!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:url-invalid-hostname","error","This url has a disallowed hostname!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (typeof this.urlSettings.allowedExtensions != "undefined" && !this.#urlHasValidExtension(value,this.urlSettings.allowedExtensions)){ - checker.createMessage("openticket:url-invalid-extension","error",`This url has an invalid extension! Choose between: ${this.urlSettings.allowedExtensions.join(", ")}!"`,lt,null,[this.urlSettings.allowedExtensions.join(", ")],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:url-invalid-extension","error",`This url has an invalid extension! Choose between: ${this.urlSettings.allowedExtensions.join(", ")}!"`,lt,null,[this.urlSettings.allowedExtensions.join(", ")],this.id,(this.options.docs ?? null)) return false }else if (typeof this.urlSettings.allowedPaths != "undefined" && !this.#urlHasValidPath(value,this.urlSettings.allowedPaths)){ - checker.createMessage("openticket:url-invalid-path","error","This url has an invalid path!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:url-invalid-path","error","This url has an invalid path!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else if (typeof this.urlSettings.regex != "undefined" && !this.urlSettings.regex.test(value)){ - checker.createMessage("openticket:url-invalid","error","This url is invalid!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:url-invalid","error","This url is invalid!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else return true } @@ -1351,7 +1351,7 @@ export class ODCheckerCustomStructure_UniqueId extends ODCheckerStringStructure const uniqueArray: string[] = (checker.storage.get(source,scope) === null) ? [] : checker.storage.get(source,scope) if (uniqueArray.includes(value)){ //unique id already exists => throw error - checker.createMessage("openticket:id-not-unique","error","This id isn't unique, use another id instead!",lt,null,[],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:id-not-unique","error","This id isn't unique, use another id instead!",lt,null,[],this.id,(this.options.docs ?? null)) return false }else{ //unique id doesn't exists => add to list @@ -1405,7 +1405,7 @@ export class ODCheckerCustomStructure_UniqueIdArray extends ODCheckerArrayStruct } }else{ //doesn't exist - checker.createMessage("openticket:id-non-existent","error",`The id "${id}" doesn't exist!`,localLt,null,[`"${id}"`],this.id,(this.options.docs ?? null)) + checker.createMessage("opendiscord:id-non-existent","error",`The id "${id}" doesn't exist!`,localLt,null,[`"${id}"`],this.id,(this.options.docs ?? null)) localQuit = true } }) diff --git a/src/core/api/modules/console.ts b/src/core/api/modules/console.ts index 3497184..fc634d6 100644 --- a/src/core/api/modules/console.ts +++ b/src/core/api/modules/console.ts @@ -501,8 +501,8 @@ export class ODLiveStatusSource extends ODManagerData { const validMessages: ODLiveStatusSourceData[] = [] //parse data from ODMain - const currentVersion: string = main.versions.get("openticket:version").toString(true) - const usingSlashCommands: boolean = main.configs.get("openticket:general").data.slashCommands + const currentVersion: string = main.versions.get("opendiscord:version").toString(true) + const usingSlashCommands: boolean = main.configs.get("opendiscord:general").data.slashCommands const usingTranscripts: false|"text"|"html" = false as false|"text"|"html" //TODO const currentLanguage: string = main.languages.getCurrentLanguageId() const usingPlugins: boolean = (main.plugins.getLength() > 0) diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index 0747ad2..aaa0c47 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -252,7 +252,7 @@ export class ODDefaultsManager { languageLoading:true, languageInitiating:true, languageSelection:true, - backupLanguage:"openticket:english", + backupLanguage:"opendiscord:english", languageList:[], checkerLoading:true, diff --git a/src/core/api/openticket/option.ts b/src/core/api/openticket/option.ts index 8268a59..d71268d 100644 --- a/src/core/api/openticket/option.ts +++ b/src/core/api/openticket/option.ts @@ -50,7 +50,7 @@ export interface ODOptionDataJson { export interface ODOptionJson { /**The id of this option. */ id:string, - /**The type of this option. (e.g. `openticket:ticket`, `openticket:website`, `openticket:role`) */ + /**The type of this option. (e.g. `opendiscord:ticket`, `opendiscord:website`, `opendiscord:role`) */ type:string, /**The version of Open Ticket used to create this option & store it in the database. */ version:string, @@ -68,7 +68,7 @@ export interface ODOptionJson { export class ODOption extends ODManager> { /**The id of this option. (from the config) */ id:ODId - /**The type of this option. (e.g. `openticket:ticket`, `openticket:website`, `openticket:role`) */ + /**The type of this option. (e.g. `opendiscord:ticket`, `opendiscord:website`, `opendiscord:role`) */ type: string constructor(id:ODValidId, type:string, data:ODOptionData[]){ @@ -138,51 +138,51 @@ export class ODOptionData extends ODManagerDat * It's used to generate typescript declarations for this class. */ export interface ODTicketOptionIds { - "openticket:name":ODOptionData, - "openticket:description":ODOptionData, + "opendiscord:name":ODOptionData, + "opendiscord:description":ODOptionData, - "openticket:button-emoji":ODOptionData, - "openticket:button-label":ODOptionData, - "openticket:button-color":ODOptionData, + "opendiscord:button-emoji":ODOptionData, + "opendiscord:button-label":ODOptionData, + "opendiscord:button-color":ODOptionData, - "openticket:admins":ODOptionData, - "openticket:admins-readonly":ODOptionData, - "openticket:allow-blacklisted-users":ODOptionData, - "openticket:questions":ODOptionData, + "opendiscord:admins":ODOptionData, + "opendiscord:admins-readonly":ODOptionData, + "opendiscord:allow-blacklisted-users":ODOptionData, + "opendiscord:questions":ODOptionData, - "openticket:channel-prefix":ODOptionData, - "openticket:channel-suffix":ODOptionData<"user-name"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed">, - "openticket:channel-category":ODOptionData, - "openticket:channel-category-closed":ODOptionData, - "openticket:channel-category-backup":ODOptionData, - "openticket:channel-categories-claimed":ODOptionData<{user:string,category:string}[]>, - "openticket:channel-description":ODOptionData, + "opendiscord:channel-prefix":ODOptionData, + "opendiscord:channel-suffix":ODOptionData<"user-name"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed">, + "opendiscord:channel-category":ODOptionData, + "opendiscord:channel-category-closed":ODOptionData, + "opendiscord:channel-category-backup":ODOptionData, + "opendiscord:channel-categories-claimed":ODOptionData<{user:string,category:string}[]>, + "opendiscord:channel-description":ODOptionData, - "openticket:dm-message-enabled":ODOptionData, - "openticket:dm-message-text":ODOptionData, - "openticket:dm-message-embed":ODOptionData, + "opendiscord:dm-message-enabled":ODOptionData, + "opendiscord:dm-message-text":ODOptionData, + "opendiscord:dm-message-embed":ODOptionData, - "openticket:ticket-message-enabled":ODOptionData, - "openticket:ticket-message-text":ODOptionData, - "openticket:ticket-message-embed":ODOptionData, - "openticket:ticket-message-ping":ODOptionData, + "opendiscord:ticket-message-enabled":ODOptionData, + "opendiscord:ticket-message-text":ODOptionData, + "opendiscord:ticket-message-embed":ODOptionData, + "opendiscord:ticket-message-ping":ODOptionData, - "openticket:autoclose-enable-hours":ODOptionData, - "openticket:autoclose-enable-leave":ODOptionData, - "openticket:autoclose-disable-claim":ODOptionData, - "openticket:autoclose-hours":ODOptionData, + "opendiscord:autoclose-enable-hours":ODOptionData, + "opendiscord:autoclose-enable-leave":ODOptionData, + "opendiscord:autoclose-disable-claim":ODOptionData, + "opendiscord:autoclose-hours":ODOptionData, - "openticket:autodelete-enable-days":ODOptionData, - "openticket:autodelete-enable-leave":ODOptionData, - "openticket:autodelete-disable-claim":ODOptionData, - "openticket:autodelete-days":ODOptionData, + "opendiscord:autodelete-enable-days":ODOptionData, + "opendiscord:autodelete-enable-leave":ODOptionData, + "opendiscord:autodelete-disable-claim":ODOptionData, + "opendiscord:autodelete-days":ODOptionData, - "openticket:cooldown-enabled":ODOptionData, - "openticket:cooldown-minutes":ODOptionData, + "opendiscord:cooldown-enabled":ODOptionData, + "opendiscord:cooldown-minutes":ODOptionData, - "openticket:limits-enabled":ODOptionData, - "openticket:limits-maximum-global":ODOptionData, - "openticket:limits-maximum-user":ODOptionData + "opendiscord:limits-enabled":ODOptionData, + "opendiscord:limits-maximum-global":ODOptionData, + "opendiscord:limits-maximum-user":ODOptionData } /**## ODTicketOption `class` @@ -193,10 +193,10 @@ export interface ODTicketOptionIds { * Use this option to create a new ticket! */ export class ODTicketOption extends ODOption { - type: "openticket:ticket" = "openticket:ticket" + type: "opendiscord:ticket" = "opendiscord:ticket" constructor(id:ODValidId, data:ODOptionData[]){ - super(id,"openticket:ticket",data) + super(id,"opendiscord:ticket",data) } get(id:OptionId): ODTicketOptionIds[OptionId] @@ -230,13 +230,13 @@ export class ODTicketOption extends ODOption { * It's used to generate typescript declarations for this class. */ export interface ODWebsiteOptionIds { - "openticket:name":ODOptionData, - "openticket:description":ODOptionData, + "opendiscord:name":ODOptionData, + "opendiscord:description":ODOptionData, - "openticket:button-emoji":ODOptionData, - "openticket:button-label":ODOptionData, + "opendiscord:button-emoji":ODOptionData, + "opendiscord:button-label":ODOptionData, - "openticket:url":ODOptionData, + "opendiscord:url":ODOptionData, } /**## ODWebsiteOption `class` @@ -247,10 +247,10 @@ export interface ODWebsiteOptionIds { * Use this option to create a button which links to a website! */ export class ODWebsiteOption extends ODOption { - type: "openticket:website" = "openticket:website" + type: "opendiscord:website" = "opendiscord:website" constructor(id:ODValidId, data:ODOptionData[]){ - super(id,"openticket:website",data) + super(id,"opendiscord:website",data) } get(id:OptionId): ODWebsiteOptionIds[OptionId] @@ -284,17 +284,17 @@ export class ODWebsiteOption extends ODOption { * It's used to generate typescript declarations for this class. */ export interface ODRoleOptionIds { - "openticket:name":ODOptionData, - "openticket:description":ODOptionData, + "opendiscord:name":ODOptionData, + "opendiscord:description":ODOptionData, - "openticket:button-emoji":ODOptionData, - "openticket:button-label":ODOptionData, - "openticket:button-color":ODOptionData, + "opendiscord:button-emoji":ODOptionData, + "opendiscord:button-label":ODOptionData, + "opendiscord:button-color":ODOptionData, - "openticket:roles":ODOptionData, - "openticket:mode":ODOptionData, - "openticket:remove-roles-on-add":ODOptionData, - "openticket:add-on-join":ODOptionData + "opendiscord:roles":ODOptionData, + "opendiscord:mode":ODOptionData, + "opendiscord:remove-roles-on-add":ODOptionData, + "opendiscord:add-on-join":ODOptionData } /**## ODRoleOption `class` @@ -305,10 +305,10 @@ export interface ODRoleOptionIds { * Use this option to create a button for reaction roles! */ export class ODRoleOption extends ODOption { - type: "openticket:role" = "openticket:role" + type: "opendiscord:role" = "opendiscord:role" constructor(id:ODValidId, data:ODOptionData[]){ - super(id,"openticket:role",data) + super(id,"opendiscord:role",data) } get(id:OptionId): ODRoleOptionIds[OptionId] @@ -424,13 +424,13 @@ export class ODOptionCounterDynamicSuffix extends ODOptionSuffix { /**Initialize the database for this suffix. */ async #init(){ - if (!await this.database.exists("openticket:option-suffix-counter",this.option.id.value)) await this.database.set("openticket:option-suffix-counter",this.option.id.value,0) + 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("openticket:option-suffix-counter",this.option.id.value) + const rawCurrentValue = 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("openticket:option-suffix-counter",this.option.id.value,newValue) + this.database.set("opendiscord:option-suffix-counter",this.option.id.value,newValue) return newValue.toString() } } @@ -454,14 +454,14 @@ export class ODOptionCounterFixedSuffix extends ODOptionSuffix { /**Initialize the database for this suffix. */ async #init(){ - if (!await this.database.exists("openticket:option-suffix-counter",this.option.id.value)) await this.database.set("openticket:option-suffix-counter",this.option.id.value,0) + 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("openticket:option-suffix-counter",this.option.id.value) + const rawCurrentValue = 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("openticket:option-suffix-counter",this.option.id.value,newValue) + 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() @@ -488,7 +488,7 @@ export class ODOptionRandomNumberSuffix extends ODOptionSuffix { /**Initialize the database for this suffix. */ async #init(){ - if (!await this.database.exists("openticket:option-suffix-history",this.option.id.value)) await this.database.set("openticket:option-suffix-history",this.option.id.value,[]) + if (!await this.database.exists("opendiscord:option-suffix-history",this.option.id.value)) await this.database.set("opendiscord:option-suffix-history",this.option.id.value,[]) } /**Get a unique number for this suffix. */ #generateUniqueValue(history:string[]): string { @@ -502,12 +502,12 @@ export class ODOptionRandomNumberSuffix extends ODOptionSuffix { else return number } getSuffix(user:discord.User): string { - const rawCurrentValues = this.database.get("openticket:option-suffix-history",this.option.id.value) + const rawCurrentValues = 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("openticket:option-suffix-history",this.option.id.value,currentValues) + this.database.set("opendiscord:option-suffix-history",this.option.id.value,currentValues) return newValue } } @@ -531,7 +531,7 @@ export class ODOptionRandomHexSuffix extends ODOptionSuffix { /**Initialize the database for this suffix. */ async #init(){ - if (!await this.database.exists("openticket:option-suffix-history",this.option.id.value)) await this.database.set("openticket:option-suffix-history",this.option.id.value,[]) + if (!await this.database.exists("opendiscord:option-suffix-history",this.option.id.value)) await this.database.set("opendiscord:option-suffix-history",this.option.id.value,[]) } /**Get a unique hex-string for this suffix. */ #generateUniqueValue(history:string[]): string { @@ -540,12 +540,12 @@ export class ODOptionRandomHexSuffix extends ODOptionSuffix { else return hex } getSuffix(user:discord.User): string { - const rawCurrentValues = this.database.get("openticket:option-suffix-history",this.option.id.value) + const rawCurrentValues = 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("openticket:option-suffix-history",this.option.id.value,currentValues) + this.database.set("opendiscord:option-suffix-history",this.option.id.value,currentValues) return newValue } } \ No newline at end of file diff --git a/src/core/api/openticket/panel.ts b/src/core/api/openticket/panel.ts index 21ec71b..633a0a8 100644 --- a/src/core/api/openticket/panel.ts +++ b/src/core/api/openticket/panel.ts @@ -54,23 +54,23 @@ export interface ODPanelJson { * It's used to generate typescript declarations for this class. */ export interface ODPanelIds { - "openticket:name":ODPanelData, - "openticket:options":ODPanelData, - "openticket:dropdown":ODPanelData, + "opendiscord:name":ODPanelData, + "opendiscord:options":ODPanelData, + "opendiscord:dropdown":ODPanelData, - "openticket:text":ODPanelData, - "openticket:embed":ODPanelData, + "opendiscord:text":ODPanelData, + "opendiscord:embed":ODPanelData, - "openticket:dropdown-placeholder":ODPanelData, + "opendiscord:dropdown-placeholder":ODPanelData, - "openticket:enable-max-tickets-warning-text":ODPanelData, - "openticket:enable-max-tickets-warning-embed":ODPanelData, + "opendiscord:enable-max-tickets-warning-text":ODPanelData, + "opendiscord:enable-max-tickets-warning-embed":ODPanelData, - "openticket:describe-options-layout":ODPanelData<"simple"|"normal"|"detailed">, - "openticket:describe-options-custom-title":ODPanelData, - "openticket:describe-options-in-text":ODPanelData, - "openticket:describe-options-in-embed-fields":ODPanelData, - "openticket:describe-options-in-embed-description":ODPanelData + "opendiscord:describe-options-layout":ODPanelData<"simple"|"normal"|"detailed">, + "opendiscord:describe-options-custom-title":ODPanelData, + "opendiscord:describe-options-in-text":ODPanelData, + "opendiscord:describe-options-in-embed-fields":ODPanelData, + "opendiscord:describe-options-in-embed-description":ODPanelData } /**## ODPanel `class` diff --git a/src/core/api/openticket/question.ts b/src/core/api/openticket/question.ts index cd99aad..5f19a4b 100644 --- a/src/core/api/openticket/question.ts +++ b/src/core/api/openticket/question.ts @@ -60,7 +60,7 @@ export interface ODQuestionJson { export class ODQuestion extends ODManager> { /**The id of this question. (from the config) */ id:ODId - /**The type of this question (e.g. `openticket:short` or `openticket:paragraph`) */ + /**The type of this question (e.g. `opendiscord:short` or `opendiscord:paragraph`) */ type: string constructor(id:ODValidId, type:string, data:ODQuestionData[]){ @@ -130,13 +130,13 @@ export class ODQuestionData extends ODManagerD * It's used to generate typescript declarations for this class. */ export interface ODShortQuestionIds { - "openticket:name":ODQuestionData, - "openticket:required":ODQuestionData, - "openticket:placeholder":ODQuestionData, + "opendiscord:name":ODQuestionData, + "opendiscord:required":ODQuestionData, + "opendiscord:placeholder":ODQuestionData, - "openticket:length-enabled":ODQuestionData, - "openticket:length-min":ODQuestionData, - "openticket:length-max":ODQuestionData + "opendiscord:length-enabled":ODQuestionData, + "opendiscord:length-min":ODQuestionData, + "opendiscord:length-max":ODQuestionData } /**## ODShortQuestion `class` @@ -147,10 +147,10 @@ export interface ODShortQuestionIds { * Use this question in an option to add a short text field to the modal! */ export class ODShortQuestion extends ODQuestion { - type: "openticket:short" = "openticket:short" + type: "opendiscord:short" = "opendiscord:short" constructor(id:ODValidId, data:ODQuestionData[]){ - super(id,"openticket:short",data) + super(id,"opendiscord:short",data) } get(id:QuestionId): ODShortQuestionIds[QuestionId] @@ -184,13 +184,13 @@ export class ODShortQuestion extends ODQuestion { * It's used to generate typescript declarations for this class. */ export interface ODParagraphQuestionIds { - "openticket:name":ODQuestionData, - "openticket:required":ODQuestionData, - "openticket:placeholder":ODQuestionData, + "opendiscord:name":ODQuestionData, + "opendiscord:required":ODQuestionData, + "opendiscord:placeholder":ODQuestionData, - "openticket:length-enabled":ODQuestionData, - "openticket:length-min":ODQuestionData, - "openticket:length-max":ODQuestionData + "opendiscord:length-enabled":ODQuestionData, + "opendiscord:length-min":ODQuestionData, + "opendiscord:length-max":ODQuestionData } /**## ODParagraphQuestion `class` @@ -201,10 +201,10 @@ export interface ODParagraphQuestionIds { * Use this question in an option to add a paragraph text field to the modal! */ export class ODParagraphQuestion extends ODQuestion { - type: "openticket:paragraph" = "openticket:paragraph" + type: "opendiscord:paragraph" = "opendiscord:paragraph" constructor(id:ODValidId, data:ODQuestionData[]){ - super(id,"openticket:paragraph",data) + super(id,"opendiscord:paragraph",data) } get(id:QuestionId): ODParagraphQuestionIds[QuestionId] diff --git a/src/core/api/openticket/role.ts b/src/core/api/openticket/role.ts index 6240470..ce22481 100644 --- a/src/core/api/openticket/role.ts +++ b/src/core/api/openticket/role.ts @@ -54,10 +54,10 @@ export interface ODRoleJson { * It's used to generate typescript declarations for this class. */ export interface ODRoleIds { - "openticket:roles":ODRoleData, - "openticket:mode":ODRoleData, - "openticket:remove-roles-on-add":ODRoleData, - "openticket:add-on-join":ODRoleData + "opendiscord:roles":ODRoleData, + "opendiscord:mode":ODRoleData, + "opendiscord:remove-roles-on-add":ODRoleData, + "opendiscord:add-on-join":ODRoleData } /**## ODRole `class` diff --git a/src/core/api/openticket/ticket.ts b/src/core/api/openticket/ticket.ts index bd00bec..7b03243 100644 --- a/src/core/api/openticket/ticket.ts +++ b/src/core/api/openticket/ticket.ts @@ -49,7 +49,7 @@ export class ODTicketManager extends ODManager { } /**Get the main ticket message of a ticket channel when found. */ async getTicketMessage(ticket:ODTicket): Promise|null> { - const msgId = ticket.get("openticket:ticket-message").value + const msgId = ticket.get("opendiscord:ticket-message").value if (!this.#guild || !msgId) return null try { const channel = await this.getTicketChannel(ticket) @@ -64,22 +64,22 @@ export class ODTicketManager extends ODManager { if (!this.#guild) return null try { if (user == "creator"){ - const creatorId = ticket.get("openticket:opened-by").value + const creatorId = ticket.get("opendiscord:opened-by").value if (!creatorId) return null else return (await this.#guild.client.users.fetch(creatorId)) }else if (user == "closer"){ - const closerId = ticket.get("openticket:closed-by").value + const closerId = ticket.get("opendiscord:closed-by").value if (!closerId) return null else return (await this.#guild.client.users.fetch(closerId)) }else if (user == "claimer"){ - const claimerId = ticket.get("openticket:claimed-by").value + const claimerId = ticket.get("opendiscord:claimed-by").value if (!claimerId) return null else return (await this.#guild.client.users.fetch(claimerId)) }else if (user == "pinner"){ - const pinnerId = ticket.get("openticket:pinned-by").value + const pinnerId = ticket.get("opendiscord:pinned-by").value if (!pinnerId) return null else return (await this.#guild.client.users.fetch(pinnerId)) @@ -94,14 +94,14 @@ export class ODTicketManager extends ODManager { if (!channel) return null //add creator - const creatorId = ticket.get("openticket:opened-by").value + const creatorId = ticket.get("opendiscord:opened-by").value if (creatorId){ const creator = await this.#client.fetchUser(creatorId) if (creator) final.push({user:creator,role:"creator"}) } //add participants - const participants = ticket.get("openticket:participants").value.filter((p) => p.type == "user") + const participants = ticket.get("opendiscord:participants").value.filter((p) => p.type == "user") for (const p of participants){ if (!final.find((u) => u.user.id == p.id)){ const participant = await this.#client.fetchUser(p.id) @@ -110,7 +110,7 @@ export class ODTicketManager extends ODManager { } //add admin roles - const roles = ticket.get("openticket:participants").value.filter((p) => p.type == "role") + const roles = ticket.get("opendiscord:participants").value.filter((p) => p.type == "role") for (const r of roles){ const role = await this.#client.fetchGuildRole(channel.guild,r.id) if (role){ @@ -154,35 +154,35 @@ export interface ODTicketJson { * It's used to generate typescript declarations for this class. */ export interface ODTicketIds { - "openticket:busy":ODTicketData, - "openticket:ticket-message":ODTicketData, - "openticket:participants":ODTicketData<{type:"role"|"user",id:string}[]>, - "openticket:channel-suffix":ODTicketData, + "opendiscord:busy":ODTicketData, + "opendiscord:ticket-message":ODTicketData, + "opendiscord:participants":ODTicketData<{type:"role"|"user",id:string}[]>, + "opendiscord:channel-suffix":ODTicketData, - "openticket:open":ODTicketData, - "openticket:opened-by":ODTicketData, - "openticket:opened-on":ODTicketData, - "openticket:closed":ODTicketData, - "openticket:closed-by":ODTicketData, - "openticket:closed-on":ODTicketData, - "openticket:claimed":ODTicketData, - "openticket:claimed-by":ODTicketData, - "openticket:claimed-on":ODTicketData, - "openticket:pinned":ODTicketData, - "openticket:pinned-by":ODTicketData, - "openticket:pinned-on":ODTicketData, - "openticket:for-deletion":ODTicketData, + "opendiscord:open":ODTicketData, + "opendiscord:opened-by":ODTicketData, + "opendiscord:opened-on":ODTicketData, + "opendiscord:closed":ODTicketData, + "opendiscord:closed-by":ODTicketData, + "opendiscord:closed-on":ODTicketData, + "opendiscord:claimed":ODTicketData, + "opendiscord:claimed-by":ODTicketData, + "opendiscord:claimed-on":ODTicketData, + "opendiscord:pinned":ODTicketData, + "opendiscord:pinned-by":ODTicketData, + "opendiscord:pinned-on":ODTicketData, + "opendiscord:for-deletion":ODTicketData, - "openticket:category":ODTicketData, - "openticket:category-mode":ODTicketData, + "opendiscord:category":ODTicketData, + "opendiscord:category-mode":ODTicketData, - "openticket:autoclose-enabled":ODTicketData, - "openticket:autoclose-hours":ODTicketData, - "openticket:autoclosed":ODTicketData, - "openticket:autodelete-enabled":ODTicketData, - "openticket:autodelete-days":ODTicketData, + "opendiscord:autoclose-enabled":ODTicketData, + "opendiscord:autoclose-hours":ODTicketData, + "opendiscord:autoclosed":ODTicketData, + "opendiscord:autodelete-enabled":ODTicketData, + "opendiscord:autodelete-days":ODTicketData, - "openticket:answers":ODTicketData<{id:string,name:string,type:"short"|"paragraph",value:string|null}[]>, + "opendiscord:answers":ODTicketData<{id:string,name:string,type:"short"|"paragraph",value:string|null}[]>, } /**## ODTicket `class` diff --git a/src/core/api/openticket/transcript.ts b/src/core/api/openticket/transcript.ts index 6af77c9..854cfee 100644 --- a/src/core/api/openticket/transcript.ts +++ b/src/core/api/openticket/transcript.ts @@ -13,7 +13,7 @@ import * as discord from "discord.js" * * This class manages all transcript generators in the bot. * - * The 2 default built-in transcript generators are: `openticket:html-compiler` & `openticket:text-compiler`. + * The 2 default built-in transcript generators are: `opendiscord:html-compiler` & `opendiscord:text-compiler`. */ export class ODTranscriptManager extends ODManager> { /**The manager responsible for collecting all messages in a channel. */ @@ -119,8 +119,8 @@ export class ODTranscriptCompiler extends ODManagerData { * It's used to generate typescript declarations for this class. */ export interface ODTranscriptCompilerIds { - "openticket:html-compiler":ODTranscriptCompiler<{url:string}>, - "openticket:text-compiler":ODTranscriptCompiler<{contents:string}>, + "opendiscord:html-compiler":ODTranscriptCompiler<{url:string}>, + "opendiscord:text-compiler":ODTranscriptCompiler<{contents:string}>, } /**## ODTranscriptManager_Default `default_class` diff --git a/src/core/startup/dump.ts b/src/core/startup/dump.ts index 27d0cc1..5ec486b 100644 --- a/src/core/startup/dump.ts +++ b/src/core/startup/dump.ts @@ -22,7 +22,7 @@ const disableDumpCommand = false export const loadDumpCommand = () => { if (disableDumpCommand) return - opendiscord.client.textCommands.add(new api.ODTextCommand("openticket:dump",{ + opendiscord.client.textCommands.add(new api.ODTextCommand("opendiscord:dump",{ allowBots:false, guildPermission:true, dmPermission:true, diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index 9a8e01c..07bc19c 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -5,8 +5,8 @@ export const loadVersionMigrationSystem = async () => { await preloadMigrationContext() const lastVersion = await isMigrationRequired() - opendiscord.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("openticket:last-version",opendiscord.versions.get("openticket:version").toString())) - if (lastVersion && !opendiscord.flags.get("openticket:no-migration").value){ + opendiscord.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("opendiscord:last-version",opendiscord.versions.get("opendiscord:version").toString())) + if (lastVersion && !opendiscord.flags.get("opendiscord:no-migration").value){ //MIGRATION IS REQUIRED opendiscord.log("Detected old data!","info") opendiscord.log("Starting closed API context...","debug") @@ -22,10 +22,10 @@ export const loadVersionMigrationSystem = async () => { saveAllVersionsToDatabase() //DEFAULT FLAGS - if (opendiscord.flags.exists("openticket:no-plugins") && opendiscord.flags.get("openticket:no-plugins").value) opendiscord.defaults.setDefault("pluginLoading",false) - if (opendiscord.flags.exists("openticket:soft-plugins") && opendiscord.flags.get("openticket:soft-plugins").value) opendiscord.defaults.setDefault("softPluginLoading",true) - if (opendiscord.flags.exists("openticket:crash") && opendiscord.flags.get("openticket:crash").value) opendiscord.defaults.setDefault("crashOnError",true) - if (opendiscord.flags.exists("openticket:force-slash-update") && opendiscord.flags.get("openticket:force-slash-update").value) opendiscord.defaults.setDefault("forceSlashCommandRegistration",true) + if (opendiscord.flags.exists("opendiscord:no-plugins") && opendiscord.flags.get("opendiscord:no-plugins").value) opendiscord.defaults.setDefault("pluginLoading",false) + if (opendiscord.flags.exists("opendiscord:soft-plugins") && opendiscord.flags.get("opendiscord:soft-plugins").value) opendiscord.defaults.setDefault("softPluginLoading",true) + if (opendiscord.flags.exists("opendiscord:crash") && opendiscord.flags.get("opendiscord:crash").value) opendiscord.defaults.setDefault("crashOnError",true) + if (opendiscord.flags.exists("opendiscord:force-slash-update") && opendiscord.flags.get("opendiscord:force-slash-update").value) opendiscord.defaults.setDefault("forceSlashCommandRegistration",true) //LEAVE MIGRATION CONTEXT await unloadMigrationContext() @@ -51,10 +51,10 @@ const unloadMigrationContext = async () => { } const isMigrationRequired = async (): Promise => { - const rawVersion = await opendiscord.databases.get("openticket:global").get("openticket:last-version","openticket:version") + const rawVersion = await opendiscord.databases.get("opendiscord:global").get("opendiscord:last-version","opendiscord:version") if (!rawVersion) return false - const version = api.ODVersion.fromString("openticket:last-version",rawVersion) - if (opendiscord.versions.get("openticket:version").compare(version) == "higher"){ + const version = api.ODVersion.fromString("opendiscord:last-version",rawVersion) + if (opendiscord.versions.get("opendiscord:version").compare(version) == "higher"){ return version }else return false } @@ -78,9 +78,9 @@ const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { } const saveAllVersionsToDatabase = async () => { - const globalDatabase = opendiscord.databases.get("openticket:global") + const globalDatabase = opendiscord.databases.get("opendiscord:global") await opendiscord.versions.loopAll(async (version,id) => { - await globalDatabase.set("openticket:last-version",id.value,version.toString()) + await globalDatabase.set("opendiscord:last-version",id.value,version.toString()) }) } \ No newline at end of file diff --git a/src/core/startup/migration.ts b/src/core/startup/migration.ts index a34ae1d..46e72cf 100644 --- a/src/core/startup/migration.ts +++ b/src/core/startup/migration.ts @@ -2,7 +2,7 @@ import {opendiscord, api, utilities} from "../../index" export const migrations = [ //MIGRATE TO v4.0.0 - new utilities.ODVersionMigration(api.ODVersion.fromString("openticket:version","v4.0.0"),async () => { + new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.0"),async () => { //nothing needs to be transferred :) }) ] \ No newline at end of file diff --git a/src/data/framework/checkerLoader.ts b/src/data/framework/checkerLoader.ts index 28f99eb..8955ae9 100644 --- a/src/data/framework/checkerLoader.ts +++ b/src/data/framework/checkerLoader.ts @@ -1,19 +1,19 @@ import {opendiscord, api, utilities} from "../../index" -const generalConfig = opendiscord.configs.get("openticket:general") +const generalConfig = opendiscord.configs.get("opendiscord:general") export const loadAllConfigCheckers = async () => { - opendiscord.checkers.add(new api.ODChecker("openticket:general",opendiscord.checkers.storage,0,opendiscord.configs.get("openticket:general"),defaultGeneralStructure)) - opendiscord.checkers.add(new api.ODChecker("openticket:options",opendiscord.checkers.storage,1,opendiscord.configs.get("openticket:options"),defaultOptionsStructure)) - opendiscord.checkers.add(new api.ODChecker("openticket:panels",opendiscord.checkers.storage,0,opendiscord.configs.get("openticket:panels"),defaultPanelsStructure)) - opendiscord.checkers.add(new api.ODChecker("openticket:questions",opendiscord.checkers.storage,2,opendiscord.configs.get("openticket:questions"),defaultQuestionsStructure)) - opendiscord.checkers.add(new api.ODChecker("openticket:transcripts",opendiscord.checkers.storage,0,opendiscord.configs.get("openticket:transcripts"),defaultTranscriptsStructure)) + opendiscord.checkers.add(new api.ODChecker("opendiscord:general",opendiscord.checkers.storage,0,opendiscord.configs.get("opendiscord:general"),defaultGeneralStructure)) + opendiscord.checkers.add(new api.ODChecker("opendiscord:options",opendiscord.checkers.storage,1,opendiscord.configs.get("opendiscord:options"),defaultOptionsStructure)) + opendiscord.checkers.add(new api.ODChecker("opendiscord:panels",opendiscord.checkers.storage,0,opendiscord.configs.get("opendiscord:panels"),defaultPanelsStructure)) + opendiscord.checkers.add(new api.ODChecker("opendiscord:questions",opendiscord.checkers.storage,2,opendiscord.configs.get("opendiscord:questions"),defaultQuestionsStructure)) + opendiscord.checkers.add(new api.ODChecker("opendiscord:transcripts",opendiscord.checkers.storage,0,opendiscord.configs.get("opendiscord:transcripts"),defaultTranscriptsStructure)) } export const loadAllConfigCheckerFunctions = async () => { - opendiscord.checkers.functions.add(new api.ODCheckerFunction("openticket:unused-options",defaultUnusedOptionsFunction)) - opendiscord.checkers.functions.add(new api.ODCheckerFunction("openticket:unused-questions",defaultUnusedQuestionsFunction)) - opendiscord.checkers.functions.add(new api.ODCheckerFunction("openticket:dropdown-options",defaultDropdownOptionsFunction)) + opendiscord.checkers.functions.add(new api.ODCheckerFunction("opendiscord:unused-options",defaultUnusedOptionsFunction)) + opendiscord.checkers.functions.add(new api.ODCheckerFunction("opendiscord:unused-questions",defaultUnusedQuestionsFunction)) + opendiscord.checkers.functions.add(new api.ODCheckerFunction("opendiscord:dropdown-options",defaultDropdownOptionsFunction)) } export const loadAllConfigCheckerTranslations = async () => { @@ -27,514 +27,514 @@ export const loadAllConfigCheckerTranslations = async () => { //GLOBAL FUNCTIONS export const registerDefaultCheckerSystemTranslations = (tm:api.ODCheckerTranslationRegister_Default,lm:api.ODLanguageManager_Default) => { //SYSTEM - //tm.quickTranslate(lm,"checker.system.headerOpenTicket","other","openticket:header-openticket") //OPEN TICKET (ignore) - tm.quickTranslate(lm,"checker.system.typeError","other","openticket:type-error") // [ERROR] (ignore) - tm.quickTranslate(lm,"checker.system.typeWarning","other","openticket:type-warning") // [WARNING] (ignore) - tm.quickTranslate(lm,"checker.system.typeInfo","other","openticket:type-info") // [INFO] (ignore) - tm.quickTranslate(lm,"checker.system.headerConfigChecker","other","openticket:header-configchecker") // CONFIG CHECKER - tm.quickTranslate(lm,"checker.system.headerDescription","other","openticket:header-description") // check for errors in your config files! - tm.quickTranslate(lm,"checker.system.footerError","other","openticket:footer-error") // the bot won't start until all {0}'s are fixed! - tm.quickTranslate(lm,"checker.system.footerWarning","other","openticket:footer-warning") // it's recommended to fix all {0}'s before starting! - tm.quickTranslate(lm,"checker.system.footerSupport","other","openticket:footer-support") // SUPPORT: {0} - DOCS: {1} - tm.quickTranslate(lm,"checker.system.compactInformation","other","openticket:compact-information") // use {0} for more information! - tm.quickTranslate(lm,"checker.system.dataPath","other","openticket:data-path") // path - tm.quickTranslate(lm,"checker.system.dataDocs","other","openticket:data-docs") // docs - tm.quickTranslate(lm,"checker.system.dataMessages","other","openticket:data-message") // message + //tm.quickTranslate(lm,"checker.system.headerOpenTicket","other","opendiscord:header-openticket") //OPEN TICKET (ignore) + tm.quickTranslate(lm,"checker.system.typeError","other","opendiscord:type-error") // [ERROR] (ignore) + tm.quickTranslate(lm,"checker.system.typeWarning","other","opendiscord:type-warning") // [WARNING] (ignore) + tm.quickTranslate(lm,"checker.system.typeInfo","other","opendiscord:type-info") // [INFO] (ignore) + tm.quickTranslate(lm,"checker.system.headerConfigChecker","other","opendiscord:header-configchecker") // CONFIG CHECKER + tm.quickTranslate(lm,"checker.system.headerDescription","other","opendiscord:header-description") // check for errors in your config files! + tm.quickTranslate(lm,"checker.system.footerError","other","opendiscord:footer-error") // the bot won't start until all {0}'s are fixed! + tm.quickTranslate(lm,"checker.system.footerWarning","other","opendiscord:footer-warning") // it's recommended to fix all {0}'s before starting! + tm.quickTranslate(lm,"checker.system.footerSupport","other","opendiscord:footer-support") // SUPPORT: {0} - DOCS: {1} + tm.quickTranslate(lm,"checker.system.compactInformation","other","opendiscord:compact-information") // use {0} for more information! + tm.quickTranslate(lm,"checker.system.dataPath","other","opendiscord:data-path") // path + tm.quickTranslate(lm,"checker.system.dataDocs","other","opendiscord:data-docs") // docs + tm.quickTranslate(lm,"checker.system.dataMessages","other","opendiscord:data-message") // message } export const registerDefaultCheckerMessageTranslations = (tm:api.ODCheckerTranslationRegister_Default,lm:api.ODLanguageManager_Default) => { //STRUCTURES - tm.quickTranslate(lm,"checker.messages.invalidType","message","openticket:invalid-type") // This property needs to be the type: {0}! - tm.quickTranslate(lm,"checker.messages.propertyMissing","message","openticket:property-missing") // The property {0} is missing from this object! - tm.quickTranslate(lm,"checker.messages.propertyOptional","message","openticket:property-optional") // The property {0} is optional in this object! - tm.quickTranslate(lm,"checker.messages.objectDisabled","message","openticket:object-disabled") // This object is disabled, enable it using {0}! - tm.quickTranslate(lm,"checker.messages.nullInvalid","message","openticket:null-invalid") // This property can't be null! - tm.quickTranslate(lm,"checker.messages.switchInvalidType","message","openticket:switch-invalid-type") // This needs to be one of the following types: {0}! - tm.quickTranslate(lm,"checker.messages.objectSwitchInvalid","message","openticket:object-switch-invalid-type") // This object needs to be one of the following types: {0}! + tm.quickTranslate(lm,"checker.messages.invalidType","message","opendiscord:invalid-type") // This property needs to be the type: {0}! + tm.quickTranslate(lm,"checker.messages.propertyMissing","message","opendiscord:property-missing") // The property {0} is missing from this object! + tm.quickTranslate(lm,"checker.messages.propertyOptional","message","opendiscord:property-optional") // The property {0} is optional in this object! + tm.quickTranslate(lm,"checker.messages.objectDisabled","message","opendiscord:object-disabled") // This object is disabled, enable it using {0}! + tm.quickTranslate(lm,"checker.messages.nullInvalid","message","opendiscord:null-invalid") // This property can't be null! + tm.quickTranslate(lm,"checker.messages.switchInvalidType","message","opendiscord:switch-invalid-type") // This needs to be one of the following types: {0}! + tm.quickTranslate(lm,"checker.messages.objectSwitchInvalid","message","opendiscord:object-switch-invalid-type") // This object needs to be one of the following types: {0}! - tm.quickTranslate(lm,"checker.messages.stringTooShort","message","openticket:string-too-short") // This string can't be shorter than {0} characters! - tm.quickTranslate(lm,"checker.messages.stringTooLong","message","openticket:string-too-long") // This string can't be longer than {0} characters! - tm.quickTranslate(lm,"checker.messages.stringLengthInvalid","message","openticket:string-length-invalid") // This string needs to be {0} characters long! - tm.quickTranslate(lm,"checker.messages.stringStartsWith","message","openticket:string-starts-with") // This string needs to start with {0}! - tm.quickTranslate(lm,"checker.messages.stringEndsWith","message","openticket:string-ends-with") // This string needs to end with {0}! - tm.quickTranslate(lm,"checker.messages.stringContains","message","openticket:string-contains") // This string needs to contain {0}! - tm.quickTranslate(lm,"checker.messages.stringChoices","message","openticket:string-choices") // This string can only be one of the following values: {0}! - tm.quickTranslate(lm,"checker.messages.stringRegex","message","openticket:string-regex") // This string is invalid! + tm.quickTranslate(lm,"checker.messages.stringTooShort","message","opendiscord:string-too-short") // This string can't be shorter than {0} characters! + tm.quickTranslate(lm,"checker.messages.stringTooLong","message","opendiscord:string-too-long") // This string can't be longer than {0} characters! + tm.quickTranslate(lm,"checker.messages.stringLengthInvalid","message","opendiscord:string-length-invalid") // This string needs to be {0} characters long! + tm.quickTranslate(lm,"checker.messages.stringStartsWith","message","opendiscord:string-starts-with") // This string needs to start with {0}! + tm.quickTranslate(lm,"checker.messages.stringEndsWith","message","opendiscord:string-ends-with") // This string needs to end with {0}! + tm.quickTranslate(lm,"checker.messages.stringContains","message","opendiscord:string-contains") // This string needs to contain {0}! + tm.quickTranslate(lm,"checker.messages.stringChoices","message","opendiscord:string-choices") // This string can only be one of the following values: {0}! + tm.quickTranslate(lm,"checker.messages.stringRegex","message","opendiscord:string-regex") // This string is invalid! - tm.quickTranslate(lm,"checker.messages.numberTooShort","message","openticket:number-too-short") // This number can't be shorter than {0} characters! - tm.quickTranslate(lm,"checker.messages.numberTooLong","message","openticket:number-too-long") // This number can't be longer than {0} characters! - tm.quickTranslate(lm,"checker.messages.numberLengthInvalid","message","openticket:number-length-invalid") // This number needs to be {0} characters long! - tm.quickTranslate(lm,"checker.messages.numberTooSmall","message","openticket:number-too-small") // This number needs to be at least {0}! - tm.quickTranslate(lm,"checker.messages.numberTooLarge","message","openticket:number-too-large") // This number needs to be at most {0}! - tm.quickTranslate(lm,"checker.messages.numberNotEqual","message","openticket:number-not-equal") // This number needs to be {0}! - tm.quickTranslate(lm,"checker.messages.numberStep","message","openticket:number-step") // This number needs to be a multiple of {0}! - tm.quickTranslate(lm,"checker.messages.numberStepOffset","message","openticket:number-step-offset") // This number needs to be a multiple of {0} starting with {1}! - tm.quickTranslate(lm,"checker.messages.numberStartsWith","message","openticket:number-starts-with") // This number needs to start with {0}! - tm.quickTranslate(lm,"checker.messages.numberEndsWith","message","openticket:number-ends-with") // This number needs to end with {0}! - tm.quickTranslate(lm,"checker.messages.numberContains","message","openticket:number-contains") // This number needs to contain {0}! - tm.quickTranslate(lm,"checker.messages.numberChoices","message","openticket:number-choices") // This number can only be one of the following values: {0}! - tm.quickTranslate(lm,"checker.messages.numberFloat","message","openticket:number-float") // This number can't be a decimal! - tm.quickTranslate(lm,"checker.messages.numberNegative","message","openticket:number-negative") // This number can't be negative! - tm.quickTranslate(lm,"checker.messages.numberPositive","message","openticket:number-positive") // This number can't be positive! - tm.quickTranslate(lm,"checker.messages.numberZero","message","openticket:number-zero") // This number can't be zero! + tm.quickTranslate(lm,"checker.messages.numberTooShort","message","opendiscord:number-too-short") // This number can't be shorter than {0} characters! + tm.quickTranslate(lm,"checker.messages.numberTooLong","message","opendiscord:number-too-long") // This number can't be longer than {0} characters! + tm.quickTranslate(lm,"checker.messages.numberLengthInvalid","message","opendiscord:number-length-invalid") // This number needs to be {0} characters long! + tm.quickTranslate(lm,"checker.messages.numberTooSmall","message","opendiscord:number-too-small") // This number needs to be at least {0}! + tm.quickTranslate(lm,"checker.messages.numberTooLarge","message","opendiscord:number-too-large") // This number needs to be at most {0}! + tm.quickTranslate(lm,"checker.messages.numberNotEqual","message","opendiscord:number-not-equal") // This number needs to be {0}! + tm.quickTranslate(lm,"checker.messages.numberStep","message","opendiscord:number-step") // This number needs to be a multiple of {0}! + tm.quickTranslate(lm,"checker.messages.numberStepOffset","message","opendiscord:number-step-offset") // This number needs to be a multiple of {0} starting with {1}! + tm.quickTranslate(lm,"checker.messages.numberStartsWith","message","opendiscord:number-starts-with") // This number needs to start with {0}! + tm.quickTranslate(lm,"checker.messages.numberEndsWith","message","opendiscord:number-ends-with") // This number needs to end with {0}! + tm.quickTranslate(lm,"checker.messages.numberContains","message","opendiscord:number-contains") // This number needs to contain {0}! + tm.quickTranslate(lm,"checker.messages.numberChoices","message","opendiscord:number-choices") // This number can only be one of the following values: {0}! + tm.quickTranslate(lm,"checker.messages.numberFloat","message","opendiscord:number-float") // This number can't be a decimal! + tm.quickTranslate(lm,"checker.messages.numberNegative","message","opendiscord:number-negative") // This number can't be negative! + tm.quickTranslate(lm,"checker.messages.numberPositive","message","opendiscord:number-positive") // This number can't be positive! + tm.quickTranslate(lm,"checker.messages.numberZero","message","opendiscord:number-zero") // This number can't be zero! - tm.quickTranslate(lm,"checker.messages.booleanTrue","message","openticket:boolean-true") // This boolean can't be true! - tm.quickTranslate(lm,"checker.messages.booleanFalse","message","openticket:boolean-false") // This boolean can't be false! + tm.quickTranslate(lm,"checker.messages.booleanTrue","message","opendiscord:boolean-true") // This boolean can't be true! + tm.quickTranslate(lm,"checker.messages.booleanFalse","message","opendiscord:boolean-false") // This boolean can't be false! - tm.quickTranslate(lm,"checker.messages.arrayEmptyDisabled","message","openticket:array-empty-disabled") // This array isn't allowed to be empty! - tm.quickTranslate(lm,"checker.messages.arrayEmptyRequired","message","openticket:array-empty-required") // This array is required to be empty! - tm.quickTranslate(lm,"checker.messages.arrayTooShort","message","openticket:array-too-short") // This array needs to have a length of at least {0}! - tm.quickTranslate(lm,"checker.messages.arrayTooLong","message","openticket:array-too-long") // This array needs to have a length of at most {0}! - tm.quickTranslate(lm,"checker.messages.arrayLengthInvalid","message","openticket:array-length-invalid") // This array needs to have a length of {0}! - tm.quickTranslate(lm,"checker.messages.arrayInvalidTypes","message","openticket:array-invalid-types") // This array can only contain the following types: {0}! - tm.quickTranslate(lm,"checker.messages.arrayDouble","message","openticket:array-double") // This array doesn't allow the same value twice! + tm.quickTranslate(lm,"checker.messages.arrayEmptyDisabled","message","opendiscord:array-empty-disabled") // This array isn't allowed to be empty! + tm.quickTranslate(lm,"checker.messages.arrayEmptyRequired","message","opendiscord:array-empty-required") // This array is required to be empty! + tm.quickTranslate(lm,"checker.messages.arrayTooShort","message","opendiscord:array-too-short") // This array needs to have a length of at least {0}! + tm.quickTranslate(lm,"checker.messages.arrayTooLong","message","opendiscord:array-too-long") // This array needs to have a length of at most {0}! + tm.quickTranslate(lm,"checker.messages.arrayLengthInvalid","message","opendiscord:array-length-invalid") // This array needs to have a length of {0}! + tm.quickTranslate(lm,"checker.messages.arrayInvalidTypes","message","opendiscord:array-invalid-types") // This array can only contain the following types: {0}! + tm.quickTranslate(lm,"checker.messages.arrayDouble","message","opendiscord:array-double") // This array doesn't allow the same value twice! - tm.quickTranslate(lm,"checker.messages.discordInvalidId","message","openticket:discord-invalid-id") // This is an invalid discord {0} id! - tm.quickTranslate(lm,"checker.messages.discordInvalidIdOptions","message","openticket:discord-invalid-id-options") // This is an invalid discord {0} id! You can also use one of these: {1}! - tm.quickTranslate(lm,"checker.messages.discordInvalidToken","message","openticket:discord-invalid-token") // This is an invalid discord token (syntactically)! - tm.quickTranslate(lm,"checker.messages.colorInvalid","message","openticket:color-invalid") // This is an invalid hex color! - tm.quickTranslate(lm,"checker.messages.emojiTooShort","message","openticket:emoji-too-short") // This string needs to have at least {0} emoji's! - tm.quickTranslate(lm,"checker.messages.emojiTooLong","message","openticket:emoji-too-long") // This string needs to have at most {0} emoji's! - tm.quickTranslate(lm,"checker.messages.emojiCustom","message","openticket:emoji-custom") // This emoji can't be a custom discord emoji! - tm.quickTranslate(lm,"checker.messages.emojiInvalid","message","openticket:emoji-invalid") // This is an invalid emoji! - tm.quickTranslate(lm,"checker.messages.urlInvalid","message","openticket:url-invalid") // This url is invalid! - tm.quickTranslate(lm,"checker.messages.urlInvalidHttp","message","openticket:url-invalid-http") // This url can only use the https:// protocol! - tm.quickTranslate(lm,"checker.messages.urlInvalidProtocol","message","openticket:url-invalid-protocol") // This url can only use the http:// & https:// protocols! - tm.quickTranslate(lm,"checker.messages.urlInvalidHostname","message","openticket:url-invalid-hostname") // This url has a disallowed hostname! - tm.quickTranslate(lm,"checker.messages.urlInvalidExtension","message","openticket:url-invalid-extension") // This url has an invalid extension! Choose between: {0}! - tm.quickTranslate(lm,"checker.messages.urlInvalidPath","message","openticket:url-invalid-path") // This url has an invalid path! - tm.quickTranslate(lm,"checker.messages.idNotUnique","message","openticket:id-not-unique") // This id isn't unique, use another id instead! - tm.quickTranslate(lm,"checker.messages.idNonExistent","message","openticket:id-non-existent") // The id {0} doesn't exist! + tm.quickTranslate(lm,"checker.messages.discordInvalidId","message","opendiscord:discord-invalid-id") // This is an invalid discord {0} id! + tm.quickTranslate(lm,"checker.messages.discordInvalidIdOptions","message","opendiscord:discord-invalid-id-options") // This is an invalid discord {0} id! You can also use one of these: {1}! + tm.quickTranslate(lm,"checker.messages.discordInvalidToken","message","opendiscord:discord-invalid-token") // This is an invalid discord token (syntactically)! + tm.quickTranslate(lm,"checker.messages.colorInvalid","message","opendiscord:color-invalid") // This is an invalid hex color! + tm.quickTranslate(lm,"checker.messages.emojiTooShort","message","opendiscord:emoji-too-short") // This string needs to have at least {0} emoji's! + tm.quickTranslate(lm,"checker.messages.emojiTooLong","message","opendiscord:emoji-too-long") // This string needs to have at most {0} emoji's! + tm.quickTranslate(lm,"checker.messages.emojiCustom","message","opendiscord:emoji-custom") // This emoji can't be a custom discord emoji! + tm.quickTranslate(lm,"checker.messages.emojiInvalid","message","opendiscord:emoji-invalid") // This is an invalid emoji! + tm.quickTranslate(lm,"checker.messages.urlInvalid","message","opendiscord:url-invalid") // This url is invalid! + tm.quickTranslate(lm,"checker.messages.urlInvalidHttp","message","opendiscord:url-invalid-http") // This url can only use the https:// protocol! + tm.quickTranslate(lm,"checker.messages.urlInvalidProtocol","message","opendiscord:url-invalid-protocol") // This url can only use the http:// & https:// protocols! + tm.quickTranslate(lm,"checker.messages.urlInvalidHostname","message","opendiscord:url-invalid-hostname") // This url has a disallowed hostname! + tm.quickTranslate(lm,"checker.messages.urlInvalidExtension","message","opendiscord:url-invalid-extension") // This url has an invalid extension! Choose between: {0}! + tm.quickTranslate(lm,"checker.messages.urlInvalidPath","message","opendiscord:url-invalid-path") // This url has an invalid path! + tm.quickTranslate(lm,"checker.messages.idNotUnique","message","opendiscord:id-not-unique") // This id isn't unique, use another id instead! + tm.quickTranslate(lm,"checker.messages.idNonExistent","message","opendiscord:id-non-existent") // The id {0} doesn't exist! } export const registerDefaultCheckerCustomTranslations = (tm:api.ODCheckerTranslationRegister_Default,lm:api.ODLanguageManager_Default) => { //CUSTOM - tm.quickTranslate(lm,"checker.messages.invalidLanguage","message","openticket:invalid-language") // This is an invalid language! - tm.quickTranslate(lm,"checker.messages.invalidButton","message","openticket:invalid-button") // This button needs to have at least an {0} or {1}! - tm.quickTranslate(lm,"checker.messages.unusedOption","message","openticket:unused-option") // The option {0} isn't used anywhere! - tm.quickTranslate(lm,"checker.messages.unusedQuestion","message","openticket:unused-question") // The question {0} isn't used anywhere! - tm.quickTranslate(lm,"checker.messages.dropdownOption","message","openticket:dropdown-option") // A panel with dropdown enabled can only contain options of the 'ticket' type! + tm.quickTranslate(lm,"checker.messages.invalidLanguage","message","opendiscord:invalid-language") // This is an invalid language! + tm.quickTranslate(lm,"checker.messages.invalidButton","message","opendiscord:invalid-button") // This button needs to have at least an {0} or {1}! + tm.quickTranslate(lm,"checker.messages.unusedOption","message","opendiscord:unused-option") // The option {0} isn't used anywhere! + tm.quickTranslate(lm,"checker.messages.unusedQuestion","message","opendiscord:unused-question") // The question {0} isn't used anywhere! + tm.quickTranslate(lm,"checker.messages.dropdownOption","message","opendiscord:dropdown-option") // A panel with dropdown enabled can only contain options of the 'ticket' type! //TODO TRANSLATION!!! - //tm.quickTranslate(lm,"checker.messages.TODO","message","openticket:invalid-version") // The version specified in your config is invalid! Make sure you have updated it to the latest version! + //tm.quickTranslate(lm,"checker.messages.TODO","message","opendiscord:invalid-version") // The version specified in your config is invalid! Make sure you have updated it to the latest version! } //UTILITY FUNCTIONS const createMsgStructure = (id:api.ODValidId) => { return new api.ODCheckerObjectStructure(id,{children:[ - {key:"dm",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:msg-dm",{})}, - {key:"logs",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:msg-logs",{})}, + {key:"dm",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:msg-dm",{})}, + {key:"logs",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:msg-logs",{})}, ]}) } const createTicketEmbedStructure = (id:api.ODValidId) => { return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[ - {key:"title",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-embed-text",{maxLength:256})}, - {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-embed-description",{maxLength:4096})}, - {key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:ticket-embed-color",true,true)}, + {key:"title",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-text",{maxLength:256})}, + {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-description",{maxLength:4096})}, + {key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:ticket-embed-color",true,true)}, - {key:"image",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:ticket-embed-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, - {key:"thumbnail",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:ticket-embed-thumbnail",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, - {key:"fields",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("openticket:ticket-embed-fields",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:ticket-embed-fields",{children:[ - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-embed-field-name",{minLength:1,maxLength:256})}, - {key:"value",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-embed-field-value",{minLength:1,maxLength:1024})}, - {key:"inline",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-embed-field-inline",{})} + {key:"image",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:ticket-embed-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, + {key:"thumbnail",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:ticket-embed-thumbnail",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, + {key:"fields",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("opendiscord:ticket-embed-fields",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("opendiscord:ticket-embed-fields",{children:[ + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-field-name",{minLength:1,maxLength:256})}, + {key:"value",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-field-value",{minLength:1,maxLength:1024})}, + {key:"inline",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-field-inline",{})} ]})})}, - {key:"timestamp",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-embed-timestamp",{})} + {key:"timestamp",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-timestamp",{})} ]})}) } const createTicketPingStructure = (id:api.ODValidId) => { return new api.ODCheckerObjectStructure(id,{children:[ - {key:"@here",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-ping-here",{})}, - {key:"@everyone",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-ping-everyone",{})}, - {key:"custom",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:ticket-ping-custom","role",[],{allowDoubles:false})}, + {key:"@here",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-here",{})}, + {key:"@everyone",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-everyone",{})}, + {key:"custom",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ping-custom","role",[],{allowDoubles:false})}, ]}) } const createPanelEmbedStructure = (id:api.ODValidId) => { return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[ - {key:"title",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-embed-text",{maxLength:256})}, - {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-embed-description",{maxLength:4096})}, - {key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:panel-embed-color",true,true)}, - {key:"url",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:panel-embed-url",true,{allowHttp:false})}, + {key:"title",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-text",{maxLength:256})}, + {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-description",{maxLength:4096})}, + {key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:panel-embed-color",true,true)}, + {key:"url",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:panel-embed-url",true,{allowHttp:false})}, - {key:"image",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:panel-embed-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, - {key:"thumbnail",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:panel-embed-thumbnail",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, + {key:"image",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:panel-embed-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, + {key:"thumbnail",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:panel-embed-thumbnail",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, - {key:"footer",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-embed-footer",{maxLength:2048})}, - {key:"fields",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("openticket:panel-embed-fields",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:panel-embed-fields",{children:[ - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-embed-field-name",{minLength:1,maxLength:256})}, - {key:"value",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-embed-field-value",{minLength:1,maxLength:1024})}, - {key:"inline",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-embed-field-inline",{})} + {key:"footer",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-footer",{maxLength:2048})}, + {key:"fields",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("opendiscord:panel-embed-fields",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("opendiscord:panel-embed-fields",{children:[ + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-field-name",{minLength:1,maxLength:256})}, + {key:"value",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-field-value",{minLength:1,maxLength:1024})}, + {key:"inline",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-embed-field-inline",{})} ]})})}, - {key:"timestamp",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-embed-timestamp",{})} + {key:"timestamp",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-embed-timestamp",{})} ]})}) } function loadFromEnv(){ - const generalConfig = opendiscord.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("opendiscord:general") if (generalConfig.data && generalConfig.data.tokenFromENV && typeof generalConfig.data.tokenFromENV == "boolean") return generalConfig.data.tokenFromENV else return false } //STRUCTURES -export const defaultGeneralStructure = new api.ODCheckerObjectStructure("openticket:general",{children:[ +export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendiscord:general",{children:[ //STATUS - {key:"_INFO",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:info",{children:[ - {key:"support",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:info-support",{choices:["https://otdocs.dj-dj.be"]})}, - {key:"discord",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:info-discord",{choices:["https://discord.dj-dj.be"]})}, - {key:"version",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:info-version",{custom(checker,value,locationTrace,locationId,locationDocs) { + {key:"_INFO",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:info",{children:[ + {key:"support",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:info-support",{choices:["https://otdocs.dj-dj.be"]})}, + {key:"discord",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:info-discord",{choices:["https://discord.dj-dj.be"]})}, + {key:"version",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:info-version",{custom(checker,value,locationTrace,locationId,locationDocs) { const lt = checker.locationTraceDeref(locationTrace) if (typeof value != "string") return false - else if (value != "open-ticket-"+opendiscord.versions.get("openticket:version").toString()){ - checker.createMessage("openticket:invalid-version","warning","The version specified in your config is invalid! Make sure you have updated it to the latest version!",lt,null,[],locationId,locationDocs) + else if (value != "open-ticket-"+opendiscord.versions.get("opendiscord:version").toString()){ + checker.createMessage("opendiscord:invalid-version","warning","The version specified in your config is invalid! Make sure you have updated it to the latest version!",lt,null,[],locationId,locationDocs) return false }else return true },})}, ]})}, //BASIC - {key:"token",optional:false,priority:0,checker:(loadFromEnv()) ? new api.ODCheckerStringStructure("openticket:token-disabled",{}) : new api.ODCheckerCustomStructure_DiscordToken("openticket:token")}, - {key:"tokenFromENV",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:token-env",{})}, - {key:"mainColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:main-color",true,false)}, - {key:"language",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:language",{ + {key:"token",optional:false,priority:0,checker:(loadFromEnv()) ? new api.ODCheckerStringStructure("opendiscord:token-disabled",{}) : new api.ODCheckerCustomStructure_DiscordToken("opendiscord:token")}, + {key:"tokenFromENV",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:token-env",{})}, + {key:"mainColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:main-color",true,false)}, + {key:"language",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:language",{ custom:(checker,value,locationTrace,locationId,locationDocs) => { const lt = checker.locationTraceDeref(locationTrace) if (typeof value != "string") return false else if (!opendiscord.defaults.getDefault("languageList").includes(value)){ - checker.createMessage("openticket:invalid-language","error","This is an invalid language!",lt,null,[],locationId,locationDocs) + checker.createMessage("opendiscord:invalid-language","error","This is an invalid language!",lt,null,[],locationId,locationDocs) return false }else return true }, })}, - {key:"prefix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:prefix",{minLength:1})}, - {key:"serverId",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:server-id","server",false,[])}, - {key:"globalAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:global-admins","role",[],{allowDoubles:false})}, - {key:"slashCommands",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:slash-commands",{})}, - {key:"textCommands",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:text-commands",{})}, + {key:"prefix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:prefix",{minLength:1})}, + {key:"serverId",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:server-id","server",false,[])}, + {key:"globalAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:global-admins","role",[],{allowDoubles:false})}, + {key:"slashCommands",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:slash-commands",{})}, + {key:"textCommands",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:text-commands",{})}, //STATUS - {key:"status",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:status",{ + {key:"status",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:status",{ property:"enabled", enabledValue:true, - checker:new api.ODCheckerObjectStructure("openticket:status",{children:[ - {key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:status-type",{choices:["listening","watching","playing","custom"]})}, - {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:status-text",{minLength:1,maxLength:128})}, - {key:"status",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:status-type",{choices:["online","invisible","idle","dnd"]})}, + checker:new api.ODCheckerObjectStructure("opendiscord:status",{children:[ + {key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:status-type",{choices:["listening","watching","playing","custom"]})}, + {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:status-text",{minLength:1,maxLength:128})}, + {key:"status",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:status-type",{choices:["online","invisible","idle","dnd"]})}, ]}) })}, //SYSTEM - {key:"system",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:system",{children:[ - {key:"removeParticipantsOnClose",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:remove-participants-on-close",{})}, - {key:"replyOnTicketCreation",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:reply-on-ticket-creation",{})}, - {key:"replyOnReactionRole",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:reply-on-reaction-role",{})}, - {key:"useTranslatedConfigChecker",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:use-translated-config-checker",{})}, - {key:"preferSlashOverText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:prefer-slash-over-text",{})}, - {key:"sendErrorOnUnknownCommand",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:send-error-on-unknown-command",{})}, - {key:"questionFieldsInCodeBlock",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:question-fields-in-code-block",{})}, - {key:"disableVerifyBars",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:disable-verify-bars",{})}, - {key:"useRedErrorEmbeds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:use-red-error-embeds",{})}, - {key:"emojiStyle",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:emoji-style",{choices:["before","after","double","disabled"]})}, + {key:"system",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:system",{children:[ + {key:"removeParticipantsOnClose",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:remove-participants-on-close",{})}, + {key:"replyOnTicketCreation",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-ticket-creation",{})}, + {key:"replyOnReactionRole",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-reaction-role",{})}, + {key:"useTranslatedConfigChecker",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:use-translated-config-checker",{})}, + {key:"preferSlashOverText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:prefer-slash-over-text",{})}, + {key:"sendErrorOnUnknownCommand",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:send-error-on-unknown-command",{})}, + {key:"questionFieldsInCodeBlock",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:question-fields-in-code-block",{})}, + {key:"disableVerifyBars",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:disable-verify-bars",{})}, + {key:"useRedErrorEmbeds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:use-red-error-embeds",{})}, + {key:"emojiStyle",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:emoji-style",{choices:["before","after","double","disabled"]})}, - {key:"enableTicketClaimButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-ticket-claim-buttons",{})}, - {key:"enableTicketCloseButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-ticket-close-buttons",{})}, - {key:"enableTicketPinButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-ticket-pin-buttons",{})}, - {key:"enableTicketDeleteButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-ticket-delete-buttons",{})}, - {key:"enableTicketActionWithReason",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-ticket-action-with-reason",{})}, - {key:"enableDeleteWithoutTranscript",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:enable-delete-without-transcript",{})}, + {key:"enableTicketClaimButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-claim-buttons",{})}, + {key:"enableTicketCloseButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-close-buttons",{})}, + {key:"enableTicketPinButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-pin-buttons",{})}, + {key:"enableTicketDeleteButtons",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-delete-buttons",{})}, + {key:"enableTicketActionWithReason",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-action-with-reason",{})}, + {key:"enableDeleteWithoutTranscript",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:enable-delete-without-transcript",{})}, - {key:"logs",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:system-logs",{ + {key:"logs",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:system-logs",{ property:"enabled", enabledValue:true, - checker:new api.ODCheckerObjectStructure("openticket:system-logs",{children:[ - {key:"channel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:log-channel","channel",false,[])}, + checker:new api.ODCheckerObjectStructure("opendiscord:system-logs",{children:[ + {key:"channel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:log-channel","channel",false,[])}, ]}) })}, - {key:"limits",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:limits",{children:[ - {key:"globalMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:limits-global",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})}, - {key:"userMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:limits-user",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})} + {key:"limits",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:limits",{children:[ + {key:"globalMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:limits-global",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})}, + {key:"userMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:limits-user",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})} ]})})}, - {key:"permissions",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:system-permissions",{children:[ - {key:"help",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-help","role",false,["admin","everyone","none"])}, - {key:"panel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-panel","role",false,["admin","everyone","none"])}, - {key:"ticket",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-ticket","role",false,["admin","everyone","none"])}, - {key:"close",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-close","role",false,["admin","everyone","none"])}, - {key:"delete",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-delete","role",false,["admin","everyone","none"])}, - {key:"reopen",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-reopen","role",false,["admin","everyone","none"])}, - {key:"claim",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-claim","role",false,["admin","everyone","none"])}, - {key:"unclaim",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-unclaim","role",false,["admin","everyone","none"])}, - {key:"pin",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-pin","role",false,["admin","everyone","none"])}, - {key:"unpin",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-unpin","role",false,["admin","everyone","none"])}, - {key:"move",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-move","role",false,["admin","everyone","none"])}, - {key:"rename",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-rename","role",false,["admin","everyone","none"])}, - {key:"add",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-add","role",false,["admin","everyone","none"])}, - {key:"remove",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-remove","role",false,["admin","everyone","none"])}, - {key:"blacklist",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-blacklist","role",false,["admin","everyone","none"])}, - {key:"stats",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-stats","role",false,["admin","everyone","none"])}, - {key:"clear",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-clear","role",false,["admin","everyone","none"])}, - {key:"autoclose",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-autoclose","role",false,["admin","everyone","none"])}, - {key:"autodelete",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:permissions-autodelete","role",false,["admin","everyone","none"])} + {key:"permissions",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:system-permissions",{children:[ + {key:"help",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-help","role",false,["admin","everyone","none"])}, + {key:"panel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-panel","role",false,["admin","everyone","none"])}, + {key:"ticket",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-ticket","role",false,["admin","everyone","none"])}, + {key:"close",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-close","role",false,["admin","everyone","none"])}, + {key:"delete",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-delete","role",false,["admin","everyone","none"])}, + {key:"reopen",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-reopen","role",false,["admin","everyone","none"])}, + {key:"claim",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-claim","role",false,["admin","everyone","none"])}, + {key:"unclaim",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-unclaim","role",false,["admin","everyone","none"])}, + {key:"pin",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-pin","role",false,["admin","everyone","none"])}, + {key:"unpin",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-unpin","role",false,["admin","everyone","none"])}, + {key:"move",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-move","role",false,["admin","everyone","none"])}, + {key:"rename",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-rename","role",false,["admin","everyone","none"])}, + {key:"add",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-add","role",false,["admin","everyone","none"])}, + {key:"remove",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-remove","role",false,["admin","everyone","none"])}, + {key:"blacklist",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-blacklist","role",false,["admin","everyone","none"])}, + {key:"stats",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-stats","role",false,["admin","everyone","none"])}, + {key:"clear",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-clear","role",false,["admin","everyone","none"])}, + {key:"autoclose",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-autoclose","role",false,["admin","everyone","none"])}, + {key:"autodelete",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-autodelete","role",false,["admin","everyone","none"])} ]})}, - {key:"messages",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:system-permissions",{children:[ - {key:"creation",optional:false,priority:0,checker:createMsgStructure("openticket:msg-creation")}, - {key:"closing",optional:false,priority:0,checker:createMsgStructure("openticket:msg-closing")}, - {key:"deleting",optional:false,priority:0,checker:createMsgStructure("openticket:msg-deleting")}, - {key:"reopening",optional:false,priority:0,checker:createMsgStructure("openticket:msg-reopening")}, - {key:"claiming",optional:false,priority:0,checker:createMsgStructure("openticket:msg-claiming")}, - {key:"pinning",optional:false,priority:0,checker:createMsgStructure("openticket:msg-pinning")}, - {key:"adding",optional:false,priority:0,checker:createMsgStructure("openticket:msg-adding")}, - {key:"removing",optional:false,priority:0,checker:createMsgStructure("openticket:msg-removing")}, - {key:"renaming",optional:false,priority:0,checker:createMsgStructure("openticket:msg-renaming")}, - {key:"moving",optional:false,priority:0,checker:createMsgStructure("openticket:msg-moving")}, - {key:"blacklisting",optional:false,priority:0,checker:createMsgStructure("openticket:msg-blacklisting")}, - {key:"roleAdding",optional:false,priority:0,checker:createMsgStructure("openticket:msg-role-adding")}, - {key:"roleRemoving",optional:false,priority:0,checker:createMsgStructure("openticket:msg-role-removing")} + {key:"messages",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:system-permissions",{children:[ + {key:"creation",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-creation")}, + {key:"closing",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-closing")}, + {key:"deleting",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-deleting")}, + {key:"reopening",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-reopening")}, + {key:"claiming",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-claiming")}, + {key:"pinning",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-pinning")}, + {key:"adding",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-adding")}, + {key:"removing",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-removing")}, + {key:"renaming",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-renaming")}, + {key:"moving",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-moving")}, + {key:"blacklisting",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-blacklisting")}, + {key:"roleAdding",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-role-adding")}, + {key:"roleRemoving",optional:false,priority:0,checker:createMsgStructure("opendiscord:msg-role-removing")} ]})}, ]})} ]}) -export const defaultOptionsStructure = new api.ODCheckerArrayStructure("openticket:options",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectSwitchStructure("openticket:options",{objects:[ +export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendiscord:options",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectSwitchStructure("opendiscord:options",{objects:[ //TICKET - {name:"ticket",priority:0,properties:[{key:"type",value:"ticket"}],checker:new api.ODCheckerObjectStructure("openticket:ticket",{children:[ - {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:ticket-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-name",{minLength:2,maxLength:50})}, - {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-description",{maxLength:256})}, + {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:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-description",{maxLength:256})}, //TICKET BUTTON - {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-button",{children:[ - {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("openticket:ticket-button-emoji",0,1,true)}, - {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:80})}, - {key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-color",{choices:["gray","red","green","blue"]})}, + {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[ + {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true)}, + {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80})}, + {key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-color",{choices:["gray","red","green","blue"]})}, ],custom:(checker,value,locationTrace,locationId,locationDocs) => { const lt = checker.locationTraceDeref(locationTrace) //check if emoji & label exists if (typeof value != "object") return false else if (value && value["emoji"].length < 1 && value["label"].length < 1){ //label & emoji are both empty - checker.createMessage("openticket:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs) + checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs) return false }else return true }})}, //TICKET ADMINS - {key:"ticketAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:ticket-ticket-admins","role",[],{allowDoubles:false})}, - {key:"readonlyAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:ticket-readonly-admins","role",[],{allowDoubles:false})}, - {key:"allowCreationByBlacklistedUsers",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-allow-blacklisted-users",{})}, - {key:"questions",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("openticket:option-questions","openticket","question-ids","question-ids-used",{allowDoubles:false,maxLength:5})}, + {key:"ticketAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ticket-admins","role",[],{allowDoubles:false})}, + {key:"readonlyAdmins",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-readonly-admins","role",[],{allowDoubles:false})}, + {key:"allowCreationByBlacklistedUsers",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-allow-blacklisted-users",{})}, + {key:"questions",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:option-questions","openticket","question-ids","question-ids-used",{allowDoubles:false,maxLength:5})}, //TICKET CHANNEL - {key:"channel",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-channel",{children:[ - {key:"prefix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-channel-prefix",{maxLength:25,regex:/^[^\s]*$/})}, - {key:"suffix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-channel-suffix",{choices:["user-name","user-id","random-number","random-hex","counter-dynamic","counter-fixed"]})}, + {key:"channel",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel",{children:[ + {key:"prefix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-prefix",{maxLength:25,regex:/^[^\s]*$/})}, + {key:"suffix",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-suffix",{choices:["user-name","user-id","random-number","random-hex","counter-dynamic","counter-fixed"]})}, - {key:"category",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:ticket-channel-category","category",true,[])}, - {key:"closedCategory",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:ticket-channel-closed-category","category",true,[])}, - {key:"backupCategory",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:ticket-channel-backup-category","category",true,[])}, - {key:"claimedCategory",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("openticket:ticket-channel-claimed-category",{allowDoubles:false,allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:ticket-channel-claimed-category",{children:[ - {key:"user",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:ticket-channel-claimed-user","user",false,[])}, - {key:"category",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:ticket-channel-claimed-category","category",false,[])} + {key:"category",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-category","category",true,[])}, + {key:"closedCategory",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-closed-category","category",true,[])}, + {key:"backupCategory",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-backup-category","category",true,[])}, + {key:"claimedCategory",optional:false,priority:0,checker:new api.ODCheckerArrayStructure("opendiscord:ticket-channel-claimed-category",{allowDoubles:false,allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel-claimed-category",{children:[ + {key:"user",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-claimed-user","user",false,[])}, + {key:"category",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-claimed-category","category",false,[])} ]})})}, - {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-channel-description",{})}, + {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-description",{})}, ]})}, //DM MESSAGE - {key:"dmMessage",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:ticket-dm-message",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:ticket-dm-message",{children:[ - {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-message-text",{maxLength:4096})}, - {key:"embed",optional:false,priority:0,checker:createTicketEmbedStructure("openticket:ticket-message-embed")} + {key:"dmMessage",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-dm-message",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-dm-message",{children:[ + {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-message-text",{maxLength:4096})}, + {key:"embed",optional:false,priority:0,checker:createTicketEmbedStructure("opendiscord:ticket-message-embed")} ]})})}, //TICKET MESSAGE - {key:"ticketMessage",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:ticket-message",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:ticket-message",{children:[ - {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-message-text",{maxLength:4096})}, - {key:"embed",optional:false,priority:0,checker:createTicketEmbedStructure("openticket:ticket-message-embed")}, - {key:"ping",optional:false,priority:0,checker:createTicketPingStructure("openticket:ticket-message-ping")} + {key:"ticketMessage",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-message",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-message",{children:[ + {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-message-text",{maxLength:4096})}, + {key:"embed",optional:false,priority:0,checker:createTicketEmbedStructure("opendiscord:ticket-message-embed")}, + {key:"ping",optional:false,priority:0,checker:createTicketPingStructure("opendiscord:ticket-message-ping")} ]})})}, //AUTOCLOSE - {key:"autoclose",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-autoclose",{children:[ - {key:"enableInactiveHours",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autoclose-enable-hours",{})}, - {key:"inactiveHours",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:ticket-autoclose-hours",{zeroAllowed:false,negativeAllowed:false,floatAllowed:true,min:1,max:8544})}, - {key:"enableUserLeave",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autoclose-enable-leave",{})}, - {key:"disableOnClaim",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autoclose-disable-claim",{})}, + {key:"autoclose",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-autoclose",{children:[ + {key:"enableInactiveHours",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autoclose-enable-hours",{})}, + {key:"inactiveHours",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-autoclose-hours",{zeroAllowed:false,negativeAllowed:false,floatAllowed:true,min:1,max:8544})}, + {key:"enableUserLeave",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autoclose-enable-leave",{})}, + {key:"disableOnClaim",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autoclose-disable-claim",{})}, ]})}, //AUTODELETE - {key:"autodelete",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-autodelete",{children:[ - {key:"enableInactiveDays",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autodelete-enable-days",{})}, - {key:"inactiveDays",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:ticket-autodelete-days",{zeroAllowed:false,negativeAllowed:false,floatAllowed:true,min:1,max:356})}, - {key:"enableUserLeave",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autodelete-enable-leave",{})}, - {key:"disableOnClaim",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:ticket-autodelete-disable-claim",{})}, + {key:"autodelete",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-autodelete",{children:[ + {key:"enableInactiveDays",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autodelete-enable-days",{})}, + {key:"inactiveDays",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-autodelete-days",{zeroAllowed:false,negativeAllowed:false,floatAllowed:true,min:1,max:356})}, + {key:"enableUserLeave",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autodelete-enable-leave",{})}, + {key:"disableOnClaim",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-autodelete-disable-claim",{})}, ]})}, //COOLDOWN - {key:"cooldown",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:ticket-cooldown",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:ticket-cooldown",{children:[ - {key:"cooldownMinutes",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:ticket-cooldown-minutes",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1,max:512640})}, + {key:"cooldown",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-cooldown",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-cooldown",{children:[ + {key:"cooldownMinutes",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-cooldown-minutes",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1,max:512640})}, ]})})}, //LIMITS - {key:"limits",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:ticket-limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:ticket-limits",{children:[ - {key:"globalMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:ticket-limits-global",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})}, - {key:"userMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:ticket-limits-user",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})} + {key:"limits",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:ticket-limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-limits",{children:[ + {key:"globalMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-limits-global",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})}, + {key:"userMaximum",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:ticket-limits-user",{zeroAllowed:false,negativeAllowed:false,floatAllowed:false,min:1})} ]})})}, ]})}, //WEBSITE - {name:"website",priority:0,properties:[{key:"type",value:"website"}],checker:new api.ODCheckerObjectStructure("openticket:options-website",{children:[ - {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:website-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:website-name",{minLength:2,maxLength:50})}, - {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:website-description",{maxLength:256})}, + {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:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:website-description",{maxLength:256})}, //WEBSITE BUTTON - {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-button",{children:[ - {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("openticket:ticket-button-emoji",0,1,true)}, - {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:80})}, + {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[ + {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true)}, + {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80})}, ],custom:(checker,value,locationTrace,locationId,locationDocs) => { const lt = checker.locationTraceDeref(locationTrace) //check if emoji & label exists if (typeof value != "object") return false else if (value && value["emoji"].length < 1 && value["label"].length < 1){ //label & emoji are both empty - checker.createMessage("openticket:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs) + checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs) return false }else return true }})}, //WEBSITE URL - {key:"url",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:website-url",false,{allowHttp:false})}, + {key:"url",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:website-url",false,{allowHttp:false})}, ]})}, //REACTION ROLES - {name:"role",priority:0,properties:[{key:"type",value:"role"}],checker:new api.ODCheckerObjectStructure("openticket:options-role",{children:[ - {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:role-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:role-name",{minLength:2,maxLength:50})}, - {key:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:role-description",{maxLength:256})}, + {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:"description",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-description",{maxLength:256})}, //ROLE BUTTON - {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:ticket-button",{children:[ - {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("openticket:ticket-button-emoji",0,1,true)}, - {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-label",{maxLength:80})}, - {key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:ticket-button-color",{choices:["gray","red","green","blue"]})}, + {key:"button",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[ + {key:"emoji",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true)}, + {key:"label",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80})}, + {key:"color",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-color",{choices:["gray","red","green","blue"]})}, ],custom:(checker,value,locationTrace,locationId,locationDocs) => { const lt = checker.locationTraceDeref(locationTrace) //check if emoji & label exists if (typeof value != "object") return false else if (value && value["emoji"].length < 1 && value["label"].length < 1){ //label & emoji are both empty - checker.createMessage("openticket:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs) + checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs) return false }else return true }})}, //ROLE SETTINGS - {key:"roles",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:role-roles","role",[],{allowDoubles:false,minLength:1})}, - {key:"mode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:role-mode",{choices:["add","remove","add&remove"]})}, - {key:"removeRolesOnAdd",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("openticket:role-remove-roles","role",[],{allowDoubles:false})}, - {key:"addOnMemberJoin",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:role-add-on-join",{})}, + {key:"roles",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:role-roles","role",[],{allowDoubles:false,minLength:1})}, + {key:"mode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:role-mode",{choices:["add","remove","add&remove"]})}, + {key:"removeRolesOnAdd",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:role-remove-roles","role",[],{allowDoubles:false})}, + {key:"addOnMemberJoin",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:role-add-on-join",{})}, ]})}, ]})}) -export const defaultPanelsStructure = new api.ODCheckerArrayStructure("openticket:panels",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:panels",{children:[ - {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:panel-id","openticket","panel-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-name",{minLength:3,maxLength:50})}, - {key:"dropdown",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-dropdown",{})}, - {key:"options",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueIdArray("openticket:panel-options","openticket","option-ids","option-ids-used",{allowDoubles:false,maxLength:25})}, +export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendiscord:panels",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("opendiscord:panels",{children:[ + {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})}, //EMBED & TEXT - {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-text",{maxLength:4096})}, - {key:"embed",optional:false,priority:0,checker:createPanelEmbedStructure("openticket:panel-embed")}, + {key:"text",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-text",{maxLength:4096})}, + {key:"embed",optional:false,priority:0,checker:createPanelEmbedStructure("opendiscord:panel-embed")}, //SETTINGS - {key:"settings",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:panel-settings",{children:[ - {key:"dropdownPlaceholder",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-settings-placeholder",{maxLength:100})}, - {key:"enableMaxTicketsWarningInText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-settings-maxtickets-text",{})}, - {key:"enableMaxTicketsWarningInEmbed",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-settings-maxtickets-embed",{})}, + {key:"settings",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:panel-settings",{children:[ + {key:"dropdownPlaceholder",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-placeholder",{maxLength:100})}, + {key:"enableMaxTicketsWarningInText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-text",{})}, + {key:"enableMaxTicketsWarningInEmbed",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-embed",{})}, - {key:"describeOptionsLayout",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-settings-describe-layout",{choices:["simple","normal","detailed"]})}, - {key:"describeOptionsCustomTitle",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:panel-settings-describe-title",{maxLength:512})}, - {key:"describeOptionsInText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-settings-describe-text",{})}, - {key:"describeOptionsInEmbedFields",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-settings-describe-fields",{})}, - {key:"describeOptionsInEmbedDescription",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:panel-settings-describe-embed",{})}, + {key:"describeOptionsLayout",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-describe-layout",{choices:["simple","normal","detailed"]})}, + {key:"describeOptionsCustomTitle",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-describe-title",{maxLength:512})}, + {key:"describeOptionsInText",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-describe-text",{})}, + {key:"describeOptionsInEmbedFields",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-describe-fields",{})}, + {key:"describeOptionsInEmbedDescription",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-describe-embed",{})}, ]})}, ]})}) -export const defaultQuestionsStructure = new api.ODCheckerArrayStructure("openticket:questions",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("openticket:questions",{children:[ - {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("openticket:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, - {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:question-name",{minLength:3,maxLength:45})}, - {key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:question-type",{choices:["short","paragraph"]})}, +export const defaultQuestionsStructure = new api.ODCheckerArrayStructure("opendiscord:questions",{allowedTypes:["object"],propertyChecker:new api.ODCheckerObjectStructure("opendiscord:questions",{children:[ + {key:"id",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40})}, + {key:"name",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45})}, + {key:"type",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:question-type",{choices:["short","paragraph"]})}, - {key:"required",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:question-required",{})}, - {key:"placeholder",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:question-placeholder",{maxLength:100})}, + {key:"required",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{})}, + {key:"placeholder",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100})}, - {key:"length",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:question-length",{children:[ - {key:"min",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false})}, - {key:"max",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("openticket:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false})}, + {key:"length",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:question-length",{children:[ + {key:"min",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false})}, + {key:"max",optional:false,priority:0,checker:new api.ODCheckerNumberStructure("opendiscord:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false})}, ]})})}, ]})}) -export const defaultTranscriptsStructure = new api.ODCheckerObjectStructure("openticket:transcripts",{children:[ +export const defaultTranscriptsStructure = new api.ODCheckerObjectStructure("opendiscord:transcripts",{children:[ //GENERAL - {key:"general",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:transcripts-general",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:transcripts-general",{children:[ - {key:"enableChannel",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-enable-channel",{})}, - {key:"enableCreatorDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-enable-creator-dm",{})}, - {key:"enableParticipantDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-enable-participant-dm",{})}, - {key:"enableActiveAdminDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-enable-active-admin-dm",{})}, - {key:"enableEveryAdminDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-enable-every-admin-dm",{})}, + {key:"general",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-general",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-general",{children:[ + {key:"enableChannel",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-channel",{})}, + {key:"enableCreatorDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-creator-dm",{})}, + {key:"enableParticipantDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-participant-dm",{})}, + {key:"enableActiveAdminDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-active-admin-dm",{})}, + {key:"enableEveryAdminDM",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-enable-every-admin-dm",{})}, - {key:"channel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("openticket:transcripts-channel","channel",true,[])}, - {key:"mode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-mode",{choices:["html","text"]})}, + {key:"channel",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:transcripts-channel","channel",true,[])}, + {key:"mode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-mode",{choices:["html","text"]})}, ]})})}, //EMBED SETTINGS - {key:"embedSettings",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:transcripts-embed-settings",{children:[ - {key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-embed-color",false,true)}, - {key:"listAllParticipants",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-embed-list-participants",{})}, - {key:"includeTicketStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-embed-include-ticket-stats",{})}, + {key:"embedSettings",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-embed-settings",{children:[ + {key:"customColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-embed-color",false,true)}, + {key:"listAllParticipants",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-embed-list-participants",{})}, + {key:"includeTicketStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-embed-include-ticket-stats",{})}, ]})}, //TEXT STYLE - {key:"textTranscriptStyle",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:transcripts-text",{children:[ - {key:"layout",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-text-layout",{choices:["simple","normal","detailed"]})}, - {key:"includeStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-stats",{})}, - {key:"includeIds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-ids",{})}, - {key:"includeEmbeds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-embeds",{})}, - {key:"includeFiles",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-files",{})}, - {key:"includeBotMessages",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("openticket:transcripts-text-include-bots",{})}, + {key:"textTranscriptStyle",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-text",{children:[ + {key:"layout",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-text-layout",{choices:["simple","normal","detailed"]})}, + {key:"includeStats",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-stats",{})}, + {key:"includeIds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-ids",{})}, + {key:"includeEmbeds",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-embeds",{})}, + {key:"includeFiles",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-files",{})}, + {key:"includeBotMessages",optional:false,priority:0,checker:new api.ODCheckerBooleanStructure("opendiscord:transcripts-text-include-bots",{})}, - {key:"fileMode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-text-file-mode",{choices:["custom","channel-name","channel-id","user-name","user-id"]})}, - {key:"customFileName",optional:false,priority:0,checker:new api.ODCheckerStringStructure("openticket:transcripts-file-name",{maxLength:512,regex:/^[^\.#%&{}\\<>*?/!'":@`|=]*$/})}, + {key:"fileMode",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-text-file-mode",{choices:["custom","channel-name","channel-id","user-name","user-id"]})}, + {key:"customFileName",optional:false,priority:0,checker:new api.ODCheckerStringStructure("opendiscord:transcripts-file-name",{maxLength:512,regex:/^[^\.#%&{}\\<>*?/!'":@`|=]*$/})}, ]})}, //HTML STYLE - {key:"htmlTranscriptStyle",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("openticket:transcripts-html",{children:[ + {key:"htmlTranscriptStyle",optional:false,priority:0,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html",{children:[ //HTML BACKGROUND - {key:"background",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:transcripts-html-background",{property:"enableCustomBackground",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:transcripts-html-background",{children:[ - {key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-background-color",false,true)}, - {key:"backgroundImage",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:transcripts-html-background-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, + {key:"background",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-background",{property:"enableCustomBackground",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-background",{children:[ + {key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-background-color",false,true)}, + {key:"backgroundImage",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:transcripts-html-background-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp",".gif"]})}, ]})})}, //HTML HEADER - {key:"header",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:transcripts-html-header",{property:"enableCustomHeader",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:transcripts-html-header",{children:[ - {key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-header-bgcolor",false,false)}, - {key:"decoColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-header-decocolor",false,false)}, - {key:"textColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-header-textcolor",false,false)}, + {key:"header",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-header",{property:"enableCustomHeader",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-header",{children:[ + {key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-header-bgcolor",false,false)}, + {key:"decoColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-header-decocolor",false,false)}, + {key:"textColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-header-textcolor",false,false)}, ]})})}, //HTML STATS - {key:"stats",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:transcripts-html-stats",{property:"enableCustomStats",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:transcripts-html-stats",{children:[ - {key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-stats-bgcolor",false,false)}, - {key:"keyTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-stats-keycolor",false,false)}, - {key:"valueTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-stats-valuecolor",false,false)}, - {key:"hideBackgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-stats-hidebgcolor",false,false)}, - {key:"hideTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("openticket:transcripts-html-stats-hidecolor",false,false)}, + {key:"stats",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-stats",{property:"enableCustomStats",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-stats",{children:[ + {key:"backgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-bgcolor",false,false)}, + {key:"keyTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-keycolor",false,false)}, + {key:"valueTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-valuecolor",false,false)}, + {key:"hideBackgroundColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-hidebgcolor",false,false)}, + {key:"hideTextColor",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:transcripts-html-stats-hidecolor",false,false)}, ]})})}, //HTML FAVICON - {key:"favicon",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("openticket:transcripts-html-favicon",{property:"enableCustomFavicon",enabledValue:true,checker:new api.ODCheckerObjectStructure("openticket:transcripts-html-favicon",{children:[ - {key:"imageUrl",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("openticket:transcripts-html-favicon-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp"]})}, + {key:"favicon",optional:false,priority:0,checker:new api.ODCheckerEnabledObjectStructure("opendiscord:transcripts-html-favicon",{property:"enableCustomFavicon",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:transcripts-html-favicon",{children:[ + {key:"imageUrl",optional:false,priority:0,checker:new api.ODCheckerCustomStructure_UrlString("opendiscord:transcripts-html-favicon-image",true,{allowHttp:false,allowedExtensions:[".png",".jpg",".jpeg",".webp"]})}, ]})})}, ]})}, ]}) @@ -544,14 +544,14 @@ export const defaultUnusedOptionsFunction = (manager:api.ODCheckerManager, funct const usedOptionList: string[] = manager.storage.get("openticket","option-ids-used") if (!optionList || ! usedOptionList) return {valid:true,messages:[]} - const optionChecker = manager.get("openticket:options") + const optionChecker = manager.get("opendiscord:options") if (!optionChecker) return {valid:true,messages:[]} const final: api.ODCheckerMessage[] = [] optionList.forEach((id) => { if (!usedOptionList.includes(id)){ //id isn't used anywhere => create warning - final.push(functions.createMessage("openticket:options","openticket:unused-option",optionChecker.config.file,"warning",`The option "${id}" isn't used anywhere!`,[],null,[`"${id}"`],new api.ODId("openticket:unused-options"),null)) + final.push(functions.createMessage("opendiscord:options","opendiscord:unused-option",optionChecker.config.file,"warning",`The option "${id}" isn't used anywhere!`,[],null,[`"${id}"`],new api.ODId("opendiscord:unused-options"),null)) } }) @@ -563,14 +563,14 @@ export const defaultUnusedQuestionsFunction = (manager:api.ODCheckerManager, fun const usedQuestionList: string[] = manager.storage.get("openticket","question-ids-used") if (!questionList || ! usedQuestionList) return {valid:true,messages:[]} - const questionChecker = manager.get("openticket:questions") + const questionChecker = manager.get("opendiscord:questions") if (!questionChecker) return {valid:true,messages:[]} const final: api.ODCheckerMessage[] = [] questionList.forEach((id) => { if (!usedQuestionList.includes(id)){ //id isn't used anywhere => create warning - final.push(functions.createMessage("openticket:questions","openticket:unused-question",questionChecker.config.file,"warning",`The question "${id}" isn't used anywhere!`,[],null,[`"${id}"`],new api.ODId("openticket:unused-questions"),null)) + final.push(functions.createMessage("opendiscord:questions","opendiscord:unused-question",questionChecker.config.file,"warning",`The question "${id}" isn't used anywhere!`,[],null,[`"${id}"`],new api.ODId("opendiscord:unused-questions"),null)) } }) @@ -582,10 +582,10 @@ export const defaultDropdownOptionsFunction = (manager:api.ODCheckerManager, fun const panelList: string[] = manager.storage.get("openticket","panel-ids") if (!panelList) return {valid:true,messages:[]} - const panelConfig = opendiscord.configs.get("openticket:panels") + const panelConfig = opendiscord.configs.get("opendiscord:panels") if (!panelConfig) return {valid:true,messages:[]} - const optionConfig = opendiscord.configs.get("openticket:options") + const optionConfig = opendiscord.configs.get("opendiscord:options") if (!optionConfig) return {valid:true,messages:[]} const final: api.ODCheckerMessage[] = [] @@ -599,7 +599,7 @@ export const defaultDropdownOptionsFunction = (manager:api.ODCheckerManager, fun else return false })){ //give error when non-ticket options exist in dropdown panel! - final.push(functions.createMessage("openticket:panels","openticket:dropdown-option",panelConfig.file,"error","A panel with dropdown enabled can only contain options of the 'ticket' type!",[index,"options"],null,[],new api.ODId("openticket:dropdown-options"),null)) + final.push(functions.createMessage("opendiscord:panels","opendiscord:dropdown-option",panelConfig.file,"error","A panel with dropdown enabled can only contain options of the 'ticket' type!",[index,"options"],null,[],new api.ODId("opendiscord:dropdown-options"),null)) } }) diff --git a/src/data/framework/codeLoader.ts b/src/data/framework/codeLoader.ts index b253888..472f9fd 100644 --- a/src/data/framework/codeLoader.ts +++ b/src/data/framework/codeLoader.ts @@ -1,12 +1,12 @@ import {opendiscord, api, utilities} from "../../index" import * as discord from "discord.js" -const generalConfig = opendiscord.configs.get("openticket:general") -const globalDatabase = opendiscord.databases.get("openticket:global") -const userDatabase = opendiscord.databases.get("openticket:users") -const ticketDatabase = opendiscord.databases.get("openticket:tickets") -const statsDatabase = opendiscord.databases.get("openticket:stats") -const optionDatabase = opendiscord.databases.get("openticket:options") +const generalConfig = opendiscord.configs.get("opendiscord:general") +const globalDatabase = opendiscord.databases.get("opendiscord:global") +const userDatabase = opendiscord.databases.get("opendiscord:users") +const ticketDatabase = opendiscord.databases.get("opendiscord:tickets") +const statsDatabase = opendiscord.databases.get("opendiscord:stats") +const optionDatabase = opendiscord.databases.get("opendiscord:options") const mainServer = opendiscord.client.mainServer export const loadAllCode = async () => { @@ -22,28 +22,28 @@ export const loadAllCode = async () => { export const loadCommandErrorHandlingCode = async () => { //COMMAND ERROR HANDLING - opendiscord.code.add(new api.ODCode("openticket:command-error-handling",14,() => { + opendiscord.code.add(new api.ODCode("opendiscord:command-error-handling",14,() => { //invalid/missing options opendiscord.client.textCommands.onError(async (error) => { if (error.msg.channel.type == discord.ChannelType.GroupDM) return if (error.type == "invalid_option"){ - error.msg.channel.send((await opendiscord.builders.messages.getSafe("openticket:error-option-invalid").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) + error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-option-invalid").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) }else if (error.type == "missing_option"){ - error.msg.channel.send((await opendiscord.builders.messages.getSafe("openticket:error-option-missing").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) + error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-option-missing").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) }else if (error.type == "unknown_command" && generalConfig.data.system.sendErrorOnUnknownCommand){ - error.msg.channel.send((await opendiscord.builders.messages.getSafe("openticket:error-unknown-command").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) + error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-unknown-command").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message) } }) //responder timeout opendiscord.responders.commands.setTimeoutErrorCallback(async (instance,source) => { - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) },null) opendiscord.responders.buttons.setTimeoutErrorCallback(async (instance,source) => { - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) },null) opendiscord.responders.dropdowns.setTimeoutErrorCallback(async (instance,source) => { - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) },null) opendiscord.responders.modals.setTimeoutErrorCallback(async (instance,source) => { if (!instance.channel){ @@ -52,14 +52,14 @@ export const loadCommandErrorHandlingCode = async () => { }}) return } - instance.reply(await opendiscord.builders.messages.getSafe("openticket:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) + instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-responder-timeout").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user})) },null) })) } export const loadStartListeningInteractionsCode = async () => { //START LISTENING TO INTERACTIONS - opendiscord.code.add(new api.ODCode("openticket:start-listening-interactions",13,() => { + opendiscord.code.add(new api.ODCode("opendiscord:start-listening-interactions",13,() => { opendiscord.client.slashCommands.startListeningToInteractions() opendiscord.client.textCommands.startListeningToInteractions() })) @@ -69,11 +69,11 @@ export const loadDatabaseCleanersCode = async () => { if (!mainServer) return //PANEL DATABASE CLEANER - opendiscord.code.add(new api.ODCode("openticket:panel-database-cleaner",12,async () => { + opendiscord.code.add(new api.ODCode("opendiscord:panel-database-cleaner",12,async () => { const validPanels: string[] = [] //check global database for valid panel embeds - for (const panel of (await globalDatabase.getCategory("openticket:panel-update") ?? [])){ + for (const panel of (await globalDatabase.getCategory("opendiscord:panel-update") ?? [])){ if (!validPanels.includes(panel.key)){ try{ const splittedId = panel.key.split("_") @@ -84,70 +84,70 @@ export const loadDatabaseCleanersCode = async () => { } //remove all unused panels - for (const panel of (await globalDatabase.getCategory("openticket:panel-update") ?? [])){ + for (const panel of (await globalDatabase.getCategory("opendiscord:panel-update") ?? [])){ if (!validPanels.includes(panel.key)){ - await globalDatabase.delete("openticket:panel-update",panel.key) + await globalDatabase.delete("opendiscord:panel-update",panel.key) } } //delete panel from database on delete opendiscord.client.client.on("messageDelete",async (msg) => { - if (await globalDatabase.exists("openticket:panel-update",msg.channel.id+"_"+msg.id)){ - await globalDatabase.delete("openticket:panel-update",msg.channel.id+"_"+msg.id) + if (await globalDatabase.exists("opendiscord:panel-update",msg.channel.id+"_"+msg.id)){ + await globalDatabase.delete("opendiscord:panel-update",msg.channel.id+"_"+msg.id) } }) })) //SUFFIX DATABASE CLEANER - opendiscord.code.add(new api.ODCode("openticket:suffix-database-cleaner",11,async () => { + opendiscord.code.add(new api.ODCode("opendiscord:suffix-database-cleaner",11,async () => { const validSuffixCounters: string[] = [] const validSuffixHistories: string[] = [] //check global database for valid option suffix counters - for (const counter of (await globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ + for (const counter of (await globalDatabase.getCategory("opendiscord:option-suffix-counter") ?? [])){ if (!validSuffixCounters.includes(counter.key)){ if (opendiscord.options.exists(counter.key)) validSuffixCounters.push(counter.key) } } //check global database for valid option suffix histories - for (const history of (await globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ + for (const history of (await globalDatabase.getCategory("opendiscord:option-suffix-history") ?? [])){ if (!validSuffixHistories.includes(history.key)){ if (opendiscord.options.exists(history.key)) validSuffixHistories.push(history.key) } } //remove all unused suffix counters - for (const counter of (await globalDatabase.getCategory("openticket:option-suffix-counter") ?? [])){ + for (const counter of (await globalDatabase.getCategory("opendiscord:option-suffix-counter") ?? [])){ if (!validSuffixCounters.includes(counter.key)){ - await globalDatabase.delete("openticket:option-suffix-counter",counter.key) + await globalDatabase.delete("opendiscord:option-suffix-counter",counter.key) } } //remove all unused suffix histories - for (const history of (await globalDatabase.getCategory("openticket:option-suffix-history") ?? [])){ + for (const history of (await globalDatabase.getCategory("opendiscord:option-suffix-history") ?? [])){ if (!validSuffixHistories.includes(history.key)){ - await globalDatabase.delete("openticket:option-suffix-history",history.key) + await globalDatabase.delete("opendiscord:option-suffix-history",history.key) } } })) //OPTION DATABASE CLEANER - opendiscord.code.add(new api.ODCode("openticket:option-database-cleaner",10,async () => { + opendiscord.code.add(new api.ODCode("opendiscord:option-database-cleaner",10,async () => { //delete all unused options (async) - for (const option of (await optionDatabase.getCategory("openticket:used-option") ?? [])){ + for (const option of (await optionDatabase.getCategory("opendiscord:used-option") ?? [])){ if (!opendiscord.options.exists(option.key)){ //remove because option isn't loaded into memory (0 tickets require it) - await optionDatabase.delete("openticket:used-option",option.key) + await optionDatabase.delete("opendiscord:used-option",option.key) }else if (!opendiscord.tickets.getAll().some((ticket) => ticket.option.id.value == option.key)){ //remove when loaded into memory (0 tickets require it) - await optionDatabase.delete("openticket:used-option",option.key) + await optionDatabase.delete("opendiscord:used-option",option.key) } } })) //USER DATABASE CLEANER (full async/parallel because it takes a lot of time) - opendiscord.code.add(new api.ODCode("openticket:user-database-cleaner",9,() => { + opendiscord.code.add(new api.ODCode("opendiscord:user-database-cleaner",9,() => { utilities.runAsync(async () => { const validUsers: string[] = [] @@ -163,7 +163,7 @@ export const loadDatabaseCleanersCode = async () => { //check stats database for valid users for (const stat of (await statsDatabase.getAll())){ - if (stat.category.startsWith("openticket:user_")){ + if (stat.category.startsWith("opendiscord:user_")){ if (!validUsers.includes(stat.key)){ try{ const member = await mainServer.members.fetch(stat.key) @@ -182,7 +182,7 @@ export const loadDatabaseCleanersCode = async () => { //remove all unused stats for (const stat of (await statsDatabase.getAll())){ - if (stat.category.startsWith("openticket:user_")){ + if (stat.category.startsWith("opendiscord:user_")){ if (!validUsers.includes(stat.key)){ await statsDatabase.delete(stat.category,stat.key) } @@ -203,7 +203,7 @@ export const loadDatabaseCleanersCode = async () => { //remove unused stats for (const stat of (await statsDatabase.getAll())){ - if (stat.category.startsWith("openticket:user_")){ + if (stat.category.startsWith("opendiscord:user_")){ if (stat.key == member.id){ await statsDatabase.delete(stat.category,stat.key) } @@ -213,7 +213,7 @@ export const loadDatabaseCleanersCode = async () => { })) //TICKET DATABASE CLEANER - opendiscord.code.add(new api.ODCode("openticket:ticket-database-cleaner",8,async () => { + opendiscord.code.add(new api.ODCode("opendiscord:ticket-database-cleaner",8,async () => { const validTickets: string[] = [] //check ticket database for valid tickets @@ -228,7 +228,7 @@ export const loadDatabaseCleanersCode = async () => { //check stats database for valid tickets for (const stat of (await statsDatabase.getAll())){ - if (stat.category.startsWith("openticket:ticket_")){ + if (stat.category.startsWith("opendiscord:ticket_")){ if (!validTickets.includes(stat.key)){ try{ const channel = await opendiscord.client.fetchGuildTextChannel(mainServer,stat.key) @@ -248,7 +248,7 @@ export const loadDatabaseCleanersCode = async () => { //remove all unused stats for (const stat of (await statsDatabase.getAll())){ - if (stat.category.startsWith("openticket:ticket_")){ + if (stat.category.startsWith("opendiscord:ticket_")){ if (!validTickets.includes(stat.key)){ await statsDatabase.delete(stat.category,stat.key) } @@ -269,7 +269,7 @@ export const loadDatabaseCleanersCode = async () => { //remove unused stats for (const stat of (await statsDatabase.getAll())){ - if (stat.category.startsWith("openticket:ticket_")){ + if (stat.category.startsWith("opendiscord:ticket_")){ if (stat.key == channel.id){ await statsDatabase.delete(stat.category,stat.key) } @@ -281,9 +281,9 @@ export const loadDatabaseCleanersCode = async () => { export const loadPanelAutoUpdateCode = async () => { //PANEL AUTO UPDATE - opendiscord.code.add(new api.ODCode("openticket:panel-auto-update",7,async () => { - const globalDatabase = opendiscord.databases.get("openticket:global") - const panelIds = await globalDatabase.getCategory("openticket:panel-update") ?? [] + opendiscord.code.add(new api.ODCode("opendiscord:panel-auto-update",7,async () => { + const globalDatabase = opendiscord.databases.get("opendiscord:global") + const panelIds = await globalDatabase.getCategory("opendiscord:panel-update") ?? [] if (!mainServer) return for (const panelId of panelIds){ @@ -291,7 +291,7 @@ export const loadPanelAutoUpdateCode = async () => { //panel doesn't exist anymore in config and needs to be removed if (!panel){ - globalDatabase.delete("openticket:panel-update",panelId.key) + globalDatabase.delete("opendiscord:panel-update",panelId.key) return } @@ -302,7 +302,7 @@ export const loadPanelAutoUpdateCode = async () => { const message = await opendiscord.client.fetchGuildChannelMessage(mainServer,channel,splittedId[1]) if (!message || !message.editable) return - message.edit((await opendiscord.builders.messages.getSafe("openticket:panel").build("auto-update",{guild:mainServer,channel,user:opendiscord.client.client.user,panel})).message) + message.edit((await opendiscord.builders.messages.getSafe("opendiscord:panel").build("auto-update",{guild:mainServer,channel,user:opendiscord.client.client.user,panel})).message) opendiscord.log("Panel in server got auto-updated!","info",[ {key:"channelid",value:splittedId[0]}, {key:"messageid",value:splittedId[1]}, @@ -315,62 +315,62 @@ export const loadPanelAutoUpdateCode = async () => { export const loadDatabaseSaversCode = async () => { //TICKET SAVER - opendiscord.code.add(new api.ODCode("openticket:ticket-saver",6,() => { - const mainVersion = opendiscord.versions.get("openticket:version") + opendiscord.code.add(new api.ODCode("opendiscord:ticket-saver",6,() => { + const mainVersion = opendiscord.versions.get("opendiscord:version") opendiscord.tickets.onAdd(async (ticket) => { - await ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) + await ticketDatabase.set("opendiscord:ticket",ticket.id.value,ticket.toJson(mainVersion)) //add option to database if non-existent - if (!(await optionDatabase.exists("openticket:used-option",ticket.option.id.value))){ - await optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) + if (!(await optionDatabase.exists("opendiscord:used-option",ticket.option.id.value))){ + await optionDatabase.set("opendiscord:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) } }) opendiscord.tickets.onChange(async (ticket) => { - await ticketDatabase.set("openticket:ticket",ticket.id.value,ticket.toJson(mainVersion)) + await ticketDatabase.set("opendiscord:ticket",ticket.id.value,ticket.toJson(mainVersion)) //add option to database if non-existent - if (!(await optionDatabase.exists("openticket:used-option",ticket.option.id.value))){ - await optionDatabase.set("openticket:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) + if (!(await optionDatabase.exists("opendiscord:used-option",ticket.option.id.value))){ + await optionDatabase.set("opendiscord:used-option",ticket.option.id.value,ticket.option.toJson(mainVersion)) } //delete all unused options on ticket move for (const option of opendiscord.options.getAll()){ - if (await optionDatabase.exists("openticket:used-option",option.id.value) && !opendiscord.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ - await optionDatabase.delete("openticket:used-option",option.id.value) + if (await optionDatabase.exists("opendiscord:used-option",option.id.value) && !opendiscord.tickets.getAll().some((ticket) => ticket.option.id.value == option.id.value)){ + await optionDatabase.delete("opendiscord:used-option",option.id.value) } } }) opendiscord.tickets.onRemove(async (ticket) => { - await ticketDatabase.delete("openticket:ticket",ticket.id.value) + await ticketDatabase.delete("opendiscord:ticket",ticket.id.value) //remove option from database if unused if (!opendiscord.tickets.getAll().some((ticket) => ticket.option.id.value == ticket.option.id.value)){ - await optionDatabase.delete("openticket:used-option",ticket.option.id.value) + await optionDatabase.delete("opendiscord:used-option",ticket.option.id.value) } }) })) //BLACKLIST SAVER - opendiscord.code.add(new api.ODCode("openticket:blacklist-saver",5,() => { + opendiscord.code.add(new api.ODCode("opendiscord:blacklist-saver",5,() => { opendiscord.blacklist.onAdd(async (blacklist) => { - await userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) + await userDatabase.set("opendiscord:blacklist",blacklist.id.value,blacklist.reason) }) opendiscord.blacklist.onChange(async (blacklist) => { - await userDatabase.set("openticket:blacklist",blacklist.id.value,blacklist.reason) + await userDatabase.set("opendiscord:blacklist",blacklist.id.value,blacklist.reason) }) opendiscord.blacklist.onRemove(async (blacklist) => { - await userDatabase.delete("openticket:blacklist",blacklist.id.value) + await userDatabase.delete("opendiscord:blacklist",blacklist.id.value) }) })) //AUTO ROLE ON JOIN - opendiscord.code.add(new api.ODCode("openticket:auto-role-on-join",4,() => { + opendiscord.code.add(new api.ODCode("opendiscord:auto-role-on-join",4,() => { opendiscord.client.client.on("guildMemberAdd",async (member) => { for (const option of opendiscord.options.getAll()){ - if (option instanceof api.ODRoleOption && option.get("openticket:add-on-join").value){ + if (option instanceof api.ODRoleOption && option.get("opendiscord:add-on-join").value){ //add these roles on user join - await opendiscord.actions.get("openticket:reaction-role").run("panel-button",{guild:member.guild,user:member.user,option,overwriteMode:"add"}) + await opendiscord.actions.get("opendiscord:reaction-role").run("panel-button",{guild:member.guild,user:member.user,option,overwriteMode:"add"}) } } }) @@ -379,26 +379,26 @@ export const loadDatabaseSaversCode = async () => { const loadAutoCode = () => { //AUTOCLOSE TIMEOUT - opendiscord.code.add(new api.ODCode("openticket:autoclose-timeout",3,() => { + opendiscord.code.add(new api.ODCode("opendiscord:autoclose-timeout",3,() => { setInterval(async () => { let count = 0 for (const ticket of opendiscord.tickets.getAll()){ const channel = await opendiscord.tickets.getTicketChannel(ticket) if (!channel) return const lastMessage = (await channel.messages.fetch({limit:5})).first() - if (lastMessage && !ticket.get("openticket:closed").value){ + if (lastMessage && !ticket.get("opendiscord:closed").value){ //ticket has last message - const disableOnClaim = ticket.option.get("openticket:autoclose-disable-claim").value && ticket.get("openticket:claimed").value - const enabled = (disableOnClaim) ? false : ticket.get("openticket:autoclose-enabled").value - const hours = ticket.get("openticket:autoclose-hours").value + const disableOnClaim = ticket.option.get("opendiscord:autoclose-disable-claim").value && ticket.get("opendiscord:claimed").value + const enabled = (disableOnClaim) ? false : ticket.get("opendiscord:autoclose-enabled").value + const hours = ticket.get("opendiscord:autoclose-hours").value const time = hours*60*60*1000 //hours in milliseconds if (enabled && (new Date().getTime() - lastMessage.createdTimestamp) >= time){ //autoclose ticket - await opendiscord.actions.get("openticket:close-ticket").run("autoclose",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) - await channel.send((await opendiscord.builders.messages.getSafe("openticket:autoclose-message").build("timeout",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) + await opendiscord.actions.get("opendiscord:close-ticket").run("autoclose",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) + await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("timeout",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) count++ - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-autoclosed",1,"increase") } } } @@ -410,21 +410,21 @@ const loadAutoCode = () => { })) //AUTOCLOSE LEAVE - opendiscord.code.add(new api.ODCode("openticket:autoclose-leave",2,() => { + opendiscord.code.add(new api.ODCode("opendiscord:autoclose-leave",2,() => { opendiscord.client.client.on("guildMemberRemove",async (member) => { for (const ticket of opendiscord.tickets.getAll()){ - if (ticket.get("openticket:opened-by").value == member.id){ + if (ticket.get("opendiscord:opened-by").value == member.id){ const channel = await opendiscord.tickets.getTicketChannel(ticket) if (!channel) return //ticket has been created by this user - const disableOnClaim = ticket.option.get("openticket:autoclose-disable-claim").value && ticket.get("openticket:claimed").value - const enabled = (disableOnClaim || !ticket.get("openticket:autoclose-enabled").value) ? false : ticket.option.get("openticket:autoclose-enable-leave") + const disableOnClaim = ticket.option.get("opendiscord:autoclose-disable-claim").value && ticket.get("opendiscord:claimed").value + const enabled = (disableOnClaim || !ticket.get("opendiscord:autoclose-enabled").value) ? false : ticket.option.get("opendiscord:autoclose-enable-leave") if (enabled){ //autoclose ticket - await opendiscord.actions.get("openticket:close-ticket").run("autoclose",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) - await channel.send((await opendiscord.builders.messages.getSafe("openticket:autoclose-message").build("leave",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-autoclosed",1,"increase") + await opendiscord.actions.get("opendiscord:close-ticket").run("autoclose",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autoclose",sendMessage:false}) + await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("leave",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-autoclosed",1,"increase") } } } @@ -432,7 +432,7 @@ const loadAutoCode = () => { })) //AUTODELETE TIMEOUT - opendiscord.code.add(new api.ODCode("openticket:autodelete-timeout",1,() => { + opendiscord.code.add(new api.ODCode("opendiscord:autodelete-timeout",1,() => { setInterval(async () => { let count = 0 for (const ticket of opendiscord.tickets.getAll()){ @@ -441,17 +441,17 @@ const loadAutoCode = () => { const lastMessage = (await channel.messages.fetch({limit:5})).first() if (lastMessage){ //ticket has last message - const disableOnClaim = ticket.option.get("openticket:autodelete-disable-claim").value && ticket.get("openticket:claimed").value - const enabled = (disableOnClaim) ? false : ticket.get("openticket:autodelete-enabled").value - const days = ticket.get("openticket:autodelete-days").value + const disableOnClaim = ticket.option.get("opendiscord:autodelete-disable-claim").value && ticket.get("opendiscord:claimed").value + const enabled = (disableOnClaim) ? false : ticket.get("opendiscord:autodelete-enabled").value + const days = ticket.get("opendiscord:autodelete-days").value const time = days*24*60*60*1000 //days in milliseconds if (enabled && (new Date().getTime() - lastMessage.createdTimestamp) >= time){ //autodelete ticket - await channel.send((await opendiscord.builders.messages.getSafe("openticket:autodelete-message").build("timeout",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) - await opendiscord.actions.get("openticket:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) + await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:autodelete-message").build("timeout",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) + await opendiscord.actions.get("opendiscord:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) count++ - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-autodeleted",1,"increase") } } } @@ -463,21 +463,21 @@ const loadAutoCode = () => { })) //AUTODELETE LEAVE - opendiscord.code.add(new api.ODCode("openticket:autodelete-leave",0,() => { + opendiscord.code.add(new api.ODCode("opendiscord:autodelete-leave",0,() => { opendiscord.client.client.on("guildMemberRemove",async (member) => { for (const ticket of opendiscord.tickets.getAll()){ - if (ticket.get("openticket:opened-by").value == member.id){ + if (ticket.get("opendiscord:opened-by").value == member.id){ const channel = await opendiscord.tickets.getTicketChannel(ticket) if (!channel) return //ticket has been created by this user - const disableOnClaim = ticket.option.get("openticket:autodelete-disable-claim").value && ticket.get("openticket:claimed").value - const enabled = (disableOnClaim || !ticket.get("openticket:autodelete-enabled").value) ? false : ticket.option.get("openticket:autodelete-enable-leave") + const disableOnClaim = ticket.option.get("opendiscord:autodelete-disable-claim").value && ticket.get("opendiscord:claimed").value + const enabled = (disableOnClaim || !ticket.get("opendiscord:autodelete-enabled").value) ? false : ticket.option.get("opendiscord:autodelete-enable-leave") if (enabled){ //autodelete ticket - await channel.send((await opendiscord.builders.messages.getSafe("openticket:autodelete-message").build("leave",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) - await opendiscord.actions.get("openticket:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) - await opendiscord.stats.get("openticket:global").setStat("openticket:tickets-autodeleted",1,"increase") + await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:autodelete-message").build("leave",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket})).message) + await opendiscord.actions.get("opendiscord:delete-ticket").run("autodelete",{guild:channel.guild,channel,user:opendiscord.client.client.user,ticket,reason:"Autodelete",sendMessage:false,withoutTranscript:false}) + await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-autodeleted",1,"increase") } } } @@ -485,10 +485,10 @@ const loadAutoCode = () => { })) //TICKET ANTI BUSY - opendiscord.code.add(new api.ODCode("openticket:ticket-anti-busy",-1,() => { + opendiscord.code.add(new api.ODCode("opendiscord:ticket-anti-busy",-1,() => { for (const ticket of opendiscord.tickets.getAll()){ - //free tickets from corruption due to openticket:busy variable - ticket.get("openticket:busy").value = false + //free tickets from corruption due to opendiscord:busy variable + ticket.get("opendiscord:busy").value = false } })) } \ No newline at end of file diff --git a/src/data/framework/commandLoader.ts b/src/data/framework/commandLoader.ts index fc9a82b..c62ccf3 100644 --- a/src/data/framework/commandLoader.ts +++ b/src/data/framework/commandLoader.ts @@ -5,7 +5,7 @@ const lang = opendiscord.languages export const loadAllSlashCommands = async () => { const commands = opendiscord.client.slashCommands - const generalConfig = opendiscord.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("opendiscord:general") if (!generalConfig) return const act = discord.ApplicationCommandType @@ -15,13 +15,13 @@ export const loadAllSlashCommands = async () => { //create panel choices const panelChoices : {name:string, value:string}[] = [] - opendiscord.configs.get("openticket:panels").data.forEach((panel) => { + opendiscord.configs.get("opendiscord:panels").data.forEach((panel) => { panelChoices.push({name:panel.name, value:panel.id}) }) //create ticket choices const ticketChoices : {name:string, value:string}[] = [] - opendiscord.configs.get("openticket:options").data.forEach((option) => { + opendiscord.configs.get("opendiscord:options").data.forEach((option) => { if (option.type != "ticket") return ticketChoices.push({name:option.name, value:option.id}) }) @@ -32,7 +32,7 @@ export const loadAllSlashCommands = async () => { } //HELP - if (allowedCommands.includes("help")) commands.add(new api.ODSlashCommand("openticket:help",{ + if (allowedCommands.includes("help")) commands.add(new api.ODSlashCommand("opendiscord:help",{ type:act.ChatInput, name:"help", description:lang.getTranslation("commands.help"), @@ -41,7 +41,7 @@ export const loadAllSlashCommands = async () => { })) //PANEL - if (allowedCommands.includes("panel")) commands.add(new api.ODSlashCommand("openticket:panel",{ + if (allowedCommands.includes("panel")) commands.add(new api.ODSlashCommand("opendiscord:panel",{ type:act.ChatInput, name:"panel", description:lang.getTranslation("commands.panel"), @@ -73,7 +73,7 @@ export const loadAllSlashCommands = async () => { })) //TICKET (when enabled) - if (allowedCommands.includes("ticket")) commands.add(new api.ODSlashCommand("openticket:ticket",{ + if (allowedCommands.includes("ticket")) commands.add(new api.ODSlashCommand("opendiscord:ticket",{ type:act.ChatInput, name:"ticket", description:lang.getTranslation("commands.ticket"), @@ -99,7 +99,7 @@ export const loadAllSlashCommands = async () => { })) //CLOSE - if (allowedCommands.includes("close")) commands.add(new api.ODSlashCommand("openticket:close",{ + if (allowedCommands.includes("close")) commands.add(new api.ODSlashCommand("opendiscord:close",{ type:act.ChatInput, name:"close", description:lang.getTranslation("commands.close"), @@ -116,7 +116,7 @@ export const loadAllSlashCommands = async () => { })) //DELETE - if (allowedCommands.includes("delete") && generalConfig.data.system.enableDeleteWithoutTranscript) commands.add(new api.ODSlashCommand("openticket:delete",{ + if (allowedCommands.includes("delete") && generalConfig.data.system.enableDeleteWithoutTranscript) commands.add(new api.ODSlashCommand("opendiscord:delete",{ type:act.ChatInput, name:"delete", description:lang.getTranslation("commands.delete"), @@ -137,7 +137,7 @@ export const loadAllSlashCommands = async () => { } ] })) - else if (allowedCommands.includes("delete")) commands.add(new api.ODSlashCommand("openticket:delete",{ + else if (allowedCommands.includes("delete")) commands.add(new api.ODSlashCommand("opendiscord:delete",{ type:act.ChatInput, name:"delete", description:lang.getTranslation("commands.delete"), @@ -154,7 +154,7 @@ export const loadAllSlashCommands = async () => { })) //REOPEN - if (allowedCommands.includes("reopen")) commands.add(new api.ODSlashCommand("openticket:reopen",{ + if (allowedCommands.includes("reopen")) commands.add(new api.ODSlashCommand("opendiscord:reopen",{ type:act.ChatInput, name:"reopen", description:lang.getTranslation("commands.reopen"), @@ -171,7 +171,7 @@ export const loadAllSlashCommands = async () => { })) //CLAIM - if (allowedCommands.includes("claim")) commands.add(new api.ODSlashCommand("openticket:claim",{ + if (allowedCommands.includes("claim")) commands.add(new api.ODSlashCommand("opendiscord:claim",{ type:act.ChatInput, name:"claim", description:lang.getTranslation("commands.claim"), @@ -194,7 +194,7 @@ export const loadAllSlashCommands = async () => { })) //UNCLAIM - if (allowedCommands.includes("unclaim")) commands.add(new api.ODSlashCommand("openticket:unclaim",{ + if (allowedCommands.includes("unclaim")) commands.add(new api.ODSlashCommand("opendiscord:unclaim",{ type:act.ChatInput, name:"unclaim", description:lang.getTranslation("commands.unclaim"), @@ -211,7 +211,7 @@ export const loadAllSlashCommands = async () => { })) //PIN - if (allowedCommands.includes("pin")) commands.add(new api.ODSlashCommand("openticket:pin",{ + if (allowedCommands.includes("pin")) commands.add(new api.ODSlashCommand("opendiscord:pin",{ type:act.ChatInput, name:"pin", description:lang.getTranslation("commands.pin"), @@ -228,7 +228,7 @@ export const loadAllSlashCommands = async () => { })) //UNPIN - if (allowedCommands.includes("unpin")) commands.add(new api.ODSlashCommand("openticket:unpin",{ + if (allowedCommands.includes("unpin")) commands.add(new api.ODSlashCommand("opendiscord:unpin",{ type:act.ChatInput, name:"unpin", description:lang.getTranslation("commands.unpin"), @@ -245,7 +245,7 @@ export const loadAllSlashCommands = async () => { })) //MOVE - if (allowedCommands.includes("move")) commands.add(new api.ODSlashCommand("openticket:move",{ + if (allowedCommands.includes("move")) commands.add(new api.ODSlashCommand("opendiscord:move",{ type:act.ChatInput, name:"move", description:lang.getTranslation("commands.move"), @@ -277,7 +277,7 @@ export const loadAllSlashCommands = async () => { })) //RENAME - if (allowedCommands.includes("rename")) commands.add(new api.ODSlashCommand("openticket:rename",{ + if (allowedCommands.includes("rename")) commands.add(new api.ODSlashCommand("opendiscord:rename",{ type:act.ChatInput, name:"rename", description:lang.getTranslation("commands.rename"), @@ -301,7 +301,7 @@ export const loadAllSlashCommands = async () => { })) //ADD - if (allowedCommands.includes("add")) commands.add(new api.ODSlashCommand("openticket:add",{ + if (allowedCommands.includes("add")) commands.add(new api.ODSlashCommand("opendiscord:add",{ type:act.ChatInput, name:"add", description:lang.getTranslation("commands.add"), @@ -324,7 +324,7 @@ export const loadAllSlashCommands = async () => { })) //REMOVE - if (allowedCommands.includes("remove")) commands.add(new api.ODSlashCommand("openticket:remove",{ + if (allowedCommands.includes("remove")) commands.add(new api.ODSlashCommand("opendiscord:remove",{ type:act.ChatInput, name:"remove", description:lang.getTranslation("commands.remove"), @@ -347,7 +347,7 @@ export const loadAllSlashCommands = async () => { })) //BLACKLIST - if (allowedCommands.includes("blacklist")) commands.add(new api.ODSlashCommand("openticket:blacklist",{ + if (allowedCommands.includes("blacklist")) commands.add(new api.ODSlashCommand("opendiscord:blacklist",{ type:act.ChatInput, name:"blacklist", description:lang.getTranslation("commands.blacklist"), @@ -414,7 +414,7 @@ export const loadAllSlashCommands = async () => { })) //STATS - if (allowedCommands.includes("stats")) commands.add(new api.ODSlashCommand("openticket:stats",{ + if (allowedCommands.includes("stats")) commands.add(new api.ODSlashCommand("opendiscord:stats",{ type:act.ChatInput, name:"stats", description:lang.getTranslation("commands.stats"), @@ -469,7 +469,7 @@ export const loadAllSlashCommands = async () => { })) //CLEAR - if (allowedCommands.includes("clear")) commands.add(new api.ODSlashCommand("openticket:clear",{ + if (allowedCommands.includes("clear")) commands.add(new api.ODSlashCommand("opendiscord:clear",{ type:act.ChatInput, name:"clear", description:lang.getTranslation("commands.clear"), @@ -496,7 +496,7 @@ export const loadAllSlashCommands = async () => { })) //AUTOCLOSE - if (allowedCommands.includes("autoclose")) commands.add(new api.ODSlashCommand("openticket:autoclose",{ + if (allowedCommands.includes("autoclose")) commands.add(new api.ODSlashCommand("opendiscord:autoclose",{ type:act.ChatInput, name:"autoclose", description:lang.getTranslation("commands.autoclose"), @@ -540,7 +540,7 @@ export const loadAllSlashCommands = async () => { })) //AUTODELETE - if (allowedCommands.includes("autodelete")) commands.add(new api.ODSlashCommand("openticket:autodelete",{ + if (allowedCommands.includes("autodelete")) commands.add(new api.ODSlashCommand("opendiscord:autodelete",{ type:act.ChatInput, name:"autodelete", description:lang.getTranslation("commands.autodelete"), @@ -586,7 +586,7 @@ export const loadAllSlashCommands = async () => { export const loadAllTextCommands = async () => { const commands = opendiscord.client.textCommands - const generalConfig = opendiscord.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("opendiscord:general") if (!generalConfig) return if (!generalConfig.data.textCommands) return @@ -594,13 +594,13 @@ export const loadAllTextCommands = async () => { //create panel choices const panelChoices : string[] = [] - opendiscord.configs.get("openticket:panels").data.forEach((panel) => { + opendiscord.configs.get("opendiscord:panels").data.forEach((panel) => { panelChoices.push(panel.id) }) //create ticket choices const ticketChoices : string[] = [] - opendiscord.configs.get("openticket:options").data.forEach((option) => { + opendiscord.configs.get("opendiscord:options").data.forEach((option) => { if (option.type != "ticket") return ticketChoices.push(option.id) }) @@ -611,7 +611,7 @@ export const loadAllTextCommands = async () => { } //HELP - if (allowedCommands.includes("help")) commands.add(new api.ODTextCommand("openticket:help",{ + if (allowedCommands.includes("help")) commands.add(new api.ODTextCommand("opendiscord:help",{ name:"help", prefix, dmPermission:true, @@ -620,7 +620,7 @@ export const loadAllTextCommands = async () => { })) //PANEL - if (allowedCommands.includes("panel")) commands.add(new api.ODTextCommand("openticket:panel",{ + if (allowedCommands.includes("panel")) commands.add(new api.ODTextCommand("opendiscord:panel",{ name:"panel", prefix, dmPermission:false, @@ -641,7 +641,7 @@ export const loadAllTextCommands = async () => { })) //CLOSE - if (allowedCommands.includes("close")) commands.add(new api.ODTextCommand("openticket:close",{ + if (allowedCommands.includes("close")) commands.add(new api.ODTextCommand("opendiscord:close",{ name:"close", prefix, dmPermission:false, @@ -658,7 +658,7 @@ export const loadAllTextCommands = async () => { })) //DELETE - if (allowedCommands.includes("delete")) commands.add(new api.ODTextCommand("openticket:delete",{ + if (allowedCommands.includes("delete")) commands.add(new api.ODTextCommand("opendiscord:delete",{ name:"delete", prefix, dmPermission:false, @@ -675,7 +675,7 @@ export const loadAllTextCommands = async () => { })) //REOPEN - if (allowedCommands.includes("reopen")) commands.add(new api.ODTextCommand("openticket:reopen",{ + if (allowedCommands.includes("reopen")) commands.add(new api.ODTextCommand("opendiscord:reopen",{ name:"reopen", prefix, dmPermission:false, @@ -692,7 +692,7 @@ export const loadAllTextCommands = async () => { })) //CLAIM - if (allowedCommands.includes("claim")) commands.add(new api.ODTextCommand("openticket:claim",{ + if (allowedCommands.includes("claim")) commands.add(new api.ODTextCommand("opendiscord:claim",{ name:"claim", prefix, dmPermission:false, @@ -714,7 +714,7 @@ export const loadAllTextCommands = async () => { })) //UNCLAIM - if (allowedCommands.includes("unclaim")) commands.add(new api.ODTextCommand("openticket:unclaim",{ + if (allowedCommands.includes("unclaim")) commands.add(new api.ODTextCommand("opendiscord:unclaim",{ name:"unclaim", prefix, dmPermission:false, @@ -731,7 +731,7 @@ export const loadAllTextCommands = async () => { })) //PIN - if (allowedCommands.includes("pin")) commands.add(new api.ODTextCommand("openticket:pin",{ + if (allowedCommands.includes("pin")) commands.add(new api.ODTextCommand("opendiscord:pin",{ name:"pin", prefix, dmPermission:false, @@ -748,7 +748,7 @@ export const loadAllTextCommands = async () => { })) //UNPIN - if (allowedCommands.includes("unpin")) commands.add(new api.ODTextCommand("openticket:unpin",{ + if (allowedCommands.includes("unpin")) commands.add(new api.ODTextCommand("opendiscord:unpin",{ name:"unpin", prefix, dmPermission:false, @@ -765,7 +765,7 @@ export const loadAllTextCommands = async () => { })) //MOVE - if (allowedCommands.includes("move")) commands.add(new api.ODTextCommand("openticket:move",{ + if (allowedCommands.includes("move")) commands.add(new api.ODTextCommand("opendiscord:move",{ name:"move", prefix, dmPermission:false, @@ -788,7 +788,7 @@ export const loadAllTextCommands = async () => { })) //RENAME - if (allowedCommands.includes("rename")) commands.add(new api.ODTextCommand("openticket:rename",{ + if (allowedCommands.includes("rename")) commands.add(new api.ODTextCommand("opendiscord:rename",{ name:"rename", prefix, dmPermission:false, @@ -811,7 +811,7 @@ export const loadAllTextCommands = async () => { })) //ADD - if (allowedCommands.includes("add")) commands.add(new api.ODTextCommand("openticket:add",{ + if (allowedCommands.includes("add")) commands.add(new api.ODTextCommand("opendiscord:add",{ name:"add", prefix, dmPermission:false, @@ -833,7 +833,7 @@ export const loadAllTextCommands = async () => { })) //REMOVE - if (allowedCommands.includes("remove")) commands.add(new api.ODTextCommand("openticket:remove",{ + if (allowedCommands.includes("remove")) commands.add(new api.ODTextCommand("opendiscord:remove",{ name:"remove", prefix, dmPermission:false, @@ -855,7 +855,7 @@ export const loadAllTextCommands = async () => { })) //BLACKLIST - if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("openticket:blacklist-view",{ + if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("opendiscord:blacklist-view",{ name:"blacklist view", prefix, dmPermission:false, @@ -863,7 +863,7 @@ export const loadAllTextCommands = async () => { allowBots:false })) - if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("openticket:blacklist-add",{ + if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("opendiscord:blacklist-add",{ name:"blacklist add", prefix, dmPermission:false, @@ -884,7 +884,7 @@ export const loadAllTextCommands = async () => { ] })) - if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("openticket:blacklist-remove",{ + if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("opendiscord:blacklist-remove",{ name:"blacklist remove", prefix, dmPermission:false, @@ -905,7 +905,7 @@ export const loadAllTextCommands = async () => { ] })) - if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("openticket:blacklist-get",{ + if (allowedCommands.includes("blacklist")) commands.add(new api.ODTextCommand("opendiscord:blacklist-get",{ name:"blacklist get", prefix, dmPermission:false, @@ -921,7 +921,7 @@ export const loadAllTextCommands = async () => { })) //STATS - if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("openticket:stats-global",{ + if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("opendiscord:stats-global",{ name:"stats global", prefix, dmPermission:false, @@ -929,7 +929,7 @@ export const loadAllTextCommands = async () => { allowBots:false })) - if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("openticket:stats-reset",{ + if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("opendiscord:stats-reset",{ name:"stats reset", prefix, dmPermission:false, @@ -945,7 +945,7 @@ export const loadAllTextCommands = async () => { ] })) - if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("openticket:stats-user",{ + if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("opendiscord:stats-user",{ name:"stats user", prefix, dmPermission:false, @@ -960,7 +960,7 @@ export const loadAllTextCommands = async () => { ] })) - if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("openticket:stats-ticket",{ + if (allowedCommands.includes("stats")) commands.add(new api.ODTextCommand("opendiscord:stats-ticket",{ name:"stats ticket", prefix, dmPermission:false, @@ -977,7 +977,7 @@ export const loadAllTextCommands = async () => { })) //CLEAR - if (allowedCommands.includes("clear")) commands.add(new api.ODTextCommand("openticket:clear",{ + if (allowedCommands.includes("clear")) commands.add(new api.ODTextCommand("opendiscord:clear",{ name:"clear", prefix, dmPermission:false, @@ -1004,7 +1004,7 @@ export const loadAllTextCommands = async () => { })) //AUTOCLOSE - if (allowedCommands.includes("autoclose")) commands.add(new api.ODTextCommand("openticket:autoclose-disable",{ + if (allowedCommands.includes("autoclose")) commands.add(new api.ODTextCommand("opendiscord:autoclose-disable",{ name:"autoclose disable", prefix, dmPermission:false, @@ -1020,7 +1020,7 @@ export const loadAllTextCommands = async () => { ] })) - if (allowedCommands.includes("autoclose")) commands.add(new api.ODTextCommand("openticket:autoclose-enable",{ + if (allowedCommands.includes("autoclose")) commands.add(new api.ODTextCommand("opendiscord:autoclose-enable",{ name:"autoclose enable", prefix, dmPermission:false, @@ -1045,7 +1045,7 @@ export const loadAllTextCommands = async () => { })) //AUTODELETE - if (allowedCommands.includes("autodelete")) commands.add(new api.ODTextCommand("openticket:autodelete-disable",{ + if (allowedCommands.includes("autodelete")) commands.add(new api.ODTextCommand("opendiscord:autodelete-disable",{ name:"autodelete disable", prefix, dmPermission:false, @@ -1061,7 +1061,7 @@ export const loadAllTextCommands = async () => { ] })) - if (allowedCommands.includes("autodelete")) commands.add(new api.ODTextCommand("openticket:autodelete-enable",{ + if (allowedCommands.includes("autodelete")) commands.add(new api.ODTextCommand("opendiscord:autodelete-enable",{ name:"autodelete enable", prefix, dmPermission:false, diff --git a/src/data/framework/configLoader.ts b/src/data/framework/configLoader.ts index aee1956..597f9c5 100644 --- a/src/data/framework/configLoader.ts +++ b/src/data/framework/configLoader.ts @@ -1,12 +1,12 @@ import {opendiscord, api, utilities} from "../../index" export const loadAllConfigs = async () => { - const devconfigFlag = opendiscord.flags.get("openticket:dev-config") + const devconfigFlag = opendiscord.flags.get("opendiscord:dev-config") const isDevconfig = devconfigFlag ? devconfigFlag.value : false - opendiscord.configs.add(new api.ODJsonConfig("openticket:general","general.json",(isDevconfig) ? "./devconfig/" : "./config/")) - opendiscord.configs.add(new api.ODJsonConfig("openticket:options","options.json",(isDevconfig) ? "./devconfig/" : "./config/")) - opendiscord.configs.add(new api.ODJsonConfig("openticket:panels","panels.json",(isDevconfig) ? "./devconfig/" : "./config/")) - opendiscord.configs.add(new api.ODJsonConfig("openticket:questions","questions.json",(isDevconfig) ? "./devconfig/" : "./config/")) - opendiscord.configs.add(new api.ODJsonConfig("openticket:transcripts","transcripts.json",(isDevconfig) ? "./devconfig/" : "./config/")) + opendiscord.configs.add(new api.ODJsonConfig("opendiscord:general","general.json",(isDevconfig) ? "./devconfig/" : "./config/")) + opendiscord.configs.add(new api.ODJsonConfig("opendiscord:options","options.json",(isDevconfig) ? "./devconfig/" : "./config/")) + opendiscord.configs.add(new api.ODJsonConfig("opendiscord:panels","panels.json",(isDevconfig) ? "./devconfig/" : "./config/")) + opendiscord.configs.add(new api.ODJsonConfig("opendiscord:questions","questions.json",(isDevconfig) ? "./devconfig/" : "./config/")) + opendiscord.configs.add(new api.ODJsonConfig("opendiscord:transcripts","transcripts.json",(isDevconfig) ? "./devconfig/" : "./config/")) } \ No newline at end of file diff --git a/src/data/framework/cooldownLoader.ts b/src/data/framework/cooldownLoader.ts index ca25eb3..2a431ac 100644 --- a/src/data/framework/cooldownLoader.ts +++ b/src/data/framework/cooldownLoader.ts @@ -8,10 +8,10 @@ export const loadAllCooldowns = async () => { } export const loadTicketOptionCooldown = (option:api.ODTicketOption) => { - if (option.get("openticket:cooldown-enabled").value){ + if (option.get("opendiscord:cooldown-enabled").value){ //option has cooldown - const minutes = option.get("openticket:cooldown-minutes").value + const minutes = option.get("opendiscord:cooldown-minutes").value const milliseconds = minutes*60000 - opendiscord.cooldowns.add(new api.ODTimeoutCooldown("openticket:option-cooldown_"+option.id.value,milliseconds)) + opendiscord.cooldowns.add(new api.ODTimeoutCooldown("opendiscord:option-cooldown_"+option.id.value,milliseconds)) } } \ No newline at end of file diff --git a/src/data/framework/databaseLoader.ts b/src/data/framework/databaseLoader.ts index 8b5d4ef..65baeef 100644 --- a/src/data/framework/databaseLoader.ts +++ b/src/data/framework/databaseLoader.ts @@ -1,7 +1,7 @@ import {opendiscord, api, utilities} from "../../index" import * as fjs from "formatted-json-stringify" -const devdatabaseFlag = opendiscord.flags.get("openticket:dev-database") +const devdatabaseFlag = opendiscord.flags.get("opendiscord:dev-database") const isDevdatabase = devdatabaseFlag ? devdatabaseFlag.value : false export const loadAllDatabases = async () => { @@ -46,8 +46,8 @@ const defaultOptionFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectFo ]) ])) -export const defaultGlobalDatabase = new api.ODFormattedJsonDatabase("openticket:global","global.json",defaultInlineFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") -export const defaultStatsDatabase = new api.ODFormattedJsonDatabase("openticket:stats","stats.json",defaultInlineFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") -export const defaultTicketsDatabase = new api.ODFormattedJsonDatabase("openticket:tickets","tickets.json",defaultTicketFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") -export const defaultUsersDatabase = new api.ODFormattedJsonDatabase("openticket:users","users.json",defaultInlineFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") -export const defaultOptionsDatabase = new api.ODFormattedJsonDatabase("openticket:options","options.json",defaultOptionFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") \ No newline at end of file +export const defaultGlobalDatabase = new api.ODFormattedJsonDatabase("opendiscord:global","global.json",defaultInlineFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") +export const defaultStatsDatabase = new api.ODFormattedJsonDatabase("opendiscord:stats","stats.json",defaultInlineFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") +export const defaultTicketsDatabase = new api.ODFormattedJsonDatabase("opendiscord:tickets","tickets.json",defaultTicketFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") +export const defaultUsersDatabase = new api.ODFormattedJsonDatabase("opendiscord:users","users.json",defaultInlineFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") +export const defaultOptionsDatabase = new api.ODFormattedJsonDatabase("opendiscord:options","options.json",defaultOptionFormatter,(isDevdatabase) ? "./devdatabase/" : "./database/") \ No newline at end of file diff --git a/src/data/framework/flagLoader.ts b/src/data/framework/flagLoader.ts index 1e90e62..9f980ff 100644 --- a/src/data/framework/flagLoader.ts +++ b/src/data/framework/flagLoader.ts @@ -1,18 +1,18 @@ import {opendiscord, api, utilities} from "../../index" export const loadAllFlags = async () => { - opendiscord.flags.add(new api.ODFlag("openticket:no-migration","No Migration","Disable Open Ticket data migration on update!","--no-migration",["-nm"])) - opendiscord.flags.add(new api.ODFlag("openticket:dev-config","Developer Config","Use the configs in /devconfig/ instead of /config/!","--dev-config",["-dc"])) - opendiscord.flags.add(new api.ODFlag("openticket:dev-database","Developer Database","Use the databases in /devdatabase/ instead of /database/!","--dev-database",["-nd"])) - opendiscord.flags.add(new api.ODFlag("openticket:debug","Debug Mode","Couldn't you find the error? Try to check this out!","--debug",["-d"])) - opendiscord.flags.add(new api.ODFlag("openticket:crash","Crash On Error","Crash the bot on an unknown error!","--crash",["-cr"])) - opendiscord.flags.add(new api.ODFlag("openticket:no-transcripts","No HTML Transcripts","Disable uploading HTML transcripts (for debugging)","--no-transcripts",["-nt"])) - opendiscord.flags.add(new api.ODFlag("openticket:no-checker","No Config Checker","Disable the Config Checker (for debugging)","--no-checker",["-nc"])) - opendiscord.flags.add(new api.ODFlag("openticket:checker","Full Config Checker","Render the Config Checker with extra details!","--checker",["-c"])) - opendiscord.flags.add(new api.ODFlag("openticket:no-easter","No Easter Eggs","Disable little Open Ticket easter eggs hidden in the bot!","--no-easter",["-ne"])) - opendiscord.flags.add(new api.ODFlag("openticket:no-plugins","No Plugins","Disable all Open Ticket plugins!","--no-plugins",["-np"])) - opendiscord.flags.add(new api.ODFlag("openticket:soft-plugins","Soft Plugins","Don't crash the bot when a plugin crashes!","--soft-plugins",["-sp"])) - opendiscord.flags.add(new api.ODFlag("openticket:force-slash-update","Force Slash Update","Force update all slash commands.","--force-slash",["-fs"])) - opendiscord.flags.add(new api.ODFlag("openticket:no-compile","No Compile","Disable compilation of plugins & bot before starting.","--no-compile",[])) - opendiscord.flags.add(new api.ODFlag("openticket:compile-only","Compile Only","This description will never be shown because the bot wouldn't run when this flag is enabled :)","--compile-only",[])) + opendiscord.flags.add(new api.ODFlag("opendiscord:no-migration","No Migration","Disable Open Ticket data migration on update!","--no-migration",["-nm"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:dev-config","Developer Config","Use the configs in /devconfig/ instead of /config/!","--dev-config",["-dc"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:dev-database","Developer Database","Use the databases in /devdatabase/ instead of /database/!","--dev-database",["-nd"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:debug","Debug Mode","Couldn't you find the error? Try to check this out!","--debug",["-d"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:crash","Crash On Error","Crash the bot on an unknown error!","--crash",["-cr"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:no-transcripts","No HTML Transcripts","Disable uploading HTML transcripts (for debugging)","--no-transcripts",["-nt"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:no-checker","No Config Checker","Disable the Config Checker (for debugging)","--no-checker",["-nc"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:checker","Full Config Checker","Render the Config Checker with extra details!","--checker",["-c"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:no-easter","No Easter Eggs","Disable little Open Ticket easter eggs hidden in the bot!","--no-easter",["-ne"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:no-plugins","No Plugins","Disable all Open Ticket plugins!","--no-plugins",["-np"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:soft-plugins","Soft Plugins","Don't crash the bot when a plugin crashes!","--soft-plugins",["-sp"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:force-slash-update","Force Slash Update","Force update all slash commands.","--force-slash",["-fs"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:no-compile","No Compile","Disable compilation of plugins & bot before starting.","--no-compile",[])) + opendiscord.flags.add(new api.ODFlag("opendiscord:compile-only","Compile Only","This description will never be shown because the bot wouldn't run when this flag is enabled :)","--compile-only",[])) } \ No newline at end of file diff --git a/src/data/framework/helpMenuLoader.ts b/src/data/framework/helpMenuLoader.ts index 4c6d7b1..914d1ef 100644 --- a/src/data/framework/helpMenuLoader.ts +++ b/src/data/framework/helpMenuLoader.ts @@ -5,18 +5,18 @@ const lang = opendiscord.languages export const loadAllHelpMenuCategories = async () => { const helpmenu = opendiscord.helpmenu - helpmenu.add(new api.ODHelpMenuCategory("openticket:general",5,utilities.emojiTitle("📎","General Commands"))) //TODO TRANSLATION!!! - helpmenu.add(new api.ODHelpMenuCategory("openticket:ticket-basic",4,utilities.emojiTitle("🎫","Basic Ticket Commands"))) //TODO TRANSLATION!!! - helpmenu.add(new api.ODHelpMenuCategory("openticket:ticket-advanced",4,utilities.emojiTitle("💡","Advanced Ticket Commands"))) //TODO TRANSLATION!!! - helpmenu.add(new api.ODHelpMenuCategory("openticket:ticket-user",3,utilities.emojiTitle("👤","User Ticket Commands"))) //TODO TRANSLATION!!! - helpmenu.add(new api.ODHelpMenuCategory("openticket:admin",2,utilities.emojiTitle("🚨","Admin Commands"))) //TODO TRANSLATION!!! - helpmenu.add(new api.ODHelpMenuCategory("openticket:advanced",1,utilities.emojiTitle("🚧","Advanced Commands"))) //TODO TRANSLATION!!! - helpmenu.add(new api.ODHelpMenuCategory("openticket:extra",0,utilities.emojiTitle("✨","Extra Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("opendiscord:general",5,utilities.emojiTitle("📎","General Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("opendiscord:ticket-basic",4,utilities.emojiTitle("🎫","Basic Ticket Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("opendiscord:ticket-advanced",4,utilities.emojiTitle("💡","Advanced Ticket Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("opendiscord:ticket-user",3,utilities.emojiTitle("👤","User Ticket Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("opendiscord:admin",2,utilities.emojiTitle("🚨","Admin Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("opendiscord:advanced",1,utilities.emojiTitle("🚧","Advanced Commands"))) //TODO TRANSLATION!!! + helpmenu.add(new api.ODHelpMenuCategory("opendiscord:extra",0,utilities.emojiTitle("✨","Extra Commands"))) //TODO TRANSLATION!!! } export const loadAllHelpMenuComponents = async () => { const helpmenu = opendiscord.helpmenu - const generalConfig = opendiscord.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("opendiscord:general") if (!generalConfig) return const prefix = generalConfig.data.prefix @@ -27,24 +27,24 @@ export const loadAllHelpMenuComponents = async () => { if (generalConfig.data.system.permissions[key] != "none") allowedCommands.push(key) } - const general = helpmenu.get("openticket:general") + const general = helpmenu.get("opendiscord:general") if (general){ - if (allowedCommands.includes("help")) general.add(new api.ODHelpMenuCommandComponent("openticket:help",1,{ + if (allowedCommands.includes("help")) general.add(new api.ODHelpMenuCommandComponent("opendiscord:help",1,{ textName:prefix+"help", textDescription:lang.getTranslation("helpMenu.help"), slashName:"/help", slashDescription:lang.getTranslation("helpMenu.help") })) - if (allowedCommands.includes("ticket")) general.add(new api.ODHelpMenuCommandComponent("openticket:ticket",0,{ + if (allowedCommands.includes("ticket")) general.add(new api.ODHelpMenuCommandComponent("opendiscord:ticket",0,{ slashName:"/ticket", slashDescription:lang.getTranslation("commands.ticket"), slashOptions:[{name:"id",optional:false}] })) } - const ticketBasic = helpmenu.get("openticket:ticket-basic") + const ticketBasic = helpmenu.get("opendiscord:ticket-basic") if (ticketBasic){ - if (allowedCommands.includes("close")) ticketBasic.add(new api.ODHelpMenuCommandComponent("openticket:close",10,{ + if (allowedCommands.includes("close")) ticketBasic.add(new api.ODHelpMenuCommandComponent("opendiscord:close",10,{ textName:prefix+"close", textDescription:lang.getTranslation("helpMenu.close"), slashName:"/close", @@ -53,7 +53,7 @@ export const loadAllHelpMenuComponents = async () => { slashOptions:[{name:"reason",optional:true}] })) if (enableDeleteWithoutTranscript){ - if (allowedCommands.includes("delete")) ticketBasic.add(new api.ODHelpMenuCommandComponent("openticket:delete",9,{ + if (allowedCommands.includes("delete")) ticketBasic.add(new api.ODHelpMenuCommandComponent("opendiscord:delete",9,{ textName:prefix+"delete", textDescription:lang.getTranslation("helpMenu.delete"), slashName:"/delete", @@ -62,7 +62,7 @@ export const loadAllHelpMenuComponents = async () => { slashOptions:[{name:"notranscript",optional:true},{name:"reason",optional:true}] })) }else{ - if (allowedCommands.includes("delete")) ticketBasic.add(new api.ODHelpMenuCommandComponent("openticket:delete",9,{ + if (allowedCommands.includes("delete")) ticketBasic.add(new api.ODHelpMenuCommandComponent("opendiscord:delete",9,{ textName:prefix+"delete", textDescription:lang.getTranslation("helpMenu.delete"), slashName:"/delete", @@ -71,7 +71,7 @@ export const loadAllHelpMenuComponents = async () => { slashOptions:[{name:"reason",optional:true}] })) } - if (allowedCommands.includes("reopen")) ticketBasic.add(new api.ODHelpMenuCommandComponent("openticket:reopen",8,{ + if (allowedCommands.includes("reopen")) ticketBasic.add(new api.ODHelpMenuCommandComponent("opendiscord:reopen",8,{ textName:prefix+"reopen", textDescription:lang.getTranslation("helpMenu.reopen"), slashName:"/reopen", @@ -81,9 +81,9 @@ export const loadAllHelpMenuComponents = async () => { })) } - const ticketAdvanced = helpmenu.get("openticket:ticket-advanced") + const ticketAdvanced = helpmenu.get("opendiscord:ticket-advanced") if (ticketAdvanced){ - if (allowedCommands.includes("pin")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("openticket:pin",5,{ + if (allowedCommands.includes("pin")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("opendiscord:pin",5,{ textName:prefix+"pin", textDescription:lang.getTranslation("helpMenu.pin"), slashName:"/pin", @@ -91,7 +91,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"reason",optional:true}], slashOptions:[{name:"reason",optional:true}] })) - if (allowedCommands.includes("unpin")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("openticket:unpin",4,{ + if (allowedCommands.includes("unpin")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("opendiscord:unpin",4,{ textName:prefix+"unpin", textDescription:lang.getTranslation("helpMenu.unpin"), slashName:"/unpin", @@ -99,7 +99,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"reason",optional:true}], slashOptions:[{name:"reason",optional:true}] })) - if (allowedCommands.includes("move")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("openticket:move",3,{ + if (allowedCommands.includes("move")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("opendiscord:move",3,{ textName:prefix+"move", textDescription:lang.getTranslation("helpMenu.move"), slashName:"/move", @@ -107,7 +107,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"id",optional:false},{name:"reason",optional:true}], slashOptions:[{name:"id",optional:false},{name:"reason",optional:true}] })) - if (allowedCommands.includes("rename")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("openticket:rename",2,{ + if (allowedCommands.includes("rename")) ticketAdvanced.add(new api.ODHelpMenuCommandComponent("opendiscord:rename",2,{ textName:prefix+"rename", textDescription:lang.getTranslation("helpMenu.rename"), slashName:"/rename", @@ -117,9 +117,9 @@ export const loadAllHelpMenuComponents = async () => { })) } - const ticketUser = helpmenu.get("openticket:ticket-channel") + const ticketUser = helpmenu.get("opendiscord:ticket-channel") if (ticketUser){ - if (allowedCommands.includes("claim")) ticketUser.add(new api.ODHelpMenuCommandComponent("openticket:claim",7,{ + if (allowedCommands.includes("claim")) ticketUser.add(new api.ODHelpMenuCommandComponent("opendiscord:claim",7,{ textName:prefix+"claim", textDescription:lang.getTranslation("helpMenu.claim"), slashName:"/claim", @@ -127,7 +127,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"user",optional:true},{name:"reason",optional:true}], slashOptions:[{name:"user",optional:true},{name:"reason",optional:true}] })) - if (allowedCommands.includes("unclaim")) ticketUser.add(new api.ODHelpMenuCommandComponent("openticket:unclaim",6,{ + if (allowedCommands.includes("unclaim")) ticketUser.add(new api.ODHelpMenuCommandComponent("opendiscord:unclaim",6,{ textName:prefix+"unclaim", textDescription:lang.getTranslation("helpMenu.unclaim"), slashName:"/unclaim", @@ -135,7 +135,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"reason",optional:true}], slashOptions:[{name:"reason",optional:true}] })) - if (allowedCommands.includes("add")) ticketUser.add(new api.ODHelpMenuCommandComponent("openticket:add",1,{ + if (allowedCommands.includes("add")) ticketUser.add(new api.ODHelpMenuCommandComponent("opendiscord:add",1,{ textName:prefix+"add", textDescription:lang.getTranslation("helpMenu.add"), slashName:"/add", @@ -143,7 +143,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"user",optional:false},{name:"reason",optional:true}], slashOptions:[{name:"user",optional:false},{name:"reason",optional:true}] })) - if (allowedCommands.includes("remove")) ticketUser.add(new api.ODHelpMenuCommandComponent("openticket:remove",0,{ + if (allowedCommands.includes("remove")) ticketUser.add(new api.ODHelpMenuCommandComponent("opendiscord:remove",0,{ textName:prefix+"remove", textDescription:lang.getTranslation("helpMenu.remove"), slashName:"/remove", @@ -153,9 +153,9 @@ export const loadAllHelpMenuComponents = async () => { })) } - const admin = helpmenu.get("openticket:admin") + const admin = helpmenu.get("opendiscord:admin") if (admin){ - if (allowedCommands.includes("panel")) admin.add(new api.ODHelpMenuCommandComponent("openticket:panel",4,{ + if (allowedCommands.includes("panel")) admin.add(new api.ODHelpMenuCommandComponent("opendiscord:panel",4,{ textName:prefix+"panel", textDescription:lang.getTranslation("helpMenu.panel"), slashName:"/panel", @@ -163,13 +163,13 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"id",optional:false}], slashOptions:[{name:"id",optional:false}] })) - if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("openticket:blacklist-view",3,{ + if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("opendiscord:blacklist-view",3,{ textName:prefix+"blacklist view", textDescription:lang.getTranslation("commands.blacklistView"), slashName:"/blacklist view", slashDescription:lang.getTranslation("commands.blacklistView") })) - if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("openticket:blacklist-add",2,{ + if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("opendiscord:blacklist-add",2,{ textName:prefix+"blacklist add", textDescription:lang.getTranslation("commands.blacklistAdd"), slashName:"/blacklist add", @@ -177,7 +177,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"user",optional:false},{name:"reason",optional:true}], slashOptions:[{name:"user",optional:false},{name:"reason",optional:true}] })) - if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("openticket:blacklist-remove",1,{ + if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("opendiscord:blacklist-remove",1,{ textName:prefix+"blacklist remove", textDescription:lang.getTranslation("commands.blacklistRemove"), slashName:"/blacklist remove", @@ -185,7 +185,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"user",optional:false},{name:"reason",optional:true}], slashOptions:[{name:"user",optional:false},{name:"reason",optional:true}] })) - if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("openticket:blacklist-get",0,{ + if (allowedCommands.includes("blacklist")) admin.add(new api.ODHelpMenuCommandComponent("opendiscord:blacklist-get",0,{ textName:prefix+"blacklist get", textDescription:lang.getTranslation("commands.blacklistGet"), slashName:"/blacklist get", @@ -195,15 +195,15 @@ export const loadAllHelpMenuComponents = async () => { })) } - const advanced = helpmenu.get("openticket:advanced") + const advanced = helpmenu.get("opendiscord:advanced") if (advanced){ - if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:stats-global",5,{ + if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("opendiscord:stats-global",5,{ textName:prefix+"stats global", textDescription:lang.getTranslation("commands.statsGlobal"), slashName:"/stats global", slashDescription:lang.getTranslation("commands.statsGlobal") })) - if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:stats-ticket",4,{ + if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("opendiscord:stats-ticket",4,{ textName:prefix+"stats ticket", textDescription:lang.getTranslation("commands.statsTicket"), slashName:"/stats ticket", @@ -211,7 +211,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"ticket",optional:false}], slashOptions:[{name:"ticket",optional:false}] })) - if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:stats-user",2,{ + if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("opendiscord:stats-user",2,{ textName:prefix+"stats user", textDescription:lang.getTranslation("commands.statsUser"), slashName:"/stats user", @@ -219,7 +219,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"user",optional:false}], slashOptions:[{name:"user",optional:false}] })) - if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:stats-reset",2,{ + if (allowedCommands.includes("stats")) advanced.add(new api.ODHelpMenuCommandComponent("opendiscord:stats-reset",2,{ textName:prefix+"stats reset", textDescription:lang.getTranslation("commands.statsReset"), slashName:"/stats reset", @@ -227,7 +227,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"reason",optional:true}], slashOptions:[{name:"reason",optional:true}] })) - if (allowedCommands.includes("autoclose")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:autoclose-disable",1,{ + if (allowedCommands.includes("autoclose")) advanced.add(new api.ODHelpMenuCommandComponent("opendiscord:autoclose-disable",1,{ textName:prefix+"autoclose disable", textDescription:lang.getTranslation("commands.autocloseDisable"), slashName:"/autoclose disable", @@ -235,7 +235,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"reason",optional:true}], slashOptions:[{name:"reason",optional:true}] })) - if (allowedCommands.includes("autoclose")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:autoclose-enable",0,{ + if (allowedCommands.includes("autoclose")) advanced.add(new api.ODHelpMenuCommandComponent("opendiscord:autoclose-enable",0,{ textName:prefix+"autoclose enable", textDescription:lang.getTranslation("commands.autocloseEnable"), slashName:"/autoclose enable", @@ -243,7 +243,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"time",optional:false},{name:"reason",optional:true}], slashOptions:[{name:"time",optional:false},{name:"reason",optional:true}] })) - if (allowedCommands.includes("autodelete")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:autodelete-disable",1,{ + if (allowedCommands.includes("autodelete")) advanced.add(new api.ODHelpMenuCommandComponent("opendiscord:autodelete-disable",1,{ textName:prefix+"autodelete disable", textDescription:lang.getTranslation("commands.autodeleteDisable"), slashName:"/autodelete disable", @@ -251,7 +251,7 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"reason",optional:true}], slashOptions:[{name:"reason",optional:true}] })) - if (allowedCommands.includes("autodelete")) advanced.add(new api.ODHelpMenuCommandComponent("openticket:autodelete-enable",0,{ + if (allowedCommands.includes("autodelete")) advanced.add(new api.ODHelpMenuCommandComponent("opendiscord:autodelete-enable",0,{ textName:prefix+"autodelete enable", textDescription:lang.getTranslation("commands.autodeleteEnable"), slashName:"/autodelete enable", diff --git a/src/data/framework/languageLoader.ts b/src/data/framework/languageLoader.ts index 922ab19..ab200be 100644 --- a/src/data/framework/languageLoader.ts +++ b/src/data/framework/languageLoader.ts @@ -2,29 +2,29 @@ import {opendiscord, api, utilities} from "../../index" export const loadAllLanguages = async () => { //register languages - opendiscord.languages.add(new api.ODJsonLanguage("openticket:custom","custom.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:english","english.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:dutch","dutch.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:portuguese","portuguese.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:czech","czech.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:german","german.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:catalan","catalan.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:hungarian","hungarian.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:spanish","spanish.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:romanian","romanian.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:ukrainian","ukrainian.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:indonesian","indonesian.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:italian","italian.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:estonian","estonian.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:finnish","finnish.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:danish","danish.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:thai","thai.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:turkish","turkish.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:french","french.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:arabic","arabic.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:hindi","hindi.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:lithuanian","lithuanian.json")) - opendiscord.languages.add(new api.ODJsonLanguage("openticket:polish","polish.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:custom","custom.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:english","english.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:dutch","dutch.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:portuguese","portuguese.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:czech","czech.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:german","german.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:catalan","catalan.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:hungarian","hungarian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:spanish","spanish.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:romanian","romanian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:ukrainian","ukrainian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:indonesian","indonesian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:italian","italian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:estonian","estonian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:finnish","finnish.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:danish","danish.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:thai","thai.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:turkish","turkish.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:french","french.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:arabic","arabic.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:hindi","hindi.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:lithuanian","lithuanian.json")) + opendiscord.languages.add(new api.ODJsonLanguage("opendiscord:polish","polish.json")) /** How to add more languages? * - Register the language to the manager (see above) diff --git a/src/data/framework/liveStatusLoader.ts b/src/data/framework/liveStatusLoader.ts index a698e38..5aaaa74 100644 --- a/src/data/framework/liveStatusLoader.ts +++ b/src/data/framework/liveStatusLoader.ts @@ -2,5 +2,5 @@ import {opendiscord, api, utilities} from "../../index" export const loadAllLiveStatusSources = async () => { //DEFAULT DJDJ DEV - opendiscord.livestatus.add(new api.ODLiveStatusUrlSource("openticket:default-djdj-dev","https://raw.githubusercontent.com/DJj123dj/open-ticket/refs/heads/dev/src/livestatus.json")) + opendiscord.livestatus.add(new api.ODLiveStatusUrlSource("opendiscord:default-djdj-dev","https://raw.githubusercontent.com/DJj123dj/open-ticket/refs/heads/dev/src/livestatus.json")) } \ No newline at end of file diff --git a/src/data/framework/permissionLoader.ts b/src/data/framework/permissionLoader.ts index 8fc855a..0b33ae4 100644 --- a/src/data/framework/permissionLoader.ts +++ b/src/data/framework/permissionLoader.ts @@ -2,7 +2,7 @@ import {opendiscord, api, utilities} from "../../index" import * as discord from "discord.js" export const loadAllPermissions = async () => { - const generalConfig = opendiscord.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("opendiscord:general") if (!generalConfig) return const mainServer = opendiscord.client.mainServer if (!mainServer) return @@ -10,14 +10,14 @@ export const loadAllPermissions = async () => { //DEVELOPER & OWNER const developer = (await opendiscord.client.client.application.fetch()).owner if (developer instanceof discord.User){ - opendiscord.permissions.add(new api.ODPermission("openticket:developer-"+developer.id,"global-user","developer",developer)) + opendiscord.permissions.add(new api.ODPermission("opendiscord:developer-"+developer.id,"global-user","developer",developer)) }else if (developer instanceof discord.Team){ developer.members.forEach((member) => { - opendiscord.permissions.add(new api.ODPermission("openticket:developer-"+member.user.id,"global-user","developer",member.user)) + opendiscord.permissions.add(new api.ODPermission("opendiscord:developer-"+member.user.id,"global-user","developer",member.user)) }) } const owner = (await mainServer.members.fetch(mainServer.ownerId)).user - opendiscord.permissions.add(new api.ODPermission("openticket:owner-"+owner.id,"global-user","owner",owner)) + opendiscord.permissions.add(new api.ODPermission("opendiscord:owner-"+owner.id,"global-user","owner",owner)) //GLOBAL ADMINS generalConfig.data.globalAdmins.forEach(async (admin) => { @@ -26,7 +26,7 @@ export const loadAllPermissions = async () => { {key:"roleid",value:admin} ]) - opendiscord.permissions.add(new api.ODPermission("openticket:global-admin-"+admin,"global-role","admin",role)) + opendiscord.permissions.add(new api.ODPermission("opendiscord:global-admin-"+admin,"global-role","admin",role)) }) //TICKET ADMINS @@ -35,17 +35,17 @@ export const loadAllPermissions = async () => { const channel = await opendiscord.client.fetchGuildTextChannel(mainServer,ticket.id.value) if (!channel) return - const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] - const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] + const admins = ticket.option.exists("opendiscord:admins") ? ticket.option.get("opendiscord:admins").value : [] + const readAdmins = ticket.option.exists("opendiscord:admins-readonly") ? ticket.option.get("opendiscord:admins-readonly").value : [] for (const admin of admins.concat(readAdmins)){ - if (opendiscord.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return + if (opendiscord.permissions.exists("opendiscord:ticket-admin_"+ticket.id.value+"_"+admin)) return const role = await mainServer.roles.fetch(admin) if (!role) return opendiscord.log("Unable to register permission for ticket admin!","error",[ {key:"roleid",value:admin} ]) - opendiscord.permissions.add(new api.ODPermission("openticket:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) + opendiscord.permissions.add(new api.ODPermission("opendiscord:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) } }catch(err){ process.emit("uncaughtException",err) @@ -60,26 +60,26 @@ export const addTicketPermissions = async (ticket:api.ODTicket) => { const channel = await opendiscord.client.fetchGuildTextChannel(mainServer,ticket.id.value) if (!channel) return - const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] - const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] + const admins = ticket.option.exists("opendiscord:admins") ? ticket.option.get("opendiscord:admins").value : [] + const readAdmins = ticket.option.exists("opendiscord:admins-readonly") ? ticket.option.get("opendiscord:admins-readonly").value : [] for (const admin of admins.concat(readAdmins)){ - if (opendiscord.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return + if (opendiscord.permissions.exists("opendiscord:ticket-admin_"+ticket.id.value+"_"+admin)) return const role = await mainServer.roles.fetch(admin) if (!role) return opendiscord.log("Unable to register permission for ticket admin!","error",[ {key:"roleid",value:admin} ]) - opendiscord.permissions.add(new api.ODPermission("openticket:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) + opendiscord.permissions.add(new api.ODPermission("opendiscord:ticket-admin_"+ticket.id.value+"_"+admin,"channel-role","support",role,channel)) } } export const removeTicketPermissions = async (ticket:api.ODTicket) => { - const admins = ticket.option.exists("openticket:admins") ? ticket.option.get("openticket:admins").value : [] - const readAdmins = ticket.option.exists("openticket:admins-readonly") ? ticket.option.get("openticket:admins-readonly").value : [] + const admins = ticket.option.exists("opendiscord:admins") ? ticket.option.get("opendiscord:admins").value : [] + const readAdmins = ticket.option.exists("opendiscord:admins-readonly") ? ticket.option.get("opendiscord:admins-readonly").value : [] admins.concat(readAdmins).forEach(async (admin) => { - if (!opendiscord.permissions.exists("openticket:ticket-admin_"+ticket.id.value+"_"+admin)) return - opendiscord.permissions.remove("openticket:ticket-admin_"+ticket.id.value+"_"+admin) + if (!opendiscord.permissions.exists("opendiscord:ticket-admin_"+ticket.id.value+"_"+admin)) return + opendiscord.permissions.remove("opendiscord:ticket-admin_"+ticket.id.value+"_"+admin) }) } \ No newline at end of file diff --git a/src/data/framework/postLoader.ts b/src/data/framework/postLoader.ts index 4338c5f..4098ee1 100644 --- a/src/data/framework/postLoader.ts +++ b/src/data/framework/postLoader.ts @@ -1,14 +1,14 @@ import {opendiscord, api, utilities} from "../../index" export const loadAllPosts = async () => { - const generalConfig = opendiscord.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("opendiscord:general") if (!generalConfig) return - const transcriptConfig = opendiscord.configs.get("openticket:transcripts") + const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts") if (!transcriptConfig) return //LOGS CHANNEL - if (generalConfig.data.system.logs.enabled) opendiscord.posts.add(new api.ODPost("openticket:logs",generalConfig.data.system.logs.channel)) + if (generalConfig.data.system.logs.enabled) opendiscord.posts.add(new api.ODPost("opendiscord:logs",generalConfig.data.system.logs.channel)) //TRANSCRIPTS CHANNEL - if (transcriptConfig.data.general.enabled && transcriptConfig.data.general.enableChannel) opendiscord.posts.add(new api.ODPost("openticket:transcripts",transcriptConfig.data.general.channel)) + if (transcriptConfig.data.general.enabled && transcriptConfig.data.general.enableChannel) opendiscord.posts.add(new api.ODPost("opendiscord:transcripts",transcriptConfig.data.general.channel)) } \ No newline at end of file diff --git a/src/data/framework/progressBarLoader.ts b/src/data/framework/progressBarLoader.ts index 39a5a84..27795f4 100644 --- a/src/data/framework/progressBarLoader.ts +++ b/src/data/framework/progressBarLoader.ts @@ -25,43 +25,43 @@ export const loadAllProgressBarRenderers = async () => { //VALUE RENDERER const valueRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} valueRendererSettings.labelType = "value" - opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:value-renderer",valueRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("opendiscord:value-renderer",valueRendererSettings)) //FRACTION RENDERER const fractionRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} fractionRendererSettings.labelType = "fraction" - opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:fraction-renderer",fractionRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("opendiscord:fraction-renderer",fractionRendererSettings)) //PERCENTAGE RENDERER const percentageRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} percentageRendererSettings.labelType = "percentage" - opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:percentage-renderer",percentageRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("opendiscord:percentage-renderer",percentageRendererSettings)) //TIME MS RENDERER const timeMsRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} timeMsRendererSettings.labelType = "time-ms" - opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-ms-renderer",timeMsRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("opendiscord:time-ms-renderer",timeMsRendererSettings)) //TIME SEC RENDERER const timeSecRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} timeSecRendererSettings.labelType = "time-sec" - opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-sec-renderer",timeSecRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("opendiscord:time-sec-renderer",timeSecRendererSettings)) //TIME MIN RENDERER const timeMinRendererSettings: api.ODProgressBarRenderer_DefaultSettings = {...defaultSettings} timeMinRendererSettings.labelType = "time-min" - opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("openticket:time-min-renderer",timeMinRendererSettings)) + opendiscord.progressbars.renderers.add(new api.ODProgressBarRenderer_Default("opendiscord:time-min-renderer",timeMinRendererSettings)) } export const loadAllProgressBars = async () => { - const fractRenderer = opendiscord.progressbars.renderers.get("openticket:fraction-renderer") + const fractRenderer = opendiscord.progressbars.renderers.get("opendiscord:fraction-renderer") //SLASH COMMAND REMOVE (doesn't have correct amount yet) - opendiscord.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-remove",fractRenderer.withAdditionalSettings({filledBarColor:"red"}),0,"max",null,"Commands Removed")) + opendiscord.progressbars.add(new api.ODManualProgressBar("opendiscord:slash-command-remove",fractRenderer.withAdditionalSettings({filledBarColor:"red"}),0,"max",null,"Commands Removed")) //SLASH COMMAND CREATE (doesn't have correct amount yet) - opendiscord.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-create",fractRenderer.withAdditionalSettings({filledBarColor:"green"}),0,"max",null,"Commands Created")) + opendiscord.progressbars.add(new api.ODManualProgressBar("opendiscord:slash-command-create",fractRenderer.withAdditionalSettings({filledBarColor:"green"}),0,"max",null,"Commands Created")) //SLASH COMMAND UPDATE (doesn't have correct amount yet) - opendiscord.progressbars.add(new api.ODManualProgressBar("openticket:slash-command-update",fractRenderer.withAdditionalSettings({filledBarColor:"openticket"}),0,"max",null,"Commands Updated")) + opendiscord.progressbars.add(new api.ODManualProgressBar("opendiscord:slash-command-update",fractRenderer.withAdditionalSettings({filledBarColor:"openticket"}),0,"max",null,"Commands Updated")) } \ No newline at end of file diff --git a/src/data/framework/startScreenLoader.ts b/src/data/framework/startScreenLoader.ts index 48c4329..b80d7dc 100644 --- a/src/data/framework/startScreenLoader.ts +++ b/src/data/framework/startScreenLoader.ts @@ -3,7 +3,7 @@ import ansis from "ansis" export const loadAllStartScreenComponents = async () => { //LOGO - opendiscord.startscreen.add(new api.ODStartScreenLogoComponent("openticket:logo",1000,[ + opendiscord.startscreen.add(new api.ODStartScreenLogoComponent("opendiscord:logo",1000,[ " ██████╗ ██████╗ ███████╗███╗ ██╗ ████████╗██╗ ██████╗██╗ ██╗███████╗████████╗ ", " ██╔═══██╗██╔══██╗██╔════╝████╗ ██║ ╚══██╔══╝██║██╔════╝██║ ██╔╝██╔════╝╚══██╔══╝ ", " ██║ ██║██████╔╝█████╗ ██╔██╗ ██║ ██║ ██║██║ █████╔╝ █████╗ ██║ ", @@ -14,34 +14,34 @@ export const loadAllStartScreenComponents = async () => { //HEADER const currentLanguageMetadata = opendiscord.languages.getLanguageMetadata() - opendiscord.startscreen.add(new api.ODStartScreenHeaderComponent("openticket:header",999,[ - {key:"Version",value:opendiscord.versions.get("openticket:version").toString()}, + opendiscord.startscreen.add(new api.ODStartScreenHeaderComponent("opendiscord:header",999,[ + {key:"Version",value:opendiscord.versions.get("opendiscord:version").toString()}, {key:"Support",value:"https://discord.dj-dj.be"}, {key:"Language",value:(currentLanguageMetadata ? currentLanguageMetadata.language : "Unknown")} ]," - ",{ align:"center", - width:opendiscord.startscreen.get("openticket:logo") + width:opendiscord.startscreen.get("opendiscord:logo") })) //FLAGS - opendiscord.startscreen.add(new api.ODStartScreenFlagsCategoryComponent("openticket:flags",4,opendiscord.flags.getAll())) + opendiscord.startscreen.add(new api.ODStartScreenFlagsCategoryComponent("opendiscord:flags",4,opendiscord.flags.getAll())) //PLUGINS - opendiscord.startscreen.add(new api.ODStartScreenPluginsCategoryComponent("openticket:plugins",3,opendiscord.plugins.getAll(),opendiscord.plugins.unknownCrashedPlugins)) + opendiscord.startscreen.add(new api.ODStartScreenPluginsCategoryComponent("opendiscord:plugins",3,opendiscord.plugins.getAll(),opendiscord.plugins.unknownCrashedPlugins)) //STATS - opendiscord.startscreen.add(new api.ODStartScreenPropertiesCategoryComponent("openticket:stats",2,"startup info",[ + opendiscord.startscreen.add(new api.ODStartScreenPropertiesCategoryComponent("opendiscord:stats",2,"startup info",[ {key:"status",value:ansis.bold(opendiscord.client.activity.getStatusType())+opendiscord.client.activity.text+" ("+opendiscord.client.activity.status+")"}, {key:"options",value:"loaded "+ansis.bold(opendiscord.options.getLength().toString())+" options!"}, {key:"panels",value:"loaded "+ansis.bold(opendiscord.panels.getLength().toString())+" panels!"}, {key:"tickets",value:"loaded "+ansis.bold(opendiscord.tickets.getLength().toString())+" tickets!"}, {key:"roles",value:"loaded "+ansis.bold(opendiscord.roles.getLength().toString())+" roles!"}, - {key:"help",value:ansis.bold(opendiscord.configs.get("openticket:general").data.prefix+"help")+" or "+ansis.bold("/help")} + {key:"help",value:ansis.bold(opendiscord.configs.get("opendiscord:general").data.prefix+"help")+" or "+ansis.bold("/help")} ])) //LIVESTATUS - opendiscord.startscreen.add(new api.ODStartScreenLiveStatusCategoryComponent("openticket:livestatus",1,opendiscord.livestatus)) + opendiscord.startscreen.add(new api.ODStartScreenLiveStatusCategoryComponent("opendiscord:livestatus",1,opendiscord.livestatus)) //LOGS - opendiscord.startscreen.add(new api.ODStartScreenLogCategoryComponent("openticket:logs",0)) + opendiscord.startscreen.add(new api.ODStartScreenLogCategoryComponent("opendiscord:logs",0)) } \ No newline at end of file diff --git a/src/data/framework/statLoader.ts b/src/data/framework/statLoader.ts index 22f5505..7f56020 100644 --- a/src/data/framework/statLoader.ts +++ b/src/data/framework/statLoader.ts @@ -5,48 +5,48 @@ const stats = opendiscord.stats const lang = opendiscord.languages export const loadAllStatScopes = async () => { - stats.add(new api.ODStatGlobalScope("openticket:global",utilities.emojiTitle("📊",lang.getTranslation("stats.scopes.global")))) - stats.add(new api.ODStatGlobalScope("openticket:system",utilities.emojiTitle("⚙️",lang.getTranslation("stats.scopes.system")))) - stats.add(new api.ODStatScope("openticket:user",utilities.emojiTitle("📊",lang.getTranslation("stats.scopes.user")))) - stats.add(new api.ODStatScope("openticket:ticket",utilities.emojiTitle("📊",lang.getTranslation("stats.scopes.ticket")))) - stats.add(new api.ODStatScope("openticket:participants",utilities.emojiTitle("👥",lang.getTranslation("stats.scopes.participants")))) + stats.add(new api.ODStatGlobalScope("opendiscord:global",utilities.emojiTitle("📊",lang.getTranslation("stats.scopes.global")))) + stats.add(new api.ODStatGlobalScope("opendiscord:system",utilities.emojiTitle("⚙️",lang.getTranslation("stats.scopes.system")))) + stats.add(new api.ODStatScope("opendiscord:user",utilities.emojiTitle("📊",lang.getTranslation("stats.scopes.user")))) + stats.add(new api.ODStatScope("opendiscord:ticket",utilities.emojiTitle("📊",lang.getTranslation("stats.scopes.ticket")))) + stats.add(new api.ODStatScope("opendiscord:participants",utilities.emojiTitle("👥",lang.getTranslation("stats.scopes.participants")))) } export const loadAllStats = async () => { - const generalConfig = opendiscord.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("opendiscord:general") if (!generalConfig) return - const global = stats.get("openticket:global") + const global = stats.get("opendiscord:global") if (global){ - global.add(new api.ODBasicStat("openticket:tickets-created",10,lang.getTranslation("stats.properties.ticketsCreated"),0)) - global.add(new api.ODBasicStat("openticket:tickets-closed",9,lang.getTranslation("stats.properties.ticketsClosed"),0)) - global.add(new api.ODBasicStat("openticket:tickets-deleted",8,lang.getTranslation("stats.properties.ticketsDeleted"),0)) - global.add(new api.ODBasicStat("openticket:tickets-reopened",7,lang.getTranslation("stats.properties.ticketsReopened"),0)) - global.add(new api.ODBasicStat("openticket:tickets-autoclosed",6,lang.getTranslation("stats.properties.ticketsAutoclosed"),0)) - global.add(new api.ODBasicStat("openticket:tickets-autodeleted",5,"Tickets Autodeleted",0)) //TODO TRANSLATION!!! - global.add(new api.ODBasicStat("openticket:tickets-claimed",4,lang.getTranslation("stats.properties.ticketsClaimed"),0)) - global.add(new api.ODBasicStat("openticket:tickets-pinned",3,lang.getTranslation("stats.properties.ticketsPinned"),0)) - global.add(new api.ODBasicStat("openticket:tickets-moved",2,lang.getTranslation("stats.properties.ticketsMoved"),0)) - global.add(new api.ODBasicStat("openticket:users-blacklisted",1,lang.getTranslation("stats.properties.usersBlacklisted"),0)) - global.add(new api.ODBasicStat("openticket:transcripts-created",0,lang.getTranslation("stats.properties.transcriptsCreated"),0)) + global.add(new api.ODBasicStat("opendiscord:tickets-created",10,lang.getTranslation("stats.properties.ticketsCreated"),0)) + global.add(new api.ODBasicStat("opendiscord:tickets-closed",9,lang.getTranslation("stats.properties.ticketsClosed"),0)) + global.add(new api.ODBasicStat("opendiscord:tickets-deleted",8,lang.getTranslation("stats.properties.ticketsDeleted"),0)) + global.add(new api.ODBasicStat("opendiscord:tickets-reopened",7,lang.getTranslation("stats.properties.ticketsReopened"),0)) + global.add(new api.ODBasicStat("opendiscord:tickets-autoclosed",6,lang.getTranslation("stats.properties.ticketsAutoclosed"),0)) + global.add(new api.ODBasicStat("opendiscord:tickets-autodeleted",5,"Tickets Autodeleted",0)) //TODO TRANSLATION!!! + global.add(new api.ODBasicStat("opendiscord:tickets-claimed",4,lang.getTranslation("stats.properties.ticketsClaimed"),0)) + global.add(new api.ODBasicStat("opendiscord:tickets-pinned",3,lang.getTranslation("stats.properties.ticketsPinned"),0)) + global.add(new api.ODBasicStat("opendiscord:tickets-moved",2,lang.getTranslation("stats.properties.ticketsMoved"),0)) + global.add(new api.ODBasicStat("opendiscord:users-blacklisted",1,lang.getTranslation("stats.properties.usersBlacklisted"),0)) + global.add(new api.ODBasicStat("opendiscord:transcripts-created",0,lang.getTranslation("stats.properties.transcriptsCreated"),0)) } - const system = stats.get("openticket:system") + const system = stats.get("opendiscord:system") if (system){ - system.add(new api.ODDynamicStat("openticket:startup-date",1,() => { + system.add(new api.ODDynamicStat("opendiscord:startup-date",1,() => { return lang.getTranslation("params.uppercase.startupDate")+": "+discord.time(opendiscord.processStartupDate,"f") })) - system.add(new api.ODDynamicStat("openticket:version",0,() => { - return lang.getTranslation("params.uppercase.version")+": `"+opendiscord.versions.get("openticket:version").toString()+"`" + system.add(new api.ODDynamicStat("opendiscord:version",0,() => { + return lang.getTranslation("params.uppercase.version")+": `"+opendiscord.versions.get("opendiscord:version").toString()+"`" })) } - const user = stats.get("openticket:user") + const user = stats.get("opendiscord:user") if (user){ - user.add(new api.ODDynamicStat("openticket:name",11,async (scopeId,guild,channel,user) => { + user.add(new api.ODDynamicStat("opendiscord:name",11,async (scopeId,guild,channel,user) => { return lang.getTranslation("params.uppercase.name")+": "+discord.userMention(scopeId) })) - user.add(new api.ODDynamicStat("openticket:role",10,async (scopeId,guild,channel,user) => { + user.add(new api.ODDynamicStat("opendiscord:role",10,async (scopeId,guild,channel,user) => { try{ const scopeMember = await guild.members.fetch(scopeId) if (!scopeMember) return "" @@ -62,67 +62,67 @@ export const loadAllStats = async () => { return "" } })) - user.add(new api.ODBasicStat("openticket:tickets-created",8,lang.getTranslation("stats.properties.ticketsCreated"),0)) - user.add(new api.ODBasicStat("openticket:tickets-closed",7,lang.getTranslation("stats.properties.ticketsClosed"),0)) - user.add(new api.ODBasicStat("openticket:tickets-deleted",6,lang.getTranslation("stats.properties.ticketsDeleted"),0)) - user.add(new api.ODBasicStat("openticket:tickets-reopened",5,lang.getTranslation("stats.properties.ticketsReopened"),0)) - user.add(new api.ODBasicStat("openticket:tickets-claimed",4,lang.getTranslation("stats.properties.ticketsClaimed"),0)) - user.add(new api.ODBasicStat("openticket:tickets-pinned",3,lang.getTranslation("stats.properties.ticketsPinned"),0)) - user.add(new api.ODBasicStat("openticket:tickets-moved",2,lang.getTranslation("stats.properties.ticketsMoved"),0)) - user.add(new api.ODBasicStat("openticket:users-blacklisted",1,lang.getTranslation("stats.properties.usersBlacklisted"),0)) - user.add(new api.ODBasicStat("openticket:transcripts-created",0,lang.getTranslation("stats.properties.transcriptsCreated"),0)) + user.add(new api.ODBasicStat("opendiscord:tickets-created",8,lang.getTranslation("stats.properties.ticketsCreated"),0)) + user.add(new api.ODBasicStat("opendiscord:tickets-closed",7,lang.getTranslation("stats.properties.ticketsClosed"),0)) + user.add(new api.ODBasicStat("opendiscord:tickets-deleted",6,lang.getTranslation("stats.properties.ticketsDeleted"),0)) + user.add(new api.ODBasicStat("opendiscord:tickets-reopened",5,lang.getTranslation("stats.properties.ticketsReopened"),0)) + user.add(new api.ODBasicStat("opendiscord:tickets-claimed",4,lang.getTranslation("stats.properties.ticketsClaimed"),0)) + user.add(new api.ODBasicStat("opendiscord:tickets-pinned",3,lang.getTranslation("stats.properties.ticketsPinned"),0)) + user.add(new api.ODBasicStat("opendiscord:tickets-moved",2,lang.getTranslation("stats.properties.ticketsMoved"),0)) + user.add(new api.ODBasicStat("opendiscord:users-blacklisted",1,lang.getTranslation("stats.properties.usersBlacklisted"),0)) + user.add(new api.ODBasicStat("opendiscord:transcripts-created",0,lang.getTranslation("stats.properties.transcriptsCreated"),0)) } - const ticket = stats.get("openticket:ticket") + const ticket = stats.get("opendiscord:ticket") if (ticket){ - ticket.add(new api.ODDynamicStat("openticket:name",5,async (scopeId,guild,channel,user) => { + ticket.add(new api.ODDynamicStat("opendiscord:name",5,async (scopeId,guild,channel,user) => { return lang.getTranslation("params.uppercase.ticket")+": "+discord.channelMention(scopeId) })) - ticket.add(new api.ODDynamicStat("openticket:status",4,async (scopeId,guild,channel,user) => { + ticket.add(new api.ODDynamicStat("opendiscord:status",4,async (scopeId,guild,channel,user) => { const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" - const closed = ticket.exists("openticket:closed") ? ticket.get("openticket:closed").value : false + const closed = ticket.exists("opendiscord:closed") ? ticket.get("opendiscord:closed").value : false return closed ? lang.getTranslation("params.uppercase.status")+": 🔒 `Closed`" : lang.getTranslation("params.uppercase.status")+": 🔓 `Open`" //TODO TRANSLATION!!! })) - ticket.add(new api.ODDynamicStat("openticket:claimed",3,async (scopeId,guild,channel,user) => { + ticket.add(new api.ODDynamicStat("opendiscord:claimed",3,async (scopeId,guild,channel,user) => { const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" - const claimed = ticket.exists("openticket:claimed") ? ticket.get("openticket:claimed").value : false + const claimed = ticket.exists("opendiscord:claimed") ? ticket.get("opendiscord:claimed").value : false return claimed ? lang.getTranslation("params.uppercase.claimed")+": 🟢 `Yes`" : lang.getTranslation("params.uppercase.claimed")+": 🔴 `No`" //TODO TRANSLATION!!! })) - ticket.add(new api.ODDynamicStat("openticket:pinned",2,async (scopeId,guild,channel,user) => { + ticket.add(new api.ODDynamicStat("opendiscord:pinned",2,async (scopeId,guild,channel,user) => { const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" - const pinned = ticket.exists("openticket:pinned") ? ticket.get("openticket:pinned").value : false + const pinned = ticket.exists("opendiscord:pinned") ? ticket.get("opendiscord:pinned").value : false return pinned ? lang.getTranslation("params.uppercase.pinned")+": 🟢 `Yes`" : lang.getTranslation("params.uppercase.pinned")+": 🔴 `No`" //TODO TRANSLATION!!! })) - ticket.add(new api.ODDynamicStat("openticket:creation-date",1,async (scopeId,guild,channel,user) => { + ticket.add(new api.ODDynamicStat("opendiscord:creation-date",1,async (scopeId,guild,channel,user) => { const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" - const rawDate = ticket.get("openticket:opened-on").value ?? new Date().getTime() + const rawDate = ticket.get("opendiscord:opened-on").value ?? new Date().getTime() return lang.getTranslation("params.uppercase.creationDate")+": "+discord.time(new Date(rawDate),"f") })) - ticket.add(new api.ODDynamicStat("openticket:creator",0,async (scopeId,guild,channel,user) => { + ticket.add(new api.ODDynamicStat("opendiscord:creator",0,async (scopeId,guild,channel,user) => { const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" - const creator = ticket.get("openticket:opened-by").value + const creator = ticket.get("opendiscord:opened-by").value return lang.getTranslation("params.uppercase.creator")+": "+ (creator ? discord.userMention(creator) : "`unknown`") })) } - const participants = stats.get("openticket:participants") + const participants = stats.get("opendiscord:participants") if (participants){ - participants.add(new api.ODDynamicStat("openticket:participants",0,async (scopeId,guild,channel,user) => { + participants.add(new api.ODDynamicStat("opendiscord:participants",0,async (scopeId,guild,channel,user) => { const ticket = opendiscord.tickets.get(scopeId) if (!ticket) return "" - const participants = ticket.exists("openticket:participants") ? ticket.get("openticket:participants").value : [] + const participants = ticket.exists("opendiscord:participants") ? ticket.get("opendiscord:participants").value : [] return participants.map((p) => { return (p.type == "role") ? discord.roleMention(p.id) : discord.userMention(p.id) diff --git a/src/data/openticket/blacklistLoader.ts b/src/data/openticket/blacklistLoader.ts index 25e6d3e..6e8ed6a 100644 --- a/src/data/openticket/blacklistLoader.ts +++ b/src/data/openticket/blacklistLoader.ts @@ -1,10 +1,10 @@ import {opendiscord, api, utilities} from "../../index" export const loadAllBlacklistedUsers = async () => { - const userDatabase = opendiscord.databases.get("openticket:users") + const userDatabase = opendiscord.databases.get("opendiscord:users") if (!userDatabase) return - const users = await userDatabase.getCategory("openticket:blacklist") ?? [] + const users = await userDatabase.getCategory("opendiscord:blacklist") ?? [] users.forEach((user) => { if (typeof user.value == "string" || user.value === null) opendiscord.blacklist.add(new api.ODBlacklist(user.key,user.value)) }) diff --git a/src/data/openticket/optionLoader.ts b/src/data/openticket/optionLoader.ts index 138ba95..302f7d2 100644 --- a/src/data/openticket/optionLoader.ts +++ b/src/data/openticket/optionLoader.ts @@ -1,7 +1,7 @@ import {opendiscord, api, utilities} from "../../index" export const loadAllOptions = async () => { - const optionConfig = opendiscord.configs.get("openticket:options") + const optionConfig = opendiscord.configs.get("opendiscord:options") if (!optionConfig) return optionConfig.data.forEach((option) => { @@ -56,85 +56,85 @@ export const loadAllOptions = async () => { export const loadTicketOption = (option:api.ODJsonConfig_DefaultOptionTicketType): api.ODTicketOption => { return new api.ODTicketOption(option.id,[ - new api.ODOptionData("openticket:name",option.name), - new api.ODOptionData("openticket:description",option.description), + new api.ODOptionData("opendiscord:name",option.name), + new api.ODOptionData("opendiscord:description",option.description), - new api.ODOptionData("openticket:button-emoji",option.button.emoji), - new api.ODOptionData("openticket:button-label",option.button.label), - new api.ODOptionData("openticket:button-color",option.button.color), + new api.ODOptionData("opendiscord:button-emoji",option.button.emoji), + new api.ODOptionData("opendiscord:button-label",option.button.label), + new api.ODOptionData("opendiscord:button-color",option.button.color), - new api.ODOptionData("openticket:admins",option.ticketAdmins), - new api.ODOptionData("openticket:admins-readonly",option.readonlyAdmins), - new api.ODOptionData("openticket:allow-blacklisted-users",option.allowCreationByBlacklistedUsers), - new api.ODOptionData("openticket:questions",option.questions), + new api.ODOptionData("opendiscord:admins",option.ticketAdmins), + new api.ODOptionData("opendiscord:admins-readonly",option.readonlyAdmins), + new api.ODOptionData("opendiscord:allow-blacklisted-users",option.allowCreationByBlacklistedUsers), + new api.ODOptionData("opendiscord:questions",option.questions), - new api.ODOptionData("openticket:channel-prefix",option.channel.prefix), - new api.ODOptionData("openticket:channel-suffix",option.channel.suffix), - new api.ODOptionData("openticket:channel-category",option.channel.category), - new api.ODOptionData("openticket:channel-category-closed",option.channel.closedCategory), - new api.ODOptionData("openticket:channel-category-backup",option.channel.backupCategory), - new api.ODOptionData("openticket:channel-categories-claimed",option.channel.claimedCategory), - new api.ODOptionData("openticket:channel-description",option.channel.description), + new api.ODOptionData("opendiscord:channel-prefix",option.channel.prefix), + new api.ODOptionData("opendiscord:channel-suffix",option.channel.suffix), + new api.ODOptionData("opendiscord:channel-category",option.channel.category), + new api.ODOptionData("opendiscord:channel-category-closed",option.channel.closedCategory), + new api.ODOptionData("opendiscord:channel-category-backup",option.channel.backupCategory), + new api.ODOptionData("opendiscord:channel-categories-claimed",option.channel.claimedCategory), + new api.ODOptionData("opendiscord:channel-description",option.channel.description), - new api.ODOptionData("openticket:dm-message-enabled",option.dmMessage.enabled), - new api.ODOptionData("openticket:dm-message-text",option.dmMessage.text), - new api.ODOptionData("openticket:dm-message-embed",option.dmMessage.embed), + new api.ODOptionData("opendiscord:dm-message-enabled",option.dmMessage.enabled), + new api.ODOptionData("opendiscord:dm-message-text",option.dmMessage.text), + new api.ODOptionData("opendiscord:dm-message-embed",option.dmMessage.embed), - new api.ODOptionData("openticket:ticket-message-enabled",option.ticketMessage.enabled), - new api.ODOptionData("openticket:ticket-message-text",option.ticketMessage.text), - new api.ODOptionData("openticket:ticket-message-embed",option.ticketMessage.embed), - new api.ODOptionData("openticket:ticket-message-ping",option.ticketMessage.ping), + new api.ODOptionData("opendiscord:ticket-message-enabled",option.ticketMessage.enabled), + new api.ODOptionData("opendiscord:ticket-message-text",option.ticketMessage.text), + new api.ODOptionData("opendiscord:ticket-message-embed",option.ticketMessage.embed), + new api.ODOptionData("opendiscord:ticket-message-ping",option.ticketMessage.ping), - new api.ODOptionData("openticket:autoclose-enable-hours",option.autoclose.enableInactiveHours), - new api.ODOptionData("openticket:autoclose-enable-leave",option.autoclose.enableUserLeave), - new api.ODOptionData("openticket:autoclose-disable-claim",option.autoclose.disableOnClaim), - new api.ODOptionData("openticket:autoclose-hours",option.autoclose.inactiveHours), + new api.ODOptionData("opendiscord:autoclose-enable-hours",option.autoclose.enableInactiveHours), + new api.ODOptionData("opendiscord:autoclose-enable-leave",option.autoclose.enableUserLeave), + new api.ODOptionData("opendiscord:autoclose-disable-claim",option.autoclose.disableOnClaim), + new api.ODOptionData("opendiscord:autoclose-hours",option.autoclose.inactiveHours), - new api.ODOptionData("openticket:autodelete-enable-days",option.autodelete.enableInactiveDays), - new api.ODOptionData("openticket:autodelete-enable-leave",option.autodelete.enableUserLeave), - new api.ODOptionData("openticket:autodelete-disable-claim",option.autodelete.disableOnClaim), - new api.ODOptionData("openticket:autodelete-days",option.autodelete.inactiveDays), + new api.ODOptionData("opendiscord:autodelete-enable-days",option.autodelete.enableInactiveDays), + new api.ODOptionData("opendiscord:autodelete-enable-leave",option.autodelete.enableUserLeave), + new api.ODOptionData("opendiscord:autodelete-disable-claim",option.autodelete.disableOnClaim), + new api.ODOptionData("opendiscord:autodelete-days",option.autodelete.inactiveDays), - new api.ODOptionData("openticket:cooldown-enabled",option.cooldown.enabled), - new api.ODOptionData("openticket:cooldown-minutes",option.cooldown.cooldownMinutes), + new api.ODOptionData("opendiscord:cooldown-enabled",option.cooldown.enabled), + new api.ODOptionData("opendiscord:cooldown-minutes",option.cooldown.cooldownMinutes), - new api.ODOptionData("openticket:limits-enabled",option.limits.enabled), - new api.ODOptionData("openticket:limits-maximum-global",option.limits.globalMaximum), - new api.ODOptionData("openticket:limits-maximum-user",option.limits.userMaximum) + new api.ODOptionData("opendiscord:limits-enabled",option.limits.enabled), + new api.ODOptionData("opendiscord:limits-maximum-global",option.limits.globalMaximum), + new api.ODOptionData("opendiscord:limits-maximum-user",option.limits.userMaximum) ]) } export const loadWebsiteOption = (opt:api.ODJsonConfig_DefaultOptionWebsiteType): api.ODWebsiteOption => { return new api.ODWebsiteOption(opt.id,[ - new api.ODOptionData("openticket:name",opt.name), - new api.ODOptionData("openticket:description",opt.description), + new api.ODOptionData("opendiscord:name",opt.name), + new api.ODOptionData("opendiscord:description",opt.description), - new api.ODOptionData("openticket:button-emoji",opt.button.emoji), - new api.ODOptionData("openticket:button-label",opt.button.label), + new api.ODOptionData("opendiscord:button-emoji",opt.button.emoji), + new api.ODOptionData("opendiscord:button-label",opt.button.label), - new api.ODOptionData("openticket:url",opt.url) + new api.ODOptionData("opendiscord:url",opt.url) ]) } export const loadRoleOption = (opt:api.ODJsonConfig_DefaultOptionRoleType): api.ODRoleOption => { return new api.ODRoleOption(opt.id,[ - new api.ODOptionData("openticket:name",opt.name), - new api.ODOptionData("openticket:description",opt.description), + new api.ODOptionData("opendiscord:name",opt.name), + new api.ODOptionData("opendiscord:description",opt.description), - new api.ODOptionData("openticket:button-emoji",opt.button.emoji), - new api.ODOptionData("openticket:button-label",opt.button.label), - new api.ODOptionData("openticket:button-color",opt.button.color), + new api.ODOptionData("opendiscord:button-emoji",opt.button.emoji), + new api.ODOptionData("opendiscord:button-label",opt.button.label), + new api.ODOptionData("opendiscord:button-color",opt.button.color), - new api.ODOptionData("openticket:roles",opt.roles), - new api.ODOptionData("openticket:mode",opt.mode), - new api.ODOptionData("openticket:remove-roles-on-add",opt.removeRolesOnAdd), - new api.ODOptionData("openticket:add-on-join",opt.addOnMemberJoin) + new api.ODOptionData("opendiscord:roles",opt.roles), + new api.ODOptionData("opendiscord:mode",opt.mode), + new api.ODOptionData("opendiscord:remove-roles-on-add",opt.removeRolesOnAdd), + new api.ODOptionData("opendiscord:add-on-join",opt.addOnMemberJoin) ]) } export const loadTicketOptionSuffix = (option:api.ODTicketOption): api.ODOptionSuffix => { - const mode = option.get("openticket:channel-suffix").value - const globalDatabase = opendiscord.databases.get("openticket:global") + const mode = option.get("opendiscord:channel-suffix").value + const globalDatabase = opendiscord.databases.get("opendiscord:global") if (mode == "user-name") return new api.ODOptionUserNameSuffix(option.id.value,option) else if (mode == "random-number") return new api.ODOptionRandomNumberSuffix(option.id.value,option,globalDatabase) else if (mode == "random-hex") return new api.ODOptionRandomHexSuffix(option.id.value,option,globalDatabase) diff --git a/src/data/openticket/panelLoader.ts b/src/data/openticket/panelLoader.ts index 0b55c67..3820ae0 100644 --- a/src/data/openticket/panelLoader.ts +++ b/src/data/openticket/panelLoader.ts @@ -2,7 +2,7 @@ import {opendiscord, api, utilities} from "../../index" import * as discord from "discord.js" export const loadAllPanels = async () => { - const panelConfig = opendiscord.configs.get("openticket:panels") + const panelConfig = opendiscord.configs.get("opendiscord:panels") if (!panelConfig) return panelConfig.data.forEach((panel) => { @@ -23,28 +23,28 @@ export const loadAllPanels = async () => { export const loadPanel = (panel:api.ODJsonConfig_DefaultPanelType) => { return new api.ODPanel(panel.id,[ - new api.ODPanelData("openticket:name",panel.name), - new api.ODPanelData("openticket:options",panel.options), - new api.ODPanelData("openticket:dropdown",panel.dropdown), + new api.ODPanelData("opendiscord:name",panel.name), + new api.ODPanelData("opendiscord:options",panel.options), + new api.ODPanelData("opendiscord:dropdown",panel.dropdown), - new api.ODPanelData("openticket:text",panel.text), - new api.ODPanelData("openticket:embed",panel.embed), + new api.ODPanelData("opendiscord:text",panel.text), + new api.ODPanelData("opendiscord:embed",panel.embed), - new api.ODPanelData("openticket:dropdown-placeholder",panel.settings.dropdownPlaceholder), - new api.ODPanelData("openticket:enable-max-tickets-warning-text",panel.settings.enableMaxTicketsWarningInText), - new api.ODPanelData("openticket:enable-max-tickets-warning-embed",panel.settings.enableMaxTicketsWarningInEmbed), - new api.ODPanelData("openticket:describe-options-layout",panel.settings.describeOptionsLayout), - new api.ODPanelData("openticket:describe-options-custom-title",panel.settings.describeOptionsCustomTitle), - new api.ODPanelData("openticket:describe-options-in-text",panel.settings.describeOptionsInText), - new api.ODPanelData("openticket:describe-options-in-embed-fields",panel.settings.describeOptionsInEmbedFields), - new api.ODPanelData("openticket:describe-options-in-embed-description",panel.settings.describeOptionsInEmbedDescription), + new api.ODPanelData("opendiscord:dropdown-placeholder",panel.settings.dropdownPlaceholder), + new api.ODPanelData("opendiscord:enable-max-tickets-warning-text",panel.settings.enableMaxTicketsWarningInText), + new api.ODPanelData("opendiscord:enable-max-tickets-warning-embed",panel.settings.enableMaxTicketsWarningInEmbed), + new api.ODPanelData("opendiscord:describe-options-layout",panel.settings.describeOptionsLayout), + new api.ODPanelData("opendiscord:describe-options-custom-title",panel.settings.describeOptionsCustomTitle), + new api.ODPanelData("opendiscord:describe-options-in-text",panel.settings.describeOptionsInText), + new api.ODPanelData("opendiscord:describe-options-in-embed-fields",panel.settings.describeOptionsInEmbedFields), + new api.ODPanelData("opendiscord:describe-options-in-embed-description",panel.settings.describeOptionsInEmbedDescription), ]) } export function describePanelOptions(mode:"fields",panel:api.ODPanel): {name:string,value:string}[] export function describePanelOptions(mode:"text",panel:api.ODPanel): string export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): {name:string,value:string}[]|string { - const layout = panel.get("openticket:describe-options-layout").value - const dropdownMode = panel.get("openticket:dropdown").value + const layout = panel.get("opendiscord:describe-options-layout").value + const dropdownMode = panel.get("opendiscord:dropdown").value const options: api.ODOption[] = [] let hasTicket = false let hasWebsite = false @@ -52,7 +52,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { let ticketOnly = true let websiteOnly = true let roleOnly = true - panel.get("openticket:options").value.forEach((id) => { + panel.get("opendiscord:options").value.forEach((id) => { const opt = opendiscord.options.get(id) if (opt){ if (opt instanceof api.ODTicketOption){ @@ -76,24 +76,24 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { //TODO TRANSLATION!!! const autotitle = (hasTicket && ticketOnly) ? "Select your ticket:" : ((hasRole && roleOnly) ? "Select your role:" : "Select your option:") - const title = (panel.get("openticket:describe-options-custom-title").value.length < 1) ? "__"+autotitle+"__\n" : "__"+panel.get("openticket:describe-options-custom-title").value+"__\n" + const title = (panel.get("opendiscord:describe-options-custom-title").value.length < 1) ? "__"+autotitle+"__\n" : "__"+panel.get("opendiscord:describe-options-custom-title").value+"__\n" if (mode == "fields") return options.map((opt) => { if (opt instanceof api.ODTicketOption){ //ticket option - const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" - const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" - let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + const emoji = opt.exists("opendiscord:button-emoji") ? opt.get("opendiscord:button-emoji").value : "" + const name = opt.exists("opendiscord:name") ? opt.get("opendiscord:name").value : "``" + let description = opt.exists("opendiscord:description") ? opt.get("opendiscord:description").value : "``" if (layout == "normal" || layout == "detailed"){ //TODO TRANSLATION!!! - if (opt.exists("openticket:cooldown-enabled") && opt.get("openticket:cooldown-enabled").value) description = description + "\nCooldown: `"+opt.get("openticket:cooldown-minutes").value+" min`" + if (opt.exists("opendiscord:cooldown-enabled") && opt.get("opendiscord:cooldown-enabled").value) description = description + "\nCooldown: `"+opt.get("opendiscord:cooldown-minutes").value+" min`" //TODO TRANSLATION!!! - if (opt.exists("openticket:limits-enabled") && opt.get("openticket:limits-enabled").value) description = description + "\nMax Tickets: `"+opt.get("openticket:limits-maximum-user").value+"`" + if (opt.exists("opendiscord:limits-enabled") && opt.get("opendiscord:limits-enabled").value) description = description + "\nMax Tickets: `"+opt.get("opendiscord:limits-maximum-user").value+"`" } if (layout == "detailed"){ //TODO TRANSLATION!!! - if (opt.exists("openticket:admins")) description = description + "\nAdmins: "+opt.get("openticket:admins").value.map((admin) => discord.roleMention(admin)).join(", ") + if (opt.exists("opendiscord:admins")) description = description + "\nAdmins: "+opt.get("opendiscord:admins").value.map((admin) => discord.roleMention(admin)).join(", ") } if (description == "") description = "``" @@ -101,22 +101,22 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { }else if (opt instanceof api.ODWebsiteOption){ //website option - const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" - const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" - let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + const emoji = opt.exists("opendiscord:button-emoji") ? opt.get("opendiscord:button-emoji").value : "" + const name = opt.exists("opendiscord:name") ? opt.get("opendiscord:name").value : "``" + let description = opt.exists("opendiscord:description") ? opt.get("opendiscord:description").value : "``" if (description == "") description = "``" return {name:utilities.emojiTitle(emoji,name),value:description} }else if (opt instanceof api.ODRoleOption){ //role option - const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" - const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" - let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + const emoji = opt.exists("opendiscord:button-emoji") ? opt.get("opendiscord:button-emoji").value : "" + const name = opt.exists("opendiscord:name") ? opt.get("opendiscord:name").value : "``" + let description = opt.exists("opendiscord:description") ? opt.get("opendiscord:description").value : "``" if (layout == "normal" || layout == "detailed"){ //TODO TRANSLATION!!! - if (opt.exists("openticket:roles")) description = description + "\nRoles: "+opt.get("openticket:roles").value.map((admin) => discord.roleMention(admin)).join(", ") + if (opt.exists("opendiscord:roles")) description = description + "\nRoles: "+opt.get("opendiscord:roles").value.map((admin) => discord.roleMention(admin)).join(", ") } if (description == "") description = "``" @@ -124,28 +124,28 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { }else{ //auto-generated plugin option - const emoji = opt.get("openticket:button-emoji") as api.ODOptionData|null - const name = opt.get("openticket:name") as api.ODOptionData|null - const description = opt.get("openticket:description") as api.ODOptionData|null + const emoji = opt.get("opendiscord:button-emoji") as api.ODOptionData|null + const name = opt.get("opendiscord:name") as api.ODOptionData|null + const description = opt.get("opendiscord:description") as api.ODOptionData|null return {name:utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`")),value:((description && description.value) ? description.value : "``")} } }) else if (mode == "text") return title+options.map((opt) => { if (opt instanceof api.ODTicketOption){ //ticket option - const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" - const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" - let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + const emoji = opt.exists("opendiscord:button-emoji") ? opt.get("opendiscord:button-emoji").value : "" + const name = opt.exists("opendiscord:name") ? opt.get("opendiscord:name").value : "``" + let description = opt.exists("opendiscord:description") ? opt.get("opendiscord:description").value : "``" if (layout == "normal" || layout == "detailed"){ //TODO TRANSLATION!!! - if (opt.exists("openticket:cooldown-enabled") && opt.get("openticket:cooldown-enabled").value) description = description + "\nCooldown: `"+opt.get("openticket:cooldown-minutes").value+" min`" + if (opt.exists("opendiscord:cooldown-enabled") && opt.get("opendiscord:cooldown-enabled").value) description = description + "\nCooldown: `"+opt.get("opendiscord:cooldown-minutes").value+" min`" //TODO TRANSLATION!!! - if (opt.exists("openticket:limits-enabled") && opt.get("openticket:limits-enabled").value) description = description + "\nMax Tickets: `"+opt.get("openticket:limits-maximum-user").value+"`" + if (opt.exists("opendiscord:limits-enabled") && opt.get("opendiscord:limits-enabled").value) description = description + "\nMax Tickets: `"+opt.get("opendiscord:limits-maximum-user").value+"`" } if (layout == "detailed"){ //TODO TRANSLATION!!! - if (opt.exists("openticket:admins")) description = description + "\nAdmins: "+opt.get("openticket:admins").value.map((admin) => discord.roleMention(admin)).join(", ") + if (opt.exists("opendiscord:admins")) description = description + "\nAdmins: "+opt.get("opendiscord:admins").value.map((admin) => discord.roleMention(admin)).join(", ") } if (layout == "simple") return "**"+utilities.emojiTitle(emoji,name)+":** "+description @@ -153,22 +153,22 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { }else if (opt instanceof api.ODWebsiteOption){ //website option - const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" - const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" - let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + const emoji = opt.exists("opendiscord:button-emoji") ? opt.get("opendiscord:button-emoji").value : "" + const name = opt.exists("opendiscord:name") ? opt.get("opendiscord:name").value : "``" + let description = opt.exists("opendiscord:description") ? opt.get("opendiscord:description").value : "``" if (layout == "simple") return "**"+utilities.emojiTitle(emoji,name)+":** "+description else return "**"+utilities.emojiTitle(emoji,name)+"**\n"+description }else if (opt instanceof api.ODRoleOption){ //role option - const emoji = opt.exists("openticket:button-emoji") ? opt.get("openticket:button-emoji").value : "" - const name = opt.exists("openticket:name") ? opt.get("openticket:name").value : "``" - let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "``" + const emoji = opt.exists("opendiscord:button-emoji") ? opt.get("opendiscord:button-emoji").value : "" + const name = opt.exists("opendiscord:name") ? opt.get("opendiscord:name").value : "``" + let description = opt.exists("opendiscord:description") ? opt.get("opendiscord:description").value : "``" if (layout == "normal" || layout == "detailed"){ //TODO TRANSLATION!!! - if (opt.exists("openticket:roles")) description = description + "\nRoles: "+opt.get("openticket:roles").value.map((admin) => discord.roleMention(admin)).join(", ") + if (opt.exists("opendiscord:roles")) description = description + "\nRoles: "+opt.get("opendiscord:roles").value.map((admin) => discord.roleMention(admin)).join(", ") } if (layout == "simple") return "**"+utilities.emojiTitle(emoji,name)+":** "+description @@ -176,9 +176,9 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): { }else{ //auto-generated plugin option - const emoji = opt.get("openticket:button-emoji") as api.ODOptionData|null - const name = opt.get("openticket:name") as api.ODOptionData|null - const description = opt.get("openticket:description") as api.ODOptionData|null + const emoji = opt.get("opendiscord:button-emoji") as api.ODOptionData|null + const name = opt.get("opendiscord:name") as api.ODOptionData|null + const description = opt.get("opendiscord:description") as api.ODOptionData|null if (layout == "simple") return "**"+utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`"))+":** "+(description ? description.value : "``") else return "**"+utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`"))+"**\n"+(description ? description.value : "``") diff --git a/src/data/openticket/questionLoader.ts b/src/data/openticket/questionLoader.ts index 7ee9a42..5a2f0be 100644 --- a/src/data/openticket/questionLoader.ts +++ b/src/data/openticket/questionLoader.ts @@ -1,7 +1,7 @@ import {opendiscord, api, utilities} from "../../index" export const loadAllQuestions = async () => { - const questionConfig = opendiscord.configs.get("openticket:questions") + const questionConfig = opendiscord.configs.get("opendiscord:questions") if (!questionConfig) return questionConfig.data.forEach((question) => { @@ -30,24 +30,24 @@ export const loadAllQuestions = async () => { export const loadShortQuestion = (option:api.ODJsonConfig_DefaultShortQuestionType) => { return new api.ODShortQuestion(option.id,[ - new api.ODQuestionData("openticket:name",option.name), - new api.ODQuestionData("openticket:required",option.required), - new api.ODQuestionData("openticket:placeholder",option.placeholder), + new api.ODQuestionData("opendiscord:name",option.name), + new api.ODQuestionData("opendiscord:required",option.required), + new api.ODQuestionData("opendiscord:placeholder",option.placeholder), - new api.ODQuestionData("openticket:length-enabled",option.length.enabled), - new api.ODQuestionData("openticket:length-min",option.length.min), - new api.ODQuestionData("openticket:length-max",option.length.max), + new api.ODQuestionData("opendiscord:length-enabled",option.length.enabled), + new api.ODQuestionData("opendiscord:length-min",option.length.min), + new api.ODQuestionData("opendiscord:length-max",option.length.max), ]) } export const loadParagraphQuestion = (option:api.ODJsonConfig_DefaultParagraphQuestionType) => { return new api.ODParagraphQuestion(option.id,[ - new api.ODQuestionData("openticket:name",option.name), - new api.ODQuestionData("openticket:required",option.required), - new api.ODQuestionData("openticket:placeholder",option.placeholder), + new api.ODQuestionData("opendiscord:name",option.name), + new api.ODQuestionData("opendiscord:required",option.required), + new api.ODQuestionData("opendiscord:placeholder",option.placeholder), - new api.ODQuestionData("openticket:length-enabled",option.length.enabled), - new api.ODQuestionData("openticket:length-min",option.length.min), - new api.ODQuestionData("openticket:length-max",option.length.max), + new api.ODQuestionData("opendiscord:length-enabled",option.length.enabled), + new api.ODQuestionData("opendiscord:length-min",option.length.min), + new api.ODQuestionData("opendiscord:length-max",option.length.max), ]) } \ No newline at end of file diff --git a/src/data/openticket/roleLoader.ts b/src/data/openticket/roleLoader.ts index 0714fc3..1db2c7a 100644 --- a/src/data/openticket/roleLoader.ts +++ b/src/data/openticket/roleLoader.ts @@ -10,9 +10,9 @@ export const loadAllRoles = async () => { export const loadRole = (option:api.ODRoleOption) => { return new api.ODRole(option.id,[ - new api.ODRoleData("openticket:roles",option.get("openticket:roles").value), - new api.ODRoleData("openticket:mode",option.get("openticket:mode").value), - new api.ODRoleData("openticket:remove-roles-on-add",option.get("openticket:remove-roles-on-add").value), - new api.ODRoleData("openticket:add-on-join",option.get("openticket:add-on-join").value) + new api.ODRoleData("opendiscord:roles",option.get("opendiscord:roles").value), + new api.ODRoleData("opendiscord:mode",option.get("opendiscord:mode").value), + new api.ODRoleData("opendiscord:remove-roles-on-add",option.get("opendiscord:remove-roles-on-add").value), + new api.ODRoleData("opendiscord:add-on-join",option.get("opendiscord:add-on-join").value) ]) } \ No newline at end of file diff --git a/src/data/openticket/ticketLoader.ts b/src/data/openticket/ticketLoader.ts index 9432b13..976322e 100644 --- a/src/data/openticket/ticketLoader.ts +++ b/src/data/openticket/ticketLoader.ts @@ -1,12 +1,12 @@ import {opendiscord, api, utilities} from "../../index" -const optionDatabase = opendiscord.databases.get("openticket:options") +const optionDatabase = opendiscord.databases.get("opendiscord:options") export const loadAllTickets = async () => { - const ticketDatabase = opendiscord.databases.get("openticket:tickets") + const ticketDatabase = opendiscord.databases.get("opendiscord:tickets") if (!ticketDatabase) return - const tickets = await ticketDatabase.getCategory("openticket:ticket") + const tickets = await ticketDatabase.getCategory("opendiscord:ticket") if (!tickets) return for (const ticket of tickets){ try { @@ -19,14 +19,14 @@ export const loadAllTickets = async () => { } export const loadTicket = async (ticket:api.ODTicketJson) => { - const backupOption = (await optionDatabase.exists("openticket:used-option",ticket.option)) ? api.ODTicketOption.fromJson(await optionDatabase.get("openticket:used-option",ticket.option) as api.ODOptionJson) : null + const backupOption = (await optionDatabase.exists("opendiscord:used-option",ticket.option)) ? api.ODTicketOption.fromJson(await optionDatabase.get("opendiscord:used-option",ticket.option) as api.ODOptionJson) : null const configOption = opendiscord.options.get(ticket.option) //check if option is of type "ticket" if (configOption && !(configOption instanceof api.ODTicketOption)) throw new api.ODSystemError("Unable to load ticket because option is not of 'ticket' type!") //manage backup option - if (configOption) await optionDatabase.set("openticket:used-option",configOption.id.value,configOption.toJson(opendiscord.versions.get("openticket:version"))) + if (configOption) await optionDatabase.set("opendiscord:used-option",configOption.id.value,configOption.toJson(opendiscord.versions.get("opendiscord:version"))) else if (backupOption) opendiscord.options.add(backupOption) else throw new api.ODSystemError("Unable to use backup option! Normal option not found in config!") diff --git a/src/data/openticket/transcriptLoader.ts b/src/data/openticket/transcriptLoader.ts index 16c437e..43c0278 100644 --- a/src/data/openticket/transcriptLoader.ts +++ b/src/data/openticket/transcriptLoader.ts @@ -3,7 +3,7 @@ import * as discord from "discord.js" const collector = opendiscord.transcripts.collector const messages = opendiscord.builders.messages -const transcriptConfig = opendiscord.configs.get("openticket:transcripts") +const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts") const textConfig = transcriptConfig.data.textTranscriptStyle const htmlVersion = Buffer.from("b3BlbnRpY2tldFRSQU5TQ1JJUFQxMjM0","base64").toString("utf8") @@ -44,7 +44,7 @@ export const loadAllTranscriptCompilers = async () => { } //TEXT COMPILER - opendiscord.transcripts.add(new api.ODTranscriptCompiler<{contents:string}>("openticket:text-compiler",undefined,async (ticket,channel,user) => { + opendiscord.transcripts.add(new api.ODTranscriptCompiler<{contents:string}>("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} @@ -104,10 +104,10 @@ export const loadAllTranscriptCompilers = async () => { const finalStats: string[] = [] - const creationDate = ticket.get("openticket:opened-on").value - const closeDate = ticket.get("openticket:closed-on").value - const claimDate = ticket.get("openticket:claimed-on").value - const pinDate = ticket.get("openticket:pinned-on").value + const creationDate = ticket.get("opendiscord:opened-on").value + const closeDate = ticket.get("opendiscord:closed-on").value + const claimDate = ticket.get("opendiscord:claimed-on").value + const pinDate = ticket.get("opendiscord:pinned-on").value const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const closer = await opendiscord.tickets.getTicketUser(ticket,"closer") const claimer = await opendiscord.tickets.getTicketUser(ticket,"claimer") @@ -164,16 +164,16 @@ export const loadAllTranscriptCompilers = async () => { },async (result) => { //READY return { - channelMessage:await messages.getSafe("openticket:transcript-text-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:text-compiler")}), - creatorDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:text-compiler")}), - participantDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("participant-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:text-compiler")}), - activeAdminDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("active-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:text-compiler")}), - everyAdminDmMessage:await messages.getSafe("openticket:transcript-text-ready").build("every-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:text-compiler")}) + channelMessage:await messages.getSafe("opendiscord:transcript-text-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:text-compiler")}), + creatorDmMessage:await messages.getSafe("opendiscord:transcript-text-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:text-compiler")}), + participantDmMessage:await messages.getSafe("opendiscord:transcript-text-ready").build("participant-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:text-compiler")}), + activeAdminDmMessage:await messages.getSafe("opendiscord:transcript-text-ready").build("active-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:text-compiler")}), + everyAdminDmMessage:await messages.getSafe("opendiscord:transcript-text-ready").build("every-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:text-compiler")}) } })) //HTML COMPILER - opendiscord.transcripts.add(new api.ODTranscriptCompiler<{url:string}>("openticket:html-compiler",async (ticket,channel,user) => { + opendiscord.transcripts.add(new api.ODTranscriptCompiler<{url:string}>("opendiscord:html-compiler",async (ticket,channel,user) => { //INIT const req = new api.ODHTTPGetRequest("https://apis.dj-dj.be/transcripts/status.json",false) const res = await req.run() @@ -191,7 +191,7 @@ export const loadAllTranscriptCompilers = async () => { return {success:false,errorReason:"HTML Transcripts are currently unavailable due to JSON parse error!",pendingMessage:null} } - return {success:true,errorReason:null,pendingMessage:await messages.getSafe("openticket:transcript-html-progress").build("channel",{guild:channel.guild,channel,user,ticket,compiler:opendiscord.transcripts.get("openticket:html-compiler"),remaining:16000})} + 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) => { //COMPILE const rawMessages = await collector.collectAllMessages(ticket) @@ -355,7 +355,7 @@ export const loadAllTranscriptCompilers = async () => { const htmlFinal: api.ODTranscriptHtmlV2Data = { version:"2", - otversion:opendiscord.versions.get("openticket:version").toString(true), + otversion:opendiscord.versions.get("opendiscord:version").toString(true), bot:{ name:opendiscord.client.client.user.displayName, id:opendiscord.client.client.user.id, @@ -410,7 +410,7 @@ export const loadAllTranscriptCompilers = async () => { claimedpfp:(claimer ? claimer.displayAvatarURL() : "https://transcripts.dj-dj.be/favicon.png"), closedtime:new Date().getTime(), - openedtime:ticket.get("openticket:opened-on").value ?? new Date().getTime(), + openedtime:ticket.get("opendiscord:opened-on").value ?? new Date().getTime(), //role colors are currently unused roleColors:[], @@ -474,11 +474,11 @@ export const loadAllTranscriptCompilers = async () => { //READY await utilities.timer(16000) //wait until transcript is ready return { - channelMessage:await messages.getSafe("openticket:transcript-html-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:html-compiler")}), - creatorDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:html-compiler")}), - participantDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("participant-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:html-compiler")}), - activeAdminDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("active-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:html-compiler")}), - everyAdminDmMessage:await messages.getSafe("openticket:transcript-html-ready").build("every-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("openticket:html-compiler")}) + 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")}), + participantDmMessage:await messages.getSafe("opendiscord:transcript-html-ready").build("participant-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:html-compiler")}), + activeAdminDmMessage:await messages.getSafe("opendiscord:transcript-html-ready").build("active-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:html-compiler")}), + everyAdminDmMessage:await messages.getSafe("opendiscord:transcript-html-ready").build("every-admin-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:html-compiler")}) } })) } diff --git a/src/index.ts b/src/index.ts index b5f5edc..383e087 100644 --- a/src/index.ts +++ b/src/index.ts @@ -111,7 +111,7 @@ const main = async () => { //load debug if (opendiscord.defaults.getDefault("debugLoading")){ - const debugFlag = opendiscord.flags.get("openticket:debug") + const debugFlag = opendiscord.flags.get("opendiscord:debug") opendiscord.debug.visible = (debugFlag) ? debugFlag.value : false } @@ -146,7 +146,7 @@ const main = async () => { } //UTILITY CONFIG - const generalConfig = opendiscord.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("opendiscord:general") if (opendiscord.defaults.getDefault("emojiTitleStyleLoading")){ //set emoji style based on config @@ -193,9 +193,9 @@ const main = async () => { //add available languages to list for config checker const languageList = opendiscord.defaults.getDefault("languageList") const languageIds = opendiscord.languages.getIds().map((id) => { - if (id.value.startsWith("openticket:")){ + if (id.value.startsWith("opendiscord:")){ //is open ticket language => return without prefix - return id.value.split("openticket:")[1] + return id.value.split("opendiscord:")[1] }else return id.value }) languageList.push(...languageIds) @@ -210,7 +210,7 @@ const main = async () => { if (languageId.includes(":")){ opendiscord.languages.setCurrentLanguage(languageId) }else{ - opendiscord.languages.setCurrentLanguage("openticket:"+languageId) + opendiscord.languages.setCurrentLanguage("opendiscord:"+languageId) } //set backup language @@ -253,8 +253,8 @@ const main = async () => { await opendiscord.events.get("afterCheckerTranslationsLoaded").emit([opendiscord.checkers.translation,opendiscord.checkers]) //render config checker - const advancedCheckerFlag = opendiscord.flags.get("openticket:checker") - const disableCheckerFlag = opendiscord.flags.get("openticket:no-checker") + const advancedCheckerFlag = opendiscord.flags.get("opendiscord:checker") + const disableCheckerFlag = opendiscord.flags.get("opendiscord:no-checker") await opendiscord.events.get("onCheckerRender").emit([opendiscord.checkers.renderer,opendiscord.checkers]) if (opendiscord.defaults.getDefault("checkerRendering") && !(disableCheckerFlag ? disableCheckerFlag.value : false)){ @@ -330,9 +330,9 @@ const main = async () => { ) //get token from config or env - const configToken = opendiscord.configs.get("openticket:general").data.token ? opendiscord.configs.get("openticket:general").data.token : "" + const configToken = opendiscord.configs.get("opendiscord:general").data.token ? opendiscord.configs.get("opendiscord:general").data.token : "" const envToken = opendiscord.env.getVariable("TOKEN") ? opendiscord.env.getVariable("TOKEN") : "" - const token = opendiscord.configs.get("openticket:general").data.tokenFromENV ? envToken : configToken + const token = opendiscord.configs.get("opendiscord:general").data.tokenFromENV ? envToken : configToken opendiscord.client.token = token } await opendiscord.events.get("onClientLoad").emit([opendiscord.client]) @@ -347,7 +347,7 @@ const main = async () => { //check if all servers are valid const botServers = client.getGuilds() - const generalConfig = opendiscord.configs.get("openticket:general") + const generalConfig = opendiscord.configs.get("opendiscord:general") const serverId = generalConfig.data.serverId ? generalConfig.data.serverId : "" if (!serverId) throw new api.ODSystemError("Server Id Missing!") @@ -417,9 +417,9 @@ const main = async () => { const updatableCmds = cmds.registered.filter((cmd) => cmd.requiresUpdate || opendiscord.defaults.getDefault("forceSlashCommandRegistration")).map((cmd) => cmd.instance) //init progress bars - const removeProgress = opendiscord.progressbars.get("openticket:slash-command-remove") - const createProgress = opendiscord.progressbars.get("openticket:slash-command-create") - const updateProgress = opendiscord.progressbars.get("openticket:slash-command-update") + const removeProgress = opendiscord.progressbars.get("opendiscord:slash-command-remove") + const createProgress = opendiscord.progressbars.get("opendiscord:slash-command-create") + const updateProgress = opendiscord.progressbars.get("opendiscord:slash-command-update") //remove unused cmds, create new cmds & update existing cmds if (opendiscord.defaults.getDefault("allowSlashCommandRemoval")) await opendiscord.client.slashCommands.removeUnusedCommands(removableCmds,undefined,removeProgress) @@ -732,7 +732,7 @@ const main = async () => { //load stat scopes opendiscord.log("Loading stats...","system") if (opendiscord.defaults.getDefault("statScopesLoading")){ - opendiscord.stats.useDatabase(opendiscord.databases.get("openticket:stats")) + opendiscord.stats.useDatabase(opendiscord.databases.get("opendiscord:stats")) await (await import("./data/framework/statLoader.js")).loadAllStatScopes() } await opendiscord.events.get("onStatScopeLoad").emit([opendiscord.stats]) From f2cefae37c35735260a35c743bc56b8d16978095 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 1 Feb 2025 11:22:49 +0100 Subject: [PATCH 133/157] database will auto-update for the breaking change --- src/core/api/modules/database.ts | 34 ++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/core/api/modules/database.ts b/src/core/api/modules/database.ts index ab6d601..acf1f50 100644 --- a/src/core/api/modules/database.ts +++ b/src/core/api/modules/database.ts @@ -7,6 +7,30 @@ import nodepath from "path" import { ODDebugger } from "./console" import * as fjs from "formatted-json-stringify" +///////////////////////////////////////////////////////// +//TEMPORARY OPENTICKET => OPENDISCORD MIGRATION UTILITIES +///////////////////////////////////////////////////////// + +/** ## ❌ Temporary function. Will be removed on full OTv4 release! */ +export function TEMP_migrateDatabaseIdPrefix(id:string): string { + if (!id.startsWith("openticket:")) return id + return id.replace("openticket:","opendiscord:") +} +/** ## ❌ Temporary function. Will be removed on full OTv4 release! */ +export function TEMP_migrateDatabaseValuePrefix(value:string): string { + return value.replaceAll('"openticket:','"opendiscord:') +} +/** ## ❌ Temporary function. Will be removed on full OTv4 release! */ +export function TEMP_migrateDatabaseStructurePrefix(structure:ODJsonDatabaseStructure): ODJsonDatabaseStructure { + return structure.map((data) => { + return { + category:TEMP_migrateDatabaseIdPrefix(data.category), + key:TEMP_migrateDatabaseIdPrefix(data.key), + value:JSON.parse(TEMP_migrateDatabaseValuePrefix(JSON.stringify(data.value))) + } + }) +} + /**## ODDatabaseManager `class` * This is an Open Ticket database manager. * @@ -94,7 +118,10 @@ export class ODJsonDatabase extends ODDatabase { /**Init the database. */ init(): ODPromiseVoid { - this.#system.getData() + //this.#system.getData() + //TEMPORARY!!! + const newData = TEMP_migrateDatabaseStructurePrefix(this.#system.getData()) + this.#system.setData(newData) } /**Set/overwrite the value of `category` & `key`. Returns `true` when overwritten! * @example @@ -199,7 +226,10 @@ export class ODFormattedJsonDatabase extends ODDatabase { /**Init the database. */ init(): ODPromiseVoid { - this.#system.getData() + //this.#system.getData() + //TEMPORARY!!! + const newData = TEMP_migrateDatabaseStructurePrefix(this.#system.getData()) + this.#system.setData(newData) } /**Set/overwrite the value of `category` & `key`. Returns `true` when overwritten! * @example From 27f6e3a81f45565418759b087b0896964e2c282c Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 1 Feb 2025 11:23:17 +0100 Subject: [PATCH 134/157] Compiler will now only hash JS & TS files --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 25e9576..d7cc959 100644 --- a/index.js +++ b/index.js @@ -45,7 +45,7 @@ function computeSourceHash(dir,upperHash){ for (const file of info) { const fullPath = nodepath.join(dir,file.name) - if (file.isFile()){ + if (file.isFile() && [".js",".ts",".jsx",".tsx"].some((ext) => file.name.endsWith(ext))){ const statInfo = fs.statSync(fullPath) //compute hash using file metadata const fileInfo = `${fullPath}:${statInfo.size}:${statInfo.mtimeMs}` From a397b66c9edd80680b3f0fb5f6c978f1129fc593 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 1 Feb 2025 11:52:02 +0100 Subject: [PATCH 135/157] Update createDocs.js --- .docs/createDocs.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.docs/createDocs.js b/.docs/createDocs.js index dc0375f..f624022 100644 --- a/.docs/createDocs.js +++ b/.docs/createDocs.js @@ -99,10 +99,11 @@ for (const file of result.children){ const typeIds = file.groups?.find((g) => g.title == "Type Aliases")?.children ?? [] const enumIds = file.groups?.find((g) => g.title == "Enumerations")?.children ?? [] const varIds = file.groups?.find((g) => g.title == "Variables")?.children ?? [] + const funcIds = file.groups?.find((g) => g.title == "Functions")?.children ?? [] for (const declaration of file.children){ const declarationName = declaration.name - const declarationType = classIds.includes(declaration.id) ? "class" : interfaceIds.includes(declaration.id) ? "interface" : typeIds.includes(declaration.id) ? "type" : enumIds.includes(declaration.id) ? "enum" : varIds.includes(declaration.id) ? "variable" : "other" + const declarationType = classIds.includes(declaration.id) ? "class" : interfaceIds.includes(declaration.id) ? "interface" : typeIds.includes(declaration.id) ? "type" : enumIds.includes(declaration.id) ? "enum" : varIds.includes(declaration.id) ? "variable" : funcIds.includes(declaration.id) ? "function" : "other" availableElements.push({name:declarationName,type:declarationType}) } } @@ -114,12 +115,13 @@ for (const file of result.children){ const typeIds = file.groups?.find((g) => g.title == "Type Aliases")?.children ?? [] const enumIds = file.groups?.find((g) => g.title == "Enumerations")?.children ?? [] const varIds = file.groups?.find((g) => g.title == "Variables")?.children ?? [] + const funcIds = file.groups?.find((g) => g.title == "Functions")?.children ?? [] for (const declaration of (file.children ?? [])){ const declarationName = declaration.name if (skipElementNames.includes(declarationName)) continue - const declarationType = classIds.includes(declaration.id) ? "class" : interfaceIds.includes(declaration.id) ? "interface" : typeIds.includes(declaration.id) ? "type" : enumIds.includes(declaration.id) ? "enum" : varIds.includes(declaration.id) ? "variable" : "other" + const declarationType = classIds.includes(declaration.id) ? "class" : interfaceIds.includes(declaration.id) ? "interface" : typeIds.includes(declaration.id) ? "type" : enumIds.includes(declaration.id) ? "enum" : varIds.includes(declaration.id) ? "variable" : funcIds.includes(declaration.id) ? "function" : "other" const declarationTypeParams = (declaration.typeParameters) ? declaration.typeParameters.map((tp) => { return {name:tp.name,type:handleType(tp.type)} }) : null @@ -232,6 +234,10 @@ for (const file of result.children){ //VARIABLE declarationChildren.push(handleType(declaration.type)) + }else if (declarationType == "function"){ + //FUNCTION + declarationChildren.push(handleFunction(declaration)) + } exported.push({ From bf952e3ef7e2dd921d69829c6b24dbd3a6196f45 Mon Sep 17 00:00:00 2001 From: Roppl3r Date: Sun, 2 Feb 2025 20:23:32 +0100 Subject: [PATCH 136/157] Fixed month parsing in dateString() utility causing incorrect dates in text transcripts. --- src/core/startup/init.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index be3c7b3..77fd55e 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -181,7 +181,7 @@ export const utilities: ODUtilities = { }) as ReturnValue }, dateString(date): string { - return `${date.getDate()}/${date.getMonth()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}` + return `${date.getDate()}/${date.getMonth()+1}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}` }, async asyncReplace(text,regex,func): Promise { const promises: Promise[] = [] From 06e7919162dbad957a94b5e49f7437a685fd0847 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 3 Feb 2025 21:01:36 +0100 Subject: [PATCH 137/157] Fixed panel dropdown bug with empty option label --- src/builders/dropdowns.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/builders/dropdowns.ts b/src/builders/dropdowns.ts index e23da85..2f675c5 100644 --- a/src/builders/dropdowns.ts +++ b/src/builders/dropdowns.ts @@ -18,10 +18,12 @@ const panelDropdowns = () => { const {panel,options} = params const parsedOptions: api.ODDropdownData["options"] = options.map((option) => { + const label = option.get("opendiscord:button-label").value.substring(0,100) const desc = option.get("opendiscord:description").value.substring(0,100) const emoji = option.get("opendiscord:button-emoji").value + return { - label:option.get("opendiscord:button-label").value.substring(0,100), + label:(label.length > 0) ? label : "", value:"od:ticket-option_"+panel.id.value+"_"+option.id.value, emoji:(emoji.length > 0) ? emoji : undefined, description:(desc.length > 0) ? desc : undefined, From 4e709f2a0bded122435bb658f39cab2f424b4824 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:42:24 +0100 Subject: [PATCH 138/157] Update createDocs.js --- .docs/createDocs.js | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/.docs/createDocs.js b/.docs/createDocs.js index f624022..a2d45d4 100644 --- a/.docs/createDocs.js +++ b/.docs/createDocs.js @@ -51,6 +51,41 @@ const handleFunction = (memberType) => { return {type:"function",inherited:signatureInherited,comment:signatureComment,parameters:signatureParameters,returns:signatureReturns} } +const handleObject = (memberType) => { + if (!memberType || !memberType.children || !Array.isArray(memberType.children)) return {type:"unknown"} + const propertyIds = memberType.groups?.find((g) => g.title == "Properties")?.children ?? [] + const methodIds = memberType.groups?.find((g) => g.title == "Methods")?.children ?? [] + + const objectChildren = [] + for (const member of (memberType.children ?? [])){ + const memberName = member.name + const memberType = propertyIds.includes(member.id) ? "property" : methodIds.includes(member.id) ? "method" : "other" + let memberComment = member.comment?.summary?.map((c) => c.text).join("") ?? null + + const rawMemberSource = member.sources ? (member.sources[0] ?? null) : null + let memberSource = rawMemberSource ? rawMemberSource.fileName+":"+rawMemberSource.line+":"+rawMemberSource.character : null + + let memberDetails = null + if (memberType == "property"){ + //INTERFACE => PROPERTY + memberDetails = handleType(member.type) + }else if (memberType == "method"){ + //INTERFACE => METHOD + memberDetails = handleFunction(member) + memberComment = memberDetails.comment + } + + objectChildren.push({ + type:memberType, + name:memberName, + comment:memberComment, + source:memberSource, + details:memberDetails + }) + } + return {type:"object",children:objectChildren} +} + const handleType = (memberType) => { if (!memberType || !memberType.type) return {type:"unknown"} else if (memberType.type == "intrinsic") return {type:"primitive",name:memberType.name} @@ -72,9 +107,7 @@ const handleType = (memberType) => { }else return {type:"unknown"} } else if (memberType.type == "literal") return {type:"literal",name:(typeof memberType.value == "string") ? JSON.stringify(memberType.value) : String(memberType.value)} - else if (memberType.type == "reflection" && memberType.declaration && memberType.declaration.signatures && memberType.declaration.signatures[0]){ - return handleFunction(memberType.declaration) - }else if (memberType.type == "typeOperator"){ + else if (memberType.type == "typeOperator"){ if (memberType.operator == "keyof") return {type:"keyof",child:handleType(memberType.target)} else if (memberType.operator == "readonly") return {type:"readonly",child:handleType(memberType.target)} else if (memberType.operator == "unique") return {type:"unique",child:handleType(memberType.target)} @@ -90,6 +123,12 @@ const handleType = (memberType) => { else if (memberType.type == "templateLiteral") return {type:"template",head:memberType.head,tails:memberType.tail.map((t) => { return {element:handleType(t[0]),text:t[1]} })} + else if (memberType.type == "reflection" && memberType.declaration && memberType.declaration.signatures && memberType.declaration.signatures[0]){ + return handleFunction(memberType.declaration) + } + else if (memberType.type == "reflection"){ + return handleObject(memberType.declaration) + } else return {type:"unknown"} } From 071c8f953cd9d3ef21b6ea3ac1de3df0b11e58b8 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 5 Feb 2025 17:04:10 +0100 Subject: [PATCH 139/157] Update createDocs.js --- .docs/createDocs.js | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/.docs/createDocs.js b/.docs/createDocs.js index a2d45d4..efb5a05 100644 --- a/.docs/createDocs.js +++ b/.docs/createDocs.js @@ -185,6 +185,12 @@ for (const file of result.children){ const rawMemberSource = member.sources ? (member.sources[0] ?? null) : null let memberSource = rawMemberSource ? rawMemberSource.fileName+":"+rawMemberSource.line+":"+rawMemberSource.character : null + const memberInherited = member.flags.isInherited ? true : false + const memberStatic = member.flags.isStatic ? true : false + const memberProtected = member.flags.isProtected ? true : false + const memberOptional = member.flags.isOptional ? true : false + const memberReadonly = member.flags.isReadonly ? true : false + let memberDetails = null if (memberType == "property"){ //CLASS => PROPERTY @@ -206,7 +212,12 @@ for (const file of result.children){ name:memberName, comment:memberComment, source:memberSource, - details:memberDetails + details:memberDetails, + inherited:memberInherited, + static:memberStatic, + protected:memberProtected, + optional:memberOptional, + readonly:memberReadonly }) } }else if (declarationType == "interface"){ @@ -222,6 +233,12 @@ for (const file of result.children){ const rawMemberSource = member.sources ? (member.sources[0] ?? null) : null let memberSource = rawMemberSource ? rawMemberSource.fileName+":"+rawMemberSource.line+":"+rawMemberSource.character : null + const memberInherited = member.flags.isInherited ? true : false + const memberStatic = member.flags.isStatic ? true : false + const memberProtected = member.flags.isProtected ? true : false + const memberOptional = member.flags.isOptional ? true : false + const memberReadonly = member.flags.isReadonly ? true : false + let memberDetails = null if (memberType == "property"){ //INTERFACE => PROPERTY @@ -237,7 +254,12 @@ for (const file of result.children){ name:memberName, comment:memberComment, source:memberSource, - details:memberDetails + details:memberDetails, + inherited:memberInherited, + static:memberStatic, + protected:memberProtected, + optional:memberOptional, + readonly:memberReadonly }) } }else if (declarationType == "type"){ @@ -261,12 +283,23 @@ for (const file of result.children){ memberDetails = handleType(member.type) } + const memberInherited = member.flags.isInherited ? true : false + const memberStatic = member.flags.isStatic ? true : false + const memberProtected = member.flags.isProtected ? true : false + const memberOptional = member.flags.isOptional ? true : false + const memberReadonly = member.flags.isReadonly ? true : false + declarationChildren.push({ type:memberType, name:memberName, comment:memberComment, source:memberSource, - details:memberDetails + details:memberDetails, + inherited:memberInherited, + static:memberStatic, + protected:memberProtected, + optional:memberOptional, + readonly:memberReadonly }) } }else if (declarationType == "variable"){ From b2a5e65fe2214d5779b7c0975d43ffa02cb0f130 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 9 Feb 2025 11:18:24 +0100 Subject: [PATCH 140/157] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 86fec4b..69e58ed 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ You're also able to customise every little aspect of the bot! From embeds to tra - **🔄 rotating status** - Create a rotating bot status & use dynamic variables from the bot! - **💾 sqlite database** - Use an `sqlite` database for increased performances! - **🎉 custom embeds** - Create your own embeds and use them in your server! + - **⏰ reminders** - Create & manage customisable reminders in your server! - **🎨 customisation** - Yep, you heard it right! Even more customisation! - **😁 And so much more...** @@ -130,6 +131,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat |[`ot-feedback`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-feedback/) |an_developer |💼 Management |A plugin to gather feedback of your support service. | |[`ot-assign-role`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-assign-role/) |rapid.fast |💼 Management |This plugin assigns a predefined role to a user upon creating a ticket. | |[`ot-volume-warning`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-volume-warning/) |guillee.3 |💼 Management |Alerts ticket creators when too many tickets are open, indicating possible response delays. | +|[`od-reminders`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/od-reminders/) |guillee.3 |💼 Management |Set reminders that will be sent to a channel every specified time. | |[`ot-translate-cmds`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-translate-cmds/) |guillee.3 |🤖 Client |Translate all built-in command names, descriptions & options. | ### 📢 Categories From 9395e9af758fd52734d03614e7fdabc2af3070a6 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 9 Feb 2025 11:19:03 +0100 Subject: [PATCH 141/157] Added 13 new utility events for plugins --- src/core/api/defaults/event.ts | 27 ++++++++++++++++++++++++++- src/core/api/modules/base.ts | 1 + src/data/framework/eventLoader.ts | 25 +++++++++++++++++++++++++ src/index.ts | 25 +++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts index 51826c9..1833156 100644 --- a/src/core/api/defaults/event.ts +++ b/src/core/api/defaults/event.ts @@ -63,7 +63,7 @@ export interface ODEventIds_Default { "onFlagInit": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> "afterFlagsInitiated": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid> - //progres bars + //progress bars "onProgressBarRendererLoad": ODEvent_Default<(renderers:ODProgressBarRendererManager_Default) => ODPromiseVoid> "afterProgressBarRenderersLoaded": ODEvent_Default<(renderers:ODProgressBarRendererManager_Default) => ODPromiseVoid> "onProgressBarLoad": ODEvent_Default<(progressbars:ODProgressBarManager_Default) => ODPromiseVoid> @@ -106,6 +106,10 @@ export interface ODEventIds_Default { "afterCheckersRendered": ODEvent_Default<(renderer:ODCheckerRenderer_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid> "onCheckerQuit": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid> + //plugin loading before client + "onPluginBeforeClientLoad": ODEvent_Default<() => ODPromiseVoid>, + "afterPluginBeforeClientLoaded": ODEvent_Default<() => ODPromiseVoid>, + //client configuration "onClientLoad": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid> "afterClientLoaded": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid> @@ -128,6 +132,10 @@ export interface ODEventIds_Default { "onTextCommandLoad": ODEvent_Default<(text:ODTextCommandManager_Default, client:ODClientManager_Default,) => ODPromiseVoid> "afterTextCommandsLoaded": ODEvent_Default<(text:ODTextCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid> + //plugin loading before managers + "onPluginBeforeManagerLoad": ODEvent_Default<() => ODPromiseVoid>, + "afterPluginBeforeManagerLoaded": ODEvent_Default<() => ODPromiseVoid>, + //questions "onQuestionLoad": ODEvent_Default<(questions:ODQuestionManager) => ODPromiseVoid> "afterQuestionsLoaded": ODEvent_Default<(questions:ODQuestionManager) => ODPromiseVoid> @@ -210,6 +218,10 @@ export interface ODEventIds_Default { "onTranscriptReady": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid> "afterTranscriptReady": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid> + //plugin loading before builders + "onPluginBeforeBuilderLoad": ODEvent_Default<() => ODPromiseVoid>, + "afterPluginBeforeBuilderLoaded": ODEvent_Default<() => ODPromiseVoid>, + //builders "onButtonBuilderLoad": ODEvent_Default<(buttons:ODButtonManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> "afterButtonBuildersLoaded": ODEvent_Default<(buttons:ODButtonManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> @@ -224,6 +236,10 @@ export interface ODEventIds_Default { "onModalBuilderLoad": ODEvent_Default<(modals:ODModalManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> "afterModalBuildersLoaded": ODEvent_Default<(modals:ODModalManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + //plugin loading before responders + "onPluginBeforeResponderLoad": ODEvent_Default<() => ODPromiseVoid>, + "afterPluginBeforeResponderLoaded": ODEvent_Default<() => ODPromiseVoid>, + //responders "onCommandResponderLoad": ODEvent_Default<(commands:ODCommandResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> "afterCommandRespondersLoaded": ODEvent_Default<(commands:ODCommandResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> @@ -234,6 +250,10 @@ export interface ODEventIds_Default { "onModalResponderLoad": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> "afterModalRespondersLoaded": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid> + //plugin loading before finalizations + "onPluginBeforeFinalizationLoad": ODEvent_Default<() => ODPromiseVoid>, + "afterPluginBeforeFinalizationLoaded": ODEvent_Default<() => ODPromiseVoid>, + //actions "onActionLoad": ODEvent_Default<(actions:ODActionManager_Default) => ODPromiseVoid> "afterActionsLoaded": ODEvent_Default<(actions:ODActionManager_Default) => ODPromiseVoid> @@ -272,6 +292,10 @@ export interface ODEventIds_Default { "onStatInit": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid> "afterStatsInitiated": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid> + //plugin loading before code + "onPluginBeforeCodeLoad": ODEvent_Default<() => ODPromiseVoid>, + "afterPluginBeforeCodeLoaded": ODEvent_Default<() => ODPromiseVoid>, + //code "onCodeLoad": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid> "afterCodeLoaded": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid> @@ -289,6 +313,7 @@ export interface ODEventIds_Default { "afterStartScreensRendered": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid> //ready + "beforeReadyForUsage": ODEvent_Default<() => ODPromiseVoid> "onReadyForUsage": ODEvent_Default<() => ODPromiseVoid> } diff --git a/src/core/api/modules/base.ts b/src/core/api/modules/base.ts index 368f237..a3b8066 100644 --- a/src/core/api/modules/base.ts +++ b/src/core/api/modules/base.ts @@ -104,6 +104,7 @@ export class ODId { export class ODManagerChangeHelper { #change: (() => void)|null = null + /**Trigger an `onChange()` event in the parent `ODManager` of this class. */ protected _change(){ if (this.#change){ try{ diff --git a/src/data/framework/eventLoader.ts b/src/data/framework/eventLoader.ts index 7ec14ae..2124a1e 100644 --- a/src/data/framework/eventLoader.ts +++ b/src/data/framework/eventLoader.ts @@ -60,6 +60,10 @@ export const loadAllEvents = () => { "afterCheckersRendered", "onCheckerQuit", + //plugin loading before client + "onPluginBeforeClientLoad", + "afterPluginBeforeClientLoaded", + //client configuration "onClientLoad", "afterClientLoaded", @@ -82,6 +86,10 @@ export const loadAllEvents = () => { "onTextCommandLoad", "afterTextCommandsLoaded", + //plugin loading before managers + "onPluginBeforeManagerLoad", + "afterPluginBeforeManagerLoaded", + //questions "onQuestionLoad", "afterQuestionsLoaded", @@ -164,6 +172,10 @@ export const loadAllEvents = () => { "onTranscriptReady", "afterTranscriptReady", + //plugin loading before builders + "onPluginBeforeBuilderLoad", + "afterPluginBeforeBuilderLoaded", + //builders "onButtonBuilderLoad", "afterButtonBuildersLoaded", @@ -178,6 +190,10 @@ export const loadAllEvents = () => { "onModalBuilderLoad", "afterModalBuildersLoaded", + //plugin loading before responders + "onPluginBeforeResponderLoad", + "afterPluginBeforeResponderLoaded", + //responders "onCommandResponderLoad", "afterCommandRespondersLoaded", @@ -188,6 +204,10 @@ export const loadAllEvents = () => { "onModalResponderLoad", "afterModalRespondersLoaded", + //plugin loading before finalizations + "onPluginBeforeFinalizationLoad", + "afterPluginBeforeFinalizationLoaded", + //actions "onActionLoad", "afterActionsLoaded", @@ -226,6 +246,10 @@ export const loadAllEvents = () => { "onStatInit", "afterStatsInitiated", + //plugin loading before code + "onPluginBeforeCodeLoad", + "afterPluginBeforeCodeLoaded", + //code "onCodeLoad", "afterCodeLoaded", @@ -243,6 +267,7 @@ export const loadAllEvents = () => { "afterStartScreensRendered", //ready + "beforeReadyForUsage", "onReadyForUsage" ] eventList.forEach((event) => opendiscord.events.add(new api.ODEvent(event))) diff --git a/src/index.ts b/src/index.ts index 383e087..507e744 100644 --- a/src/index.ts +++ b/src/index.ts @@ -284,6 +284,10 @@ const main = async () => { } } + //plugin loading before client + await opendiscord.events.get("onPluginBeforeClientLoad").emit([]) + await opendiscord.events.get("afterPluginBeforeClientLoaded").emit([]) + //client configuration opendiscord.log("Loading client...","system") if (opendiscord.defaults.getDefault("clientLoading")){ @@ -458,6 +462,10 @@ const main = async () => { opendiscord.log("discord.js client ready!","info") } + //plugin loading before managers + await opendiscord.events.get("onPluginBeforeManagerLoad").emit([]) + await opendiscord.events.get("afterPluginBeforeManagerLoaded").emit([]) + //load questions opendiscord.log("Loading questions...","system") if (opendiscord.defaults.getDefault("questionLoading")){ @@ -522,6 +530,10 @@ const main = async () => { await opendiscord.events.get("onTranscriptHistoryLoad").emit([opendiscord.transcripts]) await opendiscord.events.get("afterTranscriptHistoryLoaded").emit([opendiscord.transcripts]) + //plugin loading before builders + await opendiscord.events.get("onPluginBeforeBuilderLoad").emit([]) + await opendiscord.events.get("afterPluginBeforeBuilderLoaded").emit([]) + //load button builders opendiscord.log("Loading buttons...","system") if (opendiscord.defaults.getDefault("buttonBuildersLoading")){ @@ -570,6 +582,10 @@ const main = async () => { await opendiscord.events.get("onModalBuilderLoad").emit([opendiscord.builders.modals,opendiscord.builders,opendiscord.actions]) await opendiscord.events.get("afterModalBuildersLoaded").emit([opendiscord.builders.modals,opendiscord.builders,opendiscord.actions]) + //plugin loading before responders + await opendiscord.events.get("onPluginBeforeResponderLoad").emit([]) + await opendiscord.events.get("afterPluginBeforeResponderLoaded").emit([]) + //load command responders opendiscord.log("Loading command responders...","system") if (opendiscord.defaults.getDefault("commandRespondersLoading")){ @@ -639,6 +655,10 @@ const main = async () => { await opendiscord.events.get("onModalResponderLoad").emit([opendiscord.responders.modals,opendiscord.responders,opendiscord.actions]) await opendiscord.events.get("afterModalRespondersLoaded").emit([opendiscord.responders.modals,opendiscord.responders,opendiscord.actions]) + //plugin loading before finalizations + await opendiscord.events.get("onPluginBeforeFinalizationLoad").emit([]) + await opendiscord.events.get("afterPluginBeforeFinalizationLoaded").emit([]) + //load actions opendiscord.log("Loading actions...","system") if (opendiscord.defaults.getDefault("actionsLoading")){ @@ -752,6 +772,10 @@ const main = async () => { await opendiscord.events.get("afterStatsInitiated").emit([opendiscord.stats]) } + //plugin loading before code + await opendiscord.events.get("onPluginBeforeCodeLoad").emit([]) + await opendiscord.events.get("afterPluginBeforeCodeLoaded").emit([]) + //load code opendiscord.log("Loading code...","system") if (opendiscord.defaults.getDefault("codeLoading")){ @@ -802,6 +826,7 @@ const main = async () => { //YIPPPIE!! //The startup of Open Ticket is completed :) + await opendiscord.events.get("beforeReadyForUsage").emit([]) opendiscord.readyStartupDate = new Date() await opendiscord.events.get("onReadyForUsage").emit([]) } From f13777e5f3e9a43ee4bd2268c8f355a225a9039d Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 9 Feb 2025 11:34:37 +0100 Subject: [PATCH 142/157] Update README.md --- README.md | 26 +++++++++++++------------- src/builders/embeds.ts | 2 +- src/core/startup/init.ts | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 69e58ed..df5287e 100644 --- a/README.md +++ b/README.md @@ -183,19 +183,19 @@ This is the main team working on Open Ticket. Don't forget to check their profil |🇵🇱 Polish |danoglez |🟢 Up To Date | |🇪🇪 Estonian |iamnotmega |🔵 Up To Date (ChatGPT) | |🇫🇮 Finnish |iamnotmega |🔵 Up To Date (ChatGPT) | -|🇷🇺 Russian |apexo & ander |🟠 Temporary Outdated (beta) | -|🇳🇴 Norwegian |noonenook |🟠 Temporary Outdated (beta) | -|❓ Kurdish |raze.hama |🟠 Temporary Outdated (beta) | -|❓ Persian |sasanwm |🟠 Temporary Outdated (beta) | -|🇱🇻 Latvian |ronalds1398 |🟠 Temporary Outdated (beta) | -|🇯🇵 Japanese |iamnotmega |🟠 Temporary Outdated (beta) | -|🇰🇷 Korean |iamnotmega |🟠 Temporary Outdated (beta) | -|🇨🇳 Simplified Chinese |iamnotmega |🟠 Temporary Outdated (beta) | -|🇨🇳 Traditional Chinese|iamnotmega |🟠 Temporary Outdated (beta) | -|🇸🇪 Swedish |iamnotmega |🟠 Temporary Outdated (beta) | -|🇻🇳 Vietnamese |iamnotmega |🟠 Temporary Outdated (beta) | -|🇸🇮 Slovenian |n1kkec |🔴 Outdated | -|🇬🇷 Greek |stefanos |🔴 Outdated | +|🇷🇺 Russian |/ |🔴 Missing | +|🇳🇴 Norwegian |/ |🔴 Missing | +|🇱🇻 Latvian |/ |🔴 Missing | +|🇯🇵 Japanese |/ |🔴 Missing | +|🇰🇷 Korean |/ |🔴 Missing | +|🇨🇳 Simplified Chinese |/ |🔴 Missing | +|🇨🇳 Traditional Chinese|/ |🔴 Missing | +|🇸🇪 Swedish |/ |🔴 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! diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts index 67d4373..3b9dd1f 100644 --- a/src/builders/embeds.ts +++ b/src/builders/embeds.ts @@ -449,7 +449,7 @@ const statsEmbeds = () => { }else if (utilities.easterEggs.translators.includes(user.id)){ instance.setFooter("💬 Open Ticket Translator") } - } + } }) ]) diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index 77fd55e..6f0cf62 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -197,9 +197,39 @@ export const utilities: ODUtilities = { return result }, easterEggs:{ - creator:"779742674932072469", + /* THANK YOU TO ALL OUR CONTRIBUTORS!!! */ + creator:"779742674932072469", //DJj123dj translators:[ - "779742674932072469" + "779742674932072469", //DJj123dj + "574172558006681601", //Sanke + "540639725300613136", //Guillee.3 + "547231585368539136", //Mods HD + "664934139954331649", //SpyEye + "498055992962187264", //Redactado + "912052735950618705", //T0miiis + "366673202610569227", //johusens + "360780292853858306", //David.3 + "950611418389024809", //Sarcastic + "461603955517161473", //Maurizo + "465111430274875402", //The_Gamer + "586376952470831104", //Erxg + "226695254433202176", //Mkevas + "437695615095275520", //NoOneNook + "530047191222583307", //Anderskiy + "719072181631320145", //ToStam + "1172870906377408512", //Stragar + "1084794575945744445", //Sasanwm + "449613814049275905", //Benzorich + "905373133085741146", //Ronalds + "918504977369018408", //Palestinian + "807970841035145216", //Kornel0706 + "1198883915826475080", //Nova + "669988226819162133", //Danoglez + "1313597620996018271", //Fraden1 + "547809968145956884", //TsgIndrius + "264120132660363267", //Quiradon + "1272034143777329215", //NotMega + "LOREMIPSUM", //TODO ] }, ODVersionMigration From 9702c4d97d5efd2730dd0397005edc6fae0ccf81 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 12 Feb 2025 16:27:34 +0100 Subject: [PATCH 143/157] Fixed stats resetting due to breaking change --- src/core/api/modules/database.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/api/modules/database.ts b/src/core/api/modules/database.ts index acf1f50..1e1dbad 100644 --- a/src/core/api/modules/database.ts +++ b/src/core/api/modules/database.ts @@ -14,7 +14,7 @@ import * as fjs from "formatted-json-stringify" /** ## ❌ Temporary function. Will be removed on full OTv4 release! */ export function TEMP_migrateDatabaseIdPrefix(id:string): string { if (!id.startsWith("openticket:")) return id - return id.replace("openticket:","opendiscord:") + return id.replaceAll("openticket:","opendiscord:") } /** ## ❌ Temporary function. Will be removed on full OTv4 release! */ export function TEMP_migrateDatabaseValuePrefix(value:string): string { From a2f9593d5551e45739c76dbdb619ef189be6fc19 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 15 Feb 2025 18:22:23 +0100 Subject: [PATCH 144/157] Fixed #134 : text transcripts incorrect newlines --- src/data/openticket/transcriptLoader.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/data/openticket/transcriptLoader.ts b/src/data/openticket/transcriptLoader.ts index 43c0278..c3e1b50 100644 --- a/src/data/openticket/transcriptLoader.ts +++ b/src/data/openticket/transcriptLoader.ts @@ -128,7 +128,7 @@ export const loadAllTranscriptCompilers = async () => { //TODO TRANSLATION!!! if (creationDate) finalStats.push("Created On: "+utilities.dateString(new Date(creationDate))) if (creator) finalStats.push("Created By: "+creator.displayName) - finalStats.push("") + if (closer || claimer || pinner) finalStats.push("") if (closer) finalStats.push("Closed By: "+closer.displayName) if (claimer) finalStats.push("Claimed By: "+claimer.displayName) if (pinner) finalStats.push("Pinned By: "+pinner.displayName) @@ -140,16 +140,16 @@ export const loadAllTranscriptCompilers = async () => { //TODO TRANSLATION!!! if (creationDate) finalStats.push("Created On: "+utilities.dateString(new Date(creationDate))) if (creator) finalStats.push("Created By: "+creator.displayName) - finalStats.push("") + if (closer || closeDate) finalStats.push("") if (closeDate) finalStats.push("Closed On: "+utilities.dateString(new Date(closeDate))) if (closer) finalStats.push("Closed By: "+closer.displayName) - finalStats.push("") + if (claimer || claimDate) finalStats.push("") if (claimDate) finalStats.push("Claimed On: "+utilities.dateString(new Date(claimDate))) if (claimer) finalStats.push("Claimed By: "+claimer.displayName) - finalStats.push("") + if (pinner || pinDate) finalStats.push("") if (pinDate) finalStats.push("Pinned On: "+utilities.dateString(new Date(pinDate))) if (pinner) finalStats.push("Pinned By: "+pinner.displayName) - finalStats.push("") + if (closer || claimer || pinner) finalStats.push("") finalStats.push("Deleted On: "+utilities.dateString(new Date())) finalStats.push("Deleted By: "+user.displayName) finalStats.push("\n") From 58674452d8caabdaee495964067503f2281529d5 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 15 Feb 2025 19:01:53 +0100 Subject: [PATCH 145/157] Added quick setup to README.md --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index df5287e..ad305b4 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,17 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat DOSEV5 +### ⏱️ Quick Setup +> 1. Download the latest version of Open Ticket on [Github](https://github.com/DJj123dj/open-ticket). +> 2. Make sure node.js & npm are installed using `node -v` (minimum `v18`). +> 3. Install any required dependencies using `npm install`. +> 4. Configure the bot in the `./config/` directory. +> 5. Start the bot using `npm start` or `node index.js` +> - The bot will let you know any existing config errors. +> - Fix these errors and restart the bot. +> 6. Enjoy using Open Ticket! +> ### [📔 Visit Documentation](https://otdocs.dj-dj.be) + ## 📸 Preview Ticket Message Ticket Stats Message From b12556120cc669e18ccfe8928b282f4c2cb25616 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Mon, 17 Feb 2025 19:44:18 +0100 Subject: [PATCH 146/157] Made database migration compatible with plugins --- src/core/startup/init.ts | 16 ++++++++++++++-- src/core/startup/manageMigration.ts | 24 +++++++++++++++++++++++- src/core/startup/migration.ts | 6 ++++++ src/index.ts | 7 +++++-- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index 6f0cf62..bd39e7b 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -112,7 +112,7 @@ export interface ODUtilities { * * It shouldn't be used by plugins because this is an internal API feature! */ - ODVersionMigration:new (version:api.ODVersion,func:() => void|Promise) => ODVersionMigration + ODVersionMigration:new (version:api.ODVersion,func:() => void|Promise,afterInitFunc:() => void|Promise) => ODVersionMigration } /**## ODVersionMigration `utility class` @@ -125,10 +125,13 @@ export class ODVersionMigration { version: api.ODVersion /**The migration function */ #func: () => void|Promise + /**The migration function */ + #afterInitFunc: () => void|Promise - constructor(version:api.ODVersion,func:() => void|Promise){ + constructor(version:api.ODVersion,func:() => void|Promise,afterInitFunc:() => void|Promise){ this.version = version this.#func = func + this.#afterInitFunc = afterInitFunc } /**Run this version migration as a plugin. Returns `false` when someting goes wrong. */ async migrate(): Promise { @@ -139,6 +142,15 @@ export class ODVersionMigration { return false } } + /**Run this version migration as a plugin. Returns `false` when someting goes wrong. */ + async migrateAfterInit(): Promise { + try{ + await this.#afterInitFunc() + return true + }catch{ + return false + } + } } export const utilities: ODUtilities = { diff --git a/src/core/startup/manageMigration.ts b/src/core/startup/manageMigration.ts index 07bc19c..8ac3f1c 100644 --- a/src/core/startup/manageMigration.ts +++ b/src/core/startup/manageMigration.ts @@ -29,6 +29,8 @@ export const loadVersionMigrationSystem = async () => { //LEAVE MIGRATION CONTEXT await unloadMigrationContext() + + return lastVersion } const preloadMigrationContext = async () => { @@ -71,7 +73,27 @@ const loadAllVersionMigrations = async (lastVersion:api.ODVersion) => { if (migration.version.compare(lastVersion) == "higher"){ const success = await migration.migrate() if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[ - {key:"success",value:success ? "true" : "false"} + {key:"success",value:success ? "true" : "false"}, + {key:"afterInit",value:"false"} + ]) + } + } +} + +export const loadAllAfterInitVersionMigrations = async (lastVersion:api.ODVersion) => { + const migrations = (await import("./migration.js")).migrations + migrations.sort((a,b) => { + const comparison = a.version.compare(b.version) + if (comparison == "equal") return 0 + else if (comparison == "higher") return 1 + else return -1 + }) + for (const migration of migrations){ + if (migration.version.compare(lastVersion) == "higher"){ + const success = await migration.migrateAfterInit() + if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[ + {key:"success",value:success ? "true" : "false"}, + {key:"afterInit",value:"true"} ]) } } diff --git a/src/core/startup/migration.ts b/src/core/startup/migration.ts index 46e72cf..d3af5f0 100644 --- a/src/core/startup/migration.ts +++ b/src/core/startup/migration.ts @@ -3,6 +3,12 @@ import {opendiscord, api, utilities} from "../../index" export const migrations = [ //MIGRATE TO v4.0.0 new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.0"),async () => { + //MIGRATE BEFORE STARTUP + + //nothing needs to be transferred :) + },() => { + //MIGRATE AFTER INITIAL STARTUP (plugins, flags, config, database, language, ... => loaded) + //nothing needs to be transferred :) }) ] \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 507e744..1bb3b3e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -76,8 +76,8 @@ const main = async () => { } }) - //handle data migration - await (await import("./core/startup/manageMigration.js")).loadVersionMigrationSystem() + //handle data migration (PART 1) + const lastVersion = await (await import("./core/startup/manageMigration.js")).loadVersionMigrationSystem() //load plugins if (opendiscord.defaults.getDefault("pluginLoading")){ @@ -222,6 +222,9 @@ const main = async () => { await opendiscord.events.get("afterLanguagesSelected").emit([opendiscord.languages.get(languageId),opendiscord.languages.get(backupLanguageId),opendiscord.languages]) } + + //handle data migration (PART 2) + if (lastVersion) await (await import("./core/startup/manageMigration.js")).loadAllAfterInitVersionMigrations(lastVersion) //load config checker opendiscord.log("Loading config checker...","system") From e6c413cdf547683cf09fcabc86817dca882eb3a0 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 18 Feb 2025 18:18:10 +0100 Subject: [PATCH 147/157] Fixed typos in comments --- src/builders/messages.ts | 2 +- src/core/api/modules/client.ts | 18 +++++++++--------- src/core/startup/init.ts | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/builders/messages.ts b/src/builders/messages.ts index d0353a2..3b1531f 100644 --- a/src/builders/messages.ts +++ b/src/builders/messages.ts @@ -459,7 +459,7 @@ const errorMessages = () => { }) ) - //ERROR NOD IN GUILD + //ERROR NOT IN GUILD messages.add(new api.ODMessage("opendiscord:error-not-in-guild")) messages.get("opendiscord:error-not-in-guild").workers.add( new api.ODWorker("opendiscord:error-not-in-guild",0,async (instance,params,source) => { diff --git a/src/core/api/modules/client.ts b/src/core/api/modules/client.ts index 646cd3a..d2e2868 100644 --- a/src/core/api/modules/client.ts +++ b/src/core/api/modules/client.ts @@ -68,7 +68,7 @@ export class ODClientManager { /**The main server of the bot. Provided by serverId in the config */ mainServer: discord.Guild|null = null - /**(❌ DO NOD OVERWRITE ❌) Internal Open Ticket function to continue the startup when the client is ready! */ + /**(❌ DO NOT OVERWRITE ❌) Internal Open Ticket function to continue the startup when the client is ready! */ readyListener: (() => Promise)|null = null /**The status manager is responsible for setting the bot status. */ activity: ODClientActivityManager @@ -1417,7 +1417,7 @@ export class ODTextCommandManager extends ODManager { tempContent = tempContent.substring(trueValue.length+1) }else if (option.required){ - //REQUIRED => ERROR IF NOD EXISTING + //REQUIRED => ERROR IF NOT EXISTING const invalidregex = /^[^ ]+/ const invalidRes = invalidregex.exec(tempContent) if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"boolean") @@ -1463,7 +1463,7 @@ export class ODTextCommandManager extends ODManager { }) } }else if (option.required){ - //REQUIRED => ERROR IF NOD EXISTING + //REQUIRED => ERROR IF NOT EXISTING const invalidRegex = /^[^ ]+/ const invalidRes = invalidRegex.exec(tempContent) if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"number_invalid") @@ -1489,7 +1489,7 @@ export class ODTextCommandManager extends ODManager { optionError("invalid_option",option,location,value,"string_choice") }else if (option.required && value === ""){ - //REQUIRED => ERROR IF NOD EXISTING + //REQUIRED => ERROR IF NOT EXISTING optionError("missing_option",option,location) }else{ @@ -1529,7 +1529,7 @@ export class ODTextCommandManager extends ODManager { }) } }else if (option.required){ - //REQUIRED => ERROR IF NOD EXISTING + //REQUIRED => ERROR IF NOT EXISTING optionError("missing_option",option,location) } } @@ -1566,7 +1566,7 @@ export class ODTextCommandManager extends ODManager { } } }else if (option.required){ - //REQUIRED => ERROR IF NOD EXISTING + //REQUIRED => ERROR IF NOT EXISTING const invalidRegex = /^[^ ]+/ const invalidRes = invalidRegex.exec(tempContent) if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"channel_not_found") @@ -1601,7 +1601,7 @@ export class ODTextCommandManager extends ODManager { } } }else if (option.required){ - //REQUIRED => ERROR IF NOD EXISTING + //REQUIRED => ERROR IF NOT EXISTING const invalidRegex = /^[^ ]+/ const invalidRes = invalidRegex.exec(tempContent) if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"role_not_found") @@ -1636,7 +1636,7 @@ export class ODTextCommandManager extends ODManager { } } }else if (option.required){ - //REQUIRED => ERROR IF NOD EXISTING + //REQUIRED => ERROR IF NOT EXISTING const invalidRegex = /^[^ ]+/ const invalidRes = invalidRegex.exec(tempContent) if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"member_not_found") @@ -1667,7 +1667,7 @@ export class ODTextCommandManager extends ODManager { optionError("invalid_option",option,location,value,"user_not_found") } }else if (option.required){ - //REQUIRED => ERROR IF NOD EXISTING + //REQUIRED => ERROR IF NOT EXISTING const invalidRegex = /^[^ ]+/ const invalidRes = invalidRegex.exec(tempContent) if (invalidRes) optionError("invalid_option",option,location,invalidRes[0],"user_not_found") diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index bd39e7b..d1e5958 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -133,7 +133,7 @@ export class ODVersionMigration { this.#func = func this.#afterInitFunc = afterInitFunc } - /**Run this version migration as a plugin. Returns `false` when someting goes wrong. */ + /**Run this version migration as a plugin. Returns `false` when something goes wrong. */ async migrate(): Promise { try{ await this.#func() @@ -142,7 +142,7 @@ export class ODVersionMigration { return false } } - /**Run this version migration as a plugin. Returns `false` when someting goes wrong. */ + /**Run this version migration as a plugin (after other plugins have loaded). Returns `false` when something goes wrong. */ async migrateAfterInit(): Promise { try{ await this.#afterInitFunc() From c89e93d33d56dddc9e288a159a432669e4015051 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 19 Feb 2025 15:29:16 +0100 Subject: [PATCH 148/157] Fixed crash resulting of non-returning statements --- src/actions/handleTranscriptErrors.ts | 6 ++---- src/commands/claim.ts | 10 +++++----- src/commands/clear.ts | 5 ++--- src/commands/close.ts | 10 +++++----- src/commands/delete.ts | 8 ++++---- src/commands/pin.ts | 12 ++++++------ src/commands/reopen.ts | 10 +++++----- src/commands/unclaim.ts | 10 +++++----- src/commands/unpin.ts | 10 +++++----- 9 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/actions/handleTranscriptErrors.ts b/src/actions/handleTranscriptErrors.ts index 5c83ab1..bc0cf9a 100644 --- a/src/actions/handleTranscriptErrors.ts +++ b/src/actions/handleTranscriptErrors.ts @@ -44,8 +44,7 @@ export const registerButtonResponders = async () => { }), new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance - const originalSource = instance.interaction.customId.split("_")[1] - if (originalSource != "slash" && originalSource != "text" && originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "other") return + const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIds_Default["opendiscord:delete-ticket"]["source"] if (!guild){ instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) @@ -122,8 +121,7 @@ export const registerButtonResponders = async () => { }), new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance - const originalSource = instance.interaction.customId.split("_")[1] - if (originalSource != "slash" && originalSource != "text" && originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "other") return + const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIds_Default["opendiscord:delete-ticket"]["source"] if (!guild){ instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) diff --git a/src/commands/claim.ts b/src/commands/claim.ts index 50981e1..d47aedb 100644 --- a/src/commands/claim.ts +++ b/src/commands/claim.ts @@ -89,11 +89,11 @@ export const registerButtonResponders = async () => { opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:claim-ticket",/^od:claim-ticket/)) opendiscord.responders.buttons.get("opendiscord:claim-ticket").workers.add( new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source,cancel) => { - const originalSource = instance.interaction.customId.split("_")[1] - if (originalSource != "ticket-message" && originalSource != "unclaim-message") return + const originalSource = instance.interaction.customId.split("_")[1] as Exclude if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:claim-ticket-ticket-message").activate(instance) - else await opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").activate(instance) + else if (originalSource == "unclaim-message") await opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").activate(instance) + else await instance.defer("update",false) }) ) } @@ -116,7 +116,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"unclaim-message"|"other") + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //claim with reason @@ -128,7 +128,7 @@ export const registerModalResponders = async () => { await instance.defer("update",false) await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("other",{guild,channel,user,ticket,reason})) - }else if (originalSource == "other"){ + }else{ await instance.defer("update",false) await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } diff --git a/src/commands/clear.ts b/src/commands/clear.ts index 8541903..3eb7b66 100644 --- a/src/commands/clear.ts +++ b/src/commands/clear.ts @@ -92,12 +92,11 @@ export const registerButtonResponders = async () => { new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,source,cancel) => { const {guild,channel,user} = instance if (!guild || channel.isDMBased()) return - const originalSource = instance.interaction.customId.split("_")[1] - if (originalSource != "slash" && originalSource != "text" && originalSource != "other") return + const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIds_Default["opendiscord:clear-tickets"]["source"] const filter = instance.interaction.customId.split("_")[2] as api.ODTicketClearFilter //start ticket clear - instance.defer("update",true) + await instance.defer("update",true) const list: string[] = [] const ticketList = opendiscord.tickets.getAll().filter((ticket) => { if (filter == "all") return true diff --git a/src/commands/close.ts b/src/commands/close.ts index 75cc683..ebb4616 100644 --- a/src/commands/close.ts +++ b/src/commands/close.ts @@ -88,11 +88,11 @@ export const registerButtonResponders = async () => { opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:close-ticket",/^od:close-ticket_/)) opendiscord.responders.buttons.get("opendiscord:close-ticket").workers.add( new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source,cancel) => { - const originalSource = instance.interaction.customId.split("_")[1] - if (originalSource != "ticket-message" && originalSource != "reopen-message") return + const originalSource = instance.interaction.customId.split("_")[1] as Exclude if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:close-ticket-ticket-message").activate(instance) - else await opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").activate(instance) + else if (originalSource == "reopen-message") await opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").activate(instance) + else await instance.defer("update",false) }) ) } @@ -115,7 +115,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"reopen-message"|"other") + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //close with reason @@ -127,7 +127,7 @@ export const registerModalResponders = async () => { await instance.defer("update",false) await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason})) - }else if (originalSource == "other"){ + }else{ await instance.defer("update",false) await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } diff --git a/src/commands/delete.ts b/src/commands/delete.ts index 3a36efe..11d315f 100644 --- a/src/commands/delete.ts +++ b/src/commands/delete.ts @@ -84,13 +84,13 @@ export const registerButtonResponders = async () => { opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:delete-ticket",/^od:delete-ticket/)) opendiscord.responders.buttons.get("opendiscord:delete-ticket").workers.add( new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => { - const originalSource = instance.interaction.customId.split("_")[1] - if (originalSource != "ticket-message" && originalSource != "reopen-message" && originalSource != "close-message" && originalSource != "autoclose-message") return + const originalSource = instance.interaction.customId.split("_")[1] as Exclude if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-ticket-message").activate(instance) else if (originalSource == "close-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-close-message").activate(instance) else if (originalSource == "reopen-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-reopen-message").activate(instance) else if (originalSource == "autoclose-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-autoclose-message").activate(instance) + else await instance.defer("update",false) }) ) } @@ -113,7 +113,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"other") + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //delete with reason @@ -139,7 +139,7 @@ export const registerModalResponders = async () => { //don't await DELETE action => else it will update the message after the channel has been deleted opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false}) await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason})) - }else if (originalSource == "other"){ + }else{ await instance.defer("update",false) //don't await DELETE action => else it will update the message after the channel has been deleted opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false}) diff --git a/src/commands/pin.ts b/src/commands/pin.ts index ac63a59..e58858f 100644 --- a/src/commands/pin.ts +++ b/src/commands/pin.ts @@ -88,11 +88,11 @@ export const registerButtonResponders = async () => { opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:pin-ticket",/^od:pin-ticket/)) opendiscord.responders.buttons.get("opendiscord:pin-ticket").workers.add( new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source,cancel) => { - const originalSource = instance.interaction.customId.split("_")[1] - if (originalSource != "ticket-message" && originalSource != "unpin-message") return - + const originalSource = instance.interaction.customId.split("_")[1] as Exclude + if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:pin-ticket-ticket-message").activate(instance) - else await opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").activate(instance) + else if (originalSource == "unpin-message") await opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").activate(instance) + else await instance.defer("update",false) }) ) } @@ -115,7 +115,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"unpin-message"|"other") + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //pin with reason @@ -127,7 +127,7 @@ export const registerModalResponders = async () => { await instance.defer("update",false) await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("other",{guild,channel,user,ticket,reason})) - }else if (originalSource == "other"){ + }else{ await instance.defer("update",false) await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } diff --git a/src/commands/reopen.ts b/src/commands/reopen.ts index 6fe30c9..f398aec 100644 --- a/src/commands/reopen.ts +++ b/src/commands/reopen.ts @@ -88,12 +88,12 @@ export const registerButtonResponders = async () => { opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:reopen-ticket",/^od:reopen-ticket/)) opendiscord.responders.buttons.get("opendiscord:reopen-ticket").workers.add( new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => { - const originalSource = instance.interaction.customId.split("_")[1] - if (originalSource != "ticket-message" && originalSource != "close-message" && originalSource != "autoclose-message") return + const originalSource = instance.interaction.customId.split("_")[1] as Exclude if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-ticket-message").activate(instance) else if (originalSource == "close-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-close-message").activate(instance) - else await opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").activate(instance) + else if (originalSource == "autoclose-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").activate(instance) + else await instance.defer("update",false) }) ) } @@ -116,7 +116,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"close-message"|"autoclose-message"|"other") + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //reopen with reason @@ -132,7 +132,7 @@ export const registerModalResponders = async () => { await instance.defer("update",false) await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason})) - }else if (originalSource == "other"){ + }else{ await instance.defer("update",false) await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } diff --git a/src/commands/unclaim.ts b/src/commands/unclaim.ts index 37692f3..0cdec44 100644 --- a/src/commands/unclaim.ts +++ b/src/commands/unclaim.ts @@ -88,11 +88,11 @@ export const registerButtonResponders = async () => { opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:unclaim-ticket",/^od:unclaim-ticket/)) opendiscord.responders.buttons.get("opendiscord:unclaim-ticket").workers.add( new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source,cancel) => { - const originalSource = instance.interaction.customId.split("_")[1] - if (originalSource != "ticket-message" && originalSource != "claim-message") return + const originalSource = instance.interaction.customId.split("_")[1] as Exclude if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:unclaim-ticket-ticket-message").activate(instance) - else await opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").activate(instance) + else if (originalSource == "claim-message") await opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").activate(instance) + else await instance.defer("update",false) }) ) } @@ -115,7 +115,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"claim-message"|"other") + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //unclaim with reason @@ -127,7 +127,7 @@ export const registerModalResponders = async () => { await instance.defer("update",false) await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("other",{guild,channel,user,ticket,reason})) - }else if (originalSource == "other"){ + }else{ await instance.defer("update",false) await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } diff --git a/src/commands/unpin.ts b/src/commands/unpin.ts index 9160d8a..06095ca 100644 --- a/src/commands/unpin.ts +++ b/src/commands/unpin.ts @@ -88,11 +88,11 @@ export const registerButtonResponders = async () => { opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:unpin-ticket",/^od:unpin-ticket/)) opendiscord.responders.buttons.get("opendiscord:unpin-ticket").workers.add( new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source,cancel) => { - const originalSource = instance.interaction.customId.split("_")[1] - if (originalSource != "ticket-message" && originalSource != "pin-message") return + const originalSource = instance.interaction.customId.split("_")[1] as Exclude if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:unpin-ticket-ticket-message").activate(instance) - else await opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").activate(instance) + else if (originalSource == "pin-message") await opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").activate(instance) + else await instance.defer("update",false) }) ) } @@ -115,7 +115,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as ("ticket-message"|"pin-message"|"other") + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //unpin with reason @@ -127,7 +127,7 @@ export const registerModalResponders = async () => { await instance.defer("update",false) await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false}) await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("other",{guild,channel,user,ticket,reason})) - }else if (originalSource == "other"){ + }else{ await instance.defer("update",false) await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true}) } From 15eef95fdd95a6d75937701911bff90443e7f2c2 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 19 Feb 2025 15:43:43 +0100 Subject: [PATCH 149/157] Decreased /clear speed to reduce ratelimit chances --- src/actions/clearTickets.ts | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/actions/clearTickets.ts b/src/actions/clearTickets.ts index c654557..f2fac57 100644 --- a/src/actions/clearTickets.ts +++ b/src/actions/clearTickets.ts @@ -14,12 +14,32 @@ export const registerActions = async () => { await opendiscord.events.get("onTicketsClear").emit([list,user,channel,filter]) const nameList: string[] = [] - for (const ticket of list){ - const ticketChannel = await opendiscord.tickets.getTicketChannel(ticket) - if (!ticketChannel) return - nameList.push("#"+ticketChannel.name) - await opendiscord.actions.get("opendiscord:delete-ticket").run("clear",{guild,channel:ticketChannel,user,ticket,reason:"Cleared Ticket",sendMessage:true,withoutTranscript:false}) + + //split tickets into smaller groups of 10 (to decrease ratelimit chances for HTML Transcripts & discord API) + const subGroupList: api.ODTicket[][] = [] + let tempSubGroup: api.ODTicket[] = [] + list.forEach((ticket,index) => { + tempSubGroup.push(ticket) + if (tempSubGroup.length >= 10){ + subGroupList.push(tempSubGroup) + tempSubGroup = [] + } + }) + if (tempSubGroup.length > 0) subGroupList.push(tempSubGroup) + + let groupIndex = 0 + for (const ticketGroup of subGroupList){ + for (const ticket of ticketGroup){ + const ticketChannel = await opendiscord.tickets.getTicketChannel(ticket) + if (!ticketChannel) return + nameList.push("#"+ticketChannel.name) + await opendiscord.actions.get("opendiscord:delete-ticket").run("clear",{guild,channel:ticketChannel,user,ticket,reason:"Cleared Ticket",sendMessage:true,withoutTranscript:false}) + await utilities.timer(2000) //wait 2sec between each deletion + } + if (groupIndex < subGroupList.length-1) await utilities.timer(45*1000) //wait 45sec between each group deletion (10 tickets) + groupIndex++ } + instance.list = nameList await opendiscord.events.get("afterTicketsCleared").emit([list,user,channel,filter]) }), From 0d40c23aa888b0fe9f12f58d3956c3733435896d Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 19 Feb 2025 15:48:37 +0100 Subject: [PATCH 150/157] Fixed HTML Transcripts "member not found" error. --- src/core/api/openticket/transcript.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/api/openticket/transcript.ts b/src/core/api/openticket/transcript.ts index 854cfee..49e5ca9 100644 --- a/src/core/api/openticket/transcript.ts +++ b/src/core/api/openticket/transcript.ts @@ -318,7 +318,10 @@ export class ODTranscriptCollector { const restMsg = await this.#client.rest.get(discord.Routes.channelMessage(msg.channelId,msg.id)) as discord.APIMessage & {interaction_metadata:{name:string}} const commandName = restMsg.interaction_metadata.name ?? "unknown-command" //slash command reply - const member = await msg.guild.members.fetch(msg.interactionMetadata.user.id) + let member: discord.GuildMember|null = null + try{ + member = await msg.guild.members.fetch(msg.interactionMetadata.user.id) + }catch{} //member not found (user left the server) reply = { type:"interaction", name:commandName, From 177dee7468c61e8e22e6afe92cebae8a618a9157 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Thu, 27 Feb 2025 20:51:59 +0100 Subject: [PATCH 151/157] Type simplifications (for documentation) --- src/core/api/defaults/config.ts | 296 ++++++++++++++++++-------------- src/core/api/modules/base.ts | 5 + src/core/api/modules/checker.ts | 21 ++- 3 files changed, 183 insertions(+), 139 deletions(-) diff --git a/src/core/api/defaults/config.ts b/src/core/api/defaults/config.ts index ccdcfd0..5d54c6f 100644 --- a/src/core/api/defaults/config.ts +++ b/src/core/api/defaults/config.ts @@ -77,6 +77,170 @@ export interface ODJsonConfig_DefaultMessageSettingsType { */ export type ODJsonConfig_DefaultCmdPermissionSettingsType = "admin"|"everyone"|"none"|string +/**## ODJsonConfig_DefaultInfo `interface` + * This object contains a few URLs and metadata for the config. + */ +export interface ODJsonConfig_DefaultInfo { + /**A link to the Open Ticket documentation. */ + support:string, + /**A link to the DJdj Development discord server. */ + discord:string, + /**The version of Open Ticket this config is compatible with. */ + version:string +} + +/**## ODJsonConfig_DefaultSystemLogs `interface` + * All settings related to the log channel. + */ +export interface ODJsonConfig_DefaultSystemLogs { + /**Enable logging. Individual actions should still be added via the `"system"."messages"..."logs"` */ + enabled:boolean, + /**The channel to send logs to. */ + channel:string +} + +/**## ODJsonConfig_DefaultSystemLimits `interface` + * All settings related to global ticket limits. + */ +export interface ODJsonConfig_DefaultSystemLimits { + /**Enable global ticket limits. */ + enabled:boolean, + /**The maximum amount of tickets that are allowed in the server at the same time. */ + globalMaximum:number, + /**The maximum amount of tickets that a user is allowed to create at the same time. */ + userMaximum:number +} + +/**## ODJsonConfig_DefaultSystemPermissions `interface` + * Configure permissions for all Open Ticket commands & actions. + */ +export interface ODJsonConfig_DefaultSystemPermissions { + help:ODJsonConfig_DefaultCmdPermissionSettingsType, + panel:ODJsonConfig_DefaultCmdPermissionSettingsType, + ticket:ODJsonConfig_DefaultCmdPermissionSettingsType, + close:ODJsonConfig_DefaultCmdPermissionSettingsType, + delete:ODJsonConfig_DefaultCmdPermissionSettingsType, + reopen:ODJsonConfig_DefaultCmdPermissionSettingsType, + claim:ODJsonConfig_DefaultCmdPermissionSettingsType, + unclaim:ODJsonConfig_DefaultCmdPermissionSettingsType, + pin:ODJsonConfig_DefaultCmdPermissionSettingsType, + unpin:ODJsonConfig_DefaultCmdPermissionSettingsType, + move:ODJsonConfig_DefaultCmdPermissionSettingsType, + rename:ODJsonConfig_DefaultCmdPermissionSettingsType, + add:ODJsonConfig_DefaultCmdPermissionSettingsType, + remove:ODJsonConfig_DefaultCmdPermissionSettingsType, + blacklist:ODJsonConfig_DefaultCmdPermissionSettingsType, + stats:ODJsonConfig_DefaultCmdPermissionSettingsType, + clear:ODJsonConfig_DefaultCmdPermissionSettingsType, + autoclose:ODJsonConfig_DefaultCmdPermissionSettingsType, + autodelete:ODJsonConfig_DefaultCmdPermissionSettingsType +} + +/**## ODJsonConfig_DefaultSystemMessages `interface` + * Configure dm & log messages for all Open Ticket commands & actions. + */ +export interface ODJsonConfig_DefaultSystemMessages { + creation:ODJsonConfig_DefaultMessageSettingsType, + closing:ODJsonConfig_DefaultMessageSettingsType, + deleting:ODJsonConfig_DefaultMessageSettingsType, + reopening:ODJsonConfig_DefaultMessageSettingsType, + claiming:ODJsonConfig_DefaultMessageSettingsType, + pinning:ODJsonConfig_DefaultMessageSettingsType, + adding:ODJsonConfig_DefaultMessageSettingsType, + removing:ODJsonConfig_DefaultMessageSettingsType, + renaming:ODJsonConfig_DefaultMessageSettingsType, + moving:ODJsonConfig_DefaultMessageSettingsType, + blacklisting:ODJsonConfig_DefaultMessageSettingsType, + roleAdding:ODJsonConfig_DefaultMessageSettingsType, + roleRemoving:ODJsonConfig_DefaultMessageSettingsType +} + +/**## ODJsonConfig_DefaultSystem `interface` + * All settings related to the ticket system. + */ +export interface ODJsonConfig_DefaultSystem { + /**Remove all participants (except admins) from the ticket when it's closed. */ + removeParticipantsOnClose:boolean, + /**Reply with an ephemeral message when a ticket is created. */ + replyOnTicketCreation:boolean, + /**Reply with an ephemeral message when reaction roles are changed. */ + replyOnReactionRole:boolean, + /**Use a translated config checker in the console. */ + useTranslatedConfigChecker:boolean, + /**Prefer slash-commands over text-commands when displaying them in menu's and messages. */ + preferSlashOverText:boolean, + /**Reply with "unknown command" when the prefix is used without a valid command. */ + sendErrorOnUnknownCommand:boolean, + /**Display the question fields (in a ticket message) in code blocks. */ + questionFieldsInCodeBlock:boolean, + /**Disable the (✅❌) buttons and directly run the action. */ + disableVerifyBars:boolean, + /**Display error embeds/messages with red instead of the default bot color. */ + useRedErrorEmbeds:boolean, + /**The emoji style used in the bot. This will affect all embeds, titles & messages in the bot. */ + emojiStyle:"before"|"after"|"double"|"disabled", + + /**Enable/disable the ticket claim & unclaim button in the ticket message. */ + enableTicketClaimButtons:boolean, + /**Enable/disable the ticket close & re-open button in the ticket message. */ + enableTicketCloseButtons:boolean, + /**Enable/disable the ticket pin & unpin button in the ticket message. */ + enableTicketPinButtons:boolean, + /**Enable/disable the ticket delete button in the ticket message. */ + enableTicketDeleteButtons:boolean, + /**Enable/disable the "with reason" button for all actions in the ticket message. */ + enableTicketActionWithReason:boolean, + /**Enable/disable the delete without transcript feature (button & /delete command). */ + enableDeleteWithoutTranscript:boolean, + + /**All settings related to the log channel. */ + logs:ODJsonConfig_DefaultSystemLogs, + + /**All settings related to global ticket limits. */ + limits:ODJsonConfig_DefaultSystemLimits, + + /**Configure permissions for all Open Ticket commands & actions. */ + permissions:ODJsonConfig_DefaultSystemPermissions, + + /**Configure dm & log messages for all Open Ticket commands & actions. */ + messages:ODJsonConfig_DefaultSystemMessages +} + +/**## ODJsonConfig_DefaultGeneralData `interface` + * All contents of the `general.json` config file. + */ +export interface ODJsonConfig_DefaultGeneralData { + /**This object contains a few URLs and metadata for the config. */ + _INFO:ODJsonConfig_DefaultInfo, + + /**The token of the bot. (Empty when using `tokenFromENV`) */ + token:string, + /**Use the token from the `.env` file as `TOKEN=xxxxx`. */ + tokenFromENV:boolean, + + /**The main (hex) color used in almost every embed in the bot. */ + mainColor:discord.ColorResolvable, + /**The language to use. Can be the id of the language or the id without the prefix when using `opendiscord:...`. */ + language:string, + /**The prefix used in all text-commands. */ + prefix:string, + /**The id of the discord server where the bot is used. */ + serverId:string, + /**A list of discord role ids which are able to access all tickets & commands. */ + globalAdmins:string[], + + /**Are slash commands enabled? */ + slashCommands:boolean, + /**Are text commands enabled? */ + textCommands:boolean, + + /**All settings related to the status of the bot. */ + status:ODJsonConfig_DefaultStatusType, + + /**All settings related to the ticket system. */ + system:ODJsonConfig_DefaultSystem +} + /**## ODJsonConfig_DefaultGeneral `default_class` * This is a special class that adds type definitions & typescript to the ODJsonConfig class. * It doesn't add any extra features! @@ -84,137 +248,7 @@ export type ODJsonConfig_DefaultCmdPermissionSettingsType = "admin"|"everyone"|" * This default class is made for the `general.json` config! */ export class ODJsonConfig_DefaultGeneral extends ODJsonConfig { - declare data: { - /**This object contains a few URLs and metadata for the config. */ - _INFO:{ - /**A link to the Open Ticket documentation. */ - support:string, - /**A link to the DJdj Development discord server. */ - discord:string, - /**The version of Open Ticket this config is compatible with. */ - version:string - }, - - /**The token of the bot. (Empty when using `tokenFromENV`) */ - token:string, - /**Use the token from the `.env` file as `TOKEN=xxxxx`. */ - tokenFromENV:boolean, - - /**The main (hex) color used in almost every embed in the bot. */ - mainColor:discord.ColorResolvable, - /**The language to use. Can be the id of the language or the id without the prefix when using `opendiscord:...`. */ - language:string, - /**The prefix used in all text-commands. */ - prefix:string, - /**The id of the discord server where the bot is used. */ - serverId:string, - /**A list of discord role ids which are able to access all tickets & commands. */ - globalAdmins:string[], - - /**Are slash commands enabled? */ - slashCommands:boolean, - /**Are text commands enabled? */ - textCommands:boolean, - - /**All settings related to the status of the bot. */ - status:ODJsonConfig_DefaultStatusType, - - /**All settings related to the ticket system. */ - system:{ - /**Remove all participants (except admins) from the ticket when it's closed. */ - removeParticipantsOnClose:boolean, - /**Reply with an ephemeral message when a ticket is created. */ - replyOnTicketCreation:boolean, - /**Reply with an ephemeral message when reaction roles are changed. */ - replyOnReactionRole:boolean, - /**Use a translated config checker in the console. */ - useTranslatedConfigChecker:boolean, - /**Prefer slash-commands over text-commands when displaying them in menu's and messages. */ - preferSlashOverText:boolean, - /**Reply with "unknown command" when the prefix is used without a valid command. */ - sendErrorOnUnknownCommand:boolean, - /**Display the question fields (in a ticket message) in code blocks. */ - questionFieldsInCodeBlock:boolean, - /**Disable the (✅❌) buttons and directly run the action. */ - disableVerifyBars:boolean, - /**Display error embeds/messages with red instead of the default bot color. */ - useRedErrorEmbeds:boolean, - /**The emoji style used in the bot. This will affect all embeds, titles & messages in the bot. */ - emojiStyle:"before"|"after"|"double"|"disabled", - - - /**Enable/disable the ticket claim & unclaim button in the ticket message. */ - enableTicketClaimButtons:boolean, - /**Enable/disable the ticket close & re-open button in the ticket message. */ - enableTicketCloseButtons:boolean, - /**Enable/disable the ticket pin & unpin button in the ticket message. */ - enableTicketPinButtons:boolean, - /**Enable/disable the ticket delete button in the ticket message. */ - enableTicketDeleteButtons:boolean, - /**Enable/disable the "with reason" button for all actions in the ticket message. */ - enableTicketActionWithReason:boolean, - /**Enable/disable the delete without transcript feature (button & /delete command). */ - enableDeleteWithoutTranscript:boolean, - - /**All settings related to the log channel. */ - logs:{ - /**Enable logging. Individual actions should still be added via the `"system"."messages"..."logs"` */ - enabled:boolean, - /**The channel to send logs to. */ - channel:string - }, - - /**All settings related to global ticket limits. */ - limits:{ - /**Enable global ticket limits. */ - enabled:boolean, - /**The maximum amount of tickets that are allowed in the server at the same time. */ - globalMaximum:number, - /**The maximum amount of tickets that a user is allowed to create at the same time. */ - userMaximum:number - }, - - /**Configure permissions for all Open Ticket commands & actions. */ - permissions:{ - help:ODJsonConfig_DefaultCmdPermissionSettingsType, - panel:ODJsonConfig_DefaultCmdPermissionSettingsType, - ticket:ODJsonConfig_DefaultCmdPermissionSettingsType, - close:ODJsonConfig_DefaultCmdPermissionSettingsType, - delete:ODJsonConfig_DefaultCmdPermissionSettingsType, - reopen:ODJsonConfig_DefaultCmdPermissionSettingsType, - claim:ODJsonConfig_DefaultCmdPermissionSettingsType, - unclaim:ODJsonConfig_DefaultCmdPermissionSettingsType, - pin:ODJsonConfig_DefaultCmdPermissionSettingsType, - unpin:ODJsonConfig_DefaultCmdPermissionSettingsType, - move:ODJsonConfig_DefaultCmdPermissionSettingsType, - rename:ODJsonConfig_DefaultCmdPermissionSettingsType, - add:ODJsonConfig_DefaultCmdPermissionSettingsType, - remove:ODJsonConfig_DefaultCmdPermissionSettingsType, - blacklist:ODJsonConfig_DefaultCmdPermissionSettingsType, - stats:ODJsonConfig_DefaultCmdPermissionSettingsType, - clear:ODJsonConfig_DefaultCmdPermissionSettingsType, - autoclose:ODJsonConfig_DefaultCmdPermissionSettingsType, - autodelete:ODJsonConfig_DefaultCmdPermissionSettingsType - }, - - /**Configure dm & log messages for all Open Ticket commands & actions. */ - messages:{ - creation:ODJsonConfig_DefaultMessageSettingsType, - closing:ODJsonConfig_DefaultMessageSettingsType, - deleting:ODJsonConfig_DefaultMessageSettingsType, - reopening:ODJsonConfig_DefaultMessageSettingsType, - claiming:ODJsonConfig_DefaultMessageSettingsType, - pinning:ODJsonConfig_DefaultMessageSettingsType, - adding:ODJsonConfig_DefaultMessageSettingsType, - removing:ODJsonConfig_DefaultMessageSettingsType, - renaming:ODJsonConfig_DefaultMessageSettingsType, - moving:ODJsonConfig_DefaultMessageSettingsType, - blacklisting:ODJsonConfig_DefaultMessageSettingsType, - roleAdding:ODJsonConfig_DefaultMessageSettingsType, - roleRemoving:ODJsonConfig_DefaultMessageSettingsType - } - } - } + declare data: ODJsonConfig_DefaultGeneralData } /**## ODJsonConfig_DefaultOptionType `interface` diff --git a/src/core/api/modules/base.ts b/src/core/api/modules/base.ts index a3b8066..4a7ff12 100644 --- a/src/core/api/modules/base.ts +++ b/src/core/api/modules/base.ts @@ -40,6 +40,11 @@ export type ODValidJsonType = string|number|boolean|object|ODValidJsonType[]|nul */ export type ODInterfaceWithPartialProperty = Omit & Partial> +/**## ODDiscordIdType `type` + * A list of all available discord ID types. Used in the config checker. + */ +export type ODDiscordIdType = "role"|"server"|"channel"|"category"|"user"|"member"|"interaction"|"message" + /**## ODId `class` * This is an Open Ticket identifier. * diff --git a/src/core/api/modules/checker.ts b/src/core/api/modules/checker.ts index 0e172cf..14b397b 100644 --- a/src/core/api/modules/checker.ts +++ b/src/core/api/modules/checker.ts @@ -1,7 +1,7 @@ /////////////////////////////////////// //CONFIG CHECKER MODULE /////////////////////////////////////// -import { ODId, ODManager, ODManagerData, ODValidId, ODValidJsonType } from "./base" +import { ODDiscordIdType, ODId, ODManager, ODManagerData, ODValidId, ODValidJsonType } from "./base" import { ODConfig } from "./config" import { ODLanguageManager } from "./language" import { ODDebugger } from "./console" @@ -218,6 +218,11 @@ export class ODCheckerTranslationRegister { } } +/**## ODCheckerFunctionCallback `type` + * This is the function used in the `ODCheckerFunction` class. + */ +export type ODCheckerFunctionCallback = (manager:ODCheckerManager, functions:ODCheckerFunctionManager) => ODCheckerResult + /**## ODCheckerFunction `class` * This is an Open Ticket config checker function. * @@ -225,10 +230,10 @@ export class ODCheckerTranslationRegister { * It's mostly used for things that need to be checked globally! */ export class ODCheckerFunction extends ODManagerData { - /**The function itself :) */ - func: (manager:ODCheckerManager, functions:ODCheckerFunctionManager) => ODCheckerResult + /**The function which will be executed globally after all config checkers. */ + func: ODCheckerFunctionCallback - constructor(id:ODValidId, func:(manager:ODCheckerManager, functions:ODCheckerFunctionManager) => ODCheckerResult){ + constructor(id:ODValidId, func:ODCheckerFunctionCallback){ super(id) this.func = func } @@ -1043,13 +1048,13 @@ export class ODCheckerEnabledObjectStructure extends ODCheckerStructure { */ export class ODCheckerCustomStructure_DiscordId extends ODCheckerStringStructure { /**The type of id (used in rendering) */ - readonly type: "role"|"server"|"channel"|"category"|"user"|"member"|"interaction"|"message" + readonly type: ODDiscordIdType /**Is this id allowed to be empty */ readonly emptyAllowed: boolean /**Extra matches (value will also be valid when one of these options match) */ readonly extraOptions: string[] - constructor(id:ODValidId, type:"role"|"server"|"channel"|"category"|"user"|"member"|"interaction"|"message", emptyAllowed:boolean, extraOptions:string[], options?:ODCheckerStringStructureOptions){ + constructor(id:ODValidId, type:ODDiscordIdType, emptyAllowed:boolean, extraOptions:string[], options?:ODCheckerStringStructureOptions){ //add premade custom structure checker const newOptions = options ?? {} newOptions.custom = (checker,value,locationTrace,locationId,locationDocs) => { @@ -1083,11 +1088,11 @@ export class ODCheckerCustomStructure_DiscordId extends ODCheckerStringStructure */ export class ODCheckerCustomStructure_DiscordIdArray extends ODCheckerArrayStructure { /**The type of id (used in rendering) */ - readonly type: "role"|"server"|"channel"|"category"|"user"|"member"|"interaction"|"message" + readonly type: ODDiscordIdType /**Extra matches (value will also be valid when one of these options match) */ readonly extraOptions: string[] - constructor(id:ODValidId, type:"role"|"server"|"channel"|"category"|"user"|"member"|"interaction"|"message", extraOptions:string[], options?:ODCheckerArrayStructureOptions, idOptions?:ODCheckerStringStructureOptions){ + constructor(id:ODValidId, type:ODDiscordIdType, extraOptions:string[], options?:ODCheckerArrayStructureOptions, idOptions?:ODCheckerStringStructureOptions){ //add premade custom structure checker const newOptions = options ?? {} newOptions.propertyChecker = new ODCheckerCustomStructure_DiscordId(id,type,false,extraOptions,idOptions) From e7ad3dd50b8048f2a683a763f3e7046857dbcec5 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 12 Mar 2025 22:12:51 +0100 Subject: [PATCH 152/157] Fixed startup crash codes (for Docker) --- src/core/startup/init.ts | 2 +- src/index.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/startup/init.ts b/src/core/startup/init.ts index d1e5958..450ab7e 100644 --- a/src/core/startup/init.ts +++ b/src/core/startup/init.ts @@ -4,7 +4,7 @@ let tempErrors: string[] = [] const tempError = () => { if (tempErrors.length > 0){ console.log("\n\n==============================\n[OPEN TICKET ERROR]: "+tempErrors.join("\n[OPEN TICKET ERROR]: ")+"\n==============================\n\n") - process.exit(0) + process.exit(1) } tempErrors = [] } diff --git a/src/index.ts b/src/index.ts index 1bb3b3e..9c0c914 100644 --- a/src/index.ts +++ b/src/index.ts @@ -282,7 +282,7 @@ const main = async () => { if (opendiscord.checkers.lastResult && !opendiscord.checkers.lastResult.valid && !(disableCheckerFlag ? disableCheckerFlag.value : false)){ await opendiscord.events.get("onCheckerQuit").emit([opendiscord.checkers]) if (opendiscord.defaults.getDefault("checkerQuit")){ - process.exit(0) + process.exit(1) //there is no afterCheckerQuitted event :) } } @@ -366,7 +366,7 @@ const main = async () => { opendiscord.log("The bot isn't a member of the server provided in the config!","error") opendiscord.log("Please invite your bot to the server!","info") console.log("\n") - process.exit(0) + process.exit(1) } //throw if bot doesn't have permissions in main server if (!client.checkGuildPerms(mainServer)){ @@ -374,7 +374,7 @@ const main = async () => { opendiscord.log("The bot doesn't have the correct permissions in the server provided in the config!","error") opendiscord.log("Please give the bot \"Administrator\" permissions or visit the documentation!","info") console.log("\n") - process.exit(0) + process.exit(1) } if (opendiscord.defaults.getDefault("clientMultiGuildWarning")){ //warn if bot is in multiple servers From 1e159c9bab48b3655620740400055320e4d8c309 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Wed, 12 Mar 2025 22:13:00 +0100 Subject: [PATCH 153/157] Improved dockerfile & compose --- docker-compose.yml | 8 +++++--- dockerfile | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 145d49b..8d6b02f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,6 +4,8 @@ services: openticket: build: . volumes: - - .:/app - environment: NODE_ENV=production - restart: unless-stopped \ No newline at end of file + - openticket:/home/container + restart: no + container_name: open-ticket +volumes: + openticket: \ No newline at end of file diff --git a/dockerfile b/dockerfile index bca73e3..4a0acad 100644 --- a/dockerfile +++ b/dockerfile @@ -1,9 +1,9 @@ # Docker File for Open Ticket v4 -# Use the official Node.js 18 image from Docker Hub -FROM node:18-alpine +# Use the official Node.js 20 image from Docker Hub +FROM node:20-alpine -# Set a different working directory inside the container -WORKDIR /usr/src/openticket +# Set pterodactyl working directory inside the container +WORKDIR /home/container # Copy package.json and package-lock.json into the container COPY package*.json ./ From ba3a35a343485ee63a784eb9a4e01eca199993dd Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 16 Mar 2025 18:34:43 +0100 Subject: [PATCH 154/157] Added official Open Ticket Pterodactyl eggs! --- .eggs/README.md | 34 ++++++++++++++++++ .eggs/openticket-egg-dev.json | 62 ++++++++++++++++++++++++++++++++ .eggs/openticket-egg-main.json | 62 ++++++++++++++++++++++++++++++++ .eggs/openticket-egg-v3.5.9.json | 62 ++++++++++++++++++++++++++++++++ .eggs/openticket-egg-v4.0.0.json | 62 ++++++++++++++++++++++++++++++++ README.md | 1 + 6 files changed, 283 insertions(+) create mode 100644 .eggs/README.md create mode 100644 .eggs/openticket-egg-dev.json create mode 100644 .eggs/openticket-egg-main.json create mode 100644 .eggs/openticket-egg-v3.5.9.json create mode 100644 .eggs/openticket-egg-v4.0.0.json diff --git a/.eggs/README.md b/.eggs/README.md new file mode 100644 index 0000000..cd5a7c8 --- /dev/null +++ b/.eggs/README.md @@ -0,0 +1,34 @@ +# Pterodactyl Eggs +Open Ticket Logo + +[![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.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v4.0.0) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj) + +Hi there! Open Ticket provides **official eggs** for the Pterodactyl & Pelican panels!
+There are different eggs for different versions of Open Ticket. +Please choose the one that fits your needs the most. + +If you encounter any issues while installing these eggs, please head to our [**discord server**](https://discord.dj-dj.be) for further assistance! + +### Requirements +It's recommended to provide at least `1GB` of **Memory/RAM** and `5GB` of **disk space** for Open Ticket to work correctly. + +### Egg Variants +[**`openticket-egg-main.json` (Recommended)**](openticket-egg-main.json) +- This egg will use the `main` branch of Open Ticket. + +[**`openticket-egg-v4.0.0.json`**](openticket-egg-v4.0.0.json) +- This egg will always use Open Ticket `v4.0.0`. Open Ticket updates will not have an effect on this egg. + +[**`openticket-egg-v3.5.9.json`**](openticket-egg-v3.5.9.json) +- This egg will always use Open Ticket `v3.5.9`. Open Ticket updates will not have an effect on this egg. + +[**`openticket-egg-dev.json` (Not Recommended)**](openticket-egg-dev.json) +- This egg will use the `dev` branch of Open Ticket. + +--- +Open Ticket Logo + +**Pterodactyl Eggs**
+[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)
+ +© 2025 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file diff --git a/.eggs/openticket-egg-dev.json b/.eggs/openticket-egg-dev.json new file mode 100644 index 0000000..b06efe5 --- /dev/null +++ b/.eggs/openticket-egg-dev.json @@ -0,0 +1,62 @@ +{ + "_comment": "DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO", + "meta": { + "version": "PTDL_v2", + "update_url": null + }, + "exported_at": "2025-03-16T18:10:21+01:00", + "name": "Open Ticket (Experimental)", + "author": "support@dj-dj.be", + "description": "This is the experimental Pterodactyl egg for Open Ticket, the most advanced & customisable discord ticket bot that you will ever find! DO NOT USE IN PRODUCTION!", + "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 (dev)\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=\"dev\"\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\/DJj123dj\/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\/DJj123dj\/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\/DJj123dj\/open-ticket.git .\r\n fi\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing Open Ticket node.js packages.\"\r\nif [ -f \/mnt\/server\/package.json ]; then\r\n \/usr\/local\/bin\/npm install --omit=dev\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing custom node.js packages.\"\r\nif [[ ! -z ${NODE_PACKAGES} ]]; then\r\n \/usr\/local\/bin\/npm install ${NODE_PACKAGES}\r\nfi\r\n\r\necho -e \"[OT INSTALLER] install complete!\"\r\nexit 0", + "container": "node:latest", + "entrypoint": "bash" + } + }, + "variables": [ + { + "name": "Additional Npm Packages", + "description": "Specify additional npm packages used by Open Ticket plugins. Use spaces to separate.", + "env_variable": "NODE_PACKAGES", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + }, + { + "name": "Startup Flags", + "description": "Start the bot with additional Open Ticket flags. Separate using spaces.\r\nA full reference list can be found in the documentation.", + "env_variable": "NODE_FLAGS", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + }, + { + "name": "Uninstall Npm Packages", + "description": "A list of npm packages to uninstall. Separate by spaces.", + "env_variable": "UNNODE_PACKAGES", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + } + ] +} \ No newline at end of file diff --git a/.eggs/openticket-egg-main.json b/.eggs/openticket-egg-main.json new file mode 100644 index 0000000..27d8509 --- /dev/null +++ b/.eggs/openticket-egg-main.json @@ -0,0 +1,62 @@ +{ + "_comment": "DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO", + "meta": { + "version": "PTDL_v2", + "update_url": null + }, + "exported_at": "2025-03-16T18:10:20+01:00", + "name": "Open Ticket (Latest)", + "author": "support@dj-dj.be", + "description": "This is the official Pterodactyl egg for Open Ticket, 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 (main)\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=\"main\"\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\/DJj123dj\/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\/DJj123dj\/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\/DJj123dj\/open-ticket.git .\r\n fi\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing Open Ticket node.js packages.\"\r\nif [ -f \/mnt\/server\/package.json ]; then\r\n \/usr\/local\/bin\/npm install --omit=dev\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing custom node.js packages.\"\r\nif [[ ! -z ${NODE_PACKAGES} ]]; then\r\n \/usr\/local\/bin\/npm install ${NODE_PACKAGES}\r\nfi\r\n\r\necho -e \"[OT INSTALLER] install complete!\"\r\nexit 0", + "container": "node:latest", + "entrypoint": "bash" + } + }, + "variables": [ + { + "name": "Additional Npm Packages", + "description": "Specify additional npm packages used by Open Ticket plugins. Use spaces to separate.", + "env_variable": "NODE_PACKAGES", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + }, + { + "name": "Startup Flags", + "description": "Start the bot with additional Open Ticket flags. Separate using spaces.\r\nA full reference list can be found in the documentation.", + "env_variable": "NODE_FLAGS", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + }, + { + "name": "Uninstall Npm Packages", + "description": "A list of npm packages to uninstall. Separate by spaces.", + "env_variable": "UNNODE_PACKAGES", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + } + ] +} \ No newline at end of file diff --git a/.eggs/openticket-egg-v3.5.9.json b/.eggs/openticket-egg-v3.5.9.json new file mode 100644 index 0000000..1e5a39f --- /dev/null +++ b/.eggs/openticket-egg-v3.5.9.json @@ -0,0 +1,62 @@ +{ + "_comment": "DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO", + "meta": { + "version": "PTDL_v2", + "update_url": null + }, + "exported_at": "2025-03-16T18:10:19+01:00", + "name": "Open Ticket (v3.5.9)", + "author": "support@dj-dj.be", + "description": "This is the official Pterodactyl egg for Open Ticket v3.5.9, 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 (v3.5.9)\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=\"v3.5.9\"\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\/DJj123dj\/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\/DJj123dj\/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\/DJj123dj\/open-ticket.git .\r\n fi\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing Open Ticket node.js packages.\"\r\nif [ -f \/mnt\/server\/package.json ]; then\r\n \/usr\/local\/bin\/npm install --omit=dev\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing custom node.js packages.\"\r\nif [[ ! -z ${NODE_PACKAGES} ]]; then\r\n \/usr\/local\/bin\/npm install ${NODE_PACKAGES}\r\nfi\r\n\r\necho -e \"[OT INSTALLER] install complete!\"\r\nexit 0", + "container": "node:latest", + "entrypoint": "bash" + } + }, + "variables": [ + { + "name": "Additional Npm Packages", + "description": "Specify additional npm packages used by Open Ticket plugins. Use spaces to separate.", + "env_variable": "NODE_PACKAGES", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + }, + { + "name": "Startup Flags", + "description": "Start the bot with additional Open Ticket flags. Separate using spaces.\r\nA full reference list can be found in the documentation.", + "env_variable": "NODE_FLAGS", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + }, + { + "name": "Uninstall Npm Packages", + "description": "A list of npm packages to uninstall. Separate by spaces.", + "env_variable": "UNNODE_PACKAGES", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + } + ] +} \ No newline at end of file diff --git a/.eggs/openticket-egg-v4.0.0.json b/.eggs/openticket-egg-v4.0.0.json new file mode 100644 index 0000000..22a6392 --- /dev/null +++ b/.eggs/openticket-egg-v4.0.0.json @@ -0,0 +1,62 @@ +{ + "_comment": "DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO", + "meta": { + "version": "PTDL_v2", + "update_url": null + }, + "exported_at": "2025-03-16T18:10:18+01:00", + "name": "Open Ticket (v4.0.0)", + "author": "support@dj-dj.be", + "description": "This is the official Pterodactyl egg for Open Ticket v4.0.0, the most advanced & customisable discord ticket bot that you will ever find! You can customise up to 300+ variables! This includes Html Transcripts, Advanced Plugins, Custom Embeds, Questions\/Modals, Stats & more!", + "features": null, + "docker_images": { + "ghcr.io\/parkervcp\/yolks:nodejs_20": "ghcr.io\/parkervcp\/yolks:nodejs_20" + }, + "file_denylist": [], + "startup": "if [[ ! -z ${NODE_PACKAGES} ]]; then npm install ${NODE_PACKAGES}; fi; if [[ ! -z ${UNNODE_PACKAGES} ]]; then npm uninstall ${UNNODE_PACKAGES}; fi; if [ -f \/home\/container\/package.json ]; then npm install; fi; node \"\/home\/container\/index.js\" ${NODE_FLAGS};", + "config": { + "files": "{}", + "startup": "{\r\n \"done\": \"STARTUP INFO:\"\r\n}", + "logs": "{}", + "stop": "^C" + }, + "scripts": { + "installation": { + "script": "#!\/bin\/bash\r\n# Open Ticket Installation Script (v4.0.0)\r\n# Inspired by: Node.js Installation Script\r\n# \u00a9 DJdj Development\r\n\r\necho -e \"[OT INSTALLER] installing dependencies. please wait...\"\r\napt update\r\napt install -y git curl\r\n\r\necho -e \"[OT INSTALLER] updating npm. please wait...\"\r\nnpm install npm@latest --location=global\r\n\r\nmkdir -p \/mnt\/server\r\ncd \/mnt\/server\r\n\r\nBRANCH=\"v4.0.0\"\r\n\r\nif [ \"$(ls -A \/mnt\/server)\" ]; then\r\n echo -e \"[OT INSTALLER] \/mnt\/server directory is not empty.\"\r\n if [ -d .git ]; then\r\n echo -e \"[OT INSTALLER] .git directory exists\"\r\n if [ -f .git\/config ]; then\r\n echo -e \"[OT INSTALLER] loading info from git config\"\r\n ORIGIN=$(git config --get remote.origin.url)\r\n else\r\n echo -e \"[OT INSTALLER] files found with no git config\"\r\n echo -e \"[OT INSTALLER] closing out without touching things to not break anything\"\r\n exit 10\r\n fi\r\n fi\r\n\r\n if [ \"${ORIGIN}\" == \"https:\/\/github.com\/DJj123dj\/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\/DJj123dj\/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\/DJj123dj\/open-ticket.git .\r\n fi\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing Open Ticket node.js packages.\"\r\nif [ -f \/mnt\/server\/package.json ]; then\r\n \/usr\/local\/bin\/npm install --omit=dev\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing custom node.js packages.\"\r\nif [[ ! -z ${NODE_PACKAGES} ]]; then\r\n \/usr\/local\/bin\/npm install ${NODE_PACKAGES}\r\nfi\r\n\r\necho -e \"[OT INSTALLER] install complete!\"\r\nexit 0", + "container": "node:latest", + "entrypoint": "bash" + } + }, + "variables": [ + { + "name": "Additional Npm Packages", + "description": "Specify additional npm packages used by Open Ticket plugins. Use spaces to separate.", + "env_variable": "NODE_PACKAGES", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + }, + { + "name": "Startup Flags", + "description": "Start the bot with additional Open Ticket flags. Separate using spaces.\r\nA full reference list can be found in the documentation.", + "env_variable": "NODE_FLAGS", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + }, + { + "name": "Uninstall Npm Packages", + "description": "A list of npm packages to uninstall. Separate by spaces.", + "env_variable": "UNNODE_PACKAGES", + "default_value": "", + "user_viewable": false, + "user_editable": true, + "rules": "string|nullable", + "field_type": "text" + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index ad305b4..82f5e2c 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ You're also able to customise every little aspect of the bot! From embeds to tra > The translation count may not be accurate! ### 📌 Features +- **🦇 pterodactyl support** - Open Ticket works perfect on Pterodactyl based panels! [(Download official eggs)](.eggs/README.md) - **💩 no bloat** - Your Open Ticket bot doesn't contain any form of bloat or credits! - **🔒 tested & secure** - Open Ticket has been tested by thousands of servers and is very secure! - **📈 scalable** - Open Ticket is made to handle huge servers! (Already tested in **servers with 100k members**) From bed4e2a56a259a23ab8ec6936cbc8b8c89c19e65 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 16 Mar 2025 18:35:25 +0100 Subject: [PATCH 155/157] Improved CONTRIBUTING.md & SECURITY.md markdown --- .github/CONTRIBUTING.md | 4 ++-- .github/SECURITY.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index ab24c6a..c36d673 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Contributing Guidelines Open Ticket Logo -[![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.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v4.0.0) +[![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.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v4.0.0) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj) These are the Contributing Guidelines of Open Ticket!
Here you can find everything you need to know about contributing to Open Ticket.
@@ -89,4 +89,4 @@ you are **REQUIRED to send the bug privately via one of the following methods:** **Contributing Guidelines**
[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)
-© 2024 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file +© 2025 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file diff --git a/.github/SECURITY.md b/.github/SECURITY.md index b0d15bb..ab54d11 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -46,4 +46,4 @@ If possible, try to provide screenshots! **Security Policy**
[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)
-© 2024 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file +© 2025 - [DJdj Development](https://www.dj-dj.be) - [Terms](https://www.dj-dj.be/terms#terms) - [Privacy Policy](https://www.dj-dj.be/terms#privacy) \ No newline at end of file From d28fcf40d713cc02f5336533628e6c81860ba69c Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sat, 22 Mar 2025 11:08:09 +0100 Subject: [PATCH 156/157] Fixed broken flag alias using --dev-database --- src/data/framework/flagLoader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/framework/flagLoader.ts b/src/data/framework/flagLoader.ts index 9f980ff..8c4e5bc 100644 --- a/src/data/framework/flagLoader.ts +++ b/src/data/framework/flagLoader.ts @@ -3,7 +3,7 @@ import {opendiscord, api, utilities} from "../../index" export const loadAllFlags = async () => { opendiscord.flags.add(new api.ODFlag("opendiscord:no-migration","No Migration","Disable Open Ticket data migration on update!","--no-migration",["-nm"])) opendiscord.flags.add(new api.ODFlag("opendiscord:dev-config","Developer Config","Use the configs in /devconfig/ instead of /config/!","--dev-config",["-dc"])) - opendiscord.flags.add(new api.ODFlag("opendiscord:dev-database","Developer Database","Use the databases in /devdatabase/ instead of /database/!","--dev-database",["-nd"])) + opendiscord.flags.add(new api.ODFlag("opendiscord:dev-database","Developer Database","Use the databases in /devdatabase/ instead of /database/!","--dev-database",["-dd"])) opendiscord.flags.add(new api.ODFlag("opendiscord:debug","Debug Mode","Couldn't you find the error? Try to check this out!","--debug",["-d"])) opendiscord.flags.add(new api.ODFlag("opendiscord:crash","Crash On Error","Crash the bot on an unknown error!","--crash",["-cr"])) opendiscord.flags.add(new api.ODFlag("opendiscord:no-transcripts","No HTML Transcripts","Disable uploading HTML transcripts (for debugging)","--no-transcripts",["-nt"])) From bd4929f11b7c74f09144c591a7af6f93f7dd0924 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Tue, 25 Mar 2025 17:49:42 +0100 Subject: [PATCH 157/157] Updated all URLs for repository transfer --- .eggs/README.md | 2 +- .eggs/openticket-egg-dev.json | 2 +- .eggs/openticket-egg-main.json | 2 +- .eggs/openticket-egg-v3.5.9.json | 2 +- .eggs/openticket-egg-v4.0.0.json | 2 +- .github/CONTRIBUTING.md | 4 +- .github/SECURITY.md | 2 +- README.md | 82 +++++++++++++------------- package.json | 4 +- src/data/framework/liveStatusLoader.ts | 2 +- 10 files changed, 52 insertions(+), 52 deletions(-) diff --git a/.eggs/README.md b/.eggs/README.md index cd5a7c8..b165f4a 100644 --- a/.eggs/README.md +++ b/.eggs/README.md @@ -1,7 +1,7 @@ # Pterodactyl Eggs Open Ticket Logo -[![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.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v4.0.0) [![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.0-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.0) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj) Hi there! Open Ticket provides **official eggs** for the Pterodactyl & Pelican panels!
There are different eggs for different versions of Open Ticket. diff --git a/.eggs/openticket-egg-dev.json b/.eggs/openticket-egg-dev.json index b06efe5..dea9a07 100644 --- a/.eggs/openticket-egg-dev.json +++ b/.eggs/openticket-egg-dev.json @@ -22,7 +22,7 @@ }, "scripts": { "installation": { - "script": "#!\/bin\/bash\r\n# Open Ticket Installation Script (dev)\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=\"dev\"\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\/DJj123dj\/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\/DJj123dj\/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\/DJj123dj\/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", + "script": "#!\/bin\/bash\r\n# Open Ticket Installation Script (dev)\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=\"dev\"\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" } diff --git a/.eggs/openticket-egg-main.json b/.eggs/openticket-egg-main.json index 27d8509..0e0337d 100644 --- a/.eggs/openticket-egg-main.json +++ b/.eggs/openticket-egg-main.json @@ -22,7 +22,7 @@ }, "scripts": { "installation": { - "script": "#!\/bin\/bash\r\n# Open Ticket Installation Script (main)\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=\"main\"\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\/DJj123dj\/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\/DJj123dj\/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\/DJj123dj\/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", + "script": "#!\/bin\/bash\r\n# Open Ticket Installation Script (main)\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=\"main\"\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" } diff --git a/.eggs/openticket-egg-v3.5.9.json b/.eggs/openticket-egg-v3.5.9.json index 1e5a39f..3249d68 100644 --- a/.eggs/openticket-egg-v3.5.9.json +++ b/.eggs/openticket-egg-v3.5.9.json @@ -22,7 +22,7 @@ }, "scripts": { "installation": { - "script": "#!\/bin\/bash\r\n# Open Ticket Installation Script (v3.5.9)\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=\"v3.5.9\"\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\/DJj123dj\/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\/DJj123dj\/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\/DJj123dj\/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", + "script": "#!\/bin\/bash\r\n# Open Ticket Installation Script (v3.5.9)\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=\"v3.5.9\"\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" } diff --git a/.eggs/openticket-egg-v4.0.0.json b/.eggs/openticket-egg-v4.0.0.json index 22a6392..62687c6 100644 --- a/.eggs/openticket-egg-v4.0.0.json +++ b/.eggs/openticket-egg-v4.0.0.json @@ -22,7 +22,7 @@ }, "scripts": { "installation": { - "script": "#!\/bin\/bash\r\n# Open Ticket Installation Script (v4.0.0)\r\n# Inspired by: Node.js Installation Script\r\n# \u00a9 DJdj Development\r\n\r\necho -e \"[OT INSTALLER] installing dependencies. please wait...\"\r\napt update\r\napt install -y git curl\r\n\r\necho -e \"[OT INSTALLER] updating npm. please wait...\"\r\nnpm install npm@latest --location=global\r\n\r\nmkdir -p \/mnt\/server\r\ncd \/mnt\/server\r\n\r\nBRANCH=\"v4.0.0\"\r\n\r\nif [ \"$(ls -A \/mnt\/server)\" ]; then\r\n echo -e \"[OT INSTALLER] \/mnt\/server directory is not empty.\"\r\n if [ -d .git ]; then\r\n echo -e \"[OT INSTALLER] .git directory exists\"\r\n if [ -f .git\/config ]; then\r\n echo -e \"[OT INSTALLER] loading info from git config\"\r\n ORIGIN=$(git config --get remote.origin.url)\r\n else\r\n echo -e \"[OT INSTALLER] files found with no git config\"\r\n echo -e \"[OT INSTALLER] closing out without touching things to not break anything\"\r\n exit 10\r\n fi\r\n fi\r\n\r\n if [ \"${ORIGIN}\" == \"https:\/\/github.com\/DJj123dj\/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\/DJj123dj\/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\/DJj123dj\/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", + "script": "#!\/bin\/bash\r\n# Open Ticket Installation Script (v4.0.0)\r\n# Inspired by: Node.js Installation Script\r\n# \u00a9 DJdj Development\r\n\r\necho -e \"[OT INSTALLER] installing dependencies. please wait...\"\r\napt update\r\napt install -y git curl\r\n\r\necho -e \"[OT INSTALLER] updating npm. please wait...\"\r\nnpm install npm@latest --location=global\r\n\r\nmkdir -p \/mnt\/server\r\ncd \/mnt\/server\r\n\r\nBRANCH=\"v4.0.0\"\r\n\r\nif [ \"$(ls -A \/mnt\/server)\" ]; then\r\n echo -e \"[OT INSTALLER] \/mnt\/server directory is not empty.\"\r\n if [ -d .git ]; then\r\n echo -e \"[OT INSTALLER] .git directory exists\"\r\n if [ -f .git\/config ]; then\r\n echo -e \"[OT INSTALLER] loading info from git config\"\r\n ORIGIN=$(git config --get remote.origin.url)\r\n else\r\n echo -e \"[OT INSTALLER] files found with no git config\"\r\n echo -e \"[OT INSTALLER] closing out without touching things to not break anything\"\r\n exit 10\r\n fi\r\n fi\r\n\r\n if [ \"${ORIGIN}\" == \"https:\/\/github.com\/open-discord-bots\/open-ticket.git\" ]; then\r\n echo \"pulling latest from github\"\r\n git pull\r\n fi\r\nelse\r\n echo -e \"[OT INSTALLER] \/mnt\/server is empty.\"\r\n echo -e \"[OT INSTALLER] cloning files into repo.\"\r\n if [ -z ${BRANCH} ]; then\r\n echo -e \"[OT INSTALLER] cloning default branch\"\r\n git clone https:\/\/github.com\/open-discord-bots\/open-ticket.git .\r\n else\r\n echo -e \"[OT INSTALLER] cloning ${BRANCH}'\"\r\n git clone --single-branch --branch ${BRANCH} https:\/\/github.com\/open-discord-bots\/open-ticket.git .\r\n fi\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing Open Ticket node.js packages.\"\r\nif [ -f \/mnt\/server\/package.json ]; then\r\n \/usr\/local\/bin\/npm install --omit=dev\r\nfi\r\n\r\necho -e \"[OT INSTALLER] installing custom node.js packages.\"\r\nif [[ ! -z ${NODE_PACKAGES} ]]; then\r\n \/usr\/local\/bin\/npm install ${NODE_PACKAGES}\r\nfi\r\n\r\necho -e \"[OT INSTALLER] install complete!\"\r\nexit 0", "container": "node:latest", "entrypoint": "bash" } diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index c36d673..2c9d972 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Contributing Guidelines Open Ticket Logo -[![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.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v4.0.0) [![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.0-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.0) [![Sponsor DJj123dj](https://img.shields.io/badge/sponsor-DJj123dj-ea4aaa?style=flat-square&logo=githubsponsors)](https://github.com/sponsors/DJj123dj) These are the Contributing Guidelines of Open Ticket!
Here you can find everything you need to know about contributing to Open Ticket.
@@ -36,7 +36,7 @@ Metadata can be found in the `_TRANSLATION` variable. #### Step 4: Uploading 1. When adding a new language, please mention @DJj123dj. He will add the code required for the language to work. 2. There are currently 3 ways of uploading translations: - - Create a pull request to the [__`dev` branch!__](https://github.com/DJj123dj/open-ticket/tree/dev) + - Create a pull request to the [__`dev` branch!__](https://github.com/open-discord-bots/open-ticket/tree/dev) - Create a ticket in our [discord server](https://discord.dj-dj.be)! - Send a DM to @DJj123dj on discord! 3. Now you'll need to wait until the next Open Ticket version for it to be added. diff --git a/.github/SECURITY.md b/.github/SECURITY.md index ab54d11..b092dfd 100644 --- a/.github/SECURITY.md +++ b/.github/SECURITY.md @@ -1,7 +1,7 @@ # Security Policy Open Ticket Logo -[![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.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v4.0.0) [![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.0-brightgreen.svg?style=flat-square)](https://github.com/open-discord-bots/open-ticket/releases/tag/v4.0.0) [![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!
Here you can find a list of all supported & deprecated versions of the bot.
diff --git a/README.md b/README.md index 82f5e2c..7f0e5a6 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@
Powered By
Open Ticket
Discord Invite Link -Open Ticket Version +Open Ticket Version Open Ticket Documentation -Open Ticket License +Open Ticket License Open Ticket Stars Sponsor DJj123dj

@@ -62,7 +62,7 @@ You're also able to customise every little aspect of the bot! From embeds to tra > Resources might not be accurate yet! *(because v4 is still in beta)*
> Open Ticket Tutorial > Open Ticket Docs -> Open Ticket Plugins +> Open Ticket Plugins ### ❤️ Sponsors A big thanks to all our sponsors! Without them, it wouldn't be possible to create this project! @@ -86,7 +86,7 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat ### ⏱️ Quick Setup -> 1. Download the latest version of Open Ticket on [Github](https://github.com/DJj123dj/open-ticket). +> 1. Download the latest version of Open Ticket on [Github](https://github.com/open-discord-bots/open-ticket). > 2. Make sure node.js & npm are installed using `node -v` (minimum `v18`). > 3. Install any required dependencies using `npm install`. > 4. Configure the bot in the `./config/` directory. @@ -103,48 +103,48 @@ A big thanks to all our sponsors! Without them, it wouldn't be possible to creat Example Panel 2 ## 🧩 Plugins -**Download all plugins in our [Official Plugin Repository](https://github.com/DJj123dj/open-discord-plugins)!**
+**Download all plugins in our [Official Plugin Repository](https://github.com/open-discord-bots/plugins)!**
> #### ⭐ Featured Plugins (Top 5 Most Used) -> **[`ot-sqlite-database`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-sqlite-database/), -> [`ot-migrate-v3`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-migrate-v3/), -> [`ot-reviews`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-reviews/), -> [`ot-feedback`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-feedback/), -> [`ot-tags`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-tags/)** +> **[`ot-sqlite-database`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-sqlite-database/), +> [`ot-migrate-v3`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-migrate-v3/), +> [`ot-reviews`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-reviews/), +> [`ot-feedback`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-feedback/), +> [`ot-tags`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-tags/)** ### 📦 Official *(made by DJdj Development)* |Name |Category |Description | |----------------------------------------------------------------------|----------------------------|-------------------------| -|[`example-plugin`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-plugin/) |📄 Example |This is just an example plugin for people that want to create their own plugin. | -|[`example-command`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/example-command/) |📄 Example |Sample custom command using the Open Discord system. | -|[`ot-jump-to-top`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-jump-to-top/) |📢 Command |Add a simple command to jump to the top of the ticket. | -|[`ot-kill-switch`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-kill-switch/) |📢 Command |Temporarily disable the ticket system using a kill switch. | -|[`ot-hosting-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-hosting-status/) |📢 Command |A simple command to send hosting status updates to a channel. | -|[`ot-shutdown`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-shutdown/) |📢 Command |A simple command to turn off the bot from a slash command (server & bot owner only). | -|[`ot-sqlite-database`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-sqlite-database/) |⚙️ Utility |With this plugin, the database will be an SQLite file. It's a must-have for large servers! | -|[`ot-no-slash-clear`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-no-slash-clear/) |⚙️ Utility |Disable the automatic removal of slash commands that aren't used by Open Ticket. | -|[`ot-migrate-v3`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-migrate-v3/) |⚙️ Utility |Use this plugin to migrate all tickets from Open Ticket v3 to v4. | -|[`ot-ticket-message-extras`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ticket-message-extras/) |🎨 Customisation |A plugin which adds a few little features to the ticket message. | -|[`ot-rename-keep-prefix`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |🎨 Customisation |Simple plugin to keep the channel prefix when using the /rename command. | -|[`ot-customise-buttons`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-customise-buttons/) |🎨 Customisation |Customise almost all built-in buttons. This includes the claim, reopen, close & delete buttons. | -|[`ot-ephemeral-messages`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ephemeral-messages/) |🎨 Customisation |Customise for every messages if it needs to be ephemeral or not. | -|[`ot-footers`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-footers/) |🎨 Customisation |A simple plugin to add footers in all Open Ticket embeds. | -|[`ot-alt-detector`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-alt-detector/) |💼 Management |Use the discord-alt-detector npm package by DJdj Development in your ticket bot. | -|[`ot-embeds`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-embeds/) |💼 Management |Create custom premade embeds in the config or use the command to create one from scratch. | -|[`ot-move-actions`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-move-actions/) |💼 Management |Automatically unclaim/unpin a ticket when it's moved using `/move`. | -|[`ot-reviews`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-reviews/) |💼 Management |Review system for Open Ticket! It is very customisable and has lots of features. | -|[`ot-tags`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-tags/) |💼 Management |Use tags to quickly reply with a pre-existing text. | -|[`ot-better-status`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-better-status/) |🤖 Client |An advanced status plugin to rotate between states. It also allows for the use of variables. | +|[`example-plugin`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/example-plugin/) |📄 Example |This is just an example plugin for people that want to create their own plugin. | +|[`example-command`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/example-command/) |📄 Example |Sample custom command using the Open Discord system. | +|[`ot-jump-to-top`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-jump-to-top/) |📢 Command |Add a simple command to jump to the top of the ticket. | +|[`ot-kill-switch`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-kill-switch/) |📢 Command |Temporarily disable the ticket system using a kill switch. | +|[`ot-hosting-status`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-hosting-status/) |📢 Command |A simple command to send hosting status updates to a channel. | +|[`ot-shutdown`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-shutdown/) |📢 Command |A simple command to turn off the bot from a slash command (server & bot owner only). | +|[`ot-sqlite-database`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-sqlite-database/) |⚙️ Utility |With this plugin, the database will be an SQLite file. It's a must-have for large servers! | +|[`ot-no-slash-clear`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-no-slash-clear/) |⚙️ Utility |Disable the automatic removal of slash commands that aren't used by Open Ticket. | +|[`ot-migrate-v3`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-migrate-v3/) |⚙️ Utility |Use this plugin to migrate all tickets from Open Ticket v3 to v4. | +|[`ot-ticket-message-extras`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-ticket-message-extras/) |🎨 Customisation |A plugin which adds a few little features to the ticket message. | +|[`ot-rename-keep-prefix`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-rename-keep-prefix/) |🎨 Customisation |Simple plugin to keep the channel prefix when using the /rename command. | +|[`ot-customise-buttons`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-customise-buttons/) |🎨 Customisation |Customise almost all built-in buttons. This includes the claim, reopen, close & delete buttons. | +|[`ot-ephemeral-messages`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-ephemeral-messages/) |🎨 Customisation |Customise for every messages if it needs to be ephemeral or not. | +|[`ot-footers`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-footers/) |🎨 Customisation |A simple plugin to add footers in all Open Ticket embeds. | +|[`ot-alt-detector`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-alt-detector/) |💼 Management |Use the discord-alt-detector npm package by DJdj Development in your ticket bot. | +|[`ot-embeds`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-embeds/) |💼 Management |Create custom premade embeds in the config or use the command to create one from scratch. | +|[`ot-move-actions`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-move-actions/) |💼 Management |Automatically unclaim/unpin a ticket when it's moved using `/move`. | +|[`ot-reviews`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-reviews/) |💼 Management |Review system for Open Ticket! It is very customisable and has lots of features. | +|[`ot-tags`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-tags/) |💼 Management |Use tags to quickly reply with a pre-existing text. | +|[`ot-better-status`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-better-status/) |🤖 Client |An advanced status plugin to rotate between states. It also allows for the use of variables. | ### ✅ Verified *(made by community)* |Name |Author |Category |Description | |---------------------------------------------------------------------|----------------------------|----------------------------|-------------------------| -|[`ot-config-reload`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-config-reload/) |guillee.3 |⚙️ Utility |This plugin adds a new command that allows reloading the Open Ticket config files without the need for a restart. | -|[`ot-ticket-forms`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-ticket-forms/) |guillee.3 |💼 Management |An advanced forms plugin for Open Ticket. | -|[`ot-feedback`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-feedback/) |an_developer |💼 Management |A plugin to gather feedback of your support service. | -|[`ot-assign-role`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-assign-role/) |rapid.fast |💼 Management |This plugin assigns a predefined role to a user upon creating a ticket. | -|[`ot-volume-warning`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-volume-warning/) |guillee.3 |💼 Management |Alerts ticket creators when too many tickets are open, indicating possible response delays. | -|[`od-reminders`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/od-reminders/) |guillee.3 |💼 Management |Set reminders that will be sent to a channel every specified time. | -|[`ot-translate-cmds`](https://github.com/DJj123dj/open-discord-plugins/tree/main/open-ticket/ot-translate-cmds/) |guillee.3 |🤖 Client |Translate all built-in command names, descriptions & options. | +|[`ot-config-reload`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-config-reload/) |guillee.3 |⚙️ Utility |This plugin adds a new command that allows reloading the Open Ticket config files without the need for a restart. | +|[`ot-ticket-forms`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-ticket-forms/) |guillee.3 |💼 Management |An advanced forms plugin for Open Ticket. | +|[`ot-feedback`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-feedback/) |an_developer |💼 Management |A plugin to gather feedback of your support service. | +|[`ot-assign-role`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-assign-role/) |rapid.fast |💼 Management |This plugin assigns a predefined role to a user upon creating a ticket. | +|[`ot-volume-warning`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-volume-warning/) |guillee.3 |💼 Management |Alerts ticket creators when too many tickets are open, indicating possible response delays. | +|[`od-reminders`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/od-reminders/) |guillee.3 |💼 Management |Set reminders that will be sent to a channel every specified time. | +|[`ot-translate-cmds`](https://github.com/open-discord-bots/plugins/tree/main/open-ticket/ot-translate-cmds/) |guillee.3 |🤖 Client |Translate all built-in command names, descriptions & options. | ### 📢 Categories - **📄 Example** - These plugins serve as an example or starting template. @@ -212,11 +212,11 @@ This is the main team working on Open Ticket. Don't forget to check their profil ## ⭐️ Star History Please help us grow by giving a star! It would help us a lot! - + - - - Star History Chart + + + Star History Chart diff --git a/package.json b/package.json index dbede6b..b8a164b 100644 --- a/package.json +++ b/package.json @@ -31,10 +31,10 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/DJj123dj/open-ticket.git" + "url": "git+https://github.com/open-discord-bots/open-ticket.git" }, "bugs": { - "url": "https://github.com/DJj123dj/open-ticket/issues", + "url": "https://github.com/open-discord-bots/open-ticket/issues", "email": "support@dj-dj.be" }, "homepage": "https://openticket.dj-dj.be", diff --git a/src/data/framework/liveStatusLoader.ts b/src/data/framework/liveStatusLoader.ts index 5aaaa74..647f63e 100644 --- a/src/data/framework/liveStatusLoader.ts +++ b/src/data/framework/liveStatusLoader.ts @@ -2,5 +2,5 @@ import {opendiscord, api, utilities} from "../../index" export const loadAllLiveStatusSources = async () => { //DEFAULT DJDJ DEV - opendiscord.livestatus.add(new api.ODLiveStatusUrlSource("opendiscord:default-djdj-dev","https://raw.githubusercontent.com/DJj123dj/open-ticket/refs/heads/dev/src/livestatus.json")) + opendiscord.livestatus.add(new api.ODLiveStatusUrlSource("opendiscord:default-djdj-dev","https://raw.githubusercontent.com/open-discord-bots/open-ticket/refs/heads/dev/src/livestatus.json")) } \ No newline at end of file