Open Ticket v4 Beta
This commit is contained in:
@@ -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))
|
||||
})
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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 : "`<unnamed-ticket>`"
|
||||
let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "`<no-description>`"
|
||||
|
||||
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 : "`<unnamed-website>`"
|
||||
let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "`<no-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 : "`<unnamed-role>`"
|
||||
let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "`<no-description>`"
|
||||
|
||||
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<string>|null
|
||||
const name = opt.get("openticket:name") as api.ODOptionData<string>|null
|
||||
const description = opt.get("openticket:description") as api.ODOptionData<string>|null
|
||||
return {name:utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`")),value:(description ? description.value : "`<no-description>`")}
|
||||
}
|
||||
})
|
||||
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 : "`<unnamed-ticket>`"
|
||||
let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "`<no-description>`"
|
||||
|
||||
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 : "`<unnamed-website>`"
|
||||
let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "`<no-description>`"
|
||||
|
||||
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 : "`<unnamed-role>`"
|
||||
let description = opt.exists("openticket:description") ? opt.get("openticket:description").value : "`<no-description>`"
|
||||
|
||||
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<string>|null
|
||||
const name = opt.get("openticket:name") as api.ODOptionData<string>|null
|
||||
const description = opt.get("openticket:description") as api.ODOptionData<string>|null
|
||||
|
||||
if (layout == "simple") return "**"+utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`"))+":** "+(description ? description.value : "`<no-description>`")
|
||||
else return "**"+utilities.emojiTitle((emoji ? emoji.value : ""),(name ? name.value : "`"+opt.id+"`"))+"**\n"+(description ? description.value : "`<no-description>`")
|
||||
}
|
||||
}).join("\n\n")
|
||||
else throw new api.ODSystemError("Unknown panel generation mode, choose 'text' or 'fields'")
|
||||
}
|
||||
@@ -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),
|
||||
])
|
||||
}
|
||||
@@ -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)
|
||||
])
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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 : ("<content is empty>"+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 ?? "<no-title>")+" ====\n"+(embed.description ?? "<no-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 ?? "<no-title>")+" ====\n"+(embed.description ?? "<no-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 ?? "<embed>")?.substring(0,80)
|
||||
} : undefined,
|
||||
commandOptions:(msg.reply && msg.reply.type == "interaction") ? {
|
||||
interactionId:"<outdated>",
|
||||
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 : "<unknown>"),
|
||||
creatorid:(creator ? creator.id : "<unknown>"),
|
||||
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 : "<not-claimed>"),
|
||||
claimedid:(claimer ? claimer.id : "<not-claimed>"),
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user