Support for HTML Transcripts v2.1

This commit is contained in:
DJj123dj
2025-05-01 13:56:38 +02:00
parent 94f32674cb
commit bb5c3e9c8d
6 changed files with 206 additions and 125 deletions
+1 -1
View File
@@ -49,7 +49,7 @@
}, },
"favicon":{ "favicon":{
"enableCustomFavicon":false, "enableCustomFavicon":false,
"imageUrl":"https://transcripts.dj-dj.be/favicon.png" "imageUrl":"https://t.dj-dj.be/favicon.png"
} }
} }
} }
+6 -2
View File
@@ -38,7 +38,9 @@ export const registerActions = async () => {
await opendiscord.events.get("onTranscriptInit").emit([opendiscord.transcripts,ticket,channel,user]) await opendiscord.events.get("onTranscriptInit").emit([opendiscord.transcripts,ticket,channel,user])
if (instance.compiler.init){ if (instance.compiler.init){
try{ try{
instance.initData = null
const result = await instance.compiler.init(ticket,channel,user) const result = await instance.compiler.init(ticket,channel,user)
instance.initData = result.initData
if (result.success && result.pendingMessage && transcriptConfig.data.general.enableChannel){ if (result.success && result.pendingMessage && transcriptConfig.data.general.enableChannel){
//send init message to channel //send init message to channel
const post = opendiscord.posts.get("opendiscord:transcripts") const post = opendiscord.posts.get("opendiscord:transcripts")
@@ -49,7 +51,9 @@ export const registerActions = async () => {
instance.pendingMessage = null instance.pendingMessage = null
instance.errorReason = result.errorReason instance.errorReason = result.errorReason
throw new api.ODSystemError("ODAction(ot:create-transcript) => Known Init Error => "+result.errorReason) throw new api.ODSystemError("ODAction(ot:create-transcript) => Known Init Error => "+result.errorReason)
}else instance.pendingMessage = null }else{
instance.pendingMessage = null
}
}catch(err){ }catch(err){
instance.success = false instance.success = false
cancel() cancel()
@@ -72,7 +76,7 @@ export const registerActions = async () => {
await opendiscord.events.get("onTranscriptCompile").emit([opendiscord.transcripts,ticket,channel,user]) await opendiscord.events.get("onTranscriptCompile").emit([opendiscord.transcripts,ticket,channel,user])
if (instance.compiler.compile){ if (instance.compiler.compile){
try{ try{
const result = await instance.compiler.compile(ticket,channel,user) const result = await instance.compiler.compile(ticket,channel,user,instance.initData)
if (!result.success){ if (!result.success){
instance.errorReason = result.errorReason instance.errorReason = result.errorReason
throw new api.ODSystemError("ODAction(ot:create-transcript) => Known Compiler Error => "+result.errorReason) throw new api.ODSystemError("ODAction(ot:create-transcript) => Known Compiler Error => "+result.errorReason)
+1 -1
View File
@@ -25,7 +25,7 @@ export interface ODActionManagerIds_Default {
"opendiscord:create-transcript":{ "opendiscord:create-transcript":{
source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other", source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket}, params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},
result:{compiler:ODTranscriptCompiler<any>, success:boolean, result:ODTranscriptCompilerCompileResult<any>, errorReason:string|null, pendingMessage:ODMessageBuildSentResult<true>|null, participants:{user:discord.User,role:"creator"|"participant"|"admin"}[]}, result:{compiler:ODTranscriptCompiler<any,object|null>, success:boolean, result:ODTranscriptCompilerCompileResult<any>, errorReason:string|null, pendingMessage:ODMessageBuildSentResult<true>|null, initData:object|null, participants:{user:discord.User,role:"creator"|"participant"|"admin"}[]},
workers:"opendiscord:select-compiler"|"opendiscord:init-transcript"|"opendiscord:compile-transcript"|"opendiscord:ready-transcript"|"opendiscord:logs" workers:"opendiscord:select-compiler"|"opendiscord:init-transcript"|"opendiscord:compile-transcript"|"opendiscord:ready-transcript"|"opendiscord:logs"
}, },
"opendiscord:create-ticket":{ "opendiscord:create-ticket":{
+12 -12
View File
@@ -58,9 +58,9 @@ export interface ODButtonManagerIds_Default {
"opendiscord:pin-ticket":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:pin-ticket"}, "opendiscord:pin-ticket":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:pin-ticket"},
"opendiscord:unpin-ticket":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unpin-ticket"}, "opendiscord:unpin-ticket":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unpin-ticket"},
"opendiscord:transcript-html-visit":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string}>,result:ODTranscriptCompilerCompileResult<{url:string}>},workers:"opendiscord:transcript-html-visit"}, "opendiscord:transcript-html-visit":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,result:ODTranscriptCompilerCompileResult<{url:string,availableUntil:Date}>},workers:"opendiscord:transcript-html-visit"},
"opendiscord:transcript-error-retry":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any>,reason:string|null},workers:"opendiscord:transcript-error-retry"}, "opendiscord:transcript-error-retry":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any,object|null>,reason:string|null},workers:"opendiscord:transcript-error-retry"},
"opendiscord:transcript-error-continue":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any>,reason:string|null},workers:"opendiscord:transcript-error-continue"}, "opendiscord:transcript-error-continue":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any,object|null>,reason:string|null},workers:"opendiscord:transcript-error-continue"},
"opendiscord:clear-continue":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-continue"}, "opendiscord:clear-continue":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-continue"},
} }
@@ -170,7 +170,7 @@ export class ODDropdown_Default<Source extends string, Params, WorkerIds extends
* It's used to generate typescript declarations for this class. * It's used to generate typescript declarations for this class.
*/ */
export interface ODFileManagerIds_Default { export interface ODFileManagerIds_Default {
"opendiscord:text-transcript":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any>,result:ODTranscriptCompilerCompileResult<any>},workers:"opendiscord:text-transcript"} "opendiscord:text-transcript":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any,object|null>,result:ODTranscriptCompilerCompileResult<any>},workers:"opendiscord:text-transcript"}
} }
/**## ODFileManager_Default `default_class` /**## ODFileManager_Default `default_class`
@@ -275,10 +275,10 @@ export interface ODEmbedManagerIds_Default {
"opendiscord:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-dm"}, "opendiscord:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-dm"},
"opendiscord:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-logs"}, "opendiscord:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-logs"},
"opendiscord:transcript-text-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{contents:string}>,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"opendiscord:transcript-text-ready"}, "opendiscord:transcript-text-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{contents:string},null>,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"opendiscord:transcript-text-ready"},
"opendiscord:transcript-html-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string}>,result:ODTranscriptCompilerCompileResult<{url:string}>},workers:"opendiscord:transcript-html-ready"}, "opendiscord:transcript-html-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,result:ODTranscriptCompilerCompileResult<{url:string,availableUntil:Date}>},workers:"opendiscord:transcript-html-ready"},
"opendiscord:transcript-html-progress":{source:"channel"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string}>,remaining:number},workers:"opendiscord:transcript-html-progress"}, "opendiscord:transcript-html-progress":{source:"channel"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,remaining:number},workers:"opendiscord:transcript-html-progress"},
"opendiscord:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any>,reason:string|null},workers:"opendiscord:transcript-error"}, "opendiscord:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any,object|null>,reason:string|null},workers:"opendiscord:transcript-error"},
"opendiscord:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role"}, "opendiscord:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role"},
"opendiscord:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-verify-message"}, "opendiscord:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-verify-message"},
@@ -406,10 +406,10 @@ export interface ODMessageManagerIds_Default {
"opendiscord:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-dm"}, "opendiscord:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-dm"},
"opendiscord:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-logs"}, "opendiscord:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-logs"},
"opendiscord:transcript-text-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{contents:string}>,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"opendiscord:transcript-text-ready"}, "opendiscord:transcript-text-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{contents:string},null>,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"opendiscord:transcript-text-ready"},
"opendiscord:transcript-html-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string}>,result:ODTranscriptCompilerCompileResult<{url:string}>},workers:"opendiscord:transcript-html-ready"}, "opendiscord:transcript-html-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,result:ODTranscriptCompilerCompileResult<{url:string,availableUntil:Date}>},workers:"opendiscord:transcript-html-ready"},
"opendiscord:transcript-html-progress":{source:"channel"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string}>,remaining:number},workers:"opendiscord:transcript-html-progress"}, "opendiscord:transcript-html-progress":{source:"channel"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,remaining:number},workers:"opendiscord:transcript-html-progress"},
"opendiscord:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any>,reason:string|null},workers:"opendiscord:transcript-error"}, "opendiscord:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any,object|null>,reason:string|null},workers:"opendiscord:transcript-error"},
"opendiscord:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role"}, "opendiscord:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role"},
"opendiscord:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-verify-message"}, "opendiscord:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-verify-message"},
+43 -46
View File
@@ -15,7 +15,7 @@ import * as discord from "discord.js"
* *
* The 2 default built-in transcript generators are: `opendiscord:html-compiler` & `opendiscord:text-compiler`. * The 2 default built-in transcript generators are: `opendiscord:html-compiler` & `opendiscord:text-compiler`.
*/ */
export class ODTranscriptManager extends ODManager<ODTranscriptCompiler<any>> { export class ODTranscriptManager extends ODManager<ODTranscriptCompiler<any,null|object>> {
/**The manager responsible for collecting all messages in a channel. */ /**The manager responsible for collecting all messages in a channel. */
collector: ODTranscriptCollector collector: ODTranscriptCollector
/**Alias for the client manager. */ /**Alias for the client manager. */
@@ -31,12 +31,12 @@ export class ODTranscriptManager extends ODManager<ODTranscriptCompiler<any>> {
/**## ODTranscriptCompilerInitFunction `type` /**## ODTranscriptCompilerInitFunction `type`
* This function will initiate/prepare the transcript system for an incoming transcript. * This function will initiate/prepare the transcript system for an incoming transcript.
*/ */
export type ODTranscriptCompilerInitFunction = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => (ODTranscriptCompilerInitResult)|Promise<ODTranscriptCompilerInitResult> export type ODTranscriptCompilerInitFunction<InitData extends object|null> = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => (ODTranscriptCompilerInitResult<InitData>)|Promise<ODTranscriptCompilerInitResult<InitData>>
/**## ODTranscriptCompilerCompileFunction `type` /**## ODTranscriptCompilerCompileFunction `type`
* This function will generate/compile the transcript itself. * This function will generate/compile the transcript itself.
*/ */
export type ODTranscriptCompilerCompileFunction<Data extends object> = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User) => ODTranscriptCompilerCompileResult<Data>|Promise<ODTranscriptCompilerCompileResult<Data>> export type ODTranscriptCompilerCompileFunction<Data extends object,InitData extends object|null> = (ticket:ODTicket, channel:discord.TextChannel, user:discord.User, initData:InitData) => ODTranscriptCompilerCompileResult<Data>|Promise<ODTranscriptCompilerCompileResult<Data>>
/**## ODTicketClearFilter `type` /**## ODTicketClearFilter `type`
* This function will finish, clear-up & shut-down the transcript system. This will also initiate the sending of the messages to all recipients. * This function will finish, clear-up & shut-down the transcript system. This will also initiate the sending of the messages to all recipients.
@@ -46,13 +46,15 @@ export type ODTranscriptCompilerReadyFunction<Data extends object> = (result:ODT
/**## ODTranscriptCompilerInitResult `interface` /**## ODTranscriptCompilerInitResult `interface`
* This is the result which is returned by the `init()` function. * This is the result which is returned by the `init()` function.
*/ */
export interface ODTranscriptCompilerInitResult { export interface ODTranscriptCompilerInitResult<InitData extends object|null> {
/**Was the initialization successfull? */ /**Was the initialization successfull? */
success:boolean, success:boolean,
/**When not successfull, what was the reason? This will also be shown to the user. */ /**When not successfull, what was the reason? This will also be shown to the user. */
errorReason:string|null, errorReason:string|null,
/**An optional message which will be sent while the transcript is being generated. */ /**An optional message which will be sent while the transcript is being generated. */
pendingMessage:ODMessageBuildResult|null pendingMessage:ODMessageBuildResult|null,
/**An optional object containing data from the init() function which can be used in the compiler. */
initData:InitData,
} }
/**## ODTranscriptCompilerCompileResult `interface` /**## ODTranscriptCompilerCompileResult `interface`
@@ -98,15 +100,15 @@ export interface ODTranscriptCompilerReadyResult {
* *
* These functions should be defined when creating this compiler. Existing compilers already exist for html & text transcripts. * These functions should be defined when creating this compiler. Existing compilers already exist for html & text transcripts.
*/ */
export class ODTranscriptCompiler<Data extends object> extends ODManagerData { export class ODTranscriptCompiler<Data extends object,InitData extends (object|null)> extends ODManagerData {
/*Initialise the system every time a transcript is created. Returns optional "pending" message to display while the transcript is being compiled. */ /*Initialise the system every time a transcript is created. Returns optional "pending" message to display while the transcript is being compiled. */
init: ODTranscriptCompilerInitFunction|null init: ODTranscriptCompilerInitFunction<InitData>|null
/*Compile or create the transcript. Returns data to give to the ready() function for message creation. */ /*Compile or create the transcript. Returns data to give to the ready() function for message creation. */
compile: ODTranscriptCompilerCompileFunction<Data>|null compile: ODTranscriptCompilerCompileFunction<Data,InitData>|null
/*Unload the system & create the final transcript message that will be sent. */ /*Unload the system & create the final transcript message that will be sent. */
ready: ODTranscriptCompilerReadyFunction<Data>|null ready: ODTranscriptCompilerReadyFunction<Data>|null
constructor(id:ODValidId, init?:ODTranscriptCompilerInitFunction, compile?:ODTranscriptCompilerCompileFunction<Data>, ready?:ODTranscriptCompilerReadyFunction<Data>|null){ constructor(id:ODValidId, init?:ODTranscriptCompilerInitFunction<InitData>, compile?:ODTranscriptCompilerCompileFunction<Data,InitData>, ready?:ODTranscriptCompilerReadyFunction<Data>|null){
super(id) super(id)
this.init = init ?? null this.init = init ?? null
this.compile = compile ?? null this.compile = compile ?? null
@@ -119,8 +121,8 @@ export class ODTranscriptCompiler<Data extends object> extends ODManagerData {
* It's used to generate typescript declarations for this class. * It's used to generate typescript declarations for this class.
*/ */
export interface ODTranscriptCompilerIds { export interface ODTranscriptCompilerIds {
"opendiscord:html-compiler":ODTranscriptCompiler<{url:string}>, "opendiscord:html-compiler":ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,
"opendiscord:text-compiler":ODTranscriptCompiler<{contents:string}>, "opendiscord:text-compiler":ODTranscriptCompiler<{contents:string},null>,
} }
/**## ODTranscriptManager_Default `default_class` /**## ODTranscriptManager_Default `default_class`
@@ -131,16 +133,16 @@ export interface ODTranscriptCompilerIds {
*/ */
export class ODTranscriptManager_Default extends ODTranscriptManager { export class ODTranscriptManager_Default extends ODTranscriptManager {
get<QuestionId extends keyof ODTranscriptCompilerIds>(id:QuestionId): ODTranscriptCompilerIds[QuestionId] get<QuestionId extends keyof ODTranscriptCompilerIds>(id:QuestionId): ODTranscriptCompilerIds[QuestionId]
get(id:ODValidId): ODTranscriptCompiler<any>|null get(id:ODValidId): ODTranscriptCompiler<any,null|object>|null
get(id:ODValidId): ODTranscriptCompiler<any>|null { get(id:ODValidId): ODTranscriptCompiler<any,null|object>|null {
return super.get(id) return super.get(id)
} }
remove<QuestionId extends keyof ODTranscriptCompilerIds>(id:QuestionId): ODTranscriptCompilerIds[QuestionId] remove<QuestionId extends keyof ODTranscriptCompilerIds>(id:QuestionId): ODTranscriptCompilerIds[QuestionId]
remove(id:ODValidId): ODTranscriptCompiler<any>|null remove(id:ODValidId): ODTranscriptCompiler<any,null|object>|null
remove(id:ODValidId): ODTranscriptCompiler<any>|null { remove(id:ODValidId): ODTranscriptCompiler<any,null|object>|null {
return super.remove(id) return super.remove(id)
} }
@@ -698,7 +700,7 @@ export interface ODTranscriptReactionData extends ODTranscriptEmojiData {
* The structure of the data sent to the Open Ticket HTML Transcripts v2 API. * The structure of the data sent to the Open Ticket HTML Transcripts v2 API.
*/ */
export interface ODTranscriptHtmlV2Data { export interface ODTranscriptHtmlV2Data {
version:"2", version:"2.1",
otversion:string, otversion:string,
language:string, language:string,
style:{ style:{
@@ -734,25 +736,33 @@ export interface ODTranscriptHtmlV2Data {
ticket:{ ticket:{
name:string, name:string,
id:string, id:string,
guildname:string, guildname:string,
guildid:string, guildid:string,
guildinvite:string|false, guildinvite:string|false,
creatorname:string, createdname:string|false,
creatorid:string, createdid:string|false,
closedname:string|false,
closedid:string|false,
claimedname:string|false,
claimedid:string|false,
pinnedname:string|false,
pinnedid:string|false,
deletedname:string|false,
deletedid:string|false,
closedbyname:string, createdpfp:string|false,
closedbyid:string, closedpfp:string|false,
claimedpfp:string|false,
pinnedpfp:string|false,
deletedpfp:string|false,
claimedname:string, createdtime:number|false,
claimedid:string, closedtime:number|false,
claimedtime:number|false,
creatorpfp:string, pinnedtime:number|false,
closedbypfp:string, deletedtime:number|false,
claimedpfp:string,
closedtime:number,
openedtime:number,
components:{ components:{
messages:number, messages:number,
@@ -916,22 +926,9 @@ export interface ODTranscriptHtmlV2Data {
*/ */
export interface ODTranscriptHtmlV2Response { export interface ODTranscriptHtmlV2Response {
status:"success"|"error", status:"success"|"error",
id:string, type:"transcript",
url:string,
availableUntil:number, //UNIMPLEMENTED
time:number, time:number,
estimated:{ id:string
lastdump: number,
processtime:number,
waittime:number
},
transcriptstatus:{
value:2,
data:{
fetchedmsgs:true,
uploaded:true,
inqueue:true,
processed:false,
waiting:false,
available:false
}
}
} }
+142 -62
View File
@@ -5,7 +5,8 @@ const collector = opendiscord.transcripts.collector
const messages = opendiscord.builders.messages const messages = opendiscord.builders.messages
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts") const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
const textConfig = transcriptConfig.data.textTranscriptStyle const textConfig = transcriptConfig.data.textTranscriptStyle
const htmlVersion = Buffer.from("b3BlbnRpY2tldFRSQU5TQ1JJUFQxMjM0","base64").toString("utf8") const htmlVersion = Buffer.from("eW91LXNob3VsZG50LWJlLWxvb2tpbmctYXQtdGhpcy0tLWZvci1tb3JlLWluZm8tY29tbWEtc2VuZC1hLW1lc3NhZ2UtdG8tZGpqMTIzZGo=","base64").toString("utf8")
const htmlDomain = atob("dC5kai1kai5iZQ==")
export const replaceHtmlTranscriptMentions = async (text:string) => { export const replaceHtmlTranscriptMentions = async (text:string) => {
const mainServer = opendiscord.client.mainServer const mainServer = opendiscord.client.mainServer
@@ -34,17 +35,30 @@ export const replaceHtmlTranscriptMentions = async (text:string) => {
return defaultroletext return defaultroletext
} }
/**
* This function is used to authenticate with the HTML Transcript API.
* It is NOT the token of the bot but an internal AUTH TOKEN from the API.
*
* Questions? Visit our discord server: https://discord.dj-dj.be
*/
function transcriptAuth(_A:{salt:number,secret:string}){
const _B = Buffer.from(_A.secret,"hex");const _C = Math["floor"](new Date().getTime()/(30*1000)).toString();const _D = Buffer.from(_C);const _E = Buffer.alloc(_D["length"]);_D.forEach((v,i) => {_E[i] = v ^ _B[i % _B["length"]];});return btoa(JSON.stringify({salt:_A.salt,secret:_A.secret,token:_E.toString("hex")}))
}
export const loadAllTranscriptCompilers = async () => { export const loadAllTranscriptCompilers = async () => {
class ODHTTPHtmlPostRequest extends api.ODHTTPPostRequest { class ODHTTPHtmlPostRequest extends api.ODHTTPPostRequest {
constructor(domain:string, htmlFinal:api.ODTranscriptHtmlV2Data){ constructor(transcriptAuth:string,htmlFinal:api.ODTranscriptHtmlV2Data){
super("https://"+domain+"/transcripts/upload?auth="+htmlVersion+"&version=2",true,{ super("https://"+htmlDomain+"/api/v2/upload?auth="+htmlVersion+"&token="+transcriptAuth,true,{
body:JSON.stringify(htmlFinal) body:JSON.stringify(htmlFinal),
headers:{
"Content-Type":"application/json"
}
}) })
} }
} }
//TEXT COMPILER //TEXT COMPILER
opendiscord.transcripts.add(new api.ODTranscriptCompiler<{contents:string}>("opendiscord:text-compiler",undefined,async (ticket,channel,user) => { opendiscord.transcripts.add(new api.ODTranscriptCompiler<{contents:string},null>("opendiscord:text-compiler",undefined,async (ticket,channel,user) => {
//COMPILE //COMPILE
const rawMessages = await collector.collectAllMessages(ticket) const rawMessages = await collector.collectAllMessages(ticket)
if (!rawMessages) return {ticket,channel,user,success:false,errorReason:"Unable to collect messages! Channel not found!",messages:null,data:null} if (!rawMessages) return {ticket,channel,user,success:false,errorReason:"Unable to collect messages! Channel not found!",messages:null,data:null}
@@ -173,27 +187,51 @@ export const loadAllTranscriptCompilers = async () => {
})) }))
//HTML COMPILER //HTML COMPILER
opendiscord.transcripts.add(new api.ODTranscriptCompiler<{url:string}>("opendiscord:html-compiler",async (ticket,channel,user) => { opendiscord.transcripts.add(new api.ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}|null>("opendiscord:html-compiler",async (ticket,channel,user) => {
//INIT //INIT
const req = new api.ODHTTPGetRequest("https://apis.dj-dj.be/transcripts/status.json",false) const req = new api.ODHTTPGetRequest(atob("aHR0cHM6Ly90LmRqLWRqLmJlL2FwaS92Mi9pbml0"),false)
const res = await req.run() const res = await req.run()
if (!res || res.status != 200 || !res.body){ //PENDING MESSAGE (not required anymore) => await messages.getSafe("opendiscord:transcript-html-progress").build("channel",{guild:channel.guild,channel,user,ticket,compiler:opendiscord.transcripts.get("opendiscord:html-compiler"),remaining:16000})
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body) if (res.status == 200 && res.body){
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON error! (check otdebug.txt for details)")) const data: {salt:number,secret:string} = JSON.parse(atob(res.body))
return {success:false,errorReason:"HTML Transcripts are currently unavailable!",pendingMessage:null} return {success:true,errorReason:null,pendingMessage:null,initData:{auth:transcriptAuth(data)}}
} }
try{ else{
const data = JSON.parse(res.body) if (res.status == 503){
if (!data || data["v2"] != "online") return {success:false,errorReason:"HTML Transcripts are currently unavailable due to maintenance!",pendingMessage:null} opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
}catch{ process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_503 error! (check otdebug.txt for details)"))
opendiscord.debugfile.writeNote("HTML Transcripts Error => unable to parse status! body:\n"+res.body) return {success:false,errorReason:"The HTML Transcripts are currently unreachable. Please try again later.",pendingMessage:null,initData:null}
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_STATUS_PARSE error! (check otdebug.txt for details)"))
return {success:false,errorReason:"HTML Transcripts are currently unavailable due to JSON parse error!",pendingMessage:null} }else if (res.status == 429){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_429 error! (check otdebug.txt for details)"))
return {success:false,errorReason:"The HTML Transcripts are currently unreachable because the bot is ratelimited. Please try again in a few minutes.",pendingMessage:null,initData:null}
}else if (res.status == 403){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_403 error! (check otdebug.txt for details)"))
return {success:false,errorReason:"The HTML Transcripts are unreachable because the bot has been banned from using the API. If you don't know why, please contact us at https://discord.dj-dj.be",pendingMessage:null,initData:null}
}else if (res.status == 500){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_500 error! (check otdebug.txt for details)"))
return {success:false,errorReason:"Something went wrong while compiling the HTML Transcripts, please report this error at https://discord.dj-dj.be",pendingMessage:null,initData:null}
}else if (res.status == 413){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_413 error! (check otdebug.txt for details)"))
return {success:false,errorReason:"Unable to upload transcript, file size is too large (Max 5MB)!",pendingMessage:null,initData:null}
}else{
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts INIT_COMMUNICATON_UNKNOWN error! (check otdebug.txt for details)"))
return {success:false,errorReason:"Something went wrong while compiling the HTML Transcripts, please report this error at https://discord.dj-dj.be",pendingMessage:null,initData:null}
}
} }
return {success:true,errorReason:null,pendingMessage:await messages.getSafe("opendiscord:transcript-html-progress").build("channel",{guild:channel.guild,channel,user,ticket,compiler:opendiscord.transcripts.get("opendiscord:html-compiler"),remaining:16000})} },async (ticket,channel,user,initData) => {
},async (ticket,channel,user) => {
//COMPILE //COMPILE
if (!initData) return {ticket,channel,user,success:false,errorReason:"Could not authenticate with HTML Transcript API.",messages:null,data:null}
const rawMessages = await collector.collectAllMessages(ticket) const rawMessages = await collector.collectAllMessages(ticket)
if (!rawMessages) return {ticket,channel,user,success:false,errorReason:"Unable to collect messages! Channel not found!",messages:null,data:null} if (!rawMessages) return {ticket,channel,user,success:false,errorReason:"Unable to collect messages! Channel not found!",messages:null,data:null}
const messages = await collector.convertMessagesToTranscriptData(rawMessages) const messages = await collector.convertMessagesToTranscriptData(rawMessages)
@@ -350,18 +388,14 @@ export const loadAllTranscriptCompilers = async () => {
const dsf = transcriptConfig.data.htmlTranscriptStyle.favicon const dsf = transcriptConfig.data.htmlTranscriptStyle.favicon
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator") const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
const claimer = await opendiscord.tickets.getTicketUser(ticket,"claimer")
const closer = await opendiscord.tickets.getTicketUser(ticket,"closer") const closer = await opendiscord.tickets.getTicketUser(ticket,"closer")
const claimer = await opendiscord.tickets.getTicketUser(ticket,"claimer")
const pinner = await opendiscord.tickets.getTicketUser(ticket,"pinner")
const htmlFinal: api.ODTranscriptHtmlV2Data = { const htmlFinal: api.ODTranscriptHtmlV2Data = {
version:"2", version:"2.1",
otversion:opendiscord.versions.get("opendiscord:version").toString(true), otversion:opendiscord.versions.get("opendiscord:version").toString(true),
bot:{ language:opendiscord.languages.getLanguageMetadata()?.language.toLowerCase() ?? "english",
name:opendiscord.client.client.user.displayName,
id:opendiscord.client.client.user.id,
pfp:opendiscord.client.client.user.displayAvatarURL({extension:"png"}),
},
language:opendiscord.languages.getLanguageMetadata()?.language ?? "english",
style:{ style:{
background:{ background:{
backgroundData:(dsb.backgroundImage == "") ? dsb.backgroundColor : dsb.backgroundImage, backgroundData:(dsb.backgroundImage == "") ? dsb.backgroundColor : dsb.backgroundImage,
@@ -387,30 +421,44 @@ export const loadAllTranscriptCompilers = async () => {
enableCustomFavicon:dsf.enableCustomFavicon enableCustomFavicon:dsf.enableCustomFavicon
} }
}, },
bot:{
name:opendiscord.client.client.user.displayName,
id:opendiscord.client.client.user.id,
pfp:opendiscord.client.client.user.displayAvatarURL({extension:"png"}),
},
ticket:{ ticket:{
name:channel.name, name:channel.name,
id:channel.id, id:channel.id,
guildname:channel.guild.name, guildname:channel.guild.name,
guildid:channel.guild.id, guildid:channel.guild.id,
guildinvite:"", guildinvite:false,
creatorname:(creator ? creator.displayName : "<unknown>"), createdname:(creator ? creator.displayName : false),
creatorid:(creator ? creator.id : "<unknown>"), createdid:(creator ? creator.id : false),
creatorpfp:(creator ? creator.displayAvatarURL() : "https://transcripts.dj-dj.be/favicon.png"), createdpfp:(creator ? creator.displayAvatarURL() : false),
//closer is ticket deleter (small bug) closedname:(closer ? closer.displayName : false),
closedbyname:user.displayName, closedid:(closer ? closer.id : false),
closedbyid:user.id, closedpfp:(closer ? closer.displayAvatarURL() : false),
closedbypfp:user.displayAvatarURL(),
//claiming is currently unused claimedname:(claimer ? claimer.displayName : false),
claimedname:(claimer ? claimer.displayName : "<not-claimed>"), claimedid:(claimer ? claimer.id : false),
claimedid:(claimer ? claimer.id : "<not-claimed>"), claimedpfp:(claimer ? claimer.displayAvatarURL() : false),
claimedpfp:(claimer ? claimer.displayAvatarURL() : "https://transcripts.dj-dj.be/favicon.png"),
closedtime:new Date().getTime(), pinnedname:(pinner ? pinner.displayName : false),
openedtime:ticket.get("opendiscord:opened-on").value ?? new Date().getTime(), pinnedid:(pinner ? pinner.id : false),
pinnedpfp:(pinner ? pinner.displayAvatarURL() : false),
deletedname:user.displayName,
deletedid:user.id,
deletedpfp:user.displayAvatarURL(),
createdtime:ticket.get("opendiscord:opened-on").value ?? false,
closedtime:ticket.get("opendiscord:closed-on").value ?? false,
claimedtime:ticket.get("opendiscord:claimed-on").value ?? false,
pinnedtime:ticket.get("opendiscord:pinned-on").value ?? false,
deletedtime:new Date().getTime(),
//role colors are currently unused //role colors are currently unused
roleColors:[], roleColors:[],
@@ -440,39 +488,71 @@ export const loadAllTranscriptCompilers = async () => {
}, },
customFavicon:{ customFavicon:{
enabled:dsf.enableCustomFavicon, enabled:dsf.enableCustomFavicon,
image:(dsf.imageUrl) ? dsf.imageUrl : "https://transcripts.dj-dj.be/favicon.png" image:(dsf.imageUrl) ? dsf.imageUrl : "https://t.dj-dj.be/favicon.png"
}, },
additionalFlags:[] additionalFlags:[]
} }
} }
const req = new ODHTTPHtmlPostRequest("apis.dj-dj.be",htmlFinal) const req = new ODHTTPHtmlPostRequest(initData.auth,htmlFinal)
const res = await req.run() const res = await req.run()
//check status
if (!res || res.status != 200 || !res.body){
//ratelimit error
if (res.status == 429) return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts! (Ratelimit)\nTry again in a few minutes!",messages,data:null}
//unknown status error //check status
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body) if (res.status == 200 && res.body){
return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts! (Unknown Error)",messages,data:null} //check body
}
//check body
try{
var data: api.ODTranscriptHtmlV2Response = JSON.parse(res.body) var data: api.ODTranscriptHtmlV2Response = JSON.parse(res.body)
if (!data || data["status"] != "success"){ if (!data || data["status"] != "success"){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body) opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts! (Server 500 Error)",messages,data:null}} process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_JSON_STATUS error! (check otdebug.txt for details)"))
}catch{ return {ticket,channel,user,success:false,errorReason:"TFailed to read the response of the HTML Transcripts server.",messages:null,data:null}
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body) }
return {ticket,channel,user,success:false,errorReason:"Failed to upload HTML Transcripts! (JSON parse error)",messages,data:null}
}
const url = "https://transcripts.dj-dj.be/v2/"+data.time+"_"+data.id+".html" return {
return {ticket,channel,user,success:true,errorReason:null,messages,data:{url}} ticket,channel,user,
success:true,
errorReason:null,
messages,
data:{
url:data.url,
availableUntil:new Date(data.availableUntil)
}
}
}else{
if (res.status == 503){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_503 error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"The HTML Transcripts are currently unreachable. Please try again later.",messages:null,data:null}
}else if (res.status == 429){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_429 error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"The HTML Transcripts are currently unreachable because the bot is ratelimited. Please try again in a few minutes.",messages:null,data:null}
}else if (res.status == 403){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_403 error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"The HTML Transcripts are unreachable because the bot has been banned from using the API. If you don't know why, please contact us at https://discord.dj-dj.be",messages:null,data:null}
}else if (res.status == 500){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_500 error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"Something went wrong while compiling the HTML Transcripts, please report this error at https://discord.dj-dj.be",messages:null,data:null}
}else if (res.status == 413){
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_413 error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"Unable to upload transcript, file size is too large (Max 5MB)!",messages:null,data:null}
}else{
opendiscord.debugfile.writeNote("HTML Transcripts Error => status: "+res.status+", body:\n"+res.body)
process.emit("uncaughtException",new api.ODSystemError("HTML Transcripts COMPILE_COMMUNICATON_UNKNOWN error! (check otdebug.txt for details)"))
return {ticket,channel,user,success:false,errorReason:"Something went wrong while compiling the HTML Transcripts, please report this error at https://discord.dj-dj.be",messages:null,data:null}
}
}
},async (result) => { },async (result) => {
//READY //READY
await utilities.timer(16000) //wait until transcript is ready //WAIT UNTIL READY (not required anymore) => await utilities.timer(16000)
return { return {
channelMessage:await messages.getSafe("opendiscord:transcript-html-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:html-compiler")}), channelMessage:await messages.getSafe("opendiscord:transcript-html-ready").build("channel",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:html-compiler")}),
creatorDmMessage:await messages.getSafe("opendiscord:transcript-html-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:html-compiler")}), creatorDmMessage:await messages.getSafe("opendiscord:transcript-html-ready").build("creator-dm",{guild:result.channel.guild,channel:result.channel,user:result.user,ticket:result.ticket,result,compiler:opendiscord.transcripts.get("opendiscord:html-compiler")}),