feat: update scoring system and embed message structure
This commit is contained in:
parent
04dee350fc
commit
1a48699eae
21
config.json
21
config.json
|
@ -1 +1,20 @@
|
||||||
[]
|
[
|
||||||
|
{
|
||||||
|
"server": "1119476423309131817",
|
||||||
|
"output_channel": "1282388288002330654",
|
||||||
|
"output_hook": "",
|
||||||
|
"channel_type": "exclude",
|
||||||
|
"channels": [
|
||||||
|
"1120646044594733107",
|
||||||
|
"1209520952090558565",
|
||||||
|
"1122580018170708049"
|
||||||
|
],
|
||||||
|
"emoji_type": "exclude",
|
||||||
|
"emojis": [
|
||||||
|
"⭕",
|
||||||
|
"👍",
|
||||||
|
"👀"
|
||||||
|
],
|
||||||
|
"score": 5
|
||||||
|
}
|
||||||
|
]
|
|
@ -1,6 +1,6 @@
|
||||||
import { EmbedBuilder, MessageReaction, PartialMessageReaction } from 'discord.js';
|
import { EmbedBuilder, MessageReaction, PartialMessageReaction } from 'discord.js';
|
||||||
|
|
||||||
export default function awardEmbed(reaction: MessageReaction | PartialMessageReaction) {
|
export default function awardEmbed(reaction: MessageReaction | PartialMessageReaction, score: number) {
|
||||||
function formatTime(time: Date) {
|
function formatTime(time: Date) {
|
||||||
const yyyy = time.getFullYear();
|
const yyyy = time.getFullYear();
|
||||||
const mm = time.getMonth().toString().padStart(2, '0');
|
const mm = time.getMonth().toString().padStart(2, '0');
|
||||||
|
@ -18,7 +18,7 @@ export default function awardEmbed(reaction: MessageReaction | PartialMessageRea
|
||||||
.setDescription(reaction.message.content || null)
|
.setDescription(reaction.message.content || null)
|
||||||
.setThumbnail(reaction.message.attachments.filter((attachment) => !(!attachment.height && !attachment.width)).first()?.url || null)
|
.setThumbnail(reaction.message.attachments.filter((attachment) => !(!attachment.height && !attachment.width)).first()?.url || null)
|
||||||
.addFields({
|
.addFields({
|
||||||
name: `${reaction.emoji.name} x${reaction.count} `,
|
name: `${reaction.message.reactions.cache.map((reaction) => `${reaction.emoji} x${reaction.count},`).join(' ')} / ${score.toFixed(1)}`,
|
||||||
value: `in <#${reaction.message.channelId}> • ${formatTime(reaction.message.createdAt)}\n-# ${reaction.message.id}`,
|
value: `${reaction.message.url} • ${formatTime(reaction.message.createdAt)}\n-# ${reaction.message.id}`,
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -59,12 +59,12 @@ const emojis_type = new SlashCommandSubcommandBuilder()
|
||||||
{ name: 'Include', value: 'include' },
|
{ name: 'Include', value: 'include' },
|
||||||
{ name: 'Exclude', value: 'exclude' }
|
{ name: 'Exclude', value: 'exclude' }
|
||||||
));
|
));
|
||||||
const count = new SlashCommandSubcommandBuilder()
|
const score = new SlashCommandSubcommandBuilder()
|
||||||
.setName('count')
|
.setName('score')
|
||||||
.setDescription('Set the number of reactions to trigger')
|
.setDescription('Set the number of scores to trigger')
|
||||||
.addIntegerOption(option =>
|
.addIntegerOption(option =>
|
||||||
option.setName('count')
|
option.setName('score')
|
||||||
.setDescription('The number of reactions to trigger')
|
.setDescription('The number of scores to trigger')
|
||||||
.setRequired(true));
|
.setRequired(true));
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ const config = new SlashCommandBuilder()
|
||||||
.addSubcommand(channels_type)
|
.addSubcommand(channels_type)
|
||||||
.addSubcommand(emojis)
|
.addSubcommand(emojis)
|
||||||
.addSubcommand(emojis_type)
|
.addSubcommand(emojis_type)
|
||||||
.addSubcommand(count);
|
.addSubcommand(score);
|
||||||
|
|
||||||
const commands = [config];
|
const commands = [config];
|
||||||
export default commands;
|
export default commands;
|
||||||
|
|
|
@ -11,7 +11,7 @@ export class Entry {
|
||||||
channels: string[] = [];
|
channels: string[] = [];
|
||||||
emoji_type: Type = Type.EXCLUDE;
|
emoji_type: Type = Type.EXCLUDE;
|
||||||
emojis: string[] = [];
|
emojis: string[] = [];
|
||||||
count: number = 3;
|
score: number = 5;
|
||||||
constructor(server: string) {
|
constructor(server: string) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
}
|
}
|
||||||
|
|
159
src/index.ts
159
src/index.ts
|
@ -1,4 +1,4 @@
|
||||||
import 'dotenv/config'
|
import "dotenv/config";
|
||||||
const TOKEN = process.env.TOKEN;
|
const TOKEN = process.env.TOKEN;
|
||||||
const CLIENT_ID = process.env.CLIENT_ID;
|
const CLIENT_ID = process.env.CLIENT_ID;
|
||||||
if (!TOKEN || !CLIENT_ID) {
|
if (!TOKEN || !CLIENT_ID) {
|
||||||
|
@ -15,6 +15,8 @@ import {
|
||||||
GatewayIntentBits,
|
GatewayIntentBits,
|
||||||
Events,
|
Events,
|
||||||
TextChannel,
|
TextChannel,
|
||||||
|
Message,
|
||||||
|
PartialMessage,
|
||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
|
|
||||||
const rest = new REST({ version: "10" }).setToken(TOKEN);
|
const rest = new REST({ version: "10" }).setToken(TOKEN);
|
||||||
|
@ -65,8 +67,10 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
if (subcommand === "output") {
|
if (subcommand === "output") {
|
||||||
const channel = interaction.options.getChannel("channel", true);
|
const channel = interaction.options.getChannel("channel", true);
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply({ ephemeral: true, });
|
await interaction.deferReply({ ephemeral: true });
|
||||||
let entry = entries.find((entry) => entry.server === interaction.guildId);
|
let entry = entries.find(
|
||||||
|
(entry) => entry.server === interaction.guildId
|
||||||
|
);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
entry = new Entry(interaction.guildId!);
|
entry = new Entry(interaction.guildId!);
|
||||||
entries.push(entry);
|
entries.push(entry);
|
||||||
|
@ -85,7 +89,9 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
const mode = interaction.options.getString("add_remove", true);
|
const mode = interaction.options.getString("add_remove", true);
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({ ephemeral: true });
|
||||||
let entry = entries.find((entry) => entry.server === interaction.guildId);
|
let entry = entries.find(
|
||||||
|
(entry) => entry.server === interaction.guildId
|
||||||
|
);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
entry = new Entry(interaction.guildId!);
|
entry = new Entry(interaction.guildId!);
|
||||||
entries.push(entry);
|
entries.push(entry);
|
||||||
|
@ -101,11 +107,16 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (subcommand === "channels_type") {
|
} else if (subcommand === "channels_type") {
|
||||||
const channel_type = interaction.options.getString("channels_type", true);
|
const channel_type = interaction.options.getString(
|
||||||
|
"channels_type",
|
||||||
|
true
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({ ephemeral: true });
|
||||||
|
|
||||||
let entry = entries.find((entry) => entry.server === interaction.guildId);
|
let entry = entries.find(
|
||||||
|
(entry) => entry.server === interaction.guildId
|
||||||
|
);
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
entry = new Entry(interaction.guildId!);
|
entry = new Entry(interaction.guildId!);
|
||||||
entries.push(entry);
|
entries.push(entry);
|
||||||
|
@ -164,8 +175,8 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
ephemeral: true,
|
ephemeral: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if (subcommand === "count") {
|
} else if (subcommand === "score") {
|
||||||
const count = interaction.options.getInteger("count", true);
|
const score = interaction.options.getInteger("score", true);
|
||||||
try {
|
try {
|
||||||
await interaction.deferReply({ ephemeral: true });
|
await interaction.deferReply({ ephemeral: true });
|
||||||
let entry = entries.find(
|
let entry = entries.find(
|
||||||
|
@ -175,13 +186,13 @@ client.on("interactionCreate", async (interaction) => {
|
||||||
entry = new Entry(interaction.guildId!);
|
entry = new Entry(interaction.guildId!);
|
||||||
entries.push(entry);
|
entries.push(entry);
|
||||||
}
|
}
|
||||||
entry.count = count;
|
entry.score = score;
|
||||||
await writeConfig(entries);
|
await writeConfig(entries);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
} finally {
|
} finally {
|
||||||
await interaction.followUp({
|
await interaction.followUp({
|
||||||
content: `The number needed to trigger is now ${count}`,
|
content: `The score needed to trigger is now ${score}`,
|
||||||
ephemeral: true,
|
ephemeral: true,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -202,26 +213,136 @@ client.on(Events.MessageReactionAdd, async (reaction, user) => {
|
||||||
}
|
}
|
||||||
if (!reaction.message.guild) return;
|
if (!reaction.message.guild) return;
|
||||||
|
|
||||||
const entry = entries.find((entry) => entry.server === reaction.message.guildId);
|
const entry = entries.find(
|
||||||
|
(entry) => entry.server === reaction.message.guildId
|
||||||
|
);
|
||||||
if (entry === undefined) return;
|
if (entry === undefined) return;
|
||||||
if ((entry.channel_type === Type.EXCLUDE) === entry.channels.includes(reaction.message.channelId)) return;
|
if (
|
||||||
if ((entry.emoji_type === Type.EXCLUDE) === entry.emojis.includes(`${reaction.emoji.name}`)) return;
|
(entry.channel_type === Type.EXCLUDE) ===
|
||||||
|
entry.channels.includes(reaction.message.channelId)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
if (
|
||||||
|
(entry.emoji_type === Type.EXCLUDE) ===
|
||||||
|
entry.emojis.includes(`${reaction.emoji.id || reaction.emoji.name}`)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
if (reaction.count === null || reaction.count < entry.count) return;
|
console.log(`reaction added: ${reaction.emoji.id || reaction.emoji.name}`);
|
||||||
|
const totalScore = await getMessageScore(entry, reaction.message);
|
||||||
|
|
||||||
const channel = reaction.message.guild.channels.cache.get(entry.output_channel) as TextChannel;
|
if (totalScore >= entry.score) {
|
||||||
channel.messages.fetch({ limit: 5 }).then((messages) => {
|
const channel = reaction.message.guild.channels.cache.get(
|
||||||
|
entry.output_channel
|
||||||
|
) as TextChannel;
|
||||||
|
channel.messages.fetch({ limit: 10 }).then((messages) => {
|
||||||
|
messages.find((message) => {
|
||||||
|
if (message.embeds[0]?.fields[0].value.includes(reaction.message.id)) {
|
||||||
|
message.delete();
|
||||||
|
console.log("old message deleted.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
channel.send({
|
||||||
|
embeds: [awardEmbed(reaction, totalScore)],
|
||||||
|
});
|
||||||
|
console.log("message sent.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on(Events.MessageReactionRemove, async (reaction, user) => {
|
||||||
|
if (reaction.partial) {
|
||||||
|
try {
|
||||||
|
await reaction.fetch();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Something went wrong when fetching the message:", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!reaction.message.guild) return;
|
||||||
|
|
||||||
|
const entry = entries.find(
|
||||||
|
(entry) => entry.server === reaction.message.guildId
|
||||||
|
);
|
||||||
|
if (entry === undefined) return;
|
||||||
|
if (
|
||||||
|
(entry.channel_type === Type.EXCLUDE) ===
|
||||||
|
entry.channels.includes(reaction.message.channelId)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
if (
|
||||||
|
(entry.emoji_type === Type.EXCLUDE) ===
|
||||||
|
entry.emojis.includes(`${reaction.emoji.id || reaction.emoji.name}`)
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
console.log(`reaction removed: ${reaction.emoji.id || reaction.emoji.name}`);
|
||||||
|
const totalScore = await getMessageScore(entry, reaction.message);
|
||||||
|
|
||||||
|
const channel = reaction.message.guild.channels.cache.get(
|
||||||
|
entry.output_channel
|
||||||
|
) as TextChannel;
|
||||||
|
channel.messages.fetch({ limit: 10 }).then((messages) => {
|
||||||
messages.find((message) => {
|
messages.find((message) => {
|
||||||
if (message.embeds[0]?.fields[0].value.includes(reaction.message.id)) {
|
if (message.embeds[0]?.fields[0].value.includes(reaction.message.id)) {
|
||||||
message.delete();
|
message.delete();
|
||||||
|
console.log("old message deleted.");
|
||||||
|
if (totalScore >= entry.score) {
|
||||||
|
channel.send({
|
||||||
|
embeds: [awardEmbed(reaction, totalScore)],
|
||||||
|
});
|
||||||
|
console.log("message sent.");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
channel.send({
|
|
||||||
embeds: [awardEmbed(reaction)]
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
client.login(TOKEN);
|
client.login(TOKEN);
|
||||||
|
|
||||||
|
async function getMessageScore(
|
||||||
|
entry: Entry,
|
||||||
|
message: Message | PartialMessage
|
||||||
|
): Promise<number> {
|
||||||
|
/* Message Score Calculation *
|
||||||
|
* Per user: 1 / (-1 + 2x) */
|
||||||
|
|
||||||
|
const allReactions: Map<string, number> = new Map();
|
||||||
|
const reactions = message.reactions.cache;
|
||||||
|
for (const r of reactions.values()) {
|
||||||
|
if (
|
||||||
|
(entry.emoji_type === Type.EXCLUDE) ===
|
||||||
|
entry.emojis.includes(`${r.emoji.id || r.emoji.name}`)
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
const users = await r.users.fetch();
|
||||||
|
for (const user of users.values()) {
|
||||||
|
if (user.bot) continue;
|
||||||
|
const score = allReactions.get(user.id) || 0;
|
||||||
|
allReactions.set(user.id, score + 1 / (-1 + 2 * (score + 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let totalScore = 0;
|
||||||
|
allReactions.forEach((value) => {
|
||||||
|
totalScore += value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// "message" by "user"
|
||||||
|
// id : score
|
||||||
|
// ----------------
|
||||||
|
// Total: 1.5
|
||||||
|
|
||||||
|
console.log(`"${message.id}" by "${message.author?.username}"`);
|
||||||
|
allReactions.forEach((value, key) => {
|
||||||
|
console.log(`${key} : ${value}`);
|
||||||
|
});
|
||||||
|
console.log(`----------------`);
|
||||||
|
console.log(`Total: ${totalScore}`);
|
||||||
|
|
||||||
|
return totalScore;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user