From 095dac5db74508884440dcb69b151e1fe1834b04 Mon Sep 17 00:00:00 2001 From: lbenedar Date: Mon, 6 Apr 2026 16:40:49 +0300 Subject: [PATCH] add db models, refactor json models, add references in migrations --- cmd/api/handlers.go | 43 ++--- cmd/api/main.go | 2 + db/migrations/000002_create_modules.up.sql | 5 +- db/migrations/000003_create_systems.up.sql | 5 +- db/migrations/000004_create_worlds.up.sql | 5 +- db/migrations/000005_create_users.up.sql | 5 +- internal/foundry/foundry.go | 20 +- internal/foundry/models/data.go | 44 ----- internal/foundry/models/{ => db}/errors.go | 2 +- internal/foundry/models/db/foundry_state.go | 113 +++++++++++ internal/foundry/models/db/models.go | 35 ++++ internal/foundry/models/db/module.go | 84 ++++++++ internal/foundry/models/db/system.go | 53 +++++ internal/foundry/models/db/user.go | 91 +++++++++ internal/foundry/models/db/world.go | 81 ++++++++ internal/foundry/models/json/data.go | 181 ++++++++++++++++++ internal/foundry/models/json/errors.go | 8 + .../foundry/models/{ => json}/language.go | 2 +- .../models/{ => json}/modules/dice-stats.go | 0 .../foundry/models/{ => json}/modules/pf2e.go | 0 internal/foundry/models/{ => json}/release.go | 2 +- internal/foundry/models/{ => json}/status.go | 2 +- .../foundry/models/{ => json}/template.go | 2 +- internal/foundry/models/{ => json}/users.go | 4 +- internal/foundry/models/module.go | 49 ----- internal/foundry/models/system.go | 36 ---- internal/foundry/models/world.go | 88 --------- internal/foundry/requests/get_requests.go | 6 +- 28 files changed, 709 insertions(+), 259 deletions(-) delete mode 100644 internal/foundry/models/data.go rename internal/foundry/models/{ => db}/errors.go (92%) create mode 100644 internal/foundry/models/db/foundry_state.go create mode 100644 internal/foundry/models/db/models.go create mode 100644 internal/foundry/models/db/module.go create mode 100644 internal/foundry/models/db/system.go create mode 100644 internal/foundry/models/db/user.go create mode 100644 internal/foundry/models/db/world.go create mode 100644 internal/foundry/models/json/data.go create mode 100644 internal/foundry/models/json/errors.go rename internal/foundry/models/{ => json}/language.go (94%) rename internal/foundry/models/{ => json}/modules/dice-stats.go (100%) rename internal/foundry/models/{ => json}/modules/pf2e.go (100%) rename internal/foundry/models/{ => json}/release.go (95%) rename internal/foundry/models/{ => json}/status.go (95%) rename internal/foundry/models/{ => json}/template.go (99%) rename internal/foundry/models/{ => json}/users.go (97%) delete mode 100644 internal/foundry/models/module.go delete mode 100644 internal/foundry/models/system.go delete mode 100644 internal/foundry/models/world.go diff --git a/cmd/api/handlers.go b/cmd/api/handlers.go index a1aaa92..dfd0610 100644 --- a/cmd/api/handlers.go +++ b/cmd/api/handlers.go @@ -2,8 +2,6 @@ package main import ( "net/http" - - "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models" ) func (app *application) ShowText(w http.ResponseWriter, r *http.Request) { @@ -27,27 +25,28 @@ func (app *application) ShowText(w http.ResponseWriter, r *http.Request) { } func (app *application) WhenNextSession(w http.ResponseWriter, r *http.Request) { - data, err := app.foundryApp.HandleWSRequest("/setup") - if err != nil { - app.slogger.Error("", "error", err) - w.Write([]byte(err.Error())) - return - } + // data, err := app.foundryApp.HandleWSRequest("/setup") + // if err != nil { + // app.slogger.Error("", "error", err) + // w.Write([]byte(err.Error())) + // return + // } - setupData, err := models.ParseSetupModel(data) - if err != nil { - app.slogger.Error("", "error", err) - w.Write([]byte(err.Error())) - return - } + // setupData, err := json_model.ParseSetupModel(data) + // if err != nil { + // app.slogger.Error("", "error", err) + // w.Write([]byte(err.Error())) + // return + // } - nextSession, err := setupData.GetWorlds().GetSessionTime("") - if err != nil { - app.slogger.Error("", "error", err) - w.Write([]byte(err.Error())) - return - } + // // nextSession, err := setupData.GetWorlds().GetSessionTime("") + // // if err != nil { + // // app.slogger.Error("", "error", err) + // // w.Write([]byte(err.Error())) + // // return + // // } - app.slogger.Info("Next session data is ready to send", "sessionTime", nextSession) - w.Write([]byte(nextSession.Local().String())) + // app.slogger.Info("Next session data is ready to send", "sessionTime", nextSession) + // w.Write([]byte(nextSession.Local().String())) + return } diff --git a/cmd/api/main.go b/cmd/api/main.go index 48faddc..9632d52 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -150,6 +150,8 @@ func main() { defer db.Close() app.slogger.Info("Database connection pool established") + app.foundryApp.CreateNewDataModels(db) + go app.StartListenFoundry() errLog := slog.NewLogLogger(app.slogger.Handler(), slog.LevelError) diff --git a/db/migrations/000002_create_modules.up.sql b/db/migrations/000002_create_modules.up.sql index f83d451..aab5a74 100644 --- a/db/migrations/000002_create_modules.up.sql +++ b/db/migrations/000002_create_modules.up.sql @@ -1,13 +1,14 @@ CREATE TABLE IF NOT EXISTS modules ( id INTEGER PRIMARY KEY AUTOINCREMENT, + state_id INTEGER NOT NULL, text_id VARCHAR(256) NOT NULL, title VARCHAR(256) NOT NULL, description TEXT NOT NULL, url VARCHAR(256) NOT NULL, version VARCHAR(64) NOT NULL, availability INTEGER NOT NULL, - - created_at DATETIME NOT NULL DEFAULT current_timestamp + created_at DATETIME NOT NULL DEFAULT current_timestamp, + FOREIGN KEY (state_id) REFERENCES foundry_state(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS modules_compatibility ( diff --git a/db/migrations/000003_create_systems.up.sql b/db/migrations/000003_create_systems.up.sql index e8cc274..245ab89 100644 --- a/db/migrations/000003_create_systems.up.sql +++ b/db/migrations/000003_create_systems.up.sql @@ -1,12 +1,13 @@ CREATE TABLE IF NOT EXISTS systems ( id INTEGER PRIMARY KEY AUTOINCREMENT, + state_id INTEGER NOT NULL, text_id VARCHAR(256) NOT NULL, title VARCHAR(256) NOT NULL, description TEXT NOT NULL, url VARCHAR(256) NOT NULL, download VARCHAR(256) NOT NULL, - - created_at DATETIME NOT NULL DEFAULT current_timestamp + created_at DATETIME NOT NULL DEFAULT current_timestamp, + FOREIGN KEY (state_id) REFERENCES foundry_state(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS systems_compatibility ( diff --git a/db/migrations/000004_create_worlds.up.sql b/db/migrations/000004_create_worlds.up.sql index 0da2ae2..459cd36 100644 --- a/db/migrations/000004_create_worlds.up.sql +++ b/db/migrations/000004_create_worlds.up.sql @@ -1,5 +1,6 @@ CREATE TABLE IF NOT EXISTS worlds ( id INTEGER PRIMARY KEY AUTOINCREMENT, + state_id INTEGER NOT NULL, text_id VARCHAR(256) NOT NULL, title VARCHAR(256) NOT NULL, description TEXT NOT NULL, @@ -8,8 +9,8 @@ CREATE TABLE IF NOT EXISTS worlds ( system_version VARCHAR(256) NOT NULL, playtime INTEGER NOT NULL, next_session DATETIME NOT NULL, - - created_at DATETIME NOT NULL DEFAULT current_timestamp + created_at DATETIME NOT NULL DEFAULT current_timestamp, + FOREIGN KEY (state_id) REFERENCES foundry_state(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS worlds_compatibility ( diff --git a/db/migrations/000005_create_users.up.sql b/db/migrations/000005_create_users.up.sql index 9564948..350e377 100644 --- a/db/migrations/000005_create_users.up.sql +++ b/db/migrations/000005_create_users.up.sql @@ -1,12 +1,13 @@ CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, + state_id INTEGER NOT NULL, name VARCHAR(256) NOT NULL, role INTEGER NOT NULL, character VARCHAR(128) NOT NULL, color VARCHAR(128) NOT NULL, pronouns VARCHAR(128) NOT NULL, - - created_at DATETIME NOT NULL DEFAULT current_timestamp + created_at DATETIME NOT NULL DEFAULT current_timestamp, + FOREIGN KEY (state_id) REFERENCES foundry_state(id) ON DELETE CASCADE ); CREATE TABLE IF NOT EXISTS users_hotbar ( diff --git a/internal/foundry/foundry.go b/internal/foundry/foundry.go index d36a776..69b00d5 100644 --- a/internal/foundry/foundry.go +++ b/internal/foundry/foundry.go @@ -1,6 +1,7 @@ package foundry import ( + "database/sql" "errors" "fmt" "io" @@ -10,6 +11,7 @@ import ( "strconv" "strings" + data "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models/db" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/requests" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" "github.com/gorilla/websocket" @@ -47,8 +49,7 @@ type Foundry struct { isAuth bool logger *slog.Logger - // db db.DB - + models data.Models config requests.Config ws *webSocketUtil } @@ -110,6 +111,17 @@ func (foundry *Foundry) StartListen() error { var err error for { select { + // case msg, ok := <-foundry.ws.channels.Msg(): + // if !ok { + // time.Sleep(5 * time.Microsecond) + // continue + // } + // var foundryState *json_model.FoundryState + // foundryState, err = json_model.ParseSetupModel(msg.ToByteSlice()) + // if err != nil { + // return nil + // } + // foundry.models.FoundryState.Insert(foundryState) case err = <-wsChannels.Err(): var foundryErr *FoundryError if errors.As(err, &foundryErr) { @@ -205,6 +217,10 @@ func (foundry *Foundry) SetLogger(slogger *slog.Logger) { foundry.ws.logger = slogger } +func (foundry *Foundry) CreateNewDataModels(db *sql.DB) { + foundry.models = data.NewModels(db) +} + // /** // * Poll the server to see if a World has become active, and automatically refresh if so. // * @returns {Promise} diff --git a/internal/foundry/models/data.go b/internal/foundry/models/data.go deleted file mode 100644 index 0dc7afc..0000000 --- a/internal/foundry/models/data.go +++ /dev/null @@ -1,44 +0,0 @@ -package models - -import ( - "encoding/json" -) - -type FoundryState struct { - IsAdmin bool `json:"isAdmin,omitempty"` - IsSetup bool `json:"isSetup,omitempty"` - Languages []Language `json:"languages,omitempty"` - Modules []DataTemplate `json:"modules"` - Release Release `json:"release"` - Systems []DataTemplate `json:"systems,omitempty"` - Worlds []DataTemplate `json:"worlds,omitempty"` - World *DataTemplate `json:"world,omitempty"` - Users Users `json:"users,omitempty"` - Options struct { - Language string `json:"language,omitempty"` - } `json:"options,omitempty"` - - //coreUpdate struct{} - //featuredContent struct{} - //files struct{} - //news struct{} - - //packageWarnings struct{} think about it -} - -func (state FoundryState) GetRelease() Release { - return state.Release -} - -func ParseSetupModel(data []byte) (*FoundryState, error) { - var modelSetup []FoundryState - err := json.Unmarshal(data, &modelSetup) - if err != nil { - return nil, err - } - - if len(modelSetup) > 1 { - return nil, ErrorSetupMoreThanOne - } - return &modelSetup[0], nil -} diff --git a/internal/foundry/models/errors.go b/internal/foundry/models/db/errors.go similarity index 92% rename from internal/foundry/models/errors.go rename to internal/foundry/models/db/errors.go index acaab8c..aea69d7 100644 --- a/internal/foundry/models/errors.go +++ b/internal/foundry/models/db/errors.go @@ -1,4 +1,4 @@ -package models +package db import "errors" diff --git a/internal/foundry/models/db/foundry_state.go b/internal/foundry/models/db/foundry_state.go new file mode 100644 index 0000000..6d047b3 --- /dev/null +++ b/internal/foundry/models/db/foundry_state.go @@ -0,0 +1,113 @@ +package db + +import ( + "context" + "database/sql" + "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 int + IsAdmin bool + IsSetup bool + Type StateType + CreatedAt time.Time + Options Options + Modules Modules + Systems Systems + Worlds Worlds + Users Users +} + +type Compatibility struct { + Id int + Minimum string + Verified string + Maximum string +} + +type Options struct { + Id int + 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 { + return err + } + + for i := range state.Modules { + err = m.InsertModule(&state.Modules[i], state.Id) + if err != nil { + return err + } + } + + for i := range state.Systems { + err = m.InsertSystem(&state.Systems[i], state.Id) + if err != nil { + return err + } + } + + for i := range state.Worlds { + err = m.InsertWorld(&state.Worlds[i], state.Id) + if err != nil { + return err + } + } + + for i := range state.Users { + err = m.InsertUser(&state.Users[i], state.Id) + if err != nil { + return err + } + } + + return nil +} + +func (m FoundryStateModel) InsertOptions(options *Options, stateId int) 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) +} diff --git a/internal/foundry/models/db/models.go b/internal/foundry/models/db/models.go new file mode 100644 index 0000000..85065e1 --- /dev/null +++ b/internal/foundry/models/db/models.go @@ -0,0 +1,35 @@ +package db + +import "database/sql" + +// var ( +// ErrRecordNotFound = errors.New("record not found") +// ErrEditConflict = errors.New("edit conflict") +// ) + +type Models struct { + FoundryState FoundryStateModel +} + +// type Models struct { +// Movies interface { +// Insert(movie *Movie) error +// Get(id int64) (*Movie, error) +// Update(movie *Movie) error +// Delete(id int64) error +// GetAll(title string, genres []string, filter Filters) ([]*Movie, Metadata, error) +// } +// } + +func NewModels(db *sql.DB) Models { + return Models{ + FoundryState: FoundryStateModel{DB: db}, + } +} + +// func NewMockModels() Models { +// return Models{ +// Movies: MockMovieModel{}, +// Users: MockMovieModel{}, +// } +// } diff --git a/internal/foundry/models/db/module.go b/internal/foundry/models/db/module.go new file mode 100644 index 0000000..adfe618 --- /dev/null +++ b/internal/foundry/models/db/module.go @@ -0,0 +1,84 @@ +package db + +import ( + "context" + "time" +) + +type Module struct { + Id int + TextId string + Title string + Description string + Url string + Version string + Availability int + CreatedAt time.Time + Languages []Language + Compatibility Compatibility +} + +type Language struct { + Id string + Lang string + Name string + Path string +} + +type Modules []Module + +func (modules Modules) GetById(id int) *Module { + return &modules[id] +} + +func (m FoundryStateModel) InsertModule(module *Module, stateId int) error { + query := ` + INSERT INTO modules (state_id, text_id, title, description, url, version, availability) + VALUES ($1, $2, $3, $4, $5, $6, $7) + RETURNING id, created_at` + + args := []any{stateId, module.TextId, module.Title, module.Description, module.Url, module.Version, module.Availability} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + err := m.DB.QueryRowContext(ctx, query, args...).Scan(&module.Id, &module.CreatedAt) + if err != nil { + return err + } + for i := range module.Languages { + err = m.InsertModuleLanguages(&module.Languages[i], module.Id) + if err != nil { + return err + } + } + return m.InsertModuleCompatibility(&module.Compatibility, module.Id) +} + +func (m FoundryStateModel) InsertModuleCompatibility(compatibility *Compatibility, moduleId int) error { + query := ` + INSERT INTO modules_compatibility (model_id, minumum, verified, maximum) + VALUES ($1, $2, $3, $4) + RETURNING id` + + args := []any{moduleId, compatibility.Minimum, compatibility.Verified, compatibility.Maximum} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + return m.DB.QueryRowContext(ctx, query, args...).Scan(&compatibility.Id) +} + +func (m FoundryStateModel) InsertModuleLanguages(lang *Language, moduleId int) error { + query := ` + INSERT INTO modules_compatibility (model_id, language, name, path) + VALUES ($1, $2, $3, $4) + RETURNING id` + + args := []any{moduleId, lang.Lang, lang.Name, lang.Path} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + return m.DB.QueryRowContext(ctx, query, args...).Scan(&lang.Id) +} diff --git a/internal/foundry/models/db/system.go b/internal/foundry/models/db/system.go new file mode 100644 index 0000000..aca1f8d --- /dev/null +++ b/internal/foundry/models/db/system.go @@ -0,0 +1,53 @@ +package db + +import ( + "context" + "time" +) + +type System struct { + Id int + TextId string + Title string + Description string + Url string + Download string + CreatedAt time.Time + Compatibility Compatibility +} + +type Systems []System + +func (systems Systems) GetById(id int) *System { + return &systems[id] +} + +func (m FoundryStateModel) InsertSystem(system *System, stateId int) error { + query := ` + INSERT INTO systems (state_id, text_id, title, description, url, download) + VALUES ($1, $2, $3, $4, $5, $6)` + + args := []any{stateId, system.TextId, system.Title, system.Description, system.Url, system.Download} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + err := m.DB.QueryRowContext(ctx, query, args...).Scan(&system.Id) + if err != nil { + return err + } + return m.InsertModuleCompatibility(&system.Compatibility, system.Id) +} + +func (m FoundryStateModel) InsertSystenCompatibility(compatibility *Compatibility, systemId int) error { + query := ` + INSERT INTO systems_compatibility (system_id, minumum, verified, maximum) + VALUES ($1, $2, $3, $4)` + + args := []any{systemId, compatibility.Minimum, compatibility.Verified, compatibility.Maximum} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + return m.DB.QueryRowContext(ctx, query, args...).Scan(&compatibility.Id) +} diff --git a/internal/foundry/models/db/user.go b/internal/foundry/models/db/user.go new file mode 100644 index 0000000..922aae7 --- /dev/null +++ b/internal/foundry/models/db/user.go @@ -0,0 +1,91 @@ +package db + +import ( + "context" + "time" +) + +type User struct { + Id int + Name string + Role int + Character string + Color string + Pronouns string + CreatedAt time.Time + Hotbar map[string]string + Stats UserStats +} + +type UserStats struct { + Id int + CoreVersion string + SystemId string + SystemVersion string + CreatedTime int64 + ModifiedTime int64 + LastModifiedBy string +} + +type Users []User + +func (users Users) GetById(id int) *User { + return &users[id] +} + +func (m FoundryStateModel) InsertUser(user *User, stateId int) error { + query := ` + INSERT INTO users (state_id, name, role, character, color, pronouns) + VALUES ($1, $2, $3, $4, $5, $6) + RETURNING id, created_at` + + args := []any{stateId, user.Name, user.Role, user.Character, user.Color, user.Pronouns} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + err := m.DB.QueryRowContext(ctx, query, args...).Scan(&user.Id, &user.CreatedAt) + if err != nil { + return err + } + + for k, v := range user.Hotbar { + err = m.InsertUserHotbar(k, v, user.Id) + if err != nil { + return err + } + } + + return m.InsertUserStats(&user.Stats, user.Id) +} + +func (m FoundryStateModel) InsertUserHotbar(key string, value string, userId int) error { + query := ` + INSERT INTO users_hotbar (user_id, key, value) + VALUES ($1, $2, $3)` + + args := []any{userId, key, value} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + _, err := m.DB.ExecContext(ctx, query, args...) + if err != nil { + return err + } + return nil +} + +func (m FoundryStateModel) InsertUserStats(stats *UserStats, userId int) error { + query := ` + INSERT INTO users_stats (user_id, core_version, system_id, system_version, created_time, modified_time, last_modified_by) + VALUES ($1, $2, $3, $4, $5, $6, $7) + RETURNING id` + + args := []any{userId, stats.CoreVersion, stats.SystemId, stats.SystemVersion, stats.CreatedTime, stats.ModifiedTime, stats.LastModifiedBy} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + return m.DB.QueryRowContext(ctx, query, args...).Scan(&stats.Id) +} diff --git a/internal/foundry/models/db/world.go b/internal/foundry/models/db/world.go new file mode 100644 index 0000000..2be1c5a --- /dev/null +++ b/internal/foundry/models/db/world.go @@ -0,0 +1,81 @@ +package db + +import ( + "context" + "time" +) + +type World struct { + Id int + TextId string + Title string + Description string + System string + CoreVersion string + SystemVersion string + LastPlayed string + PlayTime int64 + NextSession time.Time + CreatedAt time.Time + Compatibility Compatibility +} + +type Worlds []World + +func (worlds Worlds) GetById(id int) *World { + return &worlds[id] +} + +func (m FoundryStateModel) InsertWorld(world *World, stateId int) error { + query := ` + INSERT INTO worlds (state_id, text_id, title, description, system, core_version, system_version, playtime, next_session) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) + RETURNING id, created_at` + + args := []any{stateId, world.TextId, world.Title, world.Description, world.System, world.System, world.CoreVersion, world.SystemVersion, world.PlayTime, world.NextSession} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + err := m.DB.QueryRowContext(ctx, query, args...).Scan(&world.Id, &world.CreatedAt) + if err != nil { + return err + } + return m.InsertWorldCompatibility(&world.Compatibility, world.Id) +} + +func (m FoundryStateModel) InsertWorldCompatibility(compatibility *Compatibility, worldId int) error { + query := ` + INSERT INTO worlds_compatibility (world_id, minumum, verified, maximum) + VALUES ($1, $2, $3, $4) + RETURNING id` + + args := []any{worldId, compatibility.Minimum, compatibility.Verified, compatibility.Maximum} + + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + + return m.DB.QueryRowContext(ctx, query, args...).Scan(&compatibility.Id) +} + +// func (worlds Worlds) GetSessionTime(worldName string) (*time.Time, error) { +// if worldName == "" && len(worlds) != 1 { +// return nil, ErrorSetupNotFound +// } + +// if worldName == "" { +// return &worlds.GetById(0).NextSession, nil +// } else { +// for i := range worlds { +// if worlds[i].Id == worldName { +// return &worlds.GetById(0).NextSession, nil +// } +// } +// } + +// return nil, ErrorSetupNotFound +// } + +// func (world World) GetSessionTime() *time.Time { +// return &world.NextSession +// } diff --git a/internal/foundry/models/json/data.go b/internal/foundry/models/json/data.go new file mode 100644 index 0000000..47e433b --- /dev/null +++ b/internal/foundry/models/json/data.go @@ -0,0 +1,181 @@ +package json + +import ( + "encoding/json" + + "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models/db" +) + +type FoundryState struct { + IsAdmin bool `json:"isAdmin,omitempty"` + IsSetup bool `json:"isSetup,omitempty"` + Languages []Language `json:"languages,omitempty"` + Modules []DataTemplate `json:"modules"` + Release Release `json:"release"` + Systems []DataTemplate `json:"systems,omitempty"` + Worlds []DataTemplate `json:"worlds,omitempty"` + World *DataTemplate `json:"world,omitempty"` + Users Users `json:"users,omitempty"` + Options Options `json:"options,omitempty"` + + //coreUpdate struct{} + //featuredContent struct{} + //files struct{} + //news struct{} + + //packageWarnings struct{} think about it +} + +type Options struct { + Language string `json:"language,omitempty"` +} + +func (state FoundryState) GetRelease() Release { + return state.Release +} + +func (state FoundryState) GetFoundryStateDB(stateType db.StateType) *db.FoundryState { + dbFoundryState := db.FoundryState{ + IsAdmin: state.IsAdmin, + IsSetup: state.IsSetup, + Type: stateType, + Options: db.Options{Language: state.Options.Language}, + } + + dbFoundryState.Modules = state.GetModules() + dbFoundryState.Systems = state.GetSystems() + dbFoundryState.Worlds = state.GetWorlds() + dbFoundryState.Users = state.GetUsers() + + return &dbFoundryState +} + +func (state *FoundryState) GetModules() db.Modules { + modulesCopy := make([]db.Module, 0, 8) + for i := range state.Modules { + module := &(state.Modules[i]) + moduleCopy := db.Module{ + TextId: module.Id, + Title: module.Title, + Description: module.Description, + Compatibility: db.Compatibility{ + Minimum: module.Compatibility.Minimum, + Maximum: module.Compatibility.Maximum, + }, + Url: module.Url, + Version: module.CoreVersion, + + Availability: module.Availability, + } + for j := range module.Languages { + lang := db.Language{ + Lang: module.Languages[j].Lang, + Name: module.Languages[j].Name, + Path: module.Languages[j].Path, + } + moduleCopy.Languages = append(moduleCopy.Languages, lang) + } + modulesCopy = append(modulesCopy, moduleCopy) + } + return modulesCopy +} + +func (state *FoundryState) GetSystems() db.Systems { + systemsCopy := make([]db.System, 0, 8) + for i := range state.Systems { + system := &(state.Systems[i]) + systemCopy := db.System{ + TextId: system.Id, + Title: system.Title, + Description: system.Description, + Url: system.Url, + Compatibility: db.Compatibility{ + Minimum: system.Compatibility.Minimum, + Maximum: system.Compatibility.Maximum, + }, + Download: system.Download, + } + systemsCopy = append(systemsCopy, systemCopy) + } + return systemsCopy +} + +func (state *FoundryState) GetWorld() *db.World { + return &db.World{ + TextId: state.World.Id, + Title: state.World.Title, + Description: state.World.Description, + Compatibility: db.Compatibility{ + Minimum: state.World.Compatibility.Minimum, + Maximum: state.World.Compatibility.Maximum, + }, + System: state.World.System, + CoreVersion: state.World.CoreVersion, + SystemVersion: state.World.SystemVersion, + LastPlayed: state.World.LastPlayed, + PlayTime: state.World.PlayTime, + NextSession: state.World.NextSession, + } +} + +func (state *FoundryState) GetWorlds() db.Worlds { + worldsCopy := make([]db.World, 0, 8) + for i := range state.Worlds { + world := &(state.Worlds[i]) + worldCopy := db.World{ + TextId: world.Id, + Title: world.Title, + Description: world.Description, + Compatibility: db.Compatibility{ + Minimum: world.Compatibility.Minimum, + Maximum: world.Compatibility.Maximum, + }, + System: world.System, + CoreVersion: world.CoreVersion, + SystemVersion: world.SystemVersion, + LastPlayed: world.LastPlayed, + PlayTime: world.PlayTime, + NextSession: world.NextSession, + } + worldsCopy = append(worldsCopy, worldCopy) + } + return worldsCopy +} + +func (state *FoundryState) GetUsers() db.Users { + usersCopy := make(db.Users, 0, 8) + for i := range state.Users { + user := &(state.Users[i]) + userCopy := db.User{ + Name: user.Name, + Role: user.Role, + Character: user.Character, + Color: user.Color, + Pronouns: user.Pronouns, + Hotbar: user.Hotbar, + Stats: db.UserStats{ + CoreVersion: user.Stats.CoreVersion, + SystemId: user.Stats.SystemId, + SystemVersion: user.Stats.SystemVersion, + CreatedTime: user.Stats.CreatedTime, + ModifiedTime: user.Stats.ModifiedTime, + LastModifiedBy: user.Stats.LastModifiedBy, + }, + } + usersCopy = append(usersCopy, userCopy) + } + return usersCopy +} + +func ParseSetupModel(data []byte) (*FoundryState, error) { + var modelSetup []FoundryState + err := json.Unmarshal(data, &modelSetup) + if err != nil { + return nil, err + } + + if len(modelSetup) > 1 { + return nil, ErrorSetupMoreThanOne + } + return &modelSetup[0], nil +} diff --git a/internal/foundry/models/json/errors.go b/internal/foundry/models/json/errors.go new file mode 100644 index 0000000..de145a6 --- /dev/null +++ b/internal/foundry/models/json/errors.go @@ -0,0 +1,8 @@ +package json + +import "errors" + +var ( + ErrorSetupMoreThanOne = errors.New("Passed more than one setupData") + ErrorSetupNotFound = errors.New("Not found setup data from your request") +) diff --git a/internal/foundry/models/language.go b/internal/foundry/models/json/language.go similarity index 94% rename from internal/foundry/models/language.go rename to internal/foundry/models/json/language.go index 8c23875..fb5e0ab 100644 --- a/internal/foundry/models/language.go +++ b/internal/foundry/models/json/language.go @@ -1,4 +1,4 @@ -package models +package json type Language struct { Id string `json:"id"` diff --git a/internal/foundry/models/modules/dice-stats.go b/internal/foundry/models/json/modules/dice-stats.go similarity index 100% rename from internal/foundry/models/modules/dice-stats.go rename to internal/foundry/models/json/modules/dice-stats.go diff --git a/internal/foundry/models/modules/pf2e.go b/internal/foundry/models/json/modules/pf2e.go similarity index 100% rename from internal/foundry/models/modules/pf2e.go rename to internal/foundry/models/json/modules/pf2e.go diff --git a/internal/foundry/models/release.go b/internal/foundry/models/json/release.go similarity index 95% rename from internal/foundry/models/release.go rename to internal/foundry/models/json/release.go index 416a424..b67400c 100644 --- a/internal/foundry/models/release.go +++ b/internal/foundry/models/json/release.go @@ -1,4 +1,4 @@ -package models +package json type Release struct { Generation int `json:"generation"` diff --git a/internal/foundry/models/status.go b/internal/foundry/models/json/status.go similarity index 95% rename from internal/foundry/models/status.go rename to internal/foundry/models/json/status.go index c3d957f..160277f 100644 --- a/internal/foundry/models/status.go +++ b/internal/foundry/models/json/status.go @@ -1,4 +1,4 @@ -package models +package json type Status struct { Active bool `json:"active"` diff --git a/internal/foundry/models/template.go b/internal/foundry/models/json/template.go similarity index 99% rename from internal/foundry/models/template.go rename to internal/foundry/models/json/template.go index d33db31..8a8fa12 100644 --- a/internal/foundry/models/template.go +++ b/internal/foundry/models/json/template.go @@ -1,4 +1,4 @@ -package models +package json import "time" diff --git a/internal/foundry/models/users.go b/internal/foundry/models/json/users.go similarity index 97% rename from internal/foundry/models/users.go rename to internal/foundry/models/json/users.go index 54ee34d..62299c3 100644 --- a/internal/foundry/models/users.go +++ b/internal/foundry/models/json/users.go @@ -1,6 +1,6 @@ -package models +package json -import "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models/modules" +import "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models/json/modules" type User struct { Name string `json:"name,omitempty"` diff --git a/internal/foundry/models/module.go b/internal/foundry/models/module.go deleted file mode 100644 index 665adfc..0000000 --- a/internal/foundry/models/module.go +++ /dev/null @@ -1,49 +0,0 @@ -package models - -type Module struct { - Id string - Title string - Description string - Url string - Version string - Compatibility Compatibility - Languages []DataLanguage - Availability int -} - -type Modules []Module - -func (modules Modules) GetById(id int) *Module { - return &modules[id] -} - -func (state *FoundryState) GetModules() Modules { - modulesCopy := make([]Module, 0, 8) - for i := range state.Modules { - module := &(state.Modules[i]) - moduleCopy := Module{ - Id: module.Id, - Title: module.Title, - Description: module.Description, - Compatibility: Compatibility{ - Minimum: module.Compatibility.Minimum, - Maximum: module.Compatibility.Maximum, - }, - Url: module.Url, - Version: module.CoreVersion, - - Availability: module.Availability, - } - for j := range module.Languages { - lang := DataLanguage{ - Lang: module.Languages[j].Lang, - Name: module.Languages[j].Name, - Path: module.Languages[j].Path, - Flags: module.Languages[j].Flags, - } - moduleCopy.Languages = append(moduleCopy.Languages, lang) - } - modulesCopy = append(modulesCopy, moduleCopy) - } - return modulesCopy -} diff --git a/internal/foundry/models/system.go b/internal/foundry/models/system.go deleted file mode 100644 index e4c241c..0000000 --- a/internal/foundry/models/system.go +++ /dev/null @@ -1,36 +0,0 @@ -package models - -type System struct { - Id string - Title string - Description string - Url string - Compatibility Compatibility - Download string -} - -type Systems []System - -func (systems Systems) GetById(id int) *System { - return &systems[id] -} - -func (state *FoundryState) GetSystems() Systems { - systemsCopy := make([]System, 0, 8) - for i := range state.Systems { - system := &(state.Systems[i]) - systemCopy := System{ - Id: system.Id, - Title: system.Title, - Description: system.Description, - Url: system.Url, - Compatibility: Compatibility{ - Minimum: system.Compatibility.Minimum, - Maximum: system.Compatibility.Maximum, - }, - Download: system.Download, - } - systemsCopy = append(systemsCopy, systemCopy) - } - return systemsCopy -} diff --git a/internal/foundry/models/world.go b/internal/foundry/models/world.go deleted file mode 100644 index 649a594..0000000 --- a/internal/foundry/models/world.go +++ /dev/null @@ -1,88 +0,0 @@ -package models - -import ( - "time" -) - -type World struct { - Id string - Title string - Description string - Compatibility Compatibility - System string - CoreVersion string - SystemVersion string - LastPlayed string - PlayTime int64 - NextSession time.Time -} - -type Worlds []World - -func (worlds Worlds) GetById(id int) *World { - return &worlds[id] -} - -func (state *FoundryState) GetWorld() World { - return World{ - Id: state.World.Id, - Title: state.World.Title, - Description: state.World.Description, - Compatibility: Compatibility{ - Minimum: state.World.Compatibility.Minimum, - Maximum: state.World.Compatibility.Maximum, - }, - System: state.World.System, - CoreVersion: state.World.CoreVersion, - SystemVersion: state.World.SystemVersion, - LastPlayed: state.World.LastPlayed, - PlayTime: state.World.PlayTime, - NextSession: state.World.NextSession, - } -} - -func (state *FoundryState) GetWorlds() Worlds { - worldsCopy := make([]World, 0, 8) - for i := range state.Worlds { - world := &(state.Worlds[i]) - worldCopy := World{ - Id: world.Id, - Title: world.Title, - Description: world.Description, - Compatibility: Compatibility{ - Minimum: world.Compatibility.Minimum, - Maximum: world.Compatibility.Maximum, - }, - System: world.System, - CoreVersion: world.CoreVersion, - SystemVersion: world.SystemVersion, - LastPlayed: world.LastPlayed, - PlayTime: world.PlayTime, - NextSession: world.NextSession, - } - worldsCopy = append(worldsCopy, worldCopy) - } - return worldsCopy -} - -func (worlds Worlds) GetSessionTime(worldName string) (*time.Time, error) { - if worldName == "" && len(worlds) != 1 { - return nil, ErrorSetupNotFound - } - - if worldName == "" { - return &worlds.GetById(0).NextSession, nil - } else { - for i := range worlds { - if worlds[i].Id == worldName { - return &worlds.GetById(0).NextSession, nil - } - } - } - - return nil, ErrorSetupNotFound -} - -func (world World) GetSessionTime() *time.Time { - return &world.NextSession -} diff --git a/internal/foundry/requests/get_requests.go b/internal/foundry/requests/get_requests.go index 97360d7..853b9e4 100644 --- a/internal/foundry/requests/get_requests.go +++ b/internal/foundry/requests/get_requests.go @@ -5,7 +5,7 @@ import ( "fmt" "net/http" - "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models" + json_model "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/models/json" ) func (conf *Config) GetSessionId() error { @@ -42,7 +42,7 @@ func (conf *Config) GetSessionToken() (bool, error) { return conf.SetSessionTokenFromHeader(resp.Header) } -func (conf *Config) GetStatus() (*models.Status, error) { +func (conf *Config) GetStatus() (*json_model.Status, error) { getResp, err := http.Get(fmt.Sprintf("http://%s/api/status", conf.Host)) if err != nil { return nil, err @@ -55,7 +55,7 @@ func (conf *Config) GetStatus() (*models.Status, error) { return nil, err } - var status models.Status + var status json_model.Status err = json.Unmarshal(statusByte, &status) if err != nil { return nil, err