many update
This commit is contained in:
@ -14,8 +14,15 @@ func HandleCommand(commandName string, cooldownDuration time.Duration, handler C
|
||||
return
|
||||
}
|
||||
|
||||
// Get user information (handle both guild and DM contexts)
|
||||
user, userErr := GetUser(i)
|
||||
if userErr != nil {
|
||||
RespondWithError(s, i, "Error getting user information: "+userErr.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Get or create user and guild profile
|
||||
_, createUserError := GetOrCreateUserWithGuild(i.Member.User.ID, i.Member.User.Username, i.GuildID)
|
||||
_, createUserError := GetOrCreateUserWithGuild(user.ID, user.Username, i.GuildID)
|
||||
|
||||
if createUserError != nil {
|
||||
RespondWithError(s, i, "Error creating user profile: "+createUserError.Error())
|
||||
|
90
lib/config.go
Normal file
90
lib/config.go
Normal file
@ -0,0 +1,90 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Config holds all configuration values
|
||||
type Config struct {
|
||||
// Discord settings
|
||||
DiscordToken string
|
||||
|
||||
// Himbucks settings
|
||||
HimbucksPerReward int
|
||||
MessageCountThreshold int
|
||||
CooldownPeriod time.Duration
|
||||
|
||||
// Markov settings
|
||||
MarkovDefaultMessages int
|
||||
MarkovMaxMessages int
|
||||
MarkovCacheSize int
|
||||
|
||||
// Database settings
|
||||
MaxOpenConns int
|
||||
MaxIdleConns int
|
||||
ConnMaxLifetime time.Duration
|
||||
|
||||
// Command cooldowns (in seconds)
|
||||
PingCooldown int
|
||||
HsCooldown int
|
||||
MarkovCooldown int
|
||||
HimbucksCooldown int
|
||||
HimboardCooldown int
|
||||
SendbucksCooldown int
|
||||
}
|
||||
|
||||
var AppConfig *Config
|
||||
|
||||
// LoadConfig loads configuration from environment variables
|
||||
func LoadConfig() *Config {
|
||||
config := &Config{
|
||||
// Discord settings
|
||||
DiscordToken: getEnv("DISCORD_TOKEN", ""),
|
||||
|
||||
// Himbucks settings
|
||||
HimbucksPerReward: getEnvInt("HIMBUCKS_PER_REWARD", 10),
|
||||
MessageCountThreshold: getEnvInt("MESSAGE_COUNT_THRESHOLD", 5),
|
||||
CooldownPeriod: time.Duration(getEnvInt("HIMBUCKS_COOLDOWN_MINUTES", 1)) * time.Minute,
|
||||
|
||||
// Markov settings
|
||||
MarkovDefaultMessages: getEnvInt("MARKOV_DEFAULT_MESSAGES", 100),
|
||||
MarkovMaxMessages: getEnvInt("MARKOV_MAX_MESSAGES", 1000),
|
||||
MarkovCacheSize: getEnvInt("MARKOV_CACHE_SIZE", 10),
|
||||
|
||||
// Database settings
|
||||
MaxOpenConns: getEnvInt("DB_MAX_OPEN_CONNS", 25),
|
||||
MaxIdleConns: getEnvInt("DB_MAX_IDLE_CONNS", 5),
|
||||
ConnMaxLifetime: time.Duration(getEnvInt("DB_CONN_MAX_LIFETIME_MINUTES", 5)) * time.Minute,
|
||||
|
||||
// Command cooldowns (in seconds)
|
||||
PingCooldown: getEnvInt("PING_COOLDOWN_SECONDS", 5),
|
||||
HsCooldown: getEnvInt("HS_COOLDOWN_SECONDS", 10),
|
||||
MarkovCooldown: getEnvInt("MARKOV_COOLDOWN_SECONDS", 30),
|
||||
HimbucksCooldown: getEnvInt("HIMBUCKS_COOLDOWN_SECONDS", 5),
|
||||
HimboardCooldown: getEnvInt("HIMBOARD_COOLDOWN_SECONDS", 5),
|
||||
SendbucksCooldown: getEnvInt("SENDBUCKS_COOLDOWN_SECONDS", 1800),
|
||||
}
|
||||
|
||||
AppConfig = config
|
||||
return config
|
||||
}
|
||||
|
||||
// getEnv gets an environment variable with a default value
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// getEnvInt gets an environment variable as an integer with a default value
|
||||
func getEnvInt(key string, defaultValue int) int {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
if intValue, err := strconv.Atoi(value); err == nil {
|
||||
return intValue
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
84
lib/db.go
84
lib/db.go
@ -16,6 +16,15 @@ import (
|
||||
var DBClient *sql.DB
|
||||
var DBConnector *libsql.Connector
|
||||
|
||||
// Prepared statements
|
||||
var (
|
||||
stmtGetBalance *sql.Stmt
|
||||
stmtUpdateBalance *sql.Stmt
|
||||
stmtGetLeaderboard *sql.Stmt
|
||||
stmtGetUserProfile *sql.Stmt
|
||||
stmtUpdateProfile *sql.Stmt
|
||||
)
|
||||
|
||||
func InitDB() error {
|
||||
// Determine DB path based on /data directory existence
|
||||
var dbPath string
|
||||
@ -31,9 +40,24 @@ func InitDB() error {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Configure connection pool using config values
|
||||
db.SetMaxOpenConns(AppConfig.MaxOpenConns)
|
||||
db.SetMaxIdleConns(AppConfig.MaxIdleConns)
|
||||
db.SetConnMaxLifetime(AppConfig.ConnMaxLifetime)
|
||||
|
||||
// Test the connection
|
||||
if err := db.Ping(); err != nil {
|
||||
return fmt.Errorf("failed to ping database: %w", err)
|
||||
}
|
||||
|
||||
DBClient = db
|
||||
|
||||
return runMigrations()
|
||||
if err := runMigrations(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Prepare frequently used statements
|
||||
return prepareStatements()
|
||||
}
|
||||
|
||||
type Migration struct {
|
||||
@ -140,3 +164,61 @@ func runMigrations() error {
|
||||
log.Println("Database migrations completed successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
func prepareStatements() error {
|
||||
var err error
|
||||
|
||||
// Prepare balance query
|
||||
stmtGetBalance, err = DBClient.Prepare(`
|
||||
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 = ?`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to prepare balance query: %w", err)
|
||||
}
|
||||
|
||||
// Prepare leaderboard query
|
||||
stmtGetLeaderboard, err = DBClient.Prepare(`
|
||||
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 ?`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to prepare leaderboard query: %w", err)
|
||||
}
|
||||
|
||||
// Prepare user profile query
|
||||
stmtGetUserProfile, err = DBClient.Prepare(`
|
||||
SELECT message_count, last_reward_at
|
||||
FROM guild_profiles
|
||||
WHERE user_id = ? AND guild_id = ?`)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to prepare user profile query: %w", err)
|
||||
}
|
||||
|
||||
log.Println("Prepared statements initialized successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
// CleanupDB closes all prepared statements
|
||||
func CleanupDB() {
|
||||
if stmtGetBalance != nil {
|
||||
stmtGetBalance.Close()
|
||||
}
|
||||
if stmtUpdateBalance != nil {
|
||||
stmtUpdateBalance.Close()
|
||||
}
|
||||
if stmtGetLeaderboard != nil {
|
||||
stmtGetLeaderboard.Close()
|
||||
}
|
||||
if stmtGetUserProfile != nil {
|
||||
stmtGetUserProfile.Close()
|
||||
}
|
||||
if stmtUpdateProfile != nil {
|
||||
stmtUpdateProfile.Close()
|
||||
}
|
||||
log.Println("Database cleanup completed")
|
||||
}
|
||||
|
@ -8,12 +8,6 @@ import (
|
||||
"github.com/bwmarrin/discordgo"
|
||||
)
|
||||
|
||||
const (
|
||||
HimbucksPerReward = 10
|
||||
MessageCountThreshold = 5
|
||||
CooldownPeriod = time.Minute
|
||||
)
|
||||
|
||||
type HimbucksEntry struct {
|
||||
Username string
|
||||
Balance int
|
||||
@ -41,8 +35,8 @@ func ProcessHimbucks(s *discordgo.Session, m *discordgo.MessageCreate, ctx *Proc
|
||||
}
|
||||
|
||||
messageCount++
|
||||
shouldReward := messageCount >= MessageCountThreshold &&
|
||||
(!lastRewardAt.Valid || time.Since(lastRewardAt.Time) >= CooldownPeriod)
|
||||
shouldReward := messageCount >= AppConfig.MessageCountThreshold &&
|
||||
(!lastRewardAt.Valid || time.Since(lastRewardAt.Time) >= AppConfig.CooldownPeriod)
|
||||
|
||||
if shouldReward {
|
||||
_, err = tx.Exec(`
|
||||
@ -51,7 +45,7 @@ func ProcessHimbucks(s *discordgo.Session, m *discordgo.MessageCreate, ctx *Proc
|
||||
message_count = 0,
|
||||
last_reward_at = CURRENT_TIMESTAMP
|
||||
WHERE user_id = ? AND guild_id = ?`,
|
||||
HimbucksPerReward, ctx.UserID, ctx.GuildID)
|
||||
AppConfig.HimbucksPerReward, ctx.UserID, ctx.GuildID)
|
||||
} else {
|
||||
_, err = tx.Exec(`
|
||||
UPDATE guild_profiles
|
||||
@ -69,12 +63,7 @@ func ProcessHimbucks(s *discordgo.Session, m *discordgo.MessageCreate, ctx *Proc
|
||||
|
||||
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)
|
||||
err := stmtGetBalance.QueryRow(discordID, guildID).Scan(&balance)
|
||||
if err == sql.ErrNoRows {
|
||||
return 0, nil
|
||||
}
|
||||
@ -173,14 +162,7 @@ func SendBalance(fromDiscordID, toDiscordID, guildID string, amount int) error {
|
||||
}
|
||||
|
||||
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)
|
||||
rows, err := stmtGetLeaderboard.Query(guildID, limit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get leaderboard: %w", err)
|
||||
}
|
||||
|
Reference in New Issue
Block a user