mirror of
https://github.com/nx-bat/pet-the-pond.git
synced 2026-09-22 02:19:10 -04:00
implement db into code where needed instead.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { Command, CommandBuilder, CommandClient, CommandInteraction, Constants, SlashCommand } from "athena-prime";
|
||||
import database from "../../database";
|
||||
|
||||
// ----------
|
||||
|
||||
@SlashCommand(
|
||||
new CommandBuilder('points', "Adjust a user's points.")
|
||||
.setIntegrationTypes(Constants.ApplicationIntegrationType.GuildInstall)
|
||||
.setContexts(Constants.InteractionContextType.Guild)
|
||||
.setCommandType(Constants.ApplicationCommandType.ChatInput)
|
||||
.setMemberPermission(Constants.PermissionFlagsBits.ManageGuild)
|
||||
|
||||
.addSubcommand('give', 'Give points to a user.', builder => {
|
||||
builder.addUserOption('target', 'The user to modify.', true);
|
||||
builder.addNumberOption({ name: 'points', description: 'The points to give.', required: true, min_value: 1 })
|
||||
})
|
||||
.addSubcommand('take', 'Take points from a user.', builder => {
|
||||
builder.addUserOption('target', 'The user to modify.', true);
|
||||
builder.addNumberOption({ name: 'points', description: 'The points to take.', required: true, min_value: 1 })
|
||||
})
|
||||
.addSubcommand('set', 'Set the points of a user.', builder => {
|
||||
builder.addUserOption('target', 'The user to modify.', true);
|
||||
builder.addNumberOption({ name: 'points', description: 'The new points value.', required: true })
|
||||
})
|
||||
)
|
||||
class RankCommand extends Command<CommandClient> {
|
||||
users = [
|
||||
'1363132678022631428', // Nix.
|
||||
'454653142500507649', // Ann.
|
||||
'147433323503943680' // Pond.
|
||||
];
|
||||
|
||||
async handleCommand(context: CommandClient<any, any>, interaction: CommandInteraction) {
|
||||
if (!interaction.inGuild()) return;
|
||||
|
||||
const target = interaction.getRequiredUser('target');
|
||||
const points = interaction.getRequiredNumber('points');
|
||||
|
||||
switch (interaction.subcommand) {
|
||||
case 'give':
|
||||
await database`
|
||||
INSERT INTO points AS p (user_id, guild_id, points)
|
||||
VALUES (${target.id}, ${interaction.guild.id}, ${points})
|
||||
ON CONFLICT (user_id, guild_id)
|
||||
DO UPDATE SET points = p.points + ${points}
|
||||
`;
|
||||
|
||||
return await interaction.createMessage({
|
||||
content: `Done! *${target.username}* has been given **${points}** points.`,
|
||||
flags: Constants.MessageFlags.Ephemeral
|
||||
});
|
||||
|
||||
case 'take':
|
||||
await database`
|
||||
INSERT INTO points AS p (user_id, guild_id, points)
|
||||
VALUES ${target.id}, ${interaction.guild.id}, 0)
|
||||
ON CONFLICT (user_id, guild_id)
|
||||
DO UPDATE SET points = GREATEST(p.points - ${points}, 0)
|
||||
`;
|
||||
|
||||
return await interaction.createMessage({
|
||||
content: `Done! *${target.username}* has lost **${points}** points.`,
|
||||
flags: Constants.MessageFlags.Ephemeral
|
||||
});
|
||||
|
||||
case 'set':
|
||||
await database`
|
||||
INSERT INTO points (user_id, guild_id, points)
|
||||
VALUES (${target.id}, ${interaction.guild.id}, ${points})
|
||||
ON CONFLICT (user_id, guild_id)
|
||||
DO UPDATE SET points = ${points}
|
||||
`;
|
||||
|
||||
return await interaction.createMessage({
|
||||
content: `Done! *${target.username}*'s points has been set to **${points}**.`,
|
||||
flags: Constants.MessageFlags.Ephemeral
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new RankCommand('rank');
|
||||
@@ -0,0 +1,44 @@
|
||||
import { Command, CommandBuilder, CommandClient, CommandInteraction, Constants, SlashCommand } from "athena-prime";
|
||||
import database from "../../database";
|
||||
|
||||
// ----------
|
||||
|
||||
@SlashCommand(
|
||||
new CommandBuilder('wipe', 'Wipes all points for the guild or specific user. THIS DOES NOT ASK FOR CONFIRMATION!')
|
||||
.setIntegrationTypes(Constants.ApplicationIntegrationType.GuildInstall)
|
||||
.setContexts(Constants.InteractionContextType.Guild)
|
||||
.setCommandType(Constants.ApplicationCommandType.ChatInput)
|
||||
.setMemberPermission(Constants.PermissionFlagsBits.ManageGuild)
|
||||
.addUserOption('target', "Optional. The user to wipe.", false)
|
||||
)
|
||||
class RankCommand extends Command<CommandClient> {
|
||||
users = [
|
||||
'1363132678022631428', // Nix.
|
||||
'454653142500507649', // Ann.
|
||||
'147433323503943680' // Pond.
|
||||
];
|
||||
|
||||
async handleCommand(context: CommandClient<any, any>, interaction: CommandInteraction) {
|
||||
if (!interaction.inGuild()) return;
|
||||
|
||||
const target = interaction.getUser('target');
|
||||
|
||||
if (!target) {
|
||||
await database` UPDATE points SET points = 0 WHERE guild_id = ${interaction.guild.id}`;
|
||||
|
||||
return await interaction.createMessage({
|
||||
content: 'Done! All points for this guild have been cleared.',
|
||||
flags: Constants.MessageFlags.Ephemeral
|
||||
});
|
||||
}
|
||||
|
||||
await database` UPDATE points SET points = 0 WHERE user_id = ${target.id} AND guild_id = ${interaction.guild.id} `;
|
||||
|
||||
return await interaction.createMessage({
|
||||
content: `Done! *${target.username}*'s points have been wiped.`,
|
||||
flags: Constants.MessageFlags.Ephemeral
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new RankCommand('rank');
|
||||
@@ -1,6 +1,8 @@
|
||||
import points from './admin/points';
|
||||
import wipe from './admin/wipe';
|
||||
import leaderboard from './leaderboard';
|
||||
import rank from './rank';
|
||||
|
||||
// ----------
|
||||
|
||||
export default [leaderboard, rank];
|
||||
export default [points, wipe, leaderboard, rank];
|
||||
|
||||
@@ -3,6 +3,19 @@ import database from '../database';
|
||||
|
||||
// ----------
|
||||
|
||||
async function getLeaderboard(guild_id: string, limit: number = 10): Promise<{ user_id: string; points: number }[]> {
|
||||
return await database`
|
||||
SELECT user_id, points
|
||||
FROM points
|
||||
WHERE guild_id = ${guild_id}
|
||||
AND points > 0
|
||||
ORDER BY points DESC, user_id ASC
|
||||
LIMIT ${limit}
|
||||
`;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
@SlashCommand(
|
||||
new CommandBuilder('leaderboard', 'Get the petting leaderboard.')
|
||||
.setIntegrationTypes(Constants.ApplicationIntegrationType.GuildInstall)
|
||||
@@ -14,7 +27,7 @@ class LeaderboardCommand extends Command<CommandClient> {
|
||||
if (!interaction.inGuild()) return;
|
||||
await interaction.defer();
|
||||
|
||||
const data = await database.leaderboard.getLeaderboard(interaction.guild.id);
|
||||
const data = await getLeaderboard(interaction.guild.id);
|
||||
const description = data.length
|
||||
? data
|
||||
.map((entry, index) => `**${index + 1}.** <@${entry.user_id}> — **${entry.points}** points!`)
|
||||
@@ -39,4 +52,6 @@ class LeaderboardCommand extends Command<CommandClient> {
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
export default new LeaderboardCommand('leaderboard');
|
||||
|
||||
+34
-2
@@ -3,6 +3,36 @@ import database from "../database";
|
||||
|
||||
// ----------
|
||||
|
||||
async function getPoints(id: string, guild_id: string): Promise<number> {
|
||||
const [row] = await database`
|
||||
SELECT points
|
||||
FROM points
|
||||
WHERE user_id = ${id}
|
||||
AND guild_id = ${guild_id}
|
||||
`;
|
||||
|
||||
return row?.points ?? 0;
|
||||
}
|
||||
|
||||
async function getLeaderboardPosition(id: string, guild_id: string): Promise<number | null> {
|
||||
const [row] = await database`
|
||||
SELECT position
|
||||
FROM (
|
||||
SELECT
|
||||
user_id,
|
||||
RANK() OVER (ORDER BY points DESC) AS position
|
||||
FROM points
|
||||
WHERE guild_id = ${guild_id}
|
||||
AND points > 0
|
||||
) leaderboard
|
||||
WHERE user_id = ${id}
|
||||
`;
|
||||
|
||||
return row?.position ?? null;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
@SlashCommand(
|
||||
new CommandBuilder('rank', 'See your rank information.')
|
||||
.setIntegrationTypes(Constants.ApplicationIntegrationType.GuildInstall)
|
||||
@@ -14,8 +44,8 @@ class RankCommand extends Command<CommandClient> {
|
||||
if (!interaction.inGuild()) return;
|
||||
await interaction.defer();
|
||||
|
||||
const _points = await database.points.getPoints(interaction.member.id, interaction.guild.id);
|
||||
const _rank = await database.leaderboard.getLeaderboardPosition(interaction.member.id, interaction.guild.id);
|
||||
const _points = await getPoints(interaction.member.id, interaction.guild.id);
|
||||
const _rank = await getLeaderboardPosition(interaction.member.id, interaction.guild.id);
|
||||
|
||||
await interaction.createMessage({
|
||||
embeds: [{
|
||||
@@ -36,4 +66,6 @@ class RankCommand extends Command<CommandClient> {
|
||||
}
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
export default new RankCommand('rank');
|
||||
+1
-88
@@ -2,91 +2,4 @@ import postgres from "postgres";
|
||||
|
||||
// ----------
|
||||
|
||||
const client = postgres(process.env.DATABASE_URL);
|
||||
|
||||
async function init() {
|
||||
await client`
|
||||
CREATE TABLE IF NOT EXISTS points (
|
||||
user_id TEXT NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
points INTEGER NOT NULL DEFAULT 0 CHECK (points >= 0),
|
||||
|
||||
PRIMARY KEY (user_id, guild_id)
|
||||
)
|
||||
`;
|
||||
}
|
||||
|
||||
async function getPoints(id: string, guild_id: string): Promise<number> {
|
||||
const [row] = await client`
|
||||
SELECT points
|
||||
FROM points
|
||||
WHERE user_id = ${id}
|
||||
AND guild_id = ${guild_id}
|
||||
`;
|
||||
|
||||
return row?.points ?? 0;
|
||||
}
|
||||
|
||||
async function addPoints(id: string, guild_id: string, count: number) {
|
||||
await client`
|
||||
INSERT INTO points AS p (user_id, guild_id, points)
|
||||
VALUES (${id}, ${guild_id}, ${count})
|
||||
ON CONFLICT (user_id, guild_id)
|
||||
DO UPDATE SET points = p.points + ${count}
|
||||
`;
|
||||
}
|
||||
|
||||
async function takePoints(id: string, guild_id: string, count: number) {
|
||||
await client`
|
||||
INSERT INTO points AS p (user_id, guild_id, points)
|
||||
VALUES (${id}, ${guild_id}, 0)
|
||||
ON CONFLICT (user_id, guild_id)
|
||||
DO UPDATE SET points = GREATEST(p.points - ${count}, 0)
|
||||
`;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
async function getLeaderboard(guild_id: string, limit: number = 10): Promise<{ user_id: string; points: number }[]> {
|
||||
return await client`
|
||||
SELECT user_id, points
|
||||
FROM points
|
||||
WHERE guild_id = ${guild_id}
|
||||
AND points > 0
|
||||
ORDER BY points DESC, user_id ASC
|
||||
LIMIT ${limit}
|
||||
`;
|
||||
}
|
||||
|
||||
async function getLeaderboardPosition(id: string, guild_id: string): Promise<number | null> {
|
||||
const [row] = await client`
|
||||
SELECT position
|
||||
FROM (
|
||||
SELECT
|
||||
user_id,
|
||||
RANK() OVER (ORDER BY points DESC) AS position
|
||||
FROM points
|
||||
WHERE guild_id = ${guild_id}
|
||||
AND points > 0
|
||||
) leaderboard
|
||||
WHERE user_id = ${id}
|
||||
`;
|
||||
|
||||
return row?.position ?? null;
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
||||
export default {
|
||||
points: {
|
||||
init,
|
||||
getPoints,
|
||||
addPoints,
|
||||
takePoints
|
||||
},
|
||||
|
||||
leaderboard: {
|
||||
getLeaderboard,
|
||||
getLeaderboardPosition
|
||||
}
|
||||
};
|
||||
export default postgres(process.env.DATABASE_URL);
|
||||
@@ -8,7 +8,13 @@ class MessageReactionAddEvent extends Event<CommandClient> {
|
||||
|
||||
async handle(context: CommandClient<any, any>, message: Message, emoji: Constants.APIEmoji, member: Member) {
|
||||
if (!message.guildID || emoji.id != '1547870117080342548' || member.id == message.author.id) return;
|
||||
await database.points.addPoints(message.author.id, member.guild.id, 1);
|
||||
|
||||
await database`
|
||||
INSERT INTO points AS p (user_id, guild_id, points)
|
||||
VALUES (${message.author.id}, ${member.guild.id}, 1)
|
||||
ON CONFLICT (user_id, guild_id)
|
||||
DO UPDATE SET points = p.points + 1
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,14 @@ class MessageReactionRemoveEvent extends Event<CommandClient> {
|
||||
|
||||
async handle(context: CommandClient<any, any>, message: { id: string; channel: { id: string } }, emoji: Constants.APIEmoji, userId: string) {
|
||||
const _message = await context.getMessage(message.channel.id, message.id);
|
||||
|
||||
if (!_message.guildID || emoji.id != '1547870117080342548' || userId == _message.author.id) return;
|
||||
await database.points.takePoints(_message.author.id, _message.guildID, 1);
|
||||
|
||||
await database`
|
||||
INSERT INTO points AS p (user_id, guild_id, points)
|
||||
VALUES ${_message.author.id}, ${_message.guildID}, 0)
|
||||
ON CONFLICT (user_id, guild_id)
|
||||
DO UPDATE SET points = GREATEST(p.points - 1, 0)
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-1
@@ -26,5 +26,16 @@ events.forEach((event) => client.registerEvent(event, true));
|
||||
|
||||
// ----------
|
||||
|
||||
database.points.init();
|
||||
database`
|
||||
CREATE TABLE IF NOT EXISTS points (
|
||||
user_id TEXT NOT NULL,
|
||||
guild_id TEXT NOT NULL,
|
||||
points INTEGER NOT NULL DEFAULT 0 CHECK (points >= 0),
|
||||
|
||||
PRIMARY KEY (user_id, guild_id)
|
||||
)
|
||||
`;
|
||||
|
||||
// ----------
|
||||
|
||||
client.connect();
|
||||
|
||||
Reference in New Issue
Block a user