This commit is contained in:
David Ralph 2020-10-03 15:08:10 +01:00
parent 5ef7dc3fc4
commit b0ad6b7c88
32 changed files with 194 additions and 176 deletions

View File

@ -32,6 +32,9 @@ module.exports = {
], ],
'no-control-regex': [ 'no-control-regex': [
'off' 'off'
],
'no-console': [
'off'
] ]
} }
}; };

View File

@ -9,10 +9,10 @@ DiscordTickets is a Discord bot for managing support ticket channels, to allow y
- Highly customisable - Highly customisable
- Ticket "panel" / "widget" (react to embed to create ticket) - Ticket "panel" / "widget" (react to embed to create ticket)
- Simple commands - Simple commands
- SQLite (easy, default) **or** MySQL (recommend) storage - Supports multiple databases: SQLite (easy, default), MySQL (recommend) storage, MariaDB, PostgresSQL and Microsoft SQL Server
- Most (all of the best) features of the premium bots, for free - Most (all of the best) features of the premium bots, for free
- Self-hosted with your bot application, your logo and guild name - Self-hosted with your bot application, your logo and guild name
- Optional express.js server for web archvies: [DiscordTickets-Portal](https://github.com/eartharoid/DiscordTickets-Portal/) - Optional express.js server for web archives: [DiscordTickets-Portal](https://github.com/eartharoid/DiscordTickets-Portal/)
## Screenshot ## Screenshot
@ -31,4 +31,4 @@ For installation, configuration, usage, and other information, **go to the [wiki
## Donate ## Donate
[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/B0B214BHI) [![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/eartharoid)

View File

@ -19,7 +19,10 @@
"sqlite3": "^5.0.0" "sqlite3": "^5.0.0"
}, },
"peerDependencies": { "peerDependencies": {
"mysql2": "2.x" "mysql2": "2.x",
"mariadb": "2.x",
"pg": "8.x",
"tedious": "9.x"
}, },
"devDependencies": { "devDependencies": {
"eslint": "^7.10.0", "eslint": "^7.10.0",

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const { MessageEmbed } = require('discord.js'); const { MessageEmbed } = require('discord.js');
@ -34,17 +34,15 @@ module.exports = {
let channel = message.mentions.channels.first(); let channel = message.mentions.channels.first();
if(!channel) { if (!channel) {
channel = message.channel; channel = message.channel;
ticket = await Ticket.findOne({ where: { channel: message.channel.id } }); ticket = await Ticket.findOne({ where: { channel: message.channel.id } });
if(!ticket) if(!ticket)
return message.channel.send(notTicket); return message.channel.send(notTicket);
} else { } else {
ticket = await Ticket.findOne({ where: { channel: channel.id } }); ticket = await Ticket.findOne({ where: { channel: channel.id } });
if(!ticket) { if (!ticket) {
notTicket notTicket
.setTitle(':x: **Channel is not a ticket**') .setTitle(':x: **Channel is not a ticket**')
.setDescription(`${channel} is not a ticket channel.`); .setDescription(`${channel} is not a ticket channel.`);
@ -63,12 +61,10 @@ module.exports = {
.addField('Help', `Type \`${config.prefix}help ${this.name}\` for more information`) .addField('Help', `Type \`${config.prefix}help ${this.name}\` for more information`)
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
let member = guild.member(message.mentions.users.first() || guild.members.cache.get(args[0])); let member = guild.member(message.mentions.users.first() || guild.members.cache.get(args[0]));
if(!member) if (!member)
return message.channel.send( return message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -88,7 +84,7 @@ module.exports = {
READ_MESSAGE_HISTORY: true READ_MESSAGE_HISTORY: true
}); });
if(channel.id !== message.channel.id) if (channel.id !== message.channel.id)
channel.send( channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.colour) .setColor(config.colour)
@ -99,7 +95,6 @@ module.exports = {
); );
message.channel.send( message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.colour) .setColor(config.colour)
@ -108,7 +103,7 @@ module.exports = {
.setDescription(`${member} has been added to <#${ticket.channel}>`) .setDescription(`${member} has been added to <#${ticket.channel}>`)
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
log.info(`${message.author.tag} added a user to a ticket (#${message.channel.id})`); log.info(`${message.author.tag} added a user to a ticket (#${message.channel.id})`);
} catch (error) { } catch (error) {
log.error(error); log.error(error);

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;
@ -153,10 +153,9 @@ module.exports = {
fs.existsSync(`user/transcripts/raw/${ticket.get('channel')}.log`) fs.existsSync(`user/transcripts/raw/${ticket.get('channel')}.log`)
&& &&
fs.existsSync(`user/transcripts/raw/entities/${ticket.get('channel')}.json`) fs.existsSync(`user/transcripts/raw/entities/${ticket.get('channel')}.json`)
) )
embed.addField('Web archive', await archive.export(Ticket, channel)); embed.addField('Web archive', await archive.export(Ticket, channel));
if (embed.fields.length < 1) if (embed.fields.length < 1)
embed.setDescription(`No text transcripts or archive data exists for ticket ${ticket.id}`); embed.setDescription(`No text transcripts or archive data exists for ticket ${ticket.id}`);

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;
@ -124,13 +124,13 @@ module.exports = {
raw = `user/transcripts/raw/${ticket.get('channel')}.log`, raw = `user/transcripts/raw/${ticket.get('channel')}.log`,
json = `user/transcripts/raw/entities/${ticket.get('channel')}.json`; json = `user/transcripts/raw/entities/${ticket.get('channel')}.json`;
if (fs.existsSync(txt)) if (fs.existsSync(txt))
fs.unlinkSync(txt); fs.unlinkSync(txt);
if (fs.existsSync(raw)) if (fs.existsSync(raw))
fs.unlinkSync(raw); fs.unlinkSync(raw);
if (fs.existsSync(json)) if (fs.existsSync(json))
fs.unlinkSync(json); fs.unlinkSync(json);
// update database // update database

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;
@ -20,7 +20,7 @@ module.exports = {
execute(client, message, args, {config}) { execute(client, message, args, {config}) {
const guild = client.guilds.cache.get(config.guild); const guild = client.guilds.cache.get(config.guild);
const commands = Array.from(client.commands.values()); const commands = Array.from(client.commands.values());
if (!args.length) { if (!args.length) {
@ -29,7 +29,7 @@ module.exports = {
for (let command of commands) { for (let command of commands) {
if (command.hide) if (command.hide)
continue; continue;
if (command.permission && !message.member.hasPermission(command.permission)) if (command.permission && !message.member.hasPermission(command.permission))
continue; continue;
let desc = command.description; let desc = command.description;
@ -38,7 +38,7 @@ module.exports = {
desc = desc.substring(0, 50) + '...'; desc = desc.substring(0, 50) + '...';
cmds.push(`**${config.prefix}${command.name}** **·** ${desc}`); cmds.push(`**${config.prefix}${command.name}** **·** ${desc}`);
} }
message.channel.send( message.channel.send(
new MessageEmbed() new MessageEmbed()
.setTitle('Commands') .setTitle('Commands')
@ -58,13 +58,13 @@ module.exports = {
const name = args[0].toLowerCase(); const name = args[0].toLowerCase();
const command = client.commands.get(name) || client.commands.find(c => c.aliases && c.aliases.includes(name)); const command = client.commands.get(name) || client.commands.find(c => c.aliases && c.aliases.includes(name));
if (!command) if (!command)
return message.channel.send( return message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
.setDescription(`:x: **Invalid command name** (\`${config.prefix}help\`)`) .setDescription(`:x: **Invalid command name** (\`${config.prefix}help\`)`)
); );
const cmd = new MessageEmbed() const cmd = new MessageEmbed()
.setColor(config.colour) .setColor(config.colour)
@ -88,7 +88,7 @@ module.exports = {
} else { } else {
cmd.addField('Required Permission', `\`${command.permission || 'none'}\``, true); cmd.addField('Required Permission', `\`${command.permission || 'none'}\``, true);
} }
message.channel.send(cmd); message.channel.send(cmd);
} }

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;
@ -19,9 +19,9 @@ module.exports = {
example: 'new my server won\'t start', example: 'new my server won\'t start',
args: false, args: false,
async execute(client, message, args, {config, Ticket}) { async execute(client, message, args, {config, Ticket}) {
const guild = client.guilds.cache.get(config.guild); const guild = client.guilds.cache.get(config.guild);
const supportRole = guild.roles.cache.get(config.staff_role); const supportRole = guild.roles.cache.get(config.staff_role);
if (!supportRole) if (!supportRole)
return message.channel.send( return message.channel.send(
@ -47,8 +47,8 @@ module.exports = {
let desc = tickets.rows[t].topic.substring(0, 30); let desc = tickets.rows[t].topic.substring(0, 30);
ticketList ticketList
.push(`<#${tickets.rows[t].channel}>: \`${desc}${desc.length > 30 ? '...' : ''}\``); .push(`<#${tickets.rows[t].channel}>: \`${desc}${desc.length > 30 ? '...' : ''}\``);
} }
let m = await message.channel.send( let m = await message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -63,7 +63,7 @@ module.exports = {
await m.delete(); await m.delete();
}, 15000); }, 15000);
} }
let topic = args.join(' '); let topic = args.join(' ');
if (topic.length > 256) if (topic.length > 256)
@ -100,7 +100,7 @@ module.exports = {
{ {
id: client.user, id: client.user,
allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'ATTACH_FILES', 'READ_MESSAGE_HISTORY'] allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'ATTACH_FILES', 'READ_MESSAGE_HISTORY']
}, },
{ {
id: message.member, id: message.member,
allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'ATTACH_FILES', 'READ_MESSAGE_HISTORY'] allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'ATTACH_FILES', 'READ_MESSAGE_HISTORY']
@ -134,7 +134,7 @@ module.exports = {
await message.delete(); await message.delete();
await m.delete(); await m.delete();
}, 15000); }, 15000);
// require('../modules/archive').create(client, c); // create files // require('../modules/archive').create(client, c); // create files
let ping; let ping;

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;
@ -26,13 +26,13 @@ module.exports = {
let chanID = await Setting.findOne({ where: { key: 'panel_chan_id' } }); let chanID = await Setting.findOne({ where: { key: 'panel_chan_id' } });
let panel; let panel;
if(!chanID) if (!chanID)
chanID = await Setting.create({ chanID = await Setting.create({
key: 'panel_chan_id', key: 'panel_chan_id',
value: message.channel.id, value: message.channel.id,
}); });
if(!msgID) { if (!msgID) {
msgID = await Setting.create({ msgID = await Setting.create({
key: 'panel_msg_id', key: 'panel_msg_id',
value: '', value: '',
@ -45,7 +45,7 @@ module.exports = {
} catch (e) { } catch (e) {
log.warn('Couldn\'t delete old panel'); log.warn('Couldn\'t delete old panel');
} }
} }
message.delete(); message.delete();

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const { MessageEmbed } = require('discord.js'); const { MessageEmbed } = require('discord.js');
@ -34,15 +34,15 @@ module.exports = {
let channel = message.mentions.channels.first(); let channel = message.mentions.channels.first();
if(!channel) { if (!channel) {
channel = message.channel; channel = message.channel;
ticket = await Ticket.findOne({ where: { channel: message.channel.id } }); ticket = await Ticket.findOne({ where: { channel: message.channel.id } });
if(!ticket) if (!ticket)
return message.channel.send(notTicket); return message.channel.send(notTicket);
} else { } else {
ticket = await Ticket.findOne({ where: { channel: channel.id } }); ticket = await Ticket.findOne({ where: { channel: channel.id } });
if(!ticket) { if(!ticket) {
notTicket notTicket
@ -52,7 +52,7 @@ module.exports = {
} }
} }
if(message.author.id !== ticket.creator && !message.member.roles.cache.has(config.staff_role)) if (message.author.id !== ticket.creator && !message.member.roles.cache.has(config.staff_role))
return message.channel.send( return message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -63,11 +63,11 @@ module.exports = {
.addField('Help', `Type \`${config.prefix}help ${this.name}\` for more information`) .addField('Help', `Type \`${config.prefix}help ${this.name}\` for more information`)
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
let member = guild.member(message.mentions.users.first() || guild.members.cache.get(args[0])); let member = guild.member(message.mentions.users.first() || guild.members.cache.get(args[0]));
if(!member || member.id === message.author.id || member.id === guild.me.id) if(!member || member.id === message.author.id || member.id === guild.me.id)
return message.channel.send( return message.channel.send(
new MessageEmbed() new MessageEmbed()
@ -99,7 +99,7 @@ module.exports = {
); );
message.channel.send( message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.colour) .setColor(config.colour)
@ -108,7 +108,7 @@ module.exports = {
.setDescription(`${member} has been removed from <#${ticket.channel}>`) .setDescription(`${member} has been removed from <#${ticket.channel}>`)
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
log.info(`${message.author.tag} removed a user from a ticket (#${message.channel.id})`); log.info(`${message.author.tag} removed a user from a ticket (#${message.channel.id})`);
} catch (error) { } catch (error) {
log.error(error); log.error(error);

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const { MessageEmbed } = require('discord.js'); const { MessageEmbed } = require('discord.js');

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const { MessageEmbed } = require('discord.js'); const { MessageEmbed } = require('discord.js');
@ -19,7 +19,7 @@ module.exports = {
async execute(client, message, args, {config, Ticket}) { async execute(client, message, args, {config, Ticket}) {
const guild = client.guilds.cache.get(config.guild); const guild = client.guilds.cache.get(config.guild);
const supportRole = guild.roles.cache.get(config.staff_role); const supportRole = guild.roles.cache.get(config.staff_role);
if (!supportRole) if (!supportRole)
return message.channel.send( return message.channel.send(
@ -32,7 +32,7 @@ module.exports = {
let context = 'self'; let context = 'self';
let user = message.mentions.users.first() || guild.members.cache.get(args[0]); let user = message.mentions.users.first() || guild.members.cache.get(args[0]);
if(user) { if(user) {
if(!message.member.roles.cache.has(config.staff_role)) if(!message.member.roles.cache.has(config.staff_role))
return message.channel.send( return message.channel.send(
@ -76,17 +76,15 @@ module.exports = {
if(config.transcripts.web.enabled) if(config.transcripts.web.enabled)
embed.setDescription(`You can access all of your ticket archives on the [web portal](${config.transcripts.web.server}/${user.id}).`); embed.setDescription(`You can access all of your ticket archives on the [web portal](${config.transcripts.web.server}/${user.id}).`);
let open = [], let open = [],
closed = []; closed = [];
for (let t in openTickets.rows) { for (let t in openTickets.rows) {
let desc = openTickets.rows[t].topic.substring(0, 30); let desc = openTickets.rows[t].topic.substring(0, 30);
open.push(`> <#${openTickets.rows[t].channel}>: \`${desc}${desc.length > 20 ? '...' : ''}\``); open.push(`> <#${openTickets.rows[t].channel}>: \`${desc}${desc.length > 20 ? '...' : ''}\``);
} }
for (let t in closedTickets.rows) { for (let t in closedTickets.rows) {
let desc = closedTickets.rows[t].topic.substring(0, 30); let desc = closedTickets.rows[t].topic.substring(0, 30);
let transcript = ''; let transcript = '';
@ -95,12 +93,12 @@ module.exports = {
transcript = `\n> Type \`${config.prefix}transcript ${closedTickets.rows[t].id}\` to view.`; transcript = `\n> Type \`${config.prefix}transcript ${closedTickets.rows[t].id}\` to view.`;
closed.push(`> **#${closedTickets.rows[t].id}**: \`${desc}${desc.length > 20 ? '...' : ''}\`${transcript}`); closed.push(`> **#${closedTickets.rows[t].id}**: \`${desc}${desc.length > 20 ? '...' : ''}\`${transcript}`);
} }
let pre = context === 'self' ? 'You have' : user.username + ' has'; let pre = context === 'self' ? 'You have' : user.username + ' has';
embed.addField('Open tickets', openTickets.count === 0 ? `${pre} no open tickets.` : open.join('\n\n'), false); embed.addField('Open tickets', openTickets.count === 0 ? `${pre} no open tickets.` : open.join('\n\n'), false);
embed.addField('Closed tickets', closedTickets.count === 0 ? `${pre} no old tickets` : closed.join('\n\n'), false); embed.addField('Closed tickets', closedTickets.count === 0 ? `${pre} no old tickets` : closed.join('\n\n'), false);
message.delete({timeout: 15000}); message.delete({timeout: 15000});
let channel; let channel;

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const { MessageEmbed } = require('discord.js'); const { MessageEmbed } = require('discord.js');
@ -47,10 +47,10 @@ module.exports = {
.setTitle(':x: **Description too long**') .setTitle(':x: **Description too long**')
.setDescription('Please limit your ticket topic to less than 256 characters. A short sentence will do.') .setDescription('Please limit your ticket topic to less than 256 characters. A short sentence will do.')
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
message.channel.setTopic(`<@${ticket.creator}> | ` + topic); message.channel.setTopic(`<@${ticket.creator}> | ` + topic);
Ticket.update({ Ticket.update({
topic: topic topic: topic
}, { }, {

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const fs = require('fs'); const fs = require('fs');
@ -66,7 +66,7 @@ module.exports = {
} }
]; ];
} }
const BASE_URL = config.transcripts.web.server; const BASE_URL = config.transcripts.web.server;
if (config.transcripts.web.enabled) if (config.transcripts.web.enabled)
@ -83,7 +83,7 @@ module.exports = {
} catch (e) { } catch (e) {
channel = message.channel; channel = message.channel;
} }
channel.send(res).then(m => { channel.send(res).then(m => {
if (channel.id === message.channel.id) if (channel.id === message.channel.id)
m.delete({timeout: 15000}); m.delete({timeout: 15000});

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const { Collection, MessageEmbed } = require('discord.js'); const { Collection, MessageEmbed } = require('discord.js');
@ -23,19 +23,19 @@ module.exports = {
I am the support bot for **${guild}**. I am the support bot for **${guild}**.
Type \`${config.prefix}new\` on the server to create a new ticket.`); Type \`${config.prefix}new\` on the server to create a new ticket.`);
} // stop here if is DM } // stop here if is DM
/** /**
* Ticket transcripts * Ticket transcripts
* (bots currently still allowed) * (bots currently still allowed)
*/ */
let ticket = await Ticket.findOne({ where: { channel: message.channel.id } }); let ticket = await Ticket.findOne({ where: { channel: message.channel.id } });
if(ticket) if(ticket)
archive.add(message); // add message to archive archive.add(message); // add message to archive
if (message.author.bot || message.author.id === client.user.id) return; // goodbye bots if (message.author.bot || message.author.id === client.user.id) return; // goodbye bots
/** /**
* Command handler * Command handler
* (no bots / self) * (no bots / self)
@ -49,7 +49,7 @@ Type \`${config.prefix}new\` on the server to create a new ticket.`);
const commandName = args.shift().toLowerCase(); const commandName = args.shift().toLowerCase();
const command = client.commands.get(commandName) const command = client.commands.get(commandName)
|| client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
if (!command || commandName === 'none') return; // not an existing command if (!command || commandName === 'none') return; // not an existing command
if (message.guild.id !== guild.id) if (message.guild.id !== guild.id)
@ -76,7 +76,7 @@ Type \`${config.prefix}new\` on the server to create a new ticket.`);
); );
if (!client.cooldowns.has(command.name)) client.cooldowns.set(command.name, new Collection()); if (!client.cooldowns.has(command.name)) client.cooldowns.set(command.name, new Collection());
const now = Date.now(); const now = Date.now();
const timestamps = client.cooldowns.get(command.name); const timestamps = client.cooldowns.get(command.name);
const cooldownAmount = (command.cooldown || config.cooldown) * 1000; const cooldownAmount = (command.cooldown || config.cooldown) * 1000;

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;
@ -16,7 +16,7 @@ module.exports = {
if(!config.transcripts.web.enabled) return; if(!config.transcripts.web.enabled) return;
if (message.partial) if (message.partial)
try { try {
await message.fetch(); await message.fetch();
} catch (err) { } catch (err) {
@ -27,7 +27,7 @@ module.exports = {
let ticket = await Ticket.findOne({ where: { channel: message.channel.id } }); let ticket = await Ticket.findOne({ where: { channel: message.channel.id } });
if(!ticket) return; if(!ticket) return;
let path = `user/transcripts/raw/${message.channel.id}.log`; let path = `user/transcripts/raw/${message.channel.id}.log`;
let embeds = []; let embeds = [];

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;
@ -15,7 +15,7 @@ module.exports = {
event: 'messageReactionAdd', event: 'messageReactionAdd',
async execute(client, [r, u], {config, Ticket, Setting}) { async execute(client, [r, u], {config, Ticket, Setting}) {
if (r.partial) if (r.partial)
try { try {
await r.fetch(); await r.fetch();
} catch (err) { } catch (err) {
@ -56,7 +56,7 @@ module.exports = {
}, },
limit: config.tickets.max limit: config.tickets.max
}); });
if (tickets.count >= config.tickets.max) { if (tickets.count >= config.tickets.max) {
let ticketList = []; let ticketList = [];
for (let t in tickets.rows) { for (let t in tickets.rows) {
@ -76,7 +76,7 @@ module.exports = {
.setDescription(`Use \`${config.prefix}close\` in a server channel to close unneeded tickets.\n\n${ticketList.join(',\n')}`) .setDescription(`Use \`${config.prefix}close\` in a server channel to close unneeded tickets.\n\n${ticketList.join(',\n')}`)
.setFooter(channel.guild.name, channel.guild.iconURL()) .setFooter(channel.guild.name, channel.guild.iconURL())
); );
} catch (e) { } catch (e) {
@ -88,11 +88,11 @@ module.exports = {
.setDescription(`Use \`${config.prefix}close\` to close unneeded tickets.\n\n${ticketList.join(',\n')}`) .setDescription(`Use \`${config.prefix}close\` to close unneeded tickets.\n\n${ticketList.join(',\n')}`)
.setFooter(channel.guild.name + ' | This message will be deleted in 15 seconds', channel.guild.iconURL()) .setFooter(channel.guild.name + ' | This message will be deleted in 15 seconds', channel.guild.iconURL())
); );
return m.delete({ timeout: 15000 }); return m.delete({ timeout: 15000 });
} }
} }
let topic = 'No topic given (created via panel)'; let topic = 'No topic given (created via panel)';

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;
@ -16,7 +16,7 @@ module.exports = {
if(!config.transcripts.web.enabled) return; if(!config.transcripts.web.enabled) return;
if (o.partial) if (o.partial)
try { try {
await o.fetch(); await o.fetch();
} catch (err) { } catch (err) {
@ -24,7 +24,7 @@ module.exports = {
return; return;
} }
if (n.partial) if (n.partial)
try { try {
await n.fetch(); await n.fetch();
} catch (err) { } catch (err) {
@ -33,7 +33,7 @@ module.exports = {
} }
let ticket = await Ticket.findOne({ where: { channel: n.channel.id } }); let ticket = await Ticket.findOne({ where: { channel: n.channel.id } });
if(!ticket) return; if(!ticket) return;
let path = `user/transcripts/raw/${n.channel.id}.log`; let path = `user/transcripts/raw/${n.channel.id}.log`;
let embeds = []; let embeds = [];
@ -49,7 +49,6 @@ module.exports = {
attachments: [...n.attachments.values()], attachments: [...n.attachments.values()],
edited: true edited: true
}) + '\n'); }) + '\n');
} }
}; };

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;
@ -15,7 +15,7 @@ module.exports = {
execute(client) { execute(client) {
log.success(`Authenticated as ${client.user.tag}`); log.success(`Authenticated as ${client.user.tag}`);
const updatePresence = () => { const updatePresence = () => {
let num = Math.floor(Math.random() * config.activities.length); let num = Math.floor(Math.random() * config.activities.length);
client.user.setPresence({ client.user.setPresence({
@ -26,17 +26,17 @@ module.exports = {
}).catch(log.error); }).catch(log.error);
log.debug(`Updated presence: ${config.activity_types[num]} ${config.activities[num]}`); log.debug(`Updated presence: ${config.activity_types[num]} ${config.activities[num]}`);
}; };
updatePresence(); updatePresence();
setInterval(() => { setInterval(() => {
updatePresence(); updatePresence();
}, 60000); }, 60000);
if (client.guilds.cache.get(config.guild).member(client.user).hasPermission('ADMINISTRATOR', false)) if (client.guilds.cache.get(config.guild).member(client.user).hasPermission('ADMINISTRATOR', false))
log.success('\'ADMINISTRATOR\' permission has been granted'); log.success('\'ADMINISTRATOR\' permission has been granted');
else else
log.warn('Bot does not have \'ADMINISTRATOR\' permission'); log.warn('Bot does not have \'ADMINISTRATOR\' permission');
} }
}; };

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
@ -40,7 +40,6 @@ log.multi(log); // required to allow other files to access the logger
require('./modules/updater')(); // check for updates require('./modules/updater')(); // check for updates
/** /**
* storage * storage
*/ */
@ -48,14 +47,40 @@ const { Sequelize, Model, DataTypes } = require('sequelize');
let sequelize; let sequelize;
if(config.storage.type === 'mysql') { switch (config.storage.type) {
case 'mysql':
log.info('Connecting to MySQL database...'); log.info('Connecting to MySQL database...');
sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, { sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, {
dialect: 'mysql', dialect: 'mysql',
host: process.env.DB_HOST, host: process.env.DB_HOST,
logging: log.debug logging: log.debug
}); });
} else { break;
case 'mariadb':
log.info('Connecting to MariaDB database...');
sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, {
dialect: 'mariadb',
host: process.env.DB_HOST,
logging: log.debug
});
break;
case 'postgres':
log.info('Connecting to PostgresSQL database...');
sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, {
dialect: 'postgres',
host: process.env.DB_HOST,
logging: log.debug
});
break;
case 'microsoft':
log.info('Connecting to Microsoft SQL Server database...');
sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASS, {
dialect: 'mssql',
host: process.env.DB_HOST,
logging: log.debug
});
break;
default:
log.info('Using SQLite storage'); log.info('Using SQLite storage');
sequelize = new Sequelize({ sequelize = new Sequelize({
dialect: 'sqlite', dialect: 'sqlite',
@ -90,7 +115,7 @@ Setting.sync();
/** /**
* event loader * event loader
*/ */
const events = fs.readdirSync('src/events').filter(file => file.endsWith('.js')); const events = fs.readdirSync('src/events').filter(file => file.endsWith('.js'));
for (const file of events) { for (const file of events) {
const event = require(`./events/${file}`); const event = require(`./events/${file}`);
client.events.set(event.event, event); client.events.set(event.event, event);
@ -102,12 +127,12 @@ for (const file of events) {
/** /**
* command loader * command loader
*/ */
const commands = fs.readdirSync('src/commands').filter(file => file.endsWith('.js')); const commands = fs.readdirSync('src/commands').filter(file => file.endsWith('.js'));
for (const file of commands) { for (const file of commands) {
const command = require(`./commands/${file}`); const command = require(`./commands/${file}`);
client.commands.set(command.name, command); client.commands.set(command.name, command);
log.console(log.format(`> Loaded &7${config.prefix}${command.name}&f command`)); log.console(log.format(`> Loaded &7${config.prefix}${command.name}&f command`));
} }
log.info(`Loaded ${events.length} events and ${commands.length} commands`); log.info(`Loaded ${events.length} events and ${commands.length} commands`);

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
@ -17,7 +17,7 @@ const fetch = require('node-fetch');
module.exports.add = (message) => { module.exports.add = (message) => {
if(message.type !== 'DEFAULT') return; if (message.type !== 'DEFAULT') return;
if (config.transcripts.text.enabled) { // text transcripts if (config.transcripts.text.enabled) { // text transcripts
let path = `user/transcripts/text/${message.channel.id}.txt`, let path = `user/transcripts/text/${message.channel.id}.txt`,
@ -100,15 +100,15 @@ module.exports.export = (Ticket, channel) => new Promise((resolve, reject) => {
channel: channel.id channel: channel.id
} }
}); });
let raw = `user/transcripts/raw/${channel.id}.log`, let raw = `user/transcripts/raw/${channel.id}.log`,
json = `user/transcripts/raw/entities/${channel.id}.json`; json = `user/transcripts/raw/entities/${channel.id}.json`;
if (!config.transcripts.web.enabled || !fs.existsSync(raw) || !fs.existsSync(json)) if (!config.transcripts.web.enabled || !fs.existsSync(raw) || !fs.existsSync(json))
return reject(false); return reject(false);
let data = JSON.parse(fs.readFileSync(json)); let data = JSON.parse(fs.readFileSync(json));
data.ticket = { data.ticket = {
id: ticket.id, id: ticket.id,
name: channel.name, name: channel.name,
@ -125,7 +125,7 @@ module.exports.export = (Ticket, channel) => new Promise((resolve, reject) => {
if (index === -1) if (index === -1)
data.messages.push(message); data.messages.push(message);
else else
data.messages[index] = message; data.messages[index] = message;
}, () => { }, () => {
let endpoint = config.transcripts.web.server; let endpoint = config.transcripts.web.server;
@ -156,8 +156,8 @@ module.exports.export = (Ticket, channel) => new Promise((resolve, reject) => {
log.warn(e); log.warn(e);
return resolve(e); return resolve(e);
}); });
}); });
})(); })();
}); });

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const { version, homepage } = require('../../package.json'); const { version, homepage } = require('../../package.json');

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
const ChildLogger = require('leekslazylogger').ChildLogger; const ChildLogger = require('leekslazylogger').ChildLogger;
@ -15,32 +15,28 @@ version = 'v' + version;
const boxen = require('boxen'); const boxen = require('boxen');
const link = require('terminal-link'); const link = require('terminal-link');
module.exports = () => { module.exports = async () => {
if(!config.updater) if(!config.updater)
return; return;
const json = await (await fetch('https://api.github.com/repos/eartharoid/DiscordTickets/releases')).json();
fetch('https://api.github.com/repos/eartharoid/DiscordTickets/releases') const update = json[0];
.then(res => res.json()) let notice = [];
.then(json => {
const update = json[0];
let notice = [];
if (version !== update.tag_name) { if (version !== update.tag_name) {
log.notice(log.f(`There is an update available for Discord Tickets (${version} -> ${update.tag_name})`)); log.notice(log.f(`There is an update available for Discord Tickets (${version} -> ${update.tag_name})`));
notice.push(`&6You are currently using &c${version}&6, the latest is &a${update.tag_name}&6.`); notice.push(`&6You are currently using &c${version}&6, the latest is &a${update.tag_name}&6.`);
notice.push(`&6Download "&f${update.name}&6" from`); notice.push(`&6Download "&f${update.name}&6" from`);
notice.push(link('&6the GitHub releases page', 'https://github.com/eartharoid/DiscordTickets/releases/')); notice.push(link('&6the GitHub releases page', 'https://github.com/eartharoid/DiscordTickets/releases/'));
console.log( console.log(
boxen(log.f(notice.join('\n')), { boxen(log.f(notice.join('\n')), {
padding: 1, padding: 1,
margin: 1, margin: 1,
align: 'center', align: 'center',
borderColor: 'yellow', borderColor: 'yellow',
borderStyle: 'round' borderStyle: 'round'
}) })
); );
} }
});
}; };

View File

@ -1,9 +1,9 @@
/** /**
* *
* @name DiscordTickets * @name DiscordTickets
* @author eartharoid <contact@eartharoid.me> * @author eartharoid <contact@eartharoid.me>
* @license GNU-GPLv3 * @license GNU-GPLv3
* *
*/ */
module.exports = { module.exports = {

View File

@ -5,24 +5,24 @@
* | | | | | | / __| / __| / _ \ | '__| / _` | | | | | / __| | |/ / / _ \ | __| / __| * | | | | | | / __| / __| / _ \ | '__| / _` | | | | | / __| | |/ / / _ \ | __| / __|
* | |_| | | | \__ \ | (__ | (_) | | | | (_| | | | | | | (__ | < | __/ | |_ \__ \ * | |_| | | | \__ \ | (__ | (_) | | | | (_| | | | | | | (__ | < | __/ | |_ \__ \
* |____/ |_| |___/ \___| \___/ |_| \__,_| |_| |_| \___| |_|\_\ \___| \__| |___/ * |____/ |_| |___/ \___| \___/ |_| \__,_| |_| |_| \___| |_|\_\ \___| \__| |___/
* *
* --------------------- * ---------------------
* Quick Start * Quick Start
* --------------------- * ---------------------
* *
* > For detailed instructions, visit the GitHub repository and read the documentation: * > For detailed instructions, visit the GitHub repository and read the documentation:
* https://github.com/eartharoid/DiscordTickets/wiki * https://github.com/eartharoid/DiscordTickets/wiki
* *
* > IMPORTANT: Also edit the TOKEN in 'user/.env' * > IMPORTANT: Also edit the TOKEN in 'user/.env'
* *
* --------------------- * ---------------------
* Support * Support
* --------------------- * ---------------------
* *
* > Information: https://github.com/eartharoid/DiscordTickets/#readme * > Information: https://github.com/eartharoid/DiscordTickets/#readme
* > Discord Support Server: https://go.eartharoid.me/discord * > Discord Support Server: https://go.eartharoid.me/discord
* > Wiki: https://github.com/eartharoid/DiscordTickets/wiki * > Wiki: https://github.com/eartharoid/DiscordTickets/wiki
* *
* ############################################################################################### * ###############################################################################################
*/ */
@ -80,7 +80,7 @@ module.exports = {
channel: '' // ID of your log channel channel: '' // ID of your log channel
} }
}, },
debug: false, debug: false,
updater: true updater: true
}; };

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 698 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 577 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB