prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Calendar link in calendar not working properly
  In the description, "Join using link:  https://eventyay.com/e/fa96ae2c/video/Main Hall/187"
  
  The space is treated as a break, clipping the link at Main"
  
  "Main Hall" should be HTTP encoded to Main%20Hall
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `app/api/helpers/calendar/ical.py`
  Content:
  ```
  1 import pytz
  2 from flask import jsonify
  3 from flask_jwt_extended import current_user
  4 from icalendar import Calendar, Event
  5 from sqlalchemy import or_
  6 from sqlalchemy.orm import joinedload
  7 
  8 from app.models.session import Session
  9 
  10 
  11 def to_ical(event, include_sessions=False, my_schedule=False, user_id=None):
  12     cal = Calendar()
  13     cal.add('version', '2.0')
  14     cal.add('METHOD', 'PUBLISH')
  15     cal.add('X-WR-CALNAME', event.name)
  16     cal.add('X-WR-CALDESC', 'Event Calendar')
  17 
  18     event_component = Event()
  19     event_component.add('uid', event.identifier)
  20     event_component.add('summary', event.name)
  21     event_component.add('url', event.site_link)
  22     event_component.add('dtstart', event.starts_at_tz)
  23     event_component.add('dtend', event.ends_at_tz)
  24     event_component.add('location', event.normalized_location)
  25     event_component.add('description', event.description)
  26     if event.has_coordinates:
  27         event_component.add('geo', (event.latitude, event.longitude))
  28     if event.owner_description:
  29         event_component.add('organizer', event.owner_description)
  30 
  31     cal.add_component(event_component)
  32 
  33     if include_sessions:
  34         sessions_query = (
  35             Session.query.filter_by(event_id=event.id)
  36             .options(joinedload(Session.microlocation))
  37             .filter_by(deleted_at=None)
  38             .filter(or_(Session.state == 'accepted', Session.state == 'confirmed'))
  39             .order_by(Session.starts_at.asc())
  40         )
  41         if my_schedule:
  42             if not (current_user or user_id):
  43                 return jsonify(error='Login or User ID required'), 401
  44 
  45             user_id = user_id or current_user.id
  46             sessions_query = sessions_query.join(Session.favourites).filter_by(
  47                 user_id=user_id
  48             )
  49         sessions = sessions_query.all()
  50 
  51         for session in sessions:
  52 
  53             if not (session and session.starts_at and session.ends_at):
  54                 continue
  55 
  56             session_video_url = (
  57                 " "
  58                 + event.site_link
  59                 + '/video/'
  60                 + session.microlocation.video_stream.name
  61                 + "/"
  62                 + str(session.microlocation.video_stream.id)
  63                 if session.microlocation.video_stream
  64                 else ""
  65             )
  66             session_link_heading = (
  67                 "Join using link: " + session_video_url + "<br/>"
  68                 if session_video_url
  69                 else ""
  70             )
  71             session_description = (
  72                 " "
  73                 + "Room: "
  74                 + session.microlocation.name
  75                 + "<br/>"
  76                 + session_link_heading
  77                 + "<br/>"
  78                 + session.short_abstract
  79             )
  80             session_component = Event()
  81             session_component.add('summary', session.title)
  82             session_component.add('uid', str(session.id) + "-" + event.identifier)
  83             session_component.add('geo', (event.latitude, event.longitude))
  84             session_component.add(
  85                 'location',
  86                 session_video_url
  87                 or (session.microlocation and session.microlocation.name)
  88                 or '' + " " + event.location_name,
  89             )
  90             session_component.add(
  91                 'dtstart', session.starts_at.astimezone(pytz.timezone(event.timezone))
  92             )
  93             session_component.add(
  94                 'dtend', session.ends_at.astimezone(pytz.timezone(event.timezone))
  95             )
  96             session_component.add('description', session_description)
  97             session_component.add('url', event.site_link + '/session/' + str(session.id))
  98 
  99             cal.add_component(session_component)
  100 
  101     return cal.to_ical()
  102
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/app/api/helpers/calendar/ical.py b/app/api/helpers/calendar/ical.py
  --- a/app/api/helpers/calendar/ical.py
  +++ b/app/api/helpers/calendar/ical.py
  @@ -1,3 +1,5 @@
  +from urllib.parse import quote
  +
   import pytz
   from flask import jsonify
   from flask_jwt_extended import current_user
  @@ -57,7 +59,7 @@
                   " "
                   + event.site_link
                   + '/video/'
  -                + session.microlocation.video_stream.name
  +                + quote(session.microlocation.video_stream.name)
                   + "/"
                   + str(session.microlocation.video_stream.id)
                   if session.microlocation.video_stream
  
verification_info: {"golden_diff": "diff --git a/app/api/helpers/calendar/ical.py b/app/api/helpers/calendar/ical.py\n--- a/app/api/helpers/calendar/ical.py\n+++ b/app/api/helpers/calendar/ical.py\n@@ -1,3 +1,5 @@\n+from urllib.parse import quote\n+\n import pytz\n from flask import jsonify\n from flask_jwt_extended import current_user\n@@ -57,7 +59,7 @@\n                 \" \"\n                 + event.site_link\n                 + '/video/'\n-                + session.microlocation.video_stream.name\n+                + quote(session.microlocation.video_stream.name)\n                 + \"/\"\n                 + str(session.microlocation.video_stream.id)\n                 if session.microlocation.video_stream\n", "issue": "Calendar link in calendar not working properly\nIn the description, \"Join using link:  https://eventyay.com/e/fa96ae2c/video/Main Hall/187\"\r\n\r\nThe space is treated as a break, clipping the link at Main\"\r\n\r\n\"Main Hall\" should be HTTP encoded to Main%20Hall\n", "before_files": [{"content": "import pytz\nfrom flask import jsonify\nfrom flask_jwt_extended import current_user\nfrom icalendar import Calendar, Event\nfrom sqlalchemy import or_\nfrom sqlalchemy.orm import joinedload\n\nfrom app.models.session import Session\n\n\ndef to_ical(event, include_sessions=False, my_schedule=False, user_id=None):\n    cal = Calendar()\n    cal.add('version', '2.0')\n    cal.add('METHOD', 'PUBLISH')\n    cal.add('X-WR-CALNAME', event.name)\n    cal.add('X-WR-CALDESC', 'Event Calendar')\n\n    event_component = Event()\n    event_component.add('uid', event.identifier)\n    event_component.add('summary', event.name)\n    event_component.add('url', event.site_link)\n    event_component.add('dtstart', event.starts_at_tz)\n    event_component.add('dtend', event.ends_at_tz)\n    event_component.add('location', event.normalized_location)\n    event_component.add('description', event.description)\n    if event.has_coordinates:\n        event_component.add('geo', (event.latitude, event.longitude))\n    if event.owner_description:\n        event_component.add('organizer', event.owner_description)\n\n    cal.add_component(event_component)\n\n    if include_sessions:\n        sessions_query = (\n            Session.query.filter_by(event_id=event.id)\n            .options(joinedload(Session.microlocation))\n            .filter_by(deleted_at=None)\n            .filter(or_(Session.state == 'accepted', Session.state == 'confirmed'))\n            .order_by(Session.starts_at.asc())\n        )\n        if my_schedule:\n            if not (current_user or user_id):\n                return jsonify(error='Login or User ID required'), 401\n\n            user_id = user_id or current_user.id\n            sessions_query = sessions_query.join(Session.favourites).filter_by(\n                user_id=user_id\n            )\n        sessions = sessions_query.all()\n\n        for session in sessions:\n\n            if not (session and session.starts_at and session.ends_at):\n                continue\n\n            session_video_url = (\n                \" \"\n                + event.site_link\n                + '/video/'\n                + session.microlocation.video_stream.name\n                + \"/\"\n                + str(session.microlocation.video_stream.id)\n                if session.microlocation.video_stream\n                else \"\"\n            )\n            session_link_heading = (\n                \"Join using link: \" + session_video_url + \"<br/>\"\n                if session_video_url\n                else \"\"\n            )\n            session_description = (\n                \" \"\n                + \"Room: \"\n                + session.microlocation.name\n                + \"<br/>\"\n                + session_link_heading\n                + \"<br/>\"\n                + session.short_abstract\n            )\n            session_component = Event()\n            session_component.add('summary', session.title)\n            session_component.add('uid', str(session.id) + \"-\" + event.identifier)\n            session_component.add('geo', (event.latitude, event.longitude))\n            session_component.add(\n                'location',\n                session_video_url\n                or (session.microlocation and session.microlocation.name)\n                or '' + \" \" + event.location_name,\n            )\n            session_component.add(\n                'dtstart', session.starts_at.astimezone(pytz.timezone(event.timezone))\n            )\n            session_component.add(\n                'dtend', session.ends_at.astimezone(pytz.timezone(event.timezone))\n            )\n            session_component.add('description', session_description)\n            session_component.add('url', event.site_link + '/session/' + str(session.id))\n\n            cal.add_component(session_component)\n\n    return cal.to_ical()\n", "path": "app/api/helpers/calendar/ical.py"}], "after_files": [{"content": "from urllib.parse import quote\n\nimport pytz\nfrom flask import jsonify\nfrom flask_jwt_extended import current_user\nfrom icalendar import Calendar, Event\nfrom sqlalchemy import or_\nfrom sqlalchemy.orm import joinedload\n\nfrom app.models.session import Session\n\n\ndef to_ical(event, include_sessions=False, my_schedule=False, user_id=None):\n    cal = Calendar()\n    cal.add('version', '2.0')\n    cal.add('METHOD', 'PUBLISH')\n    cal.add('X-WR-CALNAME', event.name)\n    cal.add('X-WR-CALDESC', 'Event Calendar')\n\n    event_component = Event()\n    event_component.add('uid', event.identifier)\n    event_component.add('summary', event.name)\n    event_component.add('url', event.site_link)\n    event_component.add('dtstart', event.starts_at_tz)\n    event_component.add('dtend', event.ends_at_tz)\n    event_component.add('location', event.normalized_location)\n    event_component.add('description', event.description)\n    if event.has_coordinates:\n        event_component.add('geo', (event.latitude, event.longitude))\n    if event.owner_description:\n        event_component.add('organizer', event.owner_description)\n\n    cal.add_component(event_component)\n\n    if include_sessions:\n        sessions_query = (\n            Session.query.filter_by(event_id=event.id)\n            .options(joinedload(Session.microlocation))\n            .filter_by(deleted_at=None)\n            .filter(or_(Session.state == 'accepted', Session.state == 'confirmed'))\n            .order_by(Session.starts_at.asc())\n        )\n        if my_schedule:\n            if not (current_user or user_id):\n                return jsonify(error='Login or User ID required'), 401\n\n            user_id = user_id or current_user.id\n            sessions_query = sessions_query.join(Session.favourites).filter_by(\n                user_id=user_id\n            )\n        sessions = sessions_query.all()\n\n        for session in sessions:\n\n            if not (session and session.starts_at and session.ends_at):\n                continue\n\n            session_video_url = (\n                \" \"\n                + event.site_link\n                + '/video/'\n                + quote(session.microlocation.video_stream.name)\n                + \"/\"\n                + str(session.microlocation.video_stream.id)\n                if session.microlocation.video_stream\n                else \"\"\n            )\n            session_link_heading = (\n                \"Join using link: \" + session_video_url + \"<br/>\"\n                if session_video_url\n                else \"\"\n            )\n            session_description = (\n                \" \"\n                + \"Room: \"\n                + session.microlocation.name\n                + \"<br/>\"\n                + session_link_heading\n                + \"<br/>\"\n                + session.short_abstract\n            )\n            session_component = Event()\n            session_component.add('summary', session.title)\n            session_component.add('uid', str(session.id) + \"-\" + event.identifier)\n            session_component.add('geo', (event.latitude, event.longitude))\n            session_component.add(\n                'location',\n                session_video_url\n                or (session.microlocation and session.microlocation.name)\n                or '' + \" \" + event.location_name,\n            )\n            session_component.add(\n                'dtstart', session.starts_at.astimezone(pytz.timezone(event.timezone))\n            )\n            session_component.add(\n                'dtend', session.ends_at.astimezone(pytz.timezone(event.timezone))\n            )\n            session_component.add('description', session_description)\n            session_component.add('url', event.site_link + '/session/' + str(session.id))\n\n            cal.add_component(session_component)\n\n    return cal.to_ical()\n", "path": "app/api/helpers/calendar/ical.py"}]}