3838
3939class ScheduleMixin :
4040 MY_STARRED_ICS_TOKEN_SESSION_KEY = 'my_starred_ics_token'
41-
41+
4242 @cached_property
4343 def version (self ):
4444 if version := self .kwargs .get ("version" ):
@@ -372,28 +372,25 @@ class CalendarRedirectView(EventPermissionRequired, ScheduleMixin, TemplateView)
372372 def get (self , request , * args , ** kwargs ):
373373 # Get URL name from resolver
374374 url_name = request .resolver_match .url_name if request .resolver_match else None
375-
376375 # Determine calendar type and starred status from URL pattern
377376 is_google = "google" in url_name
378377 is_my = "my" in url_name
379378
380379 if is_my :
381380 # For starred sessions
382381 if not request .user .is_authenticated :
383- login_url = f"{ self .request .event .urls .login } ?next= { request .get_full_path ()} "
382+ login_url = f"{ self .request .event .urls .login } ?{ urlencode ({ 'next' : request .get_full_path ()} )} "
384383 return HttpResponseRedirect (login_url )
385384
386385 # Check for existing valid token
387386 existing_token = request .session .get (self .MY_STARRED_ICS_TOKEN_SESSION_KEY )
388387 generate_new_token = True
389-
390388 # If we have an existing token, check if it's still valid and not expiring soon
391389 if existing_token :
392390 token_status = self .check_token_expiry (existing_token )
393391 if token_status is True : # Token is valid and has at least 4 days left
394392 token = existing_token
395393 generate_new_token = False
396-
397394 # Generate new token if needed (this will invalidate any existing token)
398395 if generate_new_token :
399396 token = self .generate_ics_token (request , request .user .id )
@@ -419,20 +416,21 @@ def get(self, request, *args, **kwargs):
419416 if is_google :
420417 # Google Calendar requires special URL format
421418 google_url = f"https://calendar.google.com/calendar/render?{ urlencode ({'cid' : ics_url })} "
419+ # HTML-based redirection works more reliably across calendar clients like Outlook and Apple Calendar which often mishandle HTTP 302s.
422420 response = HttpResponse (
423421 f'<html><head><meta http-equiv="refresh" content="0;url={ google_url } "></head>'
424422 f'<body><p style="text-align: center; padding:2vw; font-family: Roboto,Helvetica Neue,HelveticaNeue,Helvetica,Arial,sans-serif;">Redirecting to Google Calendar: { google_url } </p><script>window.location.href="{ google_url } ";</script></body></html>' ,
425423 content_type = 'text/html'
426424 )
427425 return response
428- else :
429- # Other calendars use webcal protocol
430- parsed = urlparse (ics_url )
431- webcal_url = urlunparse (('webcal' ,) + parsed [1 :])
432- # Create a simple HTML redirect with meta refresh
433- response = HttpResponse (
434- f'<html><head><meta http-equiv="refresh" content="0;url={ webcal_url } "></head>'
435- f'<body><p style="text-align: center; padding:2vw; font-family: Roboto,Helvetica Neue,HelveticaNeue,Helvetica,Arial,sans-serif;">Redirecting to: { webcal_url } </p><script>window.location.href="{ webcal_url } ";</script></body></html>' ,
436- content_type = 'text/html'
437- )
438- return response
426+
427+ # Other calendars use webcal protocol
428+ parsed = urlparse (ics_url )
429+ webcal_url = urlunparse (('webcal' ,) + parsed [1 :])
430+ # HTML-based redirection works more reliably across calendar clients like Outlook and Apple Calendar which often mishandle HTTP 302s.
431+ response = HttpResponse (
432+ f'<html><head><meta http-equiv="refresh" content="0;url={ webcal_url } "></head>'
433+ f'<body><p style="text-align: center; padding:2vw; font-family: Roboto,Helvetica Neue,HelveticaNeue,Helvetica,Arial,sans-serif;">Redirecting to: { webcal_url } </p><script>window.location.href="{ webcal_url } ";</script></body></html>' ,
434+ content_type = 'text/html'
435+ )
436+ return response
0 commit comments