Development (#11)
We need this NOW.
---------
Co-authored-by: PineaFan <ash@pinea.dev>
Co-authored-by: pineafan <pineapplefanyt@gmail.com>
Co-authored-by: PineappleFan <PineaFan@users.noreply.github.com>
Co-authored-by: Skyler <skyler3665@gmail.com>
diff --git a/src/premium/attachmentLogs.ts b/src/premium/attachmentLogs.ts
index 156503a..b2c8391 100644
--- a/src/premium/attachmentLogs.ts
+++ b/src/premium/attachmentLogs.ts
@@ -1,4 +1,4 @@
-import { getCommandMentionByName } from './../utils/getCommandMentionByName.js';
+import { getCommandMentionByName } from './../utils/getCommandDataByName.js';
import client from "../utils/client.js";
import keyValueList from "../utils/generateKeyValueList.js";
import singleNotify from "../utils/singleNotify.js";
@@ -8,12 +8,13 @@
import type { GuildTextBasedChannel, Message } from "discord.js";
export default async function logAttachment(message: Message): Promise<AttachmentLogSchema> {
+ if (message.guild) client.database.premium.hasPremium(message.guild.id).finally(() => {});
if (!message.guild) throw new Error("Tried to log an attachment in a non-guild message");
const { renderUser, renderChannel, renderDelta } = client.logger;
const attachments = [];
for (const attachment of message.attachments.values()) {
attachments.push({
- local: await saveAttachment(attachment.url),
+ local: (await saveAttachment(attachment.url))[0],
url: attachment.url,
height: attachment.height,
width: attachment.width,
@@ -24,7 +25,7 @@
for (const link of links) {
if (link.toLowerCase().match(/\.(jpg|jpeg|png|gif|gifv|webm|webp|mp4|wav|mp3|ogg)$/gi)) {
attachments.push({
- local: await saveAttachment(link),
+ local: (await saveAttachment(link))[0],
url: link,
height: null,
width: null
@@ -38,17 +39,17 @@
singleNotify(
"noAttachmentLogChannel",
message.guild.id,
- `No channel set for attachment logging. You can set one with ${await getCommandMentionByName("settings/logs/attachments")}`,
+ `No channel set for attachment logging. You can set one with ${getCommandMentionByName("settings/logs/attachments")}`,
"Warning"
);
return { files: attachments };
}
- const channelObj = await client.channels.fetch(channel);
+ const channelObj = await message.guild.channels.fetch(channel);
if (!channelObj) {
singleNotify(
"attachmentLogChannelDeleted",
message.guild.id,
- `Your attachment history channel was deleted or is not longer accessible. You can set a new one with ${await getCommandMentionByName("settings/logs/attachments")}`,
+ `Your attachment history channel was deleted or is not longer accessible. You can set a new one with ${getCommandMentionByName("settings/logs/attachments")}`,
"Warning"
);
return { files: attachments };
@@ -70,7 +71,6 @@
],
files: attachments.map((file) => file.local)
});
- // await client.database.guilds.write(interaction.guild.id, {[`tags.${name}`]: value});
client.database.guilds.write(message.guild.id, {
[`logging.attachments.saved.${message.channel.id}${message.id}`]: m.url
});
diff --git a/src/premium/createTranscript.ts b/src/premium/createTranscript.ts
index 04fdc08..67aed04 100644
--- a/src/premium/createTranscript.ts
+++ b/src/premium/createTranscript.ts
@@ -7,18 +7,23 @@
MessageComponentInteraction,
TextChannel,
ButtonStyle,
- User
+ User,
+ ThreadChannel
} from "discord.js";
import EmojiEmbed from "../utils/generateEmojiEmbed.js";
import getEmojiByName from "../utils/getEmojiByName.js";
-import { PasteClient, Publicity, ExpireDate } from "pastebin-api";
import client from "../utils/client.js";
+import { messageException } from '../utils/createTemporaryStorage.js';
-const pbClient = new PasteClient(client.config.pastebinApiKey);
+const noTopic = new EmojiEmbed()
+ .setTitle("User not found")
+ .setDescription("There is no user associated with this ticket.")
+ .setStatus("Danger")
+ .setEmoji("CONTROL.BLOCKCROSS")
export default async function (interaction: CommandInteraction | MessageComponentInteraction) {
if (interaction.channel === null) return;
- if (!(interaction.channel instanceof TextChannel)) return;
+ if (!(interaction.channel instanceof TextChannel || interaction.channel instanceof ThreadChannel)) return;
const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
let messages: Message[] = [];
@@ -29,95 +34,75 @@
const deleted = await (interaction.channel as TextChannel).bulkDelete(fetched, true);
deletedCount = deleted.size;
messages = messages.concat(Array.from(deleted.values() as Iterable<Message>));
+ if (messages.length === 1) messageException(interaction.guild!.id, interaction.channel.id, messages[0]!.id)
} while (deletedCount === 100);
+ messages = messages.filter(message => !(
+ message.components.some(
+ component => component.components.some(
+ child => child.customId?.includes("transcript") ?? false
+ )
+ )
+ ));
- let out = "";
- messages.reverse().forEach((message) => {
- if (!message.author.bot) {
- const sentDate = new Date(message.createdTimestamp);
- out += `${message.author.username}#${message.author.discriminator} (${
- message.author.id
- }) [${sentDate.toUTCString()}]\n`;
- const lines = message.content.split("\n");
- lines.forEach((line) => {
- out += `> ${line}\n`;
- });
- out += "\n\n";
- }
- });
- const topic = interaction.channel.topic;
- let member: GuildMember | null = null;
- if (topic !== null) {
- const part = topic.split(" ")[0] ?? null;
- if (part !== null) member = interaction.guild!.members.cache.get(part) ?? null;
- }
- let m: Message;
- if (out !== "") {
- const url = await pbClient.createPaste({
- code: out,
- expireDate: ExpireDate.Never,
- name:
- `Ticket Transcript ${
- member ? "for " + member.user.username + "#" + member.user.discriminator + " " : ""
- }` + `(Created at ${new Date(interaction.channel.createdTimestamp).toDateString()})`,
- publicity: Publicity.Unlisted
- });
- const guildConfig = await client.database.guilds.read(interaction.guild!.id);
- m = (await interaction.reply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Transcript")
- .setDescription(
- "You can view the transcript using the link below. You can save the link for later" +
- (guildConfig.logging.logs.channel
- ? ` or find it in <#${guildConfig.logging.logs.channel}> once you press delete below. After this the channel will be deleted.`
- : ".")
- )
- .setStatus("Success")
- .setEmoji("CONTROL.DOWNLOAD")
- ],
- components: [
- new ActionRowBuilder<ButtonBuilder>().addComponents([
- new ButtonBuilder().setLabel("View").setStyle(ButtonStyle.Link).setURL(url),
- new ButtonBuilder()
- .setLabel("Delete")
- .setStyle(ButtonStyle.Danger)
- .setCustomId("close")
- .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
- ])
- ],
- fetchReply: true
- })) as Message;
+ let topic
+ let member: GuildMember = interaction.guild?.members.me!;
+ if (interaction.channel instanceof TextChannel) {
+ topic = interaction.channel.topic;
+ if (topic === null) return await interaction.reply({ embeds: [noTopic] });
+ const mem = interaction.guild!.members.cache.get(topic.split(" ")[1]!);
+ if (mem) member = mem;
} else {
- m = (await interaction.reply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Transcript")
- .setDescription(
- "The transcript was empty, so no changes were made. To delete this ticket, press the delete button below."
- )
- .setStatus("Success")
- .setEmoji("CONTROL.DOWNLOAD")
- ],
- components: [
- new ActionRowBuilder<ButtonBuilder>().addComponents([
- new ButtonBuilder()
- .setLabel("Delete")
- .setStyle(ButtonStyle.Danger)
- .setCustomId("close")
- .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
- ])
- ],
- fetchReply: true
- })) as Message;
+ topic = interaction.channel.name;
+ const split = topic.split("-").map(p => p.trim()) as [string, string, string];
+ const mem = interaction.guild!.members.cache.get(split[1])
+ if (mem) member = mem;
}
+
+ const newOut = await client.database.transcripts.createTranscript(messages, interaction, member);
+
+ const code = await client.database.transcripts.create(newOut);
+ if(!code) return await interaction.reply({
+ embeds: [
+ new EmojiEmbed()
+ .setTitle("Error")
+ .setDescription("An error occurred while creating the transcript.")
+ .setStatus("Danger")
+ .setEmoji("CONTROL.BLOCKCROSS")
+ ]
+ })
+ const guildConfig = await client.database.guilds.read(interaction.guild!.id);
+ const m: Message = (await interaction.reply({
+ embeds: [
+ new EmojiEmbed()
+ .setTitle("Transcript")
+ .setDescription(
+ "You can view the transcript using the link below. You can save the link for later" +
+ (guildConfig.logging.logs.channel
+ ? ` or find it in <#${guildConfig.logging.logs.channel}> once you press delete below. After this the channel will be deleted.`
+ : ".")
+ )
+ .setStatus("Success")
+ .setEmoji("CONTROL.DOWNLOAD")
+ ],
+ components: [
+ new ActionRowBuilder<ButtonBuilder>().addComponents([
+ new ButtonBuilder().setLabel("View").setStyle(ButtonStyle.Link).setURL(`https://clicks.codes/nucleus/transcript/${code}`),
+ new ButtonBuilder()
+ .setLabel("Delete")
+ .setStyle(ButtonStyle.Danger)
+ .setCustomId("close")
+ .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+ ])
+ ],
+ fetchReply: true
+ })) as Message;
let i;
try {
i = await m.awaitMessageComponent({
time: 300000,
- filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id }
+ filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id && i.message.id === m.id }
});
- i.deferUpdate();
+ await i.deferUpdate();
} catch {
return;
}
@@ -128,12 +113,13 @@
calculateType: "ticketUpdate",
color: NucleusColors.red,
emoji: "GUILD.TICKET.CLOSE",
- timestamp: new Date().getTime()
+ timestamp: Date.now()
},
list: {
- ticketFor: member ? entry(member.id, renderUser(member.user)) : entry(null, "*Unknown*"),
+ ticketFor: entry(member.id, renderUser(member.user)),
deletedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user as User)),
- deleted: entry(new Date().getTime().toString(), renderDelta(new Date().getTime()))
+ deleted: entry(Date.now().toString(), renderDelta(Date.now())),
+ transcript: entry(code, `https://clicks.codes/nucleus/transcript/${code}`)
},
hidden: {
guild: interaction.guild!.id