- Implemented syncing for `GuideLine` and `AIGuideLine` entities with encryption and decryption workflows. - Refined `GuidelineRepo` methods to check existence and update/insert records for both guideline types. - Updated timestamp handling in `GuideLine` and `AIGuideLine` models for accurate tracking. - Corrected QuillSense localization keys for labels and descriptions. - Improved database queries and modularized logic for consistency.
184 lines
8.4 KiB
TypeScript
184 lines
8.4 KiB
TypeScript
import { getUserEncryptionKey } from "../keyManager.js";
|
|
import System from "../System.js";
|
|
import PlotPoint, { PlotPointProps, PlotPointStory } from "./PlotPoint.js";
|
|
import Incident, { IncidentProps, IncidentStory } from "./Incident.js";
|
|
import ActRepository, { ActQuery } from "../repositories/act.repository.js";
|
|
import Chapter, { ChapterProps } from "./Chapter.js";
|
|
import IncidentRepository from "../repositories/incident.repository.js";
|
|
import PlotPointRepository from "../repositories/plotpoint.repository.js";
|
|
import ChapterRepo from "../repositories/chapter.repository.js";
|
|
|
|
export interface ActProps {
|
|
id: number;
|
|
summary: string | null;
|
|
incidents?: IncidentProps[];
|
|
plotPoints?: PlotPointProps[];
|
|
chapters?: ActChapter[];
|
|
}
|
|
|
|
export interface ActStory {
|
|
actId: number;
|
|
summary: string;
|
|
chapterSummary: string;
|
|
chapterGoal: string;
|
|
incidents: IncidentStory[];
|
|
plotPoints: PlotPointStory[];
|
|
}
|
|
|
|
export interface ActChapter {
|
|
chapterInfoId: number;
|
|
chapterId: string;
|
|
title: string;
|
|
chapterOrder: number;
|
|
actId: number;
|
|
incidentId: string | null;
|
|
plotPointId: string | null;
|
|
summary: string;
|
|
goal: string;
|
|
}
|
|
|
|
export interface SyncedActSummary {
|
|
id: string;
|
|
lastUpdate: number;
|
|
}
|
|
|
|
export default class Act {
|
|
/**
|
|
* Retrieves all acts data for a specific book, including chapters, incidents, and plot points.
|
|
* Decrypts summaries using the user's encryption key.
|
|
* @param userId - The unique identifier of the user
|
|
* @param bookId - The unique identifier of the book
|
|
* @param lang - The language for localization ('fr' or 'en'), defaults to 'fr'
|
|
* @returns A promise resolving to an array of Act objects with their associated data
|
|
*/
|
|
public static async getActsData(userId: string, bookId: string, lang: 'fr' | 'en' = 'fr'): Promise<ActProps[]> {
|
|
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
|
const actChapters: ActChapter[] = Chapter.getAllChapterFromActs(userId, bookId, lang);
|
|
const actQueries: ActQuery[] = ActRepository.fetchAllActs(userId, bookId, lang);
|
|
const bookIncidents: IncidentProps[] = await Incident.getIncitentsIncidents(userId, bookId, actChapters);
|
|
const bookPlotPoints: PlotPointProps[] = await PlotPoint.getPlotPoints(userId, bookId, actChapters);
|
|
|
|
const acts: ActProps[] = [];
|
|
|
|
acts.push({
|
|
id: 1,
|
|
summary: '',
|
|
chapters: actChapters.filter((chapter: ActChapter) => chapter.actId === 1)
|
|
});
|
|
|
|
acts.push({
|
|
id: 2,
|
|
summary: '',
|
|
incidents: bookIncidents ? bookIncidents : [],
|
|
});
|
|
|
|
acts.push({
|
|
id: 3,
|
|
summary: '',
|
|
plotPoints: bookPlotPoints ? bookPlotPoints : [],
|
|
});
|
|
|
|
acts.push({
|
|
id: 4,
|
|
summary: '',
|
|
chapters: actChapters.filter((chapter: ActChapter) => chapter.actId === 4)
|
|
});
|
|
|
|
acts.push({
|
|
id: 5,
|
|
summary: '',
|
|
chapters: actChapters.filter((chapter: ActChapter) => chapter.actId === 5)
|
|
});
|
|
|
|
if (actQueries.length > 0) {
|
|
for (const actQuery of actQueries) {
|
|
acts[actQuery.act_index - 1].summary = actQuery.summary && userEncryptionKey
|
|
? System.decryptDataWithUserKey(actQuery.summary, userEncryptionKey)
|
|
: '';
|
|
}
|
|
}
|
|
|
|
return acts;
|
|
}
|
|
|
|
/**
|
|
* Updates multiple acts including their summaries, incidents, plot points, and chapter information.
|
|
* Encrypts all sensitive data before storing in the database.
|
|
* @param acts - Array of act properties to update
|
|
* @param userId - The unique identifier of the user
|
|
* @param bookId - The unique identifier of the book
|
|
* @param userKey - The user's encryption key for data encryption
|
|
* @param lang - The language for localization ('fr' or 'en'), defaults to 'fr'
|
|
* @returns A promise resolving to true when all updates are complete
|
|
*/
|
|
public static async updateAct(acts: ActProps[], userId: string, bookId: string, userKey: string, lang: 'fr' | 'en' = 'fr'): Promise<boolean> {
|
|
for (const act of acts) {
|
|
const actIncidents: IncidentProps[] = act.incidents ? act.incidents : [];
|
|
const actId: number = act.id;
|
|
|
|
if (actId === 1 || actId === 4 || actId === 5) {
|
|
const encryptedActSummary: string = act.summary ? System.encryptDataWithUserKey(act.summary, userKey) : '';
|
|
try {
|
|
ActRepository.updateActSummary(userId, bookId, actId, encryptedActSummary, System.timeStampInSeconds(), lang);
|
|
} catch (error: unknown) {
|
|
const newActSummaryId: string = System.createUniqueId();
|
|
ActRepository.insertActSummary(newActSummaryId, userId, bookId, actId, encryptedActSummary, lang);
|
|
}
|
|
if (act.chapters) {
|
|
Chapter.updateChapterInfos(act.chapters, userId, actId, bookId, null, null, lang);
|
|
}
|
|
} else if (actId === 2) {
|
|
for (const incident of actIncidents) {
|
|
const encryptedIncidentSummary: string = incident.summary ? System.encryptDataWithUserKey(incident.summary, userKey) : '';
|
|
const incidentId: string = incident.incidentId;
|
|
const incidentTitle: string = incident.title;
|
|
const hashedIncidentTitle: string = System.hashElement(incidentTitle);
|
|
const encryptedIncidentTitle: string = System.encryptDataWithUserKey(incidentTitle, userKey);
|
|
IncidentRepository.updateIncident(userId, bookId, incidentId, encryptedIncidentTitle, hashedIncidentTitle, encryptedIncidentSummary, System.timeStampInSeconds(), lang);
|
|
if (incident.chapters) {
|
|
Chapter.updateChapterInfos(incident.chapters, userId, actId, bookId, incidentId, null, lang);
|
|
}
|
|
}
|
|
} else {
|
|
const actPlotPoints: PlotPointProps[] = act.plotPoints ? act.plotPoints : [];
|
|
for (const plotPoint of actPlotPoints) {
|
|
const encryptedPlotPointSummary: string = plotPoint.summary ? System.encryptDataWithUserKey(plotPoint.summary, userKey) : '';
|
|
const plotPointId: string = plotPoint.plotPointId;
|
|
const plotPointTitle: string = plotPoint.title;
|
|
const hashedPlotPointTitle: string = System.hashElement(plotPointTitle);
|
|
const encryptedPlotPointTitle: string = System.encryptDataWithUserKey(plotPointTitle, userKey);
|
|
PlotPointRepository.updatePlotPoint(userId, bookId, plotPointId, encryptedPlotPointTitle, hashedPlotPointTitle, encryptedPlotPointSummary, System.timeStampInSeconds(), lang);
|
|
if (plotPoint.chapters) {
|
|
Chapter.updateChapterInfos(plotPoint.chapters, userId, actId, bookId, null, plotPointId, lang);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Updates the story structure including acts and main chapters.
|
|
* Encrypts chapter titles and updates their order in the database.
|
|
* @param userId - The unique identifier of the user
|
|
* @param bookId - The unique identifier of the book
|
|
* @param acts - Array of act properties to update
|
|
* @param mainChapters - Array of main chapter properties to update
|
|
* @param lang - The language for localization ('fr' or 'en'), defaults to 'fr'
|
|
* @returns True when all updates are complete
|
|
*/
|
|
public static updateStory(userId: string, bookId: string, acts: ActProps[], mainChapters: ChapterProps[], lang: 'fr' | 'en' = 'fr'): boolean {
|
|
const userEncryptionKey: string = getUserEncryptionKey(userId);
|
|
Act.updateAct(acts, userId, bookId, userEncryptionKey, lang).then();
|
|
|
|
for (const chapter of mainChapters) {
|
|
const chapterId: string = chapter.chapterId;
|
|
const chapterTitle: string = chapter.title;
|
|
const chapterOrder: number = chapter.chapterOrder;
|
|
Chapter.updateChapter(userId, chapterId, chapterTitle, chapterOrder, lang);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|