Fetch full event detail: batch listing omits text_fr/attachments for events
Found by testing: unlike news items, the agenda @results batch listing always returns text_fr and items (attachments) as null for events - only description_fr (short teaser) was ever available from it. The site itself works around this by firing a second request per event (@results?UID=<uid>&fullobjects=1) when you open one; we now do the same, with a per-UID cache since a recurring event shares one UID across all its occurrences. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+26
-1
@@ -25,6 +25,30 @@ function fetch_all_events(): array
|
|||||||
return $items;
|
return $items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contrairement aux actualites, l'API renvoie text_fr/items (texte complet
|
||||||
|
* et pieces jointes) a null dans la liste paginee des evenements - il faut
|
||||||
|
* une requete par UID pour les recuperer (c'est ce que fait le site
|
||||||
|
* lui-meme quand on ouvre un evenement). Un evenement recurrent partage un
|
||||||
|
* seul UID sur toutes ses occurrences, donc un cache statique evite de
|
||||||
|
* refaire la requete pour chaque occurrence.
|
||||||
|
*/
|
||||||
|
function fetch_event_detail(string $uid): ?array
|
||||||
|
{
|
||||||
|
static $cache = [];
|
||||||
|
if (array_key_exists($uid, $cache)) {
|
||||||
|
return $cache[$uid];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$url = EVENTS_API . '?UID=' . rawurlencode($uid) . '&fullobjects=1';
|
||||||
|
$data = json_decode(http_get($url), true);
|
||||||
|
$cache[$uid] = $data['items'][0] ?? null;
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
$cache[$uid] = null;
|
||||||
|
}
|
||||||
|
return $cache[$uid];
|
||||||
|
}
|
||||||
|
|
||||||
function format_event_meta(array $item): string
|
function format_event_meta(array $item): string
|
||||||
{
|
{
|
||||||
$parts = [];
|
$parts = [];
|
||||||
@@ -54,8 +78,9 @@ function build_events_feed(): string
|
|||||||
$title = $item['title_fr'] ?? $item['title'] ?? '(sans titre)';
|
$title = $item['title_fr'] ?? $item['title'] ?? '(sans titre)';
|
||||||
$uid = $item['UID'] ?? $id;
|
$uid = $item['UID'] ?? $id;
|
||||||
$meta = format_event_meta($item);
|
$meta = format_event_meta($item);
|
||||||
|
$detail = fetch_event_detail($uid);
|
||||||
$description = ($meta !== '' ? '<p>' . htmlspecialchars($meta, ENT_QUOTES, 'UTF-8') . '</p>' : '')
|
$description = ($meta !== '' ? '<p>' . htmlspecialchars($meta, ENT_QUOTES, 'UTF-8') . '</p>' : '')
|
||||||
. full_body_html($item, $title);
|
. full_body_html($detail ?? $item, $title);
|
||||||
// Un evenement recurrent partage le meme UID sur toutes ses
|
// Un evenement recurrent partage le meme UID sur toutes ses
|
||||||
// occurrences (memes UID, dates differentes) : on suffixe le guid
|
// occurrences (memes UID, dates differentes) : on suffixe le guid
|
||||||
// avec la date de debut pour rester unique par occurrence, comme
|
// avec la date de debut pour rester unique par occurrence, comme
|
||||||
|
|||||||
+25
-1
@@ -157,6 +157,29 @@ def build_news_items() -> list[str]:
|
|||||||
return entries
|
return entries
|
||||||
|
|
||||||
|
|
||||||
|
_event_detail_cache: dict[str, dict | None] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_event_detail(uid: str) -> dict | None:
|
||||||
|
"""
|
||||||
|
Contrairement aux actualites, l'API renvoie text_fr/items (texte complet
|
||||||
|
et pieces jointes) a null dans la liste paginee des evenements - il faut
|
||||||
|
une requete par UID pour les recuperer (c'est ce que fait le site
|
||||||
|
lui-meme quand on ouvre un evenement). Un evenement recurrent partage un
|
||||||
|
seul UID sur toutes ses occurrences, d'ou le cache pour eviter de
|
||||||
|
refaire la requete pour chaque occurrence.
|
||||||
|
"""
|
||||||
|
if uid in _event_detail_cache:
|
||||||
|
return _event_detail_cache[uid]
|
||||||
|
try:
|
||||||
|
data = fetch_json(f"{EVENTS_API}?UID={uid}&fullobjects=1")
|
||||||
|
detail = (data.get("items") or [None])[0]
|
||||||
|
except Exception:
|
||||||
|
detail = None
|
||||||
|
_event_detail_cache[uid] = detail
|
||||||
|
return detail
|
||||||
|
|
||||||
|
|
||||||
def format_event_meta(item: dict) -> str:
|
def format_event_meta(item: dict) -> str:
|
||||||
parts = []
|
parts = []
|
||||||
start = parse_dt(item.get("start"))
|
start = parse_dt(item.get("start"))
|
||||||
@@ -183,7 +206,8 @@ def build_event_items() -> list[str]:
|
|||||||
guid = item.get("UID") or event_id
|
guid = item.get("UID") or event_id
|
||||||
link = f"{SITE}/agenda/{slugify(title)}?u={guid}"
|
link = f"{SITE}/agenda/{slugify(title)}?u={guid}"
|
||||||
meta = format_event_meta(item)
|
meta = format_event_meta(item)
|
||||||
description = (f"<p>{html.escape(meta)}</p>" if meta else "") + full_body_html(item, title)
|
detail = fetch_event_detail(guid) or item
|
||||||
|
description = (f"<p>{html.escape(meta)}</p>" if meta else "") + full_body_html(detail, title)
|
||||||
pub_dt = parse_dt(item.get("created") or item.get("start"))
|
pub_dt = parse_dt(item.get("created") or item.get("start"))
|
||||||
# Un evenement recurrent partage le meme UID sur toutes ses
|
# Un evenement recurrent partage le meme UID sur toutes ses
|
||||||
# occurrences : on suffixe le guid avec la date de debut pour
|
# occurrences : on suffixe le guid avec la date de debut pour
|
||||||
|
|||||||
Reference in New Issue
Block a user