Open Ticket v3.2.0

Open Ticket v3.2.0
This commit is contained in:
Jasper
2023-01-18 21:48:13 +01:00
committed by GitHub
34 changed files with 964 additions and 303 deletions
+2
View File
@@ -12,7 +12,9 @@ developerChangelog.md
storage/dynamicDB/ storage/dynamicDB/
storage/slashcmdEnabled.txt storage/slashcmdEnabled.txt
storage/database.json storage/database.json
storage/tsdatabase.json
storage/.DS_Store storage/.DS_Store
.vscode/ .vscode/
livestatus.json livestatus.json
test.js test.js
testtsconfig.json
+12 -13
View File
@@ -1,5 +1,5 @@
# Open Ticket # Open Ticket
[![discord](https://img.shields.io/badge/discord-join%20our%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-3.1.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v3.1.0) [![discord.js](https://img.shields.io/badge/discord.js-v14-CB3837.svg?style=flat-square&logo=npm)]() [![license](https://img.shields.io/badge/license-GPL%203.0-important.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/blob/main/LICENSE) [![documentation](https://img.shields.io/badge/documentation-Click%20Here-yellow.svg?style=flat-square)](https://docs.openticket.dj-dj.be) [![discord](https://img.shields.io/badge/discord-join%20our%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-3.2.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v3.2.0) [![discord.js](https://img.shields.io/badge/discord.js-v14-CB3837.svg?style=flat-square&logo=npm)]() [![license](https://img.shields.io/badge/license-GPL%203.0-important.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/blob/main/LICENSE) [![documentation](https://img.shields.io/badge/documentation-Click%20Here-yellow.svg?style=flat-square)](https://docs.openticket.dj-dj.be)
Open ticket is the most configurable open-source ticket bot for discord! Made with the newest technologies. Like: Slash commands, transcripts, multiple ticket types, buttons & dropdowns! Open ticket is the most configurable open-source ticket bot for discord! Made with the newest technologies. Like: Slash commands, transcripts, multiple ticket types, buttons & dropdowns!
Start using it now, you can do anything! Start using it now, you can do anything!
@@ -15,16 +15,18 @@ Start using it now, you can do anything!
- Sanke: for translation & new ideas - Sanke: for translation & new ideas
- Everyone that reported a bug - Everyone that reported a bug
#### And our translators! #### And our translators!
- ExothDE - Sanke#6086 (Romanian & French)
- 1x1 - Redactado#1673 (Spanish)
- Redactado - t0miiis#3022 (Czech)
- t0miiis - josuens14 (Spanish)
- josuens14 - M4#5882 (Arabic)
- M4 - ChilledBroke#9986 (Arabic)
- David. - David.#0187 (German)
- Maurizio - Maurizio#0268 (Italian)
- the_gamer#5095 (Danish)
## features ## features
- **🎉 NEW! html transcripts!**
- discord interaction buttons - discord interaction buttons
- slash & text commands - slash & text commands
- close, delete & re-open tickets - close, delete & re-open tickets
@@ -39,9 +41,6 @@ Start using it now, you can do anything!
- custom API + plugins - custom API + plugins
- unlimited tickets spread over multiple messages - unlimited tickets spread over multiple messages
- close with reason - close with reason
*comming soon*
- share transcripts
- view transcripts in html - view transcripts in html
## quick start ## quick start
@@ -52,7 +51,7 @@ Start using it now, you can do anything!
## information ## information
_v3.1.0_ _v3.2.0_
changelog: [click here](https://docs.openticket.dj-dj.be/other/changelog) changelog: [click here](https://docs.openticket.dj-dj.be/other/changelog)
+101
View File
@@ -0,0 +1,101 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
const log = bot.errorLog.log
const l = bot.language
const permsChecker = require("../core/utils/permisssionChecker")
const APIEvents = require("../core/api/modules/events")
const DISABLE = require("../core/api/api.json").disable
module.exports = () => {
bot.errorLog.log("debug","COMMANDS: loaded change.js")
if (!DISABLE.commands.text.change) client.on("messageCreate",msg => {
if (!msg.content.startsWith(config.prefix+"change")) return
if (!msg.guild) return
if (!permsChecker.command(msg.author.id,msg.guild.id)){
permsChecker.sendUserNoPerms(msg.author)
return
}
msg.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return msg.channel.send({embeds:[bot.errorLog.notInATicket]})
const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description)
const ticketId = hiddendata.data.find(d => d.key == "type").value
var newtype = msg.content.split(config.prefix+"change")[1].substring(1)
if (!newtype) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" `<type>`:\n`"+config.prefix+"change <type>`")]})
const newTicket = require("../core/utils/configParser").getTicketById(newtype)
const list = []
config.options.forEach((o) => list.push(o.id))
if (!newTicket) return bot.errorLog.invalidIdChooseFromList(list)
/**@type {String} */
var chName = msg.channel.name
const splitted = chName.split("-")
const prefix = splitted.shift()
const name = (splitted.length > 0) ? splitted.join("-") : prefix
msg.channel.setName(newTicket.channelprefix+name)
msg.channel.send({embeds:[bot.embeds.commands.changeEmbed(msg.author,newtype)]})
log("command","someone used the 'change' command",[{key:"user",value:msg.author.tag}])
log("system","ticket type changed",[{key:"user",value:msg.author.tag},{key:"ticket",value:name},{key:"newtype",value:newtype}])
APIEvents.onCommand("change",permsChecker.command(msg.author.id,msg.guild.id),msg.author,msg.channel,msg.guild,new Date())
})
})
if (!DISABLE.commands.slash.change) client.on("interactionCreate",(interaction) => {
if (!interaction.isChatInputCommand()) return
if (interaction.commandName != "change") return
if (!interaction.guild) return
if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
permsChecker.sendUserNoPerms(interaction.user)
return
}
//interaction.deferReply()
interaction.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.reply({embeds:[bot.errorLog.notInATicket]})
const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description)
const ticketId = hiddendata.data.find(d => d.key == "type").value
console.log("HELLO WORLD!! 1")
var newtype = interaction.options.getString("type",true)
if (!newtype) return interaction.reply({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" `<type>`:\n`"+config.prefix+"change <type>`")]})
console.log("HELLO WORLD!! 2")
const newTicket = require("../core/utils/configParser").getTicketById(newtype,true)
const list = []
config.options.forEach((o) => list.push(o.id))
if (!newTicket) return bot.errorLog.invalidIdChooseFromList(list)
console.log("HELLO WORLD!! 3")
/**@type {String} */
var chName = interaction.channel.name
const splitted = chName.split("-")
const prefix = splitted.shift()
const name = (splitted.length > 0) ? splitted.join("-") : prefix
console.log("HELLO WORLD!! 4")
interaction.channel.setName(newTicket.channelprefix+name)
interaction.reply({embeds:[bot.embeds.commands.changeEmbed(interaction.user,newtype)]})
console.log("HELLO WORLD!! 5")
log("command","someone used the 'change' command",[{key:"user",value:interaction.user.tag}])
log("system","ticket type changed",[{key:"user",value:interaction.user.tag},{key:"ticket",value:name},{key:"newtype",value:newtype}])
APIEvents.onCommand("change",permsChecker.command(interaction.user.id,interaction.guild.id),interaction.user,interaction.channel,interaction.guild,new Date())
})
})
}
-2
View File
@@ -21,8 +21,6 @@ module.exports = () => {
const header = config.system.ticket_channel ? l.helpMenu.header1.replace("{0}","<#"+config.system.ticket_channel+">") : l.helpMenu.header2 const header = config.system.ticket_channel ? l.helpMenu.header1.replace("{0}","<#"+config.system.ticket_channel+">") : l.helpMenu.header2
helpEmbed.setDescription(header+"`"+prefix+msgName+" <id>` ➜ _"+l.helpMenu.msgCmd+"_\n\n`"+prefix+"rename <name>` ➜ _"+l.helpMenu.renameCmd+"_\n`"+prefix+"close` ➜ _"+l.helpMenu.closeCmd+"_\n`"+prefix+"delete` ➜ _"+l.helpMenu.deleteCmd+"_\n`"+prefix+"reopen` ➜ _"+l.helpMenu.reopenCmd+"_\n\n`"+prefix+"add <user>` ➜ _"+l.helpMenu.addCmd+"_\n`"+prefix+"remove <user>` ➜ _"+l.helpMenu.removeCmd+"_") helpEmbed.setDescription(header+"`"+prefix+msgName+" <id>` ➜ _"+l.helpMenu.msgCmd+"_\n\n`"+prefix+"rename <name>` ➜ _"+l.helpMenu.renameCmd+"_\n`"+prefix+"close` ➜ _"+l.helpMenu.closeCmd+"_\n`"+prefix+"delete` ➜ _"+l.helpMenu.deleteCmd+"_\n`"+prefix+"reopen` ➜ _"+l.helpMenu.reopenCmd+"_\n\n`"+prefix+"add <user>` ➜ _"+l.helpMenu.addCmd+"_\n`"+prefix+"remove <user>` ➜ _"+l.helpMenu.removeCmd+"_")
if (config.credits) helpEmbed.setFooter({text:"Open-Ticket by DJdj Development | view on github for source code",iconURL:"https://raw.githubusercontent.com/DJj123dj/open-ticket/main/logo.png"})
var otherprefix = prefix.endsWith(" ") ? prefix.substring(0,prefix.length-1) : prefix var otherprefix = prefix.endsWith(" ") ? prefix.substring(0,prefix.length-1) : prefix
if (!DISABLE.commands.text.help) client.on("messageCreate",msg => { if (!DISABLE.commands.text.help) client.on("messageCreate",msg => {
+2 -5
View File
@@ -6,7 +6,6 @@
"prefix":"!ticket ", "prefix":"!ticket ",
"languagefile":"english", "languagefile":"english",
"credits":true,
"status":{ "status":{
"enabled":true, "enabled":true,
"type":"PLAYING", "type":"PLAYING",
@@ -22,9 +21,7 @@
"member_role":"member role (doesn't have access to tickets)", "member_role":"member role (doesn't have access to tickets)",
"closeMode":"adminonly|normal", "closeMode":"adminonly|normal",
"enable_transcript":false, "transcripts":"!!!! ALL SETTINGS FOR TRANSCRIPTS ARE LOCATED IN: transcriptconfig.json !!!!",
"enable_DM_transcript":false,
"transcript_channel":"channel id",
"showSlashcmdsInHelp":false "showSlashcmdsInHelp":false
}, },
@@ -92,7 +89,7 @@
"dropdown":false, "dropdown":false,
"enableFooter":false, "enableFooter":false,
"footer":"Open Ticket v3.1.0 - I'm a footer!", "footer":"Open Ticket v3.2.0 - I'm a footer!",
"enableThumbnail":false, "enableThumbnail":false,
"thumbnail":"https://www.example.com/catmemes/cat.png", "thumbnail":"https://www.example.com/catmemes/cat.png",
+4 -2
View File
@@ -29,7 +29,8 @@
"remove":false, "remove":false,
"rename":false, "rename":false,
"claim":false, "claim":false,
"unclaim":false "unclaim":false,
"change":false
}, },
"slash":{ "slash":{
"help":false, "help":false,
@@ -42,7 +43,8 @@
"remove":false, "remove":false,
"rename":false, "rename":false,
"claim":false, "claim":false,
"unclaim":false "unclaim":false,
"change":false
} }
}, },
"checkerjs":{ "checkerjs":{
+93 -1
View File
@@ -17,6 +17,10 @@ const ticketReopenListeners = []
const ticketAddListeners = [] const ticketAddListeners = []
const ticketRemoveListeners = [] const ticketRemoveListeners = []
const ticketClaimListeners = []
const ticketUnclaimListeners = []
const ticketChangeListeners = []
const transcriptCreationListeners = [] const transcriptCreationListeners = []
const commandListeners = [] const commandListeners = []
@@ -146,6 +150,66 @@ exports.onTicketRemove = (user,editeduser,channel,guild,date,ticketdata) => {
} }
/**
*
* @param {discord.User} user
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
* @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata
*/
exports.onTicketClaim = (user,channel,guild,date,ticketdata) => {
//system
bot.errorLog.log("api","user claimed a ticket",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}])
ticketClaimListeners.forEach((func) => {
try {
func(user,channel,guild,date,ticketdata)
}catch{}
})
}
/**
*
* @param {discord.User} user
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
* @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata
*/
exports.onTicketUnclaim = (user,channel,guild,date,ticketdata) => {
//system
bot.errorLog.log("api","user unclaimed a ticket",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}])
ticketUnclaimListeners.forEach((func) => {
try {
func(user,channel,guild,date,ticketdata)
}catch{}
})
}
/**
* @param {String} newtype
* @param {discord.User} user
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
* @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata
*/
exports.onTicketChange = (newtype,user,channel,guild,date,ticketdata) => {
//system
bot.errorLog.log("api","user changed ticket type",[{key:"newtype",value:newtype},{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}])
ticketChangeListeners.forEach((func) => {
try {
func(newtype,user,channel,guild,date,ticketdata)
}catch{}
})
}
/** /**
* *
* @param {discord.Message[]} messages * @param {discord.Message[]} messages
@@ -165,7 +229,7 @@ exports.onTranscriptCreation = (messages,channel,guild,date) => {
} }
/**@typedef {"help"|"message"|"close"|"delete"|"reopen"|"rename"|"add"|"remove"} OTCommandType */ /**@typedef {"help"|"message"|"close"|"delete"|"reopen"|"rename"|"add"|"remove"|"claim"|"unclaim"|"change"} OTCommandType */
/** /**
* *
@@ -269,6 +333,16 @@ exports.onCommand = (type,hasPerms,user,channel,guild,date) => {
* @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata * @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata
*/ */
/**
* @callback TicketTypeChangeEvent
* @param {String} newtype
* @param {discord.User} user
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
* @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:configParser.OTTicketOptions}} ticketdata
*/
/** /**
* @callback CommandEvent * @callback CommandEvent
* @param {OTCommandType} type * @param {OTCommandType} type
@@ -328,6 +402,21 @@ const onTicketRemove = (callback) => {
ticketRemoveListeners.push(callback) ticketRemoveListeners.push(callback)
} }
/**@param {TicketActionEvent} callback */
const onTicketClaim = (callback) => {
ticketClaimListeners.push(callback)
}
/**@param {TicketActionEvent} callback */
const onTicketUnclaim = (callback) => {
ticketUnclaimListeners.push(callback)
}
/**@param {TicketTypeChangeEvent} callback */
const onTicketChange = (callback) => {
ticketChangeListeners.push(callback)
}
/**@param {TranscriptCreationEvent} callback */ /**@param {TranscriptCreationEvent} callback */
const onTranscriptCreation = (callback) => { const onTranscriptCreation = (callback) => {
transcriptCreationListeners.push(callback) transcriptCreationListeners.push(callback)
@@ -355,6 +444,9 @@ exports.events = {
onTicketReopen, onTicketReopen,
onTicketAdd, onTicketAdd,
onTicketRemove, onTicketRemove,
onTicketClaim,
onTicketUnclaim,
onTicketChange,
onTranscriptCreation, onTranscriptCreation,
onCommand, onCommand,
onReactionRole, onReactionRole,
+1 -7
View File
@@ -368,7 +368,7 @@ exports.checker = async () => {
//--------------------------| //--------------------------|
//--------------------------| //--------------------------|
var configArray = ["main_color","server_id","auth_token","main_adminroles","prefix","languagefile","credits","status","system","options","messages"] var configArray = ["main_color","server_id","auth_token","main_adminroles","prefix","languagefile","status","system","options","messages"]
configArray.forEach((item) => { configArray.forEach((item) => {
if (config[item] == undefined){ if (config[item] == undefined){
throw new Error("\n\nMAIN ERROR: the item '"+item+"' doesn't exist in config.json") throw new Error("\n\nMAIN ERROR: the item '"+item+"' doesn't exist in config.json")
@@ -390,7 +390,6 @@ exports.checker = async () => {
createError("'languagefile' | invalid language, more info in the wiki") createError("'languagefile' | invalid language, more info in the wiki")
} }
checkType(config.credits,"boolean","credits")
//status: //status:
checkType(config.status.enabled,"boolean","status/enabled") checkType(config.status.enabled,"boolean","status/enabled")
if (config.status.enabled){ if (config.status.enabled){
@@ -423,11 +422,6 @@ exports.checker = async () => {
createError("'system/closeMode' | the close mode must be adminonly or normal") createError("'system/closeMode' | the close mode must be adminonly or normal")
} }
checkType(config.system.enable_transcript,"boolean","system/enable_transcript")
checkType(config.system.enable_DM_transcript,"boolean","system/enable_DM_transcript")
if (config.system.enable_transcript){
checkDiscord("channelid",config.system.transcript_channel,"system/transcript_channel")
}
checkType(config.system.showSlashcmdsInHelp,"boolean","system/showSlashcmdsInHelp") checkType(config.system.showSlashcmdsInHelp,"boolean","system/showSlashcmdsInHelp")
//options //options
+15 -5
View File
@@ -25,16 +25,26 @@ exports.closeCommandRow = new arb()
) )
.addComponents( .addComponents(
new button() new button()
.setCustomId("OTsendTranscript") .setCustomId("OTreopenTicket")
.setDisabled(false) .setDisabled(false)
.setStyle(bs.Secondary) .setStyle(bs.Success)
.setLabel(l.buttons.sendTranscript) .setLabel(l.buttons.reopen)
.setEmoji("📄") .setEmoji("✔")
)
exports.closeCommandRowDisabled = new arb()
.addComponents(
new button()
.setCustomId("OTdeleteTicket1")
.setDisabled(true)
.setStyle(bs.Danger)
.setLabel(l.buttons.delete)
.setEmoji("✖️")
) )
.addComponents( .addComponents(
new button() new button()
.setCustomId("OTreopenTicket") .setCustomId("OTreopenTicket")
.setDisabled(false) .setDisabled(true)
.setStyle(bs.Success) .setStyle(bs.Success)
.setLabel(l.buttons.reopen) .setLabel(l.buttons.reopen)
.setEmoji("✔") .setEmoji("✔")
@@ -137,3 +137,16 @@ exports.renameEmbed = (renamer,newname) => {
.setFooter({text:author.tag,iconURL:author.displayAvatarURL()}) .setFooter({text:author.tag,iconURL:author.displayAvatarURL()})
} }
} }
/**
*
* @param {discord.User} changer
* @param {String} newtype
* @returns {discord.EmbedBuilder}
*/
exports.changeEmbed = (changer,newtype) => {
return new embed()
.setTitle("🔄 "+l.commands.changeTitle.replace("{0}",newtype))
.setColor(mc)
.setFooter({text:changer.tag,iconURL:changer.displayAvatarURL()})
}
@@ -50,8 +50,8 @@ module.exports = () => {
} }
}) })
interaction.channel.send({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]})
await interaction.message.edit({components:[bot.buttons.close.openRowDisabled]}) await interaction.message.edit({components:[bot.buttons.close.openRowDisabled]})
await interaction.channel.send({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]})
await require("../../../ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete",false,true) await require("../../../ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete",false,true)
deleteTicketButtonChecker = false deleteTicketButtonChecker = false
}) })
@@ -90,8 +90,10 @@ module.exports = () => {
} }
}) })
interaction.channel.send({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]}) await interaction.message.edit({components:[bot.buttons.close.closeCommandRowDisabled]})
await require("../../../ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"deletenotranscript",false,true) await interaction.channel.send({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]})
await require("../../../ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete",false,true)
deleteTicketButtonChecker1 = false deleteTicketButtonChecker1 = false
}) })
} }
@@ -1,6 +1,5 @@
module.exports = () => { module.exports = () => {
require("./firstmsg")() require("./firstmsg")()
require("./sendTranscript")()
require("./verifyBars")() require("./verifyBars")()
//accepted //accepted
@@ -1,46 +0,0 @@
const discord = require('discord.js')
const bot = require('../../../index')
const client = bot.client
const config = bot.config
const l = bot.language
const log = bot.errorLog.log
const storage = bot.storage
const hiddendata = bot.hiddenData
const embed = discord.EmbedBuilder
const mc = config.main_color
const button = discord.ButtonBuilder
const arb = discord.ActionRowBuilder
const bs = discord.ButtonStyle
module.exports = () => {
client.on("interactionCreate",async (interaction) => {
if (!interaction.isButton()) return
if (interaction.customId != "OTsendTranscript") return
try {
interaction.deferUpdate()
} catch{}
const tsmsg = await interaction.channel.send({embeds:[bot.embeds.commands.sendTranscriptEmbed(false,interaction.channel,interaction.user)]})
const channelmessages = await interaction.channel.messages.fetch()
channelmessages.sweep((msgSweep) => {
return msgSweep.author.id == client.user.id
})
var fileattachment = await require("../../transcript").createTranscript(channelmessages,interaction.channel)
if (fileattachment == false){
log("system","internal error: transcript is not created!")
tsmsg.edit({embeds:[bot.errorLog.serverError(l.errors.somethingWentWrongTranscript)]})
return
}
try {
tsmsg.edit({embeds:[bot.embeds.commands.sendTranscriptEmbed(true,interaction.channel,interaction.user)],files:[fileattachment]})
}catch{}
})
}
+1
View File
@@ -16,6 +16,7 @@ else if (config.languagefile.startsWith("arabic")) localLanguage = require("../l
else if (config.languagefile.startsWith("spanish")) localLanguage = require("../language/spanish.json") else if (config.languagefile.startsWith("spanish")) localLanguage = require("../language/spanish.json")
else if (config.languagefile.startsWith("portuguese")) localLanguage = require("../language/portuguese.json") else if (config.languagefile.startsWith("portuguese")) localLanguage = require("../language/portuguese.json")
else if (config.languagefile.startsWith("italian")) localLanguage = require("../language/italian.json") else if (config.languagefile.startsWith("italian")) localLanguage = require("../language/italian.json")
else if (config.languagefile.startsWith("danish")) localLanguage = require("../language/danish.json")
const errorLog = async () => { const errorLog = async () => {
+21 -2
View File
@@ -32,8 +32,8 @@ module.exports = async () => {
//process.stdout.write("[status] there are "+chalk.blue("0 out of 10")+" commands ready! (this can take up to 40 seconds)") //process.stdout.write("[status] there are "+chalk.blue("0 out of 10")+" commands ready! (this can take up to 40 seconds)")
setInterval(() => { setInterval(() => {
process.stdout.cursorTo(0) process.stdout.cursorTo(0)
process.stdout.write("[status] there are "+chalk.blue(readystats+" out of 12")+" commands ready! (this can take up to 40 seconds)") process.stdout.write("[status] there are "+chalk.blue(readystats+" out of 13")+" commands ready! (this can take up to 40 seconds)")
if (readystats >= 12){ if (readystats >= 13){
const fs = require("fs") const fs = require("fs")
fs.writeFileSync("./storage/slashcmdEnabled.txt","true") fs.writeFileSync("./storage/slashcmdEnabled.txt","true")
console.log(chalk.green("\nready!")) console.log(chalk.green("\nready!"))
@@ -245,4 +245,23 @@ module.exports = async () => {
readystats++ readystats++
}) })
//category
client.application.commands.create({
name:"change",
description:"Change ticket type.",
defaultPermission:true,
type:act.ChatInput,
options:[
{
type:acot.String,
name:"type",
description:"The new ticket type.",
required:true,
choices:choices
}
]
},sid).then(() => {
readystats++
})
} }
+7 -112
View File
@@ -49,7 +49,7 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) =>
var enableTranscript = true var enableTranscript = true
var deleteRequired = false var deleteRequired = false
if (mode == "delete"){ if (mode == "delete" || mode == "deletenotranscript"){
//delete //delete
//check perms //check perms
if (!guild) return if (!guild) return
@@ -88,12 +88,6 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) =>
if (!id) return false if (!id) return false
try{
if (config.system.enable_DM_Messages){
member.send({embeds:[bot.errorLog.custom(l.messages.deletedTicketDmTitle,l.messages.deletedTicketDmDescription,":ticket:",config.main_color)]})
}
}
catch{log("system","can't send DM to member, member doesn't allow dm's")}
}) })
}else if (mode == "close"){ }else if (mode == "close"){
@@ -196,14 +190,6 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) =>
.setLabel(l.buttons.delete) .setLabel(l.buttons.delete)
.setEmoji("✖️") .setEmoji("✖️")
) )
.addComponents(
new discord.ButtonBuilder()
.setCustomId("OTsendTranscript")
.setDisabled(false)
.setStyle(discord.ButtonStyle.Secondary)
.setLabel(l.buttons.sendTranscript)
.setEmoji("📄")
)
.addComponents( .addComponents(
new discord.ButtonBuilder() new discord.ButtonBuilder()
.setCustomId("OTreopenTicket") .setCustomId("OTreopenTicket")
@@ -237,117 +223,26 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) =>
if (!id) return false if (!id) return false
try{
if (config.system.enable_DM_Messages){
member.send({embeds:[bot.errorLog.custom(l.messages.closedTicketDmTitle,l.messages.closedTicketDmDescription+"\n\n**reason:** "+newReason,":ticket:",config.main_color)]})
}
}
catch{log("system","can't send DM to member, member doesn't allow dm's")}
}) })
}else if (mode == "deletenotranscript"){
//delete with no transcript
//check perms
if (!guild) return
if (!permsChecker.command(user.id,guild.id)){
permsChecker.sendUserNoPerms(user)
return
}
//start delete proccess
enableTranscript = false
deleteRequired = true
if (!nomessage){
await channel.send({content:"**"+l.messages.gettingdeleted+"**"})
}
log("system","deleted a ticket",[{key:"user",value:user.tag},{key:"ticket",value:channel.name}])
if (!isDatabaseError) storage.set("ticketStorage",getuserID,Number(storage.get("ticketStorage",getuserID)) - 1)
//getID & send DM & send api event
await channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false
const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description)
const ticketId = hiddendata.data.find(d => d.key == "type").value
const ticketData = require("../utils/configParser").getTicketById(ticketId,true)
require("../api/modules/events").onTicketDelete(user,channel,guild,new Date(),{name:channel.name,status:"deleted",ticketOptions:ticketData})
const id = hiddendata.data.find(d => d.key == "openerid").value
if (!id) return false
try{
if (config.system.enable_DM_Messages){
member.send({embeds:[bot.errorLog.custom(l.messages.deletedTicketDmTitle,l.messages.deletedTicketDmDescription,":ticket:",config.main_color)]})
}
}
catch{log("system","can't send DM to member, member doesn't allow dm's")}
})
} }
const transcriptHandler = async () => { const transcriptHandler = async () => {
if (enableTranscript == true && mode != "deletenotranscript"){ if (!bot.tsconfig.sendTranscripts.enableChannel && !bot.tsconfig.sendTranscripts.enableDM) return false
//transcript messages
const transcriptReason = (mode == "close") ? "**"+l.messages.reason+":** "+newReason : "**"+l.messages.reason+":** "+l.messages.none
const closedByPrefix = (mode.startsWith("delete")) ? l.messages.deletedby : l.messages.closedby
if (config.system.enable_transcript || config.system.enable_DM_transcript){ const APIEvents = require("../api/modules/events")
const channelmessages = await channel.messages.fetch({cache:true}) const messages = await channel.messages.fetch({cache:true})
//remove ot bot from transcript await require("../transcriptSystem/manager")(messages,guild,channel,user,reason)
channelmessages.sweep((msgSweep) => {return msgSweep.author.id == client.user.id}) APIEvents.onTranscriptCreation(messages,channel,guild,new Date())
var fileattachment = await require("../transcript").createTranscript(channelmessages,channel)
if (fileattachment == false){log("system","internal error: transcript is not created!");return}
}
if (config.system.enable_transcript && !require("../api/api.json").disable.transcripts.server){
const transcriptEmbed = new discord.EmbedBuilder()
.setColor(config.main_color)
.setTitle("📄 "+l.messages.newTranscriptTitle)
.setDescription(transcriptReason)
.setFooter({text:closedByPrefix+": "+user.tag+" | ticket: "+channelname,iconURL:user.displayAvatarURL()})
guild.channels.cache.find(c => c.id == config.system.transcript_channel).send({
embeds:[transcriptEmbed],
files:[fileattachment]
})
}
if (config.system.enable_DM_transcript && !require("../api/api.json").disable.transcripts.dm){
const transcriptEmbed = new discord.EmbedBuilder()
.setColor(config.main_color)
.setTitle("📄 "+l.messages.newTranscriptTitle)
.setDescription(transcriptReason)
.setFooter({text:closedByPrefix+": "+user.tag+" | ticket: "+channelname,iconURL:user.displayAvatarURL()})
if (!isDatabaseError) ticketOpener.send({
embeds:[transcriptEmbed],
files:[fileattachment]
})
}
}
} }
const deleteHandler = async () => { const deleteHandler = async () => {
if (deleteRequired){ if (deleteRequired){
//const timer = () => {return new Promise((resolve,reject) => {
// setTimeout(() => {resolve(true)},7000)
//})}
//await timer()
pendingDelete.shift() pendingDelete.shift()
await channel.delete() await channel.delete()
//setTimeout(async () => {
// pendingDelete.shift()
// await channel.delete()
//},6000)
} }
} }
await transcriptHandler() if (mode == "delete" || mode == "deletenotranscript") await transcriptHandler()
deleteHandler() deleteHandler()
} }
+1 -1
View File
@@ -66,7 +66,7 @@ module.exports = () => {
if (storage.get("ticketStorage",interaction.member.id) == null || storage.get("ticketStorage",interaction.member.id) == "false"|| Number(storage.get("ticketStorage",interaction.member.id)) < config.system.max_allowed_tickets){ if (storage.get("ticketStorage",interaction.member.id) == null || storage.get("ticketStorage",interaction.member.id) == "false"|| Number(storage.get("ticketStorage",interaction.member.id)) < config.system.max_allowed_tickets){
try{ try{
if (config.system.enable_DM_Messages){ if (currentTicketOptions.enableDmOnOpen){
interaction.member.send({embeds:[bot.errorLog.custom(l.messages.newTicketDmTitle,currentTicketOptions.message,":ticket:",config.main_color)]}) interaction.member.send({embeds:[bot.errorLog.custom(l.messages.newTicketDmTitle,currentTicketOptions.message,":ticket:",config.main_color)]})
} }
} }
-75
View File
@@ -1,75 +0,0 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
const l = bot.language
/** @param {discord.TextBasedChannel} channel @returns {Promise<{ticketname:String,ticketopener:{discordjsuser:discord.User,name:String,id:String}>} */
const getUserInfo = (channel) => {
return new Promise((promiseresolve,reject) => {
//getID
var result = {
ticketopener:{
discordjsuser:"",
id:"/",
name:"/"
},
ticketname:"/"
}
channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false
const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description)
const ticketId = hiddendata.data.find(d => d.key == "type")
const id = hiddendata.data.find(d => d.key == "openerid").value
result.ticketopener.id = id
const ticketopener = client.users.cache.find(u => u.id == id)
const name = ticketopener.tag
const channelname = channel.name
promiseresolve({ticketname:channelname,ticketopener:{discordjsuser:ticketopener,name:name,id:id}})
})
})
}
/**
*
* @param {discord.Message[]} messagecollection
* @param {discord.Channel} channel
* @returns new `discord.attachmentBuilder`
*/
exports.createTranscript = async (messagecollection,channel) => {
const ticketuserdata = await getUserInfo(channel)
require("./api/modules/events").onTranscriptCreation(messagecollection,channel,channel.guild,new Date())
try {
const cd = new Date()
const months = ["January","February","March","April","May","June","July","August","September","October","November","December"]
const dateString = cd.getDate()+" "+months[cd.getMonth()-1]+" "+cd.getFullYear()+" - "+cd.getHours()+":"+cd.getMinutes()+":"+cd.getSeconds()
const filearray = ["open ticket transcript:\ntranscript creation: "+dateString+"\nticket name: "+ticketuserdata.ticketname+"\nticket opener: "+ticketuserdata.ticketopener.name,"\nTRANSCRIPT START:"]
messagecollection.reverse()
messagecollection.forEach((msg) => {
const timestamp = new Date(msg.createdTimestamp)
if (msg.content){var content = msg.content}else{var content = "*empty message*"}
const msgstats = "files: "+msg.attachments.size+", embeds: "+msg.embeds.length
filearray.push("["+timestamp.getDate()+"/"+timestamp.getMonth()+"/"+timestamp.getFullYear()+", "+timestamp.getHours()+":"+timestamp.getMinutes()+":"+timestamp.getSeconds()+"|"+msg.author.tag+"] ["+msgstats+"]\n"+content+"\n")
})
if (filearray.length < 2) filearray.push("transcript is empty")
const filestring = filearray.join("\n")
const filebuff = Buffer.from(filestring,"utf-8")
return new discord.AttachmentBuilder(filebuff,{name:"transcript_"+ticketuserdata.ticketname+".txt",description:"An Open Ticket transcript"})
}catch(err){
console.log("[error] "+err)
return false
}
}
@@ -0,0 +1,119 @@
const discord = require('discord.js')
const bot = require("../../../index")
const tsconfig = bot.tsconfig
const tsembeds = require("../embeds")
const tsdb = require("../tsdb")
const otversion = require("../../../package.json").version
const version = require("../info.json").version
/**@typedef {{style:{enableCustomBackground:Boolean, backgroundModus:"color"|"image", backgroundData:String, titleColor:String}, bot:{name:String, id:Number, pfp:String}, ticket:{creatorname:String, creatorid:Number, closedtime:Number, openedtime:Number}}} OThtsDataOption */
/**
*
* @param {discord.Guild} guild
* @param {discord.Channel} channel
* @param {discord.User} user
* @param {discord.Message[]} messagesInv
* @param {OThtsDataOption} data
*/
exports.compile = (guild,channel,user,messagesInv,data) => {
const messages = messagesInv.reverse()
var invisibleMessages = 0
const rawfiles = messages.filter((m) => Array.from(m.attachments).length > 0)
var fileAmount = 0
rawfiles.forEach((msg) => {
fileAmount = fileAmount + Array.from(msg.attachments).length
})
const messagesArray = []
messages.forEach((msg) => {
if (msg.content || msg.embeds.length > 0 || msg.attachments.toJSON().length > 0){
const embedArray = []
const fileArray = []
msg.attachments.forEach((file) => {
fileArray.push({
name:file.name,
type:file.contentType,
size:file.size.toString()+" bytes",
url:file.url
})
})
msg.embeds.forEach((embed) => {
if (embed.description){
var desc = bot.hiddenData.removeHiddenData(embed.description).description
}else{var desc = false}
embedArray.push({
title:embed.title || false,
description:desc,
authorimg:((embed.author && embed.author.iconURL) ? embed.author.iconURL : false),
authortext:(embed.author ? embed.author.name : false),
footerimg:((embed.footer && embed.footer.iconURL) ? embed.footer.iconURL : false),
footertext:(embed.footer ? embed.footer.text : false),
color:embed.hexColor,
image:((embed.image && embed.image.url) ? embed.image.url : false),
thumbnail:((embed.thumbnail && embed.thumbnail.url) ? embed.thumbnail.url : false),
url:(embed.url ? embed.url : false)
})
})
messagesArray.push({
author:{
name:msg.author.tag,
id:Number(msg.author.id),
color:msg.author.hexAccentColor || "#ffffff",
pfp:msg.author.displayAvatarURL()
},
content:msg.content || "",
timestamp:msg.createdTimestamp,
embeds:embedArray,
files:fileArray
})
}else {invisibleMessages++}
})
const result = {
version,otversion,
style:{
backgroundData:data.style.backgroundData || "",
backgroundModus:data.style.backgroundModus || "",
enableCustomBackground:data.style.enableCustomBackground || false,
titleColor:data.style.titleColor || "#F8BA00"
},
bot:{
name:data.bot.name || "Open Ticket",
id:Number(data.bot.id) || 0,
pfp:data.bot.pfp || "dj-dj.be/wp-content/uploads/2022/07/profielfoto-blauw-wit.png?size=128"
},
ticket:{
name:channel.name,
id:Number(channel.id),
guildname:guild.name,
guildid:Number(guild.id),
creatorname:data.ticket.creatorname,
creatorid:Number(data.ticket.creatorid),
closedbyname:user.tag,
closedbyid:Number(user.id),
closedtime:data.ticket.closedtime,
openedtime:data.ticket.openedtime,
messages:Array.from(messages).length-invisibleMessages,
files:fileAmount
},
messages:messagesArray
}
return result
}
@@ -0,0 +1,29 @@
const axios = require("axios").default
const discord = require('discord.js')
const bot = require("../../../index")
const tsconfig = bot.tsconfig
const tsembeds = require("../embeds")
const tsdb = require("../tsdb")
/**@typedef {{status:"success"|"error", id:String, time:Number, estimated:{lastdump: Number, processtime:Number}, transcriptstatus:{value:2, data:{fetchedmsgs:true, uploaded:true, inqueue:true, processed:false, waiting:false, available:false}}}} OTuploadResponse */
/**
* @param {Object} json
* @returns {Promise<OTuploadResponse|false>}
*/
exports.upload = async (json) => {
return new Promise(async (resolve,reject) => {
const data = encodeURIComponent(JSON.stringify(json))
try {
const res = await axios.get("https://api.transcripts.dj-dj.be/upload?auth=openticketTRANSCRIPT1234&version=1.0.0&data="+data)
if (res.status != 200) resolve(false)
resolve(res.data)
}catch{
console.log("failed transcript upload!")
resolve(false)
}
})
}
@@ -0,0 +1,67 @@
{
"version":"1.0.0",
"otversion":"3.2.0",
"style":{
"enableCustomBackground":false,
"backgroundModus":"color OR image",
"backgroundData":"#ffffff OR https://www.example.com/image.png",
"titleColor":"#ffffff"
},
"bot":{
"name":"DJdj Support Bot",
"id":12345678910,
"pfp":"https://www.example.com/image.png"
},
"ticket":{
"name":"support-DJj123dj",
"id":12345678910,
"guildname":"DJdj Development",
"guildid":12345678910,
"creatorname":"DJj123dj#1706",
"creatorid":12345678910,
"closedbyname":"DJj123dj#1706",
"closedbyid":12345678910,
"closedtime":12345678910,
"openedtime":12345678910,
"messages":1,
"files":1
},
"messages":[
{
"author":{
"name":"DJj123dj#1706",
"id":12345678910,
"color":"#ffffff",
"pfp":"https://www.example.com/image.png"
},
"content":"string or FALSE",
"timestamp":12345678910,
"embeds":[
{
"title":"string or FALSE",
"description":"string or FALSE",
"authorimg":"https://www.example.com/image.png or FALSE",
"authortext":"string or FALSE",
"footerimg":"https://www.example.com/image.png or FALSE",
"footertext":"string or FALSE",
"color":"#ffffff",
"image":"https://www.example.com/image.png or FALSE",
"thumbnail":"https://www.example.com/image.png or FALSE",
"url":"https://www.example.com/image.png or FALSE"
}
],
"files":[
{
"name":"image.png",
"type":"PNG",
"size":"1MB",
"url":"https://www.example.com/image.png"
}
]
}
]
}
+74
View File
@@ -0,0 +1,74 @@
const discord = require('discord.js')
const bot = require('../../index')
const client = bot.client
const config = bot.config
const log = bot.errorLog.log
const l = bot.language
const storage = bot.storage
const tsconfig = bot.tsconfig
/**
*
* @param {String} name
* @param {String} id
* @param {Number} rawprocesstime milliseconds
* @param {discord.User} user
*/
exports.beingprocessed = (name,id,rawprocesstime,user) => {
const newtime = rawprocesstime
const processtime = "<t:"+newtime.getTime().toString().substring(0,newtime.getTime().toString().length-3)+":R>"
const embed = new discord.EmbedBuilder()
.setTitle("🧾 Transcript")
.setColor(config.main_color)
.setAuthor({name:user.tag,iconURL:user.displayAvatarURL()})
.setFooter({text:name})
.setDescription("`This transcript is being processed...`\nPlease wait!\n\nEstimated time: "+processtime)
return embed
}
/**
*
* @param {String} name
* @param {String} id
* @param {String} url
* @param {discord.User} user
*/
exports.tsready = (name,id,url,user) => {
const embed = new discord.EmbedBuilder()
.setTitle("🧾 Transcript")
.setColor(config.main_color)
.setAuthor({name:user.tag,iconURL:user.displayAvatarURL()})
.setFooter({text:name})
.setURL(url)
.setDescription("\nThe transcript is available [here]("+url+")\n")
return embed
}
/**
*
* @param {String} name
* @param {String} id
* @param {discord.User} user
* @param {undefined|String} err
*/
exports.tserror = (name,id,user,err) => {
const embed = new discord.EmbedBuilder()
.setTitle("❌ Transcript")
.setColor(discord.Colors.Red)
.setAuthor({name:user.tag,iconURL:user.displayAvatarURL()})
.setFooter({text:name})
const errDesc = (typeof err == "string") ? "\n"+err : ""
embed.setDescription("Something went wrong while creating the HTML transcript.\n\n[possible reasons](https://docs.openticket.dj-dj.be/the-system/transcripts/transcript-errors)"+errDesc)
return embed
}
+3
View File
@@ -0,0 +1,3 @@
{
"version":"1.0.0"
}
+139
View File
@@ -0,0 +1,139 @@
const discord = require('discord.js')
const bot = require('../../index')
const client = bot.client
const config = bot.config
const log = bot.errorLog.log
const l = bot.language
const storage = bot.storage
const tsconfig = bot.tsconfig
const tsembeds = require("./embeds")
const tsdb = require("./tsdb")
const checkAvailability = async () => {
const axios = require("axios").default
const res = await axios.get("https://transcripts.dj-dj.be/status.txt")
if (!res || !(res.status == 200) || !res.data) return false
if ((res.data == "online") || (res.data == "1") || (res.data == "true")) return true
else return false
}
/**
*
* @param {discord.Message[]} messages
* @param {discord.Guild} guild
* @param {discord.TextChannel} channel
* @param {discord.User} user
* @param {String|false} reason
*/
module.exports = async (messages,guild,channel,user,reason) => {
require("../api/modules/events").onTranscriptCreation(messages,channel,guild,new Date())
const msglist = await channel.messages.fetchPinned()
const chName = channel.name
const chId = channel.id
/**@param {discord.Collection<string, discord.Message<true>>} msglist*/
const asyncmanager = async (msglist) => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false
const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description)
const ticketId = hiddendata.data.find(d => d.key == "type")
const id = hiddendata.data.find(d => d.key == "openerid").value
const opentime = new Date(Number(hiddendata.data.find(d => d.key == "createdms").value))
const ticketopener = client.users.cache.find(u => u.id == id)
const JSONDATA = require("./communication/compileJson").compile(guild,channel,user,messages,{
style:{
titleColor:tsconfig.style.titleColor,
enableCustomBackground:tsconfig.style.background.enableCustomBackground,
backgroundModus:tsconfig.style.background.backgroundModus,
backgroundData:tsconfig.style.background.backgroundData
},
bot:{
name:client.user.username,
id:client.user.id,
pfp:client.user.displayAvatarURL()
},
ticket:{
creatorid:ticketopener.id,
creatorname:ticketopener.tag,
openedtime:opentime.getTime(),
closedtime:new Date().getTime()
}
})
if (!await checkAvailability()){
const attachment = await require("./oldTranscript").createTranscript(messages,channel)
const errembed = tsembeds.tserror(chName,chId,user)
if (tsconfig.sendTranscripts.enableChannel){
/**@type {discord.TextChannel|undefined} */
const tc = guild.channels.cache.find((c) => c.id == tsconfig.sendTranscripts.channel)
if (!tc) return
tc.send({embeds:[errembed],files:[attachment]})
}
return
}
const TSdata = await require("./communication/index").upload(JSONDATA)
if (!TSdata) return false
if (TSdata.status == "success"){
const url = "https://transcripts.dj-dj.be/t/"+TSdata.time+"_"+TSdata.id+".html"
//calculate estimated time
const lastDumpTime = (new Date(TSdata.estimated.lastdump).getTime())
const dumpLoopTime = 15000
const nextDump = new Date(lastDumpTime+dumpLoopTime)
const processtime = TSdata.estimated.processtime+6000 //6sec extra time for overflow
const finaltime = new Date(nextDump.getTime()+processtime)
const duration = finaltime.getTime()-new Date().getTime()
//waiting
if (tsconfig.sendTranscripts.enableChannel){
/**@type {discord.TextChannel|undefined} */
const tc = guild.channels.cache.find((c) => c.id == tsconfig.sendTranscripts.channel)
if (!tc) return
const embed = tsembeds.beingprocessed(chName,chId,finaltime,user)
var msg = await tc.send({embeds:[embed]})
}else {var msg = false}
//ready
setTimeout(() => {
if (msg){
msg.edit({embeds:[tsembeds.tsready(chName,chId,url,user)]})
}
if (tsconfig.sendTranscripts.enableDM){
if (!user) return
const embed = tsembeds.tsready(chName,chId,url,user)
try {
user.send({embeds:[embed]})
}catch{}
}
},duration)
}else{
const attachment = await require("./oldTranscript").createTranscript(messages,channel)
const errembed = tsembeds.tserror(chName,chId,user,"`error type: transcript API error`")
if (tsconfig.sendTranscripts.enableChannel){
/**@type {discord.TextChannel|undefined} */
const tc = guild.channels.cache.find((c) => c.id == tsconfig.sendTranscripts.channel)
if (!tc) return
tc.send({embeds:[errembed],files:[attachment]})
}
}
}
asyncmanager(msglist)
}
+38
View File
@@ -0,0 +1,38 @@
const discord = require('discord.js')
const bot = require('../../index')
const client = bot.client
const config = bot.config
const l = bot.language
/**
*
* @param {discord.Message[]} messagecollection
* @returns new `discord.attachmentBuilder`
*/
exports.createTranscript = async (messagecollection) => {
try {
const cd = new Date()
const months = ["January","February","March","April","May","June","July","August","September","October","November","December"]
const dateString = cd.getDate()+" "+months[cd.getMonth()-1]+" "+cd.getFullYear()+" - "+cd.getHours()+":"+cd.getMinutes()+":"+cd.getSeconds()
const filearray = ["BACKUP TRANSCRIPT:\n"]
messagecollection.reverse()
messagecollection.forEach((msg) => {
const timestamp = new Date(msg.createdTimestamp)
if (msg.content){var content = msg.content}else{var content = "*empty message*"}
const msgstats = "files: "+msg.attachments.size+", embeds: "+msg.embeds.length
filearray.push("["+timestamp.getDate()+"/"+timestamp.getMonth()+"/"+timestamp.getFullYear()+", "+timestamp.getHours()+":"+timestamp.getMinutes()+":"+timestamp.getSeconds()+"|"+msg.author.tag+"] ["+msgstats+"]\n"+content+"\n")
})
if (filearray.length < 2) filearray.push("transcript is empty")
const filestring = filearray.join("\n")
const filebuff = Buffer.from(filestring,"utf-8")
return new discord.AttachmentBuilder(filebuff,{name:"backuptranscript.txt",description:"Open Ticket transcript"})
}catch{
return false
}
}
+71
View File
@@ -0,0 +1,71 @@
const fs = require("fs")
const location = "./storage/tsdatabase.json"
/**@returns {[{category:String, key:String, value:String}]}*/
function getData(){
if (fs.existsSync(location)){
return JSON.parse(fs.readFileSync(location).toString())
}else{
fs.writeFileSync(location,"[]")
return []
}
}
/**@param {[{category:String, key:String, value:String}]} data*/
function setData(data){
fs.writeFileSync(location,JSON.stringify(data,null,"\t"))
}
exports.set = (category,key,value) => {
const currentData = getData()
const exists = currentData.find((d) => (d.category == category) && (d.key == key)) ? true : false
var newData = []
if (exists){
currentData.forEach((d,i) => {
if (d.category == category && d.key == key){
newData.push({category,key,value})
}else{
newData.push(d)
}
})
}else{
currentData.push({category,key,value})
newData = currentData
}
setData(newData)
return exists
}
/**
* @param {String} category
* @param {String} key
* @returns {String|false}
*/
exports.get = (category,key) => {
const currentData = getData()
const tempresult = currentData.find((d) => (d.category == category) && (d.key == key))
const result = tempresult ? tempresult.value : false
return result
}
/**
* @param {String} category
* @param {String} key
* @param {String} value
*/
exports.delete = (category,key) => {
const currentData = getData()
const exists = currentData.find((d) => (d.category == category) && (d.key == key)) ? true : false
var newData = []
if (exists){
currentData.forEach((d,i) => {
if (!(d.category == category && d.key == key)){
newData.push(d)
}
})
}else{
newData = currentData
}
setData(newData)
return exists
}
+3
View File
@@ -35,7 +35,10 @@ exports.createEmbed = (id) => {
const embed = new discord.EmbedBuilder() const embed = new discord.EmbedBuilder()
.setTitle(data.name) .setTitle(data.name)
if (data.enableFooter) embed.setFooter({text:data.footer}) if (data.enableFooter) embed.setFooter({text:data.footer})
try {
if (data.enableThumbnail) embed.setThumbnail(data.thumbnail) if (data.enableThumbnail) embed.setThumbnail(data.thumbnail)
}catch{bot.errorLog.log("info","THUMBNAIL FAILED TO LOAD, probably invalid url!")}
if (data.enableCustomColor){ if (data.enableCustomColor){
embed.setColor(data.color) embed.setColor(data.color)
+6
View File
@@ -69,8 +69,13 @@ const language = require("./core/languageManager").language
exports.language = language exports.language = language
if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded language") if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded language")
const config = tempconfig const config = tempconfig
exports.config = config exports.config = config
const tsconfig = require("./transcriptconfig.json")
exports.tsconfig = tsconfig
if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded config") if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded config")
exports.storage = require('./core/dynamicdatabase/storage') exports.storage = require('./core/dynamicdatabase/storage')
if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded storage") if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded storage")
@@ -211,6 +216,7 @@ if (process.argv[2] && process.argv[2].startsWith("slash")){
require("./commands/reopen")() require("./commands/reopen")()
require("./commands/claim")() require("./commands/claim")()
require("./commands/unclaim")() require("./commands/unclaim")()
require("./commands/change")()
this.errorLog.log("debug","LOADING CORE") this.errorLog.log("debug","LOADING CORE")
//core //core
+83
View File
@@ -0,0 +1,83 @@
{
"errors":{
"missingArgsTitle":"Ugyldige argumenter",
"missingArgsDescription":"Manglende argumenter",
"noPermsTitle":"Ingen adgang",
"noPermsDescription":"Du har ikke adgang til denne kommando",
"noPermsDelete":"Kun administrators kan slette tickets",
"chooseFromListTitle":"Ugyldig ID",
"chooseFromListDescription":"Vælg et ID nedenunder",
"boterror":"Bot Fejl!",
"notInTicketTitle":"Du er ikke i en ticket!",
"notInTicketDescription":"Denne kommando fungere kun i tickets!",
"ticketDoesntExist":"Denne ticket eksistere ikke mere!",
"roleDoesntExist":"Denne rolle eksistere ikke mere!",
"anotherOption":"Dette er ikke en ticket, men noget andet!",
"maxAmountTitle":"For mange tickets er blevet oprettet!",
"maxAmountDescription":"Du har for mange tickets åbne!\nSå luk dem hvis du gerne vil oprette nye!",
"somethingWentWrong":"**Noget gik galt**\nKontakt en udvikler!",
"somethingWentWrongTranscript":"Noget gik galt med transcript!**\nKontakt en udvikler!"
},
"commands":{
"userAddedTitle":"Tilføjer {0} til denne ticket!",
"userRemovedTitle":"Fjernet {0} fra denne ticket!",
"renameTitle":"Ændret navnet til{0}!",
"closeTitle":"Closed this ticket!",
"deleteTitle":"Fjerner ticketen",
"reopenTitle":"Genåbnede denne ticket",
"claimTitle":"Denne ticket er blevet taget af {0}",
"unclaimTitle":"Denne ticket er nu tilgængelig!",
"ticketWarning":"Emebeddet er i beskeden nedenunder",
"maxTicketWarning":"**Fejl:** _Du kan kun oprettre {0} ticket adgangen!_"
},
"helpMenu":{
"title":"Tilgængelig kommandoer:",
"header1":"**Gå til {0} For at oprette en ticket!**\n\n",
"header2":"**Skriv kommandoen `/new` eller `/ticket` for at oprette en ticket!**\n\n",
"msgCmd":"Lav en embed med knapper (admins kun)",
"renameCmd":"Ændre navnet (ingen mellemrum)",
"closeCmd":"Luk denne ticket",
"deleteCmd":"Fjern denne ticket",
"addCmd":"Tilføj en person til ticketen",
"removeCmd":"Fjern en person fra ticketen",
"reopenCmd":"Genåben en ticket efter den har været lukket"
},
"buttons":{
"close":"Luk ticket",
"delete":"Fjern ticket",
"reopen":"Genåben ticket",
"sendTranscript":"Transcript",
"closeWithReason":"Luk med grundlag"
},
"messages":{
"reopenTitle":"Genåbener denne ticket",
"reopenDescription":"Du kan nu skrive igen",
"closedTitle":"Lukker ticketen!",
"closedDescription":"Kun administrators kan skrive lige nu!\n\n*Klik på knappen nedenunder for at slette eller genåbne ticketen!*",
"createdTitle":"Ticket oprettet!",
"createdDescription":"Din ticket er oprettet!",
"newTicketDmTitle":"Ny Ticket!",
"closedTicketDmTitle":"Ticket Lukket!",
"deletedTicketDmTitle":"Ticket Fjernet!",
"closedTicketDmDescription":"Din ticket er blevet lukket!",
"deletedTicketDmDescription":"Din ticket er blevet fjernet!",
"reopenTicketDmTitle":"Ticket Genåbnet!",
"reopenTicketDmDescription":"Din ticket er blevet genåbent!",
"newTranscriptTitle":" En ny transcript er tilføjet!",
"hereIsTheTranscript":"Følgende transcript:",
"chooseCategory":"Vælg en kategori:",
"gettingdeleted":"Ticketen slettes..",
"none":"Ingen",
"reason":"Grundlag",
"deletedby":"Fjernet af",
"closedby":"Lukket af",
"modalreason":"Hvad er grundlaget for lukkens af denne ticket?",
"chooseATicket": "Vælg en ticket"
}
}
+1
View File
@@ -27,6 +27,7 @@
"reopenTitle":"Re-Opened this ticket!", "reopenTitle":"Re-Opened this ticket!",
"claimTitle":"This ticket is now claimed to {0}", "claimTitle":"This ticket is now claimed to {0}",
"unclaimTitle":"This ticket isn't claimed anymore!", "unclaimTitle":"This ticket isn't claimed anymore!",
"changeTitle":"Changed ticket type to {0}!",
"ticketWarning":"The embed is in the message below!", "ticketWarning":"The embed is in the message below!",
"maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_" "maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_"
+2 -3
View File
@@ -69,9 +69,8 @@
"deletedTicketDmTitle":"Ticket löschen!", "deletedTicketDmTitle":"Ticket löschen!",
"closedTicketDmDescription":"Ihr Ticket ist geschlossen!", "closedTicketDmDescription":"Ihr Ticket ist geschlossen!",
"deletedTicketDmDescription":"Ihr Ticket ist gelöscht!", "deletedTicketDmDescription":"Ihr Ticket ist gelöscht!",
"newTranscriptTitle":"Eine neue Transscript finden Sie hier!", "newTranscriptTitle":"Eine neue Transcript finden Sie hier!",
"newTranscriptDescription":"Die Abschrift finden Sie in der obigen Textdatei!", "hereIsTheTranscript":"Hier ist das Transcript:",
"hereIsTheTranscript":"Hier ist das Transscript:",
"chooseCategory":"Wähle eine Kategorie:", "chooseCategory":"Wähle eine Kategorie:",
+17 -6
View File
@@ -114,9 +114,9 @@
"it":"Rinomina il canale di un ticket." "it":"Rinomina il canale di un ticket."
}, },
"claim":{ "claim":{
"en-GB":"", "en-GB":"Claim a ticket.",
"en-US":"", "en-US":"Claim a ticket.",
"nl":"", "nl":"Claim een ticket.",
"ro":" ", "ro":" ",
"de":" ", "de":" ",
"cs":" ", "cs":" ",
@@ -125,9 +125,20 @@
"it":" " "it":" "
}, },
"unclaim":{ "unclaim":{
"en-GB":"", "en-GB":"Un-claim a ticket.",
"en-US":"", "en-US":"Un-claim a ticket.",
"nl":"", "nl":"Ontclaim een ticket.",
"ro":" ",
"de":" ",
"cs":" ",
"fr":" ",
"es-ES":" ",
"it":" "
},
"category":{
"en-GB":"Change ticket type.",
"en-US":"Change ticket type.",
"nl":"Verander ticket type.",
"ro":" ", "ro":" ",
"de":" ", "de":" ",
"cs":" ", "cs":" ",
+2 -4
View File
@@ -1,6 +1,6 @@
{ {
"name": "open-ticket", "name": "open-ticket",
"version": "3.1.0", "version": "3.2.0",
"description": "This is an open-source discord ticket bot, you can configure it and it comes with cool features like a transcript.", "description": "This is an open-source discord ticket bot, you can configure it and it comes with cool features like a transcript.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -16,9 +16,7 @@
"axios": "^0.27.2", "axios": "^0.27.2",
"chalk": "^5.0.1", "chalk": "^5.0.1",
"discord.js": "^14.7.1", "discord.js": "^14.7.1",
"express": "^4.17.1", "node": "^16.10.0"
"node": "^16.10.0",
"node-localstorage": "^2.2.1"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
+17
View File
@@ -0,0 +1,17 @@
{
"sendTranscripts":{
"enableChannel":false,
"channel":"transcript channel id",
"enableDM":false
},
"style":{
"titleColor":"#F8BA00",
"background":{
"enableCustomBackground":false,
"backgroundModus":"color OR image",
"backgroundData":"#abc123 OR https://www.example.com/image.png"
}
}
}