|
from functools import total_ordering
|
|
from typing import List, Union
|
|
|
|
from beautiful_date import BeautifulDate
|
|
from tzlocal import get_localzone_name
|
|
from datetime import datetime, date, timedelta, time
|
|
|
|
from ._resource import Resource
|
|
from .attachment import Attachment
|
|
from .attendee import Attendee
|
|
from .conference import ConferenceSolution, ConferenceSolutionCreateRequest
|
|
from .person import Person
|
|
from .reminders import PopupReminder, EmailReminder, Reminder
|
|
from .util.date_time_util import ensure_localisation
|
|
|
|
|
|
class Visibility:
|
|
"""Possible values of the event visibility.
|
|
|
|
* `DEFAULT` - Uses the default visibility for events on the calendar. This is the default value.
|
|
* `PUBLIC` - The event is public and event details are visible to all readers of the calendar.
|
|
* `PRIVATE` - The event is private and only event attendees may view event details.
|
|
"""
|
|
|
|
DEFAULT = "default"
|
|
PUBLIC = "public"
|
|
PRIVATE = "private"
|
|
|
|
|
|
class Transparency:
|
|
"""Possible values of the event transparency.
|
|
|
|
* `OPAQUE` - Default value. The event does block time on the calendar.
|
|
This is equivalent to setting 'Show me as' to 'Busy' in the Calendar UI.
|
|
* `TRANSPARENT` - The event does not block time on the calendar.
|
|
This is equivalent to setting 'Show me as' to 'Available' in the Calendar UI.
|
|
"""
|
|
|
|
OPAQUE = 'opaque'
|
|
TRANSPARENT = 'transparent'
|
|
|
|
|
|
@total_ordering
|
|
class Event(Resource):
|
|
def __init__(
|
|
self,
|
|
summary: str,
|
|
start: Union[date, datetime, BeautifulDate],
|
|
end: Union[date, datetime, BeautifulDate] = None,
|
|
*,
|
|
timezone: str = get_localzone_name(),
|
|
event_id: str = None,
|
|
description: str = None,
|
|
location: str = None,
|
|
recurrence: Union[str, List[str]] = None,
|
|
color_id: str = None,
|
|
visibility: str = Visibility.DEFAULT,
|
|
attendees: Union[Attendee, str, List[Attendee], List[str]] = None,
|
|
attachments: Union[Attachment, List[Attachment]] = None,
|
|
conference_solution: Union[ConferenceSolution, ConferenceSolutionCreateRequest] = None,
|
|
reminders: Union[Reminder, List[Reminder]] = None,
|
|
default_reminders: bool = False,
|
|
minutes_before_popup_reminder: int = None,
|
|
minutes_before_email_reminder: int = None,
|
|
guests_can_invite_others: bool = True,
|
|
guests_can_modify: bool = False,
|
|
guests_can_see_other_guests: bool = True,
|
|
transparency: str = None,
|
|
_creator: Person = None,
|
|
_organizer: Person = None,
|
|
_created: datetime = None,
|
|
_updated: datetime = None,
|
|
_recurring_event_id: str = None,
|
|
**other
|
|
):
|
|
"""
|
|
:param summary:
|
|
Title of the event.
|
|
:param start:
|
|
Starting date/datetime.
|
|
:param end:
|
|
Ending date/datetime. If 'end' is not specified, event is considered as a 1-day or 1-hour event
|
|
if 'start' is date or datetime respectively.
|
|
: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 event_id:
|
|
Opaque identifier of the event. By default, it is generated by the server. You can specify id as a
|
|
5-1024 long string of characters used in base32hex ([a-vA-V0-9]). The ID must be unique per
|
|
calendar.
|
|
:param description:
|
|
Description of the event. Can contain HTML.
|
|
:param location:
|
|
Geographic location of the event as free-form text.
|
|
:param recurrence:
|
|
RRULE/RDATE/EXRULE/EXDATE string or list of such strings. See :py:mod:`~gcsa.recurrence`
|
|
:param color_id:
|
|
Color id referring to an entry from colors endpoint.
|
|
See :py:meth:`~gcsa.google_calendar.GoogleCalendar.list_event_colors`
|
|
:param visibility:
|
|
Visibility of the event. Default is default visibility for events on the calendar.
|
|
See :py:class:`~gcsa.event.Visibility`
|
|
:param attendees:
|
|
Attendee or list of attendees. See :py:class:`~gcsa.attendee.Attendee`.
|
|
Each attendee may be given as email string or :py:class:`~gcsa.attendee.Attendee` object.
|
|
:param attachments:
|
|
Attachment or list of attachments. See :py:class:`~gcsa.attachment.Attachment`
|
|
:param conference_solution:
|
|
:py:class:`~gcsa.conference.ConferenceSolutionCreateRequest` object to create a new conference
|
|
or :py:class:`~gcsa.conference.ConferenceSolution` object for existing conference.
|
|
:param reminders:
|
|
Reminder or list of reminder objects. See :py:mod:`~gcsa.reminders`
|
|
:param default_reminders:
|
|
Whether the default reminders of the calendar apply to the event.
|
|
:param minutes_before_popup_reminder:
|
|
Minutes before popup reminder or None if reminder is not needed.
|
|
:param minutes_before_email_reminder:
|
|
Minutes before email reminder or None if reminder is not needed.
|
|
:param guests_can_invite_others:
|
|
Whether attendees other than the organizer can invite others to the event.
|
|
:param guests_can_modify:
|
|
Whether attendees other than the organizer can modify the event.
|
|
:param guests_can_see_other_guests:
|
|
Whether attendees other than the organizer can see who the event's attendees are.
|
|
:param transparency:
|
|
Whether the event blocks time on the calendar. See :py:class:`~gcsa.event.Transparency`
|
|
:param _creator:
|
|
The creator of the event. See :py:class:`~gcsa.person.Person`
|
|
:param _organizer:
|
|
The organizer of the event. See :py:class:`~gcsa.person.Person`.
|
|
If the organizer is also an attendee, this is indicated with a separate entry in attendees with
|
|
the organizer field set to True.
|
|
To change the organizer, use the move operation
|
|
see :py:meth:`~gcsa.google_calendar.GoogleCalendar.move_event`
|
|
:param _created:
|
|
Creation time of the event. Read-only.
|
|
:param _updated:
|
|
Last modification time of the event. Read-only.
|
|
:param _recurring_event_id:
|
|
For an instance of a recurring event, this is the id of the recurring event to which
|
|
this instance belongs. Read-only.
|
|
:param other:
|
|
Other fields that should be included in request json. Will be included as they are.
|
|
See more in https://developers.google.com/calendar/v3/reference/events
|
|
"""
|
|
|
|
def ensure_list(obj):
|
|
return [] if obj is None else obj if isinstance(obj, list) else [obj]
|
|
|
|
self.timezone = timezone
|
|
self.start = start
|
|
if end or start is None:
|
|
self.end = end
|
|
elif isinstance(start, datetime):
|
|
self.end = start + timedelta(hours=1)
|
|
elif isinstance(start, date):
|
|
self.end = start + timedelta(days=1)
|
|
|
|
if isinstance(self.start, datetime) and isinstance(self.end, datetime):
|
|
self.start = ensure_localisation(self.start, timezone)
|
|
self.end = ensure_localisation(self.end, timezone)
|
|
elif isinstance(self.start, datetime) or isinstance(self.end, datetime):
|
|
raise TypeError('Start and end must either both be date or both be datetime.')
|
|
|
|
def ensure_date(d):
|
|
"""Converts d to date if it is of type BeautifulDate."""
|
|
if isinstance(d, BeautifulDate):
|
|
return date(year=d.year, month=d.month, day=d.day)
|
|
else:
|
|
return d
|
|
|
|
self.start = ensure_date(self.start)
|
|
self.end = ensure_date(self.end)
|
|
|
|
self.created = _created
|
|
self.updated = _updated
|
|
|
|
attendees = [self._ensure_attendee_from_email(a) for a in ensure_list(attendees)]
|
|
reminders = ensure_list(reminders)
|
|
|
|
if len(reminders) > 5:
|
|
raise ValueError('The maximum number of override reminders is 5.')
|
|
|
|
if default_reminders and reminders:
|
|
raise ValueError('Cannot specify both default reminders and overrides at the same time.')
|
|
|
|
self.event_id = event_id
|
|
self.summary = summary
|
|
self.description = description
|
|
self.location = location
|
|
self.recurrence = ensure_list(recurrence)
|
|
self.color_id = color_id
|
|
self.visibility = visibility
|
|
self.attendees = attendees
|
|
self.attachments = ensure_list(attachments)
|
|
self.conference_solution = conference_solution
|
|
self.reminders = reminders
|
|
self.default_reminders = default_reminders
|
|
self.recurring_event_id = _recurring_event_id
|
|
self.guests_can_invite_others = guests_can_invite_others
|
|
self.guests_can_modify = guests_can_modify
|
|
self.guests_can_see_other_guests = guests_can_see_other_guests
|
|
self.transparency = transparency
|
|
self.creator = _creator
|
|
self.organizer = _organizer
|
|
|
|
self.other = other
|
|
|
|
if minutes_before_popup_reminder is not None:
|
|
self.add_popup_reminder(minutes_before_popup_reminder)
|
|
if minutes_before_email_reminder is not None:
|
|
self.add_email_reminder(minutes_before_email_reminder)
|
|
|
|
@property
|
|
def id(self):
|
|
return self.event_id
|
|
|
|
def add_attendee(
|
|
self,
|
|
attendee: Union[str, Attendee]
|
|
):
|
|
"""Adds attendee to an event. See :py:class:`~gcsa.attendee.Attendee`.
|
|
Attendee may be given as email string or :py:class:`~gcsa.attendee.Attendee` object."""
|
|
self.attendees.append(self._ensure_attendee_from_email(attendee))
|
|
|
|
def add_attendees(
|
|
self,
|
|
attendees: List[Union[str, Attendee]]
|
|
):
|
|
"""Adds multiple attendees to an event. See :py:class:`~gcsa.attendee.Attendee`.
|
|
Each attendee may be given as email string or :py:class:`~gcsa.attendee.Attendee` object."""
|
|
for a in attendees:
|
|
self.add_attendee(a)
|
|
|
|
def add_attachment(
|
|
self,
|
|
file_url: str,
|
|
title: str = None,
|
|
mime_type: str = None
|
|
):
|
|
"""Adds attachment to an event. See :py:class:`~gcsa.attachment.Attachment`"""
|
|
self.attachments.append(Attachment(file_url=file_url, title=title, mime_type=mime_type))
|
|
|
|
def add_email_reminder(
|
|
self,
|
|
minutes_before_start: int = None,
|
|
days_before: int = None,
|
|
at: time = None
|
|
):
|
|
"""Adds email reminder to an event. See :py:class:`~gcsa.reminders.EmailReminder`"""
|
|
self.add_reminder(EmailReminder(minutes_before_start, days_before, at))
|
|
|
|
def add_popup_reminder(
|
|
self,
|
|
minutes_before_start: int = None,
|
|
days_before: int = None,
|
|
at: time = None
|
|
):
|
|
"""Adds popup reminder to an event. See :py:class:`~gcsa.reminders.PopupReminder`"""
|
|
self.add_reminder(PopupReminder(minutes_before_start, days_before, at))
|
|
|
|
def add_reminder(
|
|
self,
|
|
reminder: Reminder
|
|
):
|
|
"""Adds reminder to an event. See :py:mod:`~gcsa.reminders`"""
|
|
if len(self.reminders) > 4:
|
|
raise ValueError('The maximum number of override reminders is 5.')
|
|
self.reminders.append(reminder)
|
|
|
|
@staticmethod
|
|
def _ensure_attendee_from_email(
|
|
attendee_or_email: Union[str, Attendee]
|
|
):
|
|
"""If attendee_or_email is email string, returns created :py:class:`~gcsa.attendee.Attendee`
|
|
object with the given email."""
|
|
if isinstance(attendee_or_email, str):
|
|
return Attendee(email=attendee_or_email)
|
|
else:
|
|
return attendee_or_email
|
|
|
|
@property
|
|
def is_recurring_instance(self):
|
|
return self.recurring_event_id is not None
|
|
|
|
def __str__(self):
|
|
return '{} - {}'.format(self.start, self.summary)
|
|
|
|
def __repr__(self):
|
|
return '<Event {}>'.format(self.__str__())
|
|
|
|
def __lt__(self, other):
|
|
def ensure_datetime(d, timezone):
|
|
if type(d) is date:
|
|
return ensure_localisation(datetime(year=d.year, month=d.month, day=d.day), timezone)
|
|
else:
|
|
return d
|
|
|
|
start = ensure_datetime(self.start, self.timezone)
|
|
end = ensure_datetime(self.end, self.timezone)
|
|
|
|
other_start = ensure_datetime(other.start, other.timezone)
|
|
other_end = ensure_datetime(other.end, other.timezone)
|
|
|
|
return (start, end) < (other_start, other_end)
|
|
|
|
def __eq__(self, other):
|
|
return (
|
|
isinstance(other, Event)
|
|
and self.start == other.start
|
|
and self.end == other.end
|
|
and self.event_id == other.event_id
|
|
and self.summary == other.summary
|
|
and self.description == other.description
|
|
and self.location == other.location
|
|
and self.recurrence == other.recurrence
|
|
and self.color_id == other.color_id
|
|
and self.visibility == other.visibility
|
|
and self.attendees == other.attendees
|
|
and self.attachments == other.attachments
|
|
and self.reminders == other.reminders
|
|
and self.default_reminders == other.default_reminders
|
|
and self.created == other.created
|
|
and self.updated == other.updated
|
|
and self.recurring_event_id == other.recurring_event_id
|
|
and self.guests_can_invite_others == other.guests_can_invite_others
|
|
and self.guests_can_modify == other.guests_can_modify
|
|
and self.guests_can_see_other_guests == other.guests_can_see_other_guests
|
|
and self.other == other.other
|
|
)
|
|
|