mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-14 00:24:07 -08:00
ce066a160f
* introduce analytics * add user survey backend * add user survey backend * set answers on survey submit Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com> * change name to personalization * lint Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com> * N8n 2495 add personalization modal (#2280) * update modals * add onboarding modal * implement questions * introduce analytics * simplify impl * implement survey handling * add personalized cateogry * update modal behavior * add thank you view * handle empty cases * rename modal * standarize modal names * update image, add tags to headings * remove unused file * remove unused interfaces * clean up footer spacing * introduce analytics * refactor to fix bug * update endpoint * set min height * update stories * update naming from questions to survey * remove spacing after core categories * fix bug in logic * sort nodes * rename types * merge with be * rename userSurvey * clean up rest api * use constants for keys * use survey keys * clean up types * move personalization to its own file Co-authored-by: ahsan-virani <ahsan.virani@gmail.com> * update parameter inputs to be multiline * update spacing * Survey new options (#2300) * split up options * fix quotes * remove unused import * refactor node credentials * add user created workflow event (#2301) * update multi params * simplify env vars * fix versionCli on FE * update personalization env * clean up node detail settings * fix event User opened Credentials panel * fix font sizes across modals * clean up input spacing * fix select modal spacing * increase spacing * fix input copy * fix webhook, tab spacing, retry button * fix button sizes * fix button size * add mini xlarge sizes * fix webhook spacing * fix nodes panel event * fix workflow id in workflow execute event * improve telemetry error logging * fix config and stop process events * add flush call on n8n stop * ready for release * fix input error highlighting * revert change * update toggle spacing * fix delete positioning * keep tooltip while focused * set strict size * increase left spacing * fix sort icons * remove unnessasry <br/> * remove unnessary break * remove unnessary margin * clean unused functionality * remove unnessary css * remove duplicate tracking * only show tooltip when hovering over label * remove extra space * add br * remove extra space * clean up commas * clean up commas * remove extra space * remove extra space * rewrite desc * add commas * add space * remove extra space * add space * add dot * update credentials section * use includes Co-authored-by: ahsan-virani <ahsan.virani@gmail.com> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
1090 lines
24 KiB
TypeScript
1090 lines
24 KiB
TypeScript
import {
|
|
BINARY_ENCODING,
|
|
IExecuteFunctions,
|
|
} from 'n8n-core';
|
|
|
|
import {
|
|
IDataObject,
|
|
INodeExecutionData,
|
|
INodeType,
|
|
INodeTypeDescription,
|
|
NodeOperationError,
|
|
} from 'n8n-workflow';
|
|
|
|
import {
|
|
dropboxApiRequest,
|
|
dropboxpiRequestAllItems,
|
|
getCredentials,
|
|
getRootDirectory,
|
|
simplify,
|
|
} from './GenericFunctions';
|
|
|
|
export class Dropbox implements INodeType {
|
|
description: INodeTypeDescription = {
|
|
displayName: 'Dropbox',
|
|
name: 'dropbox',
|
|
icon: 'file:dropbox.svg',
|
|
group: ['input'],
|
|
version: 1,
|
|
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
description: 'Access data on Dropbox',
|
|
defaults: {
|
|
name: 'Dropbox',
|
|
color: '#007ee5',
|
|
},
|
|
inputs: ['main'],
|
|
outputs: ['main'],
|
|
credentials: [
|
|
{
|
|
name: 'dropboxApi',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
authentication: [
|
|
'accessToken',
|
|
],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: 'dropboxOAuth2Api',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
authentication: [
|
|
'oAuth2',
|
|
],
|
|
},
|
|
},
|
|
},
|
|
],
|
|
properties: [
|
|
{
|
|
displayName: 'Authentication',
|
|
name: 'authentication',
|
|
type: 'options',
|
|
options: [
|
|
{
|
|
name: 'Access Token',
|
|
value: 'accessToken',
|
|
},
|
|
{
|
|
name: 'OAuth2',
|
|
value: 'oAuth2',
|
|
},
|
|
],
|
|
default: 'accessToken',
|
|
description: 'Means of authenticating with the service.',
|
|
},
|
|
{
|
|
displayName: 'Resource',
|
|
name: 'resource',
|
|
type: 'options',
|
|
options: [
|
|
{
|
|
name: 'File',
|
|
value: 'file',
|
|
},
|
|
{
|
|
name: 'Folder',
|
|
value: 'folder',
|
|
},
|
|
{
|
|
name: 'Search',
|
|
value: 'search',
|
|
},
|
|
],
|
|
default: 'file',
|
|
description: 'The resource to operate on.',
|
|
},
|
|
|
|
// ----------------------------------
|
|
// operations
|
|
// ----------------------------------
|
|
{
|
|
displayName: 'Operation',
|
|
name: 'operation',
|
|
type: 'options',
|
|
displayOptions: {
|
|
show: {
|
|
resource: [
|
|
'file',
|
|
],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
name: 'Copy',
|
|
value: 'copy',
|
|
description: 'Copy a file',
|
|
},
|
|
{
|
|
name: 'Delete',
|
|
value: 'delete',
|
|
description: 'Delete a file',
|
|
},
|
|
{
|
|
name: 'Download',
|
|
value: 'download',
|
|
description: 'Download a file',
|
|
},
|
|
{
|
|
name: 'Move',
|
|
value: 'move',
|
|
description: 'Move a file',
|
|
},
|
|
{
|
|
name: 'Upload',
|
|
value: 'upload',
|
|
description: 'Upload a file',
|
|
},
|
|
],
|
|
default: 'upload',
|
|
description: 'The operation to perform.',
|
|
},
|
|
|
|
{
|
|
displayName: 'Operation',
|
|
name: 'operation',
|
|
type: 'options',
|
|
displayOptions: {
|
|
show: {
|
|
resource: [
|
|
'folder',
|
|
],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
name: 'Copy',
|
|
value: 'copy',
|
|
description: 'Copy a folder',
|
|
},
|
|
{
|
|
name: 'Create',
|
|
value: 'create',
|
|
description: 'Create a folder',
|
|
},
|
|
{
|
|
name: 'Delete',
|
|
value: 'delete',
|
|
description: 'Delete a folder',
|
|
},
|
|
{
|
|
name: 'List',
|
|
value: 'list',
|
|
description: 'Return the files and folders in a given folder',
|
|
},
|
|
{
|
|
name: 'Move',
|
|
value: 'move',
|
|
description: 'Move a folder',
|
|
},
|
|
],
|
|
default: 'create',
|
|
description: 'The operation to perform.',
|
|
},
|
|
|
|
{
|
|
displayName: 'Operation',
|
|
name: 'operation',
|
|
type: 'options',
|
|
displayOptions: {
|
|
show: {
|
|
resource: [
|
|
'search',
|
|
],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
name: 'Query',
|
|
value: 'query',
|
|
},
|
|
],
|
|
default: 'query',
|
|
description: 'The operation to perform.',
|
|
},
|
|
|
|
// ----------------------------------
|
|
// file
|
|
// ----------------------------------
|
|
|
|
// ----------------------------------
|
|
// file/folder:copy
|
|
// ----------------------------------
|
|
{
|
|
displayName: 'From Path',
|
|
name: 'path',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'copy',
|
|
],
|
|
resource: [
|
|
'file',
|
|
'folder',
|
|
],
|
|
},
|
|
},
|
|
placeholder: '/invoices/original.txt',
|
|
description: 'The path of file or folder to copy.',
|
|
},
|
|
{
|
|
displayName: 'To Path',
|
|
name: 'toPath',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'copy',
|
|
],
|
|
resource: [
|
|
'file',
|
|
'folder',
|
|
],
|
|
},
|
|
},
|
|
placeholder: '/invoices/copy.txt',
|
|
description: 'The destination path of file or folder.',
|
|
},
|
|
|
|
// ----------------------------------
|
|
// file/folder:delete
|
|
// ----------------------------------
|
|
{
|
|
displayName: 'Delete Path',
|
|
name: 'path',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'delete',
|
|
],
|
|
resource: [
|
|
'file',
|
|
'folder',
|
|
],
|
|
},
|
|
},
|
|
placeholder: '/invoices/2019/invoice_1.pdf',
|
|
description: 'The path to delete. Can be a single file or a whole folder.',
|
|
},
|
|
|
|
|
|
// ----------------------------------
|
|
// file/folder:move
|
|
// ----------------------------------
|
|
{
|
|
displayName: 'From Path',
|
|
name: 'path',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'move',
|
|
],
|
|
resource: [
|
|
'file',
|
|
'folder',
|
|
],
|
|
},
|
|
},
|
|
placeholder: '/invoices/old_name.txt',
|
|
description: 'The path of file or folder to move.',
|
|
},
|
|
{
|
|
displayName: 'To Path',
|
|
name: 'toPath',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'move',
|
|
],
|
|
resource: [
|
|
'file',
|
|
'folder',
|
|
],
|
|
},
|
|
},
|
|
placeholder: '/invoices/new_name.txt',
|
|
description: 'The new path of file or folder.',
|
|
},
|
|
|
|
// ----------------------------------
|
|
// file:download
|
|
// ----------------------------------
|
|
{
|
|
displayName: 'File Path',
|
|
name: 'path',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'download',
|
|
],
|
|
resource: [
|
|
'file',
|
|
],
|
|
},
|
|
},
|
|
placeholder: '/invoices/2019/invoice_1.pdf',
|
|
description: 'The file path of the file to download. Has to contain the full path.',
|
|
},
|
|
{
|
|
displayName: 'Binary Property',
|
|
name: 'binaryPropertyName',
|
|
type: 'string',
|
|
required: true,
|
|
default: 'data',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'download',
|
|
],
|
|
resource: [
|
|
'file',
|
|
],
|
|
},
|
|
},
|
|
description: 'Name of the binary property to which to write the data of the read file.',
|
|
},
|
|
|
|
// ----------------------------------
|
|
// file:upload
|
|
// ----------------------------------
|
|
{
|
|
displayName: 'File Path',
|
|
name: 'path',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'upload',
|
|
],
|
|
resource: [
|
|
'file',
|
|
],
|
|
},
|
|
},
|
|
placeholder: '/invoices/2019/invoice_1.pdf',
|
|
description: 'The file path of the file to upload. Has to contain the full path. The parent folder has to exist. Existing files get overwritten.',
|
|
},
|
|
{
|
|
displayName: 'Binary Data',
|
|
name: 'binaryData',
|
|
type: 'boolean',
|
|
default: false,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'upload',
|
|
],
|
|
resource: [
|
|
'file',
|
|
],
|
|
},
|
|
},
|
|
description: 'If the data to upload should be taken from binary field.',
|
|
},
|
|
{
|
|
displayName: 'File Content',
|
|
name: 'fileContent',
|
|
type: 'string',
|
|
default: '',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'upload',
|
|
],
|
|
resource: [
|
|
'file',
|
|
],
|
|
binaryData: [
|
|
false,
|
|
],
|
|
},
|
|
|
|
},
|
|
placeholder: '',
|
|
description: 'The text content of the file to upload.',
|
|
},
|
|
{
|
|
displayName: 'Binary Property',
|
|
name: 'binaryPropertyName',
|
|
type: 'string',
|
|
default: 'data',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'upload',
|
|
],
|
|
resource: [
|
|
'file',
|
|
],
|
|
binaryData: [
|
|
true,
|
|
],
|
|
},
|
|
|
|
},
|
|
placeholder: '',
|
|
description: 'Name of the binary property which contains the data for the file to be uploaded.',
|
|
},
|
|
|
|
// ----------------------------------
|
|
// search:query
|
|
// ----------------------------------
|
|
{
|
|
displayName: 'Query',
|
|
name: 'query',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'query',
|
|
],
|
|
resource: [
|
|
'search',
|
|
],
|
|
},
|
|
},
|
|
description: ' The string to search for. May match across multiple fields based on the request arguments.',
|
|
},
|
|
{
|
|
displayName: 'File Status',
|
|
name: 'fileStatus',
|
|
type: 'options',
|
|
options: [
|
|
{
|
|
name: 'Active',
|
|
value: 'active',
|
|
},
|
|
{
|
|
name: 'Deleted',
|
|
value: 'deleted',
|
|
},
|
|
],
|
|
default: 'active',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'query',
|
|
],
|
|
resource: [
|
|
'search',
|
|
],
|
|
},
|
|
},
|
|
description: ' The string to search for. May match across multiple fields based on the request arguments.',
|
|
},
|
|
{
|
|
displayName: 'Return All',
|
|
name: 'returnAll',
|
|
type: 'boolean',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'query',
|
|
],
|
|
resource: [
|
|
'search',
|
|
],
|
|
},
|
|
},
|
|
default: false,
|
|
description: 'If all results should be returned or only up to a given limit.',
|
|
},
|
|
{
|
|
displayName: 'Limit',
|
|
name: 'limit',
|
|
type: 'number',
|
|
displayOptions: {
|
|
show: {
|
|
resource: [
|
|
'search',
|
|
],
|
|
operation: [
|
|
'query',
|
|
],
|
|
returnAll: [
|
|
false,
|
|
],
|
|
},
|
|
},
|
|
default: 100,
|
|
description: 'How many results to return.',
|
|
},
|
|
{
|
|
displayName: 'Simple',
|
|
name: 'simple',
|
|
type: 'boolean',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'query',
|
|
],
|
|
resource: [
|
|
'search',
|
|
],
|
|
},
|
|
},
|
|
default: true,
|
|
description: 'When set to true a simplify version of the response will be used else the raw data.',
|
|
},
|
|
{
|
|
displayName: 'Filters',
|
|
name: 'filters',
|
|
type: 'collection',
|
|
placeholder: 'Add Filter',
|
|
default: {},
|
|
displayOptions: {
|
|
show: {
|
|
resource: [
|
|
'search',
|
|
],
|
|
operation: [
|
|
'query',
|
|
],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
displayName: 'File Categories',
|
|
name: 'file_categories',
|
|
type: 'multiOptions',
|
|
options: [
|
|
{
|
|
name: 'Audio (mp3, wav, mid, etc.)',
|
|
value: 'audio',
|
|
},
|
|
{
|
|
name: 'Document (doc, docx, txt, etc.)',
|
|
value: 'document',
|
|
},
|
|
{
|
|
name: 'Folder',
|
|
value: 'folder',
|
|
},
|
|
{
|
|
name: 'Image (jpg, png, gif, etc.)',
|
|
value: 'image',
|
|
},
|
|
{
|
|
name: 'Other',
|
|
value: 'other',
|
|
},
|
|
{
|
|
name: 'Dropbox Paper',
|
|
value: 'paper',
|
|
},
|
|
{
|
|
name: 'PDF',
|
|
value: 'pdf',
|
|
},
|
|
{
|
|
name: 'Presentation (ppt, pptx, key, etc.)',
|
|
value: 'presentation',
|
|
},
|
|
{
|
|
name: 'Spreadsheet (xlsx, xls, csv, etc.)',
|
|
value: 'spreadsheet',
|
|
},
|
|
{
|
|
name: 'Video (avi, wmv, mp4, etc.)',
|
|
value: 'video',
|
|
},
|
|
],
|
|
default: [],
|
|
},
|
|
{
|
|
displayName: 'File Extensions',
|
|
name: 'file_extensions',
|
|
type: 'string',
|
|
default: '',
|
|
description: 'Multiple can be set separated by comma. Example: jpg,pdf',
|
|
},
|
|
{
|
|
displayName: 'Folder',
|
|
name: 'path',
|
|
type: 'string',
|
|
default: '',
|
|
description: 'If this field is not specified, this module searches the entire Dropbox',
|
|
},
|
|
],
|
|
},
|
|
|
|
// ----------------------------------
|
|
// folder
|
|
// ----------------------------------
|
|
|
|
// ----------------------------------
|
|
// folder:create
|
|
// ----------------------------------
|
|
{
|
|
displayName: 'Folder',
|
|
name: 'path',
|
|
type: 'string',
|
|
default: '',
|
|
required: true,
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'create',
|
|
],
|
|
resource: [
|
|
'folder',
|
|
],
|
|
},
|
|
},
|
|
placeholder: '/invoices/2019',
|
|
description: 'The folder to create. The parent folder has to exist.',
|
|
},
|
|
|
|
// ----------------------------------
|
|
// folder:list
|
|
// ----------------------------------
|
|
{
|
|
displayName: 'Folder Path',
|
|
name: 'path',
|
|
type: 'string',
|
|
default: '',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'list',
|
|
],
|
|
resource: [
|
|
'folder',
|
|
],
|
|
},
|
|
},
|
|
placeholder: '/invoices/2019/',
|
|
description: 'The path of which to list the content.',
|
|
},
|
|
{
|
|
displayName: 'Return All',
|
|
name: 'returnAll',
|
|
type: 'boolean',
|
|
displayOptions: {
|
|
show: {
|
|
operation: [
|
|
'list',
|
|
],
|
|
resource: [
|
|
'folder',
|
|
],
|
|
},
|
|
},
|
|
default: false,
|
|
description: 'If all results should be returned or only up to a given limit.',
|
|
},
|
|
{
|
|
displayName: 'Limit',
|
|
name: 'limit',
|
|
type: 'number',
|
|
displayOptions: {
|
|
show: {
|
|
resource: [
|
|
'folder',
|
|
],
|
|
operation: [
|
|
'list',
|
|
],
|
|
returnAll: [
|
|
false,
|
|
],
|
|
},
|
|
},
|
|
default: 100,
|
|
description: 'How many results to return.',
|
|
},
|
|
{
|
|
displayName: 'Filters',
|
|
name: 'filters',
|
|
type: 'collection',
|
|
placeholder: 'Add Filter',
|
|
default: {},
|
|
displayOptions: {
|
|
show: {
|
|
resource: [
|
|
'folder',
|
|
],
|
|
operation: [
|
|
'list',
|
|
],
|
|
},
|
|
},
|
|
options: [
|
|
{
|
|
displayName: 'Include Deleted',
|
|
name: 'include_deleted',
|
|
type: 'boolean',
|
|
default: false,
|
|
description: 'If true, the results will include entries for files and folders that used to exist but were deleted. The default for this field is False.',
|
|
},
|
|
{
|
|
displayName: 'Include Shared Members ',
|
|
name: 'include_has_explicit_shared_members',
|
|
type: 'boolean',
|
|
default: false,
|
|
description: 'If true, the results will include a flag for each file indicating whether or not that file has any explicit members. The default for this field is False.',
|
|
},
|
|
{
|
|
displayName: 'Include Mounted Folders ',
|
|
name: 'include_mounted_folders',
|
|
type: 'boolean',
|
|
default: true,
|
|
description: 'If true, the results will include entries under mounted folders which includes app folder, shared folder and team folder. The default for this field is True.',
|
|
},
|
|
{
|
|
displayName: 'Include Non Downloadable Files ',
|
|
name: 'include_non_downloadable_files',
|
|
type: 'boolean',
|
|
default: true,
|
|
description: 'If true, include files that are not downloadable, i.e. Google Docs. The default for this field is True.',
|
|
},
|
|
{
|
|
displayName: 'Recursive',
|
|
name: 'recursive',
|
|
type: 'boolean',
|
|
default: false,
|
|
description: 'If true, the list folder operation will be applied recursively to all subfolders and the response will contain contents of all subfolders. The default for this field is False.',
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|
|
|
|
|
|
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
|
const items = this.getInputData();
|
|
const returnData: IDataObject[] = [];
|
|
|
|
|
|
const resource = this.getNodeParameter('resource', 0) as string;
|
|
const operation = this.getNodeParameter('operation', 0) as string;
|
|
|
|
let endpoint = '';
|
|
let requestMethod = '';
|
|
let returnAll = false;
|
|
let property = '';
|
|
let body: IDataObject | Buffer;
|
|
let options;
|
|
const query: IDataObject = {};
|
|
|
|
let headers: IDataObject = {};
|
|
let simple = false;
|
|
|
|
|
|
const { accessType } = await getCredentials.call(this);
|
|
|
|
if (accessType === 'full') {
|
|
// get the root directory to set it as the default for all operations
|
|
const { root_info: { root_namespace_id } } = await getRootDirectory.call(this);
|
|
|
|
headers = {
|
|
'dropbox-api-path-root': JSON.stringify({
|
|
'.tag': 'root',
|
|
'root': root_namespace_id,
|
|
}),
|
|
};
|
|
}
|
|
|
|
for (let i = 0; i < items.length; i++) {
|
|
try {
|
|
body = {};
|
|
|
|
if (resource === 'file') {
|
|
if (operation === 'download') {
|
|
// ----------------------------------
|
|
// download
|
|
// ----------------------------------
|
|
|
|
requestMethod = 'POST';
|
|
|
|
query.arg = JSON.stringify({
|
|
path: this.getNodeParameter('path', i) as string,
|
|
});
|
|
|
|
endpoint = 'https://content.dropboxapi.com/2/files/download';
|
|
|
|
} else if (operation === 'upload') {
|
|
// ----------------------------------
|
|
// upload
|
|
// ----------------------------------
|
|
|
|
requestMethod = 'POST';
|
|
headers['Content-Type'] = 'application/octet-stream';
|
|
|
|
query.arg = JSON.stringify({
|
|
mode: 'overwrite',
|
|
path: this.getNodeParameter('path', i) as string,
|
|
});
|
|
|
|
endpoint = 'https://content.dropboxapi.com/2/files/upload';
|
|
|
|
options = { json: false };
|
|
|
|
if (this.getNodeParameter('binaryData', i) === true) {
|
|
|
|
// Is binary file to upload
|
|
const item = items[i];
|
|
|
|
if (item.binary === undefined) {
|
|
throw new NodeOperationError(this.getNode(), 'No binary data exists on item!');
|
|
}
|
|
|
|
const propertyNameUpload = this.getNodeParameter('binaryPropertyName', i) as string;
|
|
|
|
if (item.binary[propertyNameUpload] === undefined) {
|
|
throw new NodeOperationError(this.getNode(), `No binary data property "${propertyNameUpload}" does not exists on item!`);
|
|
}
|
|
|
|
body = Buffer.from(item.binary[propertyNameUpload].data, BINARY_ENCODING);
|
|
} else {
|
|
// Is text file
|
|
body = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8');
|
|
}
|
|
}
|
|
} else if (resource === 'folder') {
|
|
if (operation === 'create') {
|
|
// ----------------------------------
|
|
// create
|
|
// ----------------------------------
|
|
|
|
requestMethod = 'POST';
|
|
body = {
|
|
path: this.getNodeParameter('path', i) as string,
|
|
};
|
|
|
|
endpoint = 'https://api.dropboxapi.com/2/files/create_folder_v2';
|
|
|
|
} else if (operation === 'list') {
|
|
// ----------------------------------
|
|
// list
|
|
// ----------------------------------
|
|
|
|
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
|
|
|
|
const filters = this.getNodeParameter('filters', i) as IDataObject;
|
|
|
|
property = 'entries';
|
|
|
|
requestMethod = 'POST';
|
|
body = {
|
|
path: this.getNodeParameter('path', i) as string,
|
|
limit: 1000,
|
|
};
|
|
|
|
if (returnAll === false) {
|
|
const limit = this.getNodeParameter('limit', 0) as number;
|
|
body.limit = limit;
|
|
}
|
|
|
|
Object.assign(body, filters);
|
|
|
|
endpoint = 'https://api.dropboxapi.com/2/files/list_folder';
|
|
|
|
}
|
|
} else if (resource === 'search') {
|
|
if (operation === 'query') {
|
|
// ----------------------------------
|
|
// query
|
|
// ----------------------------------
|
|
|
|
returnAll = this.getNodeParameter('returnAll', 0) as boolean;
|
|
|
|
simple = this.getNodeParameter('simple', 0) as boolean;
|
|
|
|
const filters = this.getNodeParameter('filters', i) as IDataObject;
|
|
|
|
property = 'matches';
|
|
|
|
requestMethod = 'POST';
|
|
body = {
|
|
query: this.getNodeParameter('query', i) as string,
|
|
options: {
|
|
filename_only: true,
|
|
},
|
|
};
|
|
|
|
if (filters.file_extensions) {
|
|
filters.file_extensions = (filters.file_extensions as string).split(',');
|
|
}
|
|
|
|
Object.assign(body.options, filters);
|
|
|
|
if (returnAll === false) {
|
|
const limit = this.getNodeParameter('limit', i) as number;
|
|
Object.assign(body.options, { max_results: limit });
|
|
}
|
|
|
|
endpoint = 'https://api.dropboxapi.com/2/files/search_v2';
|
|
}
|
|
}
|
|
if (['file', 'folder', 'search'].includes(resource)) {
|
|
if (operation === 'copy') {
|
|
// ----------------------------------
|
|
// copy
|
|
// ----------------------------------
|
|
|
|
requestMethod = 'POST';
|
|
body = {
|
|
from_path: this.getNodeParameter('path', i) as string,
|
|
to_path: this.getNodeParameter('toPath', i) as string,
|
|
};
|
|
|
|
endpoint = 'https://api.dropboxapi.com/2/files/copy_v2';
|
|
|
|
} else if (operation === 'delete') {
|
|
// ----------------------------------
|
|
// delete
|
|
// ----------------------------------
|
|
|
|
requestMethod = 'POST';
|
|
body = {
|
|
path: this.getNodeParameter('path', i) as string,
|
|
};
|
|
|
|
endpoint = 'https://api.dropboxapi.com/2/files/delete_v2';
|
|
|
|
} else if (operation === 'move') {
|
|
// ----------------------------------
|
|
// move
|
|
// ----------------------------------
|
|
|
|
requestMethod = 'POST';
|
|
body = {
|
|
from_path: this.getNodeParameter('path', i) as string,
|
|
to_path: this.getNodeParameter('toPath', i) as string,
|
|
};
|
|
|
|
endpoint = 'https://api.dropboxapi.com/2/files/move_v2';
|
|
}
|
|
} else {
|
|
throw new NodeOperationError(this.getNode(), `The resource "${resource}" is not known!`);
|
|
}
|
|
|
|
if (resource === 'file' && operation === 'download') {
|
|
// Return the data as a buffer
|
|
options = { encoding: null };
|
|
}
|
|
|
|
let responseData;
|
|
|
|
if (returnAll === true) {
|
|
responseData = await dropboxpiRequestAllItems.call(this, property, requestMethod, endpoint, body, query, headers);
|
|
} else {
|
|
responseData = await dropboxApiRequest.call(this, requestMethod, endpoint, body, query, headers, options);
|
|
}
|
|
|
|
if (resource === 'file' && operation === 'upload') {
|
|
responseData = JSON.parse(responseData);
|
|
}
|
|
|
|
if (resource === 'file' && operation === 'download') {
|
|
|
|
const newItem: INodeExecutionData = {
|
|
json: items[i].json,
|
|
binary: {},
|
|
};
|
|
|
|
if (items[i].binary !== undefined) {
|
|
// Create a shallow copy of the binary data so that the old
|
|
// data references which do not get changed still stay behind
|
|
// but the incoming data does not get changed.
|
|
Object.assign(newItem.binary, items[i].binary);
|
|
}
|
|
|
|
items[i] = newItem;
|
|
|
|
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i) as string;
|
|
|
|
const filePathDownload = this.getNodeParameter('path', i) as string;
|
|
items[i].binary![dataPropertyNameDownload] = await this.helpers.prepareBinaryData(Buffer.from(responseData), filePathDownload);
|
|
|
|
} else if (resource === 'folder' && operation === 'list') {
|
|
|
|
const propNames: { [key: string]: string } = {
|
|
'id': 'id',
|
|
'name': 'name',
|
|
'client_modified': 'lastModifiedClient',
|
|
'server_modified': 'lastModifiedServer',
|
|
'rev': 'rev',
|
|
'size': 'contentSize',
|
|
'.tag': 'type',
|
|
'content_hash': 'contentHash',
|
|
'path_lower': 'pathLower',
|
|
'path_display': 'pathDisplay',
|
|
'has_explicit_shared_members': 'hasExplicitSharedMembers',
|
|
'is_downloadable': 'isDownloadable',
|
|
};
|
|
|
|
if (returnAll === false) {
|
|
responseData = responseData.entries;
|
|
}
|
|
|
|
for (const item of responseData) {
|
|
const newItem: IDataObject = {};
|
|
|
|
// Get the props and save them under a proper name
|
|
for (const propName of Object.keys(propNames)) {
|
|
if (item[propName] !== undefined) {
|
|
newItem[propNames[propName]] = item[propName];
|
|
}
|
|
}
|
|
|
|
returnData.push(newItem as IDataObject);
|
|
}
|
|
} else if (resource === 'search' && operation === 'query') {
|
|
if (returnAll === true) {
|
|
returnData.push.apply(returnData, (simple === true) ? simplify(responseData) : responseData);
|
|
} else {
|
|
returnData.push.apply(returnData, (simple === true) ? simplify(responseData[property]) : responseData[property]);
|
|
}
|
|
} else {
|
|
returnData.push(responseData);
|
|
}
|
|
} catch (error) {
|
|
if (this.continueOnFail()) {
|
|
if (resource === 'file' && operation === 'download'){
|
|
items[i].json = { error: error.message };
|
|
}else{
|
|
returnData.push({ error: error.message });
|
|
}
|
|
continue;
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
if (resource === 'file' && operation === 'download') {
|
|
// For file downloads the files get attached to the existing items
|
|
return this.prepareOutputData(items);
|
|
} else {
|
|
// For all other ones does the output items get replaced
|
|
return [this.helpers.returnJsonArray(returnData)];
|
|
}
|
|
}
|
|
}
|