Skip to content

Commit

Permalink
added profile command
Browse files Browse the repository at this point in the history
  • Loading branch information
GhomKrosmonaute committed Oct 24, 2024
1 parent b676471 commit 81cc096
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 28 deletions.
131 changes: 113 additions & 18 deletions src/namespaces/coins.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import userTable from "#tables/user.ts"
import guildTable from "#tables/guild.ts"
import pointTable from "#tables/point.ts"
import noteTable from "#tables/rating.ts"
import messageTable from "#tables/message.ts"
import activeTable from "#tables/active.ts"
import { ResponseCache } from "#database"

export interface FullUser {
_id: number
id: string
coins: number // sum(coins)
points: number // sum(amount) rel(to_id)
rating: number // avg(value) rel(to_id)
rateOthers: number // count(rating.*) rel(from_id)
active: boolean // exists? in guild_id rel(user_id)
messages: number // count(message.*) in guild_id rel(author_id)
}

export async function giveHourlyCoins() {
// get all users with points and ratings from a join query.
const users: {
_id: number
coins: number
points: `${number}`
rating: `${number}`
givenNotes: `${number}`
active: `${string}` | null
messages: `${number}`
}[] = await userTable.query
const users: FullUser[] = await userTable.query
.leftJoin(
pointTable.query
.select("to_id")
Expand Down Expand Up @@ -56,7 +62,7 @@ export async function giveHourlyCoins() {
"user.coins",
"point_totals.points",
"notes.rating",
"given_notes.total as givenNotes",
"given_notes.total as rateOthers",
"active.user_id as active",
"message_totals.messages",
)
Expand Down Expand Up @@ -84,16 +90,105 @@ export async function giveHourlyCoins() {
.insert(
users.map((user) => ({
_id: user._id,
coins: Math.ceil(
user.coins +
+user.points * Math.max(1, +user.rating) +
+user.givenNotes * 5 +
(user.active
? Math.max(10, Math.floor(+user.messages * 0.001))
: 0),
),
coins: Math.ceil(user.coins + getUserHourlyCoins(user)),
})),
)
.onConflict("_id")
.merge(["coins"])
}

export function getUserHourlyCoins(user: FullUser): number {
return (
+user.points * Math.max(1, +user.rating) +
+user.rateOthers * 5 +
(user.active ? Math.max(10, Math.floor(+user.messages * 0.001)) : 0)
)
}

const fullUserCache = new ResponseCache(
async (userId: number, guildId: number) => {
// 1. Récupérer les informations de base de l'utilisateur
const user = await userTable.query
.select("_id", "id", "coins")
.where("_id", userId)
.first()

if (!user) {
return null // Si l'utilisateur n'existe pas
}

// 2. Calculer la somme des points reçus par l'utilisateur (table `point`)
const points = await pointTable.query
.sum({ points: "amount" })
.where("to_id", userId)
.first()

// 3. Calculer la moyenne des évaluations reçues (table `rating`) dans la guilde
const rating = await noteTable.query
.avg({ rating: "value" })
.where("to_id", userId)
.andWhere("guild_id", guildId)
.first()

// 4. Compter le nombre d'évaluations faites par l'utilisateur (table `rating`)
const rateOthers = await noteTable.query
.count({ rateOthers: "*" })
.where("from_id", userId)
.first()

// 5. Vérifier si l'utilisateur est actif dans la guilde (table `active`)
const active = await activeTable.query
.select("user_id")
.where("user_id", userId)
.andWhere("guild_id", guildId)
.first()

// 6. Compter le nombre de messages envoyés par l'utilisateur dans la guilde (table `message`)
const messages = await messageTable.query
.count({ messages: "*" })
.where("author_id", userId)
.andWhere("guild_id", guildId)
.first()

// Assemblage du résultat final
return {
_id: user._id,
id: user.id,
coins: Number(user.coins),
points: Number(points?.points || 0), // Valeur par défaut à 0 si pas de points
rating: Number(rating?.rating || 0), // Valeur par défaut à 0 si pas d'évaluation
rateOthers: Number(rateOthers?.rateOthers || 0), // Valeur par défaut à 0
active: !!active, // Convertit en booléen
messages: Number(messages?.messages || 0), // Valeur par défaut à 0 si pas de messages
}
},
6_000_000,
)

export async function getFullUser(user: { id: string }, guild: { id: string }) {
const userId = await userTable.cache.get(
`user.id.${user.id}`,
async (query) => {
return query
.select("_id")
.where("id", user.id)
.first()
.then((user) => user?._id)
},
)

const guildId = await guildTable.cache.get(
`guild.id.${guild.id}`,
async (query) => {
return query
.select("_id")
.where("id", guild.id)
.first()
.then((guild) => guild?._id)
},
)

if (!userId || !guildId) return null

return fullUserCache.get(user.id, userId, guildId)
}
16 changes: 8 additions & 8 deletions src/namespaces/rating.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ export interface RatingLadderLine {

const mineRatingCount = 2

export function renderNoteValue(value: number) {
export function renderRatingValue(value: number) {
return `**${value.toFixed(2).replace(/\.?0+$/, "")}**`
}

export function renderNoteBar(value?: number) {
export function renderRatingBar(value?: number) {
const full = "▰"
const empty = "▱"
const round = Math.round(value ?? 0)
return full.repeat(round) + empty.repeat(5 - round)
}

export function renderNoteLine(value: number, count: number) {
return `${renderNoteBar(value)} ${renderNoteValue(value)} / 5 (*x${count}*)`
export function renderRatingLine(value: number, count: number) {
return `${renderRatingBar(value)} ${renderRatingValue(value)} / 5 (*x${count}*)`
}

export const ratingLadder = (guild_id?: number) =>
Expand Down Expand Up @@ -63,7 +63,7 @@ export const ratingLadder = (guild_id?: number) =>
)
},
formatLine(line) {
return `${app.formatRank(line.rank)} ${renderNoteLine(
return `${app.formatRank(line.rank)} ${renderRatingLine(
line.score,
line.rating_count,
)} <@${line.target}>`
Expand Down Expand Up @@ -128,7 +128,7 @@ export async function ratingEmbed(target: app.GuildMember) {
const fields: app.EmbedField[] = [
{
name: "Global rating",
value: renderNoteLine(globalRating.avg, globalRating.count),
value: renderRatingLine(globalRating.avg, globalRating.count),
inline: false,
},
]
Expand All @@ -140,7 +140,7 @@ export async function ratingEmbed(target: app.GuildMember) {
) {
fields.push({
name: target.guild.name,
value: renderNoteLine(guildRating.avg, guildRating.count),
value: renderRatingLine(guildRating.avg, guildRating.count),
inline: false,
})
}
Expand All @@ -151,7 +151,7 @@ export async function ratingEmbed(target: app.GuildMember) {
value: externalRating
.map(
({ rating, guild }) =>
`${renderNoteLine(rating.avg, rating.count)} - **${guild.name}**`,
`${renderRatingLine(rating.avg, rating.count)} - **${guild.name}**`,
)
.join("\n"),
inline: false,
Expand Down
4 changes: 2 additions & 2 deletions src/namespaces/tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export async function sendLog(

const userCache = new ResponseCache((id: string) => {
return users.query.where("id", id).first()
}, 60_000)
}, 600_000)

export async function getUser(user: { id: string }): Promise<User | undefined>
export async function getUser(user: { id: string }, force: true): Promise<User>
Expand All @@ -59,7 +59,7 @@ export async function getUser(user: { id: string }, force?: true) {

const guildCache = new ResponseCache((id: string) => {
return guilds.query.where("id", id).first()
}, 60_000)
}, 600_000)

export async function getGuild(guild: {
id: string
Expand Down
55 changes: 55 additions & 0 deletions src/slash/profile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as app from "#app"

import messageTable from "#tables/message.ts"

export default new app.SlashCommand({
name: "profile",
description: "View your profile",
guildOnly: true,
channelType: "guild",
async run(interaction) {
const user = await app.getFullUser(interaction.user, interaction.guild)

if (!user) return interaction.reply("You don't have a profile yet.")

const guild = await app.getGuild(interaction.guild)

if (!guild)
return interaction.reply("This guild is not registered in the database.")

const pointRank = await app.getPointRank(interaction.user)

return interaction.reply({
embeds: [
new app.EmbedBuilder()
.setTitle(`Profile of ${interaction.user.tag}`)
.setThumbnail(interaction.user.displayAvatarURL())
.setDescription(
(pointRank
? `Helper rank: **#${pointRank.rank}** (**${user.points}** pts)\n`
: "") +
`Total money: **${user.coins}** 🪙\n` +
`Hourly money: **${Math.floor(app.getUserHourlyCoins(user))}** 🪙\n` +
`Messages sent: **${await messageTable.cache.count(
`author_id = ${user._id} AND guild_id = ${guild._id}`,
)}**`,
)
.setFields(
{
name: `Rating: ${app.renderRatingValue(user.rating)}`,
value: app.renderRatingBar(user.rating),
inline: true,
},
{
name: "Prestige",
value:
user.active && guild.active_role_id
? app.roleMention(guild.active_role_id)
: "`nope`",
inline: true,
},
),
],
})
},
})

0 comments on commit 81cc096

Please sign in to comment.