discord-tickets
Version:
Discord.js extention library for manage easily tickets
273 lines (272 loc) • 10.4 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ThreadManager = void 0;
const BaseManager_1 = require("../Base/BaseManager");
/**
* @external ThreadChannel
* @see {@link https://discord.js.org/#/docs/main/stable/class/ThreadChannel}
*/
/**
* @external Client
* @see {@link https://discord.js.org/#/docs/main/stable/class/Client}
*/
/**
* @external Collection
* @see {@link https://discord.js.org/#/docs/collection/stable/class/Collection}
*/
/**
* @external Guild
* @see {@link https://discord.js.org/#/docs/main/stable/class/Guild}
*/
/**
* @external GuildMember
* @see {@link https://discord.js.org/#/docs/main/stable/class/GuildMember}
*/
/**
* @external TextChannel
* @see {@link https://discord.js.org/#/docs/main/stable/class/TextChannel}
*/
/**
* @external Role
* @see {@link https://discord.js.org/#/docs/main/stable/class/Role}
*/
/**
* @external Message
* @see {@link https://discord.js.org/#/docs/main/stable/class/Message}
*/
const discord_js_1 = require("discord.js");
const ThreadTicket_1 = require("./ThreadTicket");
/**
* Thread Ticket Manager
* @extends {BaseManager}
*/
class ThreadManager extends BaseManager_1.BaseManager {
constructor(client, options) {
super(client, options);
/**
* The Discord Client
* @readonly
* @type {Client}
*/
if (!client)
throw new Error('Client is a required option.');
this.client = client;
/**
* The manager options
* @type {ThreadManagerOptions}
*/
this.options = options;
/**
* Collection with all tickets (tickets's cache)
* @type {Collection<string, TicketData>}
*/
this.tickets = new discord_js_1.Collection();
this.cachingTickets().then(r => null);
}
/**
* Caching raws tickets into Array
* @return {Promise<void>}
* @private
*/
cachingTickets() {
return __awaiter(this, void 0, void 0, function* () {
this.ticketRaws = yield this.getAllTickets();
if (this.options.ticketCache) {
this.ticketRaws.forEach(ticket => {
this.tickets.set(ticket.channel, new ThreadTicket_1.ThreadTicket(this, ticket));
});
}
});
}
/**
* Get options
* @private
* @param {string} id
* @return {ThreadManagerOptions}
*/
// @ts-ignore
getOptions(id) {
return __awaiter(this, void 0, void 0, function* () {
return this.options;
});
}
/**
* Create Ticket
* @param {Guild} guild Discord Guild
* @param {GuildMember} member Discord Guild Member
* @return {Promise<TextTicket>}
* @example
* //Create Thread Ticket
* await ticketThread.createTicket(message.guild, message.member)
*/
createTicket(guild, member) {
return __awaiter(this, void 0, void 0, function* () {
const options = yield this.getOptions(guild.id);
if (!options)
throw new Error("Cannot find options");
const channel = guild.channels.cache.get(options.channelId);
if (!channel || channel.type !== "GUILD_TEXT")
throw new Error("Cannot find tickets channel, please check id/if channel type is GUILD_TEXT");
const guildsTickets = this.ticketRaws.filter(ticket => ticket.guild === guild.id);
let number;
if (guildsTickets.length > 0) {
number = guildsTickets.sort((ticketA, ticketB) => ticketB.number - ticketA.number)[0].number;
}
else
number = 0;
number = (parseInt(String(number)) + 1).toString();
let newNumber = "0000" + number;
newNumber = newNumber.slice(newNumber.length - 4, newNumber.length + 2);
const message = yield channel.send(`ticket-${newNumber}`);
if (!message)
throw new Error("Cannot find Message thread's creation");
let thread = yield channel.threads.create({
startMessage: message,
name: `ticket-${newNumber}`,
reason: `Create Thread Ticket for ${member.user.tag}`,
autoArchiveDuration: "MAX",
type: "GUILD_PRIVATE_THREAD",
invitable: false
});
yield thread.members.add(member.user);
yield thread.members.add("@me");
let role = guild.roles.cache.get(options.staffRole);
if (!role)
throw new Error("Cannot find staff role");
role.members.forEach(m => {
thread.members.add(m.user);
});
const data = {
guild: guild.id,
channel: thread.id,
member: member.id,
// @ts-ignore
number: number,
status: "open",
participants: [member.id],
type: "thread"
};
this.ticketRaws.push(data);
yield this.saveTicketRaws();
const ticket = new ThreadTicket_1.ThreadTicket(this, data);
if (this.options.ticketCache) {
this.tickets.set(data.channel, new ThreadTicket_1.ThreadTicket(this, data));
}
yield message.delete();
/**
* Emitted when user create ticket
* @event ThreadManager#ticketCreate
* @param {ThreadManager} ticket Ticket resolvable
*/
this.emit("ticketCreate", ticket);
return ticket;
});
}
/**
* Delete Ticket
* @param {TextTicket} ticket Ticket class
* @return {Promise<any>}
*/
deleteTicket(ticket) {
return __awaiter(this, void 0, void 0, function* () {
yield ticket.channel.delete();
this.ticketRaws = this.ticketRaws.filter(y => y.channel !== ticket.channelId);
yield this.saveTicketRaws();
if (this.options.ticketCache) {
this.tickets.delete(ticket.channelId);
}
/**
* Emitted when ticket be delete
* @event ThreadManager#ticketDeleted
* @param {ThreadTicket} ticket Ticket resolvable
*/
return this.emit("ticketDeleted", ticket);
});
}
/**
* Close Ticket
* @param {TextTicket} ticket Ticket class
* @return {Promise<any>}
*/
closeTicket(ticket) {
return __awaiter(this, void 0, void 0, function* () {
yield ticket.channel.members.remove(ticket.member.id);
yield ticket.channel.setArchived(true);
let data = ticket.data;
data.status = "closed";
ticket = new ThreadTicket_1.ThreadTicket(this, data);
this.tickets.set(ticket.channelId, ticket);
let index = this.ticketRaws.indexOf(data);
this.ticketRaws[index] = data;
yield this.saveTicketRaws();
/**
* Emitted when ticket be closed
* @event ThreadManager#ticketClosed
* @param {TextTicket} ticket Ticket resolvable
*/
return this.emit("ticketClosed", ticket);
});
}
/**
* ReOpen ticket
* @param {TextTicket} ticket Ticket Resolvable
* @return {Promise<any>}
*/
reOpenTicket(ticket) {
return __awaiter(this, void 0, void 0, function* () {
yield ticket.channel.setArchived(false);
yield ticket.channel.members.add(ticket.member.user);
let data = ticket.data;
data.status = "open";
ticket = new ThreadTicket_1.ThreadTicket(this, data);
this.tickets.set(ticket.channelId, ticket);
let index = this.ticketRaws.indexOf(data);
this.ticketRaws[index] = data;
yield this.saveTicketRaws();
/**
* Emitted when ticket be reopen
* @event ThreadManager#ticketReOpen
* @param {ThreadTicket} ticket Ticket resolvable
*/
return this.emit("ticketReOpen", ticket);
});
}
/**
* Rename Ticket
* @param {ThreadTicket} ticket ThreadTicket
* @param {string} name new Name
* @return {Promise<any>}
*/
renameTicket(ticket, name) {
return __awaiter(this, void 0, void 0, function* () {
let newNumber = "0000" + ticket.number;
newNumber = newNumber.slice(newNumber.length - 4, newNumber.length + 2);
yield ticket.channel.setName(`${name}-${newNumber}`);
/**
* Emitted when ticket be renamed
* @event ThreadManager#ticketRename
* @param {ThreadTicket} ticket Ticket resolvable
*/
return this.emit("ticketRename", ticket);
});
}
}
exports.ThreadManager = ThreadManager;
/**
* Threads Ticket Manager Config Types
* @typedef {object} ThreadManagerOptions
* @property {boolean} enabled Manager status
* @property {string} channelId Discord Channel Id where are created tickets
* @property {string} staffRole Discord Role id who can access to tickets
* @property {boolean} ticketCache Storing tickets in the cache
* @property {StorageType} storage Storage File path
*/