diff --git a/db/migrations/000001_create_setup.down.sql b/db/migrations/000001_create_setup.down.sql index 313e11a..8fff6c7 100644 --- a/db/migrations/000001_create_setup.down.sql +++ b/db/migrations/000001_create_setup.down.sql @@ -19,6 +19,7 @@ DROP TABLE IF EXISTS system; DROP TABLE IF EXISTS package_warnings_data_error; DROP TABLE IF EXISTS package_warnings_data_warning; DROP TABLE IF EXISTS package_warnings_data; +DROP TRIGGER IF EXISTS tr_delete_package_warnings_to_data_package_warnings_data; DROP TABLE IF EXISTS package_warnings; DROP TABLE IF EXISTS news; DROP TABLE IF EXISTS folder_packs; diff --git a/db/migrations/000001_create_setup.up.sql b/db/migrations/000001_create_setup.up.sql index 40a68f7..fe2be6d 100644 --- a/db/migrations/000001_create_setup.up.sql +++ b/db/migrations/000001_create_setup.up.sql @@ -397,15 +397,30 @@ CREATE TABLE IF NOT EXISTS package_warnings ( FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE ); +CREATE TABLE IF NOT EXISTS package_warnings_to_data ( + package_warnings_id INTEGER, + package_warnings_data_id TEXT, + + PRIMARY KEY (package_warnings_id, package_warnings_data_id), + FOREIGN KEY (package_warnings_id) REFERENCES package_warnings(id) ON DELETE CASCADE, + FOREIGN KEY (package_warnings_data_id) REFERENCES package_warnings_data(id) ON DELETE CASCADE +); + +CREATE TRIGGER tr_delete_package_warnings_to_data_package_warnings_data +AFTER DELETE ON package_warnings_to_data +FOR EACH ROW +BEGIN + DELETE FROM package_warnings_data + WHERE id = OLD.id + AND NOT EXISTS (SELECT 1 FROM package_warnings_to_data WHERE package_warnings_data_id = OLD.package_warnings_data_id); +END; + CREATE TABLE IF NOT EXISTS package_warnings_data ( id TEXT PRIMARY KEY, type VARCHAR(128) NOT NULL, manifest VARCHAR(128) NOT NULL, - reinstallable BOOLEAN NOT NULL, - - package_warnings_id INTEGER, - FOREIGN KEY (package_warnings_id) REFERENCES package_warnings(id) ON DELETE CASCADE + reinstallable BOOLEAN NOT NULL ); CREATE TABLE IF NOT EXISTS package_warnings_data_warning ( @@ -510,6 +525,9 @@ CREATE TABLE IF NOT EXISTS world ( owned BOOLEAN NOT NULL DEFAULT FALSE, has_storage BOOLEAN NOT NULL DEFAULT FALSE, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')), + setup_id INTEGER, FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE ); diff --git a/db/migrations/000002_create_game.down.sql b/db/migrations/000002_create_game.down.sql index dfe693f..8fd2b4c 100644 --- a/db/migrations/000002_create_game.down.sql +++ b/db/migrations/000002_create_game.down.sql @@ -1,3 +1,191 @@ -DROP TABLE IF EXISTS modules_languages; -DROP TABLE IF EXISTS modules_compatibility; -DROP TABLE IF EXISTS modules; +DROP TRIGGER IF EXISTS tr_delete_package_warnings_to_data_package_warnings_data; +DROP TRIGGER IF EXISTS tr_delete_game_to_systems_system; +DROP TRIGGER IF EXISTS tr_delete_game_to_module_module; +DROP TABLE IF EXISTS token_turn_maker; +DROP TABLE IF EXISTS token_occludable; +DROP TABLE IF EXISTS token_light_darkness; +DROP TABLE IF EXISTS token_light_animation; +DROP TABLE IF EXISTS token_light; +DROP TABLE IF EXISTS token_bar_2; +DROP TABLE IF EXISTS token_bar_1; +DROP TABLE IF EXISTS token_texture; +DROP TABLE IF EXISTS token_sight; +DROP TABLE IF EXISTS ring_subject; +DROP TABLE IF EXISTS ring_colors; +DROP TABLE IF EXISTS ring; +DROP TABLE IF EXISTS token; +DROP TABLE IF EXISTS actor; +DROP TABLE IF EXISTS sound; +DROP TABLE IF EXISTS playlist; +DROP TABLE IF EXISTS table_result_range; +DROP TABLE IF EXISTS table_result; +DROP TABLE IF EXISTS table_; +DROP TABLE IF EXISTS journal_page_video; +DROP TABLE IF EXISTS journal_page_title; +DROP TABLE IF EXISTS journal_page_text; +DROP TABLE IF EXISTS journal_page; +DROP TABLE IF EXISTS journal; +DROP TABLE IF EXISTS setting; +DROP TABLE IF EXISTS item; +DROP TABLE IF EXISTS world_folder; +DROP TABLE IF EXISTS macro; +DROP TABLE IF EXISTS hotbar; +DROP TABLE IF EXISTS user; +DROP TABLE IF EXISTS face; +DROP TABLE IF EXISTS back; +DROP TABLE IF EXISTS card; +DROP TABLE IF EXISTS ownership_string; +DROP TABLE IF EXISTS card_deck; +DROP TABLE IF EXISTS combatant; +DROP TABLE IF EXISTS combat_groups; +DROP TABLE IF EXISTS combat; +DROP TABLE IF EXISTS message_rolls; +DROP TABLE IF EXISTS message_whisper; +DROP TABLE IF EXISTS speaker; +DROP TABLE IF EXISTS stats; +DROP TABLE IF EXISTS message; + +CREATE TABLE IF NOT EXISTS pack_new ( + id INTEGER PRIMARY KEY, + + key_ VARCHAR(128) NOT NULL, + name VARCHAR(128) NOT NULL, + label VARCHAR(128) NOT NULL, + banner VARCHAR(128) NOT NULL, + path VARCHAR(128) NOT NULL, + type VARCHAR(128) NOT NULL, + system VARCHAR(128) NOT NULL, + package_type VARCHAR(128) NOT NULL, + package_name VARCHAR(128) NOT NULL, + + module_id TEXT, + FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE +); +ALTER TABLE pack_new ADD COLUMN system_id TEXT REFERENCES system(id) ON DELETE CASCADE; +ALTER TABLE pack_new ADD COLUMN world_id TEXT REFERENCES world(id) ON DELETE CASCADE; +INSERT INTO pack_new (id, key_, name, label, banner, path, type, system, package_type, package_name, module_id, system_id, world_id) +SELECT id, key_, name, label, banner, path, type, system, package_type, package_name, module_id, system_id, world_id FROM pack; +DROP TABLE IF EXISTS pack; +ALTER TABLE pack_new RENAME TO pack; + +CREATE TABLE IF NOT EXISTS package_warnings_new ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + key_ TEXT NOT NULL, + + setup_id INTEGER, + FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE +); +INSERT INTO package_warnings_new (id, key_, setup_id) +SELECT id, key_, setup_id FROM package_warnings; +DROP TABLE IF EXISTS package_warnings; +ALTER TABLE package_warnings_new RENAME TO package_warnings; + +DROP TABLE IF EXISTS active_users; +DROP TABLE IF EXISTS system_update; +DROP INDEX IF EXISTS idx_core_update_game_id; + +CREATE TABLE IF NOT EXISTS core_update_new ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + has_update BOOLEAN NOT NULL DEFAULT FALSE, + can_update BOOLEAN NOT NULL DEFAULT FALSE, + could_reach_website BOOLEAN NOT NULL DEFAULT FALSE, + slow_response BOOLEAN NOT NULL DEFAULT FALSE, + will_disable_modules BOOLEAN NOT NULL DEFAULT FALSE, + version VARCHAR(64) NOT NULL, + channel VARCHAR(64) NOT NULL, + + setup_id INTEGER UNIQUE, + FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE +); +INSERT INTO core_update_new (id, has_update, can_update, could_reach_website, slow_response, will_disable_modules, version, channel, setup_id) +SELECT id, has_update, can_update, could_reach_website, slow_response, will_disable_modules, version, channel, setup_id FROM core_update; +DROP TABLE IF EXISTS core_update; +ALTER TABLE core_update_new RENAME TO core_update; + +DROP TABLE IF EXISTS game_to_systems; +DROP INDEX IF EXISTS idx_world_game_id; + +CREATE TABLE IF NOT EXISTS world_new ( + id TEXT PRIMARY KEY, + + title VARCHAR(128) NOT NULL, + description VARCHAR(128) NOT NULL, + version VARCHAR(128) NOT NULL, + system VARCHAR(128) NOT NULL, + background VARCHAR(128) NOT NULL, + join_theme VARCHAR(128) NOT NULL, + core_version VARCHAR(128) NOT NULL, + system_version VARCHAR(128) NOT NULL, + last_played VARCHAR(128) NOT NULL, + playtime INTEGER NOT NULL, + availability INTEGER NOT NULL, + next_session DATETIME NOT NULL, + socket BOOLEAN NOT NULL DEFAULT FALSE, + protected BOOLEAN NOT NULL DEFAULT FALSE, + exclusive_ BOOLEAN NOT NULL DEFAULT FALSE, + persistent_storage BOOLEAN NOT NULL DEFAULT FALSE, + locked BOOLEAN NOT NULL DEFAULT FALSE, + owned BOOLEAN NOT NULL DEFAULT FALSE, + has_storage BOOLEAN NOT NULL DEFAULT FALSE, + + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')), + + setup_id INTEGER, + FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE +); +INSERT INTO world_new (id, title, description, version, system, background, join_theme, core_version, system_version, last_played, playtime, availability, next_session, socket, protected, exclusive_, persistent_storage, locked, owned, has_storage, created_at, updated_at, setup_id) +SELECT id, title, description, version, system, background, join_theme, core_version, system_version, last_played, playtime, availability, next_session, socket, protected, exclusive_, persistent_storage, locked, owned, has_storage, created_at, updated_at, setup_id FROM world; +DROP TABLE IF EXISTS world; +ALTER TABLE world_new RENAME TO world; + +DROP INDEX IF EXISTS idx_release_game_id; + +CREATE TABLE IF NOT EXISTS release_new ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + generation INTEGER NOT NULL, + build INTEGER NOT NULL, + node_version INTEGER NOT NULL, + max_generation INTEGER NOT NULL, + max_stable_generation INTEGER NOT NULL, + time DATETIME NOT NULL, + channel VARCHAR(128) NOT NULL, + suffix VARCHAR(128) NOT NULL, + + setup_id INTEGER UNIQUE, + FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE +); +INSERT INTO release_new (id, generation, build, node_version, max_generation, max_stable_generation, time, channel, suffix, setup_id) +SELECT id, generation, build, node_version, max_generation, max_stable_generation, time, channel, suffix, setup_id FROM release_; +DROP TABLE IF EXISTS release_; +ALTER TABLE release_new RENAME TO release_; + +DROP TABLE IF EXISTS game_options; +DROP INDEX IF EXISTS idx_files_game_id; + +DROP TABLE IF EXISTS files_new; +CREATE TABLE IF NOT EXISTS files_new ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + setup_id INTEGER UNIQUE, + FOREIGN KEY (setup_id) REFERENCES setup(id) ON DELETE CASCADE +); +INSERT INTO files_new (id, setup_id) +SELECT id, setup_id FROM files; +DROP TABLE IF EXISTS files; +ALTER TABLE files_new RENAME TO files; + +DROP TABLE IF EXISTS addresses; +DROP TABLE IF EXISTS game; + +CREATE TRIGGER tr_delete_package_warnings_to_data_package_warnings_data +AFTER DELETE ON package_warnings_to_data +FOR EACH ROW +BEGIN + DELETE FROM package_warnings_data + WHERE id = OLD.id + AND NOT EXISTS (SELECT 1 FROM package_warnings_to_data WHERE package_warnings_data_id = OLD.package_warnings_data_id); +END; \ No newline at end of file diff --git a/db/migrations/000002_create_game.up.sql b/db/migrations/000002_create_game.up.sql index 311d839..f92495d 100644 --- a/db/migrations/000002_create_game.up.sql +++ b/db/migrations/000002_create_game.up.sql @@ -1,5 +1,5 @@ CREATE TABLE IF NOT EXISTS game ( - id INTEGER PRIMARY KEY AUTOINCREMENT + id INTEGER PRIMARY KEY AUTOINCREMENT, demo_mode BOOLEAN NOT NULL DEFAULT FALSE, idle_logout BOOLEAN NOT NULL DEFAULT FALSE, @@ -20,6 +20,8 @@ CREATE TABLE IF NOT EXISTS addresses ( FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE ); +ALTER TABLE files ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_files_game_id ON files(game_id); CREATE TABLE IF NOT EXISTS game_options ( id INTEGER PRIMARY KEY, @@ -32,22 +34,280 @@ CREATE TABLE IF NOT EXISTS game_options ( FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE ); -CREATE TABLE IF NOT EXISTS macro ( - id TEXT PRIMARY KEY, +ALTER TABLE release_ ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_release_game_id ON release_(game_id); +ALTER TABLE world ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_world_game_id ON world(game_id); - command VARCHAR(128) NOT NULL, - name VARCHAR(128) NOT NULL, - type VARCHAR(128) NOT NULL, - img VARCHAR(128) NOT NULL, - author VARCHAR(128) NOT NULL, - scope VARCHAR(128) NOT NULL, - folder VARCHAR(128) NOT NULL, - sort INTEGER NOT NULL, +CREATE TABLE IF NOT EXISTS game_to_systems ( + game_id INTEGER, + system_id TEXT, + + PRIMARY KEY (game_id, system_id), + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE, + FOREIGN KEY (system_id) REFERENCES system(id) ON DELETE CASCADE +); + +CREATE TRIGGER tr_delete_game_to_systems_system +AFTER DELETE ON game_to_systems +FOR EACH ROW +BEGIN + DELETE FROM system + WHERE id = OLD.id + AND NOT EXISTS (SELECT 1 FROM game_to_systems WHERE system_id = OLD.system_id); +END; + +ALTER TABLE core_update ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_core_update_game_id ON core_update(game_id); + +CREATE TABLE IF NOT EXISTS system_update ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + has_update BOOLEAN NOT NULL DEFAULT FALSE, + version VARCHAR(128) NOT NULL, + + game_id INTEGER UNIQUE, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS active_users ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + value VARCHAR(128) NOT NULL, game_id INTEGER, FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE ); +CREATE TABLE IF NOT EXISTS game_to_module ( + game_id INTEGER, + module_id TEXT, + + PRIMARY KEY (game_id, module_id), + FOREIGN KEY (module_id) REFERENCES module(id) ON DELETE CASCADE, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +CREATE TRIGGER tr_delete_game_to_module_module +AFTER DELETE ON game_to_module +FOR EACH ROW +BEGIN + DELETE FROM module + WHERE id = OLD.id + AND NOT EXISTS (SELECT 1 FROM game_to_module WHERE module_id = OLD.module_id); +END; + +ALTER TABLE package_warnings ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE; +ALTER TABLE pack ADD COLUMN game_id INTEGER REFERENCES game(id) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS message ( + id TEXT PRIMARY KEY, + + blind BOOLEAN NOT NULL, + emote BOOLEAN NOT NULL, + style INTEGER NOT NULL, + timestamp DATETIME NOT NULL, + content VARCHAR(128) NOT NULL, + author VARCHAR(128) NOT NULL, + type VARCHAR(128) NOT NULL, + flavor VARCHAR(128) NOT NULL, + sound VARCHAR(128) NOT NULL, + + game_id INTEGER, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS stats ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + core_version VARCHAR(128) NOT NULL, + system_id VARCHAR(128) NOT NULL, + system_version VARCHAR(128) NOT NULL, + last_modified_by VARCHAR(128) NOT NULL, + modified_time DATETIME NOT NULL, + + message_id TEXT UNIQUE, + FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS speaker ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + scene VARCHAR(128) NOT NULL, + actor VARCHAR(128) NOT NULL, + token VARCHAR(128) NOT NULL, + alias VARCHAR(128) NOT NULL, + + message_id TEXT UNIQUE, + FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS message_whisper ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + value VARCHAR(128) NOT NULL, + + message_id TEXT, + FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS message_rolls ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + value VARCHAR(128) NOT NULL, + + message_id TEXT, + FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS combat ( + id TEXT PRIMARY KEY, + + type VARCHAR(128) NOT NULL, + scene VARCHAR(128) NOT NULL, + round INTEGER NOT NULL, + turn INTEGER NOT NULL, + sort INTEGER NOT NULL, + active INTEGER NOT NULL, + + game_id INTEGER, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN combat_id TEXT REFERENCES combat(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_combat_id ON stats(combat_id); + +CREATE TABLE IF NOT EXISTS combat_groups ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + value VARCHAR(128) NOT NULL, + + combat_id TEXT, + FOREIGN KEY (combat_id) REFERENCES combat(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS combatant ( + id TEXT PRIMARY KEY, + + token_id VARCHAR(128) NOT NULL, + scene_id VARCHAR(128) NOT NULL, + actor_id VARCHAR(128) NOT NULL, + type VARCHAR(128) NOT NULL, + img VARCHAR(128) NOT NULL, + group_ VARCHAR(128) NOT NULL, + initiative INTEGER NOT NULL, + hidden BOOLEAN NOT NULL, + defeated BOOLEAN NOT NULL, + + combat_id TEXT, + FOREIGN KEY (combat_id) REFERENCES combat(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN combatant_id TEXT REFERENCES combatant(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_combatant_id ON stats(combatant_id); + +CREATE TABLE IF NOT EXISTS card_deck ( + id TEXT PRIMARY KEY, + + name VARCHAR(128) NOT NULL, + type VARCHAR(128) NOT NULL, + description VARCHAR(128) NOT NULL, + img VARCHAR(128) NOT NULL, + folder VARCHAR(128) NOT NULL, + width INTEGER NOT NULL, + height INTEGER NOT NULL, + rotation INTEGER NOT NULL, + sort INTEGER NOT NULL, + display_count BOOLEAN NOT NULL, + + game_id INTEGER, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN card_deck_id TEXT REFERENCES card_deck(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_card_deck_id ON stats(card_deck_id); + +CREATE TABLE IF NOT EXISTS ownership_string ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + key_ VARCHAR(128) NOT NULL, + value INTEGER NOT NULL, + + card_deck_id TEXT UNIQUE, + FOREIGN KEY (card_deck_id) REFERENCES card_deck(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS card ( + id TEXT PRIMARY KEY, + + name VARCHAR(128) NOT NULL, + type VARCHAR(128) NOT NULL, + suit VARCHAR(128) NOT NULL, + description VARCHAR(128) NOT NULL, + origin VARCHAR(128) NOT NULL, + width INTEGER NOT NULL, + height INTEGER NOT NULL, + rotation INTEGER NOT NULL, + value INTEGER NOT NULL, + face INTEGER NOT NULL, + sort INTEGER NOT NULL, + drawn BOOLEAN NOT NULL, + + card_deck_id TEXT, + FOREIGN KEY (card_deck_id) REFERENCES card_deck(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS back ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + name VARCHAR(128) NOT NULL, + text VARCHAR(128) NOT NULL, + + card_id TEXT UNIQUE, + FOREIGN KEY (card_id) REFERENCES card(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN card_id TEXT REFERENCES card(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_card_id ON stats(card_id); + +CREATE TABLE IF NOT EXISTS face ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + name VARCHAR(128) NOT NULL, + img VARCHAR(128) NOT NULL, + text VARCHAR(128) NOT NULL, + + card_id TEXT, + FOREIGN KEY (card_id) REFERENCES card(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS user ( + id TEXT PRIMARY KEY, + + name VARCHAR(128) NOT NULL, + avatar VARCHAR(128) NOT NULL, + character VARCHAR(128) NOT NULL, + color VARCHAR(128) NOT NULL, + pronouns VARCHAR(128) NOT NULL, + role INTEGER NOT NULL, + + game_id INTEGER, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN user_id TEXT REFERENCES user(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_user_id ON stats(user_id); + +CREATE TABLE IF NOT EXISTS hotbar ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + key_ INTEGER NOT NULL, + value VARCHAR(128) NOT NULL, + + user_id TEXT, + FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE +); + CREATE TABLE IF NOT EXISTS macro ( id TEXT PRIMARY KEY, @@ -64,6 +324,163 @@ CREATE TABLE IF NOT EXISTS macro ( FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE ); +ALTER TABLE stats ADD COLUMN macro_id TEXT REFERENCES macro(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_macro_id ON stats(macro_id); +ALTER TABLE ownership_string ADD COLUMN macro_id TEXT REFERENCES macro(id) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS world_folder ( + id TEXT PRIMARY KEY, + + name VARCHAR(128) NOT NULL, + type VARCHAR(128) NOT NULL, + folder VARCHAR(128) NOT NULL, + sorting VARCHAR(128) NOT NULL, + description VARCHAR(128) NOT NULL, + color VARCHAR(128) NOT NULL, + sort INTEGER NOT NULL, + + game_id INTEGER, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN world_folder_id TEXT REFERENCES world_folder(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_world_folder_id ON stats(world_folder_id); + +CREATE TABLE IF NOT EXISTS item ( + id TEXT PRIMARY KEY, + + img VARCHAR(128) NOT NULL, + name VARCHAR(128) NOT NULL, + type VARCHAR(128) NOT NULL, + folder VARCHAR(128) NOT NULL, + sort INTEGER NOT NULL, + + game_id INTEGER, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN item_id TEXT REFERENCES item(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_item_id ON stats(item_id); +ALTER TABLE ownership_string ADD COLUMN item_id TEXT REFERENCES item(id) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS setting ( + id TEXT PRIMARY KEY, + + key_ VARCHAR(128) NOT NULL, + value VARCHAR(128) NOT NULL, + + game_id INTEGER, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN setting_id TEXT REFERENCES setting(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_setting_id ON stats(setting_id); + +CREATE TABLE IF NOT EXISTS journal ( + id TEXT PRIMARY KEY, + + name VARCHAR(128) NOT NULL, + sort INTEGER NOT NULL, + + game_id INTEGER, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS journal_page ( + id TEXT PRIMARY KEY, + + name VARCHAR(128) NOT NULL, + type VARCHAR(128) NOT NULL, + src VARCHAR(128) NOT NULL, + sort INTEGER NOT NULL, + + journal_id TEXT, + FOREIGN KEY (journal_id) REFERENCES journal(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS journal_page_text ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + content VARCHAR(128) NOT NULL, + markdown VARCHAR(128) NOT NULL, + format INTEGER NOT NULL, + + journal_page_id TEXT, + FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS journal_page_title ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + show BOOLEAN NOT NULL, + level INTEGER NOT NULL, + + journal_page_id TEXT, + FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS journal_page_video ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + controls BOOLEAN NOT NULL, + volume REAL NOT NULL, + + journal_page_id TEXT, + FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN journal_page_id TEXT REFERENCES journal_page(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_journal_page_id ON stats(journal_page_id); +ALTER TABLE ownership_string ADD COLUMN journal_page_id TEXT REFERENCES journal_page(id) ON DELETE CASCADE; + +ALTER TABLE ownership_string ADD COLUMN journal_id TEXT REFERENCES journal(id) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS table_ ( + id TEXT PRIMARY KEY, + + name VARCHAR(128) NOT NULL, + description VARCHAR(128) NOT NULL, + formula VARCHAR(128) NOT NULL, + img VARCHAR(128) NOT NULL, + folder VARCHAR(128) NOT NULL, + sort INTEGER NOT NULL, + replacement BOOLEAN NOT NULL, + display_roll BOOLEAN NOT NULL, + + game_id INTEGER, + FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN table_id TEXT REFERENCES table_(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_table_id ON stats(table_id); +ALTER TABLE ownership_string ADD COLUMN table_id TEXT REFERENCES table_(id) ON DELETE CASCADE; + +CREATE TABLE IF NOT EXISTS table_result ( + id TEXT PRIMARY KEY, + + type VARCHAR(128) NOT NULL, + img VARCHAR(128) NOT NULL, + description VARCHAR(128) NOT NULL, + name VARCHAR(128) NOT NULL, + weight INTEGER NOT NULL, + drawn BOOLEAN NOT NULL, + + table_id TEXT, + FOREIGN KEY (table_id) REFERENCES table_(id) ON DELETE CASCADE +); + +ALTER TABLE stats ADD COLUMN table_result_id TEXT REFERENCES table_result(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_table_result_id ON stats(table_result_id); + +CREATE TABLE IF NOT EXISTS table_result_range ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + value INTEGER NOT NULL, + + table_result_id TEXT, + FOREIGN KEY (table_result_id) REFERENCES table_result(id) ON DELETE CASCADE +); + CREATE TABLE IF NOT EXISTS playlist ( id TEXT PRIMARY KEY, @@ -82,6 +499,10 @@ CREATE TABLE IF NOT EXISTS playlist ( FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE ); +ALTER TABLE stats ADD COLUMN playlist_id TEXT REFERENCES playlist(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_playlist_id ON stats(playlist_id); +ALTER TABLE ownership_string ADD COLUMN playlist_id TEXT REFERENCES playlist(id) ON DELETE CASCADE; + CREATE TABLE IF NOT EXISTS sound ( id TEXT PRIMARY KEY, @@ -113,8 +534,13 @@ CREATE TABLE IF NOT EXISTS actor ( FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE ); +ALTER TABLE stats ADD COLUMN actor_id TEXT REFERENCES actor(id) ON DELETE CASCADE; +CREATE UNIQUE INDEX idx_stats_actor_id ON stats(actor_id); +ALTER TABLE ownership_string ADD COLUMN actor_id TEXT REFERENCES actor(id) ON DELETE CASCADE; +ALTER TABLE item ADD COLUMN actor_id TEXT REFERENCES actor(id) ON DELETE CASCADE; + CREATE TABLE IF NOT EXISTS token ( - id INTEGER PRIMARY KEY, + id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(128) NOT NULL, actor_link BOOLEAN NOT NULL, @@ -179,6 +605,43 @@ CREATE TABLE IF NOT EXISTS token_sight ( FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE ); +CREATE TABLE IF NOT EXISTS token_texture ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + src VARCHAR(128) NOT NULL, + fit VARCHAR(128) NOT NULL, + tint VARCHAR(128) NOT NULL, + scale_x REAL NOT NULL, + scale_y REAL NOT NULL, + offset_x REAL NOT NULL, + offset_y REAL NOT NULL, + rotation REAL NOT NULL, + anchor_x REAL NOT NULL, + anchor_y REAL NOT NULL, + alpha_threshold REAL NOT NULL, + + token_id INTEGER UNIQUE, + FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS token_bar_1 ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + attribute VARCHAR(128) NOT NULL, + + token_id INTEGER UNIQUE, + FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS token_bar_2 ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + attribute VARCHAR(128) NOT NULL, + + token_id INTEGER UNIQUE, + FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE +); + CREATE TABLE IF NOT EXISTS token_light ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -221,43 +684,6 @@ CREATE TABLE IF NOT EXISTS token_light_darkness ( FOREIGN KEY (token_light_id) REFERENCES token_light(id) ON DELETE CASCADE ); -CREATE TABLE IF NOT EXISTS token_texture ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - src VARCHAR(128) NOT NULL, - fit VARCHAR(128) NOT NULL, - tint VARCHAR(128) NOT NULL, - scale_x REAL NOT NULL, - scale_y REAL NOT NULL, - offset_x REAL NOT NULL, - offset_y REAL NOT NULL, - rotation REAL NOT NULL, - anchor_x REAL NOT NULL, - anchor_y REAL NOT NULL, - alpha_threshold REAL NOT NULL, - - token_id INTEGER UNIQUE, - FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS token_bar_1 ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - attribute VARCHAR(128) NOT NULL, - - token_id INTEGER UNIQUE, - FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS token_bar_2 ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - attribute VARCHAR(128) NOT NULL, - - token_id INTEGER UNIQUE, - FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE -); - CREATE TABLE IF NOT EXISTS token_occludable ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -278,384 +704,3 @@ CREATE TABLE IF NOT EXISTS token_turn_maker ( token_id INTEGER UNIQUE, FOREIGN KEY (token_id) REFERENCES token(id) ON DELETE CASCADE ); - -CREATE TABLE IF NOT EXISTS table_ ( - id TEXT PRIMARY KEY, - - name VARCHAR(128) NOT NULL, - description VARCHAR(128) NOT NULL, - formula VARCHAR(128) NOT NULL, - img VARCHAR(128) NOT NULL, - folder VARCHAR(128) NOT NULL, - sort INTEGER NOT NULL, - replacement BOOLEAN NOT NULL, - display_roll BOOLEAN NOT NULL, - - game_id INTEGER, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS table_result ( - id TEXT PRIMARY KEY, - - type VARCHAR(128) NOT NULL, - img VARCHAR(128) NOT NULL, - description VARCHAR(128) NOT NULL, - name VARCHAR(128) NOT NULL, - weight INTEGER NOT NULL, - drawn BOOLEAN NOT NULL, - - table_id INTEGER, - FOREIGN KEY (table_id) REFERENCES table_(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS table_result_range ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - range_ INTEGER NOT NULL, - - table_result_id INTEGER, - FOREIGN KEY (table_result_id) REFERENCES table_result(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS user ( - id TEXT PRIMARY KEY, - - name VARCHAR(128) NOT NULL, - avatar VARCHAR(128) NOT NULL, - character VARCHAR(128) NOT NULL, - color VARCHAR(128) NOT NULL, - pronouns VARCHAR(128) NOT NULL, - role INTEGER NOT NULL, - - game_id INTEGER, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS setting ( - id TEXT PRIMARY KEY, - - key_ VARCHAR(128) NOT NULL, - value VARCHAR(128) NOT NULL, - - game_id INTEGER, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS hotbar ( - id INTEGER PRIMARY KEY, - - key_ INTEGER NOT NULL, - value VARCHAR(128) NOT NULL, - - user_id TEXT, - FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS active_users ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - users VARCHAR(128) NOT NULL, - - game_id INTEGER, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS item ( - id TEXT PRIMARY KEY, - - img VARCHAR(128) NOT NULL, - name VARCHAR(128) NOT NULL, - type VARCHAR(128) NOT NULL, - folder VARCHAR(128) NOT NULL, - sort INTEGER NOT NULL, - - game_id INTEGER, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE, - actor_id TEXT, - FOREIGN KEY (actor_id) REFERENCES actor(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS journal ( - id TEXT PRIMARY KEY, - - name VARCHAR(128) NOT NULL, - sort INTEGER NOT NULL, - - game_id INTEGER UNIQUE, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE -); - - -CREATE TABLE IF NOT EXISTS world_folder ( - id TEXT PRIMARY KEY, - - name VARCHAR(128) NOT NULL, - type VARCHAR(128) NOT NULL, - folder VARCHAR(128) NOT NULL, - sorting VARCHAR(128) NOT NULL, - description VARCHAR(128) NOT NULL, - color VARCHAR(128) NOT NULL, - sort INTEGER NOT NULL, - - game_id INTEGER, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS message ( - id TEXT PRIMARY KEY, - - blind BOOLEAN NOT NULL, - emote BOOLEAN NOT NULL, - style INTEGER NOT NULL, - timestamp DATETIME NOT NULL, - content VARCHAR(128) NOT NULL, - author VARCHAR(128) NOT NULL, - type VARCHAR(128) NOT NULL, - flavor VARCHAR(128) NOT NULL, - sound VARCHAR(128) NOT NULL, - - game_id INTEGER, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS combat ( - id TEXT PRIMARY KEY, - - type VARCHAR(128) NOT NULL, - scene VARCHAR(128) NOT NULL, - round INTEGER NOT NULL, - turn INTEGER NOT NULL, - sort INTEGER NOT NULL, - active INTEGER NOT NULL, - - game_id INTEGER, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS card_deck ( - id TEXT PRIMARY KEY, - - name VARCHAR(128) NOT NULL, - type VARCHAR(128) NOT NULL, - description VARCHAR(128) NOT NULL, - img VARCHAR(128) NOT NULL, - folder VARCHAR(128) NOT NULL, - width INTEGER NOT NULL, - height INTEGER NOT NULL, - rotation INTEGER NOT NULL, - sort INTEGER NOT NULL, - display_count BOOLEAN NOT NULL, - - game_id INTEGER, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS combatant ( - id TEXT PRIMARY KEY, - - token_id VARCHAR(128) NOT NULL, - scene_id VARCHAR(128) NOT NULL, - actor_id VARCHAR(128) NOT NULL, - type VARCHAR(128) NOT NULL, - img VARCHAR(128) NOT NULL, - group_ VARCHAR(128) NOT NULL, - initiative INTEGER NOT NULL, - hidden BOOLEAN NOT NULL, - defeated BOOLEAN NOT NULL, - - combat_id TEXT, - FOREIGN KEY (combat_id) REFERENCES combat(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS stats ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - core_version VARCHAR(128) NOT NULL, - system_id VARCHAR(128) NOT NULL, - system_version VARCHAR(128) NOT NULL, - last_modified_by VARCHAR(128) NOT NULL, - modified_time DATETIME NOT NULL, - - message_id TEXT UNIQUE, - FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE, - combat_id TEXT UNIQUE, - FOREIGN KEY (combat_id) REFERENCES combat(id) ON DELETE CASCADE, - combatant_id TEXT UNIQUE, - FOREIGN KEY (combatant_id) REFERENCES combatant(id) ON DELETE CASCADE, - card_deck_id TEXT UNIQUE, - FOREIGN KEY (card_deck_id) REFERENCES card_deck(id) ON DELETE CASCADE, - card_id TEXT UNIQUE, - FOREIGN KEY (card_id) REFERENCES card(id) ON DELETE CASCADE, - user_id TEXT UNIQUE, - FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE, - macro_id TEXT UNIQUE, - FOREIGN KEY (macro_id) REFERENCES macro(id) ON DELETE CASCADE, - world_folder_id TEXT UNIQUE, - FOREIGN KEY (world_folder_id) REFERENCES world_folder(id) ON DELETE CASCADE, - item_id TEXT UNIQUE, - FOREIGN KEY (item_id) REFERENCES item(id) ON DELETE CASCADE, - setting_id TEXT UNIQUE, - FOREIGN KEY (setting_id) REFERENCES setting(id) ON DELETE CASCADE, - journal_page_id TEXT UNIQUE, - FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE, - table_id TEXT UNIQUE, - FOREIGN KEY (table_id) REFERENCES table_(id) ON DELETE CASCADE, - table_result_id TEXT UNIQUE, - FOREIGN KEY (table_result_id) REFERENCES table_result(id) ON DELETE CASCADE, - playlist_id TEXT UNIQUE, - FOREIGN KEY (playlist_id) REFERENCES playlist(id) ON DELETE CASCADE, - actor_id TEXT UNIQUE, - FOREIGN KEY (actor_id) REFERENCES actor(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS speaker ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - scene VARCHAR(128) NOT NULL, - actor VARCHAR(128) NOT NULL, - token VARCHAR(128) NOT NULL, - alias VARCHAR(128) NOT NULL, - - message_id TEXT UNIQUE, - FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS combat_groups ( - id TEXT PRIMARY KEY, - - groups_ VARCHAR(128) NOT NULL, - - combat_id TEXT, - FOREIGN KEY (combat_id) REFERENCES combat(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS card ( - id TEXT PRIMARY KEY, - - name VARCHAR(128) NOT NULL, - type VARCHAR(128) NOT NULL, - suit VARCHAR(128) NOT NULL, - description VARCHAR(128) NOT NULL, - origin VARCHAR(128) NOT NULL, - width INTEGER NOT NULL, - height INTEGER NOT NULL, - rotation INTEGER NOT NULL, - value INTEGER NOT NULL, - face INTEGER NOT NULL, - sort INTEGER NOT NULL, - drawn BOOLEAN NOT NULL, - - card_deck_id TEXT, - FOREIGN KEY (card_deck_id) REFERENCES card_deck(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS back ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - name VARCHAR(128) NOT NULL, - text VARCHAR(128) NOT NULL, - - card_id TEXT UNIQUE, - FOREIGN KEY (card_id) REFERENCES card(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS face ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - name VARCHAR(128) NOT NULL, - img VARCHAR(128) NOT NULL, - text VARCHAR(128) NOT NULL, - - card_id TEXT, - FOREIGN KEY (card_id) REFERENCES card(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS message_whisper ( - id TEXT PRIMARY KEY, - - value VARCHAR(128) NOT NULL, - - message_id TEXT, - FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS message_rolls ( - id TEXT PRIMARY KEY, - - value VARCHAR(128) NOT NULL, - - message_id TEXT, - FOREIGN KEY (message_id) REFERENCES message(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS journal_page ( - id TEXT PRIMARY KEY, - - name VARCHAR(128) NOT NULL, - type VARCHAR(128) NOT NULL, - src VARCHAR(128) NOT NULL, - sort INTEGER NOT NULL, - - journal_id TEXT, - FOREIGN KEY (journal_id) REFERENCES journal(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS journal_page_text ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - content VARCHAR(128) NOT NULL, - markdown VARCHAR(128) NOT NULL, - format INTEGER NOT NULL, - - journal_page_id TEXT, - FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS journal_page_title ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - show BOOLEAN NOT NULL, - level INTEGER NOT NULL, - - journal_page_id TEXT, - FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS journal_page_video ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - controls BOOLEAN NOT NULL, - volume REAL NOT NULL, - - journal_page_id TEXT, - FOREIGN KEY (journal_page_id) REFERENCES journal_page(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS ownership_string ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - key_ VARCHAR(128) NOT NULL, - value INTEGER NOT NULL, - - macro_id TEXT, - FOREIGN KEY (macro_id) REFERENCES macro(id) ON DELETE CASCADE, - item_id TEXT, - FOREIGN KEY (item_id) REFERENCES item(id) ON DELETE CASCADE, - journal_id TEXT, - FOREIGN KEY (journal_id) REFERENCES journal(id) ON DELETE CASCADE, - playlist_id TEXT, - FOREIGN KEY (playlist_id) REFERENCES playlist(id) ON DELETE CASCADE, - actor_id TEXT, - FOREIGN KEY (actor_id) REFERENCES actor(id) ON DELETE CASCADE -); - -CREATE TABLE IF NOT EXISTS system_update ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - - has_update BOOLEAN NOT NULL DEFAULT FALSE, - version VARCHAR(128) NOT NULL, - - game_id INTEGER UNIQUE, - FOREIGN KEY (game_id) REFERENCES game(id) ON DELETE CASCADE -); diff --git a/internal/foundry/actions/errors.go b/internal/foundry/actions/errors.go index baaf677..ccdabed 100644 --- a/internal/foundry/actions/errors.go +++ b/internal/foundry/actions/errors.go @@ -3,7 +3,8 @@ package actions import "errors" var ( - ErrActionNotFound = errors.New("Action doesn't found") - ErrObjTypeNotMatch = errors.New("Provided value type didn't match obj field type") - ErrObjNotPointer = errors.New("Passed obj is not pointer") + ErrActionNotFound = errors.New("Action doesn't found") + ErrObjTypeNotMatch = errors.New("Provided value type didn't match obj field type") + ErrObjNotPointer = errors.New("Passed obj is not pointer") + ErrUserChannelIsClosed = errors.New("User channel is closed") ) diff --git a/internal/foundry/actions/session.go b/internal/foundry/actions/session.go index b2efd9b..3148bdd 100644 --- a/internal/foundry/actions/session.go +++ b/internal/foundry/actions/session.go @@ -1,6 +1,8 @@ package actions import ( + "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db" + "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/json" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/transport" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/types" ) @@ -22,8 +24,18 @@ func (msg WsSessionMsg) Action(tr *transport.FoundryTransport, status *types.Fou close(tr.ReadChan.Reconnect()) return nil } - // tr.Logger.Warn("World is started. Please, return to setup page to fully initialize database") - // go msg.OnActiveWorld(tr) + + // select { + // case <-tr.LoggedInChan: + // return ErrUserChannelIsClosed + // default: + // tr.LoggedInChan <- true + // } + + // time.Sleep(3 * time.Second) + // types.CloseChannel(tr.LoggedInChan) + + go msg.OnActiveWorld(tr) return nil } @@ -37,13 +49,27 @@ func (msg WsSessionMsg) Action(tr *transport.FoundryTransport, status *types.Fou } func (msg WsSessionMsg) OnActiveWorld(tr *transport.FoundryTransport) error { - wsMsg := types.NewWsMessage("world", tr.CurrWsId) - tr.CurrWsId++ - - answer, err := tr.HandleWebsocketRequest(wsMsg) + msgJson, err := tr.GetJsonData("world") if err != nil { return err } - tr.Logger.Info("World data", "answer", string(answer)) + + tr.Logger.Info("Game data received") + + gameJson, err := json.ParseGame(msgJson) + if err != nil { + return err + } + + var foundryStateDb db.Game + gameJson.ToDB(&foundryStateDb) + + err = foundryStateDb.Insert(tr.DB) + if err != nil { + tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} + } + + tr.Logger.Info("Game data succesfully inserted to DB") + return nil } diff --git a/internal/foundry/temp_models/db/actor.go b/internal/foundry/temp_models/db/actor.go index b620692..37e6d06 100644 --- a/internal/foundry/temp_models/db/actor.go +++ b/internal/foundry/temp_models/db/actor.go @@ -1,5 +1,15 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Actor struct { ID string @@ -8,8 +18,60 @@ type Actor struct { Type string Folder string Sort int - PrototypeToken Token + PrototypeToken *Token Stats Stats Items []*Item Ownership []OwnershipString } + +func (a *Actor) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO actor (%s, id, img, name, type, folder, sort) + VALUES ($1, $2, $3, $4, $5, $6, $7)`, data.fieldName) +} + +func (a *Actor) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[string]{id: a.ID, fieldName: "actor_id"} + InsertWithCtxParallel(group, ctx, tx, a.PrototypeToken, relId) + InsertWithCtxParallel(group, ctx, tx, a.Stats, relId) + InsertSliceParallel(group, tx, a.Ownership, relId) + InsertSliceParallel(group, tx, a.Items, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (a *Actor) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, a.ID, a.Img, a.Name, a.Type, a.Folder, a.Sort} + + _, err := tx.Exec(data.query, args...) + if err != nil { + return err + } + + return a.InsertObjects(tx) +} + +func (a *Actor) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, a.ID, a.Img, a.Name, a.Type, a.Folder, a.Sort} + + _, err := tx.ExecContext(ctx, data.query, args...) + if err != nil { + return err + } + + return a.InsertObjects(tx) +} diff --git a/internal/foundry/temp_models/db/card.go b/internal/foundry/temp_models/db/card.go index e80b46e..000fafb 100644 --- a/internal/foundry/temp_models/db/card.go +++ b/internal/foundry/temp_models/db/card.go @@ -23,7 +23,7 @@ type CardDeck struct { Sort int DisplayCount bool Stats Stats - Ownership Ownership + Ownership []OwnershipString Cards []*Card } @@ -38,7 +38,7 @@ func (c *CardDeck) InsertObjects(tx *sqlx.Tx) error { relId := InsertId[string]{id: c.ID, fieldName: "card_deck_id"} InsertWithCtxParallel(group, ctx, tx, c.Stats, relId) - InsertWithCtxParallel(group, ctx, tx, c.Ownership, relId) + InsertSliceParallel(group, tx, c.Ownership, relId) InsertSliceParallel(group, tx, c.Cards, relId) err := group.Wait() diff --git a/internal/foundry/temp_models/db/game.go b/internal/foundry/temp_models/db/game.go index 573239a..f69d556 100644 --- a/internal/foundry/temp_models/db/game.go +++ b/internal/foundry/temp_models/db/game.go @@ -41,9 +41,9 @@ type Game struct { Items []*Item Settings []*Setting Journals []*Journal - Tables []*Table // + Tables []*Table Playlists []*Playlist - Actors []Actor // + Actors []*Actor // Scenes []Scene } @@ -62,22 +62,25 @@ func (g *Game) InsertObjects(tx *sqlx.Tx) error { InsertWithCtxParallel(group, ctx, tx, g.World, relDataString) InsertWithCtxParallel(group, ctx, tx, g.System, relDataString) - InsertSimpleSliceParallel(group, tx, g.ActiveUsers, &InsertId[uint]{id: g.ID, fieldName: "game_id", tableName: "active_users"}) + InsertSimpleSliceParallel(group, tx, g.ActiveUsers, + &InsertId[uint]{id: g.ID, fieldName: "game_id", tableName: "active_users"}) InsertSliceParallel(group, tx, g.Modules, relData) InsertSliceParallel(group, tx, g.PackageWarnings, relData) InsertSliceParallel(group, tx, g.Packs, relDataString) - InsertSliceParallel(group, tx, g.Messages, relData) - InsertSliceParallel(group, tx, g.Combats, relData) - InsertSliceParallel(group, tx, g.CardDeck, relData) - InsertSliceParallel(group, tx, g.Users, relData) - InsertSliceParallel(group, tx, g.Macros, relData) - InsertSliceParallel(group, tx, g.Folders, relData) - InsertSliceParallel(group, tx, g.Items, relData) - InsertSliceParallel(group, tx, g.Settings, relData) - InsertSliceParallel(group, tx, g.Journals, relData) - InsertSliceParallel(group, tx, g.Tables, relData) - InsertSliceParallel(group, tx, g.Playlists, relData) + // InsertSliceParallel(group, tx, g.Messages, relData) + // InsertSliceParallel(group, tx, g.Combats, relData) + // InsertSliceParallel(group, tx, g.CardDeck, relData) + // InsertSliceParallel(group, tx, g.Users, relData) + // InsertSliceParallel(group, tx, g.Macros, relData) + // InsertSliceParallel(group, tx, g.Folders, relData) + // InsertSliceParallel(group, tx, g.Items, + // InsertId[string]{id: strconv.FormatUint(uint64(g.ID), 10), fieldName: "game_id"}) + // InsertSliceParallel(group, tx, g.Settings, relData) + // InsertSliceParallel(group, tx, g.Journals, relData) + // InsertSliceParallel(group, tx, g.Tables, relData) + // InsertSliceParallel(group, tx, g.Playlists, relData) + // InsertSliceParallel(group, tx, g.Actors, relData) err := group.Wait() if err != nil && !errors.Is(err, sql.ErrNoRows) { diff --git a/internal/foundry/temp_models/db/index.go b/internal/foundry/temp_models/db/index.go index 1e71a58..cd7d9ad 100644 --- a/internal/foundry/temp_models/db/index.go +++ b/internal/foundry/temp_models/db/index.go @@ -15,14 +15,14 @@ type Index struct { Type string } -func (i *Index) Query(data *InsertId[uint]) { +func (i *Index) Query(data *InsertId[string]) { data.query = ` INSERT INTO index_ (pack_id, id, folder, img, name, type) VALUES ($1, $2, $3, $4, $5, $6) RETURNING id` } -func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { +func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[string]) error { if data.query == "" { return ErrNoQuery } @@ -37,7 +37,7 @@ func (i *Index) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { return nil } -func (i *Index) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { +func (i *Index) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { if data.query == "" { return ErrNoQuery } diff --git a/internal/foundry/temp_models/db/item.go b/internal/foundry/temp_models/db/item.go index 76dd316..5e8b46f 100644 --- a/internal/foundry/temp_models/db/item.go +++ b/internal/foundry/temp_models/db/item.go @@ -22,7 +22,7 @@ type Item struct { Ownership []OwnershipString } -func (i *Item) Query(data *InsertId[uint]) { +func (i *Item) Query(data *InsertId[string]) { data.query = fmt.Sprintf(` INSERT INTO world_folder (%s, id, img, name, type, folder, sort) VALUES ($1, $2, $3, $4, $5, $6, $7) @@ -43,7 +43,7 @@ func (i *Item) InsertObjects(tx *sqlx.Tx) error { return nil } -func (i *Item) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { +func (i *Item) Insert(tx *sqlx.Tx, data *InsertId[string]) error { if data.query == "" { return ErrNoQuery } @@ -58,7 +58,7 @@ func (i *Item) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { return i.InsertObjects(tx) } -func (i *Item) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { +func (i *Item) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { if data.query == "" { return ErrNoQuery } diff --git a/internal/foundry/temp_models/db/light.go b/internal/foundry/temp_models/db/light.go index 514678f..bc95156 100644 --- a/internal/foundry/temp_models/db/light.go +++ b/internal/foundry/temp_models/db/light.go @@ -1,5 +1,15 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Light struct { ID uint @@ -20,6 +30,60 @@ type Light struct { LightDarkness LightDarkness } +func (l *Light) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO token_light (%s, color, priority, angle, negative, alpha, bright, coloration, dim, + attenuation, luminosity, saturation, contrast, shadows) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) + RETURNING id`, data.fieldName) +} + +func (l *Light) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[uint]{id: l.ID, fieldName: "token_light_id"} + InsertWithCtxParallel(group, ctx, tx, l.LightAnimation, relId) + InsertWithCtxParallel(group, ctx, tx, l.LightDarkness, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (l *Light) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, l.Color, l.Priority, l.Angle, l.Negative, l.Alpha, l.Bright, l.Coloration, l.Dim, + l.Attenuation, l.Luminosity, l.Saturation, l.Contrast, l.Shadows} + + err := tx.QueryRowx(data.query, args...).Scan(&l.ID) + if err != nil { + return err + } + + return nil +} + +func (l *Light) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, l.Color, l.Priority, l.Angle, l.Negative, l.Alpha, l.Bright, l.Coloration, l.Dim, + l.Attenuation, l.Luminosity, l.Saturation, l.Contrast, l.Shadows} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&l.ID) + if err != nil { + return err + } + + return nil +} + type LightAnimation struct { ID uint @@ -27,9 +91,84 @@ type LightAnimation struct { Intensity int Reverse bool } + +func (l LightAnimation) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO token_light_animation (%s, speed, intensity, reverse) + VALUES ($1, $2, $3, $4) + RETURNING id`, data.fieldName) +} + +func (l LightAnimation) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, l.Speed, l.Intensity, l.Reverse} + + err := tx.QueryRowx(data.query, args...).Scan(&l.ID) + if err != nil { + return err + } + + return nil +} + +func (l LightAnimation) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, l.Speed, l.Intensity, l.Reverse} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&l.ID) + if err != nil { + return err + } + + return nil +} + type LightDarkness struct { ID uint Min float64 Max float64 } + +func (l LightDarkness) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO token_light_darkness (%s, min, max) + VALUES ($1, $2, $3, $4) + RETURNING id`, data.fieldName) +} + +func (l LightDarkness) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, l.Min, l.Max} + + err := tx.QueryRowx(data.query, args...).Scan(&l.ID) + if err != nil { + return err + } + + return nil +} + +func (l LightDarkness) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, l.Min, l.Max} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&l.ID) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/module.go b/internal/foundry/temp_models/db/module.go index d5fa000..5d02142 100644 --- a/internal/foundry/temp_models/db/module.go +++ b/internal/foundry/temp_models/db/module.go @@ -4,7 +4,7 @@ import ( "context" "database/sql" "errors" - "fmt" + "strings" "github.com/jmoiron/sqlx" "golang.org/x/sync/errgroup" @@ -49,12 +49,19 @@ type Module struct { } func (m *Module) Query(data *InsertId[uint]) { - data.query = fmt.Sprintf(` - INSERT INTO module (%s, id, title, description, url, license, readme, bugs, + data.query = ` + INSERT INTO module (setup_id, id, title, description, url, license, readme, bugs, changelog, version, manifest, download, socket, protected, exclusive_, persistent_storage, core_translation, library, locked, owned, has_storage, active, availability) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, - $18, $19, $20, $21, $22, $23)`, data.fieldName) + $18, $19, $20, $21, $22, $23) + ON CONFLICT(id) DO NOTHING` +} + +func (m *Module) ConnectGameQuery(data *InsertId[uint]) { + data.query = ` + INSERT INTO game_to_module (game_id, module_id) + VALUES ($1, $2)` } func (m *Module) InsertObjects(tx *sqlx.Tx) error { @@ -65,19 +72,19 @@ func (m *Module) InsertObjects(tx *sqlx.Tx) error { InsertWithCtxParallel(group, ctx, tx, m.Relationships, relId) InsertWithCtxParallel(group, ctx, tx, m.Compatibility, relId) - // scriptRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "scripts"} - // InsertSimpleSliceParallel(group, tx, m.Scripts, scriptRelId) - // esModulesRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "es_modules"} - // InsertSimpleSliceParallel(group, tx, m.Esmodules, esModulesRelId) - // tagsRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "tags"} - // InsertSimpleSliceParallel(group, tx, m.Tags, tagsRelId) + scriptRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "scripts"} + InsertSimpleSliceParallel(group, tx, m.Scripts, scriptRelId) + esModulesRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "es_modules"} + InsertSimpleSliceParallel(group, tx, m.Esmodules, esModulesRelId) + tagsRelId := &InsertId[string]{id: m.ID, fieldName: "module_id", tableName: "tags"} + InsertSimpleSliceParallel(group, tx, m.Tags, tagsRelId) - // InsertSliceParallel(group, tx, m.Authors, relId) - // InsertSliceParallel(group, tx, m.Media, relId) - // InsertSliceParallel(group, tx, m.Styles, relId) - // InsertSliceParallel(group, tx, m.Languages, relId) - // InsertSliceParallel(group, tx, m.Packs, relId) - // InsertSliceParallel(group, tx, m.PackFolders, relId) + InsertSliceParallel(group, tx, m.Authors, relId) + InsertSliceParallel(group, tx, m.Media, relId) + InsertSliceParallel(group, tx, m.Styles, relId) + InsertSliceParallel(group, tx, m.Languages, relId) + InsertSliceParallel(group, tx, m.Packs, relId) + InsertSliceParallel(group, tx, m.PackFolders, relId) err := group.Wait() if err != nil && !errors.Is(err, sql.ErrNoRows) { @@ -86,21 +93,56 @@ func (m *Module) InsertObjects(tx *sqlx.Tx) error { return nil } +func (m *Module) ConnectGame(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, m.ID} + + _, err := tx.Exec(data.query, args...) + return err +} + func (m *Module) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { if data.query == "" { return ErrNoQuery } - args := []any{data.id, m.ID, m.Title, m.Description, m.URL, m.License, m.Readme, m.Bugs, + setupID := sql.NullInt64{Int64: int64(data.id), Valid: strings.EqualFold(data.fieldName, "setup_id")} + + args := []any{setupID, data.id, m.ID, m.Title, m.Description, m.URL, m.License, m.Readme, m.Bugs, m.Changelog, m.Version, m.Manifest, m.Download, m.Socket, m.Protected, m.Exclusive, m.PersistentStorage, m.CoreTranslation, m.Library, m.Locked, m.Owned, m.HasStorage, m.Active, m.Availability} - _, err := tx.Exec(data.query, args...) + res, err := tx.Exec(data.query, args...) if err != nil { return err } - return m.InsertObjects(tx) + rowsAffected, err := res.RowsAffected() + if rowsAffected != 0 { + err = m.InsertObjects(tx) + if err != nil { + return err + } + } + + dataCopy := *data + m.ConnectGameQuery(&dataCopy) + + return m.ConnectGame(tx, &dataCopy) +} + +func (m *Module) ConnectGameCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, m.ID} + + _, err := tx.ExecContext(ctx, data.query, args...) + return err } func (m *Module) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { @@ -108,14 +150,27 @@ func (m *Module) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint return ErrNoQuery } - args := []any{data.id, m.ID, m.Title, m.Description, m.URL, m.License, m.Readme, m.Bugs, + setupID := sql.NullInt64{Int64: int64(data.id), Valid: strings.EqualFold(data.fieldName, "setup_id")} + + args := []any{setupID, data.id, m.ID, m.Title, m.Description, m.URL, m.License, m.Readme, m.Bugs, m.Changelog, m.Version, m.Manifest, m.Download, m.Socket, m.Protected, m.Exclusive, m.PersistentStorage, m.CoreTranslation, m.Library, m.Locked, m.Owned, m.HasStorage, m.Active, m.Availability} - _, err := tx.ExecContext(ctx, data.query, args...) + res, err := tx.ExecContext(ctx, data.query, args...) if err != nil { return err } - return m.InsertObjects(tx) + rowsAffected, err := res.RowsAffected() + if rowsAffected != 0 { + err = m.InsertObjects(tx) + if err != nil { + return err + } + } + + dataCopy := *data + m.ConnectGameQuery(&dataCopy) + + return m.ConnectGameCtx(ctx, tx, &dataCopy) } diff --git a/internal/foundry/temp_models/db/options.go b/internal/foundry/temp_models/db/options.go index 515e7f9..9c65e69 100644 --- a/internal/foundry/temp_models/db/options.go +++ b/internal/foundry/temp_models/db/options.go @@ -16,7 +16,7 @@ type GameOptions struct { func (g *GameOptions) Query(data *InsertId[uint]) { data.query = ` - INSERT INTO featured_content (game_id, language, update_channel, port) + INSERT INTO game_options (game_id, language, update_channel, port) VALUES ($1, $2, $3, $4) RETURNING id` } diff --git a/internal/foundry/temp_models/db/pack.go b/internal/foundry/temp_models/db/pack.go index 7b2a0a1..1cc6010 100644 --- a/internal/foundry/temp_models/db/pack.go +++ b/internal/foundry/temp_models/db/pack.go @@ -5,16 +5,14 @@ import ( "database/sql" "errors" "fmt" - "strconv" "github.com/jmoiron/sqlx" "golang.org/x/sync/errgroup" ) type Pack struct { - ID uint + ID string - Key string Name string Label string Banner string @@ -30,18 +28,17 @@ type Pack struct { func (p *Pack) Query(data *InsertId[string]) { data.query = fmt.Sprintf(` - INSERT INTO pack (%s, key_, name, label, banner, path, type, system, package_type, package_name) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) - RETURNING id`, data.fieldName) + INSERT INTO pack (%s, id, name, label, banner, path, type, system, package_type, package_name) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`, data.fieldName) } func (p *Pack) InsertObjects(tx *sqlx.Tx) error { group, ctx := errgroup.WithContext(context.Background()) InsertWithCtxParallel(group, ctx, tx, p.Ownership, - InsertId[string]{id: strconv.FormatUint(uint64(p.ID), 10), fieldName: "pack_id"}) + InsertId[string]{id: p.ID, fieldName: "pack_id"}) - relId := InsertId[uint]{id: p.ID, fieldName: "pack_id"} + relId := InsertId[string]{id: p.ID, fieldName: "pack_id"} InsertSliceParallel(group, tx, p.Index, relId) InsertSliceParallel(group, tx, p.Folders, relId) @@ -57,9 +54,10 @@ func (p *Pack) Insert(tx *sqlx.Tx, data *InsertId[string]) error { return ErrNoQuery } - args := []any{data.id, p.Key, p.Name, p.Label, p.Banner, p.Path, p.Type, p.System, p.PackageType, p.PackageName} + args := []any{data.id, p.ID, p.Name, p.Label, p.Banner, p.Path, p.Type, + p.System, p.PackageType, p.PackageName} - err := tx.QueryRowx(data.query, args...).Scan(&p.ID) + _, err := tx.Exec(data.query, args...) if err != nil { return err } @@ -72,9 +70,10 @@ func (p *Pack) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string return ErrNoQuery } - args := []any{data.id, p.Key, p.Name, p.Label, p.Banner, p.Path, p.Type, p.System, p.PackageType, p.PackageName} + args := []any{data.id, p.ID, p.Name, p.Label, p.Banner, p.Path, p.Type, + p.System, p.PackageType, p.PackageName} - err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&p.ID) + _, err := tx.ExecContext(ctx, data.query, args...) if err != nil { return err } @@ -92,13 +91,13 @@ type PackFolder struct { Sort int } -func (p *PackFolder) Query(data *InsertId[uint]) { +func (p *PackFolder) Query(data *InsertId[string]) { data.query = fmt.Sprintf(` INSERT INTO pack_folder (%s, id, description, name, sorting, type, sort) VALUES ($1, $2, $3, $4, $5, $6, $7)`, data.fieldName) } -func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { +func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[string]) error { if data.query == "" { return ErrNoQuery } @@ -113,7 +112,7 @@ func (p *PackFolder) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { return nil } -func (p *PackFolder) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { +func (p *PackFolder) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { if data.query == "" { return ErrNoQuery } diff --git a/internal/foundry/temp_models/db/package_warnings.go b/internal/foundry/temp_models/db/package_warnings.go index e5e7c33..12eee8e 100644 --- a/internal/foundry/temp_models/db/package_warnings.go +++ b/internal/foundry/temp_models/db/package_warnings.go @@ -83,8 +83,26 @@ func (p *PackageWarningsData) InsertObjects(tx *sqlx.Tx) error { func (p *PackageWarningsData) Query(data *InsertId[uint]) { data.query = ` - INSERT INTO package_warnings_data (package_warnings_id, id, type, reinstallable, manifest) - VALUES ($1, $2, $3, $4, $5)` + INSERT INTO package_warnings_data (id, type, reinstallable, manifest) + VALUES ($1, $2, $3, $4) + ON CONFLICT(id) DO NOTHING` +} + +func (p *PackageWarningsData) ConnectGameQuery(data *InsertId[uint]) { + data.query = ` + INSERT INTO package_warnings_to_data (package_warnings_id, package_warnings_data_id) + VALUES ($1, $2)` +} + +func (p *PackageWarningsData) ConnectGame(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, p.ID} + + _, err := tx.Exec(data.query, args...) + return err } func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { @@ -92,14 +110,36 @@ func (p *PackageWarningsData) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { return ErrNoQuery } - args := []any{data.id, p.ID, p.Type, p.Reinstallable, p.Manifest} + args := []any{p.ID, p.Type, p.Reinstallable, p.Manifest} - _, err := tx.Exec(data.query, args...) + res, err := tx.Exec(data.query, args...) if err != nil { return err } - return p.InsertObjects(tx) + rowsAffected, err := res.RowsAffected() + if rowsAffected != 0 { + err = p.InsertObjects(tx) + } + if err != nil { + return err + } + + dataCopy := *data + p.ConnectGameQuery(&dataCopy) + + return p.ConnectGame(tx, &dataCopy) +} + +func (p *PackageWarningsData) ConnectGameCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, p.ID} + + _, err := tx.ExecContext(ctx, data.query, args...) + return err } func (p *PackageWarningsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { @@ -107,12 +147,23 @@ func (p *PackageWarningsData) InsertCtx(ctx context.Context, tx *sqlx.Tx, data * return ErrNoQuery } - args := []any{data.id, p.ID, p.Type, p.Reinstallable, p.Manifest} + args := []any{p.ID, p.Type, p.Reinstallable, p.Manifest} - _, err := tx.ExecContext(ctx, data.query, args...) + res, err := tx.ExecContext(ctx, data.query, args...) if err != nil { return err } - return p.InsertObjects(tx) + rowsAffected, err := res.RowsAffected() + if rowsAffected != 0 { + err = p.InsertObjects(tx) + } + if err != nil { + return err + } + + dataCopy := *data + p.ConnectGameQuery(&dataCopy) + + return p.ConnectGameCtx(ctx, tx, &dataCopy) } diff --git a/internal/foundry/temp_models/db/ring.go b/internal/foundry/temp_models/db/ring.go index 02805e8..672968e 100644 --- a/internal/foundry/temp_models/db/ring.go +++ b/internal/foundry/temp_models/db/ring.go @@ -1,5 +1,15 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Ring struct { ID uint @@ -9,6 +19,57 @@ type Ring struct { Subject Subject } +func (r *Ring) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO ring (%s, enabled, effects) + VALUES ($1, $2, $3) + RETURNING id`, data.fieldName) +} + +func (r *Ring) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[uint]{id: r.ID, fieldName: "ring_id"} + InsertWithCtxParallel(group, ctx, tx, r.RingColors, relId) + InsertWithCtxParallel(group, ctx, tx, r.Subject, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (r *Ring) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, r.Enabled, r.Effects} + + err := tx.QueryRowx(data.query, args...).Scan(&r.ID) + if err != nil { + return err + } + + return nil +} + +func (r *Ring) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, r.Enabled, r.Effects} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&r.ID) + if err != nil { + return err + } + + return nil +} + type RingColors struct { ID uint @@ -16,9 +77,83 @@ type RingColors struct { Background string } +func (r RingColors) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO ring_colors (%s, ring, background) + VALUES ($1, $2, $3) + RETURNING id`, data.fieldName) +} + +func (r RingColors) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, r.Ring, r.Background} + + err := tx.QueryRowx(data.query, args...).Scan(&r.ID) + if err != nil { + return err + } + + return nil +} + +func (r RingColors) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, r.Ring, r.Background} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&r.ID) + if err != nil { + return err + } + + return nil +} + type Subject struct { ID uint Scale int Texture string } + +func (s Subject) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO ring_colors (%s, scale, texture) + VALUES ($1, $2, $3) + RETURNING id`, data.fieldName) +} + +func (s Subject) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.Scale, s.Texture} + + err := tx.QueryRowx(data.query, args...).Scan(&s.ID) + if err != nil { + return err + } + + return nil +} + +func (s Subject) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.Scale, s.Texture} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&s.ID) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/scene.go b/internal/foundry/temp_models/db/scene.go index 422f7b8..c758b77 100644 --- a/internal/foundry/temp_models/db/scene.go +++ b/internal/foundry/temp_models/db/scene.go @@ -21,7 +21,7 @@ type Scene struct { Grid SceneGrid TokenVision bool Drawings []SceneDrawing - Tokens []Token + Tokens []*Token Lights []SceneLight Notes []Note Sounds []ScenesSound @@ -119,7 +119,7 @@ type SceneLight struct { Rotation int Walls bool Vision bool - Config Light + Config *Light Hidden bool Elevation int } diff --git a/internal/foundry/temp_models/db/system.go b/internal/foundry/temp_models/db/system.go index b4e0542..89f45b3 100644 --- a/internal/foundry/temp_models/db/system.go +++ b/internal/foundry/temp_models/db/system.go @@ -4,7 +4,7 @@ import ( "context" "database/sql" "errors" - "fmt" + "strings" "github.com/jmoiron/sqlx" "golang.org/x/sync/errgroup" @@ -48,12 +48,18 @@ type System struct { } func (s *System) Query(data *InsertId[string]) { - data.query = fmt.Sprintf(` - INSERT INTO system (%s, id, title, description, url, license, bugs, changelog, version, manifest, + data.query = ` + INSERT INTO system (setup_id, id, title, description, url, license, bugs, changelog, version, manifest, download, background, primary_token_attribute, availability, socket, protected, exclusive_, persistent_storage, locked, owned, has_storage) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)`, - data.fieldName) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21) + ON CONFLICT(id) DO NOTHING` +} + +func (s *System) ConnectGameQuery(data *InsertId[string]) { + data.query = ` + INSERT INTO game_to_systems (game_id, system_id) + VALUES ($1, $2)` } func (s *System) InsertObjects(tx *sqlx.Tx) error { @@ -86,22 +92,57 @@ func (s *System) InsertObjects(tx *sqlx.Tx) error { return nil } +func (s *System) ConnectGame(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.ID} + + _, err := tx.Exec(data.query, args...) + return err +} + func (s *System) Insert(tx *sqlx.Tx, data *InsertId[string]) error { if data.query == "" { return ErrNoQuery } - args := []any{data.id, s.ID, s.Title, s.Description, s.URL, s.License, s.Bugs, + setupID := sql.NullString{String: data.id, Valid: strings.EqualFold(data.fieldName, "setup_id")} + + args := []any{setupID, s.ID, s.Title, s.Description, s.URL, s.License, s.Bugs, s.Changelog, s.Version, s.Manifest, s.Download, s.Background, s.PrimaryTokenAttribute, s.Availability, s.Socket, s.Protected, s.Exclusive, s.PersistentStorage, s.Locked, s.Owned, s.HasStorage} - _, err := tx.Exec(data.query, args...) + res, err := tx.Exec(data.query, args...) if err != nil { return err } - return s.InsertObjects(tx) + rowsAffected, err := res.RowsAffected() + if rowsAffected != 0 { + err = s.InsertObjects(tx) + if err != nil { + return err + } + } + + dataCopy := *data + s.ConnectGameQuery(&dataCopy) + + return s.ConnectGame(tx, &dataCopy) +} + +func (s *System) ConnectGameCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, s.ID} + + _, err := tx.ExecContext(ctx, data.query, args...) + return err } func (s *System) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { @@ -109,15 +150,28 @@ func (s *System) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[stri return ErrNoQuery } - args := []any{data.id, s.ID, s.Title, s.Description, s.URL, s.License, s.Bugs, + setupID := sql.NullString{String: data.id, Valid: strings.EqualFold(data.fieldName, "setup_id")} + + args := []any{setupID, s.ID, s.Title, s.Description, s.URL, s.License, s.Bugs, s.Changelog, s.Version, s.Manifest, s.Download, s.Background, s.PrimaryTokenAttribute, s.Availability, s.Socket, s.Protected, s.Exclusive, s.PersistentStorage, s.Locked, s.Owned, s.HasStorage} - _, err := tx.ExecContext(ctx, data.query, args...) + res, err := tx.ExecContext(ctx, data.query, args...) if err != nil { return err } - return s.InsertObjects(tx) + rowsAffected, err := res.RowsAffected() + if rowsAffected != 0 { + err = s.InsertObjects(tx) + if err != nil { + return err + } + } + + dataCopy := *data + s.ConnectGameQuery(&dataCopy) + + return s.ConnectGameCtx(ctx, tx, &dataCopy) } diff --git a/internal/foundry/temp_models/db/token.go b/internal/foundry/temp_models/db/token.go index 7d831ad..a4ab31e 100644 --- a/internal/foundry/temp_models/db/token.go +++ b/internal/foundry/temp_models/db/token.go @@ -1,5 +1,15 @@ package db +import ( + "context" + "database/sql" + "errors" + "fmt" + + "github.com/jmoiron/sqlx" + "golang.org/x/sync/errgroup" +) + type Token struct { ID uint @@ -16,16 +26,76 @@ type Token struct { Alpha int Width float64 Height float64 - Ring Ring - Sight TokenSight - Texture TokenTexture + Ring *Ring + Sight *TokenSight + Texture *TokenTexture Bar1 TokenBar Bar2 TokenBar - Light Light + Light *Light Occludable TokenOccludable TurnMarker TokenTurnMarker } +func (t *Token) Query(data *InsertId[string]) { + data.query = fmt.Sprintf(` + INSERT INTO token (%s, name, actor_link_ append_number, prepend_adjective, lock_rotation, random_img, display_name, + display_bars, disposition, rotation, alpha, width, height) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) + RETURNING id`, data.fieldName) +} + +func (t *Token) InsertObjects(tx *sqlx.Tx) error { + group, ctx := errgroup.WithContext(context.Background()) + + relId := InsertId[uint]{id: t.ID, fieldName: "token_id"} + InsertWithCtxParallel(group, ctx, tx, t.Ring, relId) + InsertWithCtxParallel(group, ctx, tx, t.Sight, relId) + InsertWithCtxParallel(group, ctx, tx, t.Texture, relId) + InsertWithCtxParallel(group, ctx, tx, t.Bar1, InsertId[uint]{id: t.ID, fieldName: "token_id", tableName: "token_bar_1"}) + InsertWithCtxParallel(group, ctx, tx, t.Bar1, InsertId[uint]{id: t.ID, fieldName: "token_id", tableName: "token_bar_2"}) + InsertWithCtxParallel(group, ctx, tx, t.Light, relId) + InsertWithCtxParallel(group, ctx, tx, t.Occludable, relId) + InsertWithCtxParallel(group, ctx, tx, t.TurnMarker, relId) + + err := group.Wait() + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return err + } + return nil +} + +func (t *Token) Insert(tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Name, t.ActorLink, t.AppendNumber, t.PrependAdjective, t.LockRotation, t.RandomImg, + t.DisplayName, t.DisplayBars, t.Disposition, t.Rotation, t.Alpha, t.Width, t.Height} + + err := tx.QueryRowx(data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return t.InsertObjects(tx) +} + +func (t *Token) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Name, t.ActorLink, t.AppendNumber, t.PrependAdjective, t.LockRotation, t.RandomImg, + t.DisplayName, t.DisplayBars, t.Disposition, t.Rotation, t.Alpha, t.Width, t.Height} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return t.InsertObjects(tx) +} + type TokenTexture struct { ID uint @@ -42,6 +112,43 @@ type TokenTexture struct { AlphaThreshold float64 } +func (t *TokenTexture) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO token_texture (%s, src, fit, tint, scale_x, scale_y, offset_x, offset_y, rotation, anchor_x, anchor_y, alpha_threshold) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) + RETURNING id`, data.fieldName) +} + +func (t *TokenTexture) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Src, t.Fit, t.Tint, t.ScaleX, t.ScaleY, t.OffsetX, t.OffsetY, t.Rotation, t.AnchorX, t.AnchorY, t.AlphaThreshold} + + err := tx.QueryRowx(data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return nil +} + +func (t *TokenTexture) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Src, t.Fit, t.Tint, t.ScaleX, t.ScaleY, t.OffsetX, t.OffsetY, t.Rotation, t.AnchorX, t.AnchorY, t.AlphaThreshold} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return nil +} + type TokenSight struct { ID uint @@ -54,18 +161,129 @@ type TokenSight struct { Enabled bool } +func (t *TokenSight) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO token_sight (%s, color, vision_mode, range_, angle, attenuation, brightness, enabled) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + RETURNING id`, data.fieldName) +} + +func (t *TokenSight) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Color, t.VisionMode, t.Range, t.Angle, t.Attenuation, t.Brightness, t.Enabled} + + err := tx.QueryRowx(data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return nil +} + +func (t *TokenSight) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Color, t.VisionMode, t.Range, t.Angle, t.Attenuation, t.Brightness, t.Enabled} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return nil +} + type TokenBar struct { ID uint Attribute string } +func (t TokenBar) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO %s (%s, attribute) + VALUES ($1, $2) + RETURNING id`, data.tableName, data.fieldName) +} + +func (t TokenBar) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Attribute} + + err := tx.QueryRowx(data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return nil +} + +func (t TokenBar) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Attribute} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return nil +} + type TokenOccludable struct { ID uint Radius int } +func (t TokenOccludable) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO token_occludable (%s, radius) + VALUES ($1, $2) + RETURNING id`, data.fieldName) +} + +func (t TokenOccludable) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Radius} + + err := tx.QueryRowx(data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return nil +} + +func (t TokenOccludable) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Radius} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return nil +} + type TokenTurnMarker struct { ID uint @@ -74,3 +292,40 @@ type TokenTurnMarker struct { Src string Disposition bool } + +func (t TokenTurnMarker) Query(data *InsertId[uint]) { + data.query = fmt.Sprintf(` + INSERT INTO token_turn_maker (%s, mode, animation, src, disposition) + VALUES ($1, $2, $3, $4, $5) + RETURNING id`, data.fieldName) +} + +func (t TokenTurnMarker) Insert(tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Mode, t.Animation, t.Src, t.Disposition} + + err := tx.QueryRowx(data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return nil +} + +func (t TokenTurnMarker) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[uint]) error { + if data.query == "" { + return ErrNoQuery + } + + args := []any{data.id, t.Mode, t.Animation, t.Src, t.Disposition} + + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&t.ID) + if err != nil { + return err + } + + return nil +} diff --git a/internal/foundry/temp_models/db/utils.go b/internal/foundry/temp_models/db/utils.go index ddf09d9..ae0518e 100644 --- a/internal/foundry/temp_models/db/utils.go +++ b/internal/foundry/temp_models/db/utils.go @@ -7,6 +7,7 @@ import ( "time" "github.com/jmoiron/sqlx" + "github.com/mattn/go-sqlite3" "golang.org/x/sync/errgroup" ) @@ -172,3 +173,14 @@ func DeleteAllSeq(db *sqlx.DB) error { return nil } + +func IsErrUniqueConstraint(err error) { + if sqliteErr, ok := err.(sqlite3.Error); ok { + // SQLITE_CONSTRAINT_UNIQUE (extended code 2067) + // or SQLITE_CONSTRAINT (basic code 19) + if sqliteErr.ExtendedCode == sqlite3.ErrConstraintUnique || + sqliteErr.Code == sqlite3.ErrConstraint { + fmt.Println("Record already exists") + } + } +} diff --git a/internal/foundry/temp_models/db/world.go b/internal/foundry/temp_models/db/world.go index 5303ee4..1d7c9f2 100644 --- a/internal/foundry/temp_models/db/world.go +++ b/internal/foundry/temp_models/db/world.go @@ -48,10 +48,14 @@ type World struct { func (w *World) Query(data *InsertId[string]) { data.query = fmt.Sprintf(` - INSERT INTO world (%s, id, title, description, version, system, background, join_theme, + INSERT INTO world (%[1]s, id, title, description, version, system, background, join_theme, core_version, system_version, last_played, playtime, availability, next_session, socket, protected, exclusive_, persistent_storage, locked, owned, has_storage) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21)`, + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21) + ON CONFLICT(id) DO UPDATE SET + %[1]s = EXCLUDED.%[1]s, + updated_at = datetime('now') + RETURNING (created_at == updated_at) AS was_inserted`, data.fieldName) } @@ -92,12 +96,16 @@ func (w *World) Insert(tx *sqlx.Tx, data *InsertId[string]) error { w.CoreVersion, w.SystemVersion, w.LastPlayed, w.Playtime, w.Availability, w.NextSession, w.Socket, w.Protected, w.Exclusive, w.PersistentStorage, w.Locked, w.Owned, w.HasStorage} - _, err := tx.Exec(data.query, args...) + var isInserted bool + err := tx.QueryRowx(data.query, args...).Scan(&isInserted) if err != nil { return err } - return w.InsertObjects(tx) + if isInserted { + return w.InsertObjects(tx) + } + return nil } func (w *World) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[string]) error { @@ -109,10 +117,14 @@ func (w *World) InsertCtx(ctx context.Context, tx *sqlx.Tx, data *InsertId[strin w.CoreVersion, w.SystemVersion, w.LastPlayed, w.Playtime, w.Availability, w.NextSession, w.Socket, w.Protected, w.Exclusive, w.PersistentStorage, w.Locked, w.Owned, w.HasStorage} - _, err := tx.ExecContext(ctx, data.query, args...) + var isInserted bool + err := tx.QueryRowxContext(ctx, data.query, args...).Scan(&isInserted) if err != nil { return err } - return w.InsertObjects(tx) + if isInserted { + return w.InsertObjects(tx) + } + return nil } diff --git a/internal/foundry/temp_models/json/actor.go b/internal/foundry/temp_models/json/actor.go index f003c08..bbdf8fa 100644 --- a/internal/foundry/temp_models/json/actor.go +++ b/internal/foundry/temp_models/json/actor.go @@ -18,24 +18,28 @@ type Actor struct { // ActorsEffects []any `json:"effects"` } -func (a *Actor) ToDB(dest *db.Actor) bool { +func (a *Actor) ToDB(dest **db.Actor) bool { if dest == nil { return false } - dest.Img = a.Img - dest.Name = a.Name - dest.Type = a.Type - dest.Folder = a.Folder - dest.Sort = a.Sort - dest.ID = a.ID + actor := &db.Actor{ + Img: a.Img, + Name: a.Name, + Type: a.Type, + Folder: a.Folder, + Sort: a.Sort, + ID: a.ID, + } - a.PrototypeToken.ToDB(&dest.PrototypeToken) - a.Stats.ToDB(&dest.Stats) + a.PrototypeToken.ToDB(&actor.PrototypeToken) + a.Stats.ToDB(&actor.Stats) - OwnershipToDB(&dest.Ownership, a.Ownership) + OwnershipToDB(&actor.Ownership, a.Ownership) - CopySliceToDB(&dest.Items, a.Items) + CopySliceToDB(&actor.Items, a.Items) + + *dest = actor return true } diff --git a/internal/foundry/temp_models/json/card.go b/internal/foundry/temp_models/json/card.go index f750ca5..b03d661 100644 --- a/internal/foundry/temp_models/json/card.go +++ b/internal/foundry/temp_models/json/card.go @@ -3,20 +3,20 @@ package json import "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db" type CardDeck struct { - Name string `json:"name"` - Type string `json:"type"` - Description string `json:"description"` - Img string `json:"img"` - Cards []*Card `json:"cards"` - Width int `json:"width"` - Height int `json:"height"` - Rotation int `json:"rotation"` - DisplayCount bool `json:"displayCount"` - Stats Stats `json:"_stats"` - Ownership Ownership `json:"ownership"` - Folder string `json:"folder"` - Sort int `json:"sort"` - ID string `json:"_id"` + Name string `json:"name"` + Type string `json:"type"` + Description string `json:"description"` + Img string `json:"img"` + Cards []*Card `json:"cards"` + Width int `json:"width"` + Height int `json:"height"` + Rotation int `json:"rotation"` + DisplayCount bool `json:"displayCount"` + Stats Stats `json:"_stats"` + Ownership map[string]int `json:"ownership,omitempty"` + Folder string `json:"folder"` + Sort int `json:"sort"` + ID string `json:"_id"` // Flags any `json:"flags"` // Cards0System any `json:"system"` } @@ -41,8 +41,8 @@ func (c *CardDeck) ToDB(dest **db.CardDeck) bool { } c.Stats.ToDB(&cardDeck.Stats) - c.Ownership.ToDB(&cardDeck.Ownership) + OwnershipToDB(&cardDeck.Ownership, c.Ownership) CopySliceToDB(&cardDeck.Cards, c.Cards) *dest = cardDeck diff --git a/internal/foundry/temp_models/json/game.go b/internal/foundry/temp_models/json/game.go index c3149b3..fb7bb16 100644 --- a/internal/foundry/temp_models/json/game.go +++ b/internal/foundry/temp_models/json/game.go @@ -1,6 +1,7 @@ package json import ( + "encoding/json" "sync" "gitea.local.lab/Lbenedar/foundry_helper_service/internal/foundry/temp_models/db" @@ -40,6 +41,19 @@ type Game struct { // Template Template `json:"template"` } +func ParseGame(data []byte) (*Game, error) { + var modelGame []Game + err := json.Unmarshal(data, &modelGame) + if err != nil { + return nil, err + } + + if len(modelGame) > 1 { + return nil, ErrorSetupMoreThanOne + } + return &modelGame[0], nil +} + func (g *Game) ToDB(dest *db.Game) bool { dest.UserID = g.UserID dest.DemoMode = g.DemoMode diff --git a/internal/foundry/temp_models/json/journal_page.go b/internal/foundry/temp_models/json/journal_page.go index a9780cd..7b0cca7 100644 --- a/internal/foundry/temp_models/json/journal_page.go +++ b/internal/foundry/temp_models/json/journal_page.go @@ -39,6 +39,8 @@ func (j *JournalPage) ToDB(dest **db.JournalPage) bool { OwnershipToDB(&journalPage.Ownership, j.Ownership) + *dest = journalPage + return true } diff --git a/internal/foundry/temp_models/json/light.go b/internal/foundry/temp_models/json/light.go index 628f7dc..fe3d0b3 100644 --- a/internal/foundry/temp_models/json/light.go +++ b/internal/foundry/temp_models/json/light.go @@ -20,27 +20,31 @@ type Light struct { Color string `json:"color"` } -func (l *Light) ToDB(dest *db.Light) bool { +func (l *Light) ToDB(dest **db.Light) bool { if dest == nil { return false } - dest.Alpha = l.Alpha - dest.Angle = l.Angle - dest.Bright = l.Bright - dest.Coloration = l.Coloration - dest.Dim = l.Dim - dest.Attenuation = l.Attenuation - dest.Luminosity = l.Luminosity - dest.Saturation = l.Saturation - dest.Contrast = l.Contrast - dest.Shadows = l.Shadows - dest.Negative = l.Negative - dest.Priority = l.Priority - dest.Color = l.Color + light := &db.Light{ + Alpha: l.Alpha, + Angle: l.Angle, + Bright: l.Bright, + Coloration: l.Coloration, + Dim: l.Dim, + Attenuation: l.Attenuation, + Luminosity: l.Luminosity, + Saturation: l.Saturation, + Contrast: l.Contrast, + Shadows: l.Shadows, + Negative: l.Negative, + Priority: l.Priority, + Color: l.Color, + } - l.LightAnimation.ToDB(&dest.LightAnimation) - l.LightDarkness.ToDB(&dest.LightDarkness) + l.LightAnimation.ToDB(&light.LightAnimation) + l.LightDarkness.ToDB(&light.LightDarkness) + + *dest = light return true } diff --git a/internal/foundry/temp_models/json/pack.go b/internal/foundry/temp_models/json/pack.go index 4e26718..c8c3781 100644 --- a/internal/foundry/temp_models/json/pack.go +++ b/internal/foundry/temp_models/json/pack.go @@ -36,7 +36,7 @@ func (p *Pack) ToDB(dest **db.Pack) bool { System: p.System, PackageType: p.PackageType, PackageName: p.PackageName, - Key: p.Id, + ID: p.Id, } p.Ownership.ToDB(&pack.Ownership) diff --git a/internal/foundry/temp_models/json/playlist.go b/internal/foundry/temp_models/json/playlist.go index 08f622b..873d633 100644 --- a/internal/foundry/temp_models/json/playlist.go +++ b/internal/foundry/temp_models/json/playlist.go @@ -45,6 +45,8 @@ func (p *Playlist) ToDB(dest **db.Playlist) bool { CopySliceToDB(&playlist.Sounds, p.Sounds) + *dest = playlist + return true } diff --git a/internal/foundry/temp_models/json/ring.go b/internal/foundry/temp_models/json/ring.go index a6b7c85..d77656c 100644 --- a/internal/foundry/temp_models/json/ring.go +++ b/internal/foundry/temp_models/json/ring.go @@ -9,15 +9,20 @@ type Ring struct { Subject Subject `json:"subject"` } -func (r *Ring) ToDB(dest *db.Ring) bool { +func (r *Ring) ToDB(dest **db.Ring) bool { if dest == nil { return false } - dest.Enabled = r.Enabled - dest.Effects = r.Effects - r.RingColors.ToDB(&dest.RingColors) - r.Subject.ToDB(&dest.Subject) + ring := &db.Ring{ + Enabled: r.Enabled, + Effects: r.Effects, + } + + r.RingColors.ToDB(&ring.RingColors) + r.Subject.ToDB(&ring.Subject) + + *dest = ring return true } diff --git a/internal/foundry/temp_models/json/table.go b/internal/foundry/temp_models/json/table.go index 94b3943..53dc03c 100644 --- a/internal/foundry/temp_models/json/table.go +++ b/internal/foundry/temp_models/json/table.go @@ -41,6 +41,8 @@ func (t *Table) ToDB(dest **db.Table) bool { CopySliceToDB(&table.Results, t.Results) + *dest = table + return true } diff --git a/internal/foundry/temp_models/json/token.go b/internal/foundry/temp_models/json/token.go index f0bd667..e7e19de 100644 --- a/internal/foundry/temp_models/json/token.go +++ b/internal/foundry/temp_models/json/token.go @@ -29,33 +29,37 @@ type Token struct { // DetectionModes []any `json:"detectionModes"` } -func (t *Token) ToDB(dest *db.Token) bool { +func (t *Token) ToDB(dest **db.Token) bool { if dest == nil { return false } - dest.DisplayName = t.DisplayName - dest.DisplayBars = t.DisplayBars - dest.Disposition = t.Disposition - dest.Name = t.Name - dest.ActorLink = t.ActorLink - dest.AppendNumber = t.AppendNumber - dest.PrependAdjective = t.PrependAdjective - dest.Width = t.Width - dest.Height = t.Height - dest.LockRotation = t.LockRotation - dest.Rotation = t.Rotation - dest.Alpha = t.Alpha - dest.RandomImg = t.RandomImg + token := &db.Token{ + DisplayName: t.DisplayName, + DisplayBars: t.DisplayBars, + Disposition: t.Disposition, + Name: t.Name, + ActorLink: t.ActorLink, + AppendNumber: t.AppendNumber, + PrependAdjective: t.PrependAdjective, + Width: t.Width, + Height: t.Height, + LockRotation: t.LockRotation, + Rotation: t.Rotation, + Alpha: t.Alpha, + RandomImg: t.RandomImg, + } - t.Ring.ToDB(&dest.Ring) - t.Sight.ToDB(&dest.Sight) - t.Texture.ToDB(&dest.Texture) - t.Bar1.ToDB(&dest.Bar1) - t.Bar2.ToDB(&dest.Bar2) - t.Light.ToDB(&dest.Light) - t.Occludable.ToDB(&dest.Occludable) - t.TurnMarker.ToDB(&dest.TurnMarker) + t.Ring.ToDB(&token.Ring) + t.Sight.ToDB(&token.Sight) + t.Texture.ToDB(&token.Texture) + t.Bar1.ToDB(&token.Bar1) + t.Bar2.ToDB(&token.Bar2) + t.Light.ToDB(&token.Light) + t.Occludable.ToDB(&token.Occludable) + t.TurnMarker.ToDB(&token.TurnMarker) + + *dest = token return true } @@ -74,22 +78,26 @@ type TokenTexture struct { AlphaThreshold float64 `json:"alphaThreshold"` } -func (t *TokenTexture) ToDB(dest *db.TokenTexture) bool { +func (t *TokenTexture) ToDB(dest **db.TokenTexture) bool { if dest == nil { return false } - dest.Src = t.Src - dest.ScaleX = t.ScaleX - dest.ScaleY = t.ScaleY - dest.OffsetX = t.OffsetX - dest.OffsetY = t.OffsetY - dest.Rotation = t.Rotation - dest.AnchorX = t.AnchorX - dest.AnchorY = t.AnchorY - dest.Fit = t.Fit - dest.Tint = t.Tint - dest.AlphaThreshold = t.AlphaThreshold + texture := &db.TokenTexture{ + Src: t.Src, + ScaleX: t.ScaleX, + ScaleY: t.ScaleY, + OffsetX: t.OffsetX, + OffsetY: t.OffsetY, + Rotation: t.Rotation, + AnchorX: t.AnchorX, + AnchorY: t.AnchorY, + Fit: t.Fit, + Tint: t.Tint, + AlphaThreshold: t.AlphaThreshold, + } + + *dest = texture return true } @@ -104,18 +112,22 @@ type TokenSight struct { Brightness float64 } -func (t *TokenSight) ToDB(dest *db.TokenSight) bool { +func (t *TokenSight) ToDB(dest **db.TokenSight) bool { if dest == nil { return false } - dest.Color = t.Color - dest.Enabled = t.Enabled - dest.Range = t.Range - dest.Angle = t.Angle - dest.VisionMode = t.VisionMode - dest.Attenuation = t.Attenuation - dest.Brightness = t.Brightness + sight := &db.TokenSight{ + Color: t.Color, + Enabled: t.Enabled, + Range: t.Range, + Angle: t.Angle, + VisionMode: t.VisionMode, + Attenuation: t.Attenuation, + Brightness: t.Brightness, + } + + *dest = sight return true } diff --git a/internal/foundry/transport/db.go b/internal/foundry/transport/db.go index 6897489..80e6d96 100644 --- a/internal/foundry/transport/db.go +++ b/internal/foundry/transport/db.go @@ -20,33 +20,22 @@ func (tr *FoundryTransport) FillDBWithFoundryData() { // return // } - // err = tr.InitWorldsData(idState) - // if err != nil { - // tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} - // return - // } + err = tr.InitWorldsData() + if err != nil { + tr.ReadChan.Err() <- &types.FoundryError{Direction: types.WriterCode, Err: err, Type: types.DbCode} + return + } } func (tr *FoundryTransport) InitSetupData() error { db.DeleteAll(tr.DB) db.DeleteAllSeq(tr.DB) - for k := range requests.PathToSetupState { - err := tr.InsertJsonDataToDB(k) - if err != nil { - return err - } - } - return nil + + return tr.InsertSetupToDB() } -func (tr *FoundryTransport) InsertJsonDataToDB(statePath string) error { - _, ok1 := requests.PathToSetupState[statePath] - _, ok2 := requests.PathToWorldState[statePath] - if !ok1 && !ok2 { - return ErrorStateTypeNotExist - } - - msgJson, err := tr.GetJsonData(statePath) +func (tr *FoundryTransport) InsertSetupToDB() error { + msgJson, err := tr.GetJsonDataByType(requests.SetupPath) if err != nil { return err } @@ -67,35 +56,49 @@ func (tr *FoundryTransport) InsertJsonDataToDB(statePath string) error { return nil } -// func (tr *FoundryTransport) InitWorldsData(idState int64) error { -// worlds, err := tr.Models.FoundryState.GetWorlds(idState) -// if err != nil { -// return err -// } -// tr.Logger.Debug("Worlds", "len", len(worlds)) +func (tr *FoundryTransport) InitWorldsData() error { + worlds := []string{"kingmaker"} //TODO: get world name from database -// for i := range worlds { -// worldName := worlds[i].TextId -// tr.InitWorldData(worldName) -// _, err = tr.Http.PostReturnToSetup() -// if err != nil { -// return err -// } -// } -// return nil -// } + for i := range worlds { + worldName := worlds[i] + tr.InitWorldData(worldName) + _, err := tr.Http.PostReturnToSetup() + if err != nil { + return err + } + } + return nil +} -// func (tr *FoundryTransport) InitWorldData(worldName string) error { -// tr.Logger.Debug("World name", "name", worldName) -// err := tr.LaunchWorld(worldName) -// if err != nil { -// return err -// } -// for k := range requests.PathToWorldState { -// err := tr.InsertJsonDataToDB(k) -// if err != nil { -// return err -// } -// } -// return nil -// } +func (tr *FoundryTransport) InitWorldData(worldName string) error { + tr.Logger.Debug("World name", "name", worldName) + err := tr.LaunchWorld(worldName) + if err != nil { + return err + } + return tr.InsertGameToDB() +} + +func (tr *FoundryTransport) InsertGameToDB() error { + err := tr.ConnectToWorld() + if err != nil { + return err + } + + msgJson, err := tr.GetJsonData("world") + if err != nil { + return err + } + + tr.Logger.Info("Game data received") + + gameJson, err := json.ParseGame(msgJson) + if err != nil { + return err + } + + var foundryStateDb db.Game + gameJson.ToDB(&foundryStateDb) + + return foundryStateDb.Insert(tr.DB) +} diff --git a/internal/foundry/transport/errors.go b/internal/foundry/transport/errors.go index 7c4dd9d..f7189fe 100644 --- a/internal/foundry/transport/errors.go +++ b/internal/foundry/transport/errors.go @@ -3,9 +3,11 @@ package transport import "errors" var ( - ErrorNotAuth = errors.New("Admin is not authenticated") - ErrorIsNotReady = errors.New("Connection is not ready for communication") - ErrorTimeout = errors.New("Answer has not been received after timeout") - ErrorStateTypeNotExist = errors.New("State type does not exists") - ErrorAuthPassWrong = errors.New("Authentication password is wrong") + ErrorNotAuth = errors.New("Admin is not authenticated") + ErrorIsNotReady = errors.New("Connection is not ready for communication") + ErrorTimeout = errors.New("Answer has not been received after timeout") + ErrorStateTypeNotExist = errors.New("State type does not exists") + ErrorAuthPassWrong = errors.New("Authentication password is wrong") + ErrorChannelIsClosed = errors.New("Channel has been closed") + ErrorUserIsNotConnected = errors.New("User is not connected") ) diff --git a/internal/foundry/transport/transport.go b/internal/foundry/transport/transport.go index 4c637e4..ac2126a 100644 --- a/internal/foundry/transport/transport.go +++ b/internal/foundry/transport/transport.go @@ -17,6 +17,7 @@ type FoundryTransport struct { ChanMutex sync.Mutex ReadChan types.ReadChannels ExchangeChan types.ExchangeChannels + LoggedInChan chan bool Http *requests.FoundryHttpRequest ReconnectTimeout time.Duration diff --git a/internal/foundry/transport/websocket.go b/internal/foundry/transport/websocket.go index 4273e05..5fb5128 100644 --- a/internal/foundry/transport/websocket.go +++ b/internal/foundry/transport/websocket.go @@ -31,13 +31,7 @@ func (tr *FoundryTransport) InitWebSocketConnection() error { dialer := websocket.DefaultDialer dialer.ReadBufferSize = 128 * 1024 * 1024 dialer.WriteBufferSize = 128 * 1024 * 1024 - // dialer.Jar = tr.Http.Jar - // ur, err := url.Parse(fmt.Sprintf("http://%s", tr.Http.Host)) - // if err != nil { - // return err - // } - // fmt.Printf("TEST:%v:%v\n", u.String(), dialer.Jar.Cookies(&u)) wsConn, resp, err := dialer.Dial(u.String(), wsHeader) if err != nil { return err @@ -47,8 +41,6 @@ func (tr *FoundryTransport) InitWebSocketConnection() error { for i := range cookies { fmt.Printf("TEST%d: %v\n", i, cookies[i]) } - // fmt.Printf("TEST1: %v\n") - // fmt.Printf("TEST2: %v\n", wsHeader) tr.WsConn = wsConn tr.CurrWsId = 0 @@ -118,19 +110,47 @@ func (tr *FoundryTransport) ListenWebSocket() { } } +func (tr *FoundryTransport) ConnectToWorld() error { + err := tr.LogInToWorld() + if err != nil { + return err + } + tr.Logger.Info("World is started. Succesfully logged into world") + tr.LoggedInChan = make(chan bool) + + close(tr.ReadChan.Reconnect()) + + val, ok := <-tr.LoggedInChan + if !ok { + return ErrorChannelIsClosed + } + if !val { + return ErrorUserIsNotConnected + } + + return nil +} + func (tr *FoundryTransport) SendOnlyCodeRequest(code string) error { tr.Logger.Debug("WS: Data has been send\n", "msg", types.CodesRespToReq[code]) return tr.WsConn.WriteMessage(websocket.TextMessage, []byte(types.CodesRespToReq[code])) } -func (tr *FoundryTransport) GetJsonData(stateType string) ([]byte, error) { +func (tr *FoundryTransport) GetJsonDataByType(stateType string) ([]byte, error) { msg := types.NewWsMessageByPage(stateType, tr.CurrWsId) tr.CurrWsId++ return tr.HandleWebsocketRequest(msg) } +func (tr *FoundryTransport) GetJsonData(msg string) ([]byte, error) { + wsMsg := types.NewWsMessage(msg, tr.CurrWsId) + tr.CurrWsId++ + + return tr.HandleWebsocketRequest(wsMsg) +} + func (tr *FoundryTransport) CloseWebSocketConn() error { tr.Logger.Debug("Websocket has been closed") return tr.WsConn.Close()