Merge pull request #38 from DerpyForks/master

features
This commit is contained in:
Isaac 2020-10-03 17:29:49 +01:00 committed by GitHub
commit 4b10e483a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 275 additions and 315 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

@ -18,7 +18,6 @@ module.exports = {
example: 'add @member to #ticket-23', example: 'add @member to #ticket-23',
args: true, args: true,
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 notTicket = new MessageEmbed() const notTicket = new MessageEmbed()
@ -35,14 +34,11 @@ 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 +48,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,12 +59,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) if (!member) {
return message.channel.send( return message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -79,6 +74,7 @@ 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())
); );
}
try { try {
channel.updateOverwrite(member.user, { channel.updateOverwrite(member.user, {
@ -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)
@ -97,8 +93,7 @@ module.exports = {
.setDescription(`${member} has been added by ${message.author}`) .setDescription(`${member} has been added by ${message.author}`)
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
}
message.channel.send( message.channel.send(
new MessageEmbed() new MessageEmbed()

View File

@ -21,11 +21,7 @@ module.exports = {
aliases: ['none'], aliases: ['none'],
example: 'close #ticket-17', example: 'close #ticket-17',
args: false, args: false,
async execute(client, message, args, { async execute(client, message, args, { config, Ticket }) {
config,
Ticket
}) {
const guild = client.guilds.cache.get(config.guild); const guild = client.guilds.cache.get(config.guild);
const notTicket = new MessageEmbed() const notTicket = new MessageEmbed()
@ -49,11 +45,8 @@ module.exports = {
channel: channel.id channel: channel.id
} }
}); });
if (!ticket) if (!ticket) return channel.send(notTicket);
return channel.send(notTicket);
} else { } else {
ticket = await Ticket.findOne({ ticket = await Ticket.findOne({
where: { where: {
channel: channel.id channel: channel.id
@ -102,7 +95,7 @@ module.exports = {
}); });
collector.on('collect', async () => { collector.on('collect', async () => {
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)
@ -111,6 +104,7 @@ module.exports = {
.setDescription(`Ticket closed by ${message.author}`) .setDescription(`Ticket closed by ${message.author}`)
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
}
confirm.reactions.removeAll(); confirm.reactions.removeAll();
confirm.edit( confirm.edit(
@ -149,16 +143,13 @@ module.exports = {
}]; }];
} }
if ( if (fs.existsSync(`user/transcripts/raw/${ticket.get('channel')}.log`) && fs.existsSync(`user/transcripts/raw/entities/${ticket.get('channel')}.json`)) {
fs.existsSync(`user/transcripts/raw/${ticket.get('channel')}.log`)
&&
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}`);
}
res.embed = embed; res.embed = embed;
@ -166,7 +157,6 @@ module.exports = {
} }
} }
// update database // update database
success = true; success = true;
ticket.update({ ticket.update({
@ -187,7 +177,7 @@ module.exports = {
log.info(`${message.author.tag} closed a ticket (#ticket-${ticket.id})`); log.info(`${message.author.tag} closed a ticket (#ticket-${ticket.id})`);
if (config.logs.discord.enabled) if (config.logs.discord.enabled) {
client.channels.cache.get(config.logs.discord.channel).send( client.channels.cache.get(config.logs.discord.channel).send(
new MessageEmbed() new MessageEmbed()
.setColor(config.colour) .setColor(config.colour)
@ -198,6 +188,7 @@ module.exports = {
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
.setTimestamp() .setTimestamp()
); );
}
}); });

View File

@ -24,7 +24,6 @@ module.exports = {
config, config,
Ticket Ticket
}) { }) {
const guild = client.guilds.cache.get(config.guild); const guild = client.guilds.cache.get(config.guild);
const notTicket = new MessageEmbed() const notTicket = new MessageEmbed()
@ -48,11 +47,9 @@ module.exports = {
channel: channel.id channel: channel.id
} }
}); });
if (!ticket) if (!ticket) return channel.send(notTicket);
return channel.send(notTicket);
} else { } else {
ticket = await Ticket.findOne({ ticket = await Ticket.findOne({
where: { where: {
channel: channel.id channel: channel.id
@ -65,7 +62,7 @@ module.exports = {
return message.channel.send(notTicket); return message.channel.send(notTicket);
} }
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 channel.send( return channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -77,6 +74,7 @@ module.exports = {
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
} }
}
let success; let success;
@ -124,14 +122,9 @@ 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)) fs.unlinkSync(raw);
if (fs.existsSync(json)) fs.unlinkSync(json);
if (fs.existsSync(raw))
fs.unlinkSync(raw);
if (fs.existsSync(json))
fs.unlinkSync(json);
// update database // update database
success = true; success = true;
@ -147,7 +140,7 @@ module.exports = {
log.info(`${message.author.tag} deleted a ticket (#ticket-${ticket.id})`); log.info(`${message.author.tag} deleted a ticket (#ticket-${ticket.id})`);
if (config.logs.discord.enabled) if (config.logs.discord.enabled) {
client.channels.cache.get(config.logs.discord.channel).send( client.channels.cache.get(config.logs.discord.channel).send(
new MessageEmbed() new MessageEmbed()
.setColor(config.colour) .setColor(config.colour)
@ -158,6 +151,7 @@ module.exports = {
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
.setTimestamp() .setTimestamp()
); );
}
}); });

View File

@ -18,7 +18,6 @@ module.exports = {
example: 'help new', example: 'help new',
args: false, args: false,
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());
@ -27,15 +26,12 @@ module.exports = {
let cmds = []; let cmds = [];
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)) continue;
if (command.permission && !message.member.hasPermission(command.permission))
continue;
let desc = command.description; let desc = command.description;
if (desc.length > 50) if (desc.length > 50) desc = desc.substring(0, 50) + '...';
desc = desc.substring(0, 50) + '...';
cmds.push(`**${config.prefix}${command.name}** **·** ${desc}`); cmds.push(`**${config.prefix}${command.name}** **·** ${desc}`);
} }
@ -71,11 +67,9 @@ module.exports = {
.setTitle(command.name); .setTitle(command.name);
if (command.long) { if (command.long) cmd.setDescription(command.long);
cmd.setDescription(command.long); else cmd.setDescription(command.description);
} else {
cmd.setDescription(command.description);
}
if (command.aliases) cmd.addField('Aliases', `\`${command.aliases.join(', ')}\``, true); if (command.aliases) cmd.addField('Aliases', `\`${command.aliases.join(', ')}\``, true);
if (command.usage) cmd.addField('Usage', `\`${config.prefix}${command.name} ${command.usage}\``, false); if (command.usage) cmd.addField('Usage', `\`${config.prefix}${command.name} ${command.usage}\``, false);
@ -85,12 +79,9 @@ module.exports = {
if (command.permission && !message.member.hasPermission(command.permission)) { if (command.permission && !message.member.hasPermission(command.permission)) {
cmd.addField('Required Permission', `\`${command.permission}\` :exclamation: You don't have permission to use this command`, true); cmd.addField('Required Permission', `\`${command.permission}\` :exclamation: You don't have permission to use this command`, true);
} 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);
} }
// command ends here // command ends here

