From 7324df172a82680a9ecf96be5a295eb23c7f77ee Mon Sep 17 00:00:00 2001
From: James Antill <james@and.org>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 1/16] Add some regexp validation to fix #213


Signed-off-by: James Antill <james@and.org>

---

diff --git a/fedocal/forms.py b/fedocal/forms.py
index f070c83..517f088 100644
--- a/fedocal/forms.py
+++ b/fedocal/forms.py
@@ -52,12 +52,23 @@ def validate_time(form, field):
 
 
 def validate_meeting_location(form, field):
-    """ Validate if location doesn't contain #irc-chan format
-        More info: https://fedorahosted.org/fedocal/ticket/118
+    """ Validate if location for compatibility to IRC and Matrix.
+        More info: https://fedorahosted.org/fedocal/ticket/213
     """
-    if '#' in field.data.strip():
-        raise wtforms.ValidationError(
-            _('Please use channel@server format!')
+    # As always, try: https://regex101.com/
+    # These aren't "perfect" but close enough: [-\w] allows alphanum '_' and '-'
+    loc = field.data.strip()
+    # - ircroom@irc.server
+    if re.match(r'^[-\w]+@[-\w]+([.][-\w]+)*$', loc):
+        return
+    # - #room:host.name.tld
+    if re.match(r'^#[-\w]+:[-\w]+([.][-\w]+)*$', loc):
+        return
+    # - https://matrix.to/#/#room:host.name.tld
+    if re.match(r'^https?://matrix.to/#/#[-\w]+:[-\w]+([.][-\w]+)*$', loc):
+        return
+    raise wtforms.ValidationError(
+            _('Please use channel@server or #room:server formats!')
         )
 
 
diff --git a/tests/test_flask.py b/tests/test_flask.py
index 02105a7..2db5523 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1579,7 +1579,7 @@ class Flasktests(Modeltests):
             self.assertEqual(output.status_code, 200)
             output_text = output.get_data(as_text=True)
             self.assertIn(
-                '<td>Please use channel@server format!</td>', output_text)
+                '<td>Please use channel@server or #room:server formats!</td>', output_text)
             self.assertIn(
                 '<title>Add meeting - Fedocal</title>', output_text)
 

From d94010540a2a173e5c4e3a727010ee56b658fa75 Mon Sep 17 00:00:00 2001
From: Dominik Wombacher <dominik@wombacher.cc>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 2/16] tests: Validate meeting location.


Relates to PR #214 and Issue #213

---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index 2db5523..a171050 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1562,7 +1562,9 @@ class Flasktests(Modeltests):
             self.assertIn(
                 '<title>Add meeting - Fedocal</title>', output_text)
 
-            # Invalid location
+            # Invalid meeting location: IRC Channel name without server
+            # Allowed: channel@irc.server.tld
+            # https://pagure.io/fedocal/issue/118
             data = {
                 'meeting_name': 'guess what?',
                 'meeting_date': TODAY,
@@ -1787,6 +1789,70 @@ class Flasktests(Modeltests):
                 self.assertNotIn(
                     'href="/meeting/20/?from_date=', output_text)
 
+            # Valid meeting location: IRC Channel with server
+            # https://pagure.io/fedocal/issue/118
+            data = {
+                'meeting_name': 'guess what?',
+                'meeting_date': TODAY,
+                'meeting_time_start': time(13, 0),
+                'meeting_time_stop': time(14, 0),
+                'meeting_timezone': 'Europe/Paris',
+                'meeting_location': 'meeting-1@fedoraproject.org',
+                'frequency': '',
+                'csrf_token': csrf_token,
+            }
+
+            with testing.mock_sends(schema.MeetingNewV1):
+                output = self.app.post('/test_calendar/add/', data=data,
+                                       follow_redirects=True)
+                self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
+                self.assertIn(
+                    '<li class="message">Meeting added</li>', output_text)
+
+            # Valid meeting location: Matrix Room
+            # https://pagure.io/fedocal/issue/213
+            data = {
+                'meeting_name': 'guess what?',
+                'meeting_date': TODAY,
+                'meeting_time_start': time(13, 0),
+                'meeting_time_stop': time(14, 0),
+                'meeting_timezone': 'Europe/Paris',
+                'meeting_location': '#meeting-1:fedoraproject.org',
+                'frequency': '',
+                'csrf_token': csrf_token,
+            }
+
+            with testing.mock_sends(schema.MeetingNewV1):
+                output = self.app.post('/test_calendar/add/', data=data,
+                                       follow_redirects=True)
+                self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
+                self.assertIn(
+                    '<li class="message">Meeting added</li>', output_text)
+
+            # Valid meeting location: Matrix Room URL
+            # https://pagure.io/fedocal/issue/213
+            data = {
+                'meeting_name': 'guess what?',
+                'meeting_date': TODAY,
+                'meeting_time_start': time(13, 0),
+                'meeting_time_stop': time(14, 0),
+                'meeting_timezone': 'Europe/Paris',
+                'meeting_location': 'https://matrix.to/#/#meeting-1:fedoraproject.org',
+                'frequency': '',
+                'csrf_token': csrf_token,
+            }
+
+            with testing.mock_sends(schema.MeetingNewV1):
+                output = self.app.post('/test_calendar/add/', data=data,
+                                       follow_redirects=True)
+                self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
+                self.assertIn(
+                    '<li class="message">Meeting added</li>', output_text)
+
+
     def test_edit_meeting(self):
         """ Test the edit_meeting function. """
         self.__setup_db()

From 1195a1f07b9e57fc2ce14bd10d8f91ee06bd8286 Mon Sep 17 00:00:00 2001
From: James Antill <james@and.org>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 3/16] Add more validation for #213, meet/zoom/hangouts/etc.


Signed-off-by: James Antill <james@and.org>

---

diff --git a/fedocal/forms.py b/fedocal/forms.py
index 517f088..59bd900 100644
--- a/fedocal/forms.py
+++ b/fedocal/forms.py
@@ -58,17 +58,63 @@ def validate_meeting_location(form, field):
     # As always, try: https://regex101.com/
     # These aren't "perfect" but close enough: [-\w] allows alphanum '_' and '-'
     loc = field.data.strip()
+    # Allow a "blank" entry...
+    if loc == '':
+        return
+
     # - ircroom@irc.server
     if re.match(r'^[-\w]+@[-\w]+([.][-\w]+)*$', loc):
         return
+
     # - #room:host.name.tld
     if re.match(r'^#[-\w]+:[-\w]+([.][-\w]+)*$', loc):
         return
+
     # - https://matrix.to/#/#room:host.name.tld
     if re.match(r'^https?://matrix.to/#/#[-\w]+:[-\w]+([.][-\w]+)*$', loc):
         return
+
+    # - irc://irc.server/ircroom
+    # Eg.
+    #   irc://irc.libera.chat/fedora-zh
+    if re.match(r'^irc://[-\w]+([.][-\w]+)*/[-\w]+$', loc):
+        return
+
+    # - https://meet.<server>/<name>
+    # Eg.
+    #   https://meet.google.com/acq-pwxk-fhv
+    #   https://meet.jit.si/fedora-websites-apps-meeting
+    if re.match(r'^https?://meet([.][-\w]+)+/[-\w]+$', loc):
+        return
+
+    # - https://meet.<server>/b/<name>
+    # Eg.
+    #   https://meet.kde.org/b/ale-swq-39j
+    if re.match(r'^https?://meet([.][-\w]+)+/b/[-\w]+$', loc):
+        return
+
+    # - https://<server>.zoom.us/j/<name>?pwd=<pwd>
+    # Eg.
+    #   https://umich.zoom.us/j/96648123924?pwd=RitQVVQvMFVSaXJhNkFBS08vWTk0Zz09
+    if re.match(r'^https?://[-\w]+.zoom.us/j/\d+([?]pwd=\w+)?$', loc):
+        return
+
+    # - https://hangouts.google.com/hangouts/_/<name>
+    # Eg.
+    #   https://hangouts.google.com/hangouts/_/67zc3kvkovelxctlilphwodlp4e
+    if re.match(r'^https?://hangouts.google.com/hangouts/_/[-\w]+$', loc):
+        return
+
+    # podcast.fedoraproject.org
+    if loc == 'podcast.fedoraproject.org':
+        return
+    if loc == 'http://podcast.fedoraproject.org/':
+        return
+    if loc == 'https://podcast.fedoraproject.org/':
+        return
+
     raise wtforms.ValidationError(
-            _('Please use channel@server or #room:server formats!')
+            _('Please use IRC, Matrix, meet, zoom or hangouts formats!')
         )
 
 

From 853d2490557dd60a43107026a112d905564ea1f7 Mon Sep 17 00:00:00 2001
From: James Antill <james@and.org>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 4/16] tests: Validate meeting location using current values from calendar.


Relates to PR #214 and Issue #213

Signed-off-by: James Antill <james@and.org>

---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index a171050..b01b66d 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1852,6 +1852,44 @@ class Flasktests(Modeltests):
                 self.assertIn(
                     '<li class="message">Meeting added</li>', output_text)
 
+            # Valid meeting location: List of current meeting locations:
+            meet_locations = ['',
+                'https://unomaha.zoom.us/j/609939109',
+                'https://hangouts.google.com/hangouts/_/67zc3kvkovelxctlilphwodlp4e',
+                'https://meet.opensuse.org/epel',
+                'irc://irc.libera.chat/fedora-zh',
+                'https://meet.google.com/acq-pwxk-fhv',
+                'https://meet.google.com/mic-otnv-kse',
+                'https://meet.jit.si/fedora-websites-apps-meeting',
+                'https://meet.kde.org/b/ale-swq-39j',
+                'https://umich.zoom.us/j/96648123924?pwd=RitQVVQvMFVSaXJhNkFBS08vWTk0Zz09',
+                'https://umich.zoom.us/j/99842244394?pwd=YVdkQjJTdnpBMUkySGVzK1kyTGoyZz09',
+                'https://meet.google.com/xuj-jswy-hat',
+                'podcast.fedoraproject.org',
+                'https://podcast.fedoraproject.org/',
+                'https://meet.google.com/jod-dkmw-ibd']
+            # https://pagure.io/fedocal/issue/213
+            data = {
+                'meeting_name': 'guess what?',
+                'meeting_date': TODAY,
+                'meeting_time_start': time(13, 0),
+                'meeting_time_stop': time(14, 0),
+                'meeting_timezone': 'Europe/Paris',
+                'meeting_location': None,
+                'frequency': '',
+                'csrf_token': csrf_token,
+            }
+
+            for meet_location in meet_locations:
+              with testing.mock_sends(schema.MeetingNewV1):
+                data['meeting_location'] = meet_location
+                output = self.app.post('/test_calendar/add/', data=data,
+                                       follow_redirects=True)
+                self.assertEqual(output.status_code, 200)
+                output_text = output.get_data(as_text=True)
+                self.assertIn(
+                    '<li class="message">Meeting added</li>', output_text)
+
 
     def test_edit_meeting(self):
         """ Test the edit_meeting function. """

From 189e1e703ad8e0c1adeab37eb12fd35a57bd95db Mon Sep 17 00:00:00 2001
From: James Antill <jantill@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 5/16] tests: Fix message we check for, in test error output.


Signed-off-by: James Antill <jantill@redhat.com>

---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index b01b66d..9119924 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1581,7 +1581,7 @@ class Flasktests(Modeltests):
             self.assertEqual(output.status_code, 200)
             output_text = output.get_data(as_text=True)
             self.assertIn(
-                '<td>Please use channel@server or #room:server formats!</td>', output_text)
+                '<td>Please use IRC, Matrix, meet, zoom or hangouts formats!</td>', output_text)
             self.assertIn(
                 '<title>Add meeting - Fedocal</title>', output_text)
 

From 49b87121cb28927c126d628e8418332701d40f94 Mon Sep 17 00:00:00 2001
From: James Antill <jantill@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 6/16] tests: Stupid hack workaround for mock/strftime failures.


Signed-off-by: James Antill <jantill@redhat.com>

---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index 9119924..c7ec38c 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1880,8 +1880,12 @@ class Flasktests(Modeltests):
                 'csrf_token': csrf_token,
             }
 
-            for meet_location in meet_locations:
-              with testing.mock_sends(schema.MeetingNewV1):
+            # Copy and paste works, but using:
+            #   for meet_location in meet_locations
+            # ...always fails on the second attempt.
+            import random
+            meet_location = random.choice(meet_locations)
+            with testing.mock_sends(schema.MeetingNewV1):
                 data['meeting_location'] = meet_location
                 output = self.app.post('/test_calendar/add/', data=data,
                                        follow_redirects=True)

From e5133e96b27d99631bba58ba315bf7f7bbe0b417 Mon Sep 17 00:00:00 2001
From: James Antill <jantill@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 7/16] Allow all URLs for a meeting location. Issue #213


Signed-off-by: James Antill <jantill@redhat.com>

---

diff --git a/fedocal/forms.py b/fedocal/forms.py
index 59bd900..75b24a9 100644
--- a/fedocal/forms.py
+++ b/fedocal/forms.py
@@ -108,9 +108,13 @@ def validate_meeting_location(form, field):
     # podcast.fedoraproject.org
     if loc == 'podcast.fedoraproject.org':
         return
-    if loc == 'http://podcast.fedoraproject.org/':
+
+    # Just let in all URLs ...
+    if loc.startswith('irc://'):
+        return
+    if loc.startswith('http://'):
         return
-    if loc == 'https://podcast.fedoraproject.org/':
+    if loc.startswith('https://'):
         return
 
     raise wtforms.ValidationError(

From 3ac93cf1e0d115399f95bfc252876cd29f4d5dcf Mon Sep 17 00:00:00 2001
From: James Antill <jantill@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 8/16] test: Change the meeting time to not get the testing error, and test all urls.


Signed-off-by: James Antill <jantill@redhat.com>

---

diff --git a/tests/test_flask.py b/tests/test_flask.py
index c7ec38c..628cb58 100644
--- a/tests/test_flask.py
+++ b/tests/test_flask.py
@@ -1789,20 +1789,21 @@ class Flasktests(Modeltests):
                 self.assertNotIn(
                     'href="/meeting/20/?from_date=', output_text)
 
-            # Valid meeting location: IRC Channel with server
-            # https://pagure.io/fedocal/issue/118
-            data = {
+            _mnum = 0
+            def _tst_add_meeting_loc(loc):
+              nonlocal _mnum
+              data = {
                 'meeting_name': 'guess what?',
                 'meeting_date': TODAY,
-                'meeting_time_start': time(13, 0),
-                'meeting_time_stop': time(14, 0),
+                'meeting_time_start': time(_mnum, 0),
+                'meeting_time_stop': time(_mnum+1, 0),
                 'meeting_timezone': 'Europe/Paris',
-                'meeting_location': 'meeting-1@fedoraproject.org',
+                'meeting_location': loc,
                 'frequency': '',
                 'csrf_token': csrf_token,
-            }
-
-            with testing.mock_sends(schema.MeetingNewV1):
+              }
+              _mnum += 1
+              with testing.mock_sends(schema.MeetingNewV1):
                 output = self.app.post('/test_calendar/add/', data=data,
                                        follow_redirects=True)
                 self.assertEqual(output.status_code, 200)
@@ -1810,89 +1811,37 @@ class Flasktests(Modeltests):
                 self.assertIn(
                     '<li class="message">Meeting added</li>', output_text)
 
+            meeting_locs = set()
+            # Valid meeting location: IRC Channel with server
+            # https://pagure.io/fedocal/issue/118
+            meeting_locs.add('meeting-1@fedoraproject.org')
+
             # Valid meeting location: Matrix Room
             # https://pagure.io/fedocal/issue/213
-            data = {
-                'meeting_name': 'guess what?',
-                'meeting_date': TODAY,
-                'meeting_time_start': time(13, 0),
-                'meeting_time_stop': time(14, 0),
-                'meeting_timezone': 'Europe/Paris',
-                'meeting_location': '#meeting-1:fedoraproject.org',
-                'frequency': '',
-                'csrf_token': csrf_token,
-            }
-
-            with testing.mock_sends(schema.MeetingNewV1):
-                output = self.app.post('/test_calendar/add/', data=data,
-                                       follow_redirects=True)
-                self.assertEqual(output.status_code, 200)
-                output_text = output.get_data(as_text=True)
-                self.assertIn(
-                    '<li class="message">Meeting added</li>', output_text)
+            meeting_locs.add('#meeting-1:fedoraproject.org')
 
             # Valid meeting location: Matrix Room URL
             # https://pagure.io/fedocal/issue/213
-            data = {
-                'meeting_name': 'guess what?',
-                'meeting_date': TODAY,
-                'meeting_time_start': time(13, 0),
-                'meeting_time_stop': time(14, 0),
-                'meeting_timezone': 'Europe/Paris',
-                'meeting_location': 'https://matrix.to/#/#meeting-1:fedoraproject.org',
-                'frequency': '',
-                'csrf_token': csrf_token,
-            }
-
-            with testing.mock_sends(schema.MeetingNewV1):
-                output = self.app.post('/test_calendar/add/', data=data,
-                                       follow_redirects=True)
-                self.assertEqual(output.status_code, 200)
-                output_text = output.get_data(as_text=True)
-                self.assertIn(
-                    '<li class="message">Meeting added</li>', output_text)
+            meeting_locs.add('https://matrix.to/#/#meeting-1:fedoraproject.org')
 
             # Valid meeting location: List of current meeting locations:
-            meet_locations = ['',
-                'https://unomaha.zoom.us/j/609939109',
-                'https://hangouts.google.com/hangouts/_/67zc3kvkovelxctlilphwodlp4e',
-                'https://meet.opensuse.org/epel',
-                'irc://irc.libera.chat/fedora-zh',
-                'https://meet.google.com/acq-pwxk-fhv',
-                'https://meet.google.com/mic-otnv-kse',
-                'https://meet.jit.si/fedora-websites-apps-meeting',
-                'https://meet.kde.org/b/ale-swq-39j',
-                'https://umich.zoom.us/j/96648123924?pwd=RitQVVQvMFVSaXJhNkFBS08vWTk0Zz09',
-                'https://umich.zoom.us/j/99842244394?pwd=YVdkQjJTdnpBMUkySGVzK1kyTGoyZz09',
-                'https://meet.google.com/xuj-jswy-hat',
-                'podcast.fedoraproject.org',
-                'https://podcast.fedoraproject.org/',
-                'https://meet.google.com/jod-dkmw-ibd']
-            # https://pagure.io/fedocal/issue/213
-            data = {
-                'meeting_name': 'guess what?',
-                'meeting_date': TODAY,
-                'meeting_time_start': time(13, 0),
-                'meeting_time_stop': time(14, 0),
-                'meeting_timezone': 'Europe/Paris',
-                'meeting_location': None,
-                'frequency': '',
-                'csrf_token': csrf_token,
-            }
-
-            # Copy and paste works, but using:
-            #   for meet_location in meet_locations
-            # ...always fails on the second attempt.
-            import random
-            meet_location = random.choice(meet_locations)
-            with testing.mock_sends(schema.MeetingNewV1):
-                data['meeting_location'] = meet_location
-                output = self.app.post('/test_calendar/add/', data=data,
-                                       follow_redirects=True)
-                self.assertEqual(output.status_code, 200)
-                output_text = output.get_data(as_text=True)
-                self.assertIn(
-                    '<li class="message">Meeting added</li>', output_text)
+            meeting_locs.add('')
+            meeting_locs.add('https://unomaha.zoom.us/j/609939109')
+            meeting_locs.add('https://hangouts.google.com/hangouts/_/67zc3kvkovelxctlilphwodlp4e')
+            meeting_locs.add('https://meet.opensuse.org/epel')
+            meeting_locs.add('irc://irc.libera.chat/fedora-zh')
+            meeting_locs.add('https://meet.google.com/acq-pwxk-fhv')
+            meeting_locs.add('https://meet.google.com/mic-otnv-kse')
+            meeting_locs.add('https://meet.jit.si/fedora-websites-apps-meeting')
+            meeting_locs.add('https://meet.kde.org/b/ale-swq-39j')
+            meeting_locs.add('https://umich.zoom.us/j/96648123924?pwd=RitQVVQvMFVSaXJhNkFBS08vWTk0Zz09')
+            meeting_locs.add('https://umich.zoom.us/j/99842244394?pwd=YVdkQjJTdnpBMUkySGVzK1kyTGoyZz09')
+            meeting_locs.add('https://meet.google.com/xuj-jswy-hat')
+            meeting_locs.add('podcast.fedoraproject.org')
+            meeting_locs.add('https://podcast.fedoraproject.org/')
+            meeting_locs.add('https://meet.google.com/jod-dkmw-ibd')
+            for loc in meeting_locs:
+                _tst_add_meeting_loc(loc)
 
 
     def test_edit_meeting(self):

From 6e0c35a1bc8fb039ad6b71d24bc5c8df7c8a9218 Mon Sep 17 00:00:00 2001
From: Robert Wright <robertwright8@protonmail.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 9/16] Issue #152: Adding optional reminder_delta flag


---

diff --git a/fedocal/__init__.py b/fedocal/__init__.py
index bcf1e75..630c03d 100644
--- a/fedocal/__init__.py
+++ b/fedocal/__init__.py
@@ -619,7 +619,15 @@ def ical_all():
     for calendarobj in Calendar.get_all(SESSION):
         meetings.extend(fedocallib.get_by_date(
             SESSION, calendarobj, startd, endd, extended=False))
-    fedocallib.add_meetings_to_vcal(ical, meetings)
+    try:
+        reminder = datetime.timedelta(
+            minutes=-1 * int(
+                (flask.request.args.get('reminder_delta') or '').strip()
+            )
+        )
+    except ValueError:
+        reminder = None
+    fedocallib.add_meetings_to_vcal(ical, meetings reminder=reminder)
     headers = {}
     filename = secure_filename(
         'all_calendars-%s.ical' % (
@@ -650,7 +658,15 @@ def ical_out(calendar_name):
     meetings = fedocallib.get_by_date(
         SESSION, calendarobj, startd, endd, extended=False, tzone=False)
     ical = vobject.iCalendar()
-    fedocallib.add_meetings_to_vcal(ical, meetings)
+    try:
+        reminder = datetime.timedelta(
+            minutes=-1 * int(
+                (flask.request.args.get('reminder_delta') or '').strip()
+            )
+        )
+    except ValueError:
+        reminder = None
+    fedocallib.add_meetings_to_vcal(ical, meetings reminder=reminder)
     headers = {}
     filename = secure_filename(
         '%s-%s.ical' % (

From 5edf0b8ee08eba3b22b1f2badff187e3d4138740 Mon Sep 17 00:00:00 2001
From: Michael Scherer <misc@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 10/16] Add support for Google calendar Meet button


Fix https://pagure.io/fedocal/issue/216

---

diff --git a/fedocal/fedocallib/__init__.py b/fedocal/fedocallib/__init__.py
index 061b129..0032931 100644
--- a/fedocal/fedocallib/__init__.py
+++ b/fedocal/fedocallib/__init__.py
@@ -684,6 +684,8 @@ def add_meeting_to_vcal(ical, meeting, reminder=None):
     entry.add('organizer').value = ', '.join(meeting.meeting_manager)
     if meeting.meeting_location:
         entry.add('location').value = meeting.meeting_location
+        if meeting.meeting_location.startswith('https://meet.google.com/'):
+            entry.add('x-google-conference').value = meeting.meeting_location
 
     start = entry.add('dtstart')
     stop = entry.add('dtend')
diff --git a/tests/test_fedocallib.py b/tests/test_fedocallib.py
index 0cfe7d6..39cfd4f 100644
--- a/tests/test_fedocallib.py
+++ b/tests/test_fedocallib.py
@@ -753,6 +753,26 @@ class Fedocallibtests(Modeltests):
         self.assertFalse(hasattr(event, 'valarm_list'))
         self.assertFalse(hasattr(event, 'valarm'))
 
+    def test_add_meeting_to_vcal_gmeet(self):
+        """ Test the add_meeting_to_vcal function with Google Meet"""
+        import vobject
+        calendar = vobject.iCalendar()
+        self.__setup_meeting()
+        meetings = fedocallib.get_future_single_meeting_of_user(
+            self.session, 'pingou', from_date=TODAY)
+        self.assertNotEqual(meetings, None)
+        self.assertEqual(len(meetings), 4)
+
+        meeting = meetings[0]
+        meeting.meeting_location = "https://meet.google.com/do-not-exist"
+
+        fedocallib.add_meeting_to_vcal(calendar, meeting)
+        self.assertEqual(len(calendar.vevent_list), 1)
+        event = calendar.vevent
+        print(meeting)
+        print(event)
+        self.assertEqual(event.x_google_conference.value, event.location.value)
+
     def test_add_meetings_to_vcal(self):
         """ Test the add_meetings_to_vcal function. """
         import vobject

From 87df58557e9eccc0df3be1872a40636c899521ef Mon Sep 17 00:00:00 2001
From: Michael Scherer <misc@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 11/16] Do not use '+' with frozenset and list


Fix exception:
  TypeError: unsupported operand type(s) for +: 'frozenset' and 'list'

---

diff --git a/fedocal/__init__.py b/fedocal/__init__.py
index 630c03d..6a7fe8a 100644
--- a/fedocal/__init__.py
+++ b/fedocal/__init__.py
@@ -195,10 +195,10 @@ def sanitize(text):
     """ Sanitize a given text from any not-allowed html using bleach. """
     return bleach.clean(
         text,
-        tags=bleach.ALLOWED_TAGS + [
+        tags=bleach.ALLOWED_TAGS.union([
              'p', 'br', 'div', 'h1', 'h2', 'h3', 'table', 'td', 'tr',
              'th', 'col', 'tbody', 'pre', 'img',
-            ],
+            ]),
         attributes=bleach.ALLOWED_ATTRIBUTES
     )
 

From aa408a8c71b1a8f01d4989e1bd61f16abf63b831 Mon Sep 17 00:00:00 2001
From: Michael Scherer <misc@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 12/16] Fix code to run with flask_babel 3.0


See https://github.com/python-babel/flask-babel/releases/tag/v3.0.0

---

diff --git a/fedocal/__init__.py b/fedocal/__init__.py
index 6a7fe8a..0ad5c63 100644
--- a/fedocal/__init__.py
+++ b/fedocal/__init__.py
@@ -155,7 +155,6 @@ work.
     return decorated_function
 
 
-@babel.localeselector
 def get_locale():
     """try to guess the language from the user accept
     header the browser transmits"""
@@ -166,6 +165,7 @@ def get_locale():
         )
     except ImportError:
         return 'en'
+babel.init_app(APP, locale_selector=get_locale)
 
 
 @APP.context_processor

From 5b2cff44de064de839200b1bbdea29a939709e24 Mon Sep 17 00:00:00 2001
From: Michael Scherer <misc@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 13/16] Fix tests with newer SQLAlchemy


Not sure when, but sqlalchemy.orm.relation got renamed

---

diff --git a/fedocal/fedocallib/model.py b/fedocal/fedocallib/model.py
index 408666d..0ef9d7c 100644
--- a/fedocal/fedocallib/model.py
+++ b/fedocal/fedocallib/model.py
@@ -38,7 +38,7 @@ from sqlalchemy import (
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.orm import sessionmaker
 from sqlalchemy.orm import scoped_session
-from sqlalchemy.orm import relation as relationship
+from sqlalchemy.orm import relationship
 from sqlalchemy.sql import and_, or_
 from sqlalchemy import func as safunc
 

From 9ad7ed459583a512ca3e9b06fef556313f7d2e5e Mon Sep 17 00:00:00 2001
From: Michael Scherer <misc@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 14/16] Fix default conf to run with Flask-OIDC 2.x


See https://flask-oidc.readthedocs.io/en/latest/changelog.html#id16

---

diff --git a/README.rst b/README.rst
index c35fd18..1d4d291 100644
--- a/README.rst
+++ b/README.rst
@@ -63,10 +63,9 @@ Register the application to iddev for development::
   oidc-register https://iddev.fedorainfracloud.org/ http://localhost:5000/oidc_callback
 
 
-Add the following two lines in your configuration file `fedocal.cfg`::
+Add the following line in your configuration file `fedocal.cfg`::
 
   OIDC_ID_TOKEN_COOKIE_SECURE = False
-  OIDC_REQUIRE_VERIFIED_EMAIL = False
 
 
 Run the server::
diff --git a/fedocal/default_config.py b/fedocal/default_config.py
index 4c2561c..c05f9f4 100644
--- a/fedocal/default_config.py
+++ b/fedocal/default_config.py
@@ -85,8 +85,6 @@ ICAL_REMINDER_OPTIONS = (
 OIDC_CLIENT_SECRETS = os.path.join(os.path.dirname(
     os.path.abspath(__file__)), '..', 'client_secrets.json')
 OIDC_ID_TOKEN_COOKIE_SECURE = False
-OIDC_REQUIRE_VERIFIED_EMAIL = False
-OIDC_OPENID_REALM = 'http://localhost:5000/oidc_callback'
 OIDC_SCOPES = [
     'openid', 'email', 'profile',
     'https://id.fedoraproject.org/scope/cla',

From c96e2a84a68a3b2776e682440528c4ef439eab4a Mon Sep 17 00:00:00 2001
From: Tomas Hrcka <thrcka@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 15/16] Add missing commas


Signed-off-by: Tomas Hrcka <thrcka@redhat.com>

---

diff --git a/fedocal/__init__.py b/fedocal/__init__.py
index 0ad5c63..d4da302 100644
--- a/fedocal/__init__.py
+++ b/fedocal/__init__.py
@@ -627,7 +627,7 @@ def ical_all():
         )
     except ValueError:
         reminder = None
-    fedocallib.add_meetings_to_vcal(ical, meetings reminder=reminder)
+    fedocallib.add_meetings_to_vcal(ical, meetings, reminder=reminder)
     headers = {}
     filename = secure_filename(
         'all_calendars-%s.ical' % (
@@ -666,7 +666,7 @@ def ical_out(calendar_name):
         )
     except ValueError:
         reminder = None
-    fedocallib.add_meetings_to_vcal(ical, meetings reminder=reminder)
+    fedocallib.add_meetings_to_vcal(ical, meetings, reminder=reminder)
     headers = {}
     filename = secure_filename(
         '%s-%s.ical' % (

From 1c6026a9ea8cbf2f6bb9ac72601c3353589d5ba8 Mon Sep 17 00:00:00 2001
From: Tomas Hrcka <thrcka@redhat.com>
Date: Sep 02 2024 08:33:51 +0000
Subject: [PATCH 16/16] Update python versions in tox config


Signed-off-by: Tomas Hrcka <thrcka@redhat.com>

---

diff --git a/tox.ini b/tox.ini
index a7f5f74..21fb942 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
 [tox]
-envlist = py3{6,7,8,9,10}
+envlist = py3{9,10,12}
 # If the user is missing an interpreter, don't fail
 skip_missing_interpreters = True
 

