Compare commits
No commits in common. "afa0a70f8a86cfee054856d9fcf14d508d60fcdc" and "6f8435b699bbb3a9af87e14f7eb3b9d75fcf0741" have entirely different histories.
afa0a70f8a
...
6f8435b699
|
@ -1,13 +0,0 @@
|
|||
# Prod
|
||||
**/dist
|
||||
**/node_modules
|
||||
**/persist
|
||||
|
||||
# Files
|
||||
**/.env
|
||||
**/.prettierrc
|
||||
**/LICENSE
|
||||
**/package-lock.json
|
||||
**/package.json
|
||||
**/README.md
|
||||
**/tsconfig.json
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"trailingComma": "none",
|
||||
"arrowParens": "avoid"
|
||||
}
|
|
@ -6,7 +6,6 @@
|
|||
"scripts": {
|
||||
"build": "rm -rf ./dist && tsc -p .",
|
||||
"start": "node ./dist/main.js",
|
||||
"prettier": "if prettier -v >/dev/null 2>&1; then prettier . --write; else npx prettier . --write; fi",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "powermaker450",
|
||||
|
|
|
@ -19,5 +19,5 @@
|
|||
import { Client } from "discord.js";
|
||||
|
||||
export const BotClient = new Client({
|
||||
intents: ["Guilds", "GuildMessages", "DirectMessages"]
|
||||
intents: ["Guilds", "GuildMessages", "DirectMessages"],
|
||||
});
|
||||
|
|
|
@ -24,8 +24,8 @@ import Logger from "../utils/Logger";
|
|||
|
||||
const logger = new Logger("Deployer");
|
||||
|
||||
const commandsData = Object.values(commands).map(command =>
|
||||
command.data.toJSON()
|
||||
const commandsData = Object.values(commands).map((command) =>
|
||||
command.data.toJSON(),
|
||||
);
|
||||
|
||||
const rest = new REST({ version: "9" }).setToken(BOT_TOKEN);
|
||||
|
@ -35,7 +35,7 @@ export async function deployCommands({ guildId }: DeployCommandsProps) {
|
|||
logger.log("Started refreshing (/) commands.");
|
||||
|
||||
await rest.put(Routes.applicationGuildCommands(BOT_ID, guildId), {
|
||||
body: commandsData
|
||||
body: commandsData,
|
||||
});
|
||||
|
||||
logger.log("Successfully reloaded (/) commands.");
|
||||
|
|
|
@ -17,47 +17,35 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
CommandInteraction,
|
||||
ComponentType,
|
||||
EmbedBuilder,
|
||||
SlashCommandBuilder,
|
||||
TextChannel
|
||||
TextChannel,
|
||||
} from "discord.js";
|
||||
import { BotClient } from "../bot";
|
||||
import { dt } from "../main";
|
||||
import { StoreMan } from "../storeman";
|
||||
import getRandomColor from "../utils/getRandomColor";
|
||||
import Logger from "../utils/Logger";
|
||||
import { submit } from "../modals";
|
||||
|
||||
const logger = new Logger("(/) confess");
|
||||
|
||||
export const data = new SlashCommandBuilder()
|
||||
.setName("confess")
|
||||
.setDescription("Send a confession")
|
||||
.addStringOption(option =>
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("message")
|
||||
.setRequired(true)
|
||||
.setDescription("What you want to confess")
|
||||
)
|
||||
.addStringOption(option =>
|
||||
option
|
||||
.setName("attachment")
|
||||
.setDescription("The link to an image to attach (optional)")
|
||||
.setDescription("What you want to confess"),
|
||||
);
|
||||
|
||||
export async function execute(interaction: CommandInteraction) {
|
||||
// TODO: This all works as intended, but I'd like for it so be a reusable function
|
||||
// instead because all of this is reused in src/main.ts:56
|
||||
try {
|
||||
if (dt.isBanned(interaction.guild?.id!, interaction.user.id)) {
|
||||
return interaction.reply({
|
||||
content: "You are banned from confessions in this server!",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -65,7 +53,7 @@ export async function execute(interaction: CommandInteraction) {
|
|||
return interaction.reply({
|
||||
content:
|
||||
"The bot hasn't been set up yet! Ask the server admins to set it up.",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -74,12 +62,7 @@ export async function execute(interaction: CommandInteraction) {
|
|||
const adminChannel = dt.getGuildInfo(interaction.guild?.id!)?.settings
|
||||
.modChannel;
|
||||
// @ts-ignore
|
||||
const messageContent: string = interaction.options.getString("message");
|
||||
// @ts-ignore
|
||||
const attachment: string = interaction.options.getString("attachment");
|
||||
|
||||
const isAttachment = (text: string) =>
|
||||
text && (text.startsWith("http://") || text.startsWith("https://"));
|
||||
const messageContent = interaction.options.getString("message");
|
||||
|
||||
const color = getRandomColor();
|
||||
const messageId = StoreMan.genId();
|
||||
|
@ -89,8 +72,6 @@ export async function execute(interaction: CommandInteraction) {
|
|||
// @ts-ignore
|
||||
.setDescription(messageContent);
|
||||
|
||||
isAttachment(attachment) && userConfessionEmbed.setImage(attachment);
|
||||
|
||||
const adminConfessionEmbed = new EmbedBuilder()
|
||||
.setColor(color)
|
||||
.setTitle(`Anonymous Confession \`${messageId}\``)
|
||||
|
@ -99,44 +80,22 @@ export async function execute(interaction: CommandInteraction) {
|
|||
.addFields(
|
||||
{
|
||||
name: "Author",
|
||||
value: interaction.user.displayName
|
||||
value: interaction.user.displayName,
|
||||
},
|
||||
{
|
||||
name: "Author ID",
|
||||
value: interaction.user.id
|
||||
}
|
||||
value: interaction.user.id,
|
||||
},
|
||||
);
|
||||
|
||||
isAttachment(attachment) && adminConfessionEmbed.setImage(attachment);
|
||||
|
||||
const submitConfessionButton = new ButtonBuilder()
|
||||
.setCustomId("submitConfession")
|
||||
.setLabel("Submit a Confession")
|
||||
.setStyle(ButtonStyle.Primary);
|
||||
|
||||
const actionRow = new ActionRowBuilder<ButtonBuilder>().setComponents(
|
||||
submitConfessionButton
|
||||
);
|
||||
|
||||
const message = await (
|
||||
BotClient.channels.cache.get(confessChannel!) as TextChannel
|
||||
).send({
|
||||
embeds: [userConfessionEmbed],
|
||||
components: [actionRow]
|
||||
});
|
||||
|
||||
const collector = message.createMessageComponentCollector({
|
||||
componentType: ComponentType.Button
|
||||
});
|
||||
|
||||
collector.on("collect", i => {
|
||||
if (i.customId === "submitConfession") {
|
||||
i.showModal(submit);
|
||||
}
|
||||
});
|
||||
|
||||
await (BotClient.channels.cache.get(adminChannel!) as TextChannel).send({
|
||||
embeds: [adminConfessionEmbed]
|
||||
embeds: [adminConfessionEmbed],
|
||||
});
|
||||
|
||||
dt.addConfession(
|
||||
|
@ -145,29 +104,11 @@ export async function execute(interaction: CommandInteraction) {
|
|||
interaction.user.displayName,
|
||||
interaction.user.id,
|
||||
messageContent,
|
||||
attachment
|
||||
);
|
||||
|
||||
const confessionsLength = dt.getGuildInfo(interaction.guild?.id!)
|
||||
?.confessions.length!;
|
||||
|
||||
if (confessionsLength >= 2) {
|
||||
await (
|
||||
BotClient.channels.cache.get(confessChannel!) as TextChannel
|
||||
).messages
|
||||
.fetch(
|
||||
dt.getGuildInfo(interaction.guild?.id!)?.confessions[
|
||||
confessionsLength - 2
|
||||
].messageId!
|
||||
)
|
||||
.then(message => {
|
||||
message.edit({ components: [] });
|
||||
});
|
||||
}
|
||||
|
||||
return interaction.reply({
|
||||
content: "Confession sent!",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("An error occured:", err);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import {
|
||||
CommandInteraction,
|
||||
PermissionFlagsBits,
|
||||
SlashCommandBuilder
|
||||
SlashCommandBuilder,
|
||||
} from "discord.js";
|
||||
import { dt } from "../main";
|
||||
import Logger from "../utils/Logger";
|
||||
|
@ -29,11 +29,11 @@ const logger = new Logger("(/) confessban");
|
|||
export const data = new SlashCommandBuilder()
|
||||
.setName("confessban")
|
||||
.setDescription("Ban a user from submitting confessions.")
|
||||
.addStringOption(option =>
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("id")
|
||||
.setDescription("The confession ID to ban")
|
||||
.setRequired(true)
|
||||
.setRequired(true),
|
||||
)
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers);
|
||||
|
||||
|
@ -41,18 +41,18 @@ export async function execute(interaction: CommandInteraction) {
|
|||
const result = dt.addBan(
|
||||
interaction.guild?.id!,
|
||||
// @ts-ignore
|
||||
interaction.options.getString("id")
|
||||
interaction.options.getString("id"),
|
||||
);
|
||||
|
||||
try {
|
||||
return result
|
||||
? interaction.reply({
|
||||
content: "User was banned.",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
})
|
||||
: interaction.reply({
|
||||
content: "No confession with that ID was found.",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("An error occured:", err);
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Confoss: Anonymous confessions for Discord, free as in freedom and price!
|
||||
* Copyright (C) 2024 powermaker450
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
CommandInteraction,
|
||||
PermissionFlagsBits,
|
||||
SlashCommandBuilder
|
||||
} from "discord.js";
|
||||
import { dt } from "../main";
|
||||
import { BotClient } from "../bot";
|
||||
|
||||
export const data = new SlashCommandBuilder()
|
||||
.setName("confessbanlist")
|
||||
.setDescription("Get the current ban list")
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages);
|
||||
|
||||
export async function execute(interaction: CommandInteraction) {
|
||||
const bannedMembers = dt.getBans(interaction.guild?.id!);
|
||||
|
||||
let content = bannedMembers.length
|
||||
? "Banned Members:\n"
|
||||
: "There are no banned members.";
|
||||
|
||||
for (const member of bannedMembers) {
|
||||
const identifiedMember = await BotClient.users.fetch(member.user);
|
||||
|
||||
content += `\n${identifiedMember.displayName} | \`${member.confessionId}\``;
|
||||
}
|
||||
|
||||
return interaction.reply({
|
||||
content: content,
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
|
@ -20,7 +20,7 @@ import {
|
|||
CommandInteraction,
|
||||
EmbedBuilder,
|
||||
SlashCommandBuilder,
|
||||
TextChannel
|
||||
TextChannel,
|
||||
} from "discord.js";
|
||||
import { dt } from "../main";
|
||||
import { BotClient } from "../bot";
|
||||
|
@ -32,8 +32,8 @@ const logger = new Logger("(/) confessdel");
|
|||
export const data = new SlashCommandBuilder()
|
||||
.setName("confessdel")
|
||||
.setDescription("Deletes a confession")
|
||||
.addStringOption(option =>
|
||||
option.setName("id").setDescription("The confession id").setRequired(true)
|
||||
.addStringOption((option) =>
|
||||
option.setName("id").setDescription("The confession id").setRequired(true),
|
||||
);
|
||||
|
||||
export async function execute(interaction: CommandInteraction) {
|
||||
|
@ -41,7 +41,7 @@ export async function execute(interaction: CommandInteraction) {
|
|||
return interaction.reply({
|
||||
content:
|
||||
"The bot hasn't been set up yet! Ask the server admins to set it up.",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ export async function execute(interaction: CommandInteraction) {
|
|||
try {
|
||||
const confession = dt.getConfession(
|
||||
interaction.guild?.id!,
|
||||
idVal
|
||||
idVal,
|
||||
)?.messageId;
|
||||
const channelId = dt.getGuildInfo(interaction.guild?.id!)?.settings
|
||||
.confessChannel!;
|
||||
|
@ -65,9 +65,9 @@ export async function execute(interaction: CommandInteraction) {
|
|||
|
||||
await (BotClient.channels.cache.get(channelId) as TextChannel).messages
|
||||
.fetch(confession!)
|
||||
.then(e => {
|
||||
.then((e) => {
|
||||
e.edit({
|
||||
embeds: [emptyEmbed]
|
||||
embeds: [emptyEmbed],
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -75,7 +75,7 @@ export async function execute(interaction: CommandInteraction) {
|
|||
|
||||
return interaction.reply({
|
||||
content: "Confession removed.",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("An error occured:", err);
|
||||
|
@ -84,7 +84,7 @@ export async function execute(interaction: CommandInteraction) {
|
|||
return interaction.reply({
|
||||
content:
|
||||
"Either the confession wasn't found or you may not be allowed to remove it.",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
import {
|
||||
CommandInteraction,
|
||||
PermissionFlagsBits,
|
||||
SlashCommandBuilder
|
||||
SlashCommandBuilder,
|
||||
} from "discord.js";
|
||||
import { dt } from "../main";
|
||||
import Logger from "../utils/Logger";
|
||||
|
@ -29,11 +29,11 @@ const logger = new Logger("(/) confesspardon");
|
|||
export const data = new SlashCommandBuilder()
|
||||
.setName("confesspardon")
|
||||
.setDescription("Unbans a user from confessions")
|
||||
.addStringOption(option =>
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("id")
|
||||
.setDescription("The confession ID to unban")
|
||||
.setRequired(true)
|
||||
.setRequired(true),
|
||||
)
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages);
|
||||
|
||||
|
@ -41,18 +41,18 @@ export function execute(interaction: CommandInteraction) {
|
|||
const result = dt.removeBan(
|
||||
interaction.guild?.id!,
|
||||
// @ts-ignore
|
||||
interaction.options.getString("id")
|
||||
interaction.options.getString("id"),
|
||||
);
|
||||
|
||||
try {
|
||||
return result
|
||||
? interaction.reply({
|
||||
content: "User was unbanned.",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
})
|
||||
: interaction.reply({
|
||||
content: "No confession with that ID was found.",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("An error occured:", err);
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
import * as confess from "./confess";
|
||||
import * as confessdel from "./confessdel";
|
||||
import * as confessban from "./confessban";
|
||||
import * as confessbanlist from "./confessbanlist";
|
||||
import * as confesspardon from "./confesspardon";
|
||||
import * as ping from "./ping";
|
||||
import * as setup from "./setup";
|
||||
|
@ -28,8 +27,7 @@ export const commands = {
|
|||
confess,
|
||||
confessdel,
|
||||
confessban,
|
||||
confessbanlist,
|
||||
confesspardon,
|
||||
ping,
|
||||
setup
|
||||
setup,
|
||||
};
|
||||
|
|
|
@ -23,7 +23,7 @@ import {
|
|||
CommandInteraction,
|
||||
ComponentType,
|
||||
PermissionFlagsBits,
|
||||
SlashCommandBuilder
|
||||
SlashCommandBuilder,
|
||||
} from "discord.js";
|
||||
import { dt } from "../main";
|
||||
import Logger from "../utils/Logger";
|
||||
|
@ -39,7 +39,7 @@ export async function execute(interaction: CommandInteraction) {
|
|||
if (dt.checkSetup(interaction.guild?.id!)) {
|
||||
return interaction.reply({
|
||||
content: "This guild has already been set up!",
|
||||
ephemeral: true
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -58,20 +58,20 @@ export async function execute(interaction: CommandInteraction) {
|
|||
const response = await interaction.reply({
|
||||
content: `# Let's get started, ${interaction.user.displayName}!\nFirst, let's choose a channel for your confessions.`,
|
||||
ephemeral: true,
|
||||
components: [channelRow]
|
||||
components: [channelRow],
|
||||
});
|
||||
|
||||
const collector = response.createMessageComponentCollector({
|
||||
componentType: ComponentType.ChannelSelect,
|
||||
time: 45_000
|
||||
time: 45_000,
|
||||
});
|
||||
|
||||
collector.on("collect", async i => {
|
||||
collector.on("collect", async (i) => {
|
||||
confessChannel = i.values[0];
|
||||
|
||||
await i.update({
|
||||
content: "Awesome!",
|
||||
components: []
|
||||
components: [],
|
||||
});
|
||||
|
||||
collector.stop();
|
||||
|
@ -83,55 +83,55 @@ export async function execute(interaction: CommandInteraction) {
|
|||
|
||||
const logChannelRow =
|
||||
new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(
|
||||
logChannelList
|
||||
logChannelList,
|
||||
);
|
||||
|
||||
const logResponse = await interaction.followUp({
|
||||
content: "# Now, select a logging channel, for moderation purposes.",
|
||||
ephemeral: true,
|
||||
components: [logChannelRow]
|
||||
components: [logChannelRow],
|
||||
});
|
||||
|
||||
const logCollector = logResponse.createMessageComponentCollector({
|
||||
componentType: ComponentType.ChannelSelect,
|
||||
time: 45_000
|
||||
time: 45_000,
|
||||
});
|
||||
|
||||
logCollector.on("collect", async ij => {
|
||||
logCollector.on("collect", async (ij) => {
|
||||
logChannel = ij.values[0];
|
||||
|
||||
await ij.update({
|
||||
content: "Setup Complete!",
|
||||
components: []
|
||||
components: [],
|
||||
});
|
||||
|
||||
dt.setup(guildId!, {
|
||||
confessChannel: confessChannel,
|
||||
modChannel: logChannel,
|
||||
bans: []
|
||||
bans: [],
|
||||
});
|
||||
|
||||
logCollector.stop();
|
||||
});
|
||||
|
||||
logCollector.on("end", content => {
|
||||
logCollector.on("end", (content) => {
|
||||
// If there is no content, follow up with an error message.
|
||||
!content.size &&
|
||||
interaction.followUp({
|
||||
content: "No channel selected. Please try again.",
|
||||
ephemeral: true,
|
||||
components: []
|
||||
components: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
collector.on("end", collected => {
|
||||
collector.on("end", (collected) => {
|
||||
// Same as above logCollector end
|
||||
!collected.size &&
|
||||
interaction.followUp({
|
||||
content: "No channel selected. Try again.",
|
||||
ephemeral: true,
|
||||
components: []
|
||||
components: [],
|
||||
});
|
||||
});
|
||||
} catch (err) {
|
||||
|
|
164
src/main.ts
164
src/main.ts
|
@ -16,43 +16,28 @@
|
|||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
ComponentType,
|
||||
EmbedBuilder,
|
||||
Events,
|
||||
Interaction,
|
||||
ModalSubmitInteraction,
|
||||
TextChannel
|
||||
} from "discord.js";
|
||||
import { BotClient, BOT_TOKEN, deployCommands } from "./bot";
|
||||
import { commands } from "./commands";
|
||||
import { StoreMan } from "./storeman";
|
||||
import Logger from "./utils/Logger";
|
||||
import getRandomColor from "./utils/getRandomColor";
|
||||
import { submit } from "./modals";
|
||||
|
||||
export const dt = new StoreMan(StoreMan.checkFile());
|
||||
const logger = new Logger("Main");
|
||||
|
||||
BotClient.once("ready", client => {
|
||||
BotClient.once("ready", (client) => {
|
||||
logger.log(`We're ready! Logged in as ${client.user.tag}`);
|
||||
});
|
||||
|
||||
// Deploy the commands for a new guild
|
||||
BotClient.on("guildCreate", async guild => {
|
||||
BotClient.on("guildCreate", async (guild) => {
|
||||
await deployCommands({ guildId: guild.id });
|
||||
});
|
||||
|
||||
// Delete the data for a guild after it is removed
|
||||
BotClient.on("guildDelete", guild => {
|
||||
BotClient.on("guildDelete", (guild) => {
|
||||
logger.log(`${guild.name} didn't want us anymore... :(`);
|
||||
dt.clearSettings(guild.id);
|
||||
});
|
||||
|
||||
BotClient.on(Events.InteractionCreate, async interaction => {
|
||||
BotClient.on("interactionCreate", async (interaction) => {
|
||||
if (!interaction.isCommand()) {
|
||||
return;
|
||||
}
|
||||
|
@ -64,145 +49,4 @@ BotClient.on(Events.InteractionCreate, async interaction => {
|
|||
}
|
||||
});
|
||||
|
||||
BotClient.on(Events.MessageDelete, async message => {
|
||||
const id = message.guild?.id!;
|
||||
const confessions = dt.getGuildInfo(id)?.confessions!;
|
||||
|
||||
for (const confession of confessions) {
|
||||
if (confession.messageId === id) {
|
||||
dt.adminDelConfession(id, confession.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
BotClient.on(Events.InteractionCreate, async interaction => {
|
||||
if (!interaction.isModalSubmit()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (interaction.customId === "submitConfession") {
|
||||
const messageContent: string =
|
||||
interaction.fields.getTextInputValue("confessionInput");
|
||||
const attachment: string = interaction.fields.getTextInputValue(
|
||||
"confessionAttachment"
|
||||
);
|
||||
|
||||
try {
|
||||
if (dt.isBanned(interaction.guild?.id!, interaction.user.id)) {
|
||||
return interaction.reply({
|
||||
content: "You are banned from confessions in this server!",
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
|
||||
if (!dt.getGuildInfo(interaction.guild?.id!)) {
|
||||
return interaction.reply({
|
||||
content:
|
||||
"The bot hasn't been set up yet! Ask the server admins to set it up.",
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
|
||||
const confessChannel = dt.getGuildInfo(interaction.guild?.id!)?.settings
|
||||
.confessChannel;
|
||||
const adminChannel = dt.getGuildInfo(interaction.guild?.id!)?.settings
|
||||
.modChannel;
|
||||
|
||||
const isAttachment = (text: string) =>
|
||||
text && (text.startsWith("http://") || text.startsWith("https://"));
|
||||
|
||||
const color = getRandomColor();
|
||||
const messageId = StoreMan.genId();
|
||||
const userConfessionEmbed = new EmbedBuilder()
|
||||
.setColor(color)
|
||||
.setTitle(`Anonymous Confession \`${messageId}\``)
|
||||
// @ts-ignore
|
||||
.setDescription(messageContent);
|
||||
|
||||
isAttachment(attachment) && userConfessionEmbed.setImage(attachment);
|
||||
|
||||
const adminConfessionEmbed = new EmbedBuilder()
|
||||
.setColor(color)
|
||||
.setTitle(`Anonymous Confession \`${messageId}\``)
|
||||
// @ts-ignore
|
||||
.setDescription(messageContent)
|
||||
.addFields(
|
||||
{
|
||||
name: "Author",
|
||||
value: interaction.user.displayName
|
||||
},
|
||||
{
|
||||
name: "Author ID",
|
||||
value: interaction.user.id
|
||||
}
|
||||
);
|
||||
|
||||
isAttachment(attachment) && adminConfessionEmbed.setImage(attachment);
|
||||
|
||||
const submitConfessionButton = new ButtonBuilder()
|
||||
.setCustomId("submitConfession")
|
||||
.setLabel("Submit a Confession")
|
||||
.setStyle(ButtonStyle.Primary);
|
||||
|
||||
const actionRow = new ActionRowBuilder<ButtonBuilder>().setComponents(
|
||||
submitConfessionButton
|
||||
);
|
||||
|
||||
const message = await (
|
||||
BotClient.channels.cache.get(confessChannel!) as TextChannel
|
||||
).send({
|
||||
embeds: [userConfessionEmbed],
|
||||
components: [actionRow]
|
||||
});
|
||||
|
||||
const collector = message.createMessageComponentCollector({
|
||||
componentType: ComponentType.Button
|
||||
});
|
||||
|
||||
collector.on("collect", i => {
|
||||
if (i.customId === "submitConfession") {
|
||||
i.showModal(submit);
|
||||
}
|
||||
});
|
||||
|
||||
await (BotClient.channels.cache.get(adminChannel!) as TextChannel).send({
|
||||
embeds: [adminConfessionEmbed]
|
||||
});
|
||||
|
||||
dt.addConfession(
|
||||
message,
|
||||
messageId,
|
||||
interaction.user.displayName,
|
||||
interaction.user.id,
|
||||
messageContent,
|
||||
attachment
|
||||
);
|
||||
|
||||
const confessionsLength = dt.getGuildInfo(interaction.guild?.id!)
|
||||
?.confessions.length!;
|
||||
|
||||
if (confessionsLength >= 2) {
|
||||
await (
|
||||
BotClient.channels.cache.get(confessChannel!) as TextChannel
|
||||
).messages
|
||||
.fetch(
|
||||
dt.getGuildInfo(interaction.guild?.id!)?.confessions[
|
||||
confessionsLength - 2
|
||||
].messageId!
|
||||
)
|
||||
.then(message => {
|
||||
message.edit({ components: [] });
|
||||
});
|
||||
}
|
||||
|
||||
return interaction.reply({
|
||||
content: "Confession sent!",
|
||||
ephemeral: true
|
||||
});
|
||||
} catch (err) {
|
||||
logger.error("An error occured:", err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
BotClient.login(BOT_TOKEN);
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* Confoss: Anonymous confessions for Discord, free as in freedom and price!
|
||||
* Copyright (C) 2024 powermaker450
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export * from "./submit";
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Confoss: Anonymous confessions for Discord, free as in freedom and price!
|
||||
* Copyright (C) 2024 powermaker450
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published
|
||||
* by the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {
|
||||
ActionRowBuilder,
|
||||
ModalActionRowComponentBuilder,
|
||||
ModalBuilder,
|
||||
TextInputBuilder,
|
||||
TextInputStyle
|
||||
} from "discord.js";
|
||||
|
||||
const submit = new ModalBuilder()
|
||||
.setCustomId("submitConfession")
|
||||
.setTitle("Submit Confession");
|
||||
|
||||
const confessionInput = new TextInputBuilder()
|
||||
.setCustomId("confessionInput")
|
||||
.setLabel("Confession")
|
||||
.setRequired(true)
|
||||
.setMaxLength(2000)
|
||||
.setStyle(TextInputStyle.Paragraph);
|
||||
|
||||
const attachmentInput = new TextInputBuilder()
|
||||
.setCustomId("confessionAttachment")
|
||||
.setLabel("Attachment (optional)")
|
||||
.setRequired(false)
|
||||
.setStyle(TextInputStyle.Short);
|
||||
|
||||
const confessionRow =
|
||||
new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(
|
||||
confessionInput
|
||||
);
|
||||
|
||||
const attachmentRow =
|
||||
new ActionRowBuilder<ModalActionRowComponentBuilder>().addComponents(
|
||||
attachmentInput
|
||||
);
|
||||
|
||||
submit.addComponents(confessionRow, attachmentRow);
|
||||
|
||||
export { submit };
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import fs from "fs";
|
||||
import crypto from "crypto";
|
||||
import { Confession, ConfessionBan, GuildData, GuildSettings } from "./types";
|
||||
import { Confession, GuildData, GuildSettings } from "./types";
|
||||
import { DATA_DIR } from "./config";
|
||||
import { CommandInteraction, Message } from "discord.js";
|
||||
|
||||
|
@ -39,7 +39,6 @@ export class StoreMan {
|
|||
author: string,
|
||||
authorId: string,
|
||||
content: string,
|
||||
attachment?: string
|
||||
): Confession {
|
||||
return {
|
||||
id: id,
|
||||
|
@ -47,7 +46,6 @@ export class StoreMan {
|
|||
author: author,
|
||||
authorId: authorId,
|
||||
content: content,
|
||||
attachment: attachment
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -74,7 +72,7 @@ export class StoreMan {
|
|||
fs.writeFileSync(
|
||||
StoreMan.fullPath,
|
||||
JSON.stringify(this.data, null, 2),
|
||||
"utf8"
|
||||
"utf8",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -94,7 +92,7 @@ export class StoreMan {
|
|||
this.data.push({
|
||||
id: id,
|
||||
confessions: [],
|
||||
settings: opts
|
||||
settings: opts,
|
||||
});
|
||||
|
||||
this.saveFile();
|
||||
|
@ -102,7 +100,7 @@ export class StoreMan {
|
|||
|
||||
// Clear the settings for a given guild
|
||||
public clearSettings(id: string): void {
|
||||
this.data = this.data.filter(guild => {
|
||||
this.data = this.data.filter((guild) => {
|
||||
return guild.id !== id;
|
||||
});
|
||||
this.saveFile();
|
||||
|
@ -125,7 +123,6 @@ export class StoreMan {
|
|||
author: string,
|
||||
authorId: string,
|
||||
content: string,
|
||||
attachment?: string
|
||||
): boolean {
|
||||
const guildId = message.guild?.id;
|
||||
|
||||
|
@ -137,14 +134,7 @@ export class StoreMan {
|
|||
}
|
||||
|
||||
guild.confessions.push(
|
||||
StoreMan.toConfession(
|
||||
message,
|
||||
id,
|
||||
author,
|
||||
authorId,
|
||||
content,
|
||||
attachment
|
||||
)
|
||||
StoreMan.toConfession(message, id, author, authorId, content),
|
||||
);
|
||||
this.saveFile();
|
||||
return true;
|
||||
|
@ -152,13 +142,13 @@ export class StoreMan {
|
|||
}
|
||||
|
||||
throw new Error(
|
||||
`No guild with id ${id} was found. Something's pretty wrong.`
|
||||
`No guild with id ${id} was found. Something's pretty wrong.`,
|
||||
);
|
||||
}
|
||||
|
||||
public getConfession(
|
||||
guildId: string,
|
||||
confessionId: string
|
||||
confessionId: string,
|
||||
): Confession | null {
|
||||
for (const guild of this.data) {
|
||||
if (guild.id === guildId) {
|
||||
|
@ -176,7 +166,7 @@ export class StoreMan {
|
|||
// Attempts to delete a confession. If it is sucessfully deleted, returns true, else false.
|
||||
public delConfesssion(
|
||||
{ guild, user }: CommandInteraction,
|
||||
confessionId: string
|
||||
confessionId: string,
|
||||
): boolean {
|
||||
const guildId = guild?.id;
|
||||
const userId = user.id;
|
||||
|
@ -185,7 +175,7 @@ export class StoreMan {
|
|||
if (guild.id === guildId) {
|
||||
for (const confession of guild.confessions) {
|
||||
if (confession.authorId === userId) {
|
||||
guild.confessions = guild.confessions.filter(confession => {
|
||||
guild.confessions = guild.confessions.filter((confession) => {
|
||||
return confession.id !== confessionId;
|
||||
});
|
||||
|
||||
|
@ -199,22 +189,12 @@ export class StoreMan {
|
|||
return false;
|
||||
}
|
||||
|
||||
public adminDelConfession(guildId: string, confessionId: string): void {
|
||||
for (const guild of this.data) {
|
||||
if (guild.id === guildId) {
|
||||
guild.confessions = guild.confessions.filter(confession => {
|
||||
return confession.id !== confessionId;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a certain user is banned within a guild.
|
||||
public isBanned(guildId: string, userId: string): boolean {
|
||||
for (const guild of this.data) {
|
||||
if (guild.id === guildId) {
|
||||
for (const ban of guild.settings.bans) {
|
||||
if (ban.user === userId) {
|
||||
if (ban === userId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +204,7 @@ export class StoreMan {
|
|||
return false;
|
||||
}
|
||||
|
||||
public getBans(guildId: string): ConfessionBan[] {
|
||||
public getBans(guildId: string): string[] {
|
||||
for (const guild of this.data) {
|
||||
if (guild.id === guildId) {
|
||||
return guild.settings.bans;
|
||||
|
@ -243,10 +223,7 @@ export class StoreMan {
|
|||
if (confession) {
|
||||
// Only add the user to the ban list if they aren't banned already
|
||||
!this.isBanned(guildId, confession.authorId) &&
|
||||
guild.settings.bans.push({
|
||||
user: confession.authorId,
|
||||
confessionId: confessionId
|
||||
});
|
||||
guild.settings.bans.push(confession.authorId!);
|
||||
|
||||
this.saveFile();
|
||||
return true;
|
||||
|
@ -262,10 +239,8 @@ export class StoreMan {
|
|||
for (const guild of this.data) {
|
||||
if (guild.id === guildId) {
|
||||
if (this.getConfession(guildId, confessionId)) {
|
||||
guild.settings.bans = guild.settings.bans.filter(ban => {
|
||||
return (
|
||||
ban.user !== this.getConfession(guildId, confessionId)?.authorId!
|
||||
);
|
||||
guild.settings.bans = guild.settings.bans.filter((ban) => {
|
||||
return ban !== this.getConfession(guildId, confessionId)?.authorId!;
|
||||
});
|
||||
|
||||
this.saveFile();
|
||||
|
|
|
@ -22,18 +22,12 @@ export interface Confession {
|
|||
author: string;
|
||||
authorId: string;
|
||||
content: string;
|
||||
attachment?: string;
|
||||
}
|
||||
|
||||
export interface ConfessionBan {
|
||||
user: string;
|
||||
confessionId: string;
|
||||
}
|
||||
|
||||
export interface GuildSettings {
|
||||
confessChannel: string;
|
||||
modChannel: string;
|
||||
bans: ConfessionBan[];
|
||||
bans: string[];
|
||||
}
|
||||
|
||||
export interface GuildData {
|
||||
|
|
|
@ -36,7 +36,7 @@ export default class Logger {
|
|||
public static readonly udln = chalk.underline;
|
||||
|
||||
public static readonly anon = Logger.bold.gray(
|
||||
`[ConfessBot] | ${Logger.emp("Anonymous ")}`
|
||||
`[ConfessBot] | ${Logger.emp("Anonymous ")}`,
|
||||
);
|
||||
|
||||
constructor(origin?: string) {
|
||||
|
|
Loading…
Reference in a new issue