View File

@ -19,7 +19,6 @@ 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);
@ -75,9 +74,7 @@ module.exports = {
.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())
); );
else if (topic.length < 1) else if (topic.length < 1) topic = 'No topic given';
topic = 'No topic given';
let ticket = await Ticket.create({ let ticket = await Ticket.create({
channel: '', channel: '',
@ -175,8 +172,7 @@ module.exports = {
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
if (config.tickets.pin) if (config.tickets.pin) await w.pin();
await w.pin();
// await w.pin().then(m => m.delete()); // oopsie, this deletes the pinned message // await w.pin().then(m => m.delete()); // oopsie, this deletes the pinned message
if (config.logs.discord.enabled) if (config.logs.discord.enabled)

View File

@ -18,19 +18,19 @@ module.exports = {
example: '', example: '',
args: false, args: false,
permission: 'MANAGE_GUILD', permission: 'MANAGE_GUILD',
async execute(client, message, args, {config, Setting}) { async execute(client, message, _args, {config, Setting}) {
const guild = client.guilds.cache.get(config.guild); const guild = client.guilds.cache.get(config.guild);
let msgID = await Setting.findOne({ where: { key: 'panel_msg_id' } }); let msgID = await Setting.findOne({ where: { key: 'panel_msg_id' } });
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({
@ -40,12 +40,12 @@ module.exports = {
} else { } else {
try { try {
panel = await client.channels.cache.get(chanID.get('value')).messages.fetch(msgID.get('value')); // get old panel message panel = await client.channels.cache.get(chanID.get('value')).messages.fetch(msgID.get('value')); // get old panel message
if (panel) if (panel) {
panel.delete({ reason: 'Creating new panel/widget' }).then(() => log.info('Deleted old panel')).catch(e => log.warn(e)); // delete old panel panel.delete({ reason: 'Creating new panel/widget' }).then(() => log.info('Deleted old panel')).catch(e => log.warn(e)); // delete old panel
}
} catch (e) { } catch (e) {
log.warn('Couldn\'t delete old panel'); log.warn('Couldn\'t delete old panel');
} }
} }
message.delete(); message.delete();

View File

@ -18,7 +18,6 @@ module.exports = {
example: 'remove @member from #ticket-23', example: 'remove @member from #ticket-23',
args: true, args: true,
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 notTicket = new MessageEmbed() const notTicket = new MessageEmbed()
@ -52,7 +51,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,8 +62,7 @@ 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]));
@ -88,7 +86,7 @@ module.exports = {
READ_MESSAGE_HISTORY: false READ_MESSAGE_HISTORY: false
}); });
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)
@ -97,8 +95,7 @@ module.exports = {
.setDescription(`${member} has been removed by ${message.author}`) .setDescription(`${member} has been removed by ${message.author}`)
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
}
message.channel.send( message.channel.send(
new MessageEmbed() new MessageEmbed()

View File

@ -15,8 +15,7 @@ module.exports = {
aliases: ['data', 'statistics'], aliases: ['data', 'statistics'],
example: '', example: '',
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);
let open = await Ticket.count({ where: { open: true } }); let open = await Ticket.count({ where: { open: true } });

View File

@ -17,11 +17,10 @@ module.exports = {
example: '', example: '',
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(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -29,12 +28,13 @@ module.exports = {
.setDescription(`${config.name} has not been set up correctly. Could not find a 'support team' role with the id \`${config.staff_role}\``) .setDescription(`${config.name} has not been set up correctly. Could not find a 'support team' role with the id \`${config.staff_role}\``)
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
}
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(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -45,12 +45,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())
); );
context = 'staff';
} else {
user = message.author;
} }
context = 'staff';
} else user = message.author;
let openTickets = await Ticket.findAndCountAll({ let openTickets = await Ticket.findAndCountAll({
where: { where: {
@ -74,29 +72,30 @@ module.exports = {
.setTitle(`${context === 'self' ? 'Your' : user.username + '\'s'} tickets`) .setTitle(`${context === 'self' ? 'Your' : user.username + '\'s'} tickets`)
.setFooter(guild.name + ' | This message will be deleted in 60 seconds', guild.iconURL()); .setFooter(guild.name + ' | This message will be deleted in 60 seconds', guild.iconURL());
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 = '';
let c = closedTickets.rows[t].channel; let c = closedTickets.rows[t].channel;
if(fs.existsSync(`user/transcripts/text/${c}.txt`) || config.transcripts.web.enabled) if (fs.existsSync(`user/transcripts/text/${c}.txt`) || config.transcripts.web.enabled) {
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);

View File

@ -16,7 +16,6 @@ module.exports = {
example: 'topic need help error', example: 'topic need help error',
args: true, args: true,
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);
let ticket = await Ticket.findOne({ let ticket = await Ticket.findOne({
@ -25,7 +24,7 @@ module.exports = {
} }
}); });
if (!ticket) if (!ticket) {
return message.channel.send( return message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -36,10 +35,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 topic = args.join(' '); let topic = args.join(' ');
if (topic.length > 256) if (topic.length > 256) {
return message.channel.send( return message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -48,6 +47,7 @@ module.exports = {
.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);
@ -59,7 +59,6 @@ module.exports = {
} }
}); });
message.channel.send( message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.colour) .setColor(config.colour)

View File

@ -19,7 +19,6 @@ module.exports = {
example: 'transcript 57', example: 'transcript 57',
args: true, args: true,
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 id = args[0]; const id = args[0];
@ -31,7 +30,7 @@ module.exports = {
}); });
if (!ticket) if (!ticket) {
return message.channel.send( return message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -40,8 +39,9 @@ module.exports = {
.setDescription('Couldn\'t find a closed ticket with that ID') .setDescription('Couldn\'t find a closed ticket with that ID')
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
}
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)
@ -50,6 +50,8 @@ module.exports = {
.setDescription(`You don't have permission to view ticket ${id} as it does not belong to you and you are not staff.`) .setDescription(`You don't have permission to view ticket ${id} as it does not belong to you and you are not staff.`)
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
}
let res = {}; let res = {};
const embed = new MessageEmbed() const embed = new MessageEmbed()
.setColor(config.colour) .setColor(config.colour)
@ -69,11 +71,9 @@ 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) embed.addField('Web archive', `${BASE_URL}/${ticket.creator}/${ticket.channel}`);
embed.addField('Web archive', `${BASE_URL}/${ticket.creator}/${ticket.channel}`);
if (embed.fields.length < 1) if (embed.fields.length < 1) embed.setDescription(`No text transcripts or archive data exists for ticket ${id}`);
embed.setDescription(`No text transcripts or archive data exists for ticket ${id}`);
res.embed = embed; res.embed = embed;
@ -85,8 +85,7 @@ module.exports = {
} }
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});
}); });
message.delete({timeout: 1500}); message.delete({timeout: 1500});
} }

