Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Google Drive Trigger Node): Use resource locator component #5148

Merged
merged 5 commits into from
Jan 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 5 additions & 82 deletions packages/nodes-base/nodes/Google/Drive/GoogleDrive.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { BINARY_ENCODING, IExecuteFunctions } from 'n8n-core';

import {
IDataObject,
ILoadOptionsFunctions,
INodeExecutionData,
INodeListSearchResult,
INodeType,
INodeTypeDescription,
NodeOperationError,
Expand All @@ -14,21 +12,10 @@ import { googleApiRequest, googleApiRequestAllItems } from './GenericFunctions';

import { v4 as uuid } from 'uuid';
import type { Readable } from 'stream';
import { driveSearch, fileSearch, folderSearch } from './SearchFunctions';

const UPLOAD_CHUNK_SIZE = 256 * 1024;

interface GoogleDriveFilesItem {
id: string;
name: string;
mimeType: string;
webViewLink: string;
}

interface GoogleDriveDriveItem {
id: string;
name: string;
}

export class GoogleDrive implements INodeType {
description: INodeTypeDescription = {
displayName: 'Google Drive',
Expand Down Expand Up @@ -248,7 +235,7 @@ export class GoogleDrive implements INodeType {
name: 'url',
type: 'string',
placeholder:
'https://docs.google.com/spreadsheets/d/1-i6Vx0NN-3333eeeeeeeeee333333333/edit',
'https://drive.google.com/file/d/1anGBg0b5re2VtF2bKu201_a-Vnz5BHq9Y4r-yBDAj5A/edit',
extractValue: {
type: 'regex',
regex:
Expand Down Expand Up @@ -2035,73 +2022,9 @@ export class GoogleDrive implements INodeType {

methods = {
listSearch: {
async fileSearch(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
const query: string[] = [];
if (filter) {
query.push(`name contains '${filter.replace("'", "\\'")}'`);
}
query.push("mimeType != 'application/vnd.google-apps.folder'");
const res = await googleApiRequest.call(this, 'GET', '/drive/v3/files', undefined, {
q: query.join(' and '),
pageToken: paginationToken,
fields: 'nextPageToken,files(id,name,mimeType,webViewLink)',
orderBy: 'name_natural',
});
return {
results: res.files.map((i: GoogleDriveFilesItem) => ({
name: i.name,
value: i.id,
url: i.webViewLink,
})),
paginationToken: res.nextPageToken,
};
},
async folderSearch(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
const query: string[] = [];
if (filter) {
query.push(`name contains '${filter.replace("'", "\\'")}'`);
}
query.push("mimeType = 'application/vnd.google-apps.folder'");
const res = await googleApiRequest.call(this, 'GET', '/drive/v3/files', undefined, {
q: query.join(' and '),
pageToken: paginationToken,
fields: 'nextPageToken,files(id,name,mimeType,webViewLink)',
orderBy: 'name_natural',
});
return {
results: res.files.map((i: GoogleDriveFilesItem) => ({
name: i.name,
value: i.id,
url: i.webViewLink,
})),
paginationToken: res.nextPageToken,
};
},
async driveSearch(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
const res = await googleApiRequest.call(this, 'GET', '/drive/v3/drives', undefined, {
q: filter ? `name contains '${filter.replace("'", "\\'")}'` : undefined,
pageToken: paginationToken,
});
return {
results: res.drives.map((i: GoogleDriveDriveItem) => ({
name: i.name,
value: i.id,
})),
paginationToken: res.nextPageToken,
};
},
fileSearch,
folderSearch,
driveSearch,
},
};

Expand Down
135 changes: 120 additions & 15 deletions packages/nodes-base/nodes/Google/Drive/GoogleDriveTrigger.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { extractId, googleApiRequest, googleApiRequestAllItems } from './GenericFunctions';

import moment from 'moment';
import { fileSearch, folderSearch } from './SearchFunctions';

export class GoogleDriveTrigger implements INodeType {
description: INodeTypeDescription = {
Expand Down Expand Up @@ -89,18 +90,65 @@ export class GoogleDriveTrigger implements INodeType {
],
},
{
displayName: 'File URL or ID',
displayName: 'File',
name: 'fileToWatch',
type: 'string',
type: 'resourceLocator',
default: { mode: 'list', value: '' },
required: true,
modes: [
{
displayName: 'File',
name: 'list',
type: 'list',
placeholder: 'Select a file...',
typeOptions: {
searchListMethod: 'fileSearch',
searchable: true,
},
},
{
displayName: 'Link',
name: 'url',
type: 'string',
placeholder: 'https://drive.google.com/file/d/1wroCSfK-hupQIYf_xzeoUEzOhvfTFH2P/edit',
extractValue: {
type: 'regex',
regex:
'https:\\/\\/(?:drive|docs)\\.google\\.com\\/\\w+\\/d\\/([0-9a-zA-Z\\-_]+)(?:\\/.*|)',
},
validation: [
{
type: 'regex',
properties: {
regex:
'https:\\/\\/(?:drive|docs)\\.google.com\\/\\w+\\/d\\/([0-9a-zA-Z\\-_]+)(?:\\/.*|)',
errorMessage: 'Not a valid Google Drive File URL',
},
},
],
},
{
displayName: 'ID',
name: 'id',
type: 'string',
placeholder: '1anGBg0b5re2VtF2bKu201_a-Vnz5BHq9Y4r-yBDAj5A',
validation: [
{
type: 'regex',
properties: {
regex: '[a-zA-Z0-9\\-_]{2,}',
errorMessage: 'Not a valid Google Drive File ID',
},
},
],
url: '=https://drive.google.com/file/d/{{$value}}/view',
},
],
displayOptions: {
show: {
triggerOn: ['specificFile'],
},
},
default: '',
description:
'The address of this file when you view it in your browser (or just the ID contained within the URL)',
required: true,
},
{
displayName: 'Watch For',
Expand All @@ -122,18 +170,65 @@ export class GoogleDriveTrigger implements INodeType {
description: 'When to trigger this node',
},
{
displayName: 'Folder URL or ID',
displayName: 'Folder',
name: 'folderToWatch',
type: 'string',
type: 'resourceLocator',
default: { mode: 'list', value: '' },
required: true,
modes: [
{
displayName: 'Folder',
name: 'list',
type: 'list',
placeholder: 'Select a folder...',
typeOptions: {
searchListMethod: 'folderSearch',
searchable: true,
},
},
{
displayName: 'Link',
name: 'url',
type: 'string',
placeholder: 'https://drive.google.com/drive/folders/1Tx9WHbA3wBpPB4C_HcoZDH9WZFWYxAMU',
extractValue: {
type: 'regex',
regex:
'https:\\/\\/drive\\.google\\.com\\/\\w+\\/folders\\/([0-9a-zA-Z\\-_]+)(?:\\/.*|)',
},
validation: [
{
type: 'regex',
properties: {
regex:
'https:\\/\\/drive\\.google\\.com\\/\\w+\\/folders\\/([0-9a-zA-Z\\-_]+)(?:\\/.*|)',
errorMessage: 'Not a valid Google Drive Folder URL',
},
},
],
},
{
displayName: 'ID',
name: 'id',
type: 'string',
placeholder: '1anGBg0b5re2VtF2bKu201_a-Vnz5BHq9Y4r-yBDAj5A',
validation: [
{
type: 'regex',
properties: {
regex: '[a-zA-Z0-9\\-_]{2,}',
errorMessage: 'Not a valid Google Drive Folder ID',
},
},
],
url: '=https://drive.google.com/drive/folders/{{$value}}',
},
],
displayOptions: {
show: {
triggerOn: ['specificFolder'],
},
},
default: '',
description:
'The address of this folder when you view it in your browser (or just the ID contained within the URL)',
required: true,
},
{
displayName: 'Watch For',
Expand Down Expand Up @@ -303,6 +398,10 @@ export class GoogleDriveTrigger implements INodeType {
};

methods = {
listSearch: {
fileSearch,
folderSearch,
},
loadOptions: {
// Get all the calendars to display them to user so that he can
// select them easily
Expand Down Expand Up @@ -345,7 +444,9 @@ export class GoogleDriveTrigger implements INodeType {
const query = ['trashed = false'];

if (triggerOn === 'specificFolder' && event !== 'watchFolderUpdated') {
const folderToWatch = extractId(this.getNodeParameter('folderToWatch') as string);
const folderToWatch = extractId(
this.getNodeParameter('folderToWatch', '', { extractValue: true }) as string,
);
query.push(`'${folderToWatch}' in parents`);
}

Expand Down Expand Up @@ -387,7 +488,9 @@ export class GoogleDriveTrigger implements INodeType {
}

if (triggerOn === 'specificFile' && this.getMode() !== 'manual') {
const fileToWatch = extractId(this.getNodeParameter('fileToWatch') as string);
const fileToWatch = extractId(
this.getNodeParameter('fileToWatch', '', { extractValue: true }) as string,
);
files = files.filter((file: { id: string }) => file.id === fileToWatch);
}

Expand All @@ -396,7 +499,9 @@ export class GoogleDriveTrigger implements INodeType {
event === 'watchFolderUpdated' &&
this.getMode() !== 'manual'
) {
const folderToWatch = extractId(this.getNodeParameter('folderToWatch') as string);
const folderToWatch = extractId(
this.getNodeParameter('folderToWatch', '', { extractValue: true }) as string,
);
files = files.filter((file: { id: string }) => file.id === folderToWatch);
}

Expand Down
84 changes: 84 additions & 0 deletions packages/nodes-base/nodes/Google/Drive/SearchFunctions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { ILoadOptionsFunctions, INodeListSearchResult } from 'n8n-workflow';
import { googleApiRequest } from './GenericFunctions';

interface GoogleDriveFilesItem {
id: string;
name: string;
mimeType: string;
webViewLink: string;
}

interface GoogleDriveDriveItem {
id: string;
name: string;
}

export async function fileSearch(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
const query: string[] = [];
if (filter) {
query.push(`name contains '${filter.replace("'", "\\'")}'`);
}
query.push("mimeType != 'application/vnd.google-apps.folder'");
const res = await googleApiRequest.call(this, 'GET', '/drive/v3/files', undefined, {
q: query.join(' and '),
pageToken: paginationToken,
fields: 'nextPageToken,files(id,name,mimeType,webViewLink)',
orderBy: 'name_natural',
});
return {
results: res.files.map((i: GoogleDriveFilesItem) => ({
name: i.name,
value: i.id,
url: i.webViewLink,
})),
paginationToken: res.nextPageToken,
};
}

export async function folderSearch(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
const query: string[] = [];
if (filter) {
query.push(`name contains '${filter.replace("'", "\\'")}'`);
}
query.push("mimeType = 'application/vnd.google-apps.folder'");
const res = await googleApiRequest.call(this, 'GET', '/drive/v3/files', undefined, {
q: query.join(' and '),
pageToken: paginationToken,
fields: 'nextPageToken,files(id,name,mimeType,webViewLink)',
orderBy: 'name_natural',
});
return {
results: res.files.map((i: GoogleDriveFilesItem) => ({
name: i.name,
value: i.id,
url: i.webViewLink,
})),
paginationToken: res.nextPageToken,
};
}

export async function driveSearch(
this: ILoadOptionsFunctions,
filter?: string,
paginationToken?: string,
): Promise<INodeListSearchResult> {
const res = await googleApiRequest.call(this, 'GET', '/drive/v3/drives', undefined, {
q: filter ? `name contains '${filter.replace("'", "\\'")}'` : undefined,
pageToken: paginationToken,
});
return {
results: res.drives.map((i: GoogleDriveDriveItem) => ({
name: i.name,
value: i.id,
})),
paginationToken: res.nextPageToken,
};
}