Open Ticket v4.2: Config Update (JSONC)
This commit is contained in:
@@ -32,9 +32,6 @@ export interface ODTicketOptionIdMappings extends ODOptionIdConstraint {
|
||||
"opendiscord:channel-prefix":ODOptionData<string>,
|
||||
"opendiscord:channel-suffix":ODOptionData<"user-name"|"user-nickname"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed">,
|
||||
"opendiscord:channel-category":ODOptionData<string>,
|
||||
"opendiscord:channel-category-closed":ODOptionData<string>,
|
||||
"opendiscord:channel-category-backup":ODOptionData<string>,
|
||||
"opendiscord:channel-categories-claimed":ODOptionData<{user:string,category:string}[]>,
|
||||
"opendiscord:channel-topic":ODOptionData<string>,
|
||||
|
||||
"opendiscord:dm-message-enabled":ODOptionData<boolean>,
|
||||
|
||||
+124
-65
@@ -31,7 +31,7 @@ interface ODQuickSetupVariables {
|
||||
globalUserLimit?:number|null,
|
||||
removeParticipantsOnClose?:boolean,
|
||||
ticketMessageLayout?:"embed"|"text"|null,
|
||||
emojiStyle?:api.ODGeneralJsonConfig_System["emojiStyle"],
|
||||
emojiStyle?:api.ODGeneralJsonConfig_TicketSystem["emojiStyle"],
|
||||
panelName?:string,
|
||||
panelDescription?:string,
|
||||
panelDropdown?:boolean,
|
||||
@@ -234,7 +234,7 @@ async function renderQuickSetupBotToken(backFn:() => api.ODPromiseVoid){
|
||||
cli.renderHeader(headerOpts,"⏱️ Open Ticket Quick Setup: Bot Token")
|
||||
|
||||
terminal.bold.blue(stepCount(2)+"Please insert the token of your discord bot.\n")
|
||||
terminal.gray("This is used to configure the bot and is then stored securely in the './config/general.json' file.\n\n> ")
|
||||
terminal.gray("This is used to configure the bot and is then stored securely in the './config/general.jsonc' file.\n\n> ")
|
||||
|
||||
const answer = await terminal.inputField({
|
||||
style:terminal.white,
|
||||
@@ -1203,11 +1203,7 @@ async function saveQuickSetupConfig(){
|
||||
//GENERAL CONFIG
|
||||
const generalConfig = opendiscord.configs.get("opendiscord:general")
|
||||
const generalConfigData: api.ODGeneralJsonConfig_GeneralData = {
|
||||
_INFO:{
|
||||
support:"https://otdocs.dj-dj.be",
|
||||
discord:"https://discord.dj-dj.be",
|
||||
version:"open-ticket-"+opendiscord.versions.get("opendiscord:version").toString()
|
||||
},
|
||||
_CONFIG_VERSION:"open-ticket-"+opendiscord.versions.get("opendiscord:version").toString(),
|
||||
|
||||
token:quickSetupStorage.client?.token ?? "<unknown-token>",
|
||||
tokenFromENV:false,
|
||||
@@ -1222,8 +1218,29 @@ async function saveQuickSetupConfig(){
|
||||
textCommands:quickSetupStorage.textCommands ?? false,
|
||||
|
||||
status:quickSetupStorage.status ?? {enabled:false,mode:"online",type:"custom",text:"",state:""},
|
||||
logs:{
|
||||
enabled:(typeof quickSetupStorage.logChannel == "string"),
|
||||
channel:quickSetupStorage.logChannel ?? "",
|
||||
logMessages:{
|
||||
creation:{dm:true,logs:true},
|
||||
closing:{dm:true,logs:true},
|
||||
deleting:{dm:true,logs:true},
|
||||
reopening:{dm:false,logs:true},
|
||||
claiming:{dm:false,logs:true},
|
||||
pinning:{dm:false,logs:true},
|
||||
adding:{dm:false,logs:true},
|
||||
removing:{dm:false,logs:true},
|
||||
renaming:{dm:false,logs:true},
|
||||
moving:{dm:true,logs:true},
|
||||
blacklisting:{dm:true,logs:true},
|
||||
transferring:{dm:true,logs:true},
|
||||
topicChange:{dm:false,logs:true},
|
||||
priorityChange:{dm:false,logs:true},
|
||||
reactionRole:{dm:false,logs:true}
|
||||
}
|
||||
},
|
||||
|
||||
system:{
|
||||
ticketSystem:{
|
||||
preferSlashOverText:quickSetupStorage.slashCommands ?? false,
|
||||
sendErrorOnUnknownCommand:true,
|
||||
questionFieldsInCodeBlock:true,
|
||||
@@ -1234,10 +1251,11 @@ async function saveQuickSetupConfig(){
|
||||
alwaysShowReason:false,
|
||||
emojiStyle:quickSetupStorage.emojiStyle ?? "before",
|
||||
pinEmoji:"📌",
|
||||
closeEmoji:"🔒",
|
||||
|
||||
replyOnTicketCreation:false,
|
||||
replyOnTicketCreation:true,
|
||||
replyOnReactionRole:true,
|
||||
askPriorityOnTicketCreation:false,
|
||||
askPriorityOnTicketCreation:true,
|
||||
removeParticipantsOnClose:quickSetupStorage.removeParticipantsOnClose ?? false,
|
||||
disableAutocloseAfterReopen:true,
|
||||
autodeleteRequiresClosedTicket:true,
|
||||
@@ -1245,7 +1263,7 @@ async function saveQuickSetupConfig(){
|
||||
allowCloseBeforeMessage:false,
|
||||
allowCloseBeforeAdminMessage:true,
|
||||
useTranslatedConfigChecker:true,
|
||||
pinFirstTicketMessage:false,
|
||||
pinFirstTicketMessage:true,
|
||||
|
||||
enableTicketClaimButtons:true,
|
||||
enableTicketCloseButtons:true,
|
||||
@@ -1253,11 +1271,7 @@ async function saveQuickSetupConfig(){
|
||||
enableTicketDeleteButtons:true,
|
||||
enableTicketActionWithReason:true,
|
||||
enableDeleteWithoutTranscript:true,
|
||||
|
||||
logs:{
|
||||
enabled:(typeof quickSetupStorage.logChannel == "string"),
|
||||
channel:quickSetupStorage.logChannel ?? ""
|
||||
},
|
||||
enableCreateTicketForOtherUser:true,
|
||||
|
||||
limits:{
|
||||
enabled:(typeof quickSetupStorage.globalUserLimit == "number"),
|
||||
@@ -1276,49 +1290,41 @@ async function saveQuickSetupConfig(){
|
||||
showCreator:false,
|
||||
showParticipants:false
|
||||
},
|
||||
|
||||
permissions:{
|
||||
help:"everyone",
|
||||
panel:"admin",
|
||||
ticket:"everyone",
|
||||
close:"admin",
|
||||
delete:"admin",
|
||||
reopen:"admin",
|
||||
claim:"admin",
|
||||
unclaim:"admin",
|
||||
pin:"admin",
|
||||
unpin:"admin",
|
||||
move:"admin",
|
||||
rename:"admin",
|
||||
add:"admin",
|
||||
remove:"admin",
|
||||
blacklist:"admin",
|
||||
stats:"everyone",
|
||||
clear:"admin",
|
||||
autoclose:"admin",
|
||||
autodelete:"admin",
|
||||
transfer:"admin",
|
||||
topic:"admin",
|
||||
priority:"admin",
|
||||
|
||||
closedCategory:{
|
||||
enabled:false,
|
||||
categoryId:""
|
||||
},
|
||||
|
||||
messages:{
|
||||
creation:{dm:true,logs:true},
|
||||
closing:{dm:true,logs:true},
|
||||
deleting:{dm:true,logs:true},
|
||||
reopening:{dm:false,logs:true},
|
||||
claiming:{dm:false,logs:true},
|
||||
pinning:{dm:false,logs:true},
|
||||
adding:{dm:false,logs:true},
|
||||
removing:{dm:false,logs:true},
|
||||
renaming:{dm:false,logs:true},
|
||||
moving:{dm:true,logs:true},
|
||||
blacklisting:{dm:true,logs:true},
|
||||
transferring:{dm:true,logs:true},
|
||||
topicChange:{dm:false,logs:true},
|
||||
priorityChange:{dm:false,logs:true},
|
||||
reactionRole:{dm:false,logs:true}
|
||||
}
|
||||
backupCategory:{
|
||||
enabled:false,
|
||||
categoryId:""
|
||||
},
|
||||
claimedCategories:[],
|
||||
},
|
||||
permissions:{
|
||||
help:"everyone",
|
||||
panel:"admin",
|
||||
ticket:"everyone",
|
||||
close:"admin",
|
||||
delete:"admin",
|
||||
reopen:"admin",
|
||||
claim:"admin",
|
||||
unclaim:"admin",
|
||||
pin:"admin",
|
||||
unpin:"admin",
|
||||
move:"admin",
|
||||
rename:"admin",
|
||||
add:"admin",
|
||||
remove:"admin",
|
||||
blacklist:"admin",
|
||||
stats:"everyone",
|
||||
clear:"admin",
|
||||
autoclose:"admin",
|
||||
autodelete:"admin",
|
||||
transfer:"admin",
|
||||
topic:"admin",
|
||||
priority:"admin",
|
||||
transcripts:"admin"
|
||||
}
|
||||
}
|
||||
generalConfig.data = generalConfigData
|
||||
@@ -1330,10 +1336,11 @@ async function saveQuickSetupConfig(){
|
||||
{
|
||||
id:"example-question-1",
|
||||
name:"Example Question 1",
|
||||
description:"This is a short text input question.",
|
||||
type:"short",
|
||||
|
||||
required:true,
|
||||
placeholder:"Insert your short answer here!",
|
||||
|
||||
placeholder:"Insert answer...",
|
||||
length:{
|
||||
enabled:false,
|
||||
min:0,
|
||||
@@ -1343,15 +1350,69 @@ async function saveQuickSetupConfig(){
|
||||
{
|
||||
id:"example-question-2",
|
||||
name:"Example Question 2",
|
||||
description:"This is a paragraph text input question.",
|
||||
type:"paragraph",
|
||||
|
||||
required:false,
|
||||
placeholder:"Insert your long answer here!",
|
||||
|
||||
placeholder:"Insert answer...",
|
||||
length:{
|
||||
enabled:false,
|
||||
min:0,
|
||||
max:1000
|
||||
}
|
||||
},
|
||||
{
|
||||
id:"example-question-3",
|
||||
name:"Example Question 3",
|
||||
description:"This is a dropdown question.",
|
||||
type:"dropdown",
|
||||
required:false,
|
||||
|
||||
placeholder:"Choose your answer...",
|
||||
choices:[
|
||||
{title:"Choice A",description:"Apple",emoji:"🍎"},
|
||||
{title:"Choice B",description:"Banana",emoji:"🍌"},
|
||||
{title:"Choice C",description:"Orange",emoji:"🍊"},
|
||||
{title:"Choice D",description:"Kiwi",emoji:"🥝"}
|
||||
]
|
||||
},
|
||||
{
|
||||
id:"example-question-4",
|
||||
name:"Example Question 4",
|
||||
description:"This is a radio select question.",
|
||||
type:"radio-select",
|
||||
required:true,
|
||||
|
||||
choices:[
|
||||
{title:"Choice A",description:"Up",selectedByDefault:false},
|
||||
{title:"Choice B",description:"Down",selectedByDefault:false},
|
||||
{title:"Choice C",description:"Left",selectedByDefault:false},
|
||||
{title:"Choice D",description:"Right",selectedByDefault:false}
|
||||
]
|
||||
},
|
||||
{
|
||||
id:"example-question-5",
|
||||
name:"Example Question 5",
|
||||
description:"This is a checkbox select question.",
|
||||
type:"checkbox-select",
|
||||
required:true,
|
||||
|
||||
limits:{
|
||||
enabled:false,
|
||||
min:0,
|
||||
max:10
|
||||
},
|
||||
choices:[
|
||||
{title:"Choice A",description:"Happiness",selectedByDefault:false},
|
||||
{title:"Choice B",description:"Anger",selectedByDefault:false},
|
||||
{title:"Choice C",description:"Sadness",selectedByDefault:false},
|
||||
{title:"Choice D",description:"Fear",selectedByDefault:false}
|
||||
]
|
||||
},
|
||||
{
|
||||
id:"example-text-display",
|
||||
type:"text-display",
|
||||
textContents:"This is a text display. It isn't a question, but allows you to display a text, explaination or details."
|
||||
}
|
||||
]
|
||||
questionsConfig.data = questionsConfigData
|
||||
@@ -1384,9 +1445,6 @@ async function saveQuickSetupConfig(){
|
||||
prefix:ticket.channelPrefix,
|
||||
suffix:ticket.channelSuffix,
|
||||
category:quickSetupStorage.ticketCategory ?? "",
|
||||
closedCategory:"",
|
||||
backupCategory:"",
|
||||
claimedCategory:[],
|
||||
topic:ticket.description
|
||||
},
|
||||
|
||||
@@ -1482,6 +1540,7 @@ async function saveQuickSetupConfig(){
|
||||
},
|
||||
settings:{
|
||||
dropdownPlaceholder:"Open a ticket",
|
||||
maximumButtonsPerRow:5,
|
||||
|
||||
enableMaxTicketsWarningInText:(quickSetupStorage.panelLayout == "text" && (quickSetupStorage.panelMaxTicketsWarning ?? false)),
|
||||
enableMaxTicketsWarningInEmbed:(quickSetupStorage.panelLayout == "embed" && (quickSetupStorage.panelMaxTicketsWarning ?? false)),
|
||||
|
||||
+2
-2
@@ -58,7 +58,7 @@ export class ODOpenTicketMain extends api.ODMain {
|
||||
priorities: api.ODMappedPriorityManager
|
||||
|
||||
constructor(){
|
||||
const version = api.ODVersion.fromString("opendiscord:version","v4.1.3")
|
||||
const version = api.ODVersion.fromString("opendiscord:version","v4.2.0")
|
||||
const debugfile = new api.ODDebugFileManager("./","otdebug.txt",5000,version)
|
||||
const console = new api.ODConsoleManager(100,debugfile)
|
||||
const debug = new api.ODDebugger(console)
|
||||
@@ -108,7 +108,7 @@ export class ODOpenTicketMain extends api.ODMain {
|
||||
},"openticket")
|
||||
|
||||
this.livestatus.useMain(this)
|
||||
this.versions.add(api.ODVersion.fromString("opendiscord:version","v4.1.3"))
|
||||
this.versions.add(api.ODVersion.fromString("opendiscord:version","v4.2.0"))
|
||||
this.versions.add(api.ODVersion.fromString("opendiscord:transcripts","v2.1.0"))
|
||||
|
||||
//OPEN TICKET
|
||||
|
||||
+196
-95
@@ -10,20 +10,20 @@ import { ODRoleUpdateMode } from "../api/role.js"
|
||||
* It's used to generate typescript declarations for this class.
|
||||
*/
|
||||
export interface ODConfigManagerIdMappings extends api.ODConfigManagerIdConstraint {
|
||||
"opendiscord:general":ODGeneralJsonConfig,
|
||||
"opendiscord:questions":ODQuestionsJsonConfig,
|
||||
"opendiscord:options":ODOptionsJsonConfig,
|
||||
"opendiscord:panels":ODPanelsJsonConfig,
|
||||
"opendiscord:transcripts":ODTranscriptsJsonConfig
|
||||
"opendiscord:general":ODGeneralJsonCommentsConfig,
|
||||
"opendiscord:questions":ODQuestionsJsonCommentsConfig,
|
||||
"opendiscord:options":ODOptionsJsonCommentsConfig,
|
||||
"opendiscord:panels":ODPanelsJsonCommentsConfig,
|
||||
"opendiscord:transcripts":ODTranscriptsJsonCommentsConfig
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// CONFIG STRUCTURES, VALUES & TYPES
|
||||
// --> general.json
|
||||
// --> general.jsonc
|
||||
///////////////////////////////////////
|
||||
|
||||
/**## ODGeneralJsonConfig_Status `interface`
|
||||
* This interface is an object which has all properties for the status object in the `general.json` config!
|
||||
* This interface is an object which has all properties for the status object in the `general.jsonc` config!
|
||||
*/
|
||||
export interface ODGeneralJsonConfig_Status {
|
||||
/**Is the status enabled? */
|
||||
@@ -39,7 +39,7 @@ export interface ODGeneralJsonConfig_Status {
|
||||
}
|
||||
|
||||
/**## ODGeneralJsonConfig_MessageSettings `interface`
|
||||
* This interface is an object which has all properties for the "system"."messages".... object in the `general.json` config!
|
||||
* This interface is an object which has all properties for the "system"."messages".... object in the `general.jsonc` config!
|
||||
*/
|
||||
export interface ODGeneralJsonConfig_MessageSettings {
|
||||
/**Enable sending DM logs to the ticket creator for this action. */
|
||||
@@ -49,22 +49,10 @@ export interface ODGeneralJsonConfig_MessageSettings {
|
||||
}
|
||||
|
||||
/**## ODGeneralJsonConfig_CmdPermissionSettingsType `type`
|
||||
* This type is a collection of command permission settings for the "system"."permissions".... object in the `general.json` config!
|
||||
* This type is a collection of command permission settings for the "system"."permissions".... object in the `general.jsonc` config!
|
||||
*/
|
||||
export type ODGeneralJsonConfig_CmdPermissionSettingsType = "admin"|"everyone"|"none"|string
|
||||
|
||||
/**## ODGeneralJsonConfig_Info `interface`
|
||||
* This object contains a few URLs and metadata for the config.
|
||||
*/
|
||||
export interface ODGeneralJsonConfig_Info {
|
||||
/**A link to the Open Ticket documentation. */
|
||||
support:string,
|
||||
/**A link to the DJdj Development discord server. */
|
||||
discord:string,
|
||||
/**The version of Open Ticket this config is compatible with. */
|
||||
version:string
|
||||
}
|
||||
|
||||
/**## ODGeneralJsonConfig_SystemLogs `interface`
|
||||
* All settings related to the log channel.
|
||||
*/
|
||||
@@ -72,7 +60,9 @@ export interface ODGeneralJsonConfig_SystemLogs {
|
||||
/**Enable logging. Individual actions should still be added via the `"system"."messages"..."logs"` */
|
||||
enabled:boolean,
|
||||
/**The channel to send logs to. */
|
||||
channel:string
|
||||
channel:string,
|
||||
/**Configure dm & log messages for all Open Ticket commands & actions. */
|
||||
logMessages:ODGeneralJsonConfig_LogMessages
|
||||
}
|
||||
|
||||
/**## ODGeneralJsonConfig_SystemLimits `interface`
|
||||
@@ -137,12 +127,13 @@ export interface ODGeneralJsonConfig_SystemPermissions {
|
||||
transfer:ODGeneralJsonConfig_CmdPermissionSettingsType,
|
||||
topic:ODGeneralJsonConfig_CmdPermissionSettingsType,
|
||||
priority:ODGeneralJsonConfig_CmdPermissionSettingsType,
|
||||
transcripts:ODGeneralJsonConfig_CmdPermissionSettingsType,
|
||||
}
|
||||
|
||||
/**## ODGeneralJsonConfig_SystemMessages `interface`
|
||||
/**## ODGeneralJsonConfig_LogMessages `interface`
|
||||
* Configure dm & log messages for all Open Ticket commands & actions.
|
||||
*/
|
||||
export interface ODGeneralJsonConfig_SystemMessages {
|
||||
export interface ODGeneralJsonConfig_LogMessages {
|
||||
creation:ODGeneralJsonConfig_MessageSettings,
|
||||
closing:ODGeneralJsonConfig_MessageSettings,
|
||||
deleting:ODGeneralJsonConfig_MessageSettings,
|
||||
@@ -160,10 +151,10 @@ export interface ODGeneralJsonConfig_SystemMessages {
|
||||
reactionRole:ODGeneralJsonConfig_MessageSettings,
|
||||
}
|
||||
|
||||
/**## ODGeneralJsonConfig_System `interface`
|
||||
/**## ODGeneralJsonConfig_TicketSystem `interface`
|
||||
* All settings related to the ticket system.
|
||||
*/
|
||||
export interface ODGeneralJsonConfig_System {
|
||||
export interface ODGeneralJsonConfig_TicketSystem {
|
||||
/**Prefer slash-commands over text-commands when displaying them in menu's and messages. */
|
||||
preferSlashOverText:boolean,
|
||||
/**Reply with "unknown command" when the prefix is used without a valid command. */
|
||||
@@ -184,6 +175,8 @@ export interface ODGeneralJsonConfig_System {
|
||||
emojiStyle:"before"|"after"|"double"|"disabled",
|
||||
/**The emoji used when pinning tickets. This is '📌' by default. */
|
||||
pinEmoji:string,
|
||||
/**The emoji used when closing tickets. This is '🔒' by default. */
|
||||
closeEmoji:string,
|
||||
|
||||
/**Reply with an ephemeral message when a ticket is created. */
|
||||
replyOnTicketCreation:boolean,
|
||||
@@ -220,9 +213,8 @@ export interface ODGeneralJsonConfig_System {
|
||||
enableTicketActionWithReason:boolean,
|
||||
/**Enable/disable the delete without transcript feature (button & /delete command). */
|
||||
enableDeleteWithoutTranscript:boolean,
|
||||
|
||||
/**All settings related to the log channel. */
|
||||
logs:ODGeneralJsonConfig_SystemLogs,
|
||||
/**Enable/disable creating tickets for other users with /ticket <user>. (ADMIN ONLY) */
|
||||
enableCreateTicketForOtherUser:boolean,
|
||||
|
||||
/**All settings related to global ticket limits. */
|
||||
limits:ODGeneralJsonConfig_SystemLimits,
|
||||
@@ -230,19 +222,31 @@ export interface ODGeneralJsonConfig_System {
|
||||
/**All global channel topic settings. */
|
||||
channelTopic:ODGeneralJsonConfig_SystemChannelTopic,
|
||||
|
||||
/**Configure permissions for all Open Ticket commands & actions. */
|
||||
permissions:ODGeneralJsonConfig_SystemPermissions,
|
||||
|
||||
/**Configure dm & log messages for all Open Ticket commands & actions. */
|
||||
messages:ODGeneralJsonConfig_SystemMessages
|
||||
/**Move closed tickets to this channel category. */
|
||||
closedCategory:{
|
||||
enabled:boolean
|
||||
categoryId:string
|
||||
},
|
||||
/**Create tickets in this channel category when the original category is full (max 50 channels). */
|
||||
backupCategory:{
|
||||
enabled:boolean
|
||||
categoryId:string
|
||||
},
|
||||
/**Move claimed tickets to the matching channel category of the user that claimed the ticket. */
|
||||
claimedCategories:{
|
||||
/**The user who claimed the ticket. */
|
||||
user:string,
|
||||
/**The category to move the ticket to. */
|
||||
category:string
|
||||
}[],
|
||||
}
|
||||
|
||||
/**## ODGeneralJsonConfig_GeneralData `interface`
|
||||
* All contents of the `general.json` config file.
|
||||
* All contents of the `general.jsonc` config file.
|
||||
*/
|
||||
export interface ODGeneralJsonConfig_GeneralData {
|
||||
/**This object contains a few URLs and metadata for the config. */
|
||||
_INFO:ODGeneralJsonConfig_Info,
|
||||
_CONFIG_VERSION:string,
|
||||
|
||||
/**The token of the bot. (Empty when using `tokenFromENV`) */
|
||||
token:string,
|
||||
@@ -267,18 +271,24 @@ export interface ODGeneralJsonConfig_GeneralData {
|
||||
|
||||
/**All settings related to the status of the bot. */
|
||||
status:ODGeneralJsonConfig_Status,
|
||||
|
||||
|
||||
/**All settings related to the ticket system. */
|
||||
system:ODGeneralJsonConfig_System
|
||||
ticketSystem:ODGeneralJsonConfig_TicketSystem,
|
||||
|
||||
/**Configure permissions for all Open Ticket commands & actions. */
|
||||
permissions:ODGeneralJsonConfig_SystemPermissions,
|
||||
|
||||
/**All settings related to the log channel. */
|
||||
logs:ODGeneralJsonConfig_SystemLogs,
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
// CONFIG STRUCTURES, VALUES & TYPES
|
||||
// --> options.json
|
||||
// --> options.jsonc
|
||||
///////////////////////////////////////
|
||||
|
||||
/**## ODOptionsJsonConfig_BaseOption `interface`
|
||||
* This interface is an object which has all basic properties for options in the `options.json` config!
|
||||
* The basic properties for options in the `options.jsonc` config!
|
||||
*/
|
||||
export interface ODOptionsJsonConfig_BaseOption {
|
||||
/**The id of this option. */
|
||||
@@ -288,7 +298,7 @@ export interface ODOptionsJsonConfig_BaseOption {
|
||||
/**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",
|
||||
type:"ticket"|"website"|"role"|"sub-panel",
|
||||
/**All settings related to the button for the 3 option types. */
|
||||
button:{
|
||||
/**The emoji of the button. (can also be empty) */
|
||||
@@ -299,7 +309,7 @@ export interface ODOptionsJsonConfig_BaseOption {
|
||||
}
|
||||
|
||||
/**## ODOptionsJsonConfig_OptionButtonSettings `interface`
|
||||
* This interface is an object which has all button settings for ticket & reaction role options in the `options.json` config!
|
||||
* The button settings for ticket, sub-panel & reaction role options in the `options.jsonc` config!
|
||||
*/
|
||||
export interface ODOptionsJsonConfig_OptionButtonSettings {
|
||||
/**The emoji of the button. (can also be empty) */
|
||||
@@ -311,7 +321,7 @@ export interface ODOptionsJsonConfig_OptionButtonSettings {
|
||||
}
|
||||
|
||||
/**## ODOptionsJsonConfig_TicketOptionEmbedSettings `interface`
|
||||
* This interface is an object which has all message embed settings for ticket options in the `options.json` config!
|
||||
* The message embed settings for ticket options in the `options.jsonc` config!
|
||||
*/
|
||||
export interface ODOptionsJsonConfig_TicketOptionEmbedSettings {
|
||||
/**Is this embed enabled? */
|
||||
@@ -340,7 +350,7 @@ export interface ODOptionsJsonConfig_TicketOptionEmbedSettings {
|
||||
}
|
||||
|
||||
/**## ODOptionsJsonConfig_TicketOptionPingSettings `interface`
|
||||
* This interface is an object which has all message ping settings for ticket options in the `options.json` config!
|
||||
* The message ping settings for ticket options in the `options.jsonc` config!
|
||||
*/
|
||||
export interface ODOptionsJsonConfig_TicketOptionPingSettings {
|
||||
/**Ping `@here`. */
|
||||
@@ -361,23 +371,12 @@ export interface ODOptionsJsonConfig_TicketOptionChannelSettings {
|
||||
suffix:"user-name"|"user-nickname"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed",
|
||||
/**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,
|
||||
/**A list of discord category ids to move this ticket to when claimed by a specific user. */
|
||||
claimedCategory:{
|
||||
/**The user which claimed the ticket. */
|
||||
user:string,
|
||||
/**The category to move the ticket to when claimed by this user. */
|
||||
category:string
|
||||
}[],
|
||||
/**The channel topic shown at the top of the channel in discord. */
|
||||
topic:string
|
||||
}
|
||||
|
||||
/**## ODOptionsJsonConfig_TicketOption `interface`
|
||||
* This interface is an object which has all ticket properties for options in the `options.json` config!
|
||||
* All properties for ticket options in the `options.jsonc` config!
|
||||
*/
|
||||
export interface ODOptionsJsonConfig_TicketOption extends ODOptionsJsonConfig_BaseOption {
|
||||
type:"ticket",
|
||||
@@ -388,7 +387,7 @@ export interface ODOptionsJsonConfig_TicketOption extends ODOptionsJsonConfig_Ba
|
||||
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. */
|
||||
/**A list of valid question ids from the `questions.jsonc` config. */
|
||||
questions:string[],
|
||||
/**All settings related to the ticket channel itself. */
|
||||
channel:ODOptionsJsonConfig_TicketOptionChannelSettings,
|
||||
@@ -460,7 +459,7 @@ export interface ODOptionsJsonConfig_TicketOption extends ODOptionsJsonConfig_Ba
|
||||
}
|
||||
|
||||
/**## ODOptionsJsonConfig_WebsiteOption `interface`
|
||||
* This interface is an object which has all website properties for options in the `options.json` config!
|
||||
* All properties for website options in the `options.jsonc` config!
|
||||
*/
|
||||
export interface ODOptionsJsonConfig_WebsiteOption extends ODOptionsJsonConfig_BaseOption {
|
||||
type:"website",
|
||||
@@ -469,7 +468,7 @@ export interface ODOptionsJsonConfig_WebsiteOption extends ODOptionsJsonConfig_B
|
||||
}
|
||||
|
||||
/**## ODOptionsJsonConfig_RoleOption `interface`
|
||||
* This interface is an object which has all reaction role properties for options in the `options.json` config!
|
||||
* All properties for reaction-role options in the `options.jsonc` config!
|
||||
*/
|
||||
export interface ODOptionsJsonConfig_RoleOption extends ODOptionsJsonConfig_BaseOption {
|
||||
type:"role",
|
||||
@@ -484,18 +483,28 @@ export interface ODOptionsJsonConfig_RoleOption extends ODOptionsJsonConfig_Base
|
||||
addOnMemberJoin:boolean
|
||||
}
|
||||
|
||||
/**## ODOptionsJsonConfig_OptionsData `type`
|
||||
* All contents of the `options.json` config file.
|
||||
/**## ODOptionsJsonConfig_SubPanelOption `interface`
|
||||
* All properties for sub-panel options in the `options.jsonc` config!
|
||||
*/
|
||||
export type ODOptionsJsonConfig_OptionsData = (ODOptionsJsonConfig_TicketOption|ODOptionsJsonConfig_WebsiteOption|ODOptionsJsonConfig_RoleOption)[]
|
||||
export interface ODOptionsJsonConfig_SubPanelOption extends ODOptionsJsonConfig_BaseOption {
|
||||
type:"sub-panel",
|
||||
button:ODOptionsJsonConfig_OptionButtonSettings,
|
||||
/**The panel ID of the sub-panel to show when the button is clicked. */
|
||||
subPanelId:string
|
||||
}
|
||||
|
||||
/**## ODOptionsJsonConfig_OptionsData `type`
|
||||
* All contents of the `options.jsonc` config file.
|
||||
*/
|
||||
export type ODOptionsJsonConfig_OptionsData = (ODOptionsJsonConfig_TicketOption|ODOptionsJsonConfig_WebsiteOption|ODOptionsJsonConfig_RoleOption|ODOptionsJsonConfig_SubPanelOption)[]
|
||||
|
||||
///////////////////////////////////////
|
||||
// CONFIG STRUCTURES, VALUES & TYPES
|
||||
// --> panels.json
|
||||
// --> panels.jsonc
|
||||
///////////////////////////////////////
|
||||
|
||||
/**## ODPanelsJsonConfig_PanelEmbedSettings `interface`
|
||||
* This interface is an object which has all message embed settings for panels in the `panels.json` config!
|
||||
* This interface is an object which has all message embed settings for panels in the `panels.jsonc` config!
|
||||
*/
|
||||
export interface ODPanelsJsonConfig_PanelEmbedSettings {
|
||||
/**Is this embed enabled? */
|
||||
@@ -535,6 +544,8 @@ export interface ODPanelsJsonConfig_PanelEmbedSettings {
|
||||
export interface ODPanelsJsonConfig_PanelSettings {
|
||||
/**The placeholder used in the dropdown when enabled. */
|
||||
dropdownPlaceholder:string,
|
||||
/**The maximum amount of option buttons before starting a new row. */
|
||||
maximumButtonsPerRow:number
|
||||
|
||||
/**Enable a max tickets warning in the text contents. */
|
||||
enableMaxTicketsWarningInText:boolean,
|
||||
@@ -554,7 +565,7 @@ export interface ODPanelsJsonConfig_PanelSettings {
|
||||
}
|
||||
|
||||
/**## ODPanelsJsonConfig_Panel `interface`
|
||||
* This interface is an object which has all properties for panels in the `panels.json` config!
|
||||
* This interface is an object which has all properties for panels in the `panels.jsonc` config!
|
||||
*/
|
||||
export interface ODPanelsJsonConfig_Panel {
|
||||
/**The id of this panel. */
|
||||
@@ -563,7 +574,7 @@ export interface ODPanelsJsonConfig_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. */
|
||||
/**A list of valid options ids from the `options.jsonc` config. */
|
||||
options:string[],
|
||||
|
||||
/**The raw text contents of this panel. (empty for embed only) */
|
||||
@@ -575,19 +586,19 @@ export interface ODPanelsJsonConfig_Panel {
|
||||
}
|
||||
|
||||
/**## ODPanelsJsonConfig_PanelsData `type`
|
||||
* All contents of the `panels.json` config file.
|
||||
* All contents of the `panels.jsonc` config file.
|
||||
*/
|
||||
export type ODPanelsJsonConfig_PanelsData = ODPanelsJsonConfig_Panel[]
|
||||
|
||||
///////////////////////////////////////
|
||||
// CONFIG STRUCTURES, VALUES & TYPES
|
||||
// --> questions.json
|
||||
// --> questions.jsonc
|
||||
///////////////////////////////////////
|
||||
|
||||
/**## ODQuestionsJsonConfig_QuestionLengthSettings `interface`
|
||||
/**## ODQuestionsJsonConfig_TextLengthLimits `interface`
|
||||
* This interface is a collection of settings related to length validation in a question.
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_QuestionLengthSettings {
|
||||
export interface ODQuestionsJsonConfig_TextLengthLimits {
|
||||
/**Enable text length verification. */
|
||||
enabled:boolean,
|
||||
/**The minimum text input length. */
|
||||
@@ -596,48 +607,138 @@ export interface ODQuestionsJsonConfig_QuestionLengthSettings {
|
||||
max:number
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_CheckboxLimits `interface`
|
||||
* The required amount of checkboxes validation in a question.
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_CheckboxLimits {
|
||||
/**Enable checkbox limits. */
|
||||
enabled:boolean,
|
||||
/**The minimum amount of selected checkboxes. */
|
||||
min:number,
|
||||
/**The maximum amount of selected checkboxes. */
|
||||
max:number
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_DropdownChoice `interface`
|
||||
* A dropdown choice used in `ODQuestionsJsonConfig_DropdownQuestion`
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_DropdownChoice {
|
||||
/**The title of the choice. */
|
||||
title:string,
|
||||
/**The optional description of the choice. (Leave empty for none) */
|
||||
description:string,
|
||||
/**The optional emoji of the choice. (Leave empty for none) */
|
||||
emoji:string
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_RadioCheckboxChoice `interface`
|
||||
* A radio/checkbox choice used in `ODQuestionsJsonConfig_RadioSelectQuestion` & `ODQuestionsJsonConfig_CheckboxSelectQuestion`
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_RadioCheckboxChoice {
|
||||
/**The title of the choice. */
|
||||
title:string,
|
||||
/**The optional description of the choice. (Leave empty for none) */
|
||||
description:string,
|
||||
/**Is this choice selected by default? */
|
||||
selectedByDefault:boolean
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_BaseQuestion `interface`
|
||||
* This interface is an object which has all universal properties for questions in the `questions.json` config!
|
||||
* This interface is an object which has all universal properties for questions in the `questions.jsonc` config!
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_BaseQuestion {
|
||||
/**The id of this question. */
|
||||
id:string,
|
||||
/**The name of this question. */
|
||||
name:string,
|
||||
/**The description of this question. (Leave empty for none) */
|
||||
description:string,
|
||||
/**The type of this question. */
|
||||
type:"short"|"paragraph",
|
||||
type:"short"|"paragraph"|"text-display"|"dropdown"|"radio-select"|"checkbox-select",
|
||||
/**Is this question required? */
|
||||
required:boolean,
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_TextDisplayQuestion `interface`
|
||||
* All properties for a text-display in the `questions.jsonc` config!
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_TextDisplayQuestion {
|
||||
/**The id of this text-display. */
|
||||
id:string,
|
||||
/**The type of this question. */
|
||||
type:"text-display",
|
||||
/**The text contents to show in the modal. */
|
||||
textContents:string
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_ShortQuestion `interface`
|
||||
* This interface is an object which has all properties for short questions in the `questions.json` config!
|
||||
* All properties for short questions in the `questions.jsonc` config!
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_ShortQuestion extends ODQuestionsJsonConfig_BaseQuestion {
|
||||
type:"short",
|
||||
/**A placeholder for the question. */
|
||||
placeholder:string,
|
||||
/**A collection of settings related to length validation in a question. */
|
||||
length:ODQuestionsJsonConfig_QuestionLengthSettings
|
||||
length:ODQuestionsJsonConfig_TextLengthLimits
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_ParagraphQuestion `interface`
|
||||
* This interface is an object which has all properties for paragraph questions in the `questions.json` config!
|
||||
* All properties for paragraph questions in the `questions.jsonc` config!
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_ParagraphQuestion extends ODQuestionsJsonConfig_BaseQuestion {
|
||||
type:"paragraph",
|
||||
/**A placeholder for the question. */
|
||||
placeholder:string,
|
||||
/**A collection of settings related to length validation in a question. */
|
||||
length:ODQuestionsJsonConfig_QuestionLengthSettings
|
||||
length:ODQuestionsJsonConfig_TextLengthLimits
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_DropdownQuestion `interface`
|
||||
* All properties for dropdown questions in the `questions.jsonc` config!
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_DropdownQuestion extends ODQuestionsJsonConfig_BaseQuestion {
|
||||
type:"dropdown",
|
||||
/**A placeholder for the dropdown. */
|
||||
placeholder:string,
|
||||
/**A list of maximum 25 dropdown choices. */
|
||||
choices:ODQuestionsJsonConfig_DropdownChoice[]
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_RadioSelectQuestion `interface`
|
||||
* All properties for radio select questions in the `questions.jsonc` config!
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_RadioSelectQuestion extends ODQuestionsJsonConfig_BaseQuestion {
|
||||
type:"radio-select",
|
||||
/**A list of minimum 2, maximum 10 radio choices. */
|
||||
choices:ODQuestionsJsonConfig_RadioCheckboxChoice[]
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_CheckboxSelectQuestion `interface`
|
||||
* All properties for checkbox select questions in the `questions.jsonc` config!
|
||||
*/
|
||||
export interface ODQuestionsJsonConfig_CheckboxSelectQuestion extends ODQuestionsJsonConfig_BaseQuestion {
|
||||
type:"checkbox-select",
|
||||
/**Verify the checked amount of checkboxes with a minimum & maximum. */
|
||||
limits:ODQuestionsJsonConfig_CheckboxLimits
|
||||
/**A list of minimum 1, maximum 10 checkbox choices. */
|
||||
choices:ODQuestionsJsonConfig_RadioCheckboxChoice[]
|
||||
}
|
||||
|
||||
/**## ODQuestionsJsonConfig_QuestionsData `type`
|
||||
* All contents of the `questions.json` config file.
|
||||
* All contents of the `questions.jsonc` config file.
|
||||
*/
|
||||
export type ODQuestionsJsonConfig_QuestionsData = (ODQuestionsJsonConfig_ShortQuestion|ODQuestionsJsonConfig_ParagraphQuestion)[]
|
||||
export type ODQuestionsJsonConfig_QuestionsData = (
|
||||
ODQuestionsJsonConfig_ShortQuestion|
|
||||
ODQuestionsJsonConfig_ParagraphQuestion|
|
||||
ODQuestionsJsonConfig_TextDisplayQuestion|
|
||||
ODQuestionsJsonConfig_DropdownQuestion|
|
||||
ODQuestionsJsonConfig_RadioSelectQuestion|
|
||||
ODQuestionsJsonConfig_CheckboxSelectQuestion
|
||||
)[]
|
||||
|
||||
///////////////////////////////////////
|
||||
// CONFIG STRUCTURES, VALUES & TYPES
|
||||
// --> transcripts.json
|
||||
// --> transcripts.jsonc
|
||||
///////////////////////////////////////
|
||||
|
||||
/**## ODTranscriptsJsonConfig_TranscriptsTextLayout `interface`
|
||||
@@ -712,7 +813,7 @@ export interface ODTranscriptsJsonConfig_TranscriptsHtmlLayout {
|
||||
}
|
||||
|
||||
/**## ODTranscriptsJsonConfig_TranscriptsData `interface`
|
||||
* All contents of the `transcripts.json` config file.
|
||||
* All contents of the `transcripts.jsonc` config file.
|
||||
*/
|
||||
export interface ODTranscriptsJsonConfig_TranscriptsData {
|
||||
/**All general settings related to transcripts. */
|
||||
@@ -760,27 +861,27 @@ export interface ODTranscriptsJsonConfig_TranscriptsData {
|
||||
*/
|
||||
export class ODMappedConfigManager extends api.ODConfigManager<ODConfigManagerIdMappings> {}
|
||||
|
||||
/**## ODGeneralJsonConfig `class
|
||||
* A special class with types for the Open Ticket `config/general.json` config file
|
||||
/**## ODGeneralJsonCommentsConfig `class
|
||||
* A special class with types for the Open Ticket `config/general.jsonc` config file
|
||||
*/
|
||||
export class ODGeneralJsonConfig extends api.ODJsonConfig<ODGeneralJsonConfig_GeneralData> {}
|
||||
export class ODGeneralJsonCommentsConfig extends api.ODJsonCommentsConfig<ODGeneralJsonConfig_GeneralData> {}
|
||||
|
||||
/**## ODQuestionsJsonConfig `class
|
||||
* A special class with types for the Open Ticket `config/questions.json` config file
|
||||
/**## ODQuestionsJsonCommentsConfig `class
|
||||
* A special class with types for the Open Ticket `config/questions.jsonc` config file
|
||||
*/
|
||||
export class ODQuestionsJsonConfig extends api.ODJsonConfig<ODQuestionsJsonConfig_QuestionsData> {}
|
||||
export class ODQuestionsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODQuestionsJsonConfig_QuestionsData> {}
|
||||
|
||||
/**## ODOptionsJsonConfig `class
|
||||
* A special class with types for the Open Ticket `config/options.json` config file
|
||||
/**## ODOptionsJsonCommentsConfig `class
|
||||
* A special class with types for the Open Ticket `config/options.jsonc` config file
|
||||
*/
|
||||
export class ODOptionsJsonConfig extends api.ODJsonConfig<ODOptionsJsonConfig_OptionsData> {}
|
||||
export class ODOptionsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODOptionsJsonConfig_OptionsData> {}
|
||||
|
||||
/**## ODPanelsJsonConfig `class
|
||||
* A special class with types for the Open Ticket `config/panels.json` config file
|
||||
/**## ODPanelsJsonCommentsConfig `class
|
||||
* A special class with types for the Open Ticket `config/panels.jsonc` config file
|
||||
*/
|
||||
export class ODPanelsJsonConfig extends api.ODJsonConfig<ODPanelsJsonConfig_PanelsData> {}
|
||||
export class ODPanelsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODPanelsJsonConfig_PanelsData> {}
|
||||
|
||||
/**## ODTranscriptsJsonConfig `class
|
||||
* A special class with types for the Open Ticket `config/transcripts.json` config file
|
||||
/**## ODTranscriptsJsonCommentsConfig `class
|
||||
* A special class with types for the Open Ticket `config/transcripts.jsonc` config file
|
||||
*/
|
||||
export class ODTranscriptsJsonConfig extends api.ODJsonConfig<ODTranscriptsJsonConfig_TranscriptsData> {}
|
||||
export class ODTranscriptsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODTranscriptsJsonConfig_TranscriptsData> {}
|
||||
@@ -6,21 +6,21 @@ import * as api from "@open-discord-bots/framework/api"
|
||||
export interface ODOpenTicketFuseList {
|
||||
/**Load the default Open Ticket ticket priority levels. */
|
||||
priorityLoading:boolean,
|
||||
/**Load the default Open Ticket questions (from `config/questions.json`) */
|
||||
/**Load the default Open Ticket questions (from `config/questions.jsonc`) */
|
||||
questionLoading:boolean,
|
||||
/**Load the default Open Ticket options (from `config/options.json`) */
|
||||
/**Load the default Open Ticket options (from `config/options.jsonc`) */
|
||||
optionLoading:boolean,
|
||||
/**Load the default Open Ticket panels (from `config/panels.json`) */
|
||||
/**Load the default Open Ticket panels (from `config/panels.jsonc`) */
|
||||
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`) */
|
||||
/**Load the default Open Ticket reaction roles (from `config/options.jsonc`) */
|
||||
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`) */
|
||||
/**Load the default Open Ticket transcript history (from `database/transcripts.jsonc`) */
|
||||
transcriptHistoryLoading:boolean,
|
||||
/**The interval in milliseconds that are between autoclose timeout checkers. */
|
||||
autocloseCheckInterval:number,
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
import {opendiscord, api, utilities} from "../../index.js"
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
|
||||
/**Check if the no-migration flag is active. */
|
||||
function isMigrationAllowedFromFlag(){
|
||||
return (!process.argv.includes("--no-migration") && !process.argv.includes("-nm"))
|
||||
}
|
||||
|
||||
/**Read the global.json database raw to detect the last version of the bot. */
|
||||
function getRawLastVersion(){
|
||||
const isDevDatabase = process.argv.includes("--dev-database") || process.argv.includes("-dd")
|
||||
const globalDatabaseLocation = path.join(process.cwd(),(isDevDatabase) ? "./devdatabase/global.json" : "./database/global.json")
|
||||
const rawData: api.ODJsonDatabaseStructure = JSON.parse(fs.readFileSync(globalDatabaseLocation).toString())
|
||||
const lastVersion = rawData.find((d) => d.category == "opendiscord:last-version" && d.key == "opendiscord:version")?.value ?? null
|
||||
return lastVersion as string|null
|
||||
}
|
||||
|
||||
/**Check if migration is required. Returns the last version used in the database. */
|
||||
async function isMigrationRequired(): Promise<false|api.ODVersion> {
|
||||
const rawVersion = await opendiscord.databases.get("opendiscord:global").get("opendiscord:last-version","opendiscord:version")
|
||||
const rawVersion = getRawLastVersion()
|
||||
if (!rawVersion) return false
|
||||
const version = api.ODVersion.fromString("opendiscord:last-version",rawVersion)
|
||||
if (opendiscord.versions.get("opendiscord:version").compare(version) == "higher"){
|
||||
@@ -20,47 +35,6 @@ async function saveAllVersionsToDatabase(){
|
||||
})
|
||||
}
|
||||
|
||||
export async function loadVersionMigrationSystem(){
|
||||
//ENTER MIGRATION CONTEXT
|
||||
await preloadMigrationContext()
|
||||
|
||||
const lastVersion = await isMigrationRequired()
|
||||
|
||||
//save last version to database (OR set to current version if no migration is required)
|
||||
opendiscord.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("opendiscord:last-version",opendiscord.versions.get("opendiscord:version").toString()))
|
||||
|
||||
if (lastVersion && !opendiscord.flags.get("opendiscord:no-migration").value){
|
||||
//MIGRATION IS REQUIRED
|
||||
opendiscord.log("Detected old data!","info")
|
||||
opendiscord.log("Starting closed API context...","debug")
|
||||
await utilities.timer(600)
|
||||
opendiscord.log("Migrating data to new version...","debug")
|
||||
await loadAllVersionMigrations(lastVersion)
|
||||
opendiscord.log("Stopping closed API context...","debug")
|
||||
await utilities.timer(400)
|
||||
opendiscord.log("All data is now up to date!","info")
|
||||
await utilities.timer(200)
|
||||
console.log("---------------------------------------------------------------------")
|
||||
}
|
||||
saveAllVersionsToDatabase()
|
||||
|
||||
//DEFAULT FLAGS
|
||||
if (opendiscord.flags.exists("opendiscord:no-plugins") && opendiscord.flags.get("opendiscord:no-plugins").value) opendiscord.sharedFuses.setFuse("pluginLoading",false)
|
||||
if (opendiscord.flags.exists("opendiscord:soft-plugins") && opendiscord.flags.get("opendiscord:soft-plugins").value) opendiscord.sharedFuses.setFuse("softPluginLoading",true)
|
||||
if (opendiscord.flags.exists("opendiscord:crash") && opendiscord.flags.get("opendiscord:crash").value) opendiscord.sharedFuses.setFuse("crashOnError",true)
|
||||
if (opendiscord.flags.exists("opendiscord:force-slash-update") && opendiscord.flags.get("opendiscord:force-slash-update").value){
|
||||
opendiscord.sharedFuses.setFuse("forceSlashCommandRegistration",true)
|
||||
opendiscord.sharedFuses.setFuse("forceContextMenuRegistration",true)
|
||||
}
|
||||
if (opendiscord.flags.exists("opendiscord:silent") && opendiscord.flags.get("opendiscord:silent").value) opendiscord.console.silent = true
|
||||
|
||||
|
||||
//LEAVE MIGRATION CONTEXT
|
||||
await unloadMigrationContext()
|
||||
|
||||
return lastVersion
|
||||
}
|
||||
|
||||
/**Initialize the migration context by loading the built-in flags, configs & databases. */
|
||||
async function preloadMigrationContext(){
|
||||
opendiscord.debug.debug("-- MIGRATION CONTEXT START --")
|
||||
@@ -73,6 +47,52 @@ async function preloadMigrationContext(){
|
||||
opendiscord.debug.visible = true
|
||||
}
|
||||
|
||||
export async function loadVersionMigrationSystem(){
|
||||
const lastVersion = await isMigrationRequired()
|
||||
|
||||
//save last version in version manager (OR set to current version if no migration is required)
|
||||
opendiscord.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("opendiscord:last-version",opendiscord.versions.get("opendiscord:version").toString()))
|
||||
|
||||
//MIGRATION IS REQUIRED
|
||||
if (lastVersion && isMigrationAllowedFromFlag()){
|
||||
//BEFORE STARTUP MIGRATION
|
||||
opendiscord.log("Detected old data!","info")
|
||||
await loadBeforeStartupMigrations(lastVersion)
|
||||
}
|
||||
|
||||
//ENTER MIGRATION CONTEXT (must be separate for flags to work)
|
||||
await preloadMigrationContext()
|
||||
|
||||
if (lastVersion && isMigrationAllowedFromFlag()){
|
||||
//CONTEXT MIGRATION
|
||||
opendiscord.log("Starting restricted API context...","debug")
|
||||
await utilities.timer(600)
|
||||
opendiscord.log("Migrating data to new version...","debug")
|
||||
await loadContextMigrations(lastVersion)
|
||||
opendiscord.log("Stopping restricted API context...","debug")
|
||||
await utilities.timer(400)
|
||||
opendiscord.log("All data is now up to date!","info")
|
||||
await utilities.timer(200)
|
||||
console.log("---------------------------------------------------------------------")
|
||||
}
|
||||
saveAllVersionsToDatabase()
|
||||
|
||||
//SET FUSES & PROPERTIES OF SPECIAL FLAGS
|
||||
if (opendiscord.flags.exists("opendiscord:no-plugins") && opendiscord.flags.get("opendiscord:no-plugins").value) opendiscord.sharedFuses.setFuse("pluginLoading",false)
|
||||
if (opendiscord.flags.exists("opendiscord:soft-plugins") && opendiscord.flags.get("opendiscord:soft-plugins").value) opendiscord.sharedFuses.setFuse("softPluginLoading",true)
|
||||
if (opendiscord.flags.exists("opendiscord:crash") && opendiscord.flags.get("opendiscord:crash").value) opendiscord.sharedFuses.setFuse("crashOnError",true)
|
||||
if (opendiscord.flags.exists("opendiscord:force-slash-update") && opendiscord.flags.get("opendiscord:force-slash-update").value){
|
||||
opendiscord.sharedFuses.setFuse("forceSlashCommandRegistration",true)
|
||||
opendiscord.sharedFuses.setFuse("forceContextMenuRegistration",true)
|
||||
}
|
||||
if (opendiscord.flags.exists("opendiscord:silent") && opendiscord.flags.get("opendiscord:silent").value) opendiscord.console.silent = true
|
||||
|
||||
//LEAVE MIGRATION CONTEXT
|
||||
await unloadMigrationContext()
|
||||
|
||||
return lastVersion
|
||||
}
|
||||
|
||||
/**Unload the migration context to start the bot normally. */
|
||||
async function unloadMigrationContext(){
|
||||
opendiscord.debug.visible = false
|
||||
@@ -98,8 +118,8 @@ function createMigrationBackup(){
|
||||
else fs.cpSync("./database/","./.backup/database/",{force:true,recursive:true})
|
||||
}
|
||||
|
||||
/**Execute all version migration functions which are handled in the restricted migration context. */
|
||||
async function loadAllVersionMigrations(lastVersion:api.ODVersion){
|
||||
/**Execute all version migration functions which are handled before any flags, configs or databases are loaded. */
|
||||
async function loadBeforeStartupMigrations(lastVersion:api.ODVersion){
|
||||
const migrations = (await import("./migration.js")).migrations
|
||||
migrations.sort((a,b) => {
|
||||
const comparison = a.version.compare(b.version)
|
||||
@@ -114,10 +134,36 @@ async function loadAllVersionMigrations(lastVersion:api.ODVersion){
|
||||
|
||||
for (const migration of migrations){
|
||||
if (migration.version.compare(lastVersion) == "higher"){
|
||||
const success = await migration.migrate()
|
||||
const success = await migration.migrateBeforeStartup()
|
||||
if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[
|
||||
{key:"success",value:success ? "true" : "false"},
|
||||
{key:"afterInit",value:"false"}
|
||||
{key:"type",value:"before-startup"}
|
||||
])
|
||||
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**Execute all version migration functions which are handled in the restricted migration context. */
|
||||
async function loadContextMigrations(lastVersion:api.ODVersion){
|
||||
const migrations = (await import("./migration.js")).migrations
|
||||
migrations.sort((a,b) => {
|
||||
const comparison = a.version.compare(b.version)
|
||||
if (comparison == "equal") return 0
|
||||
else if (comparison == "higher") return 1
|
||||
else return -1
|
||||
})
|
||||
if (migrations.length > 0){
|
||||
//create backup of config & database
|
||||
createMigrationBackup()
|
||||
}
|
||||
|
||||
for (const migration of migrations){
|
||||
if (migration.version.compare(lastVersion) == "higher"){
|
||||
const success = await migration.migrateInContext()
|
||||
if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[
|
||||
{key:"success",value:success ? "true" : "false"},
|
||||
{key:"type",value:"restricted-context"}
|
||||
])
|
||||
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
|
||||
}
|
||||
@@ -125,7 +171,7 @@ async function loadAllVersionMigrations(lastVersion:api.ODVersion){
|
||||
}
|
||||
|
||||
/**Execute all version migration functions which are handled in the normal startup sequence. */
|
||||
export async function loadAllAfterInitVersionMigrations(lastVersion:api.ODVersion){
|
||||
export async function loadAfterStartupMigrations(lastVersion:api.ODVersion){
|
||||
const migrations = (await import("./migration.js")).migrations
|
||||
migrations.sort((a,b) => {
|
||||
const comparison = a.version.compare(b.version)
|
||||
@@ -140,10 +186,10 @@ export async function loadAllAfterInitVersionMigrations(lastVersion:api.ODVersio
|
||||
|
||||
for (const migration of migrations){
|
||||
if (migration.version.compare(lastVersion) == "higher"){
|
||||
const success = await migration.migrateAfterInit()
|
||||
const success = await migration.migrateAfterStartup()
|
||||
if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[
|
||||
{key:"success",value:success ? "true" : "false"},
|
||||
{key:"afterInit",value:"true"}
|
||||
{key:"type",value:"after-startup"}
|
||||
])
|
||||
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
|
||||
}
|
||||
|
||||
+308
-104
@@ -1,147 +1,351 @@
|
||||
import { opendiscord, api, utilities } from "../../index.js"
|
||||
import fs from "fs"
|
||||
import path from "path"
|
||||
|
||||
export const migrations = [
|
||||
//MIGRATE TO v4.0.0
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.0"),async () => {},async () => {}),
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.0"),{}),
|
||||
|
||||
//MIGRATE TO v4.0.1
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.1"),async () => {},async () => {
|
||||
//AFTER INIT MIGRATION
|
||||
|
||||
//add opendiscord:panel-message properties for all existing panels.
|
||||
const globalDatabase = opendiscord.databases.get("opendiscord:global")
|
||||
for (const panel of (await globalDatabase.getCategory("opendiscord:panel-update") ?? [])){
|
||||
globalDatabase.set("opendiscord:panel-message",panel.key,panel.value)
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.1"),{
|
||||
afterStartupMigrate:async () => {
|
||||
//add opendiscord:panel-message properties for all existing panels.
|
||||
const globalDatabase = opendiscord.databases.get("opendiscord:global")
|
||||
for (const panel of (await globalDatabase.getCategory("opendiscord:panel-update") ?? [])){
|
||||
globalDatabase.set("opendiscord:panel-message",panel.key,panel.value)
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
//MIGRATE TO v4.0.2
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.2"),async () => {},async () => {}),
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.2"),{}),
|
||||
|
||||
//MIGRATE TO v4.0.3
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.3"),async () => {},async () => {}),
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.3"),{}),
|
||||
|
||||
//MIGRATE TO v4.0.4
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.4"),async () => {},async () => {}),
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.4"),{}),
|
||||
|
||||
//MIGRATE TO v4.0.5
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.5"),async () => {},async () => {}),
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.5"),{}),
|
||||
|
||||
//MIGRATE TO v4.0.6
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.6"),async () => {},async () => {}),
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.6"),{}),
|
||||
|
||||
//MIGRATE TO v4.0.7
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.7"),async () => {},async () => {}),
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.7"),{}),
|
||||
|
||||
//MIGRATE TO v4.1.0
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.0"),async () => {},async () => {
|
||||
//AFTER INIT MIGRATION
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.0"),{
|
||||
afterStartupMigrate:async () => {
|
||||
//migrate config
|
||||
const generalConfig = opendiscord.configs.get("opendiscord:general")
|
||||
const optionConfig = opendiscord.configs.get("opendiscord:options")
|
||||
|
||||
//migrate config
|
||||
const generalConfig = opendiscord.configs.get("opendiscord:general")
|
||||
const optionConfig = opendiscord.configs.get("opendiscord:options")
|
||||
if (!generalConfig.data.status.state){
|
||||
//only migrate config when it hasn't been done manually by the user.
|
||||
|
||||
if (!generalConfig.data.status.state){
|
||||
//only migrate config when it hasn't been done manually by the user.
|
||||
if (!generalConfig.data["_INFO"]) throw new api.ODSystemError("Couldn't find general.json '_INFO' category.")
|
||||
generalConfig.data["_INFO"].version = "open-ticket-v4.1.0"
|
||||
|
||||
if (!generalConfig.data._INFO) throw new api.ODSystemError("Couldn't find general.json '_INFO' category.")
|
||||
generalConfig.data._INFO.version = "open-ticket-v4.1.0"
|
||||
if (!generalConfig.data.status) throw new api.ODSystemError("Couldn't find general.json 'status' category.")
|
||||
generalConfig.data.status.mode = generalConfig.data.status["status"] ?? "online"
|
||||
generalConfig.data.status.state = ""
|
||||
delete generalConfig.data.status["status"]
|
||||
|
||||
if (!generalConfig.data.status) throw new api.ODSystemError("Couldn't find general.json 'status' category.")
|
||||
generalConfig.data.status.mode = generalConfig.data.status["status"] ?? "online"
|
||||
generalConfig.data.status.state = ""
|
||||
delete generalConfig.data.status["status"]
|
||||
if (!generalConfig.data["system"]) throw new api.ODSystemError("Couldn't find general.json 'system' category.")
|
||||
generalConfig.data["system"].displayFieldsWithQuestions = false
|
||||
generalConfig.data["system"].showGlobalAdminsInPanelRoles = false
|
||||
generalConfig.data["system"].alwaysShowReason = false
|
||||
generalConfig.data["system"].pinEmoji = "📌"
|
||||
generalConfig.data["system"].askPriorityOnTicketCreation = false
|
||||
generalConfig.data["system"].disableAutocloseAfterReopen = true
|
||||
generalConfig.data["system"].autodeleteRequiresClosedTicket = true
|
||||
generalConfig.data["system"].adminOnlyDeleteWithoutTranscript = true
|
||||
generalConfig.data["system"].allowCloseBeforeMessage = false
|
||||
generalConfig.data["system"].allowCloseBeforeAdminMessage = true
|
||||
generalConfig.data["system"].pinFirstTicketMessage = false
|
||||
|
||||
if (!generalConfig.data.system) throw new api.ODSystemError("Couldn't find general.json 'system' category.")
|
||||
generalConfig.data.system.displayFieldsWithQuestions = false
|
||||
generalConfig.data.system.showGlobalAdminsInPanelRoles = false
|
||||
generalConfig.data.system.alwaysShowReason = false
|
||||
generalConfig.data.system.pinEmoji = "📌"
|
||||
generalConfig.data.system.askPriorityOnTicketCreation = false
|
||||
generalConfig.data.system.disableAutocloseAfterReopen = true
|
||||
generalConfig.data.system.autodeleteRequiresClosedTicket = true
|
||||
generalConfig.data.system.adminOnlyDeleteWithoutTranscript = true
|
||||
generalConfig.data.system.allowCloseBeforeMessage = false
|
||||
generalConfig.data.system.allowCloseBeforeAdminMessage = true
|
||||
generalConfig.data.system.pinFirstTicketMessage = false
|
||||
|
||||
generalConfig.data.system.channelTopic = {
|
||||
showOptionName:true,
|
||||
showOptionDescription:false,
|
||||
showOptionTopic:true,
|
||||
showPriority:false,
|
||||
showClosed:true,
|
||||
showClaimed:false,
|
||||
showPinned:false,
|
||||
showCreator:false,
|
||||
showParticipants:false
|
||||
}
|
||||
|
||||
if (!generalConfig.data.system.permissions) throw new api.ODSystemError("Couldn't find general.json 'system.permissions' category.")
|
||||
generalConfig.data.system.permissions.transfer = "admin"
|
||||
generalConfig.data.system.permissions.topic = "admin"
|
||||
generalConfig.data.system.permissions.priority = "admin"
|
||||
|
||||
if (!generalConfig.data.system.messages) throw new api.ODSystemError("Couldn't find general.json 'system.messages' category.")
|
||||
generalConfig.data.system.messages.transferring = {dm:false,logs:true}
|
||||
generalConfig.data.system.messages.topicChange = {dm:false,logs:true}
|
||||
generalConfig.data.system.messages.priorityChange = {dm:false,logs:true}
|
||||
generalConfig.data.system.messages.reactionRole = generalConfig.data.system.messages["roleAdding"] ?? {dm:false,logs:true}
|
||||
delete generalConfig.data.system.messages["roleAdding"]
|
||||
delete generalConfig.data.system.messages["roleRemoving"]
|
||||
|
||||
for (const option of optionConfig.data){
|
||||
if (option.type != "ticket") continue
|
||||
option.channel.topic = option.channel["description"] ?? ""
|
||||
delete option.channel["description"]
|
||||
|
||||
option.slowMode = {
|
||||
enabled:false,
|
||||
slowModeSeconds:20
|
||||
generalConfig.data["system"].channelTopic = {
|
||||
showOptionName:true,
|
||||
showOptionDescription:false,
|
||||
showOptionTopic:true,
|
||||
showPriority:false,
|
||||
showClosed:true,
|
||||
showClaimed:false,
|
||||
showPinned:false,
|
||||
showCreator:false,
|
||||
showParticipants:false
|
||||
}
|
||||
|
||||
if (!generalConfig.data["system"].permissions) throw new api.ODSystemError("Couldn't find general.json 'system.permissions' category.")
|
||||
generalConfig.data["system"].permissions.transfer = "admin"
|
||||
generalConfig.data["system"].permissions.topic = "admin"
|
||||
generalConfig.data["system"].permissions.priority = "admin"
|
||||
|
||||
if (!generalConfig.data["system"].messages) throw new api.ODSystemError("Couldn't find general.json 'system.messages' category.")
|
||||
generalConfig.data["system"].messages.transferring = {dm:false,logs:true}
|
||||
generalConfig.data["system"].messages.topicChange = {dm:false,logs:true}
|
||||
generalConfig.data["system"].messages.priorityChange = {dm:false,logs:true}
|
||||
generalConfig.data["system"].messages.reactionRole = generalConfig.data["system"].messages["roleAdding"] ?? {dm:false,logs:true}
|
||||
delete generalConfig.data["system"].messages["roleAdding"]
|
||||
delete generalConfig.data["system"].messages["roleRemoving"]
|
||||
|
||||
for (const option of optionConfig.data){
|
||||
if (option.type != "ticket") continue
|
||||
option.channel.topic = option.channel["description"] ?? ""
|
||||
delete option.channel["description"]
|
||||
|
||||
option.slowMode = {
|
||||
enabled:false,
|
||||
slowModeSeconds:20
|
||||
}
|
||||
}
|
||||
|
||||
await generalConfig.save()
|
||||
await optionConfig.save()
|
||||
}
|
||||
|
||||
await generalConfig.save()
|
||||
await optionConfig.save()
|
||||
}
|
||||
//migrate database
|
||||
const optionDatabase = opendiscord.databases.get("opendiscord:options")
|
||||
const ticketDatabase = opendiscord.databases.get("opendiscord:tickets")
|
||||
|
||||
//migrate database
|
||||
const optionDatabase = opendiscord.databases.get("opendiscord:options")
|
||||
const ticketDatabase = opendiscord.databases.get("opendiscord:tickets")
|
||||
for (const option of (await optionDatabase.getCategory("opendiscord:used-option") ?? [])){
|
||||
const optionData = option.value
|
||||
|
||||
const topicData = optionData.data.find((d) => d.id == "opendiscord:channel-description")
|
||||
if (topicData) topicData.id = "opendiscord:channel-topic"
|
||||
if (!optionData.data.find((d) => d.id == "opendiscord:slowmode-enabled")) optionData.data.push({id:"opendiscord:slowmode-enabled",value:false})
|
||||
if (!optionData.data.find((d) => d.id == "opendiscord:slowmode-seconds")) optionData.data.push({id:"opendiscord:slowmode-seconds",value:20})
|
||||
|
||||
for (const option of (await optionDatabase.getCategory("opendiscord:used-option") ?? [])){
|
||||
const optionData = option.value
|
||||
|
||||
const topicData = optionData.data.find((d) => d.id == "opendiscord:channel-description")
|
||||
if (topicData) topicData.id = "opendiscord:channel-topic"
|
||||
if (!optionData.data.find((d) => d.id == "opendiscord:slowmode-enabled")) optionData.data.push({id:"opendiscord:slowmode-enabled",value:false})
|
||||
if (!optionData.data.find((d) => d.id == "opendiscord:slowmode-seconds")) optionData.data.push({id:"opendiscord:slowmode-seconds",value:20})
|
||||
optionDatabase.set("opendiscord:used-option",option.key,optionData)
|
||||
}
|
||||
|
||||
optionDatabase.set("opendiscord:used-option",option.key,optionData)
|
||||
}
|
||||
for (const ticket of (await ticketDatabase.getCategory("opendiscord:ticket") ?? [])){
|
||||
const ticketData = ticket.value
|
||||
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:previous-creators")) ticketData.data.push({id:"opendiscord:previous-creators",value:[]})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened")) ticketData.data.push({id:"opendiscord:reopened",value:false})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened-by")) ticketData.data.push({id:"opendiscord:reopened-by",value:null})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened-on")) ticketData.data.push({id:"opendiscord:reopened-on",value:null})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:priority")) ticketData.data.push({id:"opendiscord:priority",value:-1})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:topic")) ticketData.data.push({id:"opendiscord:topic",value:""})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:message-sent")) ticketData.data.push({id:"opendiscord:message-sent",value:true})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:admin-message-sent")) ticketData.data.push({id:"opendiscord:admin-message-sent",value:true})
|
||||
|
||||
for (const ticket of (await ticketDatabase.getCategory("opendiscord:ticket") ?? [])){
|
||||
const ticketData = ticket.value
|
||||
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:previous-creators")) ticketData.data.push({id:"opendiscord:previous-creators",value:[]})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened")) ticketData.data.push({id:"opendiscord:reopened",value:false})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened-by")) ticketData.data.push({id:"opendiscord:reopened-by",value:null})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened-on")) ticketData.data.push({id:"opendiscord:reopened-on",value:null})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:priority")) ticketData.data.push({id:"opendiscord:priority",value:-1})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:topic")) ticketData.data.push({id:"opendiscord:topic",value:""})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:message-sent")) ticketData.data.push({id:"opendiscord:message-sent",value:true})
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:admin-message-sent")) ticketData.data.push({id:"opendiscord:admin-message-sent",value:true})
|
||||
|
||||
ticketDatabase.set("opendiscord:ticket",ticket.key,ticketData)
|
||||
ticketDatabase.set("opendiscord:ticket",ticket.key,ticketData)
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
//MIGRATE TO v4.1.1
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.1"),async () => {},async () => {}),
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.1"),{}),
|
||||
|
||||
//MIGRATE TO v4.1.2
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.2"),async () => {},async () => {}),
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.2"),{}),
|
||||
|
||||
//MIGRATE TO v4.1.3
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.3"),async () => {},async () => {}),
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.3"),{}),
|
||||
|
||||
//MIGRATE TO v4.2.0
|
||||
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.2.0"),{
|
||||
beforeStartupMigrate:async () => {
|
||||
const isDevconfig = (process.argv.includes("--dev-config") || process.argv.includes("-dc"))
|
||||
|
||||
//transfer config files to .jsonc
|
||||
const configDir = path.join(process.cwd(),(isDevconfig) ? "./devconfig/" : "./config/")
|
||||
for (const file of fs.readdirSync(configDir).filter((f) => f.endsWith(".json"))){
|
||||
try{
|
||||
fs.copyFileSync(path.join(configDir,file),path.join(configDir,file.replace(".json",".jsonc")))
|
||||
fs.rmSync(path.join(configDir,file))
|
||||
}catch(err){
|
||||
process.emit("uncaughtException",err)
|
||||
}
|
||||
}
|
||||
},
|
||||
afterStartupMigrate:async () => {
|
||||
//migrate config
|
||||
const generalConfig = opendiscord.configs.get("opendiscord:general")
|
||||
const questionConfig = opendiscord.configs.get("opendiscord:questions")
|
||||
const optionConfig = opendiscord.configs.get("opendiscord:options")
|
||||
const panelConfig = opendiscord.configs.get("opendiscord:panels")
|
||||
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
|
||||
|
||||
if (!generalConfig.data.ticketSystem){
|
||||
//only migrate config when it hasn't been done manually by the user.
|
||||
|
||||
if (!generalConfig.data["_INFO"]) throw new api.ODSystemError("Couldn't find general.jsonc '_INFO' category.")
|
||||
delete generalConfig.data["_INFO"]
|
||||
generalConfig.data._CONFIG_VERSION = "open-ticket-v4.2.0"
|
||||
|
||||
if (!generalConfig.data["system"]) throw new api.ODSystemError("Couldn't find general.jsonc 'system' category.")
|
||||
generalConfig.data.ticketSystem = generalConfig.data["system"]
|
||||
generalConfig.data.ticketSystem.closeEmoji = "🔒"
|
||||
generalConfig.data.ticketSystem.askPriorityOnTicketCreation = true
|
||||
generalConfig.data.ticketSystem.enableCreateTicketForOtherUser = true
|
||||
delete generalConfig.data["system"]
|
||||
generalConfig.data.logs = generalConfig.data.ticketSystem["logs"]
|
||||
delete generalConfig.data.ticketSystem["logs"]
|
||||
generalConfig.data.logs.logMessages = generalConfig.data.ticketSystem["messages"]
|
||||
delete generalConfig.data.ticketSystem["messages"]
|
||||
generalConfig.data.permissions = generalConfig.data.ticketSystem["permissions"]
|
||||
delete generalConfig.data.ticketSystem["permissions"]
|
||||
generalConfig.data.permissions.transcripts = "admin"
|
||||
|
||||
//closed category
|
||||
const closedCategory = {enabled:false,categoryId:"DISCORD_CATEGORY_ID"}
|
||||
for (const option of optionConfig.data){
|
||||
if (option.type != "ticket") continue
|
||||
if (option.channel["closedCategory"] && /^\d+$/.test(option.channel["closedCategory"])){
|
||||
closedCategory.enabled = true
|
||||
closedCategory.categoryId = option.channel["closedCategory"]
|
||||
}
|
||||
}
|
||||
generalConfig.data.ticketSystem.closedCategory = closedCategory
|
||||
|
||||
//backup category
|
||||
const backupCategory = {enabled:false,categoryId:"DISCORD_CATEGORY_ID"}
|
||||
for (const option of optionConfig.data){
|
||||
if (option.type != "ticket") continue
|
||||
if (option.channel["backupCategory"] && /^\d+$/.test(option.channel["backupCategory"])){
|
||||
backupCategory.enabled = true
|
||||
backupCategory.categoryId = option.channel["backupCategory"]
|
||||
}
|
||||
}
|
||||
generalConfig.data.ticketSystem.backupCategory = backupCategory
|
||||
|
||||
//claimed categories
|
||||
const claimedCategories: {user:string,category:string}[] = []
|
||||
for (const option of optionConfig.data){
|
||||
if (option.type != "ticket" || !Array.isArray(option.channel["claimedCategory"])) continue
|
||||
for (const {user,category} of option.channel["claimedCategory"]){
|
||||
if (typeof user == "string" && typeof category == "string" && /^\d+$/.test(user) && /^\d+$/.test(category) && !claimedCategories.find((c) => c.user == user)){
|
||||
claimedCategories.push({user,category})
|
||||
}
|
||||
}
|
||||
}
|
||||
generalConfig.data.ticketSystem.claimedCategories = claimedCategories
|
||||
|
||||
|
||||
//delete properties from options.jsonc
|
||||
for (const option of optionConfig.data){
|
||||
if (option.type != "ticket") continue
|
||||
delete option.channel["closedCategory"]
|
||||
delete option.channel["backupCategory"]
|
||||
delete option.channel["claimedCategory"]
|
||||
}
|
||||
|
||||
//update panels config:
|
||||
for (const panel of panelConfig.data){
|
||||
panel.settings.maximumButtonsPerRow = 5
|
||||
}
|
||||
|
||||
//update questions config:
|
||||
for (const question of questionConfig.data){
|
||||
if (question.type !== "paragraph" && question.type !== "short") continue
|
||||
question.description = ""
|
||||
}
|
||||
|
||||
//add new sub-panel option example (for users to try)
|
||||
optionConfig.data.push({
|
||||
id:"example-sub-panel",
|
||||
name:"Example Sub-Panel",
|
||||
description:"This is an example of how to implement a sub-panel in Open Ticket.",
|
||||
type:"sub-panel",
|
||||
|
||||
button:{
|
||||
color:"gray",
|
||||
label:"Sub-Panel Example",
|
||||
emoji:"📋"
|
||||
},
|
||||
subPanelId:panelConfig.data[0]?.id ?? "example-panel"
|
||||
})
|
||||
|
||||
//add new question examples (for users to try)
|
||||
questionConfig.data.push(
|
||||
{
|
||||
id:"example-dropdown-question",
|
||||
name:"Example Dropdown Question",
|
||||
description:"This is a dropdown question.",
|
||||
type:"dropdown",
|
||||
required:false,
|
||||
|
||||
placeholder:"Choose your answer...",
|
||||
choices:[
|
||||
{title:"Choice A",description:"Apple",emoji:"🍎"},
|
||||
{title:"Choice B",description:"Banana",emoji:"🍌"},
|
||||
{title:"Choice C",description:"Orange",emoji:"🍊"},
|
||||
{title:"Choice D",description:"Kiwi",emoji:"🥝"}
|
||||
]
|
||||
},
|
||||
{
|
||||
id:"example-radio-question",
|
||||
name:"Example Radio Question",
|
||||
description:"This is a radio select question.",
|
||||
type:"radio-select",
|
||||
required:true,
|
||||
|
||||
choices:[
|
||||
{title:"Choice A",description:"Up",selectedByDefault:false},
|
||||
{title:"Choice B",description:"Down",selectedByDefault:false},
|
||||
{title:"Choice C",description:"Left",selectedByDefault:false},
|
||||
{title:"Choice D",description:"Right",selectedByDefault:false}
|
||||
]
|
||||
},
|
||||
{
|
||||
id:"example-checkbox-question",
|
||||
name:"Example Checkbox Question",
|
||||
description:"This is a checkbox select question.",
|
||||
type:"checkbox-select",
|
||||
required:true,
|
||||
|
||||
limits:{
|
||||
enabled:false,
|
||||
min:0,
|
||||
max:10
|
||||
},
|
||||
choices:[
|
||||
{title:"Choice A",description:"Happiness",selectedByDefault:false},
|
||||
{title:"Choice B",description:"Anger",selectedByDefault:false},
|
||||
{title:"Choice C",description:"Sadness",selectedByDefault:false},
|
||||
{title:"Choice D",description:"Fear",selectedByDefault:false}
|
||||
]
|
||||
},
|
||||
{
|
||||
id:"example-text-display-question",
|
||||
type:"text-display",
|
||||
textContents:"This is a text display. It isn't a question, but allows you to display a text, explaination or details."
|
||||
}
|
||||
)
|
||||
|
||||
await generalConfig.save()
|
||||
await questionConfig.save()
|
||||
await optionConfig.save()
|
||||
await panelConfig.save()
|
||||
await transcriptConfig.save()
|
||||
}
|
||||
|
||||
//migrate database
|
||||
const optionDatabase = opendiscord.databases.get("opendiscord:options")
|
||||
const ticketDatabase = opendiscord.databases.get("opendiscord:tickets")
|
||||
|
||||
for (const option of (await optionDatabase.getCategory("opendiscord:used-option") ?? [])){
|
||||
const optionData = option.value
|
||||
optionData.data = optionData.data.filter((data) => (
|
||||
data.id !== "opendiscord:channel-category-closed" &&
|
||||
data.id !== "pendiscord:channel-category-backup" &&
|
||||
data.id !== "opendiscord:channel-categories-claimed"
|
||||
))
|
||||
|
||||
optionDatabase.set("opendiscord:used-option",option.key,optionData)
|
||||
}
|
||||
|
||||
for (const ticket of (await ticketDatabase.getCategory("opendiscord:ticket") ?? [])){
|
||||
const ticketData = ticket.value
|
||||
if (!ticketData.data.find((d) => d.id == "opendiscord:channel-renamed")) ticketData.data.push({id:"opendiscord:channel-renamed",value:null})
|
||||
|
||||
ticketDatabase.set("opendiscord:ticket",ticket.key,ticketData)
|
||||
}
|
||||
}
|
||||
}),
|
||||
]
|
||||
Reference in New Issue
Block a user