View File

@ -11,7 +11,7 @@ const log = new ChildLogger();
module.exports = { module.exports = {
event: 'debug', event: 'debug',
execute(client, [e]) { execute(_client, [e]) {
log.debug(e); log.debug(e);
} }
}; };

View File

@ -11,7 +11,7 @@ const log = new ChildLogger();
module.exports = { module.exports = {
event: 'error', event: 'error',
execute(client, [e]) { execute(_client, [e]) {
log.error(e); log.error(e);
} }
}; };

View File

@ -30,8 +30,7 @@ Type \`${config.prefix}new\` on the server to create a new ticket.`);
*/ */
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
@ -52,8 +51,7 @@ Type \`${config.prefix}new\` on the server to create a new ticket.`);
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) return message.reply(`This bot can only be used within the "${guild}" server`); // not in this server
return message.reply(`This bot can only be used within the "${guild}" server`); // not in this server
if (command.permission && !message.member.hasPermission(command.permission)) { if (command.permission && !message.member.hasPermission(command.permission)) {
log.console(`${message.author.tag} tried to use the '${command.name}' command without permission`); log.console(`${message.author.tag} tried to use the '${command.name}' command without permission`);
@ -66,7 +64,7 @@ Type \`${config.prefix}new\` on the server to create a new ticket.`);
); );
} }
if (command.args && !args.length) if (command.args && !args.length) {
return message.channel.send( return message.channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -74,6 +72,7 @@ Type \`${config.prefix}new\` on the server to create a new ticket.`);
.addField('Help', `Type \`${config.prefix}help ${command.name}\` for more information`) .addField('Help', `Type \`${config.prefix}help ${command.name}\` for more information`)
.setFooter(guild.name, guild.iconURL()) .setFooter(guild.name, guild.iconURL())
); );
}
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());

