|
|
@@ -79,6 +79,8 @@ class _AirbnbClient:
|
|
|
self._tz = tz
|
|
|
self._cache: dict[str, DayInfo] = {}
|
|
|
self._fetched_months: set[tuple[int, int]] = set()
|
|
|
+ self._raw_months: dict[tuple[int, int], list[dict]] = {}
|
|
|
+ self._months_inflight: dict[tuple[int, int], asyncio.Task] = {}
|
|
|
self._refresh_lock = asyncio.Lock()
|
|
|
self._refresh_task: asyncio.Task | None = None
|
|
|
|
|
|
@@ -97,6 +99,7 @@ class _AirbnbClient:
|
|
|
def clear_cache(self) -> None:
|
|
|
self._cache.clear()
|
|
|
self._fetched_months.clear()
|
|
|
+ self._raw_months.clear()
|
|
|
|
|
|
def _reload_from_env(self) -> None:
|
|
|
env_file = data_home() / 'airbnb.env'
|
|
|
@@ -231,12 +234,29 @@ class _AirbnbClient:
|
|
|
) or {}
|
|
|
return section.get('days', [])
|
|
|
|
|
|
+ async def _get_month_days(self, month: int, year: int) -> list[dict]:
|
|
|
+ key = (month, year)
|
|
|
+ if key in self._raw_months:
|
|
|
+ return self._raw_months[key]
|
|
|
+ if key in self._months_inflight:
|
|
|
+ return await self._months_inflight[key]
|
|
|
+ task = asyncio.create_task(self._fetch_month_days(month, year))
|
|
|
+ self._months_inflight[key] = task
|
|
|
+ try:
|
|
|
+ result = await task
|
|
|
+ finally:
|
|
|
+ self._months_inflight.pop(key, None)
|
|
|
+ self._raw_months[key] = result
|
|
|
+ return result
|
|
|
+
|
|
|
async def get_calendar(self, date_from: str, date_to: str) -> dict[str, DayInfo]:
|
|
|
if is_stale('airbnb'):
|
|
|
raise AirbnbAuthError(f'Airbnb credentials are stale — run: {_AUTH_HINT}')
|
|
|
- for month, year in months_in_range(date_from, date_to):
|
|
|
+ month_list = months_in_range(date_from, date_to)
|
|
|
+ all_days = await asyncio.gather(*[self._get_month_days(m, y) for m, y in month_list])
|
|
|
+ for (month, year), days in zip(month_list, all_days):
|
|
|
if (month, year) not in self._fetched_months:
|
|
|
- for day in await self._fetch_month_days(month, year):
|
|
|
+ for day in days:
|
|
|
d = day.get('day', '')
|
|
|
if d:
|
|
|
self._cache[d] = DayInfo(
|
|
|
@@ -252,9 +272,11 @@ class _AirbnbClient:
|
|
|
async def get_reservations(self, date_from: str, date_to: str) -> list[Reservation]:
|
|
|
if is_stale('airbnb'):
|
|
|
raise AirbnbAuthError(f'Airbnb credentials are stale — run: {_AUTH_HINT}')
|
|
|
+ month_list = months_in_range(date_from, date_to)
|
|
|
+ all_days = await asyncio.gather(*[self._get_month_days(m, y) for m, y in month_list])
|
|
|
booked: dict[str, str] = {}
|
|
|
- for month, year in months_in_range(date_from, date_to):
|
|
|
- for day in await self._fetch_month_days(month, year):
|
|
|
+ for days in all_days:
|
|
|
+ for day in days:
|
|
|
d = day.get('day', '')
|
|
|
res_data = day.get('reservationData')
|
|
|
if res_data and date_from <= d <= date_to:
|