Update database schema and synchronization logic

- Add `useEffect` in `ScribeLeftBar` for handling book state changes.
- Extend `BooksSyncContext` with new properties and stricter typings.
- Refine `Repositories` to include `lastUpdate` handling for synchronization processes.
- Add comprehensive `fetchComplete*` repository methods for retrieving entity-specific sync data.
- Enhance offline logic for chapters, characters, locations, and world synchronization.
- Improve error handling across IPC handlers and repositories.
This commit is contained in:
natreex
2025-12-15 20:55:24 -05:00
parent bb331b5c22
commit 64c7cb6243
23 changed files with 1609 additions and 79 deletions

View File

@@ -43,6 +43,8 @@ import fs from "fs";
import Chapter, {ActChapter, ChapterContentData, ChapterProps} from "./Chapter.js";
import UserRepo from "../repositories/user.repository.js";
import ChapterRepo from "../repositories/chapter.repository.js";
import CharacterRepo from "../repositories/character.repository.js";
import LocationRepo from "../repositories/location.repository.js";
export interface BookProps{
id:string;
@@ -97,6 +99,26 @@ export interface SyncedBook {
aiGuideLine: SyncedAIGuideLine | null;
}
export interface BookSyncCompare {
id: string;
chapters: string[];
chapterContents: string[];
chapterInfos: string[];
characters: string[];
characterAttributes: string[];
locations: string[];
locationElements: string[];
locationSubElements: string[];
worlds: string[];
worldElements: string[];
incidents: string[];
plotPoints: string[];
issues: string[];
actSummaries: string[];
guideLine: boolean;
aiGuideLine: boolean;
}
export interface SyncedChapter {
id: string;
name: string;
@@ -617,7 +639,7 @@ export default class Book {
if (actId === 1 || actId === 4 || actId === 5) {
const actSummary: string = act.summary ? System.encryptDataWithUserKey(act.summary, userKey) : '';
try {
BookRepo.updateActSummary(userId, bookId, actId, actSummary,lang);
BookRepo.updateActSummary(userId, bookId, actId, actSummary,System.timeStampInSeconds(),lang);
} catch (e: unknown) {
const actSummaryId: string = System.createUniqueId();
BookRepo.insertActSummary(actSummaryId, userId, bookId, actId, actSummary,lang);
@@ -632,7 +654,7 @@ export default class Book {
const incidentName: string = incident.title;
const incidentHashedName: string = System.hashElement(incidentName);
const encryptedIncidentName: string = System.encryptDataWithUserKey(incidentName, userKey);
BookRepo.updateIncident(userId, bookId, incidentId, encryptedIncidentName, incidentHashedName, incidentSummary, lang);
BookRepo.updateIncident(userId, bookId, incidentId, encryptedIncidentName, incidentHashedName, incidentSummary, System.timeStampInSeconds(), lang);
if (incident.chapters) {
Chapter.updateChapterInfos(incident.chapters, userId, actId, bookId, incidentId, null, lang);
}
@@ -645,7 +667,7 @@ export default class Book {
const plotPointName: string = plotPoint.title;
const plotPointHashedName: string = System.hashElement(plotPointName);
const encryptedPlotPointName: string = System.encryptDataWithUserKey(plotPointName, userKey);
BookRepo.updatePlotPoint(userId, bookId, plotPointId, encryptedPlotPointName, plotPointHashedName, plotPointSummary, lang);
BookRepo.updatePlotPoint(userId, bookId, plotPointId, encryptedPlotPointName, plotPointHashedName, plotPointSummary, System.timeStampInSeconds(), lang);
if (plotPoint.chapters) {
Chapter.updateChapterInfos(plotPoint.chapters, userId, actId, bookId, null, plotPointId, lang);
}
@@ -664,7 +686,7 @@ export default class Book {
const chapterHashedTitle: string = System.hashElement(chapterTitle);
const encryptedTitle: string = System.encryptDataWithUserKey(chapterTitle, userKey);
const chapterOrder: number = chapter.chapterOrder;
ChapterRepo.updateChapter(userId, chapterId, encryptedTitle, chapterHashedTitle, chapterOrder, lang);
ChapterRepo.updateChapter(userId, chapterId, encryptedTitle, chapterHashedTitle, chapterOrder, System.timeStampInSeconds(), lang);
}
return true;
}
@@ -849,7 +871,7 @@ export default class Book {
}));
});
BookRepo.updateWorld(userId, world.id, encryptName, System.hashElement(world.name), encryptHistory, encryptPolitics, encryptEconomy, encryptReligion, encryptLanguages, lang);
BookRepo.updateWorld(userId, world.id, encryptName, System.hashElement(world.name), encryptHistory, encryptPolitics, encryptEconomy, encryptReligion, encryptLanguages, System.timeStampInSeconds(), lang);
return BookRepo.updateWorldElements(userId, elements, lang);
}
@@ -1466,4 +1488,450 @@ export default class Book {
return BookRepo.insertSyncIssue(issue.issue_id, userId, issue.book_id, encryptedIssueName, issue.hashed_issue_name, issue.last_update, lang);
});
}
static async getCompleteSyncBook(userId: string, data: BookSyncCompare, lang: "fr" | "en"):Promise<CompleteBook> {
const userKey: string = getUserEncryptionKey(userId);
const bookData: EritBooksTable[] = [];
const chaptersData: BookChaptersTable[] = [];
const plotPointsData: BookPlotPointsTable[] = [];
const incidentsData: BookIncidentsTable[] = [];
const chapterContentsData: BookChapterContentTable[] = [];
const chapterInfosData: BookChapterInfosTable[] = [];
const charactersData: BookCharactersTable[] = [];
const characterAttributesData: BookCharactersAttributesTable[] = [];
const locationsData: BookLocationTable[] = [];
const locationElementsData: LocationElementTable[] = [];
const locationSubElementsData: LocationSubElementTable[] = [];
const worldsData: BookWorldTable[] = [];
const worldElementsData: BookWorldElementsTable[] = [];
const actSummariesData: BookActSummariesTable[] = [];
const guideLineData: BookGuideLineTable[] = [];
const aiGuideLineData: BookAIGuideLineTable[] = [];
const issuesData: BookIssuesTable[] = [];
const actSummaries: string[] = data.actSummaries;
const chapters: string[] = data.chapters;
const plotPoints: string[] = data.plotPoints;
const incidents: string[] = data.incidents;
const chapterContents: string[] = data.chapterContents;
const chapterInfos: string[] = data.chapterInfos;
const characters: string[] = data.characters;
const characterAttributes: string[] = data.characterAttributes;
const locations: string[] = data.locations;
const locationElements: string[] = data.locationElements;
const locationSubElements: string[] = data.locationSubElements;
const worlds: string[] = data.worlds;
const worldElements: string[] = data.worldElements;
const issues: string[] = data.issues;
if (actSummaries && actSummaries.length > 0) {
for (const id of actSummaries) {
const actSummary: BookActSummariesTable[] = await BookRepo.fetchCompleteActSummaryById(id, lang);
if (actSummary.length>0) {
const actSummaryData: BookActSummariesTable = actSummary[0];
actSummariesData.push({
...actSummaryData,
summary: actSummaryData.summary ? System.decryptDataWithUserKey(actSummaryData.summary, userKey) : null
});
}
}
}
if (chapters && chapters.length > 0) {
for (const id of chapters) {
const chapter: BookChaptersTable[] = await BookRepo.fetchCompleteChapterById(id, lang);
if (chapter.length>0) {
const chapterData: BookChaptersTable = chapter[0];
chaptersData.push({
...chapterData,
title: System.decryptDataWithUserKey(chapterData.title, userKey)
});
}
}
}
if (plotPoints && plotPoints.length > 0) {
for (const id of plotPoints) {
const plotPoint: BookPlotPointsTable[] = await BookRepo.fetchCompletePlotPointById(id, lang);
if (plotPoint.length>0) {
const plotPointData: BookPlotPointsTable = plotPoint[0];
plotPointsData.push({
...plotPointData,
title: System.decryptDataWithUserKey(plotPointData.title, userKey),
summary: plotPointData.summary ? System.decryptDataWithUserKey(plotPointData.summary, userKey) : null
});
}
}
}
if (incidents && incidents.length > 0) {
for (const id of incidents) {
const incident: BookIncidentsTable[] = await BookRepo.fetchCompleteIncidentById(id, lang);
if (incident.length>0) {
const incidentData: BookIncidentsTable = incident[0];
incidentsData.push({
...incidentData,
title: System.decryptDataWithUserKey(incidentData.title, userKey),
summary: incidentData.summary ? System.decryptDataWithUserKey(incidentData.summary, userKey) : null
});
}
}
}
if (chapterContents && chapterContents.length > 0) {
for (const id of chapterContents) {
const chapterContent: BookChapterContentTable[] = await BookRepo.fetchCompleteChapterContentById(id, lang);
if (chapterContent.length>0) {
const chapterContentData: BookChapterContentTable = chapterContent[0];
chapterContentsData.push({
...chapterContentData,
content: chapterContentData.content ? JSON.parse(System.decryptDataWithUserKey(chapterContentData.content, userKey)) : null
});
}
}
}
if (chapterInfos && chapterInfos.length > 0) {
for (const id of chapterInfos) {
const chapterInfo: BookChapterInfosTable[] = await BookRepo.fetchCompleteChapterInfoById(id, lang);
if (chapterInfo.length>0) {
const chapterInfoData: BookChapterInfosTable = chapterInfo[0];
chapterInfosData.push({
...chapterInfoData,
summary: chapterInfoData.summary ? System.decryptDataWithUserKey(chapterInfoData.summary, userKey) : null,
goal: chapterInfoData.goal ? System.decryptDataWithUserKey(chapterInfoData.goal, userKey) : null
});
}
}
}
if (characters && characters.length > 0) {
for (const id of characters) {
const character: BookCharactersTable[] = await BookRepo.fetchCompleteCharacterById(id, lang);
if (character.length>0) {
const characterData: BookCharactersTable = character[0];
charactersData.push({
...characterData,
first_name: System.decryptDataWithUserKey(characterData.first_name, userKey),
last_name: characterData.last_name ? System.decryptDataWithUserKey(characterData.last_name, userKey) : null,
category: System.decryptDataWithUserKey(characterData.category, userKey),
title: characterData.title ? System.decryptDataWithUserKey(characterData.title, userKey) : null,
role: characterData.role ? System.decryptDataWithUserKey(characterData.role, userKey) : null,
biography: characterData.biography ? System.decryptDataWithUserKey(characterData.biography, userKey) : null,
history: characterData.history ? System.decryptDataWithUserKey(characterData.history, userKey) : null
});
}
}
}
if (characterAttributes && characterAttributes.length > 0) {
for (const id of characterAttributes) {
const characterAttribute: BookCharactersAttributesTable[] = await BookRepo.fetchCompleteCharacterAttributeById(id, lang);
if (characterAttribute.length>0) {
const characterAttributeData: BookCharactersAttributesTable = characterAttribute[0];
characterAttributesData.push({
...characterAttributeData,
attribute_name: System.decryptDataWithUserKey(characterAttributeData.attribute_name, userKey),
attribute_value: System.decryptDataWithUserKey(characterAttributeData.attribute_value, userKey)
});
}
}
}
if (locations && locations.length > 0) {
for (const id of locations) {
const location: BookLocationTable[] = await BookRepo.fetchCompleteLocationById(id, lang);
if (location.length>0) {
const locationData: BookLocationTable = location[0];
locationsData.push({
...locationData,
loc_name: System.decryptDataWithUserKey(locationData.loc_name, userKey)
});
}
}
}
if (locationElements && locationElements.length > 0) {
for (const id of locationElements) {
const locationElement: LocationElementTable[] = await BookRepo.fetchCompleteLocationElementById(id, lang);
if (locationElement.length>0) {
const locationElementData: LocationElementTable = locationElement[0];
locationElementsData.push({
...locationElementData,
element_name: System.decryptDataWithUserKey(locationElementData.element_name, userKey),
element_description: locationElementData.element_description ? System.decryptDataWithUserKey(locationElementData.element_description, userKey) : null
});
}
}
}
if (locationSubElements && locationSubElements.length > 0) {
for (const id of locationSubElements) {
const locationSubElement: LocationSubElementTable[] = await BookRepo.fetchCompleteLocationSubElementById(id, lang);
if (locationSubElement.length>0) {
const locationSubElementData: LocationSubElementTable = locationSubElement[0];
locationSubElementsData.push({
...locationSubElementData,
sub_elem_name: System.decryptDataWithUserKey(locationSubElementData.sub_elem_name, userKey),
sub_elem_description: locationSubElementData.sub_elem_description ? System.decryptDataWithUserKey(locationSubElementData.sub_elem_description, userKey) : null
});
}
}
}
if (worlds && worlds.length > 0) {
for (const id of worlds) {
const world: BookWorldTable[] = await BookRepo.fetchCompleteWorldById(id, lang);
if (world.length>0) {
const worldData: BookWorldTable = world[0];
worldsData.push({
...worldData,
name: System.decryptDataWithUserKey(worldData.name, userKey),
history: worldData.history ? System.decryptDataWithUserKey(worldData.history, userKey) : null,
politics: worldData.politics ? System.decryptDataWithUserKey(worldData.politics, userKey) : null,
economy: worldData.economy ? System.decryptDataWithUserKey(worldData.economy, userKey) : null,
religion: worldData.religion ? System.decryptDataWithUserKey(worldData.religion, userKey) : null,
languages: worldData.languages ? System.decryptDataWithUserKey(worldData.languages, userKey) : null
});
}
}
}
if (worldElements && worldElements.length > 0) {
for (const id of worldElements) {
const worldElement: BookWorldElementsTable[] = await BookRepo.fetchCompleteWorldElementById(id, lang);
if (worldElement.length>0) {
const worldElementData: BookWorldElementsTable = worldElement[0];
worldElementsData.push({
...worldElementData,
name: System.decryptDataWithUserKey(worldElementData.name, userKey),
description: worldElementData.description ? System.decryptDataWithUserKey(worldElementData.description, userKey) : null
});
}
}
}
if (issues && issues.length > 0) {
for (const id of issues) {
const issue: BookIssuesTable[] = await BookRepo.fetchCompleteIssueById(id, lang);
if (issue.length>0) {
const issueData: BookIssuesTable = issue[0];
issuesData.push({
...issueData,
name: System.decryptDataWithUserKey(issueData.name, userKey)
});
}
}
}
console.log(data.id)
const book: EritBooksTable[] = await BookRepo.fetchCompleteBookById(data.id, lang);
if (book.length>0) {
const bookDataItem: EritBooksTable = book[0];
bookData.push({
...bookDataItem,
title: System.decryptDataWithUserKey(bookDataItem.title, userKey),
sub_title: bookDataItem.sub_title ? System.decryptDataWithUserKey(bookDataItem.sub_title, userKey) : null,
summary: bookDataItem.summary ? System.decryptDataWithUserKey(bookDataItem.summary, userKey) : null,
cover_image: bookDataItem.cover_image ? System.decryptDataWithUserKey(bookDataItem.cover_image, userKey) : null
});
}
return {
eritBooks: bookData,
chapters: chaptersData,
plotPoints: plotPointsData,
incidents: incidentsData,
chapterContents: chapterContentsData,
chapterInfos: chapterInfosData,
characters: charactersData,
characterAttributes: characterAttributesData,
locations: locationsData,
locationElements: locationElementsData,
locationSubElements: locationSubElementsData,
worlds: worldsData,
worldElements: worldElementsData,
actSummaries: actSummariesData,
guideLine: guideLineData,
aiGuideLine: aiGuideLineData,
issues: issuesData
};
}
static async syncBookFromServerToClient(userId:string,completeBook: CompleteBook,lang:"fr"|"en"):Promise<boolean> {
const userKey: string = getUserEncryptionKey(userId);
const actSummaries: BookActSummariesTable[] = completeBook.actSummaries;
const chapters: BookChaptersTable[] = completeBook.chapters;
const plotPoints: BookPlotPointsTable[] = completeBook.plotPoints;
const incidents: BookIncidentsTable[] = completeBook.incidents;
const chapterContents: BookChapterContentTable[] = completeBook.chapterContents;
const chapterInfos: BookChapterInfosTable[] = completeBook.chapterInfos;
const characters: BookCharactersTable[] = completeBook.characters;
const characterAttributes: BookCharactersAttributesTable[] = completeBook.characterAttributes;
const locations: BookLocationTable[] = completeBook.locations;
const locationElements: LocationElementTable[] = completeBook.locationElements;
const locationSubElements: LocationSubElementTable[] = completeBook.locationSubElements;
const worlds: BookWorldTable[] = completeBook.worlds;
const worldElements: BookWorldElementsTable[] = completeBook.worldElements;
const issues: BookIssuesTable[] = completeBook.issues;
const bookId: string = completeBook.eritBooks.length > 0 ? completeBook.eritBooks[0].book_id : '';
if (actSummaries && actSummaries.length > 0) {
for (const actSummary of actSummaries) {
const summary: string = System.encryptDataWithUserKey(actSummary.summary ? actSummary.summary : '', userKey)
const updated: boolean = BookRepo.updateActSummary(userId, bookId, actSummary.act_index, summary, actSummary.last_update, lang);
if (!updated) {
return false;
}
}
}
if (chapters && chapters.length > 0) {
for (const chapter of chapters) {
const title: string = System.encryptDataWithUserKey(chapter.title, userKey)
const updated: boolean = ChapterRepo.updateChapter(userId, chapter.chapter_id, title, chapter.hashed_title, chapter.chapter_order, chapter.last_update, lang);
if (!updated) {
return false;
}
}
}
if (plotPoints && plotPoints.length > 0) {
for (const plotPoint of plotPoints) {
const title: string = System.encryptDataWithUserKey(plotPoint.title, userKey);
const summary: string = System.encryptDataWithUserKey(plotPoint.summary ? plotPoint.summary : '', userKey);
const updated: boolean = BookRepo.updatePlotPoint(userId, bookId, plotPoint.plot_point_id, title, plotPoint.hashed_title, summary, plotPoint.last_update,lang);
if (!updated) {
return false;
}
}
}
if (incidents && incidents.length > 0) {
for (const incident of incidents) {
const title: string = System.encryptDataWithUserKey(incident.title, userKey);
const summary: string = System.encryptDataWithUserKey(incident.summary ? incident.summary : '', userKey);
const updated: boolean = BookRepo.updateIncident(userId, bookId, incident.incident_id, title, incident.hashed_title, summary, incident.last_update, lang);
if (!updated) {
return false;
}
}
}
if (chapterContents && chapterContents.length > 0) {
for (const chapterContent of chapterContents) {
const content: string = System.encryptDataWithUserKey(chapterContent.content ? JSON.stringify(chapterContent.content) : '', userKey);
const updated: boolean = ChapterRepo.updateChapterContent(userId, chapterContent.chapter_id, chapterContent.version, content, chapterContent.words_count, chapterContent.last_update, lang);
if (!updated) {
return false;
}
}
}
if (chapterInfos && chapterInfos.length > 0) {
for (const chapterInfo of chapterInfos) {
const summary: string = System.encryptDataWithUserKey(chapterInfo.summary ? chapterInfo.summary : '', userKey);
const goal: string = System.encryptDataWithUserKey(chapterInfo.goal ? chapterInfo.goal : '', userKey);
const updated: boolean = ChapterRepo.updateChapterInfos(userId, chapterInfo.chapter_id, chapterInfo.act_id, bookId,chapterInfo.incident_id, chapterInfo.plot_point_id, summary, goal, chapterInfo.last_update, lang);
if (!updated) {
return false;
}
}
}
if (characters && characters.length > 0) {
for (const character of characters) {
const firstName: string = System.encryptDataWithUserKey(character.first_name, userKey);
const lastName: string = System.encryptDataWithUserKey(character.last_name ? character.last_name : '', userKey);
const category: string = System.encryptDataWithUserKey(character.category, userKey);
const title: string = System.encryptDataWithUserKey(character.title ? character.title : '', userKey);
const role: string = System.encryptDataWithUserKey(character.role ? character.role : '', userKey);
const biography: string = System.encryptDataWithUserKey(character.biography ? character.biography : '', userKey);
const history: string = System.encryptDataWithUserKey(character.history ? character.history : '', userKey);
const updated: boolean = CharacterRepo.updateCharacter(userId, character.character_id, firstName, lastName, title, category, character.image || '', role, biography, history, character.last_update, lang);
if (!updated) {
return false;
}
}
}
if (characterAttributes && characterAttributes.length > 0) {
for (const characterAttribute of characterAttributes) {
const attributeName: string = System.encryptDataWithUserKey(characterAttribute.attribute_name, userKey);
const attributeValue: string = System.encryptDataWithUserKey(characterAttribute.attribute_value, userKey);
const updated: boolean = CharacterRepo.updateCharacterAttribute(userId, characterAttribute.attr_id, attributeName, attributeValue, characterAttribute.last_update, lang);
if (!updated) {
return false;
}
}
}
if (locations && locations.length > 0) {
for (const location of locations) {
const locName: string = System.encryptDataWithUserKey(location.loc_name, userKey);
const updated: boolean = LocationRepo.updateLocationSection(userId, location.loc_id, locName, location.loc_original_name, location.last_update, lang);
if (!updated) {
return false;
}
}
}
if (locationElements && locationElements.length > 0) {
for (const locationElement of locationElements) {
const elementName: string = System.encryptDataWithUserKey(locationElement.element_name, userKey);
const elementDescription: string = System.encryptDataWithUserKey(locationElement.element_description ? locationElement.element_description : '', userKey);
const updated: boolean = LocationRepo.updateLocationElement(userId, locationElement.element_id, elementName,locationElement.original_name, elementDescription, locationElement.last_update, lang);
if (!updated) {
return false;
}
}
}
if (locationSubElements && locationSubElements.length > 0) {
for (const locationSubElement of locationSubElements) {
const subElemName: string = System.encryptDataWithUserKey(locationSubElement.sub_elem_name, userKey);
const subElemDescription: string = System.encryptDataWithUserKey(locationSubElement.sub_elem_description ? locationSubElement.sub_elem_description : '', userKey);
const updated: boolean = LocationRepo.updateLocationSubElement(userId, locationSubElement.sub_element_id, subElemName, locationSubElement.original_name, subElemDescription, locationSubElement.last_update, lang);
if (!updated) {
return false;
}
}
}
if (worlds && worlds.length > 0) {
for (const world of worlds) {
const name: string = System.encryptDataWithUserKey(world.name, userKey);
const history: string = System.encryptDataWithUserKey(world.history ? world.history : '', userKey);
const politics: string = System.encryptDataWithUserKey(world.politics ? world.politics : '', userKey);
const economy: string = System.encryptDataWithUserKey(world.economy ? world.economy : '', userKey);
const religion: string = System.encryptDataWithUserKey(world.religion ? world.religion : '', userKey);
const languages: string = System.encryptDataWithUserKey(world.languages ? world.languages : '', userKey);
const updated: boolean = BookRepo.updateWorld(userId, world.world_id, name, world.hashed_name, history, politics, economy, religion, languages, world.last_update, lang);
if (!updated) {
return false;
}
}
}
if (worldElements && worldElements.length > 0) {
for (const worldElement of worldElements) {
const name: string = System.encryptDataWithUserKey(worldElement.name, userKey);
const description: string = System.encryptDataWithUserKey(worldElement.description ? worldElement.description : '', userKey);
const updated: boolean = BookRepo.updateWorldElement(userId, worldElement.element_id, name, description, worldElement.last_update, lang);
if (!updated) {
return false;
}
}
}
if (issues && issues.length > 0) {
for (const issue of issues) {
const name: string = System.encryptDataWithUserKey(issue.name, userKey);
const updated: boolean = BookRepo.updateIssue(userId, bookId, issue.issue_id, name, issue.hashed_issue_name, issue.last_update, lang);
if (!updated) {
return false;
}
}
}
return true;
}
}