View File

@ -12,11 +12,10 @@ const fs = require('fs');
module.exports = { module.exports = {
event: 'messageDelete', event: 'messageDelete',
async execute(client, [message], {config, Ticket}) { async execute(_client, [message], {config, Ticket}) {
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) {
@ -24,6 +23,7 @@ module.exports = {
log.error(err.message); log.error(err.message);
return; return;
} }
}
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;
@ -31,8 +31,7 @@ module.exports = {
let path = `user/transcripts/raw/${message.channel.id}.log`; let path = `user/transcripts/raw/${message.channel.id}.log`;
let embeds = []; let embeds = [];
for (let embed in message.embeds) for (let embed in message.embeds) embeds.push(message.embeds[embed].toJSON());
embeds.push(message.embeds[embed].toJSON());
fs.appendFileSync(path, JSON.stringify({ fs.appendFileSync(path, JSON.stringify({
id: message.id, id: message.id,
@ -44,6 +43,5 @@ module.exports = {
edited: message.edits.length > 1, edited: message.edits.length > 1,
deleted: true // delete the message deleted: true // delete the message
}) + '\n'); }) + '\n');
} }
}; };

View File

@ -14,14 +14,14 @@ const fs = require('fs');
module.exports = { 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) {
log.error(err); log.error(err);
return; return;
} }
}
let panelID = await Setting.findOne({ where: { key: 'panel_msg_id' } }); let panelID = await Setting.findOne({ where: { key: 'panel_msg_id' } });
if (!panelID) return; if (!panelID) return;
@ -35,7 +35,7 @@ module.exports = {
let channel = r.message.channel; let channel = r.message.channel;
const supportRole = channel.guild.roles.cache.get(config.staff_role); const supportRole = channel.guild.roles.cache.get(config.staff_role);
if (!supportRole) if (!supportRole) {
return channel.send( return channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -43,7 +43,7 @@ module.exports = {
.setDescription(`${config.name} has not been set up correctly. Could not find a 'support team' role with the id \`${config.staff_role}\``) .setDescription(`${config.name} has not been set up correctly. Could not find a 'support team' role with the id \`${config.staff_role}\``)
.setFooter(channel.guild.name, channel.guild.iconURL()) .setFooter(channel.guild.name, channel.guild.iconURL())
); );
}
// everything is cool // everything is cool
@ -67,7 +67,6 @@ module.exports = {
let dm = u.dmChannel || await u.createDM(); let dm = u.dmChannel || await u.createDM();
try { try {
return dm.send( return dm.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -76,10 +75,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) {
let m = await channel.send( let m = await channel.send(
new MessageEmbed() new MessageEmbed()
.setColor(config.err_colour) .setColor(config.err_colour)
@ -88,11 +84,8 @@ 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)';
@ -130,7 +123,6 @@ module.exports = {
], ],
reason: 'User requested a new support ticket channel' reason: 'User requested a new support ticket channel'
}).then(async c => { }).then(async c => {
Ticket.update({ Ticket.update({
channel: c.id channel: c.id
}, { }, {
@ -179,8 +171,7 @@ module.exports = {
.setFooter(channel.guild.name, channel.guild.iconURL()) .setFooter(channel.guild.name, channel.guild.iconURL())
); );
if (config.tickets.pin) if (config.tickets.pin) await w.pin();
await w.pin();
// await w.pin().then(m => m.delete()); // oopsie, this deletes the pinned message // await w.pin().then(m => m.delete()); // oopsie, this deletes the pinned message
if (config.logs.discord.enabled) if (config.logs.discord.enabled)
@ -197,8 +188,6 @@ module.exports = {
); );
log.info(`${u.tag} created a new ticket (#${name}) via panel`); log.info(`${u.tag} created a new ticket (#${name}) via panel`);
}).catch(log.error); }).catch(log.error);
} }
}; };

