package user import ( "context" "database/sql" "errors" "time" ) // User مدل کاربر. type User struct { ID int64 `json:"id"` Mobile string `json:"mobile"` FirstName *string `json:"first_name"` LastName *string `json:"last_name"` Avatar *string `json:"avatar"` Coins int64 `json:"coins"` IsAdmin bool `json:"is_admin"` CreatedAt time.Time `json:"created_at"` } var ErrNotFound = errors.New("user not found") // Repo دسترسی به جدول users. type Repo struct{ db *sql.DB } func NewRepo(db *sql.DB) *Repo { return &Repo{db: db} } // FindByMobile کاربر را با شماره موبایل پیدا می‌کند. func (r *Repo) FindByMobile(ctx context.Context, mobile string) (*User, error) { row := r.db.QueryRowContext(ctx, `SELECT id, mobile, first_name, last_name, avatar, coins, is_admin, created_at FROM users WHERE mobile = ?`, mobile) return scan(row) } // FindByID کاربر را با شناسه پیدا می‌کند. func (r *Repo) FindByID(ctx context.Context, id int64) (*User, error) { row := r.db.QueryRowContext(ctx, `SELECT id, mobile, first_name, last_name, avatar, coins, is_admin, created_at FROM users WHERE id = ?`, id) return scan(row) } // Create کاربر جدید می‌سازد. func (r *Repo) Create(ctx context.Context, mobile string) (*User, error) { res, err := r.db.ExecContext(ctx, `INSERT INTO users (mobile) VALUES (?)`, mobile) if err != nil { return nil, err } id, _ := res.LastInsertId() return r.FindByID(ctx, id) } // UpdateProfile نام نمایشی و آواتار کاربر را تنظیم می‌کند. func (r *Repo) UpdateProfile(ctx context.Context, id int64, firstName, avatar string) error { _, err := r.db.ExecContext(ctx, `UPDATE users SET first_name = ?, avatar = ? WHERE id = ?`, firstName, avatar, id) return err } // FindOrCreate اگر کاربر نبود می‌سازد (مطابق فلوی login-otp). func (r *Repo) FindOrCreate(ctx context.Context, mobile string) (*User, error) { u, err := r.FindByMobile(ctx, mobile) if errors.Is(err, ErrNotFound) { return r.Create(ctx, mobile) } return u, err } func scan(row *sql.Row) (*User, error) { var u User var created string err := row.Scan(&u.ID, &u.Mobile, &u.FirstName, &u.LastName, &u.Avatar, &u.Coins, &u.IsAdmin, &created) if errors.Is(err, sql.ErrNoRows) { return nil, ErrNotFound } if err != nil { return nil, err } u.CreatedAt, _ = time.Parse("2006-01-02 15:04:05", created) return &u, nil }