From c172ac4879866547219de1f24d409fe91b4df331 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Mon, 30 Dec 2019 16:08:22 -0500 Subject: [PATCH 1/8] done --- .../credentials/WordpressApi.credentials.ts | 29 ++ .../nodes/Wordpress/Wordpress.node.ts | 279 ++++++++++++++++++ .../nodes-base/nodes/Wordpress/wordpress.png | Bin 0 -> 7110 bytes packages/nodes-base/package.json | 14 +- 4 files changed, 315 insertions(+), 7 deletions(-) create mode 100644 packages/nodes-base/credentials/WordpressApi.credentials.ts create mode 100644 packages/nodes-base/nodes/Wordpress/Wordpress.node.ts create mode 100644 packages/nodes-base/nodes/Wordpress/wordpress.png diff --git a/packages/nodes-base/credentials/WordpressApi.credentials.ts b/packages/nodes-base/credentials/WordpressApi.credentials.ts new file mode 100644 index 0000000000..abe75d55d1 --- /dev/null +++ b/packages/nodes-base/credentials/WordpressApi.credentials.ts @@ -0,0 +1,29 @@ +import { + ICredentialType, + NodePropertyTypes, +} from 'n8n-workflow'; + +export class WordpressApi implements ICredentialType { + name = 'wordpressApi'; + displayName = 'Wordpress API'; + properties = [ + { + displayName: 'Username', + name: 'username', + type: 'string' as NodePropertyTypes, + default: '', + }, + { + displayName: 'Password', + name: 'password', + type: 'string' as NodePropertyTypes, + default: '', + }, + { + displayName: 'Domain', + name: 'domain', + type: 'string' as NodePropertyTypes, + default: '', + }, + ]; +} diff --git a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts new file mode 100644 index 0000000000..4a5d5550a5 --- /dev/null +++ b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts @@ -0,0 +1,279 @@ +import { + IExecuteFunctions, +} from 'n8n-core'; +import { + IDataObject, + INodeTypeDescription, + INodeExecutionData, + INodeType, +} from 'n8n-workflow'; +// import { +// flowApiRequest, +// FlowApiRequestAllItems, +// } from './GenericFunctions'; +// import { +// taskOpeations, +// taskFields, +// } from './TaskDescription'; +// import { +// ITask, TaskInfo, +// } from './TaskInterface'; + +export class Wordpress implements INodeType { + description: INodeTypeDescription = { + displayName: 'Wordpress', + name: 'Wordpress', + icon: 'file:wordpress.png', + group: ['output'], + version: 1, + subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', + description: 'Consume Wordpress API', + defaults: { + name: 'Wordpress', + color: '#c02428', + }, + inputs: ['main'], + outputs: ['main'], + credentials: [ + { + name: 'wordpressApi', + required: true, + } + ], + properties: [ + { + displayName: 'Resource', + name: 'resource', + type: 'options', + options: [ + { + name: 'Post', + value: 'post', + description: `The primary unit within Flow; tasks track units of work and can be assigned, sorted, nested, and tagged.
+ Tasks can either be part of a List, or "private" (meaning "without a list", essentially).
+ Through this endpoint you are able to do anything you wish to your tasks in Flow, including create new ones.`, + }, + ], + default: 'task', + description: 'Resource to consume.', + }, + // ...taskOpeations, + // ...taskFields, + ], + }; + + async execute(this: IExecuteFunctions): Promise { + const credentials = this.getCredentials('flowApi'); + + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + + const items = this.getInputData(); + const returnData: IDataObject[] = []; + const length = items.length as unknown as number; + let responseData; + const qs: IDataObject = {}; + const resource = this.getNodeParameter('resource', 0) as string; + const operation = this.getNodeParameter('operation', 0) as string; + + // for (let i = 0; i < length; i++) { + // if (resource === 'task') { + // //https://developer.getflow.com/api/#tasks_create-task + // if (operation === 'create') { + // const workspaceId = this.getNodeParameter('workspaceId', i) as string; + // const name = this.getNodeParameter('name', i) as string; + // const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + // const body: ITask = { + // organization_id: credentials.organizationId as number, + // }; + // const task: TaskInfo = { + // name, + // workspace_id: parseInt(workspaceId, 10) + // }; + // if (additionalFields.ownerId) { + // task.owner_id = parseInt(additionalFields.ownerId as string, 10); + // } + // if (additionalFields.listId) { + // task.list_id = parseInt(additionalFields.listId as string, 10); + // } + // if (additionalFields.startsOn) { + // task.starts_on = additionalFields.startsOn as string; + // } + // if (additionalFields.dueOn) { + // task.due_on = additionalFields.dueOn as string; + // } + // if (additionalFields.mirrorParentSubscribers) { + // task.mirror_parent_subscribers = additionalFields.mirrorParentSubscribers as boolean; + // } + // if (additionalFields.mirrorParentTags) { + // task.mirror_parent_tags = additionalFields.mirrorParentTags as boolean; + // } + // if (additionalFields.noteContent) { + // task.note_content = additionalFields.noteContent as string; + // } + // if (additionalFields.noteMimeType) { + // task.note_mime_type = additionalFields.noteMimeType as string; + // } + // if (additionalFields.parentId) { + // task.parent_id = parseInt(additionalFields.parentId as string, 10); + // } + // if (additionalFields.positionList) { + // task.position_list = additionalFields.positionList as number; + // } + // if (additionalFields.positionUpcoming) { + // task.position_upcoming = additionalFields.positionUpcoming as number; + // } + // if (additionalFields.position) { + // task.position = additionalFields.position as number; + // } + // if (additionalFields.sectionId) { + // task.section_id = additionalFields.sectionId as number; + // } + // if (additionalFields.tags) { + // task.tags = (additionalFields.tags as string).split(','); + // } + // body.task = task; + // try { + // responseData = await flowApiRequest.call(this, 'POST', '/tasks', body); + // responseData = responseData.task; + // } catch (err) { + // throw new Error(`Flow Error: ${err.message}`); + // } + // } + // //https://developer.getflow.com/api/#tasks_update-a-task + // if (operation === 'update') { + // const workspaceId = this.getNodeParameter('workspaceId', i) as string; + // const taskId = this.getNodeParameter('taskId', i) as string; + // const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + // const body: ITask = { + // organization_id: credentials.organizationId as number, + // }; + // const task: TaskInfo = { + // workspace_id: parseInt(workspaceId, 10), + // id: parseInt(taskId, 10), + // }; + // if (updateFields.name) { + // task.name = updateFields.name as string; + // } + // if (updateFields.ownerId) { + // task.owner_id = parseInt(updateFields.ownerId as string, 10); + // } + // if (updateFields.listId) { + // task.list_id = parseInt(updateFields.listId as string, 10); + // } + // if (updateFields.startsOn) { + // task.starts_on = updateFields.startsOn as string; + // } + // if (updateFields.dueOn) { + // task.due_on = updateFields.dueOn as string; + // } + // if (updateFields.mirrorParentSubscribers) { + // task.mirror_parent_subscribers = updateFields.mirrorParentSubscribers as boolean; + // } + // if (updateFields.mirrorParentTags) { + // task.mirror_parent_tags = updateFields.mirrorParentTags as boolean; + // } + // if (updateFields.noteContent) { + // task.note_content = updateFields.noteContent as string; + // } + // if (updateFields.noteMimeType) { + // task.note_mime_type = updateFields.noteMimeType as string; + // } + // if (updateFields.parentId) { + // task.parent_id = parseInt(updateFields.parentId as string, 10); + // } + // if (updateFields.positionList) { + // task.position_list = updateFields.positionList as number; + // } + // if (updateFields.positionUpcoming) { + // task.position_upcoming = updateFields.positionUpcoming as number; + // } + // if (updateFields.position) { + // task.position = updateFields.position as number; + // } + // if (updateFields.sectionId) { + // task.section_id = updateFields.sectionId as number; + // } + // if (updateFields.tags) { + // task.tags = (updateFields.tags as string).split(','); + // } + // if (updateFields.completed) { + // task.completed = updateFields.completed as boolean; + // } + // body.task = task; + // try { + // responseData = await flowApiRequest.call(this, 'PUT', `/tasks/${taskId}`, body); + // responseData = responseData.task; + // } catch (err) { + // throw new Error(`Flow Error: ${err.message}`); + // } + // } + // //https://developer.getflow.com/api/#tasks_get-task + // if (operation === 'get') { + // const taskId = this.getNodeParameter('taskId', i) as string; + // const filters = this.getNodeParameter('filters', i) as IDataObject; + // qs.organization_id = credentials.organizationId as number; + // if (filters.include) { + // qs.include = (filters.include as string[]).join(','); + // } + // try { + // responseData = await flowApiRequest.call(this,'GET', `/tasks/${taskId}`, {}, qs); + // } catch (err) { + // throw new Error(`Flow Error: ${err.message}`); + // } + // } + // //https://developer.getflow.com/api/#tasks_get-tasks + // if (operation === 'getAll') { + // const returnAll = this.getNodeParameter('returnAll', i) as boolean; + // const filters = this.getNodeParameter('filters', i) as IDataObject; + // qs.organization_id = credentials.organizationId as number; + // if (filters.include) { + // qs.include = (filters.include as string[]).join(','); + // } + // if (filters.order) { + // qs.order = filters.order as string; + // } + // if (filters.workspaceId) { + // qs.workspace_id = filters.workspaceId as string; + // } + // if (filters.createdBefore) { + // qs.created_before = filters.createdBefore as string; + // } + // if (filters.createdAfter) { + // qs.created_after = filters.createdAfter as string; + // } + // if (filters.updateBefore) { + // qs.updated_before = filters.updateBefore as string; + // } + // if (filters.updateAfter) { + // qs.updated_after = filters.updateAfter as string; + // } + // if (filters.deleted) { + // qs.deleted = filters.deleted as boolean; + // } + // if (filters.cleared) { + // qs.cleared = filters.cleared as boolean; + // } + // try { + // if (returnAll === true) { + // responseData = await FlowApiRequestAllItems.call(this, 'tasks', 'GET', '/tasks', {}, qs); + // } else { + // qs.limit = this.getNodeParameter('limit', i) as number; + // responseData = await flowApiRequest.call(this, 'GET', '/tasks', {}, qs); + // responseData = responseData.tasks; + // } + // } catch (err) { + // throw new Error(`Flow Error: ${err.message}`); + // } + // } + // } + // if (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/Wordpress/wordpress.png b/packages/nodes-base/nodes/Wordpress/wordpress.png new file mode 100644 index 0000000000000000000000000000000000000000..55005aedffeb27ab83c5557f0d7f7f73f2a858cc GIT binary patch literal 7110 zcmaiZ2T)UM7cE_+SAl>Cp-V}jW9T9Djub^8kWi$P0HLFFM4AXFNL2x;q9W2kI#NU~ zy%*`dqrd}ipZ~u1GIMgy*=Mh{_FntTH_0SQPe+xK3_ym5hexTd1~<4k!!8d}l8bkl zpCcX@Cwz>7suEsF58Lv^%~dxwGYlRcIsN5;9f<(Dm zqeXDeZWq}XOgNc~OJ_6|$$@ira>2;pWP!gjWG=2R!yq8XuN17KEYMV2k3-qj1I-~W zA|?U`%8_w!aKJoJwlW5A#2@gBJ6WJT7V9Ph0(pCTi+GEQxO&)uAkxy(ATSgJg$iF} z2xEL)ut=P+3x?}=l0SLiXpD`AgB#Yt)rI4d7isP4iIoKcFNOYk{az=^<}V#LPY9MbIq1_n7h|0fcIH9-H}+gi#FzDVc#uM)5hw*MEN%O}4|_%GN+<^S)x|MK#}Dj3Q}2J3)zLjM}l zU*7$imZB5(-_gtbOS_#ME~hBtgmkf!1>%HJXj`PG6Ba1v?dIfa=PK;tibdnF!X9WZ zvtw@?AJ78;AjsAFEk3_;p+Tr>~6>l{!1%mfq#1W z&)zP}{WT032Nw($>0*Ochs$|-I-q34P|{#qF{G`qq%9OJ42FtX3rkB_OADjKkm3^7 zU{PBnN(=`2AMC%D*B{g=;n{ZFs|Fzrtx{#R64OahKTK$Ml>QeqH@3PedvR7^=)5du~b zmqJKLOa8_CH}oH(ziX=hZPR5h4i~-rL96utqx}c;e`s|*9PAuikWTQwrGHI9Sy2kA zqAVsQ1(gEB;Sh)-6d|D~DhWrxr9{OLl2U(`{2%y#Xk304WG+%JW`Mlh5ab{*(Er5# zk$=&djIswBiFNfba&>i*Q@q^gIMkh-JTX|0%P5Dkq4+Q9f2IAw@cWYe$NuwcIKM|P zb~ib)3*?_Wr5xF(ef2^-yleF8a780~;@am|%U;|LXxOZE?eLpfpaot9&^)sm844v( zCwf;~L_&}%aNX&aQdqPX+pU4oSdQCv?|*Zb(I_N#A1xpyI7ao2hs_NZr0u`Ayxyg~aCR$~Q0+_bpQk3d9x(lWn;Z07|3=%l=2Qb{ zjEz_fNmgyh*>5oUyYKD4&J85fCESktNPX-9Tc~8%Sia3ri{ElamW|NAtE3;czP4u6 zx47)be$@4TilB}@WUZ@)-$nLRdmyj>Tz`78KS*F*)6voKievDXRe%Cl@yxMY^hX0G z+n)51b|ZsjjU{q<18LhZPK$b*wpf?Nz9a#|9z^`6A}(A5h*F#x9UFVmM($&~TSRhj z^7D9ie+j~5f4I7|#7r`wPw~7*w4ko8j&rvny3kyZ<>X=@uP#BNa_+ScB>YB=spR2Z$Fgsvf zh-dicMP0~>Gyfz}X(W)MjCI%~bxJ%8!#vN&Zun!FEpa6&62XVT5eWLsg`gmYr^ z-GFWroNj)TOxQxwhh2&@$x&X-W$qJx@%XJkyk~Nc)rjxs{YE~JnSRTAV`Dyl5_kBfY{p&< zQuZv~j4FGEW=&}ukW?G7b^5y5h{086Q^#I=O*<>MVXrDJJ+*NDNhv-0aCTb+Riy9G z8aME5dS51wS`&CPp*s`UDVLmtt{d12v@>vuG{3t+xh&3 zrVNo8=(TKIo5OD=g#(5w-=9y%LDuw{z(fA(R)! zU}Vt*7PH7u9>dd{b;k5fE>_%#{kB;Yv@Bgxskkgqi@0KDbIV>wf97vE7qOCp&Q<$3x*sePbKuHIDyI0+*Swd zGFbbG#*izkWhl{Wpto~A^bGH?>M~G!Cnwl-$IXcC2eN(#*mU<+mUV|JH4tO2?do9h ze$mhe)EV!Qq!NZT+_Nh+hN+8gPeg4lR`1qn75EFsn;@c1Ui%MxBZ*Cr3>5epj|=kA z@KyI8C!&1poXu%8qk67HgTYqa)8Zo=Q}sbytcmp;&rVlcAG3ZIWL`tI_9|?J@Ye)2 z1moA|vRTz+FBpG=+hO+!C)I-JS8G&TtHQ&>ZDW4AzL)PZ+(^J_>8T1Lxw#l7C7UoL zw4p zjm@i>CmI&;i@f|JOoj5c=!+{Oma8WV4(IXskeRJ&s}u<9og3Vuwpj4=~vtQ zhw4RRRG6?NAErsUP!8vYv3yE>;r5PgzY$9uP&a@Q+E z`qim7uNcMGrPxnV)Vgo6#;VHk$$sv0XuztG;0Ry~-`r-nx62bJA8iGu+4+&26D9aP zaRwIDS-Y5@6V2RG4%^m{eW;ezpGhgFRw)5wfC@iPYBYFSR6<)gXv;i#WgP_WaXa{# zrf~~Vq8jC`ZzW~6|6(BFyScBfG?8>rYwBHQE@~fM7G(>%ViI#If7$XtGv(bcN|P-8 z29*Rukk9#Y#I%-&xobj1YGmA9BPNd&-*3Q^QiX!S?jn5ViW9uRX-ZP>M7*L?42vN} zH%!*sC8JV~LWf%w>iBL>zp~Rl{k=6?&k?|eN-rgzOIMSnN}i@#Pf(Yl=7!jDtkUF+ z#4P1Y7F?Eu@);<8bN=f$y5m!Bo&r2qLKB{nWIPtP8%EE`U~ z$G~JMo#vuIxwUWZ**Mx?fQe6v3p?zx~21L6DvwM}c^RI;5Qu(5n>RT0Z zJJnaDeJr@RVP`hA;bvH1>3#o9sPEnqzJwa7K*7;-5I~8Y3ODSQ`|{ZSR`f3Oa}!!x zE+X)d@2iit-GG#vlt<3M^`Q-VoOVL|kOh0EbZ>j-kp+2?DbS2k<*Q)%{0y`_hU#e$ zx1mM7pgMmAtH*LlrY_WoZtr?6| zv=y=!j56iJ-;zcS-b*PvK=%#>{+341md#&;7Dg9z5l8o3}Q(B8r zTx9DCsKX~sw#jDCW~QXfWeZE9NoRPFaGb#G9+CmtFwAG1dA9`^IA@;_D;wgPk=QC>tlyEJ)GM7I+@sC z2Zp&>W!MYm*n(qixFcV z)2UJec8Tj|u#Y=j$jdrmuyte;_zOsXKV1AY<&{%+YFUk#FN3ZD5?oWB=w2GnY9w_- z+>?Ji>M$+du4t}<>%fHN4$hbk7O>(@p9_o|t9KkKQBdAE8ckT1G76JbF_n26ez*P& zI-JK&n8THMty6HVMmoOHMqjmH!<;|LQlKICu{(fP>6O2(k}9jI>i6O(Zr(-BPo-rQ zy^2ZglFSy=@?C&hfN8?1KQsM{qH1Vh_ifI0eO&^5Qr)@2c7Jz1v0JQtq7;T+FT%ZT z95k;)#%R4U5~`sthA=zuPl7+?8@=jdx~m<^rjm5r(V}@$qfh730L_5#u&gpTGCsI& zM!2}2dZXb@YoQxi)E%gcPzjj6Am-`k;`dDS;hPD|zTwE)tN5!HS_F@3?`!bKEPt@7 zTorZY9_=uk9a^RxJVI=>UhSJUx*e-nf?HgJQK%>*=ldY_*cijU(b<6q#-kFOo>^1q z_1$;h6<9mo1ZwWQF#LjWOMX5oaO`vE;V|dt=VuOH21Z#L4Z%B~2fuE9Hl$VSV}mdQz0AEniYX;3Z^E-9S)_B-AlYO<2%m9W@@h53{-AX-T!G7iN7~whX}me2<*bg zLe3*2`2hs1gQ41Y<`==k8*jv)9g;c{&3{|pOQmQ&sWNWpY& z)U)b>G7+Mb+^tnvVpP$h8ECoJZk#bzb;duHEZW zzkdCi6wXS0bwf%ZrMOHfJZeCO{NaO88 zMq>I#u$yP=d)0vwe08yw4oUh`rnjiS{iz;XNK9iqpJ?C}+PCe2TiW4cH2HSWm|{Wx z+>!6bVdAT}z9%WId4o#`O-_|u@5MU7k2(wyqs`lie#?tA98@b5Fz=oDj>UdtxDICM zt-h(U$-{SYyS6ya)o5)(f^=oL`Lo6%6x$$bT#NW+(VZ&nvY-U1W4%Jp>SOk!jP@@j z^vx|-U$oC>^QJ4-ThdZ49_rgxNC^O(?}A^Ojmr-nRb8*4WPew&y;Ib*wb!=)WE~y# zhM(d|s&a90u^)3yUtqMwF^8BQ1ui0+Fl06N@DO?LyDyriOn}sCh%KlUwOY{xe9u8| zF&XLp6>q|U|M}o*zVy)jfjB!7^Kkr+%AkN%4NJs;9d|1m1@*Gu-UI`0#L}8m8Nrl2 z$T2-RrZ4NDl&X;e_W6XP^Vyf1$ZjcJSTNa8Bg{*l6flRBVt4g%sK0Kps{;HM&ahW( zJ&s6`IH9OEvR);d`097KQLDx=bA6}DH+rp+>1U+;$Yf)#%`|B)eAv#TcwUw+_7TR> zp9RsT^s_ z>+!*=g^KM#gX0~3$mxa$GsI⪙O#ktH9kxTBn`Ph-^y$+AZV-pnL60wIyd*FI}wn z>Dux(Xi#f!FSwuBmC`&4;DaK_6R%5ONPPqy6WSuIocU6DG{AMwr|;YjwS#CgG`1=F zAYmkBCN7uN5$Zu-o%2YGhTp8CYMDHkfR6W;pSpy@H?ZuzuhzlWm@{J}Cy`$WqU<94 z()1%U?CgsY*?$UVJk$*p56JzdLMXQ9f_beLiWx<{41gizBHn%kbWT4bKT}4m(6Jv7 zlM9i|m_Wm<=m|Gyb)rj!P6BDV+$=-e4X2OpWGhx*JMldhTG1W8+M`vg1NpQD)ktJ2 z2Mc+yE-%cOvv2Qq^gXze3T)!K%QYs29tiGFazm8vIJ2gg(yb6eeG6;P>2&Wg7^m=p zf(R82nY-r^yClk~Z4`h|%&L=UhMxL(#2r;rnCgkb*nV*9jAnXSF+;Iv>xipR>lS1UXM%kH>XeqZ25RlV7E4fP(Qo&-L& zmHG^GO($?GMREB&SX7mXNUbq|7C~0{^At9zP%Cj-8_St=kwVMz0>l!CL!0S$EfGEJ zG2SUs%s0Sj+d#EDNvR{=6G1ZmO}VIFbfII0ZMMI=_`rv%?h%>wR? z{p?hBs8fvB`Rb`lXhO0Eb#9xvy3_zth%5Mv)b2;p)sYRNgTtGT`ZunyH@H*Zk7wwN z(s}xl>RN{miGP%Kt5WNa<$>zgH}b{qpL|M zKX)H|k`7Dg3L@II2F(_Mqp^`CwhNg{7~^4vt~j94KkR8&)`PIvrGlR96_ z0|UXOVFl-)KrK7lh8DoM4r*I)mimQnfCt6c`1M?!@E&8 z?5VyDL-um!f=h^6Mw=pQxUV9q7PveWxo5mAM(&c(%L`!(a zrxEvZGG1UTOzmbh>G<25X~u~b(s(hI%Z0lyyeGFUDr0G66v6|Rir)1Ah;j>Q)p)Kn z{zQoU?18_vqqP>&nwSWc3_gyisAm4?*_A9zTN1FX?$%UA+Us)0_KvVRkjz3kdlk5r z)c?%|bILbK(`HYTbc(OP_iV_*uUOm6q{Q6El=)GbMkePAnj%Bon62n`8@PtLiwgQF z>wQ;BUINK9A7|=aP01UMwDV-bJxq;>tk)9NK580Pg>oG;)N-N&QzBDyA{Zrr8FtjP zvL6+H@Qudtg;h*N-ruS)d0Rc>!w0jL*Jf_pkA<=qusvy_Yo~{&#u1!IL{H>2;S92C zn7lyFsn3Kz{7i{$t|^s^^|Gk>1RN*UcJLE|_sW2d#*JV^o2BJFE>B4W71HaRZWOb< zYofCrfp(9@tVPYv(R_EAXU?_acgXB$;^}OeTpeD_pOC2QoQraxR`UB~g~iptSkmM4 z&hdL+HHd_KKW+fzx2#?XcxwEWu_h>l(OUXLOAw9mnaUCVQhR;dD>uXnn3sQ2X^M%) zL#C<4<0apY$^)PDxSqGeY=&vd;|Z@ogf)SBF>E)KhF&h@W&9YX5!OC^w%twHmUN@P zl3u@ZahOc`d*P2^7E*6nH7+%oQ+?ho(Xh{kQNbThm$&c1Ubo9x@hUMoFNoZK7ht9i zH92}6Yg6!T+NN=xobPKsU4wkrbaof*XuXkn!*twsdaF(N<2l|B7|fO4YM5)zIHI-4 s<_iXgVJ-7_k4jW!%!D<)eSgl{o9}_osUI7A`RAItiVnO)$?D<%0amlECjbBd literal 0 HcmV?d00001 diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 8d89334a2a..d0539c25f2 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -73,7 +73,8 @@ "dist/credentials/MandrillApi.credentials.js", "dist/credentials/TodoistApi.credentials.js", "dist/credentials/TypeformApi.credentials.js", - "dist/credentials/VeroApi.credentials.js" + "dist/credentials/VeroApi.credentials.js", + "dist/credentials/WordpressApi.credentials.js" ], "nodes": [ "dist/nodes/ActiveCampaign/ActiveCampaign.node.js", @@ -125,7 +126,8 @@ "dist/nodes/MoveBinaryData.node.js", "dist/nodes/MongoDb/MongoDb.node.js", "dist/nodes/MySql/MySql.node.js", - "dist/nodes/NextCloud/NextCloud.node.js", + "dist/nodes/NextCloud/NextCloud.node.js", + "dist/nodes/Mandrill/Mandrill.node.js", "dist/nodes/NoOp.node.js", "dist/nodes/OpenWeatherMap.node.js", "dist/nodes/Pipedrive/Pipedrive.node.js", @@ -157,11 +159,9 @@ "dist/nodes/Typeform/TypeformTrigger.node.js", "dist/nodes/Vero/Vero.node.js", "dist/nodes/WriteBinaryFile.node.js", - "dist/nodes/Webhook.node.js", - "dist/nodes/Xml.node.js", - "dist/nodes/Mandrill/Mandrill.node.js", - "dist/nodes/Todoist/Todoist.node.js", - "dist/nodes/Xml.node.js" + "dist/nodes/Webhook.node.js", + "dist/nodes/Wordpress/Wordpress.node.js", + "dist/nodes/Xml.node.js" ] }, "devDependencies": { From a6403fcc81bc08a29b61e9aeeeed42b79c0e74e2 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Tue, 31 Dec 2019 16:24:01 -0500 Subject: [PATCH 2/8] done --- .../nodes/Wordpress/GenericFunctions.ts | 51 +++ .../nodes/Wordpress/PostDescription.ts | 345 ++++++++++++++++++ .../nodes/Wordpress/Wordpress.node.ts | 28 +- 3 files changed, 407 insertions(+), 17 deletions(-) create mode 100644 packages/nodes-base/nodes/Wordpress/GenericFunctions.ts create mode 100644 packages/nodes-base/nodes/Wordpress/PostDescription.ts diff --git a/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts b/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts new file mode 100644 index 0000000000..46560b0bc2 --- /dev/null +++ b/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts @@ -0,0 +1,51 @@ +import { OptionsWithUri } from 'request'; +import { + IExecuteFunctions, + ILoadOptionsFunctions, + IExecuteSingleFunctions, + BINARY_ENCODING, +} from 'n8n-core'; +import { IDataObject } from 'n8n-workflow'; + +export async function wordpressApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, option: IDataObject = {}): Promise { // tslint:disable-line:no-any + const credentials = this.getCredentials('wordpressApi'); + if (credentials === undefined) { + throw new Error('No credentials got returned!'); + } + const data = Buffer.from(`${credentials!.username}:${credentials!.password}`).toString(BINARY_ENCODING); + const headerWithAuthentication = Object.assign({}, + { Authorization: `Basic ${data}`, Accept: 'application/json', 'Content-Type': 'application/json' }); + + let options: OptionsWithUri = { + headers: headerWithAuthentication, + method, + qs, + body, + uri: uri ||`${credentials!.domain}/wp-json/wp/v2${resource}`, + json: true + }; + options = Object.assign({}, options, option); + if (Object.keys(options.body).length === 0) { + delete options.body; + } + try { + return await this.helpers.request!(options); + } catch (error) { + let errorMessage = error.message; + if (error.response.body) { + errorMessage = error.response.body.message || error.response.body.Message || error.message; + } + + throw new Error(errorMessage); + } +} + +export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any + let result; + try { + result = JSON.parse(json!); + } catch (exception) { + result = undefined; + } + return result; +} diff --git a/packages/nodes-base/nodes/Wordpress/PostDescription.ts b/packages/nodes-base/nodes/Wordpress/PostDescription.ts new file mode 100644 index 0000000000..b07840fd80 --- /dev/null +++ b/packages/nodes-base/nodes/Wordpress/PostDescription.ts @@ -0,0 +1,345 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const postOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'post', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: ``, + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const postFields = [ + +/* -------------------------------------------------------------------------- */ +/* post:create */ +/* -------------------------------------------------------------------------- */ + + { + displayName: 'ID', + name: 'id', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ] + }, + }, + description: 'The unique identifier of the customer', + }, + { + displayName: 'JSON Parameters', + name: 'jsonParameters', + type: 'boolean', + default: false, + description: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ] + }, + } + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'The table to create the row in.', + }, + ] + }, + { + displayName: 'Data', + name: 'dataAttributesUi', + placeholder: 'Add Data', + description: 'key value pairs that represent the custom user properties you want to update', + type: 'fixedCollection', + typeOptions: { + multipleValues: true, + }, + default: {}, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ], + jsonParameters: [ + false, + ], + }, + }, + options: [ + { + name: 'dataAttributesValues', + displayName: 'Data', + values: [ + { + displayName: 'Key', + name: 'key', + type: 'string', + default: '', + description: 'Name of the property to set.', + }, + { + displayName: 'Value', + name: 'value', + type: 'string', + default: '', + description: 'Value of the property to set.', + }, + ] + }, + ], + }, + { + displayName: 'Data', + name: 'dataAttributesJson', + type: 'json', + default: '', + required: false, + typeOptions: { + alwaysOpenEditWindow: true, + }, + description: 'key value pairs that represent the custom user properties you want to update', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ], + jsonParameters: [ + true, + ], + }, + }, + }, + +/* -------------------------------------------------------------------------- */ +/* user:alias */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'ID', + name: 'id', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'alias', + ] + }, + }, + description: 'The old unique identifier of the user', + }, + { + displayName: 'New ID', + name: 'newId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'alias', + ] + }, + }, + description: 'The new unique identifier of the user', + }, +/* -------------------------------------------------------------------------- */ +/* user:unsubscribe */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'ID', + name: 'id', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'unsubscribe', + ] + }, + }, + description: 'The unique identifier of the user', + }, +/* -------------------------------------------------------------------------- */ +/* user:resubscribe */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'ID', + name: 'id', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'resubscribe', + ] + }, + }, + description: 'The unique identifier of the user', + }, +/* -------------------------------------------------------------------------- */ +/* user:delete */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'ID', + name: 'id', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'delete', + ] + }, + }, + description: 'The unique identifier of the user', + }, +/* -------------------------------------------------------------------------- */ +/* user:addTags */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'ID', + name: 'id', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'addTags', + ] + }, + }, + description: 'The unique identifier of the user', + }, + { + displayName: 'Tags', + name: 'tags', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'addTags', + ] + }, + }, + description: 'Tags to add separated by ","', + }, +/* -------------------------------------------------------------------------- */ +/* user:removeTags */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'ID', + name: 'id', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'removeTags', + ] + }, + }, + description: 'The unique identifier of the user', + }, + { + displayName: 'Tags', + name: 'tags', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'removeTags', + ] + }, + }, + description: 'Tags to remove separated by ","', + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts index 4a5d5550a5..0c31f57724 100644 --- a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts +++ b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts @@ -7,17 +7,13 @@ import { INodeExecutionData, INodeType, } from 'n8n-workflow'; -// import { -// flowApiRequest, -// FlowApiRequestAllItems, -// } from './GenericFunctions'; -// import { -// taskOpeations, -// taskFields, -// } from './TaskDescription'; -// import { -// ITask, TaskInfo, -// } from './TaskInterface'; +import { + wordpressApiRequest, +} from './GenericFunctions'; +import { + postOperations, + postFields, +} from './PostDescription'; export class Wordpress implements INodeType { description: INodeTypeDescription = { @@ -49,16 +45,14 @@ export class Wordpress implements INodeType { { name: 'Post', value: 'post', - description: `The primary unit within Flow; tasks track units of work and can be assigned, sorted, nested, and tagged.
- Tasks can either be part of a List, or "private" (meaning "without a list", essentially).
- Through this endpoint you are able to do anything you wish to your tasks in Flow, including create new ones.`, + description: ``, }, ], - default: 'task', + default: 'post', description: 'Resource to consume.', }, - // ...taskOpeations, - // ...taskFields, + ...postOperations, + ...postFields, ], }; From c490d4bc84b9985464a7d4067f136fc1383aa89a Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Wed, 1 Jan 2020 10:58:27 -0500 Subject: [PATCH 3/8] done --- .../nodes/Wordpress/GenericFunctions.ts | 23 ++ .../nodes/Wordpress/PostDescription.ts | 197 +++++++++--------- .../nodes/Wordpress/Wordpress.node.ts | 29 +++ 3 files changed, 154 insertions(+), 95 deletions(-) diff --git a/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts b/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts index 46560b0bc2..7148eed754 100644 --- a/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts @@ -40,6 +40,29 @@ export async function wordpressApiRequest(this: IExecuteFunctions | IExecuteSing } } +export async function intercomApiRequestAllItems(this: IExecuteFunctions, propertyName: string, method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise { // tslint:disable-line:no-any + + const returnData: IDataObject[] = []; + + let responseData; + + query.per_page = 10; + query.page = 1; + + let uri: string | undefined; + + do { + responseData = await wordpressApiRequest.call(this, method, endpoint, body, query, uri); + uri = responseData.pages.next; + } while ( + responseData.pages !== undefined && + responseData.pages.next !== undefined && + responseData.pages.next !== null + ); + + return returnData; +} + export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any let result; try { diff --git a/packages/nodes-base/nodes/Wordpress/PostDescription.ts b/packages/nodes-base/nodes/Wordpress/PostDescription.ts index b07840fd80..f914972d6e 100644 --- a/packages/nodes-base/nodes/Wordpress/PostDescription.ts +++ b/packages/nodes-base/nodes/Wordpress/PostDescription.ts @@ -31,39 +31,22 @@ export const postFields = [ /* -------------------------------------------------------------------------- */ { - displayName: 'ID', - name: 'id', + displayName: 'Title', + name: 'title', type: 'string', required: true, default: '', displayOptions: { show: { resource: [ - 'user', + 'post', ], operation: [ 'create', ] }, }, - description: 'The unique identifier of the customer', - }, - { - displayName: 'JSON Parameters', - name: 'jsonParameters', - type: 'boolean', - default: false, - description: '', - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'create', - ] - }, - } + description: 'The title for the post', }, { displayName: 'Additional Fields', @@ -74,7 +57,7 @@ export const postFields = [ displayOptions: { show: { resource: [ - 'user', + 'post', ], operation: [ 'create', @@ -83,84 +66,108 @@ export const postFields = [ }, options: [ { - displayName: 'Email', - name: 'email', + displayName: 'Content', + name: 'content', type: 'string', default: '', - description: 'The table to create the row in.', + description: 'The content for the post', + }, + { + displayName: 'Slug', + name: 'slug', + type: 'string', + default: '', + description: 'An alphanumeric identifier for the object unique to its type.', + }, + { + displayName: 'Password', + name: 'password', + type: 'string', + default: '', + description: 'A password to protect access to the content and excerpt.', + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + options: [ + { + name: 'Publish', + value: 'publish' + }, + { + name: 'Future', + value: 'future' + }, + { + name: 'Draft', + value: 'draft' + }, + { + name: 'Pending', + value: 'pending' + }, + { + name: 'Private', + value: 'private' + }, + ], + default: '', + description: 'A named status for the post.', + }, + { + displayName: 'Content Status', + name: 'contentStatus', + type: 'options', + options: [ + { + name: 'Open', + value: 'open' + }, + { + name: 'Close', + value: 'closed' + }, + ], + default: '', + description: 'Whether or not comments are open on the post.', + }, + { + displayName: 'Ping Status', + name: 'pingStatus', + type: 'options', + options: [ + { + name: 'Open', + value: 'open' + }, + { + name: 'Close', + value: 'closed' + }, + ], + default: '', + description: 'Whether or not comments are open on the post.', + }, + { + displayName: 'Sticky', + name: 'sticky', + type: 'boolean', + default: '', + description: 'Whether or not the object should be treated as sticky.', + }, + { + displayName: 'Categories', + name: 'categories', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getCategories', + }, + default: [], + description: 'The terms assigned to the object in the category taxonomy.', }, ] }, - { - displayName: 'Data', - name: 'dataAttributesUi', - placeholder: 'Add Data', - description: 'key value pairs that represent the custom user properties you want to update', - type: 'fixedCollection', - typeOptions: { - multipleValues: true, - }, - default: {}, - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'create', - ], - jsonParameters: [ - false, - ], - }, - }, - options: [ - { - name: 'dataAttributesValues', - displayName: 'Data', - values: [ - { - displayName: 'Key', - name: 'key', - type: 'string', - default: '', - description: 'Name of the property to set.', - }, - { - displayName: 'Value', - name: 'value', - type: 'string', - default: '', - description: 'Value of the property to set.', - }, - ] - }, - ], - }, - { - displayName: 'Data', - name: 'dataAttributesJson', - type: 'json', - default: '', - required: false, - typeOptions: { - alwaysOpenEditWindow: true, - }, - description: 'key value pairs that represent the custom user properties you want to update', - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'create', - ], - jsonParameters: [ - true, - ], - }, - }, - }, /* -------------------------------------------------------------------------- */ /* user:alias */ diff --git a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts index 0c31f57724..7f85df0092 100644 --- a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts +++ b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts @@ -6,6 +6,8 @@ import { INodeTypeDescription, INodeExecutionData, INodeType, + ILoadOptionsFunctions, + INodePropertyOptions, } from 'n8n-workflow'; import { wordpressApiRequest, @@ -56,6 +58,33 @@ export class Wordpress implements INodeType { ], }; + methods = { + loadOptions: { + // Get all the available categories to display them to user so that he can + // select them easily + async getCategories(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + let categories; + try { + categories = await wordpressApiRequest.call(this, 'GET', '/categories', {}); + } catch (err) { + throw new Error(`Mandrill Error: ${err}`); + } + for (const category of categories) { + const categoryName = category.name; + const categoryId = category.id; + + returnData.push({ + name: categoryName, + value: categoryId, + }); + } + + return returnData; + } + }, + }; + async execute(this: IExecuteFunctions): Promise { const credentials = this.getCredentials('flowApi'); From f16b8a57a08b0794a48716b0908f973a80c9669d Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Thu, 2 Jan 2020 17:34:48 -0500 Subject: [PATCH 4/8] :sparkles: Wordpress node --- .../nodes/Wordpress/GenericFunctions.ts | 14 +- .../nodes/Wordpress/PostDescription.ts | 772 ++++++++++++++---- .../nodes/Wordpress/PostInterface.ts | 15 + .../nodes/Wordpress/Wordpress.node.ts | 433 +++++----- 4 files changed, 862 insertions(+), 372 deletions(-) create mode 100644 packages/nodes-base/nodes/Wordpress/PostInterface.ts diff --git a/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts b/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts index 7148eed754..7229766c45 100644 --- a/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts @@ -40,24 +40,24 @@ export async function wordpressApiRequest(this: IExecuteFunctions | IExecuteSing } } -export async function intercomApiRequestAllItems(this: IExecuteFunctions, propertyName: string, method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise { // tslint:disable-line:no-any +export async function wordpressApiRequestAllItems(this: IExecuteFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: any = {}, query: IDataObject = {}): Promise { // tslint:disable-line:no-any const returnData: IDataObject[] = []; let responseData; query.per_page = 10; - query.page = 1; + query.page = 0; let uri: string | undefined; do { - responseData = await wordpressApiRequest.call(this, method, endpoint, body, query, uri); - uri = responseData.pages.next; + query.page++; + responseData = await wordpressApiRequest.call(this, method, endpoint, body, query, uri, { resolveWithFullResponse: true }); + returnData.push.apply(returnData, responseData.body); } while ( - responseData.pages !== undefined && - responseData.pages.next !== undefined && - responseData.pages.next !== null + responseData.headers['x-wp-totalpages'] !== undefined && + parseInt(responseData.headers['x-wp-totalpages'], 10) < query.page ); return returnData; diff --git a/packages/nodes-base/nodes/Wordpress/PostDescription.ts b/packages/nodes-base/nodes/Wordpress/PostDescription.ts index f914972d6e..727312ed1e 100644 --- a/packages/nodes-base/nodes/Wordpress/PostDescription.ts +++ b/packages/nodes-base/nodes/Wordpress/PostDescription.ts @@ -16,7 +16,27 @@ export const postOperations = [ { name: 'Create', value: 'create', - description: ``, + description: 'Create a post', + }, + { + name: 'Update', + value: 'update', + description: 'Update a post', + }, + { + name: 'Get', + value: 'get', + description: 'Get a post', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all posts', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a post', }, ], default: 'create', @@ -29,7 +49,6 @@ export const postFields = [ /* -------------------------------------------------------------------------- */ /* post:create */ /* -------------------------------------------------------------------------- */ - { displayName: 'Title', name: 'title', @@ -69,6 +88,9 @@ export const postFields = [ displayName: 'Content', name: 'content', type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, default: '', description: 'The content for the post', }, @@ -116,8 +138,8 @@ export const postFields = [ description: 'A named status for the post.', }, { - displayName: 'Content Status', - name: 'contentStatus', + displayName: 'Comment Status', + name: 'commentStatus', type: 'options', options: [ { @@ -149,11 +171,60 @@ export const postFields = [ default: '', description: 'Whether or not comments are open on the post.', }, + { + displayName: 'Format', + name: 'format', + type: 'options', + options: [ + { + name: 'Standard', + value: 'standard' + }, + { + name: 'Aside', + value: 'aside' + }, + { + name: 'Chat', + value: 'chat' + }, + { + name: 'Gallery', + value: 'gallery' + }, + { + name: 'Link', + value: 'link' + }, + { + name: 'Image', + value: 'image' + }, + { + name: 'Quote', + value: 'quote' + }, + { + name: 'Status', + value: 'status' + }, + { + name: 'Video', + value: 'video' + }, + { + name: 'Audio', + value: 'audio' + }, + ], + default: '', + description: 'Whether or not comments are open on the post.', + }, { displayName: 'Sticky', name: 'sticky', type: 'boolean', - default: '', + default: false, description: 'Whether or not the object should be treated as sticky.', }, { @@ -166,187 +237,574 @@ export const postFields = [ default: [], description: 'The terms assigned to the object in the category taxonomy.', }, + { + displayName: 'Tags', + name: 'tags', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getTags', + }, + default: [], + description: 'The terms assigned to the object in the post_tag taxonomy.', + }, ] }, +/* -------------------------------------------------------------------------- */ +/* post:update */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Post ID', + name: 'postId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'post', + ], + operation: [ + 'update', + ] + }, + }, + description: 'Unique identifier for the object.', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'post', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Title', + name: 'title', + type: 'string', + default: '', + description: 'The title for the post', + }, + { + displayName: 'Content', + name: 'content', + type: 'string', + typeOptions: { + alwaysOpenEditWindow: true, + }, + default: '', + description: 'The content for the post', + }, + { + displayName: 'Slug', + name: 'slug', + type: 'string', + default: '', + description: 'An alphanumeric identifier for the object unique to its type.', + }, + { + displayName: 'Password', + name: 'password', + type: 'string', + default: '', + description: 'A password to protect access to the content and excerpt.', + }, + { + displayName: 'Status', + name: 'status', + type: 'options', + options: [ + { + name: 'Publish', + value: 'publish' + }, + { + name: 'Future', + value: 'future' + }, + { + name: 'Draft', + value: 'draft' + }, + { + name: 'Pending', + value: 'pending' + }, + { + name: 'Private', + value: 'private' + }, + ], + default: '', + description: 'A named status for the post.', + }, + { + displayName: 'Comment Status', + name: 'commentStatus', + type: 'options', + options: [ + { + name: 'Open', + value: 'open' + }, + { + name: 'Close', + value: 'closed' + }, + ], + default: '', + description: 'Whether or not comments are open on the post.', + }, + { + displayName: 'Ping Status', + name: 'pingStatus', + type: 'options', + options: [ + { + name: 'Open', + value: 'open' + }, + { + name: 'Close', + value: 'closed' + }, + ], + default: '', + description: 'Whether or not comments are open on the post.', + }, + { + displayName: 'Format', + name: 'format', + type: 'options', + options: [ + { + name: 'Standard', + value: 'standard' + }, + { + name: 'Aside', + value: 'aside' + }, + { + name: 'Chat', + value: 'chat' + }, + { + name: 'Gallery', + value: 'gallery' + }, + { + name: 'Link', + value: 'link' + }, + { + name: 'Image', + value: 'image' + }, + { + name: 'Quote', + value: 'quote' + }, + { + name: 'Status', + value: 'status' + }, + { + name: 'Video', + value: 'video' + }, + { + name: 'Audio', + value: 'audio' + }, + ], + default: '', + description: 'Whether or not comments are open on the post.', + }, + { + displayName: 'Sticky', + name: 'sticky', + type: 'boolean', + default: false, + description: 'Whether or not the object should be treated as sticky.', + }, + { + displayName: 'Categories', + name: 'categories', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getCategories', + }, + default: [], + description: 'The terms assigned to the object in the category taxonomy.', + }, + { + displayName: 'Tags', + name: 'tags', + type: 'multiOptions', + typeOptions: { + loadOptionsMethod: 'getTags', + }, + default: [], + description: 'The terms assigned to the object in the post_tag taxonomy.', + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* post:get */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Post ID', + name: 'postId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'post', + ], + operation: [ + 'get', + ] + }, + }, + description: 'Unique identifier for the object.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + resource: [ + 'post', + ], + operation: [ + 'get', + ], + }, + }, + options: [ + { + displayName: 'Password', + name: 'password', + type: 'string', + default: '', + description: 'The password for the post if it is password protected.', + }, + { + displayName: 'Context', + name: 'context', + type: 'options', + options: [ + { + name: 'View', + value: 'view', + }, + { + name: 'Embed', + value: 'embed', + }, + { + name: 'Edit', + value: 'edit', + }, + ], + default: 'view', + description: 'Scope under which the request is made; determines fields present in response.', + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* post:getAll */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'post', + ], + operation: [ + 'getAll', + ], + }, + }, + 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: [ + 'post', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 10, + }, + default: 5, + description: 'How many results to return.', + }, + { + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource: [ + 'post', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Context', + name: 'context', + type: 'options', + options: [ + { + name: 'View', + value: 'view', + }, + { + name: 'Embed', + value: 'embed', + }, + { + name: 'Edit', + value: 'edit', + }, + ], + default: [], + description: 'Scope under which the request is made; determines fields present in response.', + }, + { + displayName: 'Order By', + name: 'orderBy', + type: 'options', + options: [ + { + name: 'Author', + value: 'author', + }, + { + name: 'Date', + value: 'date', + }, + { + name: 'ID', + value: 'id', + }, + { + name: 'ID', + value: 'id', + }, + { + name: 'Include', + value: 'include', + }, + { + name: 'Modified', + value: 'modified', + }, + { + name: 'Parent', + value: 'parent', + }, + { + name: 'Relevance', + value: 'relevance', + }, + { + name: 'Slug', + value: 'slug', + }, + { + name: 'Include Slugs', + value: 'includeSlugs', + }, + { + name: 'Title', + value: 'title', + }, + ], + default: [], + description: 'Sort collection by object attribute.', + }, + { + displayName: 'Order', + name: 'order', + type: 'options', + options: [ + { + name: 'Desc', + value: 'desc', + }, + { + name: 'Asc', + value: 'asc', + }, + ], + default: 'desc', + description: 'Order sort attribute ascending or descending.', + }, + { + displayName: 'Search', + name: 'search', + type: 'string', + default: '', + description: 'Limit results to those matching a string.', + }, + { + displayName: 'After', + name: 'after', + type: 'dateTime', + default: '', + description: 'Limit response to posts published after a given ISO8601 compliant date.', + }, + { + displayName: 'Before', + name: 'before', + type: 'dateTime', + default: '', + description: 'Limit response to posts published before a given ISO8601 compliant date.', + }, + { + displayName: 'Author', + name: 'author', + type: 'multiOptions', + default: [], + typeOptions: { + loadOptionsMethod: 'getAuthors', + }, + description: 'Limit result set to posts assigned to specific authors.', + }, + { + displayName: 'Categories', + name: 'categories', + type: 'multiOptions', + default: [], + typeOptions: { + loadOptionsMethod: 'getCategories', + }, + description: 'Limit result set to all items that have the specified term assigned in the categories taxonomy.', + }, + { + displayName: 'Exclude Categories', + name: 'excludedCategories', + type: 'multiOptions', + default: [], + typeOptions: { + loadOptionsMethod: 'getCategories', + }, + description: 'Limit result set to all items except those that have the specified term assigned in the categories taxonomy.', + }, + { + displayName: 'Tags', + name: 'tags', + type: 'multiOptions', + default: [], + typeOptions: { + loadOptionsMethod: 'getTags', + }, + description: 'Limit result set to all items that have the specified term assigned in the tags taxonomy.', + }, + { + displayName: 'Exclude Tags', + name: 'excludedTags', + type: 'multiOptions', + default: [], + typeOptions: { + loadOptionsMethod: 'getTags', + }, + description: 'Limit result set to all items except those that have the specified term assigned in the tags taxonomy.', + }, + { + displayName: 'Sticky', + name: 'sticky', + type: 'boolean', + default: false, + description: 'Limit result set to items that are sticky.', + }, -/* -------------------------------------------------------------------------- */ -/* user:alias */ -/* -------------------------------------------------------------------------- */ - { - displayName: 'ID', - name: 'id', - type: 'string', - required: true, - default: '', - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'alias', - ] - }, - }, - description: 'The old unique identifier of the user', - }, - { - displayName: 'New ID', - name: 'newId', - type: 'string', - required: true, - default: '', - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'alias', - ] - }, - }, - description: 'The new unique identifier of the user', + ] }, /* -------------------------------------------------------------------------- */ -/* user:unsubscribe */ +/* post:delete */ /* -------------------------------------------------------------------------- */ { - displayName: 'ID', - name: 'id', + displayName: 'Post ID', + name: 'postId', type: 'string', required: true, default: '', displayOptions: { show: { resource: [ - 'user', - ], - operation: [ - 'unsubscribe', - ] - }, - }, - description: 'The unique identifier of the user', - }, -/* -------------------------------------------------------------------------- */ -/* user:resubscribe */ -/* -------------------------------------------------------------------------- */ - { - displayName: 'ID', - name: 'id', - type: 'string', - required: true, - default: '', - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'resubscribe', - ] - }, - }, - description: 'The unique identifier of the user', - }, -/* -------------------------------------------------------------------------- */ -/* user:delete */ -/* -------------------------------------------------------------------------- */ - { - displayName: 'ID', - name: 'id', - type: 'string', - required: true, - default: '', - displayOptions: { - show: { - resource: [ - 'user', + 'post', ], operation: [ 'delete', ] }, }, - description: 'The unique identifier of the user', + description: 'Unique identifier for the object.', }, -/* -------------------------------------------------------------------------- */ -/* user:addTags */ -/* -------------------------------------------------------------------------- */ { - displayName: 'ID', - name: 'id', - type: 'string', - required: true, - default: '', + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, displayOptions: { show: { resource: [ - 'user', + 'post', ], operation: [ - 'addTags', - ] - }, - }, - description: 'The unique identifier of the user', - }, - { - displayName: 'Tags', - name: 'tags', - type: 'string', - required: true, - default: '', - displayOptions: { - show: { - resource: [ - 'user', + 'delete', ], - operation: [ - 'addTags', - ] }, }, - description: 'Tags to add separated by ","', - }, -/* -------------------------------------------------------------------------- */ -/* user:removeTags */ -/* -------------------------------------------------------------------------- */ - { - displayName: 'ID', - name: 'id', - type: 'string', - required: true, - default: '', - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'removeTags', - ] + options: [ + { + displayName: 'Force', + name: 'force', + type: 'boolean', + default: false, + description: 'Whether to bypass trash and force deletion.', }, - }, - description: 'The unique identifier of the user', - }, - { - displayName: 'Tags', - name: 'tags', - type: 'string', - required: true, - default: '', - displayOptions: { - show: { - resource: [ - 'user', - ], - operation: [ - 'removeTags', - ] - }, - }, - description: 'Tags to remove separated by ","', + ] }, ] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Wordpress/PostInterface.ts b/packages/nodes-base/nodes/Wordpress/PostInterface.ts new file mode 100644 index 0000000000..ad4b378a1d --- /dev/null +++ b/packages/nodes-base/nodes/Wordpress/PostInterface.ts @@ -0,0 +1,15 @@ + +export interface IPost { + id?: number; + title?: string; + content?: string; + slug?: string; + password?: string; + status?: string; + comment_status?: string; + ping_status?: string; + format?: string; + sticky?: boolean; + categories?: number[]; + tags?: number[]; +} diff --git a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts index 7f85df0092..488664ed8c 100644 --- a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts +++ b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts @@ -10,12 +10,15 @@ import { INodePropertyOptions, } from 'n8n-workflow'; import { - wordpressApiRequest, + wordpressApiRequest, wordpressApiRequestAllItems, } from './GenericFunctions'; import { postOperations, postFields, } from './PostDescription'; +import { + IPost, +} from './PostInterface'; export class Wordpress implements INodeType { description: INodeTypeDescription = { @@ -66,9 +69,9 @@ export class Wordpress implements INodeType { const returnData: INodePropertyOptions[] = []; let categories; try { - categories = await wordpressApiRequest.call(this, 'GET', '/categories', {}); + categories = await wordpressApiRequestAllItems.call(this, 'GET', '/categories', {}); } catch (err) { - throw new Error(`Mandrill Error: ${err}`); + throw new Error(`Wordpress Error: ${err}`); } for (const category of categories) { const categoryName = category.name; @@ -79,19 +82,54 @@ export class Wordpress implements INodeType { value: categoryId, }); } - return returnData; - } + }, + // Get all the available tags to display them to user so that he can + // select them easily + async getTags(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + let tags; + try { + tags = await wordpressApiRequestAllItems.call(this, 'GET', '/tags', {}); + } catch (err) { + throw new Error(`Wordpress Error: ${err}`); + } + for (const tag of tags) { + const tagName = tag.name; + const tagId = tag.id; + + returnData.push({ + name: tagName, + value: tagId, + }); + } + return returnData; + }, + // Get all the available authors to display them to user so that he can + // select them easily + async getAuthors(this: ILoadOptionsFunctions): Promise { + const returnData: INodePropertyOptions[] = []; + let authors; + try { + authors = await wordpressApiRequestAllItems.call(this, 'GET', '/users', {}, { who: 'authors' }); + } catch (err) { + throw new Error(`Wordpress Error: ${err}`); + } + for (const author of authors) { + const authorName = author.name; + const authorId = author.id; + + returnData.push({ + name: authorName, + value: authorId, + }); + } + return returnData; + }, }, }; async execute(this: IExecuteFunctions): Promise { - const credentials = this.getCredentials('flowApi'); - - if (credentials === undefined) { - throw new Error('No credentials got returned!'); - } - const items = this.getInputData(); const returnData: IDataObject[] = []; const length = items.length as unknown as number; @@ -100,203 +138,182 @@ export class Wordpress implements INodeType { const resource = this.getNodeParameter('resource', 0) as string; const operation = this.getNodeParameter('operation', 0) as string; - // for (let i = 0; i < length; i++) { - // if (resource === 'task') { - // //https://developer.getflow.com/api/#tasks_create-task - // if (operation === 'create') { - // const workspaceId = this.getNodeParameter('workspaceId', i) as string; - // const name = this.getNodeParameter('name', i) as string; - // const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; - // const body: ITask = { - // organization_id: credentials.organizationId as number, - // }; - // const task: TaskInfo = { - // name, - // workspace_id: parseInt(workspaceId, 10) - // }; - // if (additionalFields.ownerId) { - // task.owner_id = parseInt(additionalFields.ownerId as string, 10); - // } - // if (additionalFields.listId) { - // task.list_id = parseInt(additionalFields.listId as string, 10); - // } - // if (additionalFields.startsOn) { - // task.starts_on = additionalFields.startsOn as string; - // } - // if (additionalFields.dueOn) { - // task.due_on = additionalFields.dueOn as string; - // } - // if (additionalFields.mirrorParentSubscribers) { - // task.mirror_parent_subscribers = additionalFields.mirrorParentSubscribers as boolean; - // } - // if (additionalFields.mirrorParentTags) { - // task.mirror_parent_tags = additionalFields.mirrorParentTags as boolean; - // } - // if (additionalFields.noteContent) { - // task.note_content = additionalFields.noteContent as string; - // } - // if (additionalFields.noteMimeType) { - // task.note_mime_type = additionalFields.noteMimeType as string; - // } - // if (additionalFields.parentId) { - // task.parent_id = parseInt(additionalFields.parentId as string, 10); - // } - // if (additionalFields.positionList) { - // task.position_list = additionalFields.positionList as number; - // } - // if (additionalFields.positionUpcoming) { - // task.position_upcoming = additionalFields.positionUpcoming as number; - // } - // if (additionalFields.position) { - // task.position = additionalFields.position as number; - // } - // if (additionalFields.sectionId) { - // task.section_id = additionalFields.sectionId as number; - // } - // if (additionalFields.tags) { - // task.tags = (additionalFields.tags as string).split(','); - // } - // body.task = task; - // try { - // responseData = await flowApiRequest.call(this, 'POST', '/tasks', body); - // responseData = responseData.task; - // } catch (err) { - // throw new Error(`Flow Error: ${err.message}`); - // } - // } - // //https://developer.getflow.com/api/#tasks_update-a-task - // if (operation === 'update') { - // const workspaceId = this.getNodeParameter('workspaceId', i) as string; - // const taskId = this.getNodeParameter('taskId', i) as string; - // const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; - // const body: ITask = { - // organization_id: credentials.organizationId as number, - // }; - // const task: TaskInfo = { - // workspace_id: parseInt(workspaceId, 10), - // id: parseInt(taskId, 10), - // }; - // if (updateFields.name) { - // task.name = updateFields.name as string; - // } - // if (updateFields.ownerId) { - // task.owner_id = parseInt(updateFields.ownerId as string, 10); - // } - // if (updateFields.listId) { - // task.list_id = parseInt(updateFields.listId as string, 10); - // } - // if (updateFields.startsOn) { - // task.starts_on = updateFields.startsOn as string; - // } - // if (updateFields.dueOn) { - // task.due_on = updateFields.dueOn as string; - // } - // if (updateFields.mirrorParentSubscribers) { - // task.mirror_parent_subscribers = updateFields.mirrorParentSubscribers as boolean; - // } - // if (updateFields.mirrorParentTags) { - // task.mirror_parent_tags = updateFields.mirrorParentTags as boolean; - // } - // if (updateFields.noteContent) { - // task.note_content = updateFields.noteContent as string; - // } - // if (updateFields.noteMimeType) { - // task.note_mime_type = updateFields.noteMimeType as string; - // } - // if (updateFields.parentId) { - // task.parent_id = parseInt(updateFields.parentId as string, 10); - // } - // if (updateFields.positionList) { - // task.position_list = updateFields.positionList as number; - // } - // if (updateFields.positionUpcoming) { - // task.position_upcoming = updateFields.positionUpcoming as number; - // } - // if (updateFields.position) { - // task.position = updateFields.position as number; - // } - // if (updateFields.sectionId) { - // task.section_id = updateFields.sectionId as number; - // } - // if (updateFields.tags) { - // task.tags = (updateFields.tags as string).split(','); - // } - // if (updateFields.completed) { - // task.completed = updateFields.completed as boolean; - // } - // body.task = task; - // try { - // responseData = await flowApiRequest.call(this, 'PUT', `/tasks/${taskId}`, body); - // responseData = responseData.task; - // } catch (err) { - // throw new Error(`Flow Error: ${err.message}`); - // } - // } - // //https://developer.getflow.com/api/#tasks_get-task - // if (operation === 'get') { - // const taskId = this.getNodeParameter('taskId', i) as string; - // const filters = this.getNodeParameter('filters', i) as IDataObject; - // qs.organization_id = credentials.organizationId as number; - // if (filters.include) { - // qs.include = (filters.include as string[]).join(','); - // } - // try { - // responseData = await flowApiRequest.call(this,'GET', `/tasks/${taskId}`, {}, qs); - // } catch (err) { - // throw new Error(`Flow Error: ${err.message}`); - // } - // } - // //https://developer.getflow.com/api/#tasks_get-tasks - // if (operation === 'getAll') { - // const returnAll = this.getNodeParameter('returnAll', i) as boolean; - // const filters = this.getNodeParameter('filters', i) as IDataObject; - // qs.organization_id = credentials.organizationId as number; - // if (filters.include) { - // qs.include = (filters.include as string[]).join(','); - // } - // if (filters.order) { - // qs.order = filters.order as string; - // } - // if (filters.workspaceId) { - // qs.workspace_id = filters.workspaceId as string; - // } - // if (filters.createdBefore) { - // qs.created_before = filters.createdBefore as string; - // } - // if (filters.createdAfter) { - // qs.created_after = filters.createdAfter as string; - // } - // if (filters.updateBefore) { - // qs.updated_before = filters.updateBefore as string; - // } - // if (filters.updateAfter) { - // qs.updated_after = filters.updateAfter as string; - // } - // if (filters.deleted) { - // qs.deleted = filters.deleted as boolean; - // } - // if (filters.cleared) { - // qs.cleared = filters.cleared as boolean; - // } - // try { - // if (returnAll === true) { - // responseData = await FlowApiRequestAllItems.call(this, 'tasks', 'GET', '/tasks', {}, qs); - // } else { - // qs.limit = this.getNodeParameter('limit', i) as number; - // responseData = await flowApiRequest.call(this, 'GET', '/tasks', {}, qs); - // responseData = responseData.tasks; - // } - // } catch (err) { - // throw new Error(`Flow Error: ${err.message}`); - // } - // } - // } - // if (Array.isArray(responseData)) { - // returnData.push.apply(returnData, responseData as IDataObject[]); - // } else { - // returnData.push(responseData as IDataObject); - // } - // } + for (let i = 0; i < length; i++) { + if (resource === 'post') { + //https://developer.wordpress.org/rest-api/reference/posts/#create-a-post + if (operation === 'create') { + const title = this.getNodeParameter('title', i) as string; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + const body: IPost = { + title, + }; + if (additionalFields.content) { + body.content = additionalFields.content as string; + } + if (additionalFields.slug) { + body.slug = additionalFields.slug as string; + } + if (additionalFields.password) { + body.password = additionalFields.password as string; + } + if (additionalFields.status) { + body.status = additionalFields.status as string; + } + if (additionalFields.commentStatus) { + body.comment_status = additionalFields.commentStatus as string; + } + if (additionalFields.pingStatus) { + body.ping_status = additionalFields.pingStatus as string; + } + if (additionalFields.sticky) { + body.sticky = additionalFields.sticky as boolean; + } + if (additionalFields.categories) { + body.categories = additionalFields.categories as number[]; + } + if (additionalFields.tags) { + body.tags = additionalFields.tags as number[]; + } + if (additionalFields.format) { + body.format = additionalFields.format as string; + } + try{ + responseData = await wordpressApiRequest.call(this, 'POST', '/posts', body); + } catch (err) { + throw new Error(`Wordpress Error: ${err.message}`); + } + } + //https://developer.wordpress.org/rest-api/reference/posts/#update-a-post + if (operation === 'update') { + const postId = this.getNodeParameter('postId', i) as string; + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + const body: IPost = { + id: parseInt(postId, 10), + }; + if (updateFields.title) { + body.title = updateFields.title as string; + } + if (updateFields.content) { + body.content = updateFields.content as string; + } + if (updateFields.slug) { + body.slug = updateFields.slug as string; + } + if (updateFields.password) { + body.password = updateFields.password as string; + } + if (updateFields.status) { + body.status = updateFields.status as string; + } + if (updateFields.commentStatus) { + body.comment_status = updateFields.commentStatus as string; + } + if (updateFields.pingStatus) { + body.ping_status = updateFields.pingStatus as string; + } + if (updateFields.sticky) { + body.sticky = updateFields.sticky as boolean; + } + if (updateFields.categories) { + body.categories = updateFields.categories as number[]; + } + if (updateFields.tags) { + body.tags = updateFields.tags as number[]; + } + if (updateFields.format) { + body.format = updateFields.format as string; + } + try { + responseData = await wordpressApiRequest.call(this, 'POST', `/posts/${postId}`, body); + } catch (err) { + throw new Error(`Wordpress Error: ${err.message}`); + } + } + //https://developer.wordpress.org/rest-api/reference/posts/#retrieve-a-post + if (operation === 'get') { + const postId = this.getNodeParameter('postId', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + options.id = postId; + if (options.password) { + qs.password = options.password as string; + } + if (options.context) { + qs.context = options.context as string; + } + try { + responseData = await wordpressApiRequest.call(this,'GET', `/posts/${postId}`, {}, qs); + } catch (err) { + throw new Error(`Wordpress Error: ${err.message}`); + } + } + //https://developer.wordpress.org/rest-api/reference/posts/#list-posts + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const filters = this.getNodeParameter('filters', i) as IDataObject; + if (filters.context) { + qs.context = filters.context as string; + } + if (filters.orderBy) { + qs.orderby = filters.orderBy as string; + } + if (filters.order) { + qs.order = filters.order as string; + } + if (filters.search) { + qs.search = filters.search as string; + } + if (filters.after) { + qs.after = filters.after as string; + } + if (filters.author) { + qs.author = filters.author as number[]; + } + if (filters.categories) { + qs.categories = filters.categories as number[]; + } + if (filters.excludedCategories) { + qs.categories_exclude = filters.excludedCategories as number[]; + } + if (filters.tags) { + qs.tags = filters.tags as number[]; + } + if (filters.excludedTags) { + qs.tags_exclude = filters.excludedTags as number[]; + } + if (filters.sticky) { + qs.sticky = filters.sticky as boolean; + } + try { + if (returnAll === true) { + responseData = await wordpressApiRequestAllItems.call(this, 'GET', '/posts', {}, qs); + } else { + qs.per_page = this.getNodeParameter('limit', i) as number; + responseData = await wordpressApiRequest.call(this, 'GET', '/posts', {}, qs); + } + } catch (err) { + throw new Error(`Wordpress Error: ${err.message}`); + } + } + //https://developer.wordpress.org/rest-api/reference/posts/#delete-a-post + if (operation === 'delete') { + const postId = this.getNodeParameter('postId', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + if (options.force) { + qs.force = options.force as boolean; + } + try { + responseData = await wordpressApiRequest.call(this, 'DELETE', `/posts/${postId}`, {}, qs); + } catch (err) { + throw new Error(`Wordpress Error: ${err.message}`); + } + } + } + if (Array.isArray(responseData)) { + returnData.push.apply(returnData, responseData as IDataObject[]); + } else { + returnData.push(responseData as IDataObject); + } + } return [this.helpers.returnJsonArray(returnData)]; } } From f4aa1003ce22bd9bb575197e4c59b78aaf587a0a Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Thu, 2 Jan 2020 17:37:45 -0500 Subject: [PATCH 5/8] nodes order changed --- packages/nodes-base/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/nodes-base/package.json b/packages/nodes-base/package.json index 6dfb99e72d..f9578cb607 100644 --- a/packages/nodes-base/package.json +++ b/packages/nodes-base/package.json @@ -71,11 +71,11 @@ "dist/credentials/TwilioApi.credentials.js", "dist/credentials/TypeformApi.credentials.js", "dist/credentials/MandrillApi.credentials.js", - "dist/credentials/TodoistApi.credentials.js", - "dist/credentials/TypeformApi.credentials.js", + "dist/credentials/TodoistApi.credentials.js", + "dist/credentials/TypeformApi.credentials.js", + "dist/credentials/TogglApi.credentials.js", "dist/credentials/VeroApi.credentials.js", "dist/credentials/WordpressApi.credentials.js" - "dist/credentials/TogglApi.credentials.js", ], "nodes": [ "dist/nodes/ActiveCampaign/ActiveCampaign.node.js", From 770dd8b25c56ff7388c7017b0ef3e832ad34c2b0 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Fri, 3 Jan 2020 14:37:15 -0500 Subject: [PATCH 6/8] :sparkles: user resource done --- .../nodes/Wordpress/PostDescription.ts | 2 +- .../nodes/Wordpress/UserDescription.ts | 567 ++++++++++++++++++ .../nodes/Wordpress/UserInterface.ts | 14 + .../nodes/Wordpress/Wordpress.node.ts | 158 ++++- 4 files changed, 737 insertions(+), 4 deletions(-) create mode 100644 packages/nodes-base/nodes/Wordpress/UserDescription.ts create mode 100644 packages/nodes-base/nodes/Wordpress/UserInterface.ts diff --git a/packages/nodes-base/nodes/Wordpress/PostDescription.ts b/packages/nodes-base/nodes/Wordpress/PostDescription.ts index 727312ed1e..752667748c 100644 --- a/packages/nodes-base/nodes/Wordpress/PostDescription.ts +++ b/packages/nodes-base/nodes/Wordpress/PostDescription.ts @@ -652,7 +652,7 @@ export const postFields = [ }, { name: 'Include Slugs', - value: 'includeSlugs', + value: 'include_slugs', }, { name: 'Title', diff --git a/packages/nodes-base/nodes/Wordpress/UserDescription.ts b/packages/nodes-base/nodes/Wordpress/UserDescription.ts new file mode 100644 index 0000000000..62b1f1b2b1 --- /dev/null +++ b/packages/nodes-base/nodes/Wordpress/UserDescription.ts @@ -0,0 +1,567 @@ +import { INodeProperties } from 'n8n-workflow'; + +export const userOperations = [ + { + displayName: 'Operation', + name: 'operation', + type: 'options', + displayOptions: { + show: { + resource: [ + 'user', + ], + }, + }, + options: [ + { + name: 'Create', + value: 'create', + description: 'Create a user', + }, + { + name: 'Update', + value: 'update', + description: 'Update a user', + }, + { + name: 'Get', + value: 'get', + description: 'Get a user', + }, + { + name: 'Get All', + value: 'getAll', + description: 'Get all users', + }, + { + name: 'Delete', + value: 'delete', + description: 'Delete a user', + }, + ], + default: 'create', + description: 'The operation to perform.', + }, +] as INodeProperties[]; + +export const userFields = [ + +/* -------------------------------------------------------------------------- */ +/* user:create */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Username', + name: 'username', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Login name for the user.', + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Display name for the user.', + }, + { + displayName: 'Fistname', + name: 'firstName', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ] + }, + }, + description: 'First name for the user.', + }, + { + displayName: 'Lastname', + name: 'lastName', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Last name for the user.', + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ] + }, + }, + description: 'The email address for the user.', + }, + { + displayName: 'Password', + name: 'password', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ] + }, + }, + description: 'Password for the user (never included)', + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'create', + ], + }, + }, + options: [ + { + displayName: 'URL', + name: 'url', + type: 'string', + default: '', + description: 'URL of the user.', + }, + { + displayName: 'Description', + name: 'description', + typeOptions: { + alwaysOpenEditWindow: true, + }, + type: 'string', + default: '', + description: 'Description of the user.', + }, + { + displayName: 'Nickname', + name: 'nickname', + type: 'string', + default: '', + description: 'The nickname for the user.', + }, + { + displayName: 'Slug', + name: 'slug', + type: 'string', + default: '', + description: 'An alphanumeric identifier for the user.', + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* user:update */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'User ID', + name: 'userId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'update', + ] + }, + }, + description: 'Unique identifier for the user.', + }, + { + displayName: 'Update Fields', + name: 'updateFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'update', + ], + }, + }, + options: [ + { + displayName: 'Username', + name: 'username', + type: 'string', + default: '', + description: 'Login name for the user.', + }, + { + displayName: 'Name', + name: 'name', + type: 'string', + default: '', + description: 'Display name for the user.', + }, + { + displayName: 'Fistname', + name: 'firstName', + type: 'string', + default: '', + description: 'First name for the user.', + }, + { + displayName: 'Lastname', + name: 'lastName', + type: 'string', + default: '', + description: 'Last name for the user.', + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + default: '', + description: 'The email address for the user.', + }, + { + displayName: 'Password', + name: 'password', + type: 'password', + default: '', + description: 'Password for the user (never included)', + }, + { + displayName: 'URL', + name: 'url', + type: 'string', + default: '', + description: 'URL of the user.', + }, + { + displayName: 'Description', + name: 'description', + typeOptions: { + alwaysOpenEditWindow: true, + }, + type: 'string', + default: '', + description: 'Description of the user.', + }, + { + displayName: 'Nickname', + name: 'nickname', + type: 'string', + default: '', + description: 'The nickname for the user.', + }, + { + displayName: 'Slug', + name: 'slug', + type: 'string', + default: '', + description: 'An alphanumeric identifier for the user.', + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* user:get */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'User ID', + name: 'userId', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'get', + ] + }, + }, + description: 'Unique identifier for the user.', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'get', + ], + }, + }, + options: [ + { + displayName: 'Context', + name: 'context', + type: 'options', + options: [ + { + name: 'View', + value: 'view', + }, + { + name: 'Embed', + value: 'embed', + }, + { + name: 'Edit', + value: 'edit', + }, + ], + default: 'view', + description: 'Scope under which the request is made; determines fields present in response.', + }, + ] + }, +/* -------------------------------------------------------------------------- */ +/* user:getAll */ +/* -------------------------------------------------------------------------- */ +{ + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'getAll', + ], + }, + }, + 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: [ + 'user', + ], + operation: [ + 'getAll', + ], + returnAll: [ + false, + ], + }, + }, + typeOptions: { + minValue: 1, + maxValue: 10, + }, + default: 5, + description: 'How many results to return.', +}, +{ + displayName: 'Filters', + name: 'filters', + type: 'collection', + placeholder: 'Add Filter', + default: {}, + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'getAll', + ], + }, + }, + options: [ + { + displayName: 'Context', + name: 'context', + type: 'options', + options: [ + { + name: 'View', + value: 'view', + }, + { + name: 'Embed', + value: 'embed', + }, + { + name: 'Edit', + value: 'edit', + }, + ], + default: [], + description: 'Scope under which the request is made; determines fields present in response.', + }, + { + displayName: 'Order By', + name: 'orderBy', + type: 'options', + options: [ + { + name: 'Name', + value: 'name', + }, + { + name: 'ID', + value: 'id', + }, + { + name: 'Include', + value: 'include', + }, + { + name: 'Registered Date', + value: 'registered_date', + }, + { + name: 'Slug', + value: 'slug', + }, + { + name: 'Include Slugs', + value: 'include_slugs', + }, + { + name: 'Email', + value: 'email', + }, + { + name: 'URL', + value: 'url', + }, + ], + default: [], + description: 'Sort collection by object attribute.', + }, + { + displayName: 'Order', + name: 'order', + type: 'options', + options: [ + { + name: 'Desc', + value: 'desc', + }, + { + name: 'Asc', + value: 'asc', + }, + ], + default: 'desc', + description: 'Order sort attribute ascending or descending.', + }, + { + displayName: 'Search', + name: 'search', + type: 'string', + default: '', + description: 'Limit results to those matching a string.', + }, + { + displayName: 'Who', + name: 'who', + type: 'options', + options: [ + { + name: 'Authors', + value: 'authors', + }, + ], + default: 'authors', + description: 'Limit result set to users who are considered authors.', + }, + ] +}, +/* -------------------------------------------------------------------------- */ +/* user:delete */ +/* -------------------------------------------------------------------------- */ + { + displayName: 'Reassign', + name: 'reassign', + type: 'string', + required: true, + default: '', + displayOptions: { + show: { + resource: [ + 'user', + ], + operation: [ + 'delete', + ] + }, + }, + description: `Reassign the deleted user's posts and links to this user ID.`, + }, +] as INodeProperties[]; diff --git a/packages/nodes-base/nodes/Wordpress/UserInterface.ts b/packages/nodes-base/nodes/Wordpress/UserInterface.ts new file mode 100644 index 0000000000..9bcf3cdeac --- /dev/null +++ b/packages/nodes-base/nodes/Wordpress/UserInterface.ts @@ -0,0 +1,14 @@ + +export interface IUser { + id?: number; + username?: string; + name?: string; + first_name?: string; + nickname?: string; + slug?: string; + last_name?: string; + email?: string; + url?: string; + description?: string; + password?: string; +} diff --git a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts index 488664ed8c..f8e784c16d 100644 --- a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts +++ b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts @@ -10,15 +10,23 @@ import { INodePropertyOptions, } from 'n8n-workflow'; import { - wordpressApiRequest, wordpressApiRequestAllItems, + wordpressApiRequest, + wordpressApiRequestAllItems, } from './GenericFunctions'; import { postOperations, postFields, } from './PostDescription'; +import { + userOperations, + userFields, +} from './UserDescription'; import { IPost, } from './PostInterface'; +import { + IUser, +} from './UserInterface'; export class Wordpress implements INodeType { description: INodeTypeDescription = { @@ -50,7 +58,12 @@ export class Wordpress implements INodeType { { name: 'Post', value: 'post', - description: ``, + description: '', + }, + { + name: 'User', + value: 'user', + description: '', }, ], default: 'post', @@ -58,6 +71,8 @@ export class Wordpress implements INodeType { }, ...postOperations, ...postFields, + ...userOperations, + ...userFields, ], }; @@ -233,7 +248,6 @@ export class Wordpress implements INodeType { if (operation === 'get') { const postId = this.getNodeParameter('postId', i) as string; const options = this.getNodeParameter('options', i) as IDataObject; - options.id = postId; if (options.password) { qs.password = options.password as string; } @@ -308,6 +322,144 @@ export class Wordpress implements INodeType { } } } + if (resource === 'user') { + //https://developer.wordpress.org/rest-api/reference/users/#create-a-user + if (operation === 'create') { + const name = this.getNodeParameter('name', i) as string; + const username = this.getNodeParameter('username', i) as string; + const firstName = this.getNodeParameter('firstName', i) as string; + const lastName = this.getNodeParameter('lastName', i) as string; + const email = this.getNodeParameter('email', i) as string; + const password = this.getNodeParameter('password', i) as string; + const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; + const body: IUser = { + name, + username, + first_name: firstName, + last_name: lastName, + email, + password, + }; + // if (operation === 'update') { + // const userId = this.getNodeParameter('userId', i) as number; + // body.id = userId; + // } + if (additionalFields.url) { + body.url = additionalFields.url as string; + } + if (additionalFields.description) { + body.description = additionalFields.description as string; + } + if (additionalFields.nickname) { + body.nickname = additionalFields.nickname as string; + } + if (additionalFields.slug) { + body.slug = additionalFields.slug as string; + } + try{ + responseData = await wordpressApiRequest.call(this, 'POST', '/users', body); + } catch (err) { + throw new Error(`Wordpress Error: ${err.message}`); + } + } + //https://developer.wordpress.org/rest-api/reference/users/#update-a-user + if (operation === 'update') { + const userId = this.getNodeParameter('userId', i) as number; + const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; + const body: IUser = { + id: userId, + }; + if (updateFields.name) { + body.name = updateFields.name as string; + } + if (updateFields.firstName) { + body.first_name = updateFields.firstName as string; + } + if (updateFields.lastName) { + body.last_name = updateFields.lastName as string; + } + if (updateFields.email) { + body.email = updateFields.email as string; + } + if (updateFields.password) { + body.password = updateFields.password as string; + } + if (updateFields.username) { + body.username = updateFields.username as string; + } + if (updateFields.url) { + body.url = updateFields.url as string; + } + if (updateFields.description) { + body.description = updateFields.description as string; + } + if (updateFields.nickname) { + body.nickname = updateFields.nickname as string; + } + if (updateFields.slug) { + body.slug = updateFields.slug as string; + } + try{ + responseData = await wordpressApiRequest.call(this, 'POST', `/users/${userId}`, body); + } catch (err) { + throw new Error(`Wordpress Error: ${err.message}`); + } + } + //https://developer.wordpress.org/rest-api/reference/users/#retrieve-a-user + if (operation === 'get') { + const userId = this.getNodeParameter('userId', i) as string; + const options = this.getNodeParameter('options', i) as IDataObject; + if (options.context) { + qs.context = options.context as string; + } + try { + responseData = await wordpressApiRequest.call(this,'GET', `/users/${userId}`, {}, qs); + } catch (err) { + throw new Error(`Wordpress Error: ${err.message}`); + } + } + //https://developer.wordpress.org/rest-api/reference/users/#list-users + if (operation === 'getAll') { + const returnAll = this.getNodeParameter('returnAll', i) as boolean; + const filters = this.getNodeParameter('filters', i) as IDataObject; + if (filters.context) { + qs.context = filters.context as string; + } + if (filters.orderBy) { + qs.orderby = filters.orderBy as string; + } + if (filters.order) { + qs.order = filters.order as string; + } + if (filters.search) { + qs.search = filters.search as string; + } + if (filters.who) { + qs.who = filters.who as string; + } + try { + if (returnAll === true) { + responseData = await wordpressApiRequestAllItems.call(this, 'GET', '/users', {}, qs); + } else { + qs.per_page = this.getNodeParameter('limit', i) as number; + responseData = await wordpressApiRequest.call(this, 'GET', '/users', {}, qs); + } + } catch (err) { + throw new Error(`Wordpress Error: ${err.message}`); + } + } + //https://developer.wordpress.org/rest-api/reference/users/#delete-a-user + if (operation === 'delete') { + const reassign = this.getNodeParameter('reassign', i) as string; + qs.reassign = reassign; + qs.force = true; + try { + responseData = await wordpressApiRequest.call(this, 'DELETE', `/users/me`, {}, qs); + } catch (err) { + throw new Error(`Wordpress Error: ${err.message}`); + } + } + } if (Array.isArray(responseData)) { returnData.push.apply(returnData, responseData as IDataObject[]); } else { From 76186cfe88f30acc9d85451096429f2a019d58ce Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Fri, 3 Jan 2020 14:42:41 -0500 Subject: [PATCH 7/8] removed comment --- packages/nodes-base/nodes/Wordpress/Wordpress.node.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts index f8e784c16d..03735a5617 100644 --- a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts +++ b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts @@ -340,10 +340,6 @@ export class Wordpress implements INodeType { email, password, }; - // if (operation === 'update') { - // const userId = this.getNodeParameter('userId', i) as number; - // body.id = userId; - // } if (additionalFields.url) { body.url = additionalFields.url as string; } From 0cb190401187fa88afe082e616ab3eddf330d304 Mon Sep 17 00:00:00 2001 From: Jan Oberhauser Date: Fri, 3 Jan 2020 21:47:19 -0600 Subject: [PATCH 8/8] :zap: Improve some things on Wordpress-Node --- .../credentials/WordpressApi.credentials.ts | 5 +- .../nodes/Wordpress/GenericFunctions.ts | 33 ++-- .../nodes/Wordpress/PostDescription.ts | 142 +++++++------- .../nodes/Wordpress/UserDescription.ts | 64 +++---- .../nodes/Wordpress/Wordpress.node.ts | 175 ++++++------------ 5 files changed, 176 insertions(+), 243 deletions(-) diff --git a/packages/nodes-base/credentials/WordpressApi.credentials.ts b/packages/nodes-base/credentials/WordpressApi.credentials.ts index abe75d55d1..25829ffbd3 100644 --- a/packages/nodes-base/credentials/WordpressApi.credentials.ts +++ b/packages/nodes-base/credentials/WordpressApi.credentials.ts @@ -20,10 +20,11 @@ export class WordpressApi implements ICredentialType { default: '', }, { - displayName: 'Domain', - name: 'domain', + displayName: 'Wordpress URL', + name: 'url', type: 'string' as NodePropertyTypes, default: '', + placeholder: 'https://example.com', }, ]; } diff --git a/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts b/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts index 7229766c45..e526017b52 100644 --- a/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Wordpress/GenericFunctions.ts @@ -1,9 +1,8 @@ import { OptionsWithUri } from 'request'; import { IExecuteFunctions, - ILoadOptionsFunctions, IExecuteSingleFunctions, - BINARY_ENCODING, + ILoadOptionsFunctions, } from 'n8n-core'; import { IDataObject } from 'n8n-workflow'; @@ -12,16 +11,20 @@ export async function wordpressApiRequest(this: IExecuteFunctions | IExecuteSing if (credentials === undefined) { throw new Error('No credentials got returned!'); } - const data = Buffer.from(`${credentials!.username}:${credentials!.password}`).toString(BINARY_ENCODING); - const headerWithAuthentication = Object.assign({}, - { Authorization: `Basic ${data}`, Accept: 'application/json', 'Content-Type': 'application/json' }); let options: OptionsWithUri = { - headers: headerWithAuthentication, + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + }, + auth: { + user: credentials!.username as string, + password: credentials!.password as string, + }, method, qs, body, - uri: uri ||`${credentials!.domain}/wp-json/wp/v2${resource}`, + uri: uri ||`${credentials!.url}/wp-json/wp/v2${resource}`, json: true }; options = Object.assign({}, options, option); @@ -36,7 +39,7 @@ export async function wordpressApiRequest(this: IExecuteFunctions | IExecuteSing errorMessage = error.response.body.message || error.response.body.Message || error.message; } - throw new Error(errorMessage); + throw new Error('Wordpress Error: ' + errorMessage); } } @@ -49,11 +52,9 @@ export async function wordpressApiRequestAllItems(this: IExecuteFunctions | ILoa query.per_page = 10; query.page = 0; - let uri: string | undefined; - do { query.page++; - responseData = await wordpressApiRequest.call(this, method, endpoint, body, query, uri, { resolveWithFullResponse: true }); + responseData = await wordpressApiRequest.call(this, method, endpoint, body, query, undefined, { resolveWithFullResponse: true }); returnData.push.apply(returnData, responseData.body); } while ( responseData.headers['x-wp-totalpages'] !== undefined && @@ -62,13 +63,3 @@ export async function wordpressApiRequestAllItems(this: IExecuteFunctions | ILoa return returnData; } - -export function validateJSON(json: string | undefined): any { // tslint:disable-line:no-any - let result; - try { - result = JSON.parse(json!); - } catch (exception) { - result = undefined; - } - return result; -} diff --git a/packages/nodes-base/nodes/Wordpress/PostDescription.ts b/packages/nodes-base/nodes/Wordpress/PostDescription.ts index 752667748c..d14f3b3292 100644 --- a/packages/nodes-base/nodes/Wordpress/PostDescription.ts +++ b/packages/nodes-base/nodes/Wordpress/PostDescription.ts @@ -18,11 +18,11 @@ export const postOperations = [ value: 'create', description: 'Create a post', }, - { - name: 'Update', - value: 'update', - description: 'Update a post', - }, + // { + // name: 'Delete', + // value: 'delete', + // description: 'Delete a post', + // }, { name: 'Get', value: 'get', @@ -34,9 +34,9 @@ export const postOperations = [ description: 'Get all posts', }, { - name: 'Delete', - value: 'delete', - description: 'Delete a post', + name: 'Update', + value: 'update', + description: 'Update a post', }, ], default: 'create', @@ -114,27 +114,27 @@ export const postFields = [ type: 'options', options: [ { - name: 'Publish', - value: 'publish' + name: 'Draft', + value: 'draft', }, { name: 'Future', - value: 'future' - }, - { - name: 'Draft', - value: 'draft' + value: 'future', }, { name: 'Pending', - value: 'pending' + value: 'pending', }, { name: 'Private', - value: 'private' + value: 'private', + }, + { + name: 'Publish', + value: 'publish', }, ], - default: '', + default: 'draft', description: 'A named status for the post.', }, { @@ -144,14 +144,14 @@ export const postFields = [ options: [ { name: 'Open', - value: 'open' + value: 'open', }, { name: 'Close', - value: 'closed' + value: 'closed', }, ], - default: '', + default: 'open', description: 'Whether or not comments are open on the post.', }, { @@ -161,15 +161,15 @@ export const postFields = [ options: [ { name: 'Open', - value: 'open' + value: 'open', }, { name: 'Close', - value: 'closed' + value: 'closed', }, ], - default: '', - description: 'Whether or not comments are open on the post.', + default: 'open', + description: 'If the a message should be send to announce the post.', }, { displayName: 'Format', @@ -178,46 +178,46 @@ export const postFields = [ options: [ { name: 'Standard', - value: 'standard' + value: 'standard', }, { name: 'Aside', - value: 'aside' + value: 'aside', }, { name: 'Chat', - value: 'chat' + value: 'chat', }, { name: 'Gallery', - value: 'gallery' + value: 'gallery', }, { name: 'Link', - value: 'link' + value: 'link', }, { name: 'Image', - value: 'image' + value: 'image', }, { name: 'Quote', - value: 'quote' + value: 'quote', }, { name: 'Status', - value: 'status' + value: 'status', }, { name: 'Video', - value: 'video' + value: 'video', }, { name: 'Audio', - value: 'audio' + value: 'audio', }, ], - default: '', + default: 'standard', description: 'Whether or not comments are open on the post.', }, { @@ -325,26 +325,26 @@ export const postFields = [ options: [ { name: 'Publish', - value: 'publish' + value: 'publish', }, { name: 'Future', - value: 'future' + value: 'future', }, { name: 'Draft', - value: 'draft' + value: 'draft', }, { name: 'Pending', - value: 'pending' + value: 'pending', }, { name: 'Private', - value: 'private' + value: 'private', }, ], - default: '', + default: 'draft', description: 'A named status for the post.', }, { @@ -354,14 +354,14 @@ export const postFields = [ options: [ { name: 'Open', - value: 'open' + value: 'open', }, { name: 'Close', - value: 'closed' + value: 'closed', }, ], - default: '', + default: 'open', description: 'Whether or not comments are open on the post.', }, { @@ -371,14 +371,14 @@ export const postFields = [ options: [ { name: 'Open', - value: 'open' + value: 'open', }, { name: 'Close', - value: 'closed' + value: 'closed', }, ], - default: '', + default: 'open', description: 'Whether or not comments are open on the post.', }, { @@ -388,47 +388,47 @@ export const postFields = [ options: [ { name: 'Standard', - value: 'standard' + value: 'standard', }, { name: 'Aside', - value: 'aside' + value: 'aside', }, { name: 'Chat', - value: 'chat' + value: 'chat', }, { name: 'Gallery', - value: 'gallery' + value: 'gallery', }, { name: 'Link', - value: 'link' + value: 'link', }, { name: 'Image', - value: 'image' + value: 'image', }, { name: 'Quote', - value: 'quote' + value: 'quote', }, { name: 'Status', - value: 'status' + value: 'status', }, { name: 'Video', - value: 'video' + value: 'video', }, { name: 'Audio', - value: 'audio' + value: 'audio', }, ], - default: '', - description: 'Whether or not comments are open on the post.', + default: 'standard', + description: 'The format of the post.', }, { displayName: 'Sticky', @@ -572,10 +572,10 @@ export const postFields = [ description: 'How many results to return.', }, { - displayName: 'Filters', - name: 'filters', + displayName: 'Options', + name: 'options', type: 'collection', - placeholder: 'Add Filter', + placeholder: 'Add Option', default: {}, displayOptions: { show: { @@ -606,7 +606,7 @@ export const postFields = [ value: 'edit', }, ], - default: [], + default: 'view', description: 'Scope under which the request is made; determines fields present in response.', }, { @@ -626,10 +626,6 @@ export const postFields = [ name: 'ID', value: 'id', }, - { - name: 'ID', - value: 'id', - }, { name: 'Include', value: 'include', @@ -659,7 +655,7 @@ export const postFields = [ value: 'title', }, ], - default: [], + default: 'id', description: 'Sort collection by object attribute.', }, { @@ -668,12 +664,12 @@ export const postFields = [ type: 'options', options: [ { - name: 'Desc', - value: 'desc', + name: 'ASC', + value: 'asc', }, { - name: 'Asc', - value: 'asc', + name: 'DESC', + value: 'desc', }, ], default: 'desc', diff --git a/packages/nodes-base/nodes/Wordpress/UserDescription.ts b/packages/nodes-base/nodes/Wordpress/UserDescription.ts index 62b1f1b2b1..a9d413bf1b 100644 --- a/packages/nodes-base/nodes/Wordpress/UserDescription.ts +++ b/packages/nodes-base/nodes/Wordpress/UserDescription.ts @@ -18,11 +18,11 @@ export const userOperations = [ value: 'create', description: 'Create a user', }, - { - name: 'Update', - value: 'update', - description: 'Update a user', - }, + // { + // name: 'Delete', + // value: 'delete', + // description: 'Delete a user', + // }, { name: 'Get', value: 'get', @@ -34,9 +34,9 @@ export const userOperations = [ description: 'Get all users', }, { - name: 'Delete', - value: 'delete', - description: 'Delete a user', + name: 'Update', + value: 'update', + description: 'Update a user', }, ], default: 'create', @@ -86,7 +86,7 @@ export const userFields = [ description: 'Display name for the user.', }, { - displayName: 'Fistname', + displayName: 'First Name', name: 'firstName', type: 'string', required: true, @@ -104,7 +104,7 @@ export const userFields = [ description: 'First name for the user.', }, { - displayName: 'Lastname', + displayName: 'Last Name', name: 'lastName', type: 'string', required: true, @@ -260,14 +260,14 @@ export const userFields = [ description: 'Display name for the user.', }, { - displayName: 'Fistname', + displayName: 'First Name', name: 'firstName', type: 'string', default: '', description: 'First name for the user.', }, { - displayName: 'Lastname', + displayName: 'Last Name', name: 'lastName', type: 'string', default: '', @@ -283,7 +283,7 @@ export const userFields = [ { displayName: 'Password', name: 'password', - type: 'password', + type: 'string', default: '', description: 'Password for the user (never included)', }, @@ -426,10 +426,10 @@ export const userFields = [ description: 'How many results to return.', }, { - displayName: 'Filters', - name: 'filters', + displayName: 'Options', + name: 'options', type: 'collection', - placeholder: 'Add Filter', + placeholder: 'Add Option', default: {}, displayOptions: { show: { @@ -460,7 +460,7 @@ export const userFields = [ value: 'edit', }, ], - default: [], + default: 'view', description: 'Scope under which the request is made; determines fields present in response.', }, { @@ -469,8 +469,8 @@ export const userFields = [ type: 'options', options: [ { - name: 'Name', - value: 'name', + name: 'Email', + value: 'email', }, { name: 'ID', @@ -480,6 +480,14 @@ export const userFields = [ name: 'Include', value: 'include', }, + { + name: 'Include Slugs', + value: 'include_slugs', + }, + { + name: 'Name', + value: 'name', + }, { name: 'Registered Date', value: 'registered_date', @@ -488,20 +496,12 @@ export const userFields = [ name: 'Slug', value: 'slug', }, - { - name: 'Include Slugs', - value: 'include_slugs', - }, - { - name: 'Email', - value: 'email', - }, { name: 'URL', value: 'url', }, ], - default: [], + default: 'id', description: 'Sort collection by object attribute.', }, { @@ -510,12 +510,12 @@ export const userFields = [ type: 'options', options: [ { - name: 'Desc', - value: 'desc', + name: 'ASC', + value: 'asc', }, { - name: 'Asc', - value: 'asc', + name: 'DESC', + value: 'desc', }, ], default: 'desc', diff --git a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts index 03735a5617..93d4df9de9 100644 --- a/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts +++ b/packages/nodes-base/nodes/Wordpress/Wordpress.node.ts @@ -3,10 +3,10 @@ import { } from 'n8n-core'; import { IDataObject, + ILoadOptionsFunctions, INodeTypeDescription, INodeExecutionData, INodeType, - ILoadOptionsFunctions, INodePropertyOptions, } from 'n8n-workflow'; import { @@ -14,12 +14,12 @@ import { wordpressApiRequestAllItems, } from './GenericFunctions'; import { - postOperations, postFields, + postOperations, } from './PostDescription'; import { - userOperations, userFields, + userOperations, } from './UserDescription'; import { IPost, @@ -31,7 +31,7 @@ import { export class Wordpress implements INodeType { description: INodeTypeDescription = { displayName: 'Wordpress', - name: 'Wordpress', + name: 'wordpress', icon: 'file:wordpress.png', group: ['output'], version: 1, @@ -39,7 +39,7 @@ export class Wordpress implements INodeType { description: 'Consume Wordpress API', defaults: { name: 'Wordpress', - color: '#c02428', + color: '#016087', }, inputs: ['main'], outputs: ['main'], @@ -82,12 +82,7 @@ export class Wordpress implements INodeType { // select them easily async getCategories(this: ILoadOptionsFunctions): Promise { const returnData: INodePropertyOptions[] = []; - let categories; - try { - categories = await wordpressApiRequestAllItems.call(this, 'GET', '/categories', {}); - } catch (err) { - throw new Error(`Wordpress Error: ${err}`); - } + const categories = await wordpressApiRequestAllItems.call(this, 'GET', '/categories', {}); for (const category of categories) { const categoryName = category.name; const categoryId = category.id; @@ -103,12 +98,7 @@ export class Wordpress implements INodeType { // select them easily async getTags(this: ILoadOptionsFunctions): Promise { const returnData: INodePropertyOptions[] = []; - let tags; - try { - tags = await wordpressApiRequestAllItems.call(this, 'GET', '/tags', {}); - } catch (err) { - throw new Error(`Wordpress Error: ${err}`); - } + const tags = await wordpressApiRequestAllItems.call(this, 'GET', '/tags', {}); for (const tag of tags) { const tagName = tag.name; const tagId = tag.id; @@ -124,12 +114,7 @@ export class Wordpress implements INodeType { // select them easily async getAuthors(this: ILoadOptionsFunctions): Promise { const returnData: INodePropertyOptions[] = []; - let authors; - try { - authors = await wordpressApiRequestAllItems.call(this, 'GET', '/users', {}, { who: 'authors' }); - } catch (err) { - throw new Error(`Wordpress Error: ${err}`); - } + const authors = await wordpressApiRequestAllItems.call(this, 'GET', '/users', {}, { who: 'authors' }); for (const author of authors) { const authorName = author.name; const authorId = author.id; @@ -192,11 +177,7 @@ export class Wordpress implements INodeType { if (additionalFields.format) { body.format = additionalFields.format as string; } - try{ - responseData = await wordpressApiRequest.call(this, 'POST', '/posts', body); - } catch (err) { - throw new Error(`Wordpress Error: ${err.message}`); - } + responseData = await wordpressApiRequest.call(this, 'POST', '/posts', body); } //https://developer.wordpress.org/rest-api/reference/posts/#update-a-post if (operation === 'update') { @@ -238,11 +219,7 @@ export class Wordpress implements INodeType { if (updateFields.format) { body.format = updateFields.format as string; } - try { - responseData = await wordpressApiRequest.call(this, 'POST', `/posts/${postId}`, body); - } catch (err) { - throw new Error(`Wordpress Error: ${err.message}`); - } + responseData = await wordpressApiRequest.call(this, 'POST', `/posts/${postId}`, body); } //https://developer.wordpress.org/rest-api/reference/posts/#retrieve-a-post if (operation === 'get') { @@ -254,58 +231,50 @@ export class Wordpress implements INodeType { if (options.context) { qs.context = options.context as string; } - try { - responseData = await wordpressApiRequest.call(this,'GET', `/posts/${postId}`, {}, qs); - } catch (err) { - throw new Error(`Wordpress Error: ${err.message}`); - } + responseData = await wordpressApiRequest.call(this,'GET', `/posts/${postId}`, {}, qs); } //https://developer.wordpress.org/rest-api/reference/posts/#list-posts if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i) as boolean; - const filters = this.getNodeParameter('filters', i) as IDataObject; - if (filters.context) { - qs.context = filters.context as string; + const options = this.getNodeParameter('options', i) as IDataObject; + if (options.context) { + qs.context = options.context as string; } - if (filters.orderBy) { - qs.orderby = filters.orderBy as string; + if (options.orderBy) { + qs.orderby = options.orderBy as string; } - if (filters.order) { - qs.order = filters.order as string; + if (options.order) { + qs.order = options.order as string; } - if (filters.search) { - qs.search = filters.search as string; + if (options.search) { + qs.search = options.search as string; } - if (filters.after) { - qs.after = filters.after as string; + if (options.after) { + qs.after = options.after as string; } - if (filters.author) { - qs.author = filters.author as number[]; + if (options.author) { + qs.author = options.author as number[]; } - if (filters.categories) { - qs.categories = filters.categories as number[]; + if (options.categories) { + qs.categories = options.categories as number[]; } - if (filters.excludedCategories) { - qs.categories_exclude = filters.excludedCategories as number[]; + if (options.excludedCategories) { + qs.categories_exclude = options.excludedCategories as number[]; } - if (filters.tags) { - qs.tags = filters.tags as number[]; + if (options.tags) { + qs.tags = options.tags as number[]; } - if (filters.excludedTags) { - qs.tags_exclude = filters.excludedTags as number[]; + if (options.excludedTags) { + qs.tags_exclude = options.excludedTags as number[]; } - if (filters.sticky) { - qs.sticky = filters.sticky as boolean; + if (options.sticky) { + qs.sticky = options.sticky as boolean; } - try { - if (returnAll === true) { - responseData = await wordpressApiRequestAllItems.call(this, 'GET', '/posts', {}, qs); - } else { - qs.per_page = this.getNodeParameter('limit', i) as number; - responseData = await wordpressApiRequest.call(this, 'GET', '/posts', {}, qs); - } - } catch (err) { - throw new Error(`Wordpress Error: ${err.message}`); + if (returnAll === true) { + responseData = await wordpressApiRequestAllItems.call(this, 'GET', '/posts', {}, qs); + } else { + qs.per_page = this.getNodeParameter('limit', i) as number; + responseData = await wordpressApiRequest.call(this, 'GET', '/posts', {}, qs); } } //https://developer.wordpress.org/rest-api/reference/posts/#delete-a-post @@ -315,11 +284,7 @@ export class Wordpress implements INodeType { if (options.force) { qs.force = options.force as boolean; } - try { - responseData = await wordpressApiRequest.call(this, 'DELETE', `/posts/${postId}`, {}, qs); - } catch (err) { - throw new Error(`Wordpress Error: ${err.message}`); - } + responseData = await wordpressApiRequest.call(this, 'DELETE', `/posts/${postId}`, {}, qs); } } if (resource === 'user') { @@ -352,11 +317,7 @@ export class Wordpress implements INodeType { if (additionalFields.slug) { body.slug = additionalFields.slug as string; } - try{ - responseData = await wordpressApiRequest.call(this, 'POST', '/users', body); - } catch (err) { - throw new Error(`Wordpress Error: ${err.message}`); - } + responseData = await wordpressApiRequest.call(this, 'POST', '/users', body); } //https://developer.wordpress.org/rest-api/reference/users/#update-a-user if (operation === 'update') { @@ -395,11 +356,7 @@ export class Wordpress implements INodeType { if (updateFields.slug) { body.slug = updateFields.slug as string; } - try{ - responseData = await wordpressApiRequest.call(this, 'POST', `/users/${userId}`, body); - } catch (err) { - throw new Error(`Wordpress Error: ${err.message}`); - } + responseData = await wordpressApiRequest.call(this, 'POST', `/users/${userId}`, body); } //https://developer.wordpress.org/rest-api/reference/users/#retrieve-a-user if (operation === 'get') { @@ -408,40 +365,32 @@ export class Wordpress implements INodeType { if (options.context) { qs.context = options.context as string; } - try { - responseData = await wordpressApiRequest.call(this,'GET', `/users/${userId}`, {}, qs); - } catch (err) { - throw new Error(`Wordpress Error: ${err.message}`); - } + responseData = await wordpressApiRequest.call(this,'GET', `/users/${userId}`, {}, qs); } //https://developer.wordpress.org/rest-api/reference/users/#list-users if (operation === 'getAll') { const returnAll = this.getNodeParameter('returnAll', i) as boolean; - const filters = this.getNodeParameter('filters', i) as IDataObject; - if (filters.context) { - qs.context = filters.context as string; + const options = this.getNodeParameter('options', i) as IDataObject; + if (options.context) { + qs.context = options.context as string; } - if (filters.orderBy) { - qs.orderby = filters.orderBy as string; + if (options.orderBy) { + qs.orderby = options.orderBy as string; } - if (filters.order) { - qs.order = filters.order as string; + if (options.order) { + qs.order = options.order as string; } - if (filters.search) { - qs.search = filters.search as string; + if (options.search) { + qs.search = options.search as string; } - if (filters.who) { - qs.who = filters.who as string; + if (options.who) { + qs.who = options.who as string; } - try { - if (returnAll === true) { - responseData = await wordpressApiRequestAllItems.call(this, 'GET', '/users', {}, qs); - } else { - qs.per_page = this.getNodeParameter('limit', i) as number; - responseData = await wordpressApiRequest.call(this, 'GET', '/users', {}, qs); - } - } catch (err) { - throw new Error(`Wordpress Error: ${err.message}`); + if (returnAll === true) { + responseData = await wordpressApiRequestAllItems.call(this, 'GET', '/users', {}, qs); + } else { + qs.per_page = this.getNodeParameter('limit', i) as number; + responseData = await wordpressApiRequest.call(this, 'GET', '/users', {}, qs); } } //https://developer.wordpress.org/rest-api/reference/users/#delete-a-user @@ -449,11 +398,7 @@ export class Wordpress implements INodeType { const reassign = this.getNodeParameter('reassign', i) as string; qs.reassign = reassign; qs.force = true; - try { - responseData = await wordpressApiRequest.call(this, 'DELETE', `/users/me`, {}, qs); - } catch (err) { - throw new Error(`Wordpress Error: ${err.message}`); - } + responseData = await wordpressApiRequest.call(this, 'DELETE', `/users/me`, {}, qs); } } if (Array.isArray(responseData)) {