|
from datetime import date, datetime
|
|
from typing import Union, List
|
|
|
|
from beautiful_date import BeautifulDate
|
|
from dateutil.relativedelta import relativedelta
|
|
from tzlocal import get_localzone_name
|
|
|
|
from gcsa._services.base_service import BaseService
|
|
from gcsa.free_busy import FreeBusy, FreeBusyQueryError
|
|
from gcsa.serializers.free_busy_serializer import FreeBusySerializer
|
|
from gcsa.util.date_time_util import to_localized_iso
|
|
|
|
|
|
class FreeBusyService(BaseService):
|
|
def get_free_busy(
|
|
self,
|
|
resource_ids: Union[str, List[str]] = None,
|
|
*,
|
|
time_min: Union[date, datetime, BeautifulDate] = None,
|
|
time_max: Union[date, datetime, BeautifulDate] = None,
|
|
timezone: str = get_localzone_name(),
|
|
group_expansion_max: int = None,
|
|
calendar_expansion_max: int = None,
|
|
ignore_errors: bool = False
|
|
) -> FreeBusy:
|
|
"""Returns free/busy information for a set of calendars and/or groups.
|
|
|
|
:param resource_ids:
|
|
Identifier or list of identifiers of calendar(s) and/or group(s).
|
|
Default is `default_calendar` specified in `GoogleCalendar`.
|
|
:param time_min:
|
|
The start of the interval for the query.
|
|
:param time_max:
|
|
The end of the interval for the query.
|
|
:param timezone:
|
|
Timezone formatted as an IANA Time Zone Database name, e.g. "Europe/Zurich". By default,
|
|
the computers local timezone is used if it is configured. UTC is used otherwise.
|
|
:param group_expansion_max:
|
|
Maximal number of calendar identifiers to be provided for a single group.
|
|
An error is returned for a group with more members than this value.
|
|
Maximum value is 100.
|
|
:param calendar_expansion_max:
|
|
Maximal number of calendars for which FreeBusy information is to be provided.
|
|
Maximum value is 50.
|
|
:param ignore_errors:
|
|
Whether errors related to calendars and/or groups should be ignored.
|
|
If `False` :py:class:`~gcsa.free_busy.FreeBusyQueryError` is raised in case of query related errors.
|
|
If `True`, related errors are stored in the resulting :py:class:`~gcsa.free_busy.FreeBusy` object.
|
|
Default is `False`.
|
|
Note, request related errors (e.x. authentication error) will not be ignored regardless of
|
|
the `ignore_errors` value.
|
|
|
|
:return:
|
|
:py:class:`~gcsa.free_busy.FreeBusy` object.
|
|
"""
|
|
|
|
time_min = time_min or datetime.now()
|
|
time_max = time_max or time_min + relativedelta(weeks=2)
|
|
|
|
time_min = to_localized_iso(time_min, timezone)
|
|
time_max = to_localized_iso(time_max, timezone)
|
|
|
|
if resource_ids is None:
|
|
resource_ids = [self.default_calendar]
|
|
elif not isinstance(resource_ids, (list, tuple, set)):
|
|
resource_ids = [resource_ids]
|
|
|
|
body = {
|
|
"timeMin": time_min,
|
|
"timeMax": time_max,
|
|
"timeZone": timezone,
|
|
"groupExpansionMax": group_expansion_max,
|
|
"calendarExpansionMax": calendar_expansion_max,
|
|
"items": [
|
|
{
|
|
"id": r_id
|
|
} for r_id in resource_ids
|
|
]
|
|
}
|
|
|
|
free_busy_json = self.service.freebusy().query(body=body).execute()
|
|
free_busy = FreeBusySerializer.to_object(free_busy_json)
|
|
if not ignore_errors and (free_busy.groups_errors or free_busy.calendars_errors):
|
|
raise FreeBusyQueryError(groups_errors=free_busy.groups_errors,
|
|
calendars_errors=free_busy.calendars_errors)
|
|
|
|
return free_busy
|
|
|