Change private help ticket cooldown
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { ActionRowBuilder, ButtonInteraction, Client, ModalBuilder, TextInputBuilder, TextInputStyle, MessageFlags, ChannelType, PermissionFlagsBits, ButtonBuilder, ButtonStyle } from 'discord.js';
|
||||
import { ticketCooldownMap } from '../shared/ticket-cooldown';
|
||||
import { Database } from '../shared/Database';
|
||||
|
||||
export default {
|
||||
@@ -19,7 +18,7 @@ export default {
|
||||
const guildSettings = await Database.getGuildSettings(guild.id);
|
||||
|
||||
if (!guildSettings || !guildSettings.private_help_role_id)
|
||||
return interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'Failed to create ticket.' });
|
||||
return interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'Failed to claim ticket.' });
|
||||
|
||||
const closeButton = new ButtonBuilder()
|
||||
.setCustomId('close-ticket')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ActionRowBuilder, ButtonInteraction, Client, ModalBuilder, TextInputBuilder, TextInputStyle, MessageFlags, ChannelType, ButtonBuilder, ButtonStyle } from 'discord.js';
|
||||
import { ticketCooldownMap } from '../shared/ticket-cooldown';
|
||||
import { Database } from '../shared/Database';
|
||||
|
||||
export default {
|
||||
name: 'close-ticket',
|
||||
@@ -14,6 +14,8 @@ export default {
|
||||
components: []
|
||||
});
|
||||
|
||||
await Database.closePrivateHelpTicket(channel.id);
|
||||
|
||||
await channel.send(`This ticket has been closed by ${interaction.user}`);
|
||||
|
||||
await interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'Ticket closed.' });
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ActionRowBuilder, ButtonInteraction, Client, ModalBuilder, TextInputBuilder, TextInputStyle, MessageFlags } from 'discord.js';
|
||||
import { ticketCooldownMap } from '../shared/ticket-cooldown';
|
||||
import { Database } from '../shared/Database';
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import { ActionRowBuilder, ButtonInteraction, Client, ModalBuilder, TextInputBuilder, TextInputStyle, MessageFlags } from 'discord.js';
|
||||
import { ticketCooldownMap } from '../shared/ticket-cooldown';
|
||||
import { canOpenPrivateHelpTicket } from '../utils';
|
||||
|
||||
export default {
|
||||
name: 'private-help',
|
||||
handler: async function (client: Client, interaction: ButtonInteraction) {
|
||||
const allowedAt = ticketCooldownMap.get(interaction.user.id);
|
||||
|
||||
if (allowedAt && Date.now() < allowedAt)
|
||||
return interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'You can only create one ticket per day.' });
|
||||
if (!(await canOpenPrivateHelpTicket(interaction.user.id)))
|
||||
return interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'You can only have one open ticket at a time that is less than a day old.' });
|
||||
|
||||
const modal = new ModalBuilder()
|
||||
.setCustomId('open-ticket-modal')
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ActionRowBuilder, ButtonInteraction, Client, ModalBuilder, TextInputBuilder, TextInputStyle, MessageFlags, ChannelType, PermissionFlagsBits, ButtonBuilder, ButtonStyle } from 'discord.js';
|
||||
import { ticketCooldownMap } from '../shared/ticket-cooldown';
|
||||
import { Database } from '../shared/Database';
|
||||
|
||||
export default {
|
||||
@@ -21,7 +20,7 @@ export default {
|
||||
const guildSettings = await Database.getGuildSettings(guild.id);
|
||||
|
||||
if (!guildSettings || !guildSettings.private_help_role_id)
|
||||
return interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'Failed to create ticket.' });
|
||||
return interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'Failed to unclaim ticket.' });
|
||||
|
||||
const closeButton = new ButtonBuilder()
|
||||
.setCustomId('close-ticket')
|
||||
|
||||
@@ -6,7 +6,6 @@ import { checkExpiredBans, initIfNecessary, loadHandlersFrom, refreshCommands }
|
||||
import { initializeWebserver } from './webserver';
|
||||
import { Database } from './shared/Database';
|
||||
import { handleAuditLogCreate, handleBanRemove, handleBulkMessageDelete, handleGuildCreate, handleMemberJoin, handleMessageCreate, handleMessageDelete, handleMessageUpdate, handleThreadCreate, handleVoiceStateUpdate } from './events';
|
||||
import { pruneOldTickets, ticketCooldownMap } from './shared/ticket-cooldown';
|
||||
import { openRedisClient } from './shared/RedisClient';
|
||||
|
||||
let ready = false;
|
||||
@@ -137,9 +136,6 @@ client.on('ready', async () => {
|
||||
|
||||
await initializeWebserver(client);
|
||||
|
||||
// Prune ticket cooldowns that are expired every day
|
||||
setInterval(pruneOldTickets, 8.64e+7);
|
||||
|
||||
// Check for expired bans every 5 minutes
|
||||
checkExpiredBans(client);
|
||||
setInterval(checkExpiredBans.bind(null, client), 300000);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, Client, GuildTextBasedChannel, MessageFlags, ModalSubmitInteraction, TextChannel, ThreadAutoArchiveDuration } from 'discord.js';
|
||||
import { ticketCooldownMap } from '../shared/ticket-cooldown';
|
||||
import { Database } from '../shared/Database';
|
||||
import { logCustomEvent } from '../utils';
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, Client, GuildTextBasedChannel, MessageFlags, ModalSubmitInteraction, TextChannel, ThreadAutoArchiveDuration } from 'discord.js';
|
||||
import { ticketCooldownMap } from '../shared/ticket-cooldown';
|
||||
import { Database } from '../shared/Database';
|
||||
|
||||
export default {
|
||||
@@ -13,8 +12,6 @@ export default {
|
||||
if (!guildSettings || !guildSettings.private_help_role_id)
|
||||
return interaction.reply({ flags: [MessageFlags.Ephemeral], content: 'Failed to create ticket. Please report this to a staff member.' });
|
||||
|
||||
ticketCooldownMap.set(interaction.user.id, Date.now() + 8.64e+7);
|
||||
|
||||
const reason = interaction.fields.getTextInputValue('ticket-message');
|
||||
|
||||
const channel = (await interaction.channel?.fetch()) as TextChannel;
|
||||
@@ -26,6 +23,12 @@ export default {
|
||||
type: ChannelType.PrivateThread
|
||||
});
|
||||
|
||||
console.log(1);
|
||||
|
||||
await Database.createPrivateHelpTicket(interaction.user.id, thread.id);
|
||||
|
||||
console.log(2);
|
||||
|
||||
const closeButton = new ButtonBuilder()
|
||||
.setCustomId('close-ticket')
|
||||
.setLabel('Click here if you no longer need help')
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelType, Client, GuildTextBasedChannel, MessageFlags, ModalSubmitInteraction, TextChannel, ThreadAutoArchiveDuration } from 'discord.js';
|
||||
import { ticketCooldownMap } from '../shared/ticket-cooldown';
|
||||
import { Database } from '../shared/Database';
|
||||
import { deferInteraction, logCustomEvent, syncName } from '../utils';
|
||||
import { config } from '../config';
|
||||
|
||||
+35
-4
@@ -1,9 +1,7 @@
|
||||
import sqlite3 from 'sqlite3';
|
||||
import { open, Database as SqliteDatabase } from 'sqlite';
|
||||
import { config } from '../config';
|
||||
import DiscordOAuth2 from 'discord-oauth2';
|
||||
import { serializeMessage, wait } from '../utils';
|
||||
import { GuildSettings, LoggedMessage, TicketMessage, TicketPhrase, Note, Ban, GuildArraySetting, GithubUserMapping, KnowledgebaseItem } from '../types';
|
||||
import { GuildSettings, LoggedMessage, TicketMessage, TicketPhrase, Note, Ban, GuildArraySetting, GithubUserMapping, KnowledgebaseItem, PrivateHelpTicket } from '../types';
|
||||
import { Message } from '../events';
|
||||
|
||||
const DB_SCHEMA = `
|
||||
@@ -67,6 +65,8 @@ const DB_SCHEMA = `
|
||||
timestamp datetime NOT NULL DEFAULT (datetime('now', 'localtime'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS index_user_ids ON notes (user_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS note_edits (
|
||||
id INTEGER PRIMARY KEY,
|
||||
note_id INTEGER,
|
||||
@@ -93,9 +93,24 @@ const DB_SCHEMA = `
|
||||
guild_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
content TEXT NOT NULL
|
||||
)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS private_help_tickets (
|
||||
id INTEGER PRIMARY KEY,
|
||||
thread_id TEXT NOT NULL,
|
||||
user_id TEXT NOT NULL,
|
||||
status INTEGER NOT NULL,
|
||||
timestamp datetime NOT NULL DEFAULT (datetime('now', 'localtime'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS index_timestamp ON private_help_tickets (timestamp);
|
||||
`;
|
||||
|
||||
export const enum PrivateHelpTicketStatus {
|
||||
OPEN = 0,
|
||||
CLOSED = 1
|
||||
}
|
||||
|
||||
export class Database {
|
||||
private static db: SqliteDatabase;
|
||||
|
||||
@@ -434,4 +449,20 @@ export class Database {
|
||||
}
|
||||
|
||||
// -- END KNOWLEDGEBASE --
|
||||
|
||||
// -- START PRIVATE HELP TICKETS --
|
||||
|
||||
static async createPrivateHelpTicket(userId: string, threadId: string) {
|
||||
await Database.db.run('INSERT INTO private_help_tickets(user_id, thread_id, status) VALUES (?, ?, ?)', userId, threadId, PrivateHelpTicketStatus.OPEN);
|
||||
}
|
||||
|
||||
static async closePrivateHelpTicket(threadId: string) {
|
||||
await Database.db.run('UPDATE private_help_tickets SET status = ? WHERE thread_id = ?', PrivateHelpTicketStatus.CLOSED, threadId);
|
||||
}
|
||||
|
||||
static async getLatestPrivateHelpTicketBy(userId: string): Promise<PrivateHelpTicket | undefined> {
|
||||
return await Database.db.get<PrivateHelpTicket>('SELECT * from private_help_tickets WHERE user_id = ? ORDER BY timestamp DESC LIMIT 1', userId);
|
||||
}
|
||||
|
||||
// -- END PRIVATE HELP TICKETS
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
export const ticketCooldownMap = new Map<string, number>();
|
||||
|
||||
export function pruneOldTickets() {
|
||||
const keys = Array.from(ticketCooldownMap.keys());
|
||||
for (const key of keys) {
|
||||
if (Date.now() >= ticketCooldownMap.get(key)!)
|
||||
ticketCooldownMap.delete(key);
|
||||
}
|
||||
}
|
||||
Vendored
+7
@@ -65,4 +65,11 @@ export type KnowledgebaseItem = {
|
||||
guild_id: string
|
||||
name: string
|
||||
content: string
|
||||
}
|
||||
|
||||
export type PrivateHelpTicket = {
|
||||
id: number
|
||||
user_id: string
|
||||
status: PrivateHelpTicketStatus,
|
||||
timestamp: string
|
||||
}
|
||||
Vendored
+5
-5
@@ -1,5 +1,5 @@
|
||||
export * from './command';
|
||||
export * from './database-types';
|
||||
export * from './e621-types';
|
||||
export * from './handler';
|
||||
export * from './helper-types';
|
||||
export * from './command.d';
|
||||
export * from './database-types.d';
|
||||
export * from './e621-types.d';
|
||||
export * from './handler.d';
|
||||
export * from './helper-types.d';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Client, Guild, User } from 'discord.js';
|
||||
import { Database, PrivateHelpTicketStatus } from '../shared/Database';
|
||||
|
||||
export async function resolveUser(client: Client, value: string, guild: Guild | null = null): Promise<User | null | undefined> {
|
||||
let user: User | null | undefined = null;
|
||||
@@ -24,4 +25,12 @@ export async function resolveUser(client: Client, value: string, guild: Guild |
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
export async function canOpenPrivateHelpTicket(id: string): Promise<boolean> {
|
||||
const latestTicket = await Database.getLatestPrivateHelpTicketBy(id);
|
||||
|
||||
if (latestTicket && latestTicket.status == PrivateHelpTicketStatus.OPEN && Date.now() - new Date(latestTicket.timestamp).getTime() < 8.64e+7) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user