View File

@@ -149,7 +149,7 @@ export default class Chapter {
const response:string = await QS.request(prompt,'summary-chapter');
console.log(response);
}*/
return ChapterRepo.updateChapterContent(userId, chapterId, version, encryptContent, wordsCount, lang);
return ChapterRepo.updateChapterContent(userId, chapterId, version, encryptContent, wordsCount, System.timeStampInSeconds(), lang);
}
public static getLastChapter(userId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): ChapterProps | null {
@@ -200,7 +200,7 @@ export default class Chapter {
const hashedTitle: string = System.hashElement(title);
const userKey: string = getUserEncryptionKey(userId);
const encryptedTitle: string = System.encryptDataWithUserKey(title, userKey);
return ChapterRepo.updateChapter(userId, chapterId, encryptedTitle, hashedTitle, chapterOrder, lang);
return ChapterRepo.updateChapter(userId, chapterId, encryptedTitle, hashedTitle, chapterOrder, System.timeStampInSeconds(), lang);
}
static updateChapterInfos(chapters: ActChapter[], userId: string, actId: number, bookId: string, incidentId: string | null, plotId: string | null, lang: 'fr' | 'en' = 'fr') {
@@ -209,7 +209,7 @@ export default class Chapter {
const summary: string = chapter.summary ? System.encryptDataWithUserKey(chapter.summary, userKey) : '';
const goal: string = chapter.goal ? System.encryptDataWithUserKey(chapter.goal, userKey) : '';
const chapterId: string = chapter.chapterId;
ChapterRepo.updateChapterInfos(userId, chapterId, actId, bookId, incidentId, plotId, summary, goal, lang);
ChapterRepo.updateChapterInfos(userId, chapterId, actId, bookId, incidentId, plotId, summary, goal, System.timeStampInSeconds(), lang);
}
}

View File

@@ -9,7 +9,7 @@ import {getUserEncryptionKey} from "../keyManager.js";
export type CharacterCategory = 'Main' | 'Secondary' | 'Recurring';
export interface CharacterPropsPost {
id: number | null;
id: string | null;
name: string;
lastName: string;
category: CharacterCategory;
@@ -118,6 +118,9 @@ export default class Character {
static updateCharacter(userId: string, character: CharacterPropsPost, lang: 'fr' | 'en' = 'fr'): boolean {
const userKey: string = getUserEncryptionKey(userId);
if (!character.id) {
return false;
}
const encryptedName: string = System.encryptDataWithUserKey(character.name, userKey);
const encryptedLastName: string = System.encryptDataWithUserKey(character.lastName, userKey);
const encryptedTitle: string = System.encryptDataWithUserKey(character.title, userKey);
@@ -126,7 +129,7 @@ export default class Character {
const encryptedRole: string = System.encryptDataWithUserKey(character.role, userKey);
const encryptedBiography: string = System.encryptDataWithUserKey(character.biography ? character.biography : '', userKey);
const encryptedHistory: string = System.encryptDataWithUserKey(character.history ? character.history : '', userKey);
return CharacterRepo.updateCharacter(userId, character.id, encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, lang);
return CharacterRepo.updateCharacter(userId, character.id, encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, System.timeStampInSeconds(), lang);
}
static addNewAttribute(characterId: string, userId: string, type: string, name: string, lang: 'fr' | 'en' = 'fr'): string {

View File

@@ -118,17 +118,17 @@ export default class Location {
for (const location of locations) {
const originalName: string = System.hashElement(location.name);
const encryptedName: string = System.encryptDataWithUserKey(location.name, userKey);
LocationRepo.updateLocationSection(userId, location.id, encryptedName, originalName, lang)
LocationRepo.updateLocationSection(userId, location.id, encryptedName, originalName, System.timeStampInSeconds(),lang)
for (const element of location.elements) {
const originalName: string = System.hashElement(element.name);
const encryptedName: string = System.encryptDataWithUserKey(element.name, userKey);
const encryptDescription: string = element.description ? System.encryptDataWithUserKey(element.description, userKey) : '';
LocationRepo.updateLocationElement(userId, element.id, encryptedName, originalName, encryptDescription, lang)
LocationRepo.updateLocationElement(userId, element.id, encryptedName, originalName, encryptDescription, System.timeStampInSeconds(), lang)
for (const subElement of element.subElements) {
const originalName: string = System.hashElement(subElement.name);
const encryptedName: string = System.encryptDataWithUserKey(subElement.name, userKey);
const encryptDescription: string = subElement.description ? System.encryptDataWithUserKey(subElement.description, userKey) : '';
LocationRepo.updateLocationSubElement(userId, subElement.id, encryptedName, originalName, encryptDescription, lang)
LocationRepo.updateLocationSubElement(userId, subElement.id, encryptedName, originalName, encryptDescription,System.timeStampInSeconds(),lang)
}
}
}

View File

@@ -63,9 +63,9 @@ export interface BookChaptersTable extends Record<string, SQLiteValue> {
book_id: string;
author_id: string;
title: string;
hashed_title: string | null;
hashed_title: string;
words_count: number | null;
chapter_order: number | null;
chapter_order: number;
last_update: number;
}
@@ -83,7 +83,7 @@ export interface BookChapterContentTable extends Record<string, SQLiteValue> {
export interface BookChapterInfosTable extends Record<string, SQLiteValue> {
chapter_info_id: string;
chapter_id: string;
act_id: number | null;
act_id: number;
incident_id: string | null;
plot_point_id: string | null;
book_id: string;
@@ -626,10 +626,10 @@ export default class BookRepo {
}
}
public static updateActSummary(userId: string, bookId: string, actId: number, summary: string, lang: 'fr' | 'en'): boolean {
public static updateActSummary(userId: string, bookId: string, actId: number, summary: string, lastUpdate: number, lang: 'fr' | 'en'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE book_act_summaries SET summary=?, last_update=? WHERE user_id=? AND book_id=? AND act_sum_id=?', [summary, System.timeStampInSeconds(), userId, bookId, actId]);
const result: RunResult = db.run('UPDATE book_act_summaries SET summary=?, last_update=? WHERE user_id=? AND book_id=? AND act_sum_id=?', [summary, lastUpdate, userId, bookId, actId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
@@ -782,10 +782,10 @@ export default class BookRepo {
}
}
public static updateIncident(userId: string, bookId: string, incidentId: string, encryptedIncidentName: string, incidentHashedName: string, incidentSummary: string, lang: 'fr' | 'en'): boolean {
public static updateIncident(userId: string, bookId: string, incidentId: string, encryptedIncidentName: string, incidentHashedName: string, incidentSummary: string, lastUpdate: number, lang: 'fr' | 'en'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE book_incidents SET title=?, hashed_title=?, summary=?, last_update=? WHERE author_id=? AND book_id=? AND incident_id=?', [encryptedIncidentName, incidentHashedName, incidentSummary, System.timeStampInSeconds(), userId, bookId, incidentId]);
const result: RunResult = db.run('UPDATE book_incidents SET title=?, hashed_title=?, summary=?, last_update=? WHERE author_id=? AND book_id=? AND incident_id=?', [encryptedIncidentName, incidentHashedName, incidentSummary, lastUpdate, userId, bookId, incidentId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
@@ -798,10 +798,10 @@ export default class BookRepo {
}
}
public static updatePlotPoint(userId: string, bookId: string, plotPointId: string, encryptedPlotPointName: string, plotPointHashedName: string, plotPointSummary: string, lang: 'fr' | 'en'): boolean {
public static updatePlotPoint(userId: string, bookId: string, plotPointId: string, encryptedPlotPointName: string, plotPointHashedName: string, plotPointSummary: string, lastUpdate:number, lang: 'fr' | 'en'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE book_plot_points SET title=?, hashed_title=?, summary=?, last_update=? WHERE author_id=? AND book_id=? AND plot_point_id=?', [encryptedPlotPointName, plotPointHashedName, plotPointSummary, System.timeStampInSeconds(), userId, bookId, plotPointId]);
const result: RunResult = db.run('UPDATE book_plot_points SET title=?, hashed_title=?, summary=?, last_update=? WHERE author_id=? AND book_id=? AND plot_point_id=?', [encryptedPlotPointName, plotPointHashedName, plotPointSummary, lastUpdate, userId, bookId, plotPointId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
@@ -863,10 +863,10 @@ export default class BookRepo {
}
}
public static updateWorld(userId: string, worldId: string, encryptName: string, hashedName: string, encryptHistory: string, encryptPolitics: string, encryptEconomy: string, encryptReligion: string, encryptLanguages: string, lang: 'fr' | 'en'): boolean {
public static updateWorld(userId: string, worldId: string, encryptName: string, hashedName: string, encryptHistory: string, encryptPolitics: string, encryptEconomy: string, encryptReligion: string, encryptLanguages: string, lastUpdate: number, lang: 'fr' | 'en'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE book_world SET name=?, hashed_name=?, history=?, politics=?, economy=?, religion=?, languages=?, last_update=? WHERE author_id=? AND world_id=?', [encryptName, hashedName, encryptHistory, encryptPolitics, encryptEconomy, encryptReligion, encryptLanguages, System.timeStampInSeconds(), userId, worldId]);
const result: RunResult = db.run('UPDATE book_world SET name=?, hashed_name=?, history=?, politics=?, economy=?, religion=?, languages=?, last_update=? WHERE author_id=? AND world_id=?', [encryptName, hashedName, encryptHistory, encryptPolitics, encryptEconomy, encryptReligion, encryptLanguages, lastUpdate, userId, worldId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
@@ -1809,4 +1809,309 @@ export default class BookRepo {
}
}
}
static async fetchCompleteActSummaryById(id: string, lang: "fr" | "en"):Promise<BookActSummariesTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT act_sum_id, book_id, user_id, act_index, summary, last_update
FROM book_act_summaries
WHERE act_sum_id = ?`,
[id]
) as BookActSummariesTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer le résumé d'acte complet.` : `Unable to retrieve complete act summary.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteChapterById(id: string, lang: "fr" | "en"):Promise<BookChaptersTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT chapter_id, book_id, author_id, title, hashed_title, words_count, chapter_order, last_update
FROM book_chapters
WHERE chapter_id = ?`,
[id]
) as BookChaptersTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer le chapitre complet.` : `Unable to retrieve complete chapter.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompletePlotPointById(id: string, lang: "fr" | "en"):Promise<BookPlotPointsTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT plot_point_id, title, hashed_title, summary, linked_incident_id, author_id, book_id, last_update
FROM book_plot_points
WHERE plot_point_id = ?`,
[id]
) as BookPlotPointsTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer le point d'intrigue complet.` : `Unable to retrieve complete plot point.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteIncidentById(id: string, lang: "fr" | "en"):Promise<BookIncidentsTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT incident_id, author_id, book_id, title, hashed_title, summary, last_update
FROM book_incidents
WHERE incident_id = ?`,
[id]
) as BookIncidentsTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer l'incident complet.` : `Unable to retrieve complete incident.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteChapterContentById(id: string, lang: "fr" | "en"):Promise<BookChapterContentTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT content_id, chapter_id, author_id, version, content, words_count, time_on_it, last_update
FROM book_chapter_content
WHERE content_id = ?`,
[id]
) as BookChapterContentTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer le contenu de chapitre complet.` : `Unable to retrieve complete chapter content.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteChapterInfoById(id: string, lang: "fr" | "en"):Promise<BookChapterInfosTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT chapter_info_id, chapter_id, act_id, incident_id, plot_point_id, book_id, author_id, summary, goal, last_update
FROM book_chapter_infos
WHERE chapter_info_id = ?`,
[id]
) as BookChapterInfosTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer les informations de chapitre complètes.` : `Unable to retrieve complete chapter info.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteCharacterById(id: string, lang: "fr" | "en"):Promise<BookCharactersTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT character_id, book_id, user_id, first_name, last_name, category, title, image, role, biography, history, last_update
FROM book_characters
WHERE character_id = ?`,
[id]
) as BookCharactersTable[];
} catch (e:unknown){
if (e 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.");
}
}
}
static async fetchCompleteCharacterAttributeById(id: string, lang: "fr" | "en"):Promise<BookCharactersAttributesTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT attr_id, character_id, user_id, attribute_name, attribute_value, last_update
FROM book_characters_attributes
WHERE attr_id = ?`,
[id]
) as BookCharactersAttributesTable[];
} catch (e:unknown){
if (e 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.");
}
}
}
static async fetchCompleteLocationById(id: string, lang: "fr" | "en"):Promise<BookLocationTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT loc_id, book_id, user_id, loc_name, loc_original_name, last_update
FROM book_location
WHERE loc_id = ?`,
[id]
) as BookLocationTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer le lieu complet.` : `Unable to retrieve complete location.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteLocationElementById(id: string, lang: "fr" | "en"):Promise<LocationElementTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT element_id, location, user_id, element_name, original_name, element_description, last_update
FROM location_element
WHERE element_id = ?`,
[id]
) as LocationElementTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer l'élément de lieu complet.` : `Unable to retrieve complete location element.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteLocationSubElementById(id: string, lang: "fr" | "en"):Promise<LocationSubElementTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT sub_element_id, element_id, user_id, sub_elem_name, original_name, sub_elem_description, last_update
FROM location_sub_element
WHERE sub_element_id = ?`,
[id]
) as LocationSubElementTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer le sous-élément de lieu complet.` : `Unable to retrieve complete location sub-element.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteWorldById(id: string, lang: "fr" | "en"):Promise<BookWorldTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT world_id, name, hashed_name, author_id, book_id, history, politics, economy, religion, languages, last_update
FROM book_world
WHERE world_id = ?`,
[id]
) as BookWorldTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer le monde complet.` : `Unable to retrieve complete world.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteWorldElementById(id: string, lang: "fr" | "en"):Promise<BookWorldElementsTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT element_id, world_id, user_id, element_type, name, original_name, description, last_update
FROM book_world_elements
WHERE element_id = ?`,
[id]
) as BookWorldElementsTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer l'élément de monde complet.` : `Unable to retrieve complete world element.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteIssueById(id: string, lang: "fr" | "en"):Promise<BookIssuesTable[]> {
try {
const db: Database = System.getDb();
return db.all(
`SELECT issue_id, author_id, book_id, name, hashed_issue_name, last_update
FROM book_issues
WHERE issue_id = ?`,
[id]
) as BookIssuesTable[];
} catch (e:unknown){
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer le problème complet.` : `Unable to retrieve complete issue.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static async fetchCompleteBookById(bookId: string, lang: "fr" | "en") {
try {
const db: Database = System.getDb();
return db.all(
`SELECT * FROM erit_books
WHERE book_id = ?`,
[bookId]
) as EritBooksTable[];
} catch (e: unknown) {
if (e instanceof Error) {
throw new Error(lang === 'fr' ? `Impossible de récupérer le livre complet.` : `Unable to retrieve complete book.`);
} else {
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static updateWorldElement(userId: string, elementId: string, name: string, description: string, lastUpdate: number,lang: "fr" | "en"):boolean {
try {
const db: Database = System.getDb();
const query:string = `UPDATE book_world_elements SET name = ?, description = ?, last_update = FROM_UNIXTIME(?) WHERE element_id = UUID_TO_BIN(?) AND user_id = UUID_TO_BIN(?)`;
const params:(string|number)[] = [name, description, lastUpdate, elementId, userId];
const result:RunResult = db.run(query, params);
return result.changes > 0;
} catch (e:unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
throw new Error(lang === 'fr' ? `Impossible de mettre à jour l'élément du monde.` : `Unable to update world element.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
static updateIssue(userId: string, bookId: string, issueId: string, name: string, hashedName: string, lastUpdate: number, lang: "fr" | "en"):boolean {
try {
const db: Database = System.getDb();
const query:string = `UPDATE book_issues SET name = ?, hashed_issue_name = ?, last_update = FROM_UNIXTIME(?) WHERE issue_id = UUID_TO_BIN(?) AND author_id = UUID_TO_BIN(?) AND book_id = UUID_TO_BIN(?)`;
const params:(string|number)[] = [name, hashedName, lastUpdate, issueId, userId, bookId];
const result:RunResult = db.run(query, params);
return result.changes > 0;
} catch (e:unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.message}`);
throw new Error(lang === 'fr' ? `Impossible de mettre à jour la problématique.` : `Unable to update issue.`);
} else {
console.error("An unknown error occurred.");
throw new Error(lang === 'fr' ? "Une erreur inconnue s'est produite." : "An unknown error occurred.");
}
}
}
}

View File

@@ -212,10 +212,10 @@ export default class ChapterRepo{
return chapterInfoId;
}
public static updateChapter(userId: string, chapterId: string, encryptedTitle: string, hashTitle: string, chapterOrder: number, lang: 'fr' | 'en' = 'fr'): boolean {
public static updateChapter(userId: string, chapterId: string, encryptedTitle: string, hashTitle: string, chapterOrder: number, lastUpdate:number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE book_chapters SET title=?, hashed_title=?, chapter_order=?, last_update=? WHERE author_id=? AND chapter_id=?', [encryptedTitle, hashTitle, chapterOrder, System.timeStampInSeconds(), userId, chapterId]);
const result: RunResult = db.run('UPDATE book_chapters SET title=?, hashed_title=?, chapter_order=?, last_update=? WHERE author_id=? AND chapter_id=?', [encryptedTitle, hashTitle, chapterOrder, lastUpdate, userId, chapterId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
@@ -228,16 +228,17 @@ export default class ChapterRepo{
}
}
public static updateChapterInfos(userId: string, chapterId: string, actId: number, bookId: string, incidentId: string | null, plotId: string | null, summary: string, goal: string | null, lang: 'fr' | 'en' = 'fr'): boolean {
public static updateChapterInfos(userId: string, chapterId: string, actId: number, bookId: string, incidentId: string | null, plotId: string | null, summary: string, goal: string | null, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
let sql: string = `UPDATE book_chapter_infos
SET summary=?,
goal=?
goal=?,
last_update=?
WHERE chapter_id = ?
AND act_id = ?
AND book_id = ?`;
const params: any[] = [summary, goal, chapterId, actId, bookId];
const params: any[] = [summary, goal, lastUpdate, chapterId, actId, bookId];
if (incidentId) {
sql += ` AND incident_id=?`;
params.push(incidentId);
@@ -265,15 +266,15 @@ export default class ChapterRepo{
}
}
public static updateChapterContent(userId: string, chapterId: string, version: number, encryptContent: string, wordsCount: number, lang: 'fr' | 'en' = 'fr'): boolean {
public static updateChapterContent(userId: string, chapterId: string, version: number, encryptContent: string, wordsCount: number, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE book_chapter_content SET content=?, words_count=?, last_update=? WHERE chapter_id=? AND author_id=? AND version=?', [encryptContent, wordsCount, System.timeStampInSeconds(), chapterId, userId, version]);
const result: RunResult = db.run('UPDATE book_chapter_content SET content=?, words_count=?, last_update=? WHERE chapter_id=? AND author_id=? AND version=?', [encryptContent, wordsCount, lastUpdate, chapterId, userId, version]);
if (result.changes > 0) {
return true;
} else {
const contentId:string = System.createUniqueId();
const insertResult: RunResult = db.run('INSERT INTO book_chapter_content (content_id,chapter_id, author_id, version, content, words_count, last_update) VALUES (?,?,?,?,?,?,?)', [contentId, chapterId, userId, version, encryptContent, wordsCount, System.timeStampInSeconds()]);
const insertResult: RunResult = db.run('INSERT INTO book_chapter_content (content_id,chapter_id, author_id, version, content, words_count, last_update) VALUES (?,?,?,?,?,?,?)', [contentId, chapterId, userId, version, encryptContent, wordsCount, lastUpdate]);
return insertResult.changes > 0;
}
} catch (e: unknown) {

View File

@@ -90,10 +90,10 @@ export default class CharacterRepo {
return attributeId;
}
static updateCharacter(userId: string, id: number | null, encryptedName: string, encryptedLastName: string, encryptedTitle: string, encryptedCategory: string, encryptedImage: string, encryptedRole: string, encryptedBiography: string, encryptedHistory: string, lang: 'fr' | 'en' = 'fr'): boolean {
static updateCharacter(userId: string, id: string, encryptedName: string, encryptedLastName: string, encryptedTitle: string, encryptedCategory: string, encryptedImage: string, encryptedRole: string, encryptedBiography: string, encryptedHistory: string, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE `book_characters` SET `first_name`=?,`last_name`=?,`title`=?,`category`=?,`image`=?,`role`=?,`biography`=?,`history`=?,`last_update`=? WHERE `character_id`=? AND `user_id`=?', [encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, System.timeStampInSeconds(), id, userId]);
const result: RunResult = db.run('UPDATE `book_characters` SET `first_name`=?,`last_name`=?,`title`=?,`category`=?,`image`=?,`role`=?,`biography`=?,`history`=?,`last_update`=? WHERE `character_id`=? AND `user_id`=?', [encryptedName, encryptedLastName, encryptedTitle, encryptedCategory, encryptedImage, encryptedRole, encryptedBiography, encryptedHistory, lastUpdate, id, userId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
@@ -165,4 +165,19 @@ export default class CharacterRepo {
}
return result;
}
static updateCharacterAttribute(userId: string, characterAttributeId: string, attributeName: string, attributeValue: string, lastUpdate: number,lang: "fr" | "en"):boolean {
try {
const db: Database = System.getDb();
const result:RunResult = db.run('UPDATE `book_characters_attributes` SET `attribute_name`=?,`attribute_value`=?, last_update=FROM_UNIXTIME(?) WHERE `attr_id`=UUID_TO_BIN(?) AND `user_id`=UUID_TO_BIN(?)', [attributeName, attributeValue, lastUpdate, characterAttributeId, userId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`DB Error: ${e.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.");
}
}
}
}

View File

@@ -107,10 +107,10 @@ export default class LocationRepo {
return subElementId;
}
static updateLocationSubElement(userId: string, id: string, encryptedName: string, originalName: string, encryptDescription: string, lang: 'fr' | 'en' = 'fr'): boolean {
static updateLocationSubElement(userId: string, id: string, encryptedName: string, originalName: string, encryptDescription: string, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE location_sub_element SET sub_elem_name=?, original_name=?, sub_elem_description=?, last_update=? WHERE sub_element_id=? AND user_id=?', [encryptedName, originalName, encryptDescription, System.timeStampInSeconds(), id, userId]);
const result: RunResult = db.run('UPDATE location_sub_element SET sub_elem_name=?, original_name=?, sub_elem_description=?, last_update=? WHERE sub_element_id=? AND user_id=?', [encryptedName, originalName, encryptDescription, lastUpdate, id, userId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
@@ -123,10 +123,10 @@ export default class LocationRepo {
}
}
static updateLocationElement(userId: string, id: string, encryptedName: string, originalName: string, encryptedDescription: string, lang: 'fr' | 'en' = 'fr'): boolean {
static updateLocationElement(userId: string, id: string, encryptedName: string, originalName: string, encryptedDescription: string, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE location_element SET element_name=?, original_name=?, element_description=?, last_update=? WHERE element_id=? AND user_id=?', [encryptedName, originalName, encryptedDescription, System.timeStampInSeconds(), id, userId]);
const result: RunResult = db.run('UPDATE location_element SET element_name=?, original_name=?, element_description=?, last_update=? WHERE element_id=? AND user_id=?', [encryptedName, originalName, encryptedDescription, lastUpdate, id, userId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {
@@ -139,10 +139,10 @@ export default class LocationRepo {
}
}
static updateLocationSection(userId: string, id: string, encryptedName: string, originalName: string, lang: 'fr' | 'en' = 'fr'): boolean {
static updateLocationSection(userId: string, id: string, encryptedName: string, originalName: string, lastUpdate: number, lang: 'fr' | 'en' = 'fr'): boolean {
try {
const db: Database = System.getDb();
const result: RunResult = db.run('UPDATE book_location SET loc_name=?, loc_original_name=?, last_update=? WHERE loc_id=? AND user_id=?', [encryptedName, originalName, System.timeStampInSeconds(), id, userId]);
const result: RunResult = db.run('UPDATE book_location SET loc_name=?, loc_original_name=?, last_update=? WHERE loc_id=? AND user_id=?', [encryptedName, originalName, lastUpdate, id, userId]);
return result.changes > 0;
} catch (e: unknown) {
if (e instanceof Error) {