Skip to content

Commit

Permalink
Add changes webhook support
Browse files Browse the repository at this point in the history
  • Loading branch information
ggodlewski committed Sep 24, 2024
1 parent bf21af0 commit a2cf19d
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 38 deletions.
4 changes: 4 additions & 0 deletions src/containers/changes/WatchChangesContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ export class WatchChangesContainer extends Container {
if (this.intervals[driveId]) {
return;
}

this.logger.info('Starting watching: ' + driveId);

this.intervals[driveId] = setInterval(async () => {
if (!this.auth) {
return;
Expand All @@ -124,6 +127,7 @@ export class WatchChangesContainer extends Container {
try {
if (!this.lastToken[driveId]) {
this.lastToken[driveId] = await this.googleDriveService.getStartTrackToken(this.auth, driveId);
// await this.googleDriveService.setupWatchChannel(this.auth, this.lastToken[driveId], driveId);
return;
}

Expand Down
26 changes: 25 additions & 1 deletion src/containers/server/routes/Controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ export interface ControllerRouteParamBody {
docs?: RouteDoc;
}

export interface ControllerRouteParamHeaders {
type: 'headers';
parameterIndex: number;
docs?: RouteDoc;
}

export interface ControllerRouteParamStream {
type: 'stream';
parameterIndex: number;
Expand Down Expand Up @@ -70,7 +76,7 @@ export interface ControllerRouteParamPath {
}

type ControllerRouteParam = ControllerRouteParamGetAll | ControllerRouteParamQuery
| ControllerRouteParamBody | ControllerRouteParamPath | ControllerRouteParamStream
| ControllerRouteParamBody | ControllerRouteParamHeaders | ControllerRouteParamPath | ControllerRouteParamStream
| ControllerRouteParamRelated | ControllerRouteParamUser | ControllerRouteParamMethod;

export interface RouteDoc {
Expand Down Expand Up @@ -245,6 +251,12 @@ export class Controller implements ControllerCallContext {
args[param.parameterIndex] = body;
}
break;
case 'headers':
{
const headers = req.headers;
args[param.parameterIndex] = headers;
}
break;
case 'stream':
args[param.parameterIndex] = req;
break;
Expand Down Expand Up @@ -450,6 +462,18 @@ export function RouteParamBody(docs: RouteDoc = {}) {
};
}

export function RouteParamHeaders(docs: RouteDoc = {}) {
return function (targetClass: Controller, methodProp: string, parameterIndex: number) {
const route = targetClass.getRoute(targetClass, methodProp);
const param: ControllerRouteParamHeaders = {
type: 'headers',
parameterIndex,
docs
};
route.params.push(param);
};
}

export function RouteParamStream(docs: RouteDoc = {}) {
return function (targetClass: Controller, methodProp: string, parameterIndex: number) {
const route = targetClass.getRoute(targetClass, methodProp);
Expand Down
26 changes: 13 additions & 13 deletions src/containers/server/routes/DriveController.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import {Controller, RouteGet, RouteParamPath, RouteParamUser, RouteResponse} from './Controller';
import {GitScanner} from '../../../git/GitScanner';
import {FolderRegistryContainer} from '../../folder_registry/FolderRegistryContainer';
import {UserConfigService} from '../../google_folder/UserConfigService';
import {FileContentService} from '../../../utils/FileContentService';
import {GoogleDriveService} from '../../../google/GoogleDriveService';
import {MarkdownTreeProcessor} from '../../transform/MarkdownTreeProcessor';
import {AuthConfig} from '../../../model/AccountJson';
import {googleMimeToExt} from '../../transform/TaskLocalFileTransform';
import {Container} from '../../../ContainerEngine';
import {GoogleTreeProcessor} from '../../google_folder/GoogleTreeProcessor';
import {getContentFileService} from '../../transform/utils';
import {redirError} from '../auth';
import {Controller, RouteGet, RouteParamPath, RouteParamUser, RouteResponse} from './Controller.ts';
import {GitScanner} from '../../../git/GitScanner.ts';
import {FolderRegistryContainer} from '../../folder_registry/FolderRegistryContainer.ts';
import {UserConfigService} from '../../google_folder/UserConfigService.ts';
import {FileContentService} from '../../../utils/FileContentService.ts';
import {GoogleDriveService} from '../../../google/GoogleDriveService.ts';
import {MarkdownTreeProcessor} from '../../transform/MarkdownTreeProcessor.ts';
import {AuthConfig} from '../../../model/AccountJson.ts';
import {googleMimeToExt} from '../../transform/TaskLocalFileTransform.ts';
import {Container} from '../../../ContainerEngine.ts';
import {GoogleTreeProcessor} from '../../google_folder/GoogleTreeProcessor.ts';
import {getContentFileService} from '../../transform/utils.ts';
import {redirError} from '../auth.ts';

export class DriveController extends Controller {
constructor(subPath: string,
Expand Down
8 changes: 4 additions & 4 deletions src/containers/server/routes/SearchController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import {
RouteGet,
RouteParamPath,
RouteParamQuery
} from './Controller';
import {FileContentService} from '../../../utils/FileContentService';
import {ShareErrorHandler} from './FolderController';
import {UserConfigService} from '../../google_folder/UserConfigService';
} from './Controller.ts';
import {FileContentService} from '../../../utils/FileContentService.ts';
import {ShareErrorHandler} from './FolderController.ts';
import {UserConfigService} from '../../google_folder/UserConfigService.ts';

export class SearchController extends Controller {
constructor(subPath: string, private filesService: FileContentService) {
Expand Down
6 changes: 3 additions & 3 deletions src/containers/server/routes/WebHookController.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {Logger} from 'winston';

import {
Controller, RouteParamBody, RoutePost,
Controller, RouteParamBody, RouteParamHeaders, RoutePost,
} from './Controller.ts';

export class WebHookController extends Controller {
Expand All @@ -11,8 +11,8 @@ export class WebHookController extends Controller {
}

@RoutePost('/')
async postEvent(@RouteParamBody() body: undefined) {
this.queryLogger.info(`WebHookController.postEvent ${JSON.stringify(body)}`);
async postEvent(@RouteParamBody() body: undefined, @RouteParamHeaders() headers: undefined) {
this.queryLogger.info(`WebHookController.postEvent ${JSON.stringify(headers)} ${JSON.stringify(body)}`);

return {};
}
Expand Down
52 changes: 35 additions & 17 deletions src/google/GoogleDriveService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import {Logger} from 'winston';
import {Writable} from 'stream';
import crypto from 'crypto';

import {GoogleFile, MimeToExt, MimeTypes, SimpleFile} from '../model/GoogleFile.ts';
import {FileId} from '../model/model.ts';
Expand Down Expand Up @@ -47,6 +48,40 @@ export class GoogleDriveService {
constructor(private logger: Logger, private quotaLimiter: QuotaLimiter) {
}

async setupWatchChannel(auth: HasAccessToken, startPageToken: string, driveId: string) {
// This API does not work as intended, no webhook is executed on change

const hexstring = crypto.randomBytes(16).toString('hex');
const uuid = hexstring.substring(0,8) + '-' + hexstring.substring(8,12) + '-' + hexstring.substring(12,16) + '-' + hexstring.substring(16,20) + '-' + hexstring.substring(20);

const params = {
pageToken: startPageToken,
supportsAllDrives: true,
includeItemsFromAllDrives: true,
// fields: '*', // file(id, name, mimeType, modifiedTime, size, md5Checksum, lastModifyingUser, parents, version, exportLinks, trashed)',
includeRemoved: true,
driveId: driveId ? driveId : undefined
};

const body = {
id: uuid,
type: 'web_hook',
address: process.env.DOMAIN + '/webhook', // Your receiving URL.
expiration: String(Date.now() + 10 * 60 * 1000)
};

await driveFetch(this.quotaLimiter, await auth.getAccessToken(), 'POST', 'https://www.googleapis.com/drive/v3/changes/watch', params, body);
/*
{
kind: 'api#channel',
id: '1873c104-3f34-07e2-086e-c97e8c23cb55',
resourceId: 'VZoPsZrgUX6TNl0BxbV2rN_zUIU',
resourceUri: 'https://www.googleapis.com/drive/v3/changes?alt=json&driveId=0AI7ud-sa0EAJUk9PVA&fields=*&includeItemsFromAllDrives=true&includeRemoved=true&pageToken=78&supportsAllDrives=true',
expiration: '1727025863000'
}
*/
}

async getStartTrackToken(auth: HasAccessToken, driveId?: string): Promise<string> {
const params = {
supportsAllDrives: true,
Expand All @@ -61,23 +96,6 @@ export class GoogleDriveService {
return res.startPageToken;
}

async subscribeWatch(auth: HasAccessToken, pageToken: string, driveId?: string) {
try {
const params = {
pageToken,
supportsAllDrives: true,
includeItemsFromAllDrives: true,
fields: 'newStartPageToken, nextPageToken, changes( file(id, name, mimeType, modifiedTime, size, md5Checksum, lastModifyingUser, parents, version, exportLinks, trashed), removed)',
includeRemoved: true,
driveId: driveId ? driveId : undefined
};
return await driveFetch(this.quotaLimiter, await auth.getAccessToken(), 'POST', 'https://www.googleapis.com/drive/v3/changes/watch', params);
} catch (err) {
err.message = 'Error watching: ' + err.message;
throw err;
}
}

async watchChanges(auth: HasAccessToken, pageToken: string, driveId?: string): Promise<Changes> {
try {
const params = {
Expand Down

0 comments on commit a2cf19d

Please sign in to comment.