package lib import ( "database/sql" "fmt" "time" "github.com/bwmarrin/discordgo" ) const ( HimbucksPerReward = 10 MessageCountThreshold = 5 CooldownPeriod = time.Minute ) type HimbucksEntry struct { Username string Balance int MessageCount int } func ProcessHimbucks(s *discordgo.Session, m *discordgo.MessageCreate, ctx *ProcessContext) error { tx, err := DBClient.Begin() if err != nil { return fmt.Errorf("failed to start transaction: %w", err) } defer tx.Rollback() // Get current state var messageCount int var lastRewardAt sql.NullTime err = tx.QueryRow(` SELECT message_count, last_reward_at FROM guild_profiles WHERE user_id = ? AND guild_id = ?`, ctx.UserID, ctx.GuildID).Scan(&messageCount, &lastRewardAt) if err != nil { return fmt.Errorf("failed to get message count: %w", err) } messageCount++ shouldReward := messageCount >= MessageCountThreshold && (!lastRewardAt.Valid || time.Since(lastRewardAt.Time) >= CooldownPeriod) if shouldReward { _, err = tx.Exec(` UPDATE guild_profiles SET currency_balance = currency_balance + ?, message_count = 0, last_reward_at = CURRENT_TIMESTAMP WHERE user_id = ? AND guild_id = ?`, HimbucksPerReward, ctx.UserID, ctx.GuildID) } else { _, err = tx.Exec(` UPDATE guild_profiles SET message_count = ? WHERE user_id = ? AND guild_id = ?`, messageCount, ctx.UserID, ctx.GuildID) } if err != nil { return fmt.Errorf("failed to update profile: %w", err) } return tx.Commit() } func GetBalance(discordID, guildID string) (int, error) { var balance int err := DBClient.QueryRow(` SELECT gp.currency_balance FROM guild_profiles gp JOIN users u ON gp.user_id = u.id WHERE u.discord_id = ? AND gp.guild_id = ?`, discordID, guildID).Scan(&balance) if err == sql.ErrNoRows { return 0, nil } if err != nil { return 0, fmt.Errorf("failed to get balance: %w", err) } return balance, nil } func SyncBalance() error { // First perform the regular sync _, syncError := DBConnector.Sync() if syncError != nil { fmt.Println("Error syncing database:", syncError) return syncError } return nil } func GetLeaderboard(guildID string, limit int) ([]HimbucksEntry, error) { rows, err := DBClient.Query(` SELECT u.username, gp.currency_balance, gp.message_count FROM guild_profiles gp JOIN users u ON gp.user_id = u.id WHERE gp.guild_id = ? ORDER BY gp.currency_balance DESC LIMIT ?`, guildID, limit) if err != nil { return nil, fmt.Errorf("failed to get leaderboard: %w", err) } defer rows.Close() var entries []HimbucksEntry for rows.Next() { var entry HimbucksEntry err := rows.Scan(&entry.Username, &entry.Balance, &entry.MessageCount) if err != nil { return nil, fmt.Errorf("failed to scan leaderboard entry: %w", err) } entries = append(entries, entry) } return entries, nil }