UNPKG

@mieweb/wikigdrive

Version:

Google Drive to MarkDown synchronization

134 lines (113 loc) 4.38 kB
import WebSocket from 'ws'; import {ContainerEngine} from '../../ContainerEngine.ts'; import {DriveJobs, JobManagerContainer, Toast} from '../job/JobManagerContainer.ts'; import {FileId} from '../../model/model.ts'; import {GoogleFile} from '../../model/GoogleFile.ts'; import {WatchChangesContainer} from '../changes/WatchChangesContainer.ts'; import {FileContentService} from '../../utils/FileContentService.ts'; import {MarkdownTreeProcessor} from '../transform/MarkdownTreeProcessor.ts'; import {UserConfigService} from '../google_folder/UserConfigService.ts'; import {getContentFileService} from '../transform/utils.ts'; export class SocketManager { socketsMap: {[driveId: string]: Set<WebSocket.WebSocket>} = {}; private fileService: FileContentService; constructor(private engine: ContainerEngine) { this.engine.subscribe('jobs:changed', (driveId, driveJobs: DriveJobs) => { this.onJobsChanged(driveId, driveJobs); }); this.engine.subscribe('toasts:added', (driveId, toast: Toast) => { this.onToastsAdded(driveId, toast); }); this.engine.subscribe('changes:changed', (driveId, changes: GoogleFile[]) => { this.onChangesChanged(driveId, changes); }); } async mount(fileService: FileContentService) { this.fileService = fileService; } async addSocketConnection(ws: WebSocket.WebSocket, driveId: string) { if (!this.socketsMap[driveId]) { this.socketsMap[driveId] = new Set<WebSocket.WebSocket>(); } this.socketsMap[driveId].add(ws); ws.send(JSON.stringify({ cmd: 'connected' })); const jobManagerContainer = <JobManagerContainer>this.engine.getContainer('job_manager'); const driveJobs = await jobManagerContainer.inspect(driveId); ws.send(JSON.stringify({ cmd: 'jobs:changed', payload: driveJobs })); if (this.engine.hasContainer('watch_changes')) { const watchChangesContainer = <WatchChangesContainer>this.engine.getContainer('watch_changes'); const changes = await watchChangesContainer.getChanges(driveId); const filteredChanges = await this.getFilteredChanges(driveId, changes); ws.send(JSON.stringify({ cmd: 'changes:changed', payload: filteredChanges })); } ws.on('close', () => { this.socketsMap[driveId].delete(ws); }); } private onToastsAdded(driveId: FileId, toast: Toast) { if (!this.socketsMap[driveId]) { return; } for (const socket of this.socketsMap[driveId]) { socket.send(JSON.stringify({ cmd: 'toasts:added', payload: toast })); } } private onJobsChanged(driveId: FileId, driveJobs: DriveJobs) { if (!this.socketsMap[driveId]) { return; } for (const socket of this.socketsMap[driveId]) { socket.send(JSON.stringify({ cmd: 'jobs:changed', payload: driveJobs })); } } async getFilteredChanges(driveId: FileId, changes: GoogleFile[]): Promise<GoogleFile[]> { let filteredChanges = []; const googleFileSystem = await this.fileService.getSubFileService(driveId, ''); const userConfigService = new UserConfigService(googleFileSystem); await userConfigService.load(); const transformedFileSystem = await this.fileService.getSubFileService(driveId + '_transform', ''); const contentFileService = await getContentFileService(transformedFileSystem, userConfigService); const markdownTreeProcessor = new MarkdownTreeProcessor(contentFileService); await markdownTreeProcessor.load(); if (!markdownTreeProcessor.isEmpty()) { for (const change of changes) { const fileId = change.id; const [file, drivePath] = await markdownTreeProcessor.findById(fileId); if (file && drivePath) { if (file.modifiedTime !== change.modifiedTime) { filteredChanges.push(change); } } } } else { filteredChanges = changes; } return filteredChanges; } private async onChangesChanged(driveId: FileId, changes: GoogleFile[]) { if (!this.socketsMap[driveId]) { return; } const filteredChanges = await this.getFilteredChanges(driveId, changes); for (const socket of this.socketsMap[driveId]) { socket.send(JSON.stringify({ cmd: 'changes:changed', payload: filteredChanges })); } } }