@mieweb/wikigdrive
Version:
Google Drive to MarkDown synchronization
128 lines (106 loc) • 4.87 kB
text/typescript
import winston from 'winston';
import {Container, ContainerConfig, ContainerConfigArr, ContainerEngine} from '../../ContainerEngine.ts';
import {GoogleDriveService} from '../../google/GoogleDriveService.ts';
import {GoogleApiContainer} from '../google_api/GoogleApiContainer.ts';
import {QueueDownloader} from './QueueDownloader.ts';
import {TaskFetchFolder} from './TaskFetchFolder.ts';
import {MimeTypes} from '../../model/GoogleFile.ts';
import {DateISO, FileId} from '../../model/model.ts';
import {FolderRegistryContainer} from '../folder_registry/FolderRegistryContainer.ts';
import {GoogleTreeProcessor} from './GoogleTreeProcessor.ts';
import {HasAccessToken} from '../../google/AuthClient.ts';
import {UserConfigService} from './UserConfigService.ts';
const __filename = import.meta.filename;
export interface GoogleTreeItem {
id: FileId;
name: string;
mimeType: string;
parentId: FileId;
version: string;
modifiedTime?: DateISO;
children?: GoogleTreeItem[];
}
export class GoogleFolderContainer extends Container {
private logger: winston.Logger;
private googleDriveService: GoogleDriveService;
private auth: HasAccessToken;
private filterFilesIds: FileId[];
private forceDownloadFilters: boolean;
private progressNotifyCallback: ({total, completed}: { total?: number; completed?: number; failed?: number }) => void;
constructor(public readonly params: ContainerConfig, public readonly paramsArr: ContainerConfigArr = {}) {
super(params, paramsArr);
this.filterFilesIds = paramsArr['filesIds'] || [];
this.forceDownloadFilters = false;
}
setForceDownloadFilters(value: boolean) {
this.forceDownloadFilters = value;
}
async init(engine: ContainerEngine): Promise<void> {
await super.init(engine);
this.logger = engine.logger.child({ filename: __filename, driveId: this.params.name, jobId: this.params.jobId });
const googleApiContainer: GoogleApiContainer = <GoogleApiContainer>this.engine.getContainer('google_api');
this.googleDriveService = new GoogleDriveService(this.logger, googleApiContainer.getQuotaLimiter());
this.auth = googleApiContainer.getAuth();
}
// eslint-disable-next-line @typescript-eslint/no-empty-function
async destroy(): Promise<void> {
}
async run() {
const downloader = new QueueDownloader(this.logger);
const filterFoldersIds: FileId[] = [];
if (this.filterFilesIds.length > 0) {
filterFoldersIds.push(this.params.folderId);
await this.buildFolderFilter(this.filterFilesIds, filterFoldersIds);
}
downloader.onProgressNotify(({ total, completed, failed }) => {
if (this.progressNotifyCallback) {
this.progressNotifyCallback({ total, completed, failed });
}
});
switch (this.params.cmd) {
case 'pull': {
const taskFetchFolder = new TaskFetchFolder(
this.logger,
this.googleDriveService,
this.auth,
this.filesService,
{id: this.params.folderId, name: this.params.folderId, mimeType: MimeTypes.FOLDER_MIME},
this.forceDownloadFilters,
{filterFilesIds: this.filterFilesIds, filterFoldersIds}
);
const folderId = this.params.name;
const googleFileSystem = await this.filesService.getSubFileService(folderId, '/');
const userConfigService = new UserConfigService(googleFileSystem);
await userConfigService.load();
taskFetchFolder.setUseGoogleMarkdowns(userConfigService.config.use_google_markdowns);
downloader.addTask(taskFetchFolder);
}
}
await downloader.finished();
const folderRegistryContainer = <FolderRegistryContainer>this.engine.getContainer('folder_registry');
const folderData = await this.filesService.readJson('.folder.json');
if (folderData?.name) {
await folderRegistryContainer.rename(this.params.folderId, folderData.name);
}
const treeProcessor = new GoogleTreeProcessor(this.filesService);
await treeProcessor.load();
await treeProcessor.regenerateTree();
await treeProcessor.save();
this.engine.emit(this.params.folderId, 'gdrive:changed', null);
}
private async buildFolderFilter(filesIds: FileId[], folderFilterIds: FileId[]): Promise<void> {
for (const fileId of filesIds) {
const file = await this.googleDriveService.getFile(this.auth, fileId);
if (!file.parentId || file.parentId === this.params.folderId) {
continue;
}
if (folderFilterIds.indexOf(file.parentId) === -1) {
folderFilterIds.push(file.parentId);
await this.buildFolderFilter([file.parentId], folderFilterIds);
}
}
}
onProgressNotify(callback: ({total, completed, warnings, failed}: { total?: number; completed?: number; warnings?: number; failed?: number }) => void) {
this.progressNotifyCallback = callback;
}
}