[IMP] microsoft_calendar: get videocall URL from a Outlook event

Basically, a Outlook event may contain a videocall URL in 2 different ways:

1) the event location may be a specific URL (such as `https://teams.microsoft.com/...`).
 In this case, we use it as `videocall_location` instead of classic `location`.
We use a list of patterns to identify these specific URLs among classic locations.

2) the event may have an attribute `isOnlineMeeting` set to `True` and
the attribute `onlineMeetingUrl` set with the URL. In this case, we use
this `onlineMeetingUrl` as `videocall_location`.

opw-2601669

closes odoo/odoo#74785

Signed-off-by: Arnaud Joset <arj@odoo.com>
This commit is contained in:
Rémy Baranx (bar)
2022-07-11 13:48:40 +02:00
parent ba37803064
commit 90480ce2d1
2 changed files with 76 additions and 0 deletions
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import pytz
import re
from dateutil.parser import parse
from dateutil.relativedelta import relativedelta
@@ -23,6 +24,9 @@ ATTENDEE_CONVERTER_M2O = {
'accepted': 'accepted',
'organizer': 'accepted',
}
VIDEOCALL_URL_PATTERNS = (
r'https://teams.microsoft.com',
)
MAX_RECURRENT_EVENT = 720
class Meeting(models.Model):
@@ -126,6 +130,16 @@ class Meeting(models.Model):
# Propagate the follow_recurrence according to the google result
values['follow_recurrence'] = not microsoft_event.is_recurrence_outlier()
# if a videocall URL is provided with the Outlook event, use it
if microsoft_event.isOnlineMeeting and microsoft_event.onlineMeeting.get("joinUrl"):
values['videocall_location'] = microsoft_event.onlineMeeting["joinUrl"]
else:
# if a location is a URL matching a specific pattern (i.e a URL to access to a videocall),
# copy it in the 'videocall_location' instead
if values['location'] and any(re.match(p, values['location']) for p in VIDEOCALL_URL_PATTERNS):
values['videocall_location'] = values['location']
values['location'] = False
values['microsoft_id'] = microsoft_event.id
if microsoft_event.is_recurrent():
values['microsoft_recurrence_master_id'] = microsoft_event.seriesMasterId
@@ -24,6 +24,25 @@ class TestSyncMicrosoft2Odoo(TransactionCase):
{'@odata.type': '#microsoft.graph.event', '@odata.etag': 'W/"DwAAABYAAABlLa4RUBXJToExnebpwea2AAALKrjF"', 'seriesMasterId': 'AQ8PojGtrADQATM3ZmYAZS0yY2MAMC00MDg1LTAwAi0wMAoARgAAA0By7X03vaNKv1GnWYTbFYAHAGUtrhFQFclOgTGd5unB5rYAAAIBDQAAAGUtrhFQFclOgTGd5unB5rYAAAALLLTEAAAA', 'type': 'occurrence', 'id': 'AQ8PojGtrADQATM3ZmYAZS0yY2MAMC00MDg1LTAwAi0wMAoBUQAICADX774WtQAAAEYAAAJAcu19N72jSr9Rp1mE2xWABwBlLa4RUBXJToExnebpwea2AAACAQ0AAABlLa4RUBXJToExnebpwea2AAAACyy0xAAAABA=', 'start': {'dateTime': '2020-05-04T14:30:00.0000000', 'timeZone': 'UTC'}, 'end': {'dateTime': '2020-05-04T16:00:00.0000000', 'timeZone': 'UTC'}},
{'@odata.type': '#microsoft.graph.event', '@odata.etag': 'W/"DwAAABYAAABlLa4RUBXJToExnebpwea2AAALKrjF"', 'seriesMasterId': 'AQ8PojGtrADQATM3ZmYAZS0yY2MAMC00MDg1LTAwAi0wMAoARgAAA0By7X03vaNKv1GnWYTbFYAHAGUtrhFQFclOgTGd5unB5rYAAAIBDQAAAGUtrhFQFclOgTGd5unB5rYAAAALLLTEAAAA', 'type': 'occurrence', 'id': 'AQ8PojGtrADQATM3ZmYAZS0yY2MAMC00MDg1LTAwAi0wMAoBUQAICADX8IdBHsAARgAAAkBy7X03vaNKv1GnWYTbFYAHAGUtrhFQFclOgTGd5unB5rYAAAIBDQAAAGUtrhFQFclOgTGd5unB5rYAAAALLLTEAAAAEA==', 'start': {'dateTime': '2020-05-05T14:30:00.0000000', 'timeZone': 'UTC'}, 'end': {'dateTime': '2020-05-05T16:00:00.0000000', 'timeZone': 'UTC'}}
]
self.single_event = [
{
'@odata.type': '#microsoft.graph.event',
'@odata.etag': 'W/"AAAAA"',
'type': 'singleInstance',
'id': "CCCCC",
'start': {
'dateTime': '2020-05-05T14:30:00.0000000',
'timeZone': 'UTC'
},
'end': {
'dateTime': '2020-05-05T16:00:00.0000000',
'timeZone': 'UTC'
},
'location': {
'displayName': "a meeting room at Odoo"
}
}
]
self.env['calendar.event']._sync_microsoft2odoo(MicrosoftEvent(values))
@@ -275,3 +294,46 @@ class TestSyncMicrosoft2Odoo(TransactionCase):
self.assertEqual(recurrent_event.calendar_event_ids[0].stop, datetime(2021, 7, 15, 15, 30))
self.assertEqual(recurrent_event.calendar_event_ids[1].start, datetime(2021, 7, 17, 15, 00))
self.assertEqual(recurrent_event.calendar_event_ids[1].stop, datetime(2021, 7, 17, 15, 30))
def test_use_classic_location(self):
ms_event = self.single_event
self.env['calendar.event']._sync_microsoft2odoo(MicrosoftEvent(ms_event))
event = self.env['calendar.event'].search([("microsoft_id", "=", ms_event[0]["id"])])
self.assertEqual(event.location, ms_event[0]["location"]["displayName"])
def test_use_url_location(self):
ms_event = self.single_event
ms_event[0]["location"]["displayName"] = "https://mylocation.com/meeting-room"
self.env['calendar.event']._sync_microsoft2odoo(MicrosoftEvent(ms_event))
event = self.env['calendar.event'].search([("microsoft_id", "=", ms_event[0]["id"])])
self.assertEqual(event.location, ms_event[0]["location"]["displayName"])
def test_use_specific_virtual_location(self):
"""
If the location of the Outlook event is a specific virtual location (such as a video Teams meeting),
use it as videocall location.
"""
ms_event = self.single_event
ms_event[0]["location"]["displayName"] = "https://teams.microsoft.com/l/meeting/1234"
self.env['calendar.event']._sync_microsoft2odoo(MicrosoftEvent(ms_event))
event = self.env['calendar.event'].search([("microsoft_id", "=", ms_event[0]["id"])])
self.assertEqual(event.location, False)
self.assertEqual(event.videocall_location, ms_event[0]["location"]["displayName"])
def test_outlook_event_has_online_meeting_url(self):
ms_event = self.single_event
ms_event[0].update({
'isOnlineMeeting': True,
'onlineMeeting': {'joinUrl': 'https://video-meeting.com/1234'}
})
self.env['calendar.event']._sync_microsoft2odoo(MicrosoftEvent(ms_event))
event = self.env['calendar.event'].search([("microsoft_id", "=", ms_event[0]["id"])])
self.assertEqual(event.videocall_location, ms_event[0]["onlineMeeting"]["joinUrl"])