@@ -10,6 +10,8 @@ devConfig5.json
|
|||||||
openticketdebug.txt
|
openticketdebug.txt
|
||||||
developerChangelog.md
|
developerChangelog.md
|
||||||
storage/dynamicDB/
|
storage/dynamicDB/
|
||||||
|
storage/slashcmdEnabled.txt
|
||||||
|
storage/database.json
|
||||||
storage/.DS_Store
|
storage/.DS_Store
|
||||||
.vscode/
|
.vscode/
|
||||||
livestatus.json
|
livestatus.json
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Open Ticket
|
# Open Ticket
|
||||||
[](https://discord.com/invite/26vT9wt3n3) [](https://github.com/DJj123dj/open-ticket/releases/tag/v3.0.1) []() [](https://github.com/DJj123dj/open-ticket/blob/main/LICENSE) [](https://docs.openticket.dj-dj.be)
|
[](https://discord.com/invite/26vT9wt3n3) [](https://github.com/DJj123dj/open-ticket/releases/tag/v3.1.0) []() [](https://github.com/DJj123dj/open-ticket/blob/main/LICENSE) [](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!
|
||||||
@@ -52,7 +52,7 @@ Start using it now, you can do anything!
|
|||||||
|
|
||||||
## information
|
## information
|
||||||
|
|
||||||
_v3.0.1_
|
_v3.1.0_
|
||||||
|
|
||||||
changelog: [click here](https://docs.openticket.dj-dj.be/other/changelog)
|
changelog: [click here](https://docs.openticket.dj-dj.be/other/changelog)
|
||||||
|
|
||||||
|
|||||||
+18
-2
@@ -92,7 +92,7 @@
|
|||||||
"dropdown":false,
|
"dropdown":false,
|
||||||
|
|
||||||
"enableFooter":false,
|
"enableFooter":false,
|
||||||
"footer":"Open Ticket v3.0.1 - I'm a footer!",
|
"footer":"Open Ticket v3.1.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",
|
||||||
@@ -101,8 +101,24 @@
|
|||||||
"color":"#ffffff",
|
"color":"#ffffff",
|
||||||
|
|
||||||
"options":["general","apply"],
|
"options":["general","apply"],
|
||||||
|
|
||||||
|
"other":{
|
||||||
"enableTicketExplaination":true,
|
"enableTicketExplaination":true,
|
||||||
"enableMaxTicketsWarning":true
|
"enableMaxTicketsWarning":true,
|
||||||
|
|
||||||
|
"customDropdownPlaceholder":{
|
||||||
|
"enable":false,
|
||||||
|
"text":"Choose a ticket"
|
||||||
|
},
|
||||||
|
"customCategoryText":{
|
||||||
|
"enable":false,
|
||||||
|
"text":"choose a category:"
|
||||||
|
},
|
||||||
|
"embedTitleURL":{
|
||||||
|
"enable":false,
|
||||||
|
"url":"https://www.dj-dj.be/projects/open-ticket"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
+36
-4
@@ -311,10 +311,6 @@ exports.checker = async () => {
|
|||||||
checkHexColor(input.color,path+"/color")
|
checkHexColor(input.color,path+"/color")
|
||||||
}
|
}
|
||||||
|
|
||||||
//ticket explaination & max tickets warning
|
|
||||||
checkType(input.enableTicketExplaination,"boolean",path+"/enableTicketExplaination")
|
|
||||||
checkType(input.enableMaxTicketsWarning,"boolean",path+"/enableMaxTicketsWarning")
|
|
||||||
|
|
||||||
//OPTIONS!!!
|
//OPTIONS!!!
|
||||||
var counter = 0
|
var counter = 0
|
||||||
input.options.forEach((option) => {if (!configParser.optionExists(option)){counter++}})
|
input.options.forEach((option) => {if (!configParser.optionExists(option)){counter++}})
|
||||||
@@ -328,6 +324,42 @@ exports.checker = async () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//other
|
||||||
|
//ticket explaination & max tickets warning
|
||||||
|
if (typeof input.other != "object"){
|
||||||
|
createError("'"+path+"/other' | this object doesn't exist!")
|
||||||
|
}else{
|
||||||
|
checkType(input.other.enableTicketExplaination,"boolean",path+"/other/enableTicketExplaination")
|
||||||
|
checkType(input.other.enableMaxTicketsWarning,"boolean",path+"/other/enableMaxTicketsWarning")
|
||||||
|
|
||||||
|
//customDropdownPlaceholder
|
||||||
|
if (typeof input.other.customDropdownPlaceholder != "object"){
|
||||||
|
createError("'"+path+"/other/customDropdownPlaceholder' | this object doesn't exist!")
|
||||||
|
}else{
|
||||||
|
checkType(input.other.customDropdownPlaceholder.enable,"boolean",path+"/other/customDropdownPlaceholder/enable")
|
||||||
|
checkType(input.other.customDropdownPlaceholder.text,"string",path+"/other/customDropdownPlaceholder/text")
|
||||||
|
if (input.other.customDropdownPlaceholder.enable && input.other.customDropdownPlaceholder.text.length < 1){createError("'"+path+"/other/customDropdownPlaceholder/text' | there is no placeholder text!")}
|
||||||
|
}
|
||||||
|
|
||||||
|
//customCategoryText
|
||||||
|
if (typeof input.other.customCategoryText != "object"){
|
||||||
|
createError("'"+path+"/other/customCategoryText' | this object doesn't exist!")
|
||||||
|
}else{
|
||||||
|
checkType(input.other.customCategoryText.enable,"boolean",path+"/other/customCategoryText/enable")
|
||||||
|
checkType(input.other.customCategoryText.text,"string",path+"/other/customCategoryText/text")
|
||||||
|
if (input.other.customCategoryText.enable && input.other.customCategoryText.text.length < 1){createError("'"+path+"/other/customCategoryText/text' | there is no category text!")}
|
||||||
|
}
|
||||||
|
|
||||||
|
//embedTitleURL
|
||||||
|
if (typeof input.other.embedTitleURL != "object"){
|
||||||
|
createError("'"+path+"/other/embedTitleURL' | this object doesn't exist!")
|
||||||
|
}else{
|
||||||
|
checkType(input.other.embedTitleURL.enable,"boolean",path+"/other/embedTitleURL/enable")
|
||||||
|
checkType(input.other.embedTitleURL.url,"string",path+"/other/embedTitleURL/text")
|
||||||
|
if (input.other.embedTitleURL.enable && input.other.embedTitleURL.url.length < 1){createError("'"+path+"/other/embedTitleURL/url' | there is no url!")}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------|
|
//--------------------------|
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
const fs = require("fs")
|
||||||
|
const location = "./storage/database.json"
|
||||||
|
|
||||||
|
|
||||||
|
/**@returns {[{category:String, key:String, value:String}]}*/
|
||||||
|
function getData(){
|
||||||
|
if (fs.existsSync(location)){
|
||||||
|
return JSON.parse(fs.readFileSync(location).toString())
|
||||||
|
}else{
|
||||||
|
fs.writeFileSync(location,"[]")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**@param {[{category:String, key:String, value:String}]} data*/
|
||||||
|
function setData(data){
|
||||||
|
fs.writeFileSync(location,JSON.stringify(data,null,"\t"))
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.set = (category,key,value) => {
|
||||||
|
const currentData = getData()
|
||||||
|
const exists = currentData.find((d) => (d.category == category) && (d.key == key)) ? true : false
|
||||||
|
var newData = []
|
||||||
|
if (exists){
|
||||||
|
currentData.forEach((d,i) => {
|
||||||
|
if (d.category == category && d.key == key){
|
||||||
|
newData.push({category,key,value})
|
||||||
|
}else{
|
||||||
|
newData.push(d)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
currentData.push({category,key,value})
|
||||||
|
newData = currentData
|
||||||
|
}
|
||||||
|
|
||||||
|
setData(newData)
|
||||||
|
return exists
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param {String} category
|
||||||
|
* @param {String} key
|
||||||
|
* @returns {String|false}
|
||||||
|
*/
|
||||||
|
exports.get = (category,key) => {
|
||||||
|
const currentData = getData()
|
||||||
|
const tempresult = currentData.find((d) => (d.category == category) && (d.key == key))
|
||||||
|
const result = tempresult ? tempresult.value : false
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param {String} category
|
||||||
|
* @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
|
||||||
|
}
|
||||||
@@ -37,3 +37,7 @@ exports.delete = (category,id) => {
|
|||||||
ls.removeItem(category+"--"+id)
|
ls.removeItem(category+"--"+id)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.set("category","key","value")
|
||||||
|
this.get("category","key",)
|
||||||
|
this.delete("category","key")
|
||||||
@@ -1,11 +1,7 @@
|
|||||||
//Do not change this without knowing what you are doing!!
|
|
||||||
const databaseFile = "local"
|
|
||||||
//Do not change this without knowing what you are doing!!
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var db = require("./dynamicfiles/local")
|
var db = require("./dynamicfiles/database")
|
||||||
}catch{
|
}catch(err){
|
||||||
|
console.log(err)
|
||||||
console.log("I couldn't find the database file! (location: ./core/dynamicdatabase/storage.js:2)")
|
console.log("I couldn't find the database file! (location: ./core/dynamicdatabase/storage.js:2)")
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ module.exports = () => {
|
|||||||
if (!interaction.isButton()) return
|
if (!interaction.isButton()) return
|
||||||
if (interaction.customId != "OTcloseTicketTrue") return
|
if (interaction.customId != "OTcloseTicketTrue") return
|
||||||
|
|
||||||
|
try {
|
||||||
interaction.deferUpdate()
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
|
|
||||||
if (closeTicketButtonChecker == true) return
|
if (closeTicketButtonChecker == true) return
|
||||||
closeTicketButtonChecker = true
|
closeTicketButtonChecker = true
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ module.exports = () => {
|
|||||||
if (!interaction.isButton()) return
|
if (!interaction.isButton()) return
|
||||||
if (interaction.customId != "OTsendTranscript") return
|
if (interaction.customId != "OTsendTranscript") return
|
||||||
|
|
||||||
|
try {
|
||||||
interaction.deferUpdate()
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
const tsmsg = await interaction.channel.send({embeds:[bot.embeds.commands.sendTranscriptEmbed(false,interaction.channel,interaction.user)]})
|
const tsmsg = await interaction.channel.send({embeds:[bot.embeds.commands.sendTranscriptEmbed(false,interaction.channel,interaction.user)]})
|
||||||
|
|
||||||
const channelmessages = await interaction.channel.messages.fetch()
|
const channelmessages = await interaction.channel.messages.fetch()
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ module.exports = () => {
|
|||||||
if (!interaction.isButton()) return
|
if (!interaction.isButton()) return
|
||||||
if (interaction.customId != "OTcloseTicket") return
|
if (interaction.customId != "OTcloseTicket") return
|
||||||
|
|
||||||
|
try {
|
||||||
interaction.deferUpdate()
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
interaction.message.edit({components:[bot.buttons.verifybars.closeVerifyBar]})
|
interaction.message.edit({components:[bot.buttons.verifybars.closeVerifyBar]})
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -28,7 +30,9 @@ module.exports = () => {
|
|||||||
if (!interaction.isButton()) return
|
if (!interaction.isButton()) return
|
||||||
if (interaction.customId != "OTcloseTicketFalse") return
|
if (interaction.customId != "OTcloseTicketFalse") return
|
||||||
|
|
||||||
|
try {
|
||||||
interaction.deferUpdate()
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
interaction.message.edit({components:[bot.buttons.close.openRowNormal]})
|
interaction.message.edit({components:[bot.buttons.close.openRowNormal]})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -37,7 +41,9 @@ module.exports = () => {
|
|||||||
if (!interaction.isButton()) return
|
if (!interaction.isButton()) return
|
||||||
if (interaction.customId != "OTdeleteTicket") return
|
if (interaction.customId != "OTdeleteTicket") return
|
||||||
|
|
||||||
|
try {
|
||||||
interaction.deferUpdate()
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
interaction.message.edit({components:[bot.buttons.verifybars.deleteVerifyBar]})
|
interaction.message.edit({components:[bot.buttons.verifybars.deleteVerifyBar]})
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -45,7 +51,9 @@ module.exports = () => {
|
|||||||
if (!interaction.isButton()) return
|
if (!interaction.isButton()) return
|
||||||
if (interaction.customId != "OTdeleteTicketFalse") return
|
if (interaction.customId != "OTdeleteTicketFalse") return
|
||||||
|
|
||||||
|
try {
|
||||||
interaction.deferUpdate()
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
interaction.message.edit({components:[bot.buttons.close.openRowNormal]})
|
interaction.message.edit({components:[bot.buttons.close.openRowNormal]})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -54,7 +62,9 @@ module.exports = () => {
|
|||||||
if (!interaction.isButton()) return
|
if (!interaction.isButton()) return
|
||||||
if (interaction.customId != "OTdeleteTicket1") return
|
if (interaction.customId != "OTdeleteTicket1") return
|
||||||
|
|
||||||
|
try {
|
||||||
interaction.deferUpdate()
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
interaction.message.edit({components:[bot.buttons.verifybars.delete1VerifyBar]})
|
interaction.message.edit({components:[bot.buttons.verifybars.delete1VerifyBar]})
|
||||||
|
|
||||||
})
|
})
|
||||||
@@ -62,7 +72,9 @@ module.exports = () => {
|
|||||||
if (!interaction.isButton()) return
|
if (!interaction.isButton()) return
|
||||||
if (interaction.customId != "OTdeleteTicketFalse1") return
|
if (interaction.customId != "OTdeleteTicketFalse1") return
|
||||||
|
|
||||||
|
try {
|
||||||
interaction.deferUpdate()
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
interaction.message.edit({components:[bot.buttons.close.closeCommandRow]})
|
interaction.message.edit({components:[bot.buttons.close.closeCommandRow]})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
+16
-9
@@ -12,16 +12,24 @@ module.exports = async () => {
|
|||||||
const chalk = await (await import("chalk")).default
|
const chalk = await (await import("chalk")).default
|
||||||
|
|
||||||
client.on("interactionCreate",(interaction) => {
|
client.on("interactionCreate",(interaction) => {
|
||||||
if (!interaction.isButton()) return
|
if (!interaction.isButton() && !interaction.isStringSelectMenu()) return
|
||||||
if (!interaction.customId.startsWith("newR")) return
|
if (interaction.isButton() && !interaction.customId.startsWith("newR")) return
|
||||||
|
if (interaction.isStringSelectMenu() && !(interaction.customId == "OTdropdownMenu")) return
|
||||||
|
|
||||||
interaction.deferUpdate()
|
|
||||||
|
|
||||||
if (interaction.customId.startsWith("newR")){
|
|
||||||
const optionid = interaction.customId.split("newR")[1]
|
|
||||||
|
|
||||||
|
const optionidRaw = interaction.isStringSelectMenu() ? interaction.values[0] : interaction.customId
|
||||||
|
if (!optionidRaw.includes("newR")) return
|
||||||
|
const optionid = optionidRaw.split("newR")[1]
|
||||||
if (!optionid){
|
if (!optionid){
|
||||||
interaction.reply({embeds:[bot.errorLog.serverError(l.errors.roleDoesntExist)]})
|
interaction.reply({embeds:[bot.errorLog.serverError(l.errors.roleDoesntExist)]})
|
||||||
return
|
return
|
||||||
|
}else{
|
||||||
|
try {
|
||||||
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -51,14 +59,14 @@ module.exports = async () => {
|
|||||||
|
|
||||||
}else if (mode == "add&remove"){
|
}else if (mode == "add&remove"){
|
||||||
option.roles.forEach((role) => {
|
option.roles.forEach((role) => {
|
||||||
if (interaction.guild.members.cache.find(u => u.id == user.id).roles.cache.has(role)){
|
if (!interaction.guild.members.cache.find(u => u.id == user.id).roles.cache.has(role)){
|
||||||
interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role)
|
interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role)
|
||||||
|
|
||||||
log("system","added role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}])
|
log("system","added role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}])
|
||||||
const apirole = interaction.guild.roles.cache.find(r => r.id == role)
|
const apirole = interaction.guild.roles.cache.find(r => r.id == role)
|
||||||
APIEvents.onReactionRole("add","add&remove",apirole,interaction.user,interaction.channel,interaction.guild,new Date())
|
APIEvents.onReactionRole("add","add&remove",apirole,interaction.user,interaction.channel,interaction.guild,new Date())
|
||||||
}else {
|
}else {
|
||||||
interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role)
|
interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role)
|
||||||
|
|
||||||
log("system","removed role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}])
|
log("system","removed role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}])
|
||||||
const apirole = interaction.guild.roles.cache.find(r => r.id == role)
|
const apirole = interaction.guild.roles.cache.find(r => r.id == role)
|
||||||
@@ -70,6 +78,5 @@ module.exports = async () => {
|
|||||||
}catch{
|
}catch{
|
||||||
interaction.channel.send({embeds:[bot.errorLog.serverError(l.errors.somethingWentWrong)]})
|
interaction.channel.send({embeds:[bot.errorLog.serverError(l.errors.somethingWentWrong)]})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
const discord = require("discord.js")
|
||||||
|
const bot = require("../../index")
|
||||||
|
const client = require("../../index").client
|
||||||
|
const config = bot.config
|
||||||
|
const configParser = require("../utils/configParser")
|
||||||
|
|
||||||
|
const act = discord.ApplicationCommandType
|
||||||
|
const acot = discord.ApplicationCommandOptionType
|
||||||
|
|
||||||
|
module.exports = async () => {
|
||||||
|
bot.errorLog.log("info","auto-updating slash commands...")
|
||||||
|
const sid = config.server_id
|
||||||
|
|
||||||
|
const ids = configParser.getTicketValuesArray("id")
|
||||||
|
/**@type {[{name:String,value:String}]} */
|
||||||
|
var choices = []
|
||||||
|
ids.forEach((id) => {
|
||||||
|
const option = configParser.getTicketById(id)
|
||||||
|
if (option){
|
||||||
|
choices.push({name:option.name,value:option.id})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**@type {[{name:String,value:String}]} */
|
||||||
|
var msgchoices = []
|
||||||
|
config.messages.forEach((msg) => {
|
||||||
|
msgchoices.push({name:msg.id,value:msg.id})
|
||||||
|
})
|
||||||
|
|
||||||
|
//slashtranslation
|
||||||
|
const ST = require("../../language/slashcmds/slash.json").data
|
||||||
|
|
||||||
|
//create a ticket (/new or /ticket)
|
||||||
|
client.application.commands.create({
|
||||||
|
name:"ticket",
|
||||||
|
description:"Create a ticket!",
|
||||||
|
descriptionLocalizations:ST.newticket,
|
||||||
|
defaultPermission:true,
|
||||||
|
type:act.ChatInput,
|
||||||
|
options:[
|
||||||
|
{
|
||||||
|
type:acot.String,
|
||||||
|
name:"type",
|
||||||
|
description:"The type of ticket.",
|
||||||
|
required:true,
|
||||||
|
choices:choices
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},sid)
|
||||||
|
|
||||||
|
client.application.commands.create({
|
||||||
|
name:"new",
|
||||||
|
description:"Create a ticket!",
|
||||||
|
defaultPermission:true,
|
||||||
|
type:act.ChatInput,
|
||||||
|
descriptionLocalizations:ST.newticket,
|
||||||
|
options:[
|
||||||
|
{
|
||||||
|
type:acot.String,
|
||||||
|
name:"type",
|
||||||
|
description:"The type of ticket.",
|
||||||
|
required:true,
|
||||||
|
choices:choices
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},sid)
|
||||||
|
|
||||||
|
//msg
|
||||||
|
client.application.commands.create({
|
||||||
|
name:"message",
|
||||||
|
description:"Create a ticket message.",
|
||||||
|
defaultPermission:true,
|
||||||
|
descriptionLocalizations:ST.message,
|
||||||
|
type:act.ChatInput,
|
||||||
|
options:[
|
||||||
|
{
|
||||||
|
type:acot.String,
|
||||||
|
name:"id",
|
||||||
|
description:"The message id.",
|
||||||
|
required:true,
|
||||||
|
choices:msgchoices,
|
||||||
|
max_length:30
|
||||||
|
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},sid)
|
||||||
|
}
|
||||||
@@ -34,6 +34,8 @@ module.exports = async () => {
|
|||||||
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 12")+" commands ready! (this can take up to 40 seconds)")
|
||||||
if (readystats >= 12){
|
if (readystats >= 12){
|
||||||
|
const fs = require("fs")
|
||||||
|
fs.writeFileSync("./storage/slashcmdEnabled.txt","true")
|
||||||
console.log(chalk.green("\nready!"))
|
console.log(chalk.green("\nready!"))
|
||||||
console.log(chalk.blue("you can now start the bot with "+chalk.bgBlue("'npm start'")+"!"))
|
console.log(chalk.blue("you can now start the bot with "+chalk.bgBlue("'npm start'")+"!"))
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) =>
|
|||||||
const guild = channel.guild
|
const guild = channel.guild
|
||||||
const user = member.user
|
const user = member.user
|
||||||
const chalk = await (await import("chalk")).default
|
const chalk = await (await import("chalk")).default
|
||||||
const channelmessages = await channel.messages.fetch()
|
|
||||||
|
|
||||||
const newReason = reason ? reason : l.messages.none
|
const newReason = reason ? reason : l.messages.none
|
||||||
|
|
||||||
@@ -31,9 +30,6 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) =>
|
|||||||
//FIX CHANNEL COULD BE CLOSED AFTER DELETE:
|
//FIX CHANNEL COULD BE CLOSED AFTER DELETE:
|
||||||
if (pendingDelete.includes(channel.id)) return false
|
if (pendingDelete.includes(channel.id)) return false
|
||||||
|
|
||||||
//remove ot bot from transcript
|
|
||||||
channelmessages.sweep((msgSweep) => {return msgSweep.author.id == client.user.id})
|
|
||||||
|
|
||||||
/**@type {String}*/
|
/**@type {String}*/
|
||||||
const channelname = channel.name
|
const channelname = channel.name
|
||||||
const ticketOpenerChannelName = channelname.split(prefix)[1]
|
const ticketOpenerChannelName = channelname.split(prefix)[1]
|
||||||
@@ -293,12 +289,17 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const transcriptHandler = async () => {
|
||||||
if (enableTranscript == true && mode != "deletenotranscript"){
|
if (enableTranscript == true && mode != "deletenotranscript"){
|
||||||
|
//transcript messages
|
||||||
const transcriptReason = (mode == "close") ? "**"+l.messages.reason+":** "+newReason : "**"+l.messages.reason+":** "+l.messages.none
|
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
|
const closedByPrefix = (mode.startsWith("delete")) ? l.messages.deletedby : l.messages.closedby
|
||||||
|
|
||||||
if (config.system.enable_transcript || config.system.enable_DM_transcript){
|
if (config.system.enable_transcript || config.system.enable_DM_transcript){
|
||||||
|
const channelmessages = await channel.messages.fetch({cache:true})
|
||||||
|
//remove ot bot from transcript
|
||||||
|
channelmessages.sweep((msgSweep) => {return msgSweep.author.id == client.user.id})
|
||||||
|
|
||||||
var fileattachment = await require("../transcript").createTranscript(channelmessages,channel)
|
var fileattachment = await require("../transcript").createTranscript(channelmessages,channel)
|
||||||
|
|
||||||
if (fileattachment == false){log("system","internal error: transcript is not created!");return}
|
if (fileattachment == false){log("system","internal error: transcript is not created!");return}
|
||||||
@@ -330,16 +331,23 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) =>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
const deleteHandler = async () => {
|
||||||
if (deleteRequired){
|
if (deleteRequired){
|
||||||
//const timer = () => {return new Promise((resolve,reject) => {
|
//const timer = () => {return new Promise((resolve,reject) => {
|
||||||
// setTimeout(() => {resolve(true)},7000)
|
// setTimeout(() => {resolve(true)},7000)
|
||||||
//})}
|
//})}
|
||||||
//await timer()
|
//await timer()
|
||||||
|
|
||||||
setTimeout(async () => {
|
|
||||||
pendingDelete.shift()
|
pendingDelete.shift()
|
||||||
await channel.delete()
|
await channel.delete()
|
||||||
},6000)
|
|
||||||
|
//setTimeout(async () => {
|
||||||
|
// pendingDelete.shift()
|
||||||
|
// await channel.delete()
|
||||||
|
//},6000)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
await transcriptHandler()
|
||||||
|
deleteHandler()
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,9 @@ module.exports = () => {
|
|||||||
client.on("interactionCreate",(interaction) => {
|
client.on("interactionCreate",(interaction) => {
|
||||||
if (!interaction.isStringSelectMenu()) return
|
if (!interaction.isStringSelectMenu()) return
|
||||||
if (interaction.customId != "OTdropdownMenu") return
|
if (interaction.customId != "OTdropdownMenu") return
|
||||||
if (interaction.values.includes("OTChooseTicket")) interaction.deferUpdate()
|
if (interaction.values.includes("OTChooseTicket")){
|
||||||
|
interaction.deferUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -50,11 +52,15 @@ module.exports = () => {
|
|||||||
if (currentTicketOptions == false) return interaction.reply({embeds:[bot.errorLog.serverError(l.errors.anotherOption)]})
|
if (currentTicketOptions == false) return interaction.reply({embeds:[bot.errorLog.serverError(l.errors.anotherOption)]})
|
||||||
|
|
||||||
if (interaction.isButton()){
|
if (interaction.isButton()){
|
||||||
|
try {
|
||||||
interaction.deferUpdate()
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
}else if (interaction.isChatInputCommand()){
|
}else if (interaction.isChatInputCommand()){
|
||||||
interaction.reply({embeds:[bot.errorLog.success(l.messages.createdTitle,l.messages.createdDescription)]})
|
interaction.reply({embeds:[bot.errorLog.success(l.messages.createdTitle,l.messages.createdDescription)]})
|
||||||
}else if (interaction.isStringSelectMenu()){
|
}else if (interaction.isStringSelectMenu()){
|
||||||
await interaction.deferUpdate()
|
try {
|
||||||
|
interaction.deferUpdate()
|
||||||
|
} catch{}
|
||||||
}
|
}
|
||||||
|
|
||||||
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){
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const l = bot.language
|
|||||||
|
|
||||||
|
|
||||||
//OTConfigMessage
|
//OTConfigMessage
|
||||||
/**@typedef {{id: string, name: string, description: string, dropdown: boolean, enableFooter: boolean, footer: string, enableThumbnail: boolean, thumbnail: string, enableCustomColor: boolean, color: string, options: string[], enableTicketExplaination: boolean, enableMaxTicketsWarning: boolean}} OTConfigMessage*/
|
/**@typedef {{id: string, name: string, description: string, dropdown: boolean, enableFooter: boolean, footer: string, enableThumbnail: boolean, thumbnail: string, enableCustomColor: boolean, color: string, options: string[], other:{enableTicketExplaination: boolean, enableMaxTicketsWarning: boolean, customDropdownPlaceholder:{enable:Boolean,text:String}, customCategoryText:{enable:Boolean,text:String}, embedTitleURL:{enable:Boolean,url:String} } }} OTConfigMessage*/
|
||||||
|
|
||||||
//StringOptions
|
//StringOptions
|
||||||
/**@typedef {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"adminroles"|"channelprefix"|"category"|"message"|"enableDmOnOpen"|"ticketmessage"|"thumbnail"|"closedCategory"} OTTicketStringOptions */
|
/**@typedef {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"adminroles"|"channelprefix"|"category"|"message"|"enableDmOnOpen"|"ticketmessage"|"thumbnail"|"closedCategory"} OTTicketStringOptions */
|
||||||
|
|||||||
@@ -7,24 +7,26 @@ const configParser = require("./configParser")
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {String[]} ids
|
* @param {String[]} ids
|
||||||
|
* @param {String|undefined|false} placeholder
|
||||||
* @returns {discord.StringSelectMenuBuilder|false}
|
* @returns {discord.StringSelectMenuBuilder|false}
|
||||||
*/
|
*/
|
||||||
exports.getDropdown = (ids) => {
|
exports.getDropdown = (ids,placeholder) => {
|
||||||
const dropdown = new discord.StringSelectMenuBuilder()
|
const dropdown = new discord.StringSelectMenuBuilder()
|
||||||
.setCustomId("OTdropdownMenu")
|
.setCustomId("OTdropdownMenu")
|
||||||
.setDisabled(false)
|
.setDisabled(false)
|
||||||
.setMaxValues(1)
|
.setMaxValues(1)
|
||||||
.setMinValues(1)
|
.setMinValues(1)
|
||||||
.setPlaceholder(l.messages.chooseATicket)
|
.setPlaceholder(placeholder || l.messages.chooseATicket)
|
||||||
.addOptions(
|
.addOptions(
|
||||||
new discord.SelectMenuOptionBuilder()
|
new discord.SelectMenuOptionBuilder()
|
||||||
.setDefault(true)
|
.setDefault(true)
|
||||||
.setLabel(l.messages.chooseATicket)
|
.setLabel(placeholder || l.messages.chooseATicket)
|
||||||
.setValue("OTChooseTicket")
|
.setValue("OTChooseTicket")
|
||||||
)
|
)
|
||||||
|
|
||||||
ids.forEach((id) => {
|
ids.forEach((id) => {
|
||||||
const option = configParser.getTicketById(id,true)
|
const option = configParser.getTicketById(id,true)
|
||||||
|
const roleoption = configParser.getRoleById(id,true)
|
||||||
if (option){
|
if (option){
|
||||||
const selectComponent = new discord.SelectMenuOptionBuilder()
|
const selectComponent = new discord.SelectMenuOptionBuilder()
|
||||||
.setDefault(false)
|
.setDefault(false)
|
||||||
@@ -38,7 +40,22 @@ exports.getDropdown = (ids) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dropdown.addOptions(selectComponent)
|
dropdown.addOptions(selectComponent)
|
||||||
|
|
||||||
|
}else if (roleoption){
|
||||||
|
const selectComponent = new discord.SelectMenuOptionBuilder()
|
||||||
|
.setDefault(false)
|
||||||
|
.setValue("OTnewR"+roleoption.id)
|
||||||
|
|
||||||
|
if (!roleoption.label && !roleoption.icon){
|
||||||
|
selectComponent.setLabel("OT ERROR: no description/emoji")
|
||||||
|
}else{
|
||||||
|
if (roleoption.label) selectComponent.setLabel(roleoption.label)
|
||||||
|
if (roleoption.icon) selectComponent.setEmoji(roleoption.icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dropdown.addOptions(selectComponent)
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,9 +43,12 @@ exports.createEmbed = (id) => {
|
|||||||
embed.setColor(config.main_color)
|
embed.setColor(config.main_color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.other.embedTitleURL.enable) embed.setURL(data.other.embedTitleURL)
|
||||||
|
|
||||||
var description = data.description
|
var description = data.description
|
||||||
if (data.enableTicketExplaination){
|
if (data.other.enableTicketExplaination){
|
||||||
description = description+"\n\n__"+l.messages.chooseCategory+"__\n"
|
const chooseCategoryMSG = data.other.customCategoryText.enable ? data.other.customCategoryText.text : l.messages.chooseCategory
|
||||||
|
description = description+"\n\n__"+chooseCategoryMSG+"__\n"
|
||||||
|
|
||||||
var ticketExplainations = []
|
var ticketExplainations = []
|
||||||
buttonData.forEach((button) => {
|
buttonData.forEach((button) => {
|
||||||
@@ -56,7 +59,7 @@ exports.createEmbed = (id) => {
|
|||||||
description = description+ticketExplainations.join("\n\n")
|
description = description+ticketExplainations.join("\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.enableMaxTicketsWarning){
|
if (data.other.enableMaxTicketsWarning){
|
||||||
description = description+"\n\n"+l.commands.maxTicketWarning.replace("{0}",config.system.max_allowed_tickets)
|
description = description+"\n\n"+l.commands.maxTicketWarning.replace("{0}",config.system.max_allowed_tickets)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +95,8 @@ exports.createEmbed = (id) => {
|
|||||||
//create the component IF DROPDOWN is true
|
//create the component IF DROPDOWN is true
|
||||||
}else{
|
}else{
|
||||||
const ids = data.options
|
const ids = data.options
|
||||||
const dropdown = require("./getDropdown").getDropdown(ids)
|
const customPlaceholder = data.other.customDropdownPlaceholder.enable ? data.other.customDropdownPlaceholder.text : false
|
||||||
|
const dropdown = require("./getDropdown").getDropdown(ids,customPlaceholder)
|
||||||
var componentRows = [
|
var componentRows = [
|
||||||
new discord.ActionRowBuilder()
|
new discord.ActionRowBuilder()
|
||||||
.setComponents(dropdown)
|
.setComponents(dropdown)
|
||||||
|
|||||||
@@ -124,6 +124,12 @@ client.on('ready',async () => {
|
|||||||
setStatus(config.status.type,config.status.text)
|
setStatus(config.status.type,config.status.text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fs.existsSync("./storage/slashcmdEnabled.txt")){
|
||||||
|
/**@type {"true"|"false"} */
|
||||||
|
const data = fs.readFileSync("./storage/slashcmdEnabled.txt").toString()
|
||||||
|
if (data === "true"){require("./core/slashSystem/autoSlashUpdate")()}
|
||||||
|
}else{fs.writeFileSync("./storage/slashcmdEnabled.txt","false")}
|
||||||
|
|
||||||
log("system","bot logged in!")
|
log("system","bot logged in!")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -150,10 +156,19 @@ client.on('ready',async () => {
|
|||||||
if (config.status.enabled){
|
if (config.status.enabled){
|
||||||
setStatus(config.status.type,config.status.text)
|
setStatus(config.status.type,config.status.text)
|
||||||
}
|
}
|
||||||
|
if (fs.existsSync("./storage/slashcmdEnabled.txt")){
|
||||||
|
/**@type {"true"|"false"} */
|
||||||
|
const data = fs.readFileSync("./storage/slashcmdEnabled.txt").toString()
|
||||||
|
if (data === "true"){require("./core/slashSystem/autoSlashUpdate")()}
|
||||||
|
}else{fs.writeFileSync("./storage/slashcmdEnabled.txt","false")}
|
||||||
|
|
||||||
log("system","bot logged in!")
|
log("system","bot logged in!")
|
||||||
|
|
||||||
|
try {
|
||||||
await client.guilds.cache.find((g) => g.id == config.server_id).members.fetch()
|
await client.guilds.cache.find((g) => g.id == config.server_id).members.fetch()
|
||||||
|
}catch{
|
||||||
|
this.errorLog.log("info","tried to cache user information, failed!")
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
console.log(chalk.red("STARTING IN ")+chalk.blue("SLASH MODE")+chalk.red("..."))
|
console.log(chalk.red("STARTING IN ")+chalk.blue("SLASH MODE")+chalk.red("..."))
|
||||||
this.errorLog.log("debug","slashmode activated")
|
this.errorLog.log("debug","slashmode activated")
|
||||||
|
|||||||
@@ -75,6 +75,9 @@
|
|||||||
|
|
||||||
"chooseCategory":"Wähle eine Kategorie:",
|
"chooseCategory":"Wähle eine Kategorie:",
|
||||||
|
|
||||||
|
"none":"keiner",
|
||||||
|
"reason":"Grund",
|
||||||
|
|
||||||
"deletedby":"Gelöscht von",
|
"deletedby":"Gelöscht von",
|
||||||
"closedby":"Geschlossen von",
|
"closedby":"Geschlossen von",
|
||||||
"modalreason":"Was ist der Grund?",
|
"modalreason":"Was ist der Grund?",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "open-ticket",
|
"name": "open-ticket",
|
||||||
"version": "3.0.1",
|
"version": "3.1.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": {
|
||||||
|
|||||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,3 @@
|
|||||||
|
This file is only here to make sure that this directory exists!
|
||||||
|
|
||||||
|
I don't have any other use :)
|
||||||
Reference in New Issue
Block a user