View File

@ -12,33 +12,33 @@ const fs = require('fs');
module.exports = { module.exports = {
event: 'messageUpdate', event: 'messageUpdate',
async execute(client, [o, n], {config, Ticket}) { async execute(_client, [o, n], {config, Ticket}) {
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) {
log.error(err); log.error(err);
return; return;
} }
}
if (n.partial) if (n.partial) {
try { try {
await n.fetch(); await n.fetch();
} catch (err) { } catch (err) {
log.error(err); log.error(err);
return; return;
} }
}
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 = [];
for (let embed in n.embeds) for (let embed in n.embeds) embeds.push({ ...n.embeds[embed] });
embeds.push({ ...n.embeds[embed] });
fs.appendFileSync(path, JSON.stringify({ fs.appendFileSync(path, JSON.stringify({
id: n.id, id: n.id,
@ -50,6 +50,5 @@ module.exports = {
edited: true edited: true
}) + '\n'); }) + '\n');
} }
}; };

View File

@ -11,7 +11,7 @@ const log = new ChildLogger();
module.exports = { module.exports = {
event: 'rateLimit', event: 'rateLimit',
execute(client, [limit]) { execute(_client, [limit]) {
log.warn('Rate-limited! (Enable debug mode in config for details)'); log.warn('Rate-limited! (Enable debug mode in config for details)');
log.debug(limit); log.debug(limit);
} }

View File

@ -13,7 +13,6 @@ const config = require('../../user/' + require('../').config);
module.exports = { module.exports = {
event: 'ready', event: 'ready',
execute(client) { execute(client) {
log.success(`Authenticated as ${client.user.tag}`); log.success(`Authenticated as ${client.user.tag}`);
const updatePresence = () => { const updatePresence = () => {
@ -33,10 +32,8 @@ module.exports = {
}, 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

@ -11,7 +11,7 @@ const log = new ChildLogger();
module.exports = { module.exports = {
event: 'warn', event: 'warn',
execute(client, [e]) { execute(_client, [e]) {
log.warn(e); log.warn(e);
} }
}; };

View File

@ -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',
@ -123,8 +148,7 @@ const clean = () => {
total++; total++;
} }
} }
if (total > 0) if (total > 0) log.info(`Deleted ${total} old text ${utils.plural('transcript', total)}`);
log.info(`Deleted ${total} old text ${utils.plural('transcript', total)}`);
}; };
if (config.transcripts.text.enabled) { if (config.transcripts.text.enabled) {

View File

@ -33,8 +33,7 @@ module.exports.add = (message) => {
json = `user/transcripts/raw/entities/${message.channel.id}.json`; json = `user/transcripts/raw/entities/${message.channel.id}.json`;
let embeds = []; let embeds = [];
for (let embed in message.embeds) for (let embed in message.embeds) embeds.push({ ...message.embeds[embed] });
embeds.push({ ...message.embeds[embed] });
// message // message
fs.appendFileSync(raw, JSON.stringify({ fs.appendFileSync(raw, JSON.stringify({
@ -104,8 +103,7 @@ module.exports.export = (Ticket, channel) => new Promise((resolve, reject) => {
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));
@ -122,15 +120,12 @@ module.exports.export = (Ticket, channel) => new Promise((resolve, reject) => {
lineReader.eachLine(raw, line => { lineReader.eachLine(raw, line => {
let message = JSON.parse(line); let message = JSON.parse(line);
let index = data.messages.findIndex(m => m.id === message.id); let index = data.messages.findIndex(m => m.id === message.id);
if (index === -1) if (index === -1) data.messages.push(message);
data.messages.push(message); else data.messages[index] = message;
else
data.messages[index] = message;
}, () => { }, () => {
let endpoint = config.transcripts.web.server; let endpoint = config.transcripts.web.server;
if (endpoint[endpoint.length - 1] === '/') if (endpoint[endpoint.length - 1] === '/') endpoint = endpoint.slice(0, -1);
endpoint = endpoint.slice(0, -1);
endpoint += `/${data.ticket.creator}/${data.ticket.channel}/?key=${process.env.ARCHIVES_KEY}`; endpoint += `/${data.ticket.creator}/${data.ticket.channel}/?key=${process.env.ARCHIVES_KEY}`;
@ -157,7 +152,5 @@ module.exports.export = (Ticket, channel) => new Promise((resolve, reject) => {
return resolve(e); return resolve(e);
}); });
}); });
})(); })();
}); });

View File

@ -15,13 +15,9 @@ 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')
.then(res => res.json())
.then(json => {
const update = json[0]; const update = json[0];
let notice = []; let notice = [];
@ -42,5 +38,4 @@ module.exports = () => {
}) })
); );
} }
});
}; };

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