From fa720358d916900ac4fdba35991f6b0ea2904eb4 Mon Sep 17 00:00:00 2001 From: martmull Date: Mon, 20 Jul 2026 13:49:21 +0200 Subject: [PATCH] Ignore call-recorder bots for unsupported meeting platforms (#23050) ## What The call-recorder scheduled a Recall bot for any calendar event that had a conference link, even when the link pointed to a platform Recall cannot join (e.g. ro.am, Daily, Whereby, or a plain dial-in). Those requests could never produce a recording. This adds a supported-platform check to the recording policy so unsupported links are ignored, with a dedicated reason, and documents the supported platforms in the app README. ## Changes - Add `SUPPORTED_MEETING_PLATFORM_URL_PATTERNS` constant (Zoom, Google Meet, Microsoft Teams, Webex, GoTo Meeting), extracted from the existing link-extraction patterns so extraction and validation share one source of truth. - Add `isSupportedMeetingPlatformUrl` util. - `resolveCallRecorderPolicyResult` now returns `UNSUPPORTED_MEETING_PLATFORM` (bot not required) when the resolved conference link is not a supported platform. - Document supported platforms and the ignore behavior in the call-recorder README. ## Tests - New unit tests for `isSupportedMeetingPlatformUrl`. - New policy test for the unsupported-platform case; updated existing policy tests to use real supported URLs. - All call-recorder unit tests pass; typecheck and lint clean. Closes twentyhq/core-team-issues#2705 --- _Generated by [Claude Code](https://claude.ai/code/session_01MWPkbdUg4QMdj4FM5mtNww)_ Review in cubic --- .../public/call-recorder/README.md | 14 ++++++++ ...all-recorder-lifecycle.integration-test.ts | 2 +- ...supported-meeting-platform-url-patterns.ts | 12 +++++++ .../build-call-recorder-policy-result.test.ts | 2 +- .../is-supported-meeting-platform-url.test.ts | 36 +++++++++++++++++++ ...esolve-call-recorder-policy-result.test.ts | 34 +++++++++++++----- ...ract-conference-link-url-from-text.util.ts | 13 ++----- .../is-supported-meeting-platform-url.util.ts | 14 ++++++++ ...esolve-call-recorder-policy-result.util.ts | 5 +++ .../__tests__/reconcile-call-recorder.test.ts | 16 ++++----- ...le-upcoming-calendar-event-batches.test.ts | 10 +++--- ...ecorder-policy-not-required-reason.type.ts | 1 + 12 files changed, 125 insertions(+), 34 deletions(-) create mode 100644 packages/twenty-apps/public/call-recorder/src/logic-functions/constants/supported-meeting-platform-url-patterns.ts create mode 100644 packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/is-supported-meeting-platform-url.test.ts create mode 100644 packages/twenty-apps/public/call-recorder/src/logic-functions/domain/is-supported-meeting-platform-url.util.ts diff --git a/packages/twenty-apps/public/call-recorder/README.md b/packages/twenty-apps/public/call-recorder/README.md index 8435377a60..2346ada3fd 100644 --- a/packages/twenty-apps/public/call-recorder/README.md +++ b/packages/twenty-apps/public/call-recorder/README.md @@ -21,6 +21,20 @@ cost scales with how much was said in the meeting, typically **$0.02–$0.06 per meeting** on default models. Set the `CALL_RECORDER_SUMMARY_ENABLED` app variable to `false` to turn summaries off. +## 🎥 Supported meeting platforms + +The recording bot can only join meetings on these platforms: + +- ✅ Google Meet +- ✅ Zoom +- ✅ Microsoft Teams +- ✅ Webex +- ✅ GoTo Meeting + +Events whose conference link points to any other platform (e.g. ro.am, Daily, +Whereby) or that only have a dial-in number are **ignored** — no bot is +scheduled, since it can't join the call. + ## 📌 Heads up - **Needs a synced calendar + video link** — ad-hoc calls that were never on diff --git a/packages/twenty-apps/public/call-recorder/src/__tests__/call-recorder-lifecycle.integration-test.ts b/packages/twenty-apps/public/call-recorder/src/__tests__/call-recorder-lifecycle.integration-test.ts index d90e31bb8d..fd8a985ca7 100644 --- a/packages/twenty-apps/public/call-recorder/src/__tests__/call-recorder-lifecycle.integration-test.ts +++ b/packages/twenty-apps/public/call-recorder/src/__tests__/call-recorder-lifecycle.integration-test.ts @@ -411,7 +411,7 @@ describe('call recorder app lifecycle (integration)', () => { endsAt: inTwoHours(), iCalUid: `call-recorder-test-${calendarEventId}`, conferenceLink: { - primaryLinkUrl: `https://meet.example.com/${calendarEventId}`, + primaryLinkUrl: `https://meet.google.com/${calendarEventId}`, }, callRecorderPreference: 'ON', ...overrides, diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/constants/supported-meeting-platform-url-patterns.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/constants/supported-meeting-platform-url-patterns.ts new file mode 100644 index 0000000000..8db550a0b6 --- /dev/null +++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/constants/supported-meeting-platform-url-patterns.ts @@ -0,0 +1,12 @@ +// Meeting platforms a Recall bot can join. Anything else (Around, Whereby, +// ro.am, Daily, plain dial-in, etc.) cannot be recorded and is ignored. +// See https://docs.recall.ai/docs/meeting-platforms +// Ordered by provider precedence: the first matching provider wins (e.g. a +// pasted Zoom invitation beats an auto-added Meet link). +export const SUPPORTED_MEETING_PLATFORM_URL_PATTERNS: RegExp[] = [ + /https:\/\/(?:[\w-]+\.)*(?:zoom\.us|zoomgov\.com)\/(?:j|my|s|w|wc\/join)\/[^\s"'<>\\]+/i, + /https:\/\/meet\.google\.com\/[^\s"'<>\\]+/i, + /https:\/\/teams\.(?:microsoft|live)\.com\/(?:l\/meetup-join|meet)\/[^\s"'<>\\]+/i, + /https:\/\/(?:[\w-]+\.)*webex\.com\/(?:meet\/|join\/|[\w-]+\/j\.php\?)[^\s"'<>\\]+/i, + /https:\/\/(?:[\w-]+\.)*(?:gotomeeting\.com\/join|gotomeet\.me)\/[^\s"'<>\\]+/i, +]; diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/build-call-recorder-policy-result.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/build-call-recorder-policy-result.test.ts index c6bcc54214..129698e32a 100644 --- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/build-call-recorder-policy-result.test.ts +++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/build-call-recorder-policy-result.test.ts @@ -13,7 +13,7 @@ const buildCalendarEventInput = ( startsAt: '2026-01-01T13:00:00.000Z', endsAt: '2026-01-01T14:00:00.000Z', iCalUid: 'ical-uid-1', - conferenceLinkUrl: 'https://meet.example.com/customer-sync', + conferenceLinkUrl: 'https://meet.google.com/customer-sync', callRecorderPreference: undefined, ...overrides, }); diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/is-supported-meeting-platform-url.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/is-supported-meeting-platform-url.test.ts new file mode 100644 index 0000000000..b6ebbdd6e4 --- /dev/null +++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/is-supported-meeting-platform-url.test.ts @@ -0,0 +1,36 @@ +import { describe, expect, it } from 'vitest'; + +import { isSupportedMeetingPlatformUrl } from 'src/logic-functions/domain/is-supported-meeting-platform-url.util'; + +describe('isSupportedMeetingPlatformUrl', () => { + it.each([ + ['a Zoom link', 'https://zoom.us/j/81234567890'], + ['a Zoom subdomain link', 'https://us02web.zoom.us/j/81234567890?pwd=aBc'], + ['a Google Meet link', 'https://meet.google.com/abc-defg-hij'], + [ + 'a Microsoft Teams link', + 'https://teams.microsoft.com/l/meetup-join/19%3ameeting_ABC%40thread.v2/0', + ], + ['a Webex link', 'https://company.webex.com/company/j.php?MTID=m1234abcd'], + ['a GoTo Meeting link', 'https://global.gotomeeting.com/join/123456789'], + ])('returns true for %s', (_label, url) => { + expect(isSupportedMeetingPlatformUrl(url)).toBe(true); + }); + + it.each([ + ['a ro.am link', 'https://ro.am/r/#/d/123'], + ['a Daily link', 'https://example.daily.co/room'], + ['a Whereby link', 'https://whereby.com/team-room'], + ['a Zoom marketing page', 'https://zoom.us/pricing'], + ['a non-conferencing URL', 'https://docs.google.com/document/d/abc'], + ['an empty string', ''], + ['a blank string', ' '], + ])('returns false for %s', (_label, url) => { + expect(isSupportedMeetingPlatformUrl(url)).toBe(false); + }); + + it('returns false for null and undefined', () => { + expect(isSupportedMeetingPlatformUrl(null)).toBe(false); + expect(isSupportedMeetingPlatformUrl(undefined)).toBe(false); + }); +}); diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/resolve-call-recorder-policy-result.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/resolve-call-recorder-policy-result.test.ts index b7ad56cbf3..78d9388633 100644 --- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/resolve-call-recorder-policy-result.test.ts +++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/__tests__/resolve-call-recorder-policy-result.test.ts @@ -21,7 +21,7 @@ describe('resolveCallRecorderPolicyResult', () => { isCanceled: false, startsAt: FUTURE_STARTS_AT, endsAt: FUTURE_ENDS_AT, - conferenceLinkUrl: 'https://meet.example.com/team-sync', + conferenceLinkUrl: 'https://meet.google.com/abc-defg-hij', }, now: NOW, }), @@ -49,6 +49,24 @@ describe('resolveCallRecorderPolicyResult', () => { }); }); + it('does not request a bot when the conference link is an unsupported platform', () => { + expect( + resolveCallRecorderPolicyResult({ + input: { + callRecorderPreference: CallRecorderPreference.ON, + isCanceled: false, + startsAt: FUTURE_STARTS_AT, + endsAt: FUTURE_ENDS_AT, + conferenceLinkUrl: 'https://ro.am/r/#/d/123', + }, + now: NOW, + }), + ).toEqual({ + shouldRequestBot: false, + reason: 'UNSUPPORTED_MEETING_PLATFORM', + }); + }); + it('requires a bot without an event preference override', () => { expect( resolveCallRecorderPolicyResult({ @@ -57,7 +75,7 @@ describe('resolveCallRecorderPolicyResult', () => { isCanceled: false, startsAt: FUTURE_STARTS_AT, endsAt: FUTURE_ENDS_AT, - conferenceLinkUrl: 'https://meet.example.com/team-sync', + conferenceLinkUrl: 'https://meet.google.com/abc-defg-hij', }, now: NOW, }), @@ -75,7 +93,7 @@ describe('resolveCallRecorderPolicyResult', () => { isCanceled: false, startsAt: FUTURE_STARTS_AT, endsAt: FUTURE_ENDS_AT, - conferenceLinkUrl: 'https://meet.example.com/team-sync', + conferenceLinkUrl: 'https://meet.google.com/abc-defg-hij', }, now: NOW, }), @@ -93,7 +111,7 @@ describe('resolveCallRecorderPolicyResult', () => { isCanceled: false, startsAt: PAST_STARTS_AT, endsAt: PAST_ENDS_AT, - conferenceLinkUrl: 'https://meet.example.com/team-sync', + conferenceLinkUrl: 'https://meet.google.com/abc-defg-hij', }, now: NOW, }), @@ -111,7 +129,7 @@ describe('resolveCallRecorderPolicyResult', () => { isCanceled: true, startsAt: FUTURE_STARTS_AT, endsAt: FUTURE_ENDS_AT, - conferenceLinkUrl: 'https://meet.example.com/team-sync', + conferenceLinkUrl: 'https://meet.google.com/abc-defg-hij', }, now: NOW, }), @@ -129,7 +147,7 @@ describe('resolveCallRecorderPolicyResult', () => { isCanceled: false, startsAt: BEYOND_HORIZON_STARTS_AT, endsAt: BEYOND_HORIZON_ENDS_AT, - conferenceLinkUrl: 'https://meet.example.com/team-sync', + conferenceLinkUrl: 'https://meet.google.com/abc-defg-hij', }, now: NOW, }), @@ -147,7 +165,7 @@ describe('resolveCallRecorderPolicyResult', () => { isCanceled: false, startsAt: FUTURE_STARTS_AT, endsAt: BEYOND_HORIZON_ENDS_AT, - conferenceLinkUrl: 'https://meet.example.com/team-sync', + conferenceLinkUrl: 'https://meet.google.com/abc-defg-hij', }, now: NOW, }), @@ -165,7 +183,7 @@ describe('resolveCallRecorderPolicyResult', () => { isCanceled: false, startsAt: '', endsAt: FUTURE_ENDS_AT, - conferenceLinkUrl: 'https://meet.example.com/team-sync', + conferenceLinkUrl: 'https://meet.google.com/abc-defg-hij', }, now: NOW, }), diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/extract-conference-link-url-from-text.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/extract-conference-link-url-from-text.util.ts index a4ab3b6d47..4b50826ed5 100644 --- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/extract-conference-link-url-from-text.util.ts +++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/extract-conference-link-url-from-text.util.ts @@ -1,15 +1,6 @@ +import { SUPPORTED_MEETING_PLATFORM_URL_PATTERNS } from 'src/logic-functions/constants/supported-meeting-platform-url-patterns'; import { isNonEmptyString } from 'src/logic-functions/utils/is-non-empty-string.util'; -// Ordered by provider precedence: the first matching provider wins (e.g. a -// pasted Zoom invitation beats an auto-added Meet link). -const CONFERENCE_LINK_URL_PATTERNS: RegExp[] = [ - /https:\/\/(?:[\w-]+\.)*(?:zoom\.us|zoomgov\.com)\/(?:j|my|s|w|wc\/join)\/[^\s"'<>\\]+/i, - /https:\/\/meet\.google\.com\/[^\s"'<>\\]+/i, - /https:\/\/teams\.(?:microsoft|live)\.com\/(?:l\/meetup-join|meet)\/[^\s"'<>\\]+/i, - /https:\/\/(?:[\w-]+\.)*webex\.com\/(?:meet\/|join\/|[\w-]+\/j\.php\?)[^\s"'<>\\]+/i, - /https:\/\/(?:[\w-]+\.)*(?:gotomeeting\.com\/join|gotomeet\.me)\/[^\s"'<>\\]+/i, -]; - // Outlook HTML bodies encode ampersands; plain-text links can end mid-sentence. const cleanExtractedConferenceLinkUrl = (url: string): string => url.replace(/&/gi, '&').replace(/[.,;:!?)\]]+$/, ''); @@ -21,7 +12,7 @@ export const extractConferenceLinkUrlFromText = ( return undefined; } - for (const pattern of CONFERENCE_LINK_URL_PATTERNS) { + for (const pattern of SUPPORTED_MEETING_PLATFORM_URL_PATTERNS) { const match = text.match(pattern); if (match !== null) { diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/is-supported-meeting-platform-url.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/is-supported-meeting-platform-url.util.ts new file mode 100644 index 0000000000..3559f715d9 --- /dev/null +++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/is-supported-meeting-platform-url.util.ts @@ -0,0 +1,14 @@ +import { SUPPORTED_MEETING_PLATFORM_URL_PATTERNS } from 'src/logic-functions/constants/supported-meeting-platform-url-patterns'; +import { isNonEmptyString } from 'src/logic-functions/utils/is-non-empty-string.util'; + +export const isSupportedMeetingPlatformUrl = ( + url: string | null | undefined, +): boolean => { + if (!isNonEmptyString(url)) { + return false; + } + + return SUPPORTED_MEETING_PLATFORM_URL_PATTERNS.some((pattern) => + pattern.test(url), + ); +}; diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/resolve-call-recorder-policy-result.util.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/resolve-call-recorder-policy-result.util.ts index a2899c35b2..1fd4b7dca9 100644 --- a/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/resolve-call-recorder-policy-result.util.ts +++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/domain/resolve-call-recorder-policy-result.util.ts @@ -2,6 +2,7 @@ import { isUndefined } from '@sniptt/guards'; import { CallRecorderPreference } from 'src/constants/call-recorder-preference'; import { computeUpcomingCalendarEventHorizonEnd } from 'src/logic-functions/domain/compute-upcoming-calendar-event-horizon-end.util'; +import { isSupportedMeetingPlatformUrl } from 'src/logic-functions/domain/is-supported-meeting-platform-url.util'; import { type CallRecorderPolicyInput } from 'src/logic-functions/types/call-recorder-policy-input.type'; import { isNonEmptyString } from 'src/logic-functions/utils/is-non-empty-string.util'; import { type CallRecorderPolicyNotRequiredReason } from 'src/logic-functions/types/call-recorder-policy-not-required-reason.type'; @@ -29,6 +30,10 @@ export const resolveCallRecorderPolicyResult = ({ return botNotRequired('MISSING_CONFERENCE_LINK'); } + if (!isSupportedMeetingPlatformUrl(input.conferenceLinkUrl)) { + return botNotRequired('UNSUPPORTED_MEETING_PLATFORM'); + } + if ( !isCalendarEventInFuture({ startsAt: input.startsAt, diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-call-recorder.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-call-recorder.test.ts index a07a6e848f..9a90907af4 100644 --- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-call-recorder.test.ts +++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-call-recorder.test.ts @@ -43,7 +43,7 @@ const buildCustomerSyncCallRecordingId = ( startsAt: string = FUTURE_STARTS_AT, ): string => computeCallRecordingIdForMeeting( - `link:meet.example.com/customer-sync:${startsAt}`, + `link:meet.google.com/customer-sync:${startsAt}`, ); type CalendarEventNode = { @@ -207,7 +207,7 @@ const buildCalendarEvent = ( endsAt: FUTURE_ENDS_AT, iCalUid: 'calendar-event-uid', conferenceLink: { - primaryLinkUrl: 'https://meet.example.com/customer-sync', + primaryLinkUrl: 'https://meet.google.com/customer-sync', }, callRecorderPreference: 'ON', ...overrides, @@ -293,7 +293,7 @@ describe('reconcileCallRecorderForCalendarEventIds', () => { ); expect(JSON.parse(createBotInit.body ?? '')).toEqual( expect.objectContaining({ - meeting_url: 'https://meet.example.com/customer-sync', + meeting_url: 'https://meet.google.com/customer-sync', join_at: FUTURE_RECALL_BOT_JOIN_AT, metadata: { twentyWorkspaceId: WORKSPACE_ID, @@ -471,7 +471,7 @@ describe('reconcileCallRecorderForCalendarEventIds', () => { expect(updateBotUrl).toBe(`${RECALL_API_BASE_URL}/bot/recall-bot-1/`); expect(JSON.parse(updateBotInit.body ?? '')).toEqual( expect.objectContaining({ - meeting_url: 'https://meet.example.com/customer-sync', + meeting_url: 'https://meet.google.com/customer-sync', join_at: FUTURE_RECALL_BOT_JOIN_AT, metadata: { twentyWorkspaceId: WORKSPACE_ID, @@ -742,7 +742,7 @@ describe('reconcileCallRecorderForCalendarEventIds', () => { removedOccurrences: [ { calendarEventId: 'calendar-event-1', - realMeetingKey: `link:meet.example.com/customer-sync:${FUTURE_STARTS_AT}`, + realMeetingKey: `link:meet.google.com/customer-sync:${FUTURE_STARTS_AT}`, startsAt: FUTURE_STARTS_AT, }, ], @@ -798,7 +798,7 @@ describe('reconcileCallRecorderForCalendarEventIds', () => { removedOccurrences: [ { calendarEventId: 'calendar-event-1', - realMeetingKey: `link:meet.example.com/customer-sync:${FUTURE_STARTS_AT}`, + realMeetingKey: `link:meet.google.com/customer-sync:${FUTURE_STARTS_AT}`, startsAt: FUTURE_STARTS_AT, }, ], @@ -860,7 +860,7 @@ describe('reconcileCallRecorderForCalendarEventIds', () => { id: 'calendar-event-2', iCalUid: 'other-meeting-uid', conferenceLink: { - primaryLinkUrl: 'https://meet.example.com/other-sync', + primaryLinkUrl: 'https://meet.google.com/other-sync', }, }), ], @@ -887,7 +887,7 @@ describe('reconcileCallRecorderForCalendarEventIds', () => { expect(result).toEqual([ expect.objectContaining({ action: 'FAILED', - realMeetingKey: `link:meet.example.com/customer-sync:${FUTURE_STARTS_AT}`, + realMeetingKey: `link:meet.google.com/customer-sync:${FUTURE_STARTS_AT}`, errorMessage: 'recall exploded', }), expect.objectContaining({ action: 'CREATED' }), diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-upcoming-calendar-event-batches.test.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-upcoming-calendar-event-batches.test.ts index d3d67de106..4e7a9b1382 100644 --- a/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-upcoming-calendar-event-batches.test.ts +++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/flows/__tests__/reconcile-upcoming-calendar-event-batches.test.ts @@ -16,7 +16,7 @@ const CLIENT: CoreApiClient = Object.assign( }, ); -const MEETING_URL = 'https://meet.example.com/abc'; +const MEETING_URL = 'https://meet.google.com/abc'; const MEETING_STARTS_AT = new Date(Date.now() + 60 * 60 * 1000).toISOString(); const MEETING_ENDS_AT = new Date(Date.now() + 2 * 60 * 60 * 1000).toISOString(); @@ -291,24 +291,24 @@ describe('reconcileUpcomingCalendarEventBatches', () => { calendarEventNodesById: { 'calendar-event-1': buildCalendarEventNode('calendar-event-1', { conferenceLink: { - primaryLinkUrl: 'https://meet.example.com/created', + primaryLinkUrl: 'https://meet.google.com/created', }, }), 'calendar-event-2': buildCalendarEventNode('calendar-event-2', { isCanceled: true, conferenceLink: { - primaryLinkUrl: 'https://meet.example.com/canceled', + primaryLinkUrl: 'https://meet.google.com/canceled', }, }), 'calendar-event-3': buildCalendarEventNode('calendar-event-3', { isCanceled: true, conferenceLink: { - primaryLinkUrl: 'https://meet.example.com/skipped', + primaryLinkUrl: 'https://meet.google.com/skipped', }, }), 'calendar-event-4': buildCalendarEventNode('calendar-event-4', { conferenceLink: { - primaryLinkUrl: 'https://meet.example.com/failed', + primaryLinkUrl: 'https://meet.google.com/failed', }, }), }, diff --git a/packages/twenty-apps/public/call-recorder/src/logic-functions/types/call-recorder-policy-not-required-reason.type.ts b/packages/twenty-apps/public/call-recorder/src/logic-functions/types/call-recorder-policy-not-required-reason.type.ts index 2423e57ea4..52c24f75f0 100644 --- a/packages/twenty-apps/public/call-recorder/src/logic-functions/types/call-recorder-policy-not-required-reason.type.ts +++ b/packages/twenty-apps/public/call-recorder/src/logic-functions/types/call-recorder-policy-not-required-reason.type.ts @@ -2,5 +2,6 @@ export type CallRecorderPolicyNotRequiredReason = | 'EVENT_CANCELED' | 'PREFERENCE_OFF' | 'MISSING_CONFERENCE_LINK' + | 'UNSUPPORTED_MEETING_PLATFORM' | 'EVENT_NOT_UPCOMING' | 'EVENT_BEYOND_SCHEDULING_HORIZON';