- Added `series-world.repo.ts` to handle database operations related to series worlds and their elements. - Implemented `series-sync.repo.ts` for managing synchronization between books and series. - Expanded `spell.ipc.ts` data models to include `seriesSpellId` for spell synchronization. - Refactored `insertSpellTag` method in `spelltag.repo.ts` for improved error handling and logic clarity.
694 lines
36 KiB
TypeScript
694 lines
36 KiB
TypeScript
import { Database, QueryResult, RunResult, SQLiteValue } from 'node-sqlite3-wasm';
|
|
import System from "../System.js";
|
|
|
|
export interface BookCharactersTable extends Record<string, SQLiteValue> {
|
|
character_id: string;
|
|
book_id: string;
|
|
user_id: string;
|
|
first_name: string;
|
|
last_name: string | null;
|
|
nickname: string | null;
|
|
age: string | null;
|
|
gender: string | null;
|
|
species: string | null;
|
|
nationality: string | null;
|
|
status: string | null;
|
|
category: string;
|
|
title: string | null;
|
|
image: string | null;
|
|
role: string | null;
|
|
biography: string | null;
|
|
history: string | null;
|
|
speech_pattern: string | null;
|
|
catchphrase: string | null;
|
|
residence: string | null;
|
|
notes: string | null;
|
|
color: string | null;
|
|
last_update: number;
|
|
}
|
|
|
|
export interface SyncedCharacterResult extends Record<string, SQLiteValue> {
|
|
character_id: string;
|
|
book_id: string;
|
|
first_name: string;
|
|
last_update: number;
|
|
}
|
|
|
|
export interface SyncedCharacterAttributeResult extends Record<string, SQLiteValue> {
|
|
attr_id: string;
|
|
character_id: string;
|
|
attribute_name: string;
|
|
last_update: number;
|
|
}
|
|
|
|
export interface BookCharactersAttributesTable extends Record<string, SQLiteValue> {
|
|
attr_id: string;
|
|
character_id: string;
|
|
user_id: string;
|
|
attribute_name: string;
|
|
attribute_value: string;
|
|
last_update: number;
|
|
}
|
|
|
|
export interface CharacterResult extends Record<string, SQLiteValue> {
|
|
character_id: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
nickname: string | null;
|
|
age: string | null;
|
|
gender: string | null;
|
|
species: string | null;
|
|
nationality: string | null;
|
|
status: string | null;
|
|
title: string;
|
|
category: string;
|
|
image: string;
|
|
role: string;
|
|
biography: string;
|
|
history: string;
|
|
speech_pattern: string | null;
|
|
catchphrase: string | null;
|
|
residence: string | null;
|
|
notes: string | null;
|
|
color: string | null;
|
|
series_character_id: string | null;
|
|
}
|
|
|
|
export interface AttributeResult extends Record<string, SQLiteValue> {
|
|
attr_id: string;
|
|
attribute_name: string;
|
|
attribute_value: string;
|
|
}
|
|
|
|
export interface CompleteCharacterResult extends Record<string, SQLiteValue> {
|
|
character_id: string;
|
|
first_name: string;
|
|
last_name: string;
|
|
nickname: string | null;
|
|
age: string | null;
|
|
gender: string | null;
|
|
species: string | null;
|
|
nationality: string | null;
|
|
status: string | null;
|
|
category: string;
|
|
title: string;
|
|
role: string;
|
|
biography: string;
|
|
history: string;
|
|
speech_pattern: string | null;
|
|
catchphrase: string | null;
|
|
residence: string | null;
|
|
notes: string | null;
|
|
color: string | null;
|
|
attribute_name: string;
|
|
attribute_value: string;
|
|
}
|
|
|
|
export default class CharacterRepo {
|
|
/**
|
|
* Fetches all characters for a specific book and user.
|
|
* @param userId - The unique identifier of the user
|
|
* @param bookId - The unique identifier of the book
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns An array of character results
|
|
*/
|
|
public static fetchCharacters(userId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): CharacterResult[] {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = 'SELECT character_id, first_name, last_name, nickname, age, gender, species, nationality, status, title, category, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, series_character_id FROM book_characters WHERE book_id=? AND user_id=?';
|
|
const params: SQLiteValue[] = [bookId, userId];
|
|
const characters: CharacterResult[] = db.all(query, params) as CharacterResult[];
|
|
return characters;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de récupérer les personnages.` : `Unable to retrieve characters.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a new character to the database.
|
|
* @param userId - The unique identifier of the user
|
|
* @param characterId - The unique identifier for the new character
|
|
* @param characterData - Object containing all encrypted character fields
|
|
* @param bookId - The unique identifier of the book
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns The character ID if successful
|
|
*/
|
|
public static addNewCharacter(userId: string, characterId: string, characterData: {
|
|
firstName: string;
|
|
lastName: string | null;
|
|
nickname: string | null;
|
|
age: string | null;
|
|
gender: string | null;
|
|
species: string | null;
|
|
nationality: string | null;
|
|
status: string | null;
|
|
title: string | null;
|
|
category: string | null;
|
|
image: string | null;
|
|
role: string | null;
|
|
biography: string | null;
|
|
history: string | null;
|
|
speechPattern: string | null;
|
|
catchphrase: string | null;
|
|
residence: string | null;
|
|
notes: string | null;
|
|
color: string | null;
|
|
}, bookId: string, lang: 'fr' | 'en' = 'fr', seriesCharacterId: string | null = null): string {
|
|
let insertResult: RunResult;
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = seriesCharacterId
|
|
? 'INSERT INTO book_characters (character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status, category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, series_character_id, last_update) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'
|
|
: 'INSERT INTO book_characters (character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status, category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)';
|
|
const params: SQLiteValue[] = seriesCharacterId
|
|
? [characterId, bookId, userId, characterData.firstName, characterData.lastName, characterData.nickname, characterData.age, characterData.gender, characterData.species, characterData.nationality, characterData.status, characterData.category, characterData.title, characterData.image, characterData.role, characterData.biography, characterData.history, characterData.speechPattern, characterData.catchphrase, characterData.residence, characterData.notes, characterData.color, seriesCharacterId, System.timeStampInSeconds()]
|
|
: [characterId, bookId, userId, characterData.firstName, characterData.lastName, characterData.nickname, characterData.age, characterData.gender, characterData.species, characterData.nationality, characterData.status, characterData.category, characterData.title, characterData.image, characterData.role, characterData.biography, characterData.history, characterData.speechPattern, characterData.catchphrase, characterData.residence, characterData.notes, characterData.color, System.timeStampInSeconds()];
|
|
insertResult = db.run(query, params);
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible d'ajouter le personnage.` : `Unable to add character.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
if (!insertResult || insertResult.changes === 0) {
|
|
throw new Error(lang === 'fr' ? `Une erreur s'est produite lors de l'ajout du personnage.` : `Error adding character.`);
|
|
}
|
|
return characterId;
|
|
}
|
|
|
|
/**
|
|
* Inserts a new attribute for a character.
|
|
* @param attributeId - The unique identifier for the new attribute
|
|
* @param characterId - The unique identifier of the character
|
|
* @param userId - The unique identifier of the user
|
|
* @param type - The attribute name/type
|
|
* @param name - The attribute value
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns The attribute ID if successful
|
|
*/
|
|
static insertAttribute(attributeId: string, characterId: string, userId: string, type: string, name: string, lang: 'fr' | 'en' = 'fr'): string {
|
|
let insertResult: RunResult;
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = 'INSERT INTO book_characters_attributes (attr_id, character_id, user_id, attribute_name, attribute_value, last_update) VALUES (?,?,?,?,?,?)';
|
|
const params: SQLiteValue[] = [attributeId, characterId, userId, type, name, System.timeStampInSeconds()];
|
|
insertResult = db.run(query, params);
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible d'ajouter l'attribut.` : `Unable to add attribute.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
if (!insertResult || insertResult.changes === 0) {
|
|
throw new Error(lang === 'fr' ? `Une erreur s'est produite lors de l'ajout de l'attribut.` : `Error adding attribute.`);
|
|
}
|
|
return attributeId;
|
|
}
|
|
|
|
/**
|
|
* Updates an existing character's information.
|
|
* @param userId - The unique identifier of the user
|
|
* @param id - The unique identifier of the character to update
|
|
* @param characterData - Object containing all encrypted character fields
|
|
* @param lastUpdate - The timestamp of the last update
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns True if the update was successful, false otherwise
|
|
*/
|
|
static updateCharacter(userId: string, id: string, characterData: {
|
|
firstName: string;
|
|
lastName: string | null;
|
|
nickname: string | null;
|
|
age: string | null;
|
|
gender: string | null;
|
|
species: string | null;
|
|
nationality: string | null;
|
|
status: string | null;
|
|
title: string | null;
|
|
category: string | null;
|
|
image: string | null;
|
|
role: string | null;
|
|
biography: string | null;
|
|
history: string | null;
|
|
speechPattern: string | null;
|
|
catchphrase: string | null;
|
|
residence: string | null;
|
|
notes: string | null;
|
|
color: string | null;
|
|
}, lastUpdate: number, lang: 'fr' | 'en' = 'fr', seriesCharacterId: string | null = null): boolean {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = seriesCharacterId !== null
|
|
? 'UPDATE book_characters SET first_name=?, last_name=?, nickname=?, age=?, gender=?, species=?, nationality=?, status=?, title=?, category=?, image=?, role=?, biography=?, history=?, speech_pattern=?, catchphrase=?, residence=?, notes=?, color=?, series_character_id=?, last_update=? WHERE character_id=? AND user_id=?'
|
|
: 'UPDATE book_characters SET first_name=?, last_name=?, nickname=?, age=?, gender=?, species=?, nationality=?, status=?, title=?, category=?, image=?, role=?, biography=?, history=?, speech_pattern=?, catchphrase=?, residence=?, notes=?, color=?, last_update=? WHERE character_id=? AND user_id=?';
|
|
const params: SQLiteValue[] = seriesCharacterId !== null
|
|
? [characterData.firstName, characterData.lastName, characterData.nickname, characterData.age, characterData.gender, characterData.species, characterData.nationality, characterData.status, characterData.title, characterData.category, characterData.image, characterData.role, characterData.biography, characterData.history, characterData.speechPattern, characterData.catchphrase, characterData.residence, characterData.notes, characterData.color, seriesCharacterId, lastUpdate, id, userId]
|
|
: [characterData.firstName, characterData.lastName, characterData.nickname, characterData.age, characterData.gender, characterData.species, characterData.nationality, characterData.status, characterData.title, characterData.category, characterData.image, characterData.role, characterData.biography, characterData.history, characterData.speechPattern, characterData.catchphrase, characterData.residence, characterData.notes, characterData.color, lastUpdate, id, userId];
|
|
const updateResult: RunResult = db.run(query, params);
|
|
return updateResult.changes > 0;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de mettre à jour le personnage.` : `Unable to update character.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes a character and all its related data (attributes) from the database.
|
|
* @param userId - The unique identifier of the user
|
|
* @param characterId - The unique identifier of the character to delete
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns True if the deletion was successful, false otherwise
|
|
*/
|
|
static deleteCharacter(userId: string, characterId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const deleteAttributesQuery: string = 'DELETE FROM `book_characters_attributes` WHERE `character_id`=? AND `user_id`=?';
|
|
db.run(deleteAttributesQuery, [characterId, userId]);
|
|
const deleteCharacterQuery: string = 'DELETE FROM `book_characters` WHERE `character_id`=? AND `user_id`=?';
|
|
const result: RunResult = db.run(deleteCharacterQuery, [characterId, userId]);
|
|
return result.changes > 0;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de supprimer le personnage.` : `Unable to delete character.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Deletes a character attribute from the database.
|
|
* @param userId - The unique identifier of the user
|
|
* @param attributeId - The unique identifier of the attribute to delete
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns True if the deletion was successful, false otherwise
|
|
*/
|
|
static deleteAttribute(userId: string, attributeId: string, lang: 'fr' | 'en' = 'fr'): boolean {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = 'DELETE FROM `book_characters_attributes` WHERE `attr_id`=? AND `user_id`=?';
|
|
const params: SQLiteValue[] = [attributeId, userId];
|
|
const deleteResult: RunResult = db.run(query, params);
|
|
return deleteResult.changes > 0;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de supprimer l'attribut.` : `Unable to delete attribute.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches all attributes for a specific character.
|
|
* @param characterId - The unique identifier of the character
|
|
* @param userId - The unique identifier of the user
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns An array of attribute results
|
|
*/
|
|
static fetchAttributes(characterId: string, userId: string, lang: 'fr' | 'en' = 'fr'): AttributeResult[] {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = 'SELECT attr_id, attribute_name, attribute_value FROM book_characters_attributes WHERE character_id=? AND user_id=?';
|
|
const params: SQLiteValue[] = [characterId, userId];
|
|
const attributes: AttributeResult[] = db.all(query, params) as AttributeResult[];
|
|
return attributes;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de récupérer les attributs.` : `Unable to retrieve attributes.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches complete character information including attributes, optionally filtered by character IDs.
|
|
* @param userId - The unique identifier of the user
|
|
* @param bookId - The unique identifier of the book
|
|
* @param tags - An optional array of character IDs to filter by
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns An array of complete character results with attributes
|
|
*/
|
|
static fetchCompleteCharacters(userId: string, bookId: string, tags: string[], lang: 'fr' | 'en' = 'fr'): CompleteCharacterResult[] {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
let query: string = 'SELECT charac.character_id, first_name, last_name, nickname, age, gender, species, nationality, status, category, title, role, biography, history, speech_pattern, catchphrase, residence, notes, color, attribute_name, attribute_value FROM book_characters AS charac LEFT JOIN book_characters_attributes AS attr ON charac.character_id=attr.character_id WHERE charac.user_id=? AND charac.book_id=?';
|
|
let params: SQLiteValue[] = [userId, bookId];
|
|
if (tags && tags.length > 0) {
|
|
const placeholders: string = tags.map((): string => '?').join(',');
|
|
query += ` AND charac.character_id IN (${placeholders})`;
|
|
params.push(...tags);
|
|
}
|
|
const characters: CompleteCharacterResult[] = db.all(query, params) as CompleteCharacterResult[];
|
|
if (characters.length === 0) {
|
|
throw new Error(lang === 'fr' ? `Aucun personnage complet trouvé.` : `No complete characters found.`);
|
|
}
|
|
return characters;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de récupérer les personnages complets.` : `Unable to retrieve complete characters.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Updates an existing character attribute.
|
|
* @param userId - The unique identifier of the user
|
|
* @param characterAttributeId - The unique identifier of the attribute to update
|
|
* @param attributeName - The new attribute name
|
|
* @param attributeValue - The new attribute value
|
|
* @param lastUpdate - The timestamp of the last update
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns True if the update was successful, false otherwise
|
|
*/
|
|
static updateCharacterAttribute(userId: string, characterAttributeId: string, attributeName: string, attributeValue: string, lastUpdate: number, lang: "fr" | "en"): boolean {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = 'UPDATE book_characters_attributes SET attribute_name=?, attribute_value=?, last_update=? WHERE attr_id=? AND user_id=?';
|
|
const params: SQLiteValue[] = [attributeName, attributeValue, lastUpdate, characterAttributeId, userId];
|
|
const updateResult: RunResult = db.run(query, params);
|
|
return updateResult.changes > 0;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de mettre à jour l'attribut du personnage.` : `Unable to update character attribute.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if a character exists in the database.
|
|
* @param userId - The unique identifier of the user
|
|
* @param characterId - The unique identifier of the character to check
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns True if the character exists, false otherwise
|
|
*/
|
|
static isCharacterExist(userId: string, characterId: string, lang: "fr" | "en"): boolean {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = 'SELECT 1 FROM `book_characters` WHERE `character_id`=? AND `user_id`=?';
|
|
const params: SQLiteValue[] = [characterId, userId];
|
|
const character: QueryResult | null = db.get(query, params) || null;
|
|
return character !== null;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de vérifier l'existence du personnage.` : `Unable to check character existence.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if a character attribute exists in the database.
|
|
* @param userId - The unique identifier of the user
|
|
* @param characterAttributeId - The unique identifier of the attribute to check
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns True if the attribute exists, false otherwise
|
|
*/
|
|
static isCharacterAttributeExist(userId: string, characterAttributeId: string, lang: "fr" | "en"): boolean {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = 'SELECT 1 FROM `book_characters_attributes` WHERE `attr_id`=? AND `user_id`=?';
|
|
const params: SQLiteValue[] = [characterAttributeId, userId];
|
|
const attribute: QueryResult | null = db.get(query, params) || null;
|
|
return attribute !== null;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de vérifier l'existence de l'attribut du personnage.` : `Unable to check character attribute existence.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches all characters for a specific book asynchronously.
|
|
* @param userId - The unique identifier of the user
|
|
* @param bookId - The unique identifier of the book
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns A promise resolving to an array of book characters
|
|
*/
|
|
static async fetchBookCharacters(userId: string, bookId: string, lang: 'fr' | 'en'): Promise<BookCharactersTable[]> {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = `SELECT character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
|
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
|
FROM book_characters WHERE user_id=? AND book_id=?`;
|
|
const params: SQLiteValue[] = [userId, bookId];
|
|
const characters: BookCharactersTable[] = db.all(query, params) as BookCharactersTable[];
|
|
return characters;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de récupérer les personnages.` : `Unable to retrieve characters.`);
|
|
} else {
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches all attributes for a specific character asynchronously.
|
|
* @param userId - The unique identifier of the user
|
|
* @param characterId - The unique identifier of the character
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns A promise resolving to an array of character attributes
|
|
*/
|
|
static async fetchBookCharactersAttributes(userId: string, characterId: string, lang: 'fr' | 'en'): Promise<BookCharactersAttributesTable[]> {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = 'SELECT attr_id, character_id, user_id, attribute_name, attribute_value, last_update FROM book_characters_attributes WHERE user_id=? AND character_id=?';
|
|
const params: SQLiteValue[] = [userId, characterId];
|
|
const attributes: BookCharactersAttributesTable[] = db.all(query, params) as BookCharactersAttributesTable[];
|
|
return attributes;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de récupérer les attributs des personnages.` : `Unable to retrieve character attributes.`);
|
|
} else {
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches all synced characters for a user.
|
|
* @param userId - The unique identifier of the user
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns An array of synced character results
|
|
*/
|
|
static fetchSyncedCharacters(userId: string, lang: 'fr' | 'en'): SyncedCharacterResult[] {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = 'SELECT character_id, book_id, first_name, last_update FROM book_characters WHERE user_id = ?';
|
|
const params: SQLiteValue[] = [userId];
|
|
const syncedCharacters: SyncedCharacterResult[] = db.all(query, params) as SyncedCharacterResult[];
|
|
return syncedCharacters;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de récupérer les personnages synchronisés.` : `Unable to retrieve synced characters.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches all synced character attributes for a user.
|
|
* @param userId - The unique identifier of the user
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns An array of synced character attribute results
|
|
*/
|
|
static fetchSyncedCharacterAttributes(userId: string, lang: 'fr' | 'en'): SyncedCharacterAttributeResult[] {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = 'SELECT attr_id, character_id, attribute_name, last_update FROM book_characters_attributes WHERE user_id = ?';
|
|
const params: SQLiteValue[] = [userId];
|
|
const syncedAttributes: SyncedCharacterAttributeResult[] = db.all(query, params) as SyncedCharacterAttributeResult[];
|
|
return syncedAttributes;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible de récupérer les attributs des personnages synchronisés.` : `Unable to retrieve synced character attributes.`);
|
|
} else {
|
|
console.error("An unknown error occurred.");
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inserts a synced character into the database.
|
|
* @param characterId - The unique identifier of the character
|
|
* @param bookId - The unique identifier of the book
|
|
* @param userId - The unique identifier of the user
|
|
* @param characterData - Object containing all character fields
|
|
* @param lastUpdate - The timestamp of the last update
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns True if the insertion was successful, false otherwise
|
|
*/
|
|
static insertSyncCharacter(characterId: string, bookId: string, userId: string, characterData: {
|
|
firstName: string;
|
|
lastName: string | null;
|
|
nickname: string | null;
|
|
age: string | null;
|
|
gender: string | null;
|
|
species: string | null;
|
|
nationality: string | null;
|
|
status: string | null;
|
|
category: string;
|
|
title: string | null;
|
|
image: string | null;
|
|
role: string | null;
|
|
biography: string | null;
|
|
history: string | null;
|
|
speechPattern: string | null;
|
|
catchphrase: string | null;
|
|
residence: string | null;
|
|
notes: string | null;
|
|
color: string | null;
|
|
}, lastUpdate: number, lang: 'fr' | 'en'): boolean {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = `INSERT INTO book_characters (
|
|
character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
|
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
|
|
const params: SQLiteValue[] = [
|
|
characterId, bookId, userId,
|
|
characterData.firstName, characterData.lastName, characterData.nickname,
|
|
characterData.age, characterData.gender, characterData.species,
|
|
characterData.nationality, characterData.status, characterData.category,
|
|
characterData.title, characterData.image, characterData.role,
|
|
characterData.biography, characterData.history, characterData.speechPattern,
|
|
characterData.catchphrase, characterData.residence, characterData.notes,
|
|
characterData.color, lastUpdate
|
|
];
|
|
const insertResult: RunResult = db.run(query, params);
|
|
return insertResult.changes > 0;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible d'insérer le personnage.` : `Unable to insert character.`);
|
|
} else {
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Inserts a synced character attribute into the database.
|
|
* @param attrId - The unique identifier of the attribute
|
|
* @param characterId - The unique identifier of the character
|
|
* @param userId - The unique identifier of the user
|
|
* @param attributeName - The name of the attribute
|
|
* @param attributeValue - The value of the attribute
|
|
* @param lastUpdate - The timestamp of the last update
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns True if the insertion was successful, false otherwise
|
|
*/
|
|
static insertSyncCharacterAttribute(attrId: string, characterId: string, userId: string, attributeName: string, attributeValue: string, lastUpdate: number, lang: 'fr' | 'en'): boolean {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = `INSERT INTO book_characters_attributes (attr_id, character_id, user_id, attribute_name, attribute_value, last_update)
|
|
VALUES (?, ?, ?, ?, ?, ?)`;
|
|
const params: SQLiteValue[] = [attrId, characterId, userId, attributeName, attributeValue, lastUpdate];
|
|
const insertResult: RunResult = db.run(query, params);
|
|
return insertResult.changes > 0;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
console.error(`DB Error: ${error.message}`);
|
|
throw new Error(lang === 'fr' ? `Impossible d'insérer l'attribut du personnage.` : `Unable to insert character attribute.`);
|
|
} else {
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches a complete character by its ID.
|
|
* @param id - The unique identifier of the character
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns A promise resolving to an array of book characters (typically one)
|
|
*/
|
|
static async fetchCompleteCharacterById(id: string, lang: "fr" | "en"): Promise<BookCharactersTable[]> {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = `SELECT character_id, book_id, user_id, first_name, last_name, nickname, age, gender, species, nationality, status,
|
|
category, title, image, role, biography, history, speech_pattern, catchphrase, residence, notes, color, last_update
|
|
FROM book_characters
|
|
WHERE character_id = ?`;
|
|
const params: SQLiteValue[] = [id];
|
|
const character: BookCharactersTable[] = db.all(query, params) as BookCharactersTable[];
|
|
return character;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
throw new Error(lang === 'fr' ? `Impossible de récupérer le personnage complet.` : `Unable to retrieve complete character.`);
|
|
} else {
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches a complete character attribute by its ID.
|
|
* @param id - The unique identifier of the attribute
|
|
* @param lang - The language for error messages ('fr' or 'en')
|
|
* @returns A promise resolving to an array of character attributes (typically one)
|
|
*/
|
|
static async fetchCompleteCharacterAttributeById(id: string, lang: "fr" | "en"): Promise<BookCharactersAttributesTable[]> {
|
|
try {
|
|
const db: Database = System.getDb();
|
|
const query: string = `SELECT attr_id, character_id, user_id, attribute_name, attribute_value, last_update
|
|
FROM book_characters_attributes
|
|
WHERE attr_id = ?`;
|
|
const params: SQLiteValue[] = [id];
|
|
const attribute: BookCharactersAttributesTable[] = db.all(query, params) as BookCharactersAttributesTable[];
|
|
return attribute;
|
|
} catch (error: unknown) {
|
|
if (error instanceof Error) {
|
|
throw new Error(lang === 'fr' ? `Impossible de récupérer l'attribut de personnage complet.` : `Unable to retrieve complete character attribute.`);
|
|
} else {
|
|
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
|
|
}
|
|
}
|
|
}
|
|
}
|