✨(back) extract ICS URL property and display in invitation emails
Add visio conference URL support to invitation emails: - Add url field to EventDetails dataclass - Extract URL property in ICalendarParser.parse() - Fix extract_property regex to preserve full URLs (was truncating https:// by splitting on colon) - Add conditional visio section to all 8 email templates (invitation, update, cancel, reply — HTML and text) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,7 @@ class EventDetails:
|
|||||||
summary: str
|
summary: str
|
||||||
description: Optional[str]
|
description: Optional[str]
|
||||||
location: Optional[str]
|
location: Optional[str]
|
||||||
|
url: Optional[str]
|
||||||
dtstart: datetime
|
dtstart: datetime
|
||||||
dtend: Optional[datetime]
|
dtend: Optional[datetime]
|
||||||
organizer_email: str
|
organizer_email: str
|
||||||
@@ -95,17 +96,10 @@ class ICalendarParser:
|
|||||||
# Handle multi-line values (lines starting with space/tab are continuations)
|
# Handle multi-line values (lines starting with space/tab are continuations)
|
||||||
icalendar = re.sub(r"\r?\n[ \t]", "", icalendar)
|
icalendar = re.sub(r"\r?\n[ \t]", "", icalendar)
|
||||||
|
|
||||||
pattern = rf"^{property_name}[;:](.+)$"
|
pattern = rf"^{property_name}(;[^:]*)?:(.+)$"
|
||||||
match = re.search(pattern, icalendar, re.MULTILINE | re.IGNORECASE)
|
match = re.search(pattern, icalendar, re.MULTILINE | re.IGNORECASE)
|
||||||
if match:
|
if match:
|
||||||
value = match.group(1)
|
return match.group(2).strip()
|
||||||
# Remove parameters (everything before the last colon if there are parameters)
|
|
||||||
if ";" in property_name or ":" not in value:
|
|
||||||
return value.strip()
|
|
||||||
# Handle properties with parameters like ORGANIZER;CN=Name:mailto:email
|
|
||||||
if ":" in value:
|
|
||||||
return value.split(":")[-1].strip()
|
|
||||||
return value.strip()
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -205,6 +199,7 @@ class ICalendarParser:
|
|||||||
summary = cls.extract_property(vevent_block, "SUMMARY") or "(Sans titre)"
|
summary = cls.extract_property(vevent_block, "SUMMARY") or "(Sans titre)"
|
||||||
description = cls.extract_property(vevent_block, "DESCRIPTION")
|
description = cls.extract_property(vevent_block, "DESCRIPTION")
|
||||||
location = cls.extract_property(vevent_block, "LOCATION")
|
location = cls.extract_property(vevent_block, "LOCATION")
|
||||||
|
url = cls.extract_property(vevent_block, "URL")
|
||||||
|
|
||||||
# Parse dates with timezone support - from VEVENT block only
|
# Parse dates with timezone support - from VEVENT block only
|
||||||
dtstart_raw, dtstart_params = cls.extract_property_with_params(
|
dtstart_raw, dtstart_params = cls.extract_property_with_params(
|
||||||
@@ -265,6 +260,7 @@ class ICalendarParser:
|
|||||||
summary=summary,
|
summary=summary,
|
||||||
description=description,
|
description=description,
|
||||||
location=location,
|
location=location,
|
||||||
|
url=url,
|
||||||
dtstart=dtstart,
|
dtstart=dtstart,
|
||||||
dtend=dtend,
|
dtend=dtend,
|
||||||
organizer_email=organizer_email,
|
organizer_email=organizer_email,
|
||||||
|
|||||||
@@ -119,6 +119,12 @@
|
|||||||
<td>{{ event.location }}</td>
|
<td>{{ event.location }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if event.url %}
|
||||||
|
<tr>
|
||||||
|
<td>Visio</td>
|
||||||
|
<td><a href="{{ event.url }}" style="color: #0066cc;">{{ event.url }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>Organisateur</td>
|
<td>Organisateur</td>
|
||||||
<td>{{ organizer_display }} <{{ event.organizer_email }}></td>
|
<td>{{ organizer_display }} <{{ event.organizer_email }}></td>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Détails de l'événement
|
|||||||
Titre : {{ event.summary }}
|
Titre : {{ event.summary }}
|
||||||
Quand : {{ start_date }} {{ time_str }}{% if start_date != end_date %} - {{ end_date }}{% endif %}
|
Quand : {{ start_date }} {{ time_str }}{% if start_date != end_date %} - {{ end_date }}{% endif %}
|
||||||
{% if event.location %}Lieu : {{ event.location }}
|
{% if event.location %}Lieu : {{ event.location }}
|
||||||
|
{% endif %}{% if event.url %}Visio : {{ event.url }}
|
||||||
{% endif %}Organisateur : {{ organizer_display }} <{{ event.organizer_email }}>
|
{% endif %}Organisateur : {{ organizer_display }} <{{ event.organizer_email }}>
|
||||||
|
|
||||||
{% if event.description %}
|
{% if event.description %}
|
||||||
|
|||||||
@@ -114,6 +114,12 @@
|
|||||||
<td>{{ event.location }}</td>
|
<td>{{ event.location }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if event.url %}
|
||||||
|
<tr>
|
||||||
|
<td>Visio</td>
|
||||||
|
<td>{{ event.url }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>Organisateur</td>
|
<td>Organisateur</td>
|
||||||
<td>{{ organizer_display }} <{{ event.organizer_email }}></td>
|
<td>{{ organizer_display }} <{{ event.organizer_email }}></td>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Détails de l'événement annulé
|
|||||||
Titre : {{ event.summary }}
|
Titre : {{ event.summary }}
|
||||||
Était prévu le : {{ start_date }} {{ time_str }}{% if start_date != end_date %} - {{ end_date }}{% endif %}
|
Était prévu le : {{ start_date }} {{ time_str }}{% if start_date != end_date %} - {{ end_date }}{% endif %}
|
||||||
{% if event.location %}Lieu : {{ event.location }}
|
{% if event.location %}Lieu : {{ event.location }}
|
||||||
|
{% endif %}{% if event.url %}Visio : {{ event.url }}
|
||||||
{% endif %}Organisateur : {{ organizer_display }} <{{ event.organizer_email }}>
|
{% endif %}Organisateur : {{ organizer_display }} <{{ event.organizer_email }}>
|
||||||
|
|
||||||
Cet événement a été annulé. Vous pouvez le supprimer de votre calendrier en ouvrant le fichier .ics en pièce jointe.
|
Cet événement a été annulé. Vous pouvez le supprimer de votre calendrier en ouvrant le fichier .ics en pièce jointe.
|
||||||
|
|||||||
@@ -101,6 +101,12 @@
|
|||||||
<td>{{ event.location }}</td>
|
<td>{{ event.location }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if event.url %}
|
||||||
|
<tr>
|
||||||
|
<td>Visio</td>
|
||||||
|
<td><a href="{{ event.url }}" style="color: #28a745;">{{ event.url }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>Participant</td>
|
<td>Participant</td>
|
||||||
<td>{{ attendee_display }} <{{ event.attendee_email }}></td>
|
<td>{{ attendee_display }} <{{ event.attendee_email }}></td>
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ Détails de l'événement
|
|||||||
Titre : {{ event.summary }}
|
Titre : {{ event.summary }}
|
||||||
Quand : {{ start_date }} {{ time_str }}{% if start_date != end_date %} - {{ end_date }}{% endif %}
|
Quand : {{ start_date }} {{ time_str }}{% if start_date != end_date %} - {{ end_date }}{% endif %}
|
||||||
{% if event.location %}Lieu : {{ event.location }}
|
{% if event.location %}Lieu : {{ event.location }}
|
||||||
|
{% endif %}{% if event.url %}Visio : {{ event.url }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
La réponse du participant a été enregistrée dans le fichier .ics en pièce jointe.
|
La réponse du participant a été enregistrée dans le fichier .ics en pièce jointe.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -124,6 +124,12 @@
|
|||||||
<td>{{ event.location }}</td>
|
<td>{{ event.location }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if event.url %}
|
||||||
|
<tr>
|
||||||
|
<td>Visio</td>
|
||||||
|
<td><a href="{{ event.url }}" style="color: #e65100;">{{ event.url }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>Organisateur</td>
|
<td>Organisateur</td>
|
||||||
<td>{{ organizer_display }} <{{ event.organizer_email }}></td>
|
<td>{{ organizer_display }} <{{ event.organizer_email }}></td>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Détails de l'événement mis à jour
|
|||||||
Titre : {{ event.summary }}
|
Titre : {{ event.summary }}
|
||||||
Quand : {{ start_date }} {{ time_str }}{% if start_date != end_date %} - {{ end_date }}{% endif %}
|
Quand : {{ start_date }} {{ time_str }}{% if start_date != end_date %} - {{ end_date }}{% endif %}
|
||||||
{% if event.location %}Lieu : {{ event.location }}
|
{% if event.location %}Lieu : {{ event.location }}
|
||||||
|
{% endif %}{% if event.url %}Visio : {{ event.url }}
|
||||||
{% endif %}Organisateur : {{ organizer_display }} <{{ event.organizer_email }}>
|
{% endif %}Organisateur : {{ organizer_display }} <{{ event.organizer_email }}>
|
||||||
|
|
||||||
{% if event.description %}
|
{% if event.description %}
|
||||||
|
|||||||
Reference in New Issue
Block a user