feat(Google Calendar Node): Next occurrence property in recurring events (#8444)

This commit is contained in:
Michael Kret 2024-01-26 12:36:57 +00:00 committed by GitHub
parent 1db35c18e9
commit bf11c7c1bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 77 additions and 8 deletions

View file

@ -12,12 +12,12 @@ import type {
import { NodeApiError } from 'n8n-workflow'; import { NodeApiError } from 'n8n-workflow';
import moment from 'moment-timezone'; import moment from 'moment-timezone';
import { RRule } from 'rrule';
export async function googleApiRequest( export async function googleApiRequest(
this: IExecuteFunctions | ILoadOptionsFunctions | IPollFunctions, this: IExecuteFunctions | ILoadOptionsFunctions | IPollFunctions,
method: string, method: string,
resource: string, resource: string,
body: any = {}, body: any = {},
qs: IDataObject = {}, qs: IDataObject = {},
uri?: string, uri?: string,
@ -128,3 +128,54 @@ export async function getTimezones(
); );
return { results }; return { results };
} }
type RecurentEvent = {
start: {
dateTime: string;
timeZone: string;
};
end: {
dateTime: string;
timeZone: string;
};
recurrence: string[];
nextOccurrence?: {
start: {
dateTime: string;
timeZone: string;
};
end: {
dateTime: string;
timeZone: string;
};
};
};
export function addNextOccurrence(items: RecurentEvent[]) {
for (const item of items) {
if (item.recurrence) {
const rrule = RRule.fromString(item.recurrence[0]);
const until = rrule.options?.until;
const now = new Date();
if (until && until < now) {
continue;
}
const nextOccurrence = rrule.after(new Date());
item.nextOccurrence = {
start: {
dateTime: moment(nextOccurrence).format(),
timeZone: item.start.timeZone,
},
end: {
dateTime: moment(nextOccurrence)
.add(moment(item.end.dateTime).diff(moment(item.start.dateTime)))
.format(),
timeZone: item.end.timeZone,
},
};
}
}
return items;
}

View file

@ -13,6 +13,7 @@ import { NodeApiError, NodeOperationError } from 'n8n-workflow';
import moment from 'moment-timezone'; import moment from 'moment-timezone';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { import {
addNextOccurrence,
encodeURIComponentOnce, encodeURIComponentOnce,
getCalendars, getCalendars,
getTimezones, getTimezones,
@ -376,6 +377,10 @@ export class GoogleCalendar implements INodeType {
{}, {},
qs, qs,
); );
if (responseData) {
responseData = addNextOccurrence([responseData]);
}
} }
//https://developers.google.com/calendar/v3/reference/events/list //https://developers.google.com/calendar/v3/reference/events/list
if (operation === 'getAll') { if (operation === 'getAll') {
@ -440,6 +445,10 @@ export class GoogleCalendar implements INodeType {
); );
responseData = responseData.items; responseData = responseData.items;
} }
if (responseData) {
responseData = addNextOccurrence(responseData);
}
} }
//https://developers.google.com/calendar/v3/reference/events/patch //https://developers.google.com/calendar/v3/reference/events/patch
if (operation === 'update') { if (operation === 'update') {

View file

@ -880,6 +880,7 @@
"redis": "4.6.12", "redis": "4.6.12",
"rfc2047": "4.0.1", "rfc2047": "4.0.1",
"rhea": "1.0.24", "rhea": "1.0.24",
"rrule": "^2.8.1",
"rss-parser": "3.12.0", "rss-parser": "3.12.0",
"semver": "7.5.4", "semver": "7.5.4",
"showdown": "2.1.0", "showdown": "2.1.0",

View file

@ -171,7 +171,7 @@ importers:
dependencies: dependencies:
axios: axios:
specifier: 1.6.5 specifier: 1.6.5
version: 1.6.5(debug@3.2.7) version: 1.6.5(debug@4.3.4)
packages/@n8n/nodes-langchain: packages/@n8n/nodes-langchain:
dependencies: dependencies:
@ -390,7 +390,7 @@ importers:
version: 7.87.0 version: 7.87.0
axios: axios:
specifier: 1.6.5 specifier: 1.6.5
version: 1.6.5(debug@3.2.7) version: 1.6.5(debug@4.3.4)
basic-auth: basic-auth:
specifier: 2.0.1 specifier: 2.0.1
version: 2.0.1 version: 2.0.1
@ -736,7 +736,7 @@ importers:
version: 1.11.0 version: 1.11.0
axios: axios:
specifier: 1.6.5 specifier: 1.6.5
version: 1.6.5(debug@3.2.7) version: 1.6.5(debug@4.3.4)
concat-stream: concat-stream:
specifier: 2.0.0 specifier: 2.0.0
version: 2.0.0 version: 2.0.0
@ -1041,7 +1041,7 @@ importers:
version: 10.5.0(vue@3.3.4) version: 10.5.0(vue@3.3.4)
axios: axios:
specifier: 1.6.5 specifier: 1.6.5
version: 1.6.5(debug@3.2.7) version: 1.6.5(debug@4.3.4)
chart.js: chart.js:
specifier: ^4.4.0 specifier: ^4.4.0
version: 4.4.0 version: 4.4.0
@ -1359,6 +1359,9 @@ importers:
rhea: rhea:
specifier: 1.0.24 specifier: 1.0.24
version: 1.0.24 version: 1.0.24
rrule:
specifier: ^2.8.1
version: 2.8.1
rss-parser: rss-parser:
specifier: 3.12.0 specifier: 3.12.0
version: 3.12.0 version: 3.12.0
@ -12069,7 +12072,7 @@ packages:
/axios@0.21.4: /axios@0.21.4:
resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==}
dependencies: dependencies:
follow-redirects: 1.15.5(debug@3.2.7) follow-redirects: 1.15.5(debug@4.3.4)
transitivePeerDependencies: transitivePeerDependencies:
- debug - debug
dev: false dev: false
@ -12087,7 +12090,7 @@ packages:
/axios@1.6.5: /axios@1.6.5:
resolution: {integrity: sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==} resolution: {integrity: sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==}
dependencies: dependencies:
follow-redirects: 1.15.5(debug@3.2.7) follow-redirects: 1.15.5(debug@4.3.4)
form-data: 4.0.0 form-data: 4.0.0
proxy-from-env: 1.1.0 proxy-from-env: 1.1.0
transitivePeerDependencies: transitivePeerDependencies:
@ -12112,7 +12115,6 @@ packages:
proxy-from-env: 1.1.0 proxy-from-env: 1.1.0
transitivePeerDependencies: transitivePeerDependencies:
- debug - debug
dev: true
/babel-core@7.0.0-bridge.0(@babel/core@7.22.9): /babel-core@7.0.0-bridge.0(@babel/core@7.22.9):
resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==} resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==}
@ -23467,6 +23469,12 @@ packages:
resolution: {integrity: sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==} resolution: {integrity: sha512-2+MhsfPhvauN1O8KaXpXAOfR/fwe8dnUXVM+xw7yt40lJRfPVQxV6yryZm0cgRvAj5fMF/mdRZbL2ptwbs5i2g==}
dev: true dev: true
/rrule@2.8.1:
resolution: {integrity: sha512-hM3dHSBMeaJ0Ktp7W38BJZ7O1zOgaFEsn41PDk+yHoEtfLV+PoJt9E9xAlZiWgf/iqEqionN0ebHFZIDAp+iGw==}
dependencies:
tslib: 2.6.1
dev: false
/rrweb-cssom@0.6.0: /rrweb-cssom@0.6.0:
resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==}
dev: true dev: true