SPB Git forge

spb/sorti-ka

Public

Toutes les sorties et tous les événements du Québec, un seul endroit — 7 connecteurs, fiches SSR, design Groupe KA.

58commits 1branches 0releases
13.7 MBsize
maindefault branch
17 days agolast push
HTML 82.9% Python 15.2% TypeScript 0.9% JavaScript 0.7%
5.0 KB · 105 lines python
Raw Blame History
1# -----------------------------------------------------------------------------2# Sorti-Ka — Agrégateur de sorties & événements (province de Québec)3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# connectors/lhjmq.py : LHJMQ — matchs des 12 équipes québécoises (Phase 3)5#   Source    : API HockeyTech « modulekit » (lscluster.hockeytech.com) — le6#               flux JSON public qui motorise le site officiel theqmjhl.ca7#               (clé publique embarquée dans les sites de la ligue, largement8#               documentée). 2 GET/sync : saisons + calendrier de la saison9#               courante (~580 matchs, dont ~384 à domicile au Québec,10#               vérifié 2026-08-19 pour 2026-27).11#   Extraction: date + heure locale exactes, aréna (venue_name), équipes,12#               statut. Seuls les matchs À DOMICILE au Québec sont publiés13#               (Chicoutimi, Baie-Comeau, Victoriaville, Blainville-Boisbriand,14#               Sherbrooke, Gatineau, Québec, Rouyn-Noranda, Rimouski,15#               Val-d'Or, Shawinigan, Drummondville). Prix non publié par la16#               ligue → jamais inventé. Lien = fiche de match officielle.17#   Accès     : usage index + lien vers theqmjhl.ca ; GET throttlés,18#               identification honnête. Couverture régionale forte19#               (Abitibi, Côte-Nord, Bas-Saint-Laurent, Saguenay…).20# -----------------------------------------------------------------------------21from __future__ import annotations2223from datetime import date2425from ..normalize import clean_text, parse_time26from ..schema import Event27from .base import BaseConnector2829FEED = ("https://lscluster.hockeytech.com/feed/?feed=modulekit&view={view}"30        "&key=f322673b6bcae299&fmt=json&client_code=lhjmq&lang=fr{extra}")31GAME_URL = "https://theqmjhl.ca/gamecentre/{gid}"3233# villes des équipes QC → la ville affichée sur la fiche Sorti-Ka34QC_TEAM_CITIES = {35    "Chicoutimi": "Saguenay", "Baie-Comeau": "Baie-Comeau",36    "Victoriaville": "Victoriaville", "Blainville-Boisbriand": "Boisbriand",37    "Sherbrooke": "Sherbrooke", "Gatineau": "Gatineau", "Québec": "Québec",38    "Rouyn-Noranda": "Rouyn-Noranda", "Rimouski": "Rimouski",39    "Val-d'Or": "Val-d'Or", "Shawinigan": "Shawinigan",40    "Drummondville": "Drummondville",41}424344def _label(team: dict, side: str) -> str:45    """« Remparts de Québec » à partir de city/nickname ; repli sur le nom brut."""46    nick = clean_text(team.get(f"{side}_team_nickname") or "")47    city = clean_text(team.get(f"{side}_team_city") or "")48    if nick and city:49        return f"{nick} ({city})"50    return clean_text(team.get(f"{side}_team_name") or "")515253class LhjmqConnector(BaseConnector):54    source_id = "lhjmq"55    request_delay = 1.05657    def _current_seasons(self) -> list[str]:58        """Saisons non terminées (régulière + séries), les plus récentes."""59        data = self.get_json(FEED.format(view="seasons", extra=""))60        seasons = (data.get("SiteKit") or {}).get("Seasons") or []61        today = date.today().isoformat()62        keep = [s["season_id"] for s in seasons63                if (s.get("end_date") or "") >= today]64        return sorted(keep, key=int)[-2:]      # au plus 2 (régulière + séries)6566    def fetch(self) -> list[Event]:67        events: list[Event] = []68        seen: set[str] = set()69        for sid in self._current_seasons():70            data = self.get_json(FEED.format(71                view="schedule", extra=f"&season_id={sid}"))72            for g in (data.get("SiteKit") or {}).get("Schedule") or []:73                home_city = clean_text(g.get("home_team_city") or "")74                if home_city not in QC_TEAM_CITIES:75                    continue76                gid = str(g.get("game_id") or "")77                d = g.get("date_played") or ""78                if not gid or not d or gid in seen:79                    continue80                seen.add(gid)81                home, vis = _label(g, "home"), _label(g, "visiting")82                heure = parse_time(g.get("schedule_time") or "")83                venue = clean_text(g.get("venue_name") or "")84                status = ""85                if str(g.get("game_status") or "").lower().startswith(86                        ("cancel", "annul")):87                    status = "cancelled"88                events.append(Event(89                    source=self.source_id,90                    external_id=gid,91                    url=GAME_URL.format(gid=gid),92                    title=f"LHJMQ : {vis} c. {home}",93                    description=(f"Match de la Ligue de hockey junior "94                                 f"Maritimes Québec (LHJMQ) — {vis} en "95                                 f"visite chez {home}, {venue}."),96                    raw_categories=["hockey", "sport"],97                    venue=venue,98                    city=QC_TEAM_CITIES[home_city],99                    start_date=d,100                    start_time=heure,101                    status=status,102                    organizer="LHJMQ",103                ))104        return events105