diff --git a/packages/nodes-base/nodes/Disqus/Disqus.node.ts b/packages/nodes-base/nodes/Disqus/Disqus.node.ts index 85eb133def..213da8ef4b 100644 --- a/packages/nodes-base/nodes/Disqus/Disqus.node.ts +++ b/packages/nodes-base/nodes/Disqus/Disqus.node.ts @@ -9,7 +9,7 @@ import { INodeType, } from 'n8n-workflow'; -import { OptionsWithUri } from 'request'; +import { disqusApiRequest, disqusApiRequestAllItems } from './GenericFunctions'; export class Disqus implements INodeType { @@ -164,6 +164,47 @@ export class Disqus implements INodeType { }, description: 'The short name(aka ID) of the forum to get.', }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'forum', + ], + operation: [ + 'getPosts', + ], + }, + }, + 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: [ + 'forum', + ], + operation: [ + 'getPosts', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 100, + description: 'How many results to return.', + }, { displayName: 'Additional Fields', name: 'additionalFields', @@ -261,6 +302,47 @@ export class Disqus implements INodeType { }, description: 'The short name(aka ID) of the forum to get Categories.', }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'forum', + ], + operation: [ + 'getCategories', + ], + }, + }, + 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: [ + 'forum', + ], + operation: [ + 'getCategories', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 100, + description: 'How many results to return.', + }, { displayName: 'Additional Fields', name: 'additionalFields', @@ -323,6 +405,47 @@ export class Disqus implements INodeType { }, description: 'The short name(aka ID) of the forum to get Threads.', }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'forum', + ], + operation: [ + 'getThreads', + ], + }, + }, + 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: [ + 'forum', + ], + operation: [ + 'getThreads', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 100, + }, + default: 100, + description: 'How many results to return.', + }, { displayName: 'Additional Fields', name: 'additionalFields', @@ -399,11 +522,6 @@ export class Disqus implements INodeType { const items = this.getInputData(); const returnData: IDataObject[] = []; - const credentials = this.getCredentials('disqusApi'); - - if (credentials === undefined) { - throw new Error('No credentials got returned!'); - } const resource = this.getNodeParameter('resource', 0) as string; const operation = this.getNodeParameter('operation', 0) as string; @@ -435,6 +553,13 @@ export class Disqus implements INodeType { Object.assign(qs, additionalFields); + try { + const responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint); + returnData.push(responseData.response); + } catch (error) { + throw error; + } + } else if (operation === 'getPosts') { // ---------------------------------- // getPosts @@ -445,12 +570,28 @@ export class Disqus implements INodeType { endpoint = 'forums/listPosts.json'; const id = this.getNodeParameter('id', i) as string; - qs.forum = id; - const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; - Object.assign(qs, additionalFields); + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + + qs.forum = id; + qs.limit = 100; + + try { + let responseData: IDataObject = {}; + if(returnAll) { + responseData.response = await disqusApiRequestAllItems.call(this, requestMethod, qs, endpoint); + } else { + const limit = this.getNodeParameter('limit', i) as string; + qs.limit = limit; + responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint); + } + returnData.push.apply(returnData, responseData.response as IDataObject[]); + } catch (error) { + throw error; + } + } else if (operation === 'getCategories') { // ---------------------------------- // getCategories @@ -461,12 +602,28 @@ export class Disqus implements INodeType { endpoint = 'forums/listCategories.json'; const id = this.getNodeParameter('id', i) as string; - qs.forum = id; - + const returnAll = this.getNodeParameter('returnAll', i) as boolean; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; - Object.assign(qs, additionalFields); + qs.forum = id; + qs.limit = 100; + + try { + let responseData: IDataObject = {}; + + if(returnAll) { + responseData.response = await disqusApiRequestAllItems.call(this, requestMethod, qs, endpoint); + } else { + const limit = this.getNodeParameter('limit', i) as string; + qs.limit = limit; + responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint) as IDataObject; + } + returnData.push.apply(returnData, responseData.response as IDataObject[]) ; + } catch (error) { + throw error; + } + } else if (operation === 'getThreads') { // ---------------------------------- // getThreads @@ -477,12 +634,29 @@ export class Disqus implements INodeType { endpoint = 'forums/listThreads.json'; const id = this.getNodeParameter('id', i) as string; + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + qs.forum = id; + qs.limit = 100; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; Object.assign(qs, additionalFields); + try { + let responseData: IDataObject = {}; + if(returnAll) { + responseData.response = await disqusApiRequestAllItems.call(this, requestMethod, qs, endpoint); + } else { + const limit = this.getNodeParameter('limit', i) as string; + qs.limit = limit; + responseData = await disqusApiRequest.call(this, requestMethod, qs, endpoint); + } + returnData.push.apply(returnData, responseData.response as IDataObject[]); + } catch (error) { + throw error; + } + } else { throw new Error(`The operation "${operation}" is not known!`); } @@ -490,41 +664,6 @@ export class Disqus implements INodeType { } else { throw new Error(`The resource "${resource}" is not known!`); } - - qs.api_key = credentials.accessToken; - endpoint = `https://disqus.com/api/3.0/${endpoint}`; - - const options: OptionsWithUri = { - method: requestMethod, - qs, - uri: endpoint, - json: true, - }; - - - let responseData; - try { - responseData = await this.helpers.request(options); - } catch (error) { - if (error.statusCode === 401) { - // Return a clear error - throw new Error('The Disqus credentials are not valid!'); - } - - if (error.error && error.error.error_summary) { - // Try to return the error prettier - throw new Error(`Disqus error response [${error.statusCode}]: ${error.error.error_summary}`); - } - - // If that data does not exist for some reason return the actual error - throw error; - } - - if (responseData && Array.isArray(responseData)) { - returnData.push.apply(returnData, responseData as IDataObject[]); - } else { - returnData.push(responseData as IDataObject); - } } return [this.helpers.returnJsonArray(returnData)]; diff --git a/packages/nodes-base/nodes/Disqus/GenericFunctions.ts b/packages/nodes-base/nodes/Disqus/GenericFunctions.ts new file mode 100644 index 0000000000..e5e5c1b7df --- /dev/null +++ b/packages/nodes-base/nodes/Disqus/GenericFunctions.ts @@ -0,0 +1,87 @@ +import { OptionsWithUri } from 'request'; +import { + IExecuteFunctions, + IExecuteSingleFunctions, + IHookFunctions, + ILoadOptionsFunctions, +} from 'n8n-core'; +import { IDataObject } from 'n8n-workflow'; + +export async function disqusApiRequest( + this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, + method: string, + qs: IDataObject = {}, + uri?: string, + body: any = {}, + option: IDataObject = {} + ): Promise { // tslint:disable-line:no-any + + const credentials = this.getCredentials('disqusApi') as IDataObject; + qs.api_key = credentials.accessToken; + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + + let options: OptionsWithUri = { + method, + qs, + body, + uri: `https://disqus.com/api/3.0/${uri}`, + json: true + }; + + options = Object.assign({}, options, option); + if (Object.keys(options.body).length === 0) { + delete options.body; + } + try { + const result = await this.helpers.request!(options) + return result; + } catch (error) { + console.log(error) + if (error.statusCode === 401) { + // Return a clear error + throw new Error('The Disqus credentials are not valid!'); + } + + if (error.error && error.error.error_summary) { + // Try to return the error prettier + throw new Error(`Disqus error response [${error.statusCode}]: ${error.error.error_summary}`); + } + + // If that data does not exist for some reason return the actual error + throw error; + } +} + +/** + * Make an API request to paginated flow endpoint + * and return all results + */ +export async function disqusApiRequestAllItems( + this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, + method: string, + qs: IDataObject = {}, + uri?: string, + body: any = {}, + option: IDataObject = {} + ): Promise { // tslint:disable-line:no-any + + const returnData: IDataObject[] = []; + + let responseData; + + try { + do { + responseData = await disqusApiRequest.call(this, method, qs, uri, body, option); + qs.cursor = responseData.cursor.id; + returnData.push.apply(returnData, responseData.response); + } while ( + responseData.cursor.more === true && + responseData.cursor.hasNext === true + ); + return returnData; + } catch(error) { + throw error; + } +}