Vremena dnevnih namaza (sabah, podne, ikindija, akšam, jacija) sa api.vaktija.ba. - idriz/apps/vaktija/store.py: izbor lokacije + bundlana lista (lokacije.json, 118 lokacija; id=indeks). Sarajevo default. Bez openai/requests (uvozi ga admin). - client.py: dohvat vakat[] po (lokacija, datum) sa keširanjem; API vraća lokalna vremena (sam vodi DST). vakat[1] je izlazak sunca (nije namaz), preskočen. - manifest.py: alat namaz_vrijeme(koji): 'sljedeci' = prvi nadolazeći (ili sutra sabah ako su svi prošli); ili konkretan namaz (danas ako nadolazi, inače sutra). Bosanska gramatika za "za X sati/minuta" i rod (prošao/prošlo/prošla). - admin.py + templates/vaktija.html: dropdown svih lokacija, Sarajevo default. - Registrovano u load_apps() i ADMIN_APPS. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LzKpYaEsuWDevuNnvSjcFW
68 lines
2.2 KiB
Python
68 lines
2.2 KiB
Python
"""Dohvat vremena namaza sa api.vaktija.ba, sa keširanjem po (lokacija, datum).
|
|
|
|
Koristi requests (uvozi ga samo asistent, ne admin). API vraća lokalna vremena
|
|
(sam vodi računa o ljetnom/zimskom vremenu). vakat[] ima 6 vrijednosti:
|
|
[sabah/zora, izlazak sunca, podne, ikindija, akšam, jacija].
|
|
"""
|
|
import datetime as dt
|
|
import json
|
|
import logging
|
|
import os
|
|
import tempfile
|
|
import threading
|
|
from pathlib import Path
|
|
|
|
import requests
|
|
|
|
log = logging.getLogger("idriz.vaktija")
|
|
|
|
CACHE_PATH = Path(os.environ.get(
|
|
"IDRIZ_VAKTIJA_CACHE_PATH", str(Path.home() / ".local/share/idriz/vaktija-cache.json")))
|
|
API = "https://api.vaktija.ba/vaktija/v1"
|
|
_lock = threading.Lock()
|
|
|
|
|
|
def _load_cache() -> dict:
|
|
try:
|
|
return json.loads(CACHE_PATH.read_text(encoding="utf-8"))
|
|
except (OSError, json.JSONDecodeError):
|
|
return {}
|
|
|
|
|
|
def _save_cache(cache: dict) -> None:
|
|
# drži zadnjih ~60 dana da fajl ne raste
|
|
if len(cache) > 60:
|
|
for k in sorted(cache.keys())[:-60]:
|
|
del cache[k]
|
|
with _lock:
|
|
CACHE_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
fd, tmp = tempfile.mkstemp(dir=str(CACHE_PATH.parent), suffix=".tmp")
|
|
try:
|
|
with os.fdopen(fd, "w", encoding="utf-8") as f:
|
|
json.dump(cache, f, ensure_ascii=False)
|
|
os.replace(tmp, CACHE_PATH)
|
|
finally:
|
|
if os.path.exists(tmp):
|
|
os.unlink(tmp)
|
|
|
|
|
|
def fetch_vakat(loc_id: int, date: dt.date) -> list[str] | None:
|
|
"""Vrati listu od 6 vremena ("H:MM") za datu lokaciju i datum, ili None ako ne uspije."""
|
|
key = f"{loc_id}-{date.isoformat()}"
|
|
cache = _load_cache()
|
|
if key in cache:
|
|
return cache[key]
|
|
url = f"{API}/{loc_id}/{date.year}/{date.month}/{date.day}"
|
|
try:
|
|
r = requests.get(url, timeout=10, headers={"User-Agent": "Idriz/0.1"})
|
|
r.raise_for_status()
|
|
vakat = r.json().get("vakat")
|
|
if isinstance(vakat, list) and len(vakat) == 6:
|
|
cache[key] = vakat
|
|
_save_cache(cache)
|
|
return vakat
|
|
log.warning("neočekivan odgovor vaktije za %s: %r", key, vakat)
|
|
except Exception: # noqa: BLE001
|
|
log.warning("vaktija API nije uspio za %s", key)
|
|
return None
|