package db import ( "context" "database/sql" "errors" "time" ) type StateType int const ( AuthState = StateType(0) SetupState = StateType(1) JoinState = StateType(2) PlayersState = StateType(3) UpdateState = StateType(4) LicenseState = StateType(5) ) type FoundryState struct { Id int64 IsAdmin bool IsSetup bool Type StateType CreatedAt time.Time Options Options Modules Modules Systems Systems Worlds Worlds Users Users } type Compatibility struct { Id int64 Minimum string Verified string Maximum string } type Options struct { Id int64 Language string } type FoundryStateModel struct { DB *sql.DB } func (m FoundryStateModel) Insert(state *FoundryState) error { query := ` INSERT INTO foundry_state (is_admin, is_setup, state_type) VALUES ($1, $2, $3) RETURNING id, created_at` args := []any{state.IsAdmin, state.IsSetup, state.Type} ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := m.DB.QueryRowContext(ctx, query, args...).Scan(&state.Id, &state.CreatedAt) if err != nil { return err } err = m.InsertOptions(&state.Options, state.Id) if err != nil && err != sql.ErrNoRows { return err } for i := range state.Modules { err = m.InsertModule(&state.Modules[i], state.Id) if err != nil && err != sql.ErrNoRows { return err } } for i := range state.Systems { err = m.InsertSystem(&state.Systems[i], state.Id) if err != nil && err != sql.ErrNoRows { return err } } for i := range state.Worlds { err = m.InsertWorld(&state.Worlds[i], state.Id) if err != nil && err != sql.ErrNoRows { return err } } for i := range state.Users { err = m.InsertUser(&state.Users[i], state.Id) if err != nil && err != sql.ErrNoRows { return err } } return nil } func (m FoundryStateModel) InsertOptions(options *Options, stateId int64) error { query := ` INSERT INTO options (state_id, lang) VALUES ($1, $2) RETURNING id` args := []any{stateId, options.Language} ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() return m.DB.QueryRowContext(ctx, query, args...).Scan(&options.Id) } func (m FoundryStateModel) Get(id int64) (*FoundryState, error) { if id < 1 { return nil, ErrorRecordNotFound } query := ` SELECT id, created_at, is_admin, is_setup, state_type FROM foundry_state WHERE id = $1` var state FoundryState ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := m.DB.QueryRowContext(ctx, query, id).Scan( &state.Id, &state.CreatedAt, &state.IsAdmin, &state.IsSetup, &state.Type, ) if err != nil { switch { case errors.Is(err, sql.ErrNoRows): return nil, ErrorRecordNotFound default: return nil, err } } state.Modules, err = m.GetModules(state.Id) if err != nil { return nil, err } state.Systems, err = m.GetSystems(state.Id) if err != nil { return nil, err } state.Worlds, err = m.GetWorlds(state.Id) if err != nil { return nil, err } state.Users, err = m.GetUsers(state.Id) if err != nil { return nil, err } options, err := m.GetOptions(state.Id) if err != nil { return nil, err } state.Options = *options return &state, nil } func (m FoundryStateModel) GetOptions(idState int64) (*Options, error) { if idState < 1 { return nil, ErrorRecordNotFound } query := ` SELECT id, lang FROM options WHERE state_id = $1` var options Options ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() err := m.DB.QueryRowContext(ctx, query, idState).Scan( &options.Id, &options.Language, ) if err != nil { switch { case errors.Is(err, sql.ErrNoRows): return nil, ErrorRecordNotFound default: return nil, err } } return &options, nil } func (m FoundryStateModel) GetIdByType(stateType StateType) (int64, error) { if stateType < 0 { return -1, ErrorRecordNotFound } query := ` SELECT id FROM foundry_state WHERE state_type = $1` ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() var id int64 err := m.DB.QueryRowContext(ctx, query, stateType).Scan(&id) if err != nil { switch { case errors.Is(err, sql.ErrNoRows): return -1, ErrorRecordNotFound default: return -1, err } } return id, nil } func (m FoundryStateModel) Delete(id int64) error { if id < 1 { return ErrorRecordNotFound } query := ` DELETE FROM foundry_state WHERE id = $1` ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() result, err := m.DB.ExecContext(ctx, query, id) if err != nil { return err } rowsAffected, err := result.RowsAffected() if err != nil { return err } if rowsAffected == 0 { return ErrorRecordNotFound } return nil } func (m FoundryStateModel) DeleteAll() error { query := ` DELETE FROM foundry_state` ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() result, err := m.DB.ExecContext(ctx, query) if err != nil { return err } rowsAffected, err := result.RowsAffected() if err != nil { return err } if rowsAffected == 0 { return ErrorRecordNotFound } return nil } func (m FoundryStateModel) DeleteAllSeq() error { query := ` DELETE FROM sqlite_sequence` ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() result, err := m.DB.ExecContext(ctx, query) if err != nil { return err } rowsAffected, err := result.RowsAffected() if err != nil { return err } if rowsAffected == 0 { return ErrorRecordNotFound } return nil }