233 lines
6.8 KiB
Go

package users
import (
"fmt"
"time"
"dk/internal/database"
"zombiezen.com/go/sqlite"
)
// Builder provides a fluent interface for creating users
type Builder struct {
user *User
}
// NewBuilder creates a new user builder with default values
func NewBuilder() *Builder {
now := time.Now().Unix()
return &Builder{
user: &User{
Verified: 0, // Default unverified
Token: "", // Empty verification token
Registered: now, // Current time
LastOnline: now, // Current time
Auth: 0, // Default no special permissions
X: 0, // Default starting position
Y: 0, // Default starting position
ClassID: 1, // Default to class 1
Currently: "In Town", // Default status
Fighting: 0, // Default not fighting
HP: 15, // Default starting HP
MP: 0, // Default starting MP
TP: 10, // Default starting TP
MaxHP: 15, // Default starting max HP
MaxMP: 0, // Default starting max MP
MaxTP: 10, // Default starting max TP
Level: 1, // Default starting level
Gold: 100, // Default starting gold
Exp: 0, // Default starting exp
Strength: 5, // Default starting strength
Dexterity: 5, // Default starting dexterity
Attack: 5, // Default starting attack
Defense: 5, // Default starting defense
Spells: "", // No spells initially
Towns: "", // No towns visited initially
},
}
}
// WithUsername sets the username
func (b *Builder) WithUsername(username string) *Builder {
b.user.Username = username
return b
}
// WithPassword sets the password
func (b *Builder) WithPassword(password string) *Builder {
b.user.Password = password
return b
}
// WithEmail sets the email address
func (b *Builder) WithEmail(email string) *Builder {
b.user.Email = email
return b
}
// WithVerified sets the verification status
func (b *Builder) WithVerified(verified bool) *Builder {
if verified {
b.user.Verified = 1
} else {
b.user.Verified = 0
}
return b
}
// WithToken sets the verification token
func (b *Builder) WithToken(token string) *Builder {
b.user.Token = token
return b
}
// WithAuth sets the authorization level
func (b *Builder) WithAuth(auth int) *Builder {
b.user.Auth = auth
return b
}
// AsAdmin sets the user as admin (auth = 4)
func (b *Builder) AsAdmin() *Builder {
b.user.Auth = 4
return b
}
// AsModerator sets the user as moderator (auth = 2)
func (b *Builder) AsModerator() *Builder {
b.user.Auth = 2
return b
}
// WithClassID sets the character class ID
func (b *Builder) WithClassID(classID int) *Builder {
b.user.ClassID = classID
return b
}
// WithPosition sets the starting coordinates
func (b *Builder) WithPosition(x, y int) *Builder {
b.user.X = x
b.user.Y = y
return b
}
// WithLevel sets the starting level
func (b *Builder) WithLevel(level int) *Builder {
b.user.Level = level
return b
}
// WithGold sets the starting gold amount
func (b *Builder) WithGold(gold int) *Builder {
b.user.Gold = gold
return b
}
// WithStats sets the core character stats
func (b *Builder) WithStats(strength, dexterity, attack, defense int) *Builder {
b.user.Strength = strength
b.user.Dexterity = dexterity
b.user.Attack = attack
b.user.Defense = defense
return b
}
// WithHP sets current and maximum HP
func (b *Builder) WithHP(hp, maxHP int) *Builder {
b.user.HP = hp
b.user.MaxHP = maxHP
return b
}
// WithMP sets current and maximum MP
func (b *Builder) WithMP(mp, maxMP int) *Builder {
b.user.MP = mp
b.user.MaxMP = maxMP
return b
}
// WithTP sets current and maximum TP
func (b *Builder) WithTP(tp, maxTP int) *Builder {
b.user.TP = tp
b.user.MaxTP = maxTP
return b
}
// WithCurrently sets the current status message
func (b *Builder) WithCurrently(currently string) *Builder {
b.user.Currently = currently
return b
}
// WithRegistered sets the registration timestamp
func (b *Builder) WithRegistered(registered int64) *Builder {
b.user.Registered = registered
return b
}
// WithRegisteredTime sets the registration timestamp from time.Time
func (b *Builder) WithRegisteredTime(t time.Time) *Builder {
b.user.Registered = t.Unix()
return b
}
// WithSpells sets the user's known spells
func (b *Builder) WithSpells(spells []string) *Builder {
b.user.SetSpellIDs(spells)
return b
}
// WithTowns sets the user's visited towns
func (b *Builder) WithTowns(towns []string) *Builder {
b.user.SetTownIDs(towns)
return b
}
// Create saves the user to the database and returns the created user with ID
func (b *Builder) Create() (*User, error) {
// Use a transaction to ensure we can get the ID
var user *User
err := database.Transaction(func(tx *database.Tx) error {
query := `INSERT INTO users (username, password, email, verified, token, registered, last_online, auth,
x, y, class_id, currently, fighting, monster_id, monster_hp, monster_sleep, monster_immune,
uber_damage, uber_defense, hp, mp, tp, max_hp, max_mp, max_tp, level, gold, exp,
gold_bonus, exp_bonus, strength, dexterity, attack, defense, weapon_id, armor_id, shield_id,
slot_1_id, slot_2_id, slot_3_id, weapon_name, armor_name, shield_name,
slot_1_name, slot_2_name, slot_3_name, drop_code, spells, towns)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
if err := tx.Exec(query, b.user.Username, b.user.Password, b.user.Email, b.user.Verified, b.user.Token,
b.user.Registered, b.user.LastOnline, b.user.Auth, b.user.X, b.user.Y, b.user.ClassID, b.user.Currently,
b.user.Fighting, b.user.MonsterID, b.user.MonsterHP, b.user.MonsterSleep, b.user.MonsterImmune,
b.user.UberDamage, b.user.UberDefense, b.user.HP, b.user.MP, b.user.TP, b.user.MaxHP, b.user.MaxMP, b.user.MaxTP,
b.user.Level, b.user.Gold, b.user.Exp, b.user.GoldBonus, b.user.ExpBonus, b.user.Strength, b.user.Dexterity,
b.user.Attack, b.user.Defense, b.user.WeaponID, b.user.ArmorID, b.user.ShieldID, b.user.Slot1ID,
b.user.Slot2ID, b.user.Slot3ID, b.user.WeaponName, b.user.ArmorName, b.user.ShieldName,
b.user.Slot1Name, b.user.Slot2Name, b.user.Slot3Name, b.user.DropCode, b.user.Spells, b.user.Towns); err != nil {
return fmt.Errorf("failed to insert user: %w", err)
}
// Get the last insert ID
var id int
err := tx.Query("SELECT last_insert_rowid()", func(stmt *sqlite.Stmt) error {
id = stmt.ColumnInt(0)
return nil
})
if err != nil {
return fmt.Errorf("failed to get insert ID: %w", err)
}
b.user.ID = id
user = b.user
return nil
})
if err != nil {
return nil, err
}
return user, nil
}