mirror of
https://github.com/b4tman/sync_ics2gcal
synced 2025-01-21 07:28:24 +00:00
more types in gcal
This commit is contained in:
parent
260f168077
commit
2f3a87f25f
@ -1,6 +1,17 @@
|
|||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import List, Dict, Any, Callable, Tuple, Optional, Union, TypedDict, TypeAlias
|
from typing import (
|
||||||
|
List,
|
||||||
|
Dict,
|
||||||
|
Any,
|
||||||
|
Callable,
|
||||||
|
Tuple,
|
||||||
|
Optional,
|
||||||
|
Union,
|
||||||
|
TypedDict,
|
||||||
|
TypeAlias,
|
||||||
|
Literal,
|
||||||
|
)
|
||||||
|
|
||||||
import google.auth
|
import google.auth
|
||||||
from google.oauth2 import service_account
|
from google.oauth2 import service_account
|
||||||
@ -20,7 +31,55 @@ class EventDateTime(TypedDict, total=False):
|
|||||||
|
|
||||||
EventDateOrDateTime: TypeAlias = Union[EventDate, EventDateTime]
|
EventDateOrDateTime: TypeAlias = Union[EventDate, EventDateTime]
|
||||||
|
|
||||||
EventData: TypeAlias = Dict[str, Union[str, EventDateOrDateTime, None]]
|
|
||||||
|
class ACLScope(TypedDict, total=False):
|
||||||
|
type: str
|
||||||
|
value: str
|
||||||
|
|
||||||
|
|
||||||
|
class ACLRule(TypedDict, total=False):
|
||||||
|
scope: ACLScope
|
||||||
|
role: str
|
||||||
|
|
||||||
|
|
||||||
|
class CalendarData(TypedDict, total=False):
|
||||||
|
id: str
|
||||||
|
summary: str
|
||||||
|
description: str
|
||||||
|
timeZone: str
|
||||||
|
|
||||||
|
|
||||||
|
class EventData(TypedDict, total=False):
|
||||||
|
id: str
|
||||||
|
summary: str
|
||||||
|
description: str
|
||||||
|
start: EventDateOrDateTime
|
||||||
|
end: EventDateOrDateTime
|
||||||
|
iCalUID: str
|
||||||
|
location: str
|
||||||
|
status: str
|
||||||
|
created: str
|
||||||
|
updated: str
|
||||||
|
sequence: int
|
||||||
|
transparency: str
|
||||||
|
visibility: str
|
||||||
|
|
||||||
|
|
||||||
|
EventDataKey = Union[
|
||||||
|
Literal["id"],
|
||||||
|
Literal["summary"],
|
||||||
|
Literal["description"],
|
||||||
|
Literal["start"],
|
||||||
|
Literal["end"],
|
||||||
|
Literal["iCalUID"],
|
||||||
|
Literal["location"],
|
||||||
|
Literal["status"],
|
||||||
|
Literal["created"],
|
||||||
|
Literal["updated"],
|
||||||
|
Literal["sequence"],
|
||||||
|
Literal["transparency"],
|
||||||
|
Literal["visibility"],
|
||||||
|
]
|
||||||
EventList: TypeAlias = List[EventData]
|
EventList: TypeAlias = List[EventData]
|
||||||
EventTuple: TypeAlias = Tuple[EventData, EventData]
|
EventTuple: TypeAlias = Tuple[EventData, EventData]
|
||||||
|
|
||||||
@ -90,7 +149,7 @@ def select_event_key(event: EventData) -> Optional[str]:
|
|||||||
key name or None if no key found
|
key name or None if no key found
|
||||||
"""
|
"""
|
||||||
|
|
||||||
key = None
|
key: Optional[str] = None
|
||||||
if "iCalUID" in event:
|
if "iCalUID" in event:
|
||||||
key = "iCalUID"
|
key = "iCalUID"
|
||||||
elif "id" in event:
|
elif "id" in event:
|
||||||
@ -118,9 +177,10 @@ class GoogleCalendar:
|
|||||||
callback function
|
callback function
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def callback(request_id: str, response: Any, exception: Exception):
|
def callback(request_id: str, response: Any, exception: Optional[Exception]):
|
||||||
event: EventData = events_by_req[int(request_id)]
|
event: EventData = events_by_req[int(request_id)]
|
||||||
key: str = str(select_event_key(event))
|
event_key: Optional[str] = select_event_key(event)
|
||||||
|
key: str = event_key if event_key is not None else ""
|
||||||
|
|
||||||
if exception is not None:
|
if exception is not None:
|
||||||
self.logger.error(
|
self.logger.error(
|
||||||
@ -131,7 +191,7 @@ class GoogleCalendar:
|
|||||||
str(exception),
|
str(exception),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
resp_key: str = select_event_key(response)
|
resp_key: Optional[str] = select_event_key(response)
|
||||||
if resp_key is not None:
|
if resp_key is not None:
|
||||||
event = response
|
event = response
|
||||||
key = resp_key
|
key = resp_key
|
||||||
@ -183,7 +243,9 @@ class GoogleCalendar:
|
|||||||
exists: List[EventTuple] = []
|
exists: List[EventTuple] = []
|
||||||
not_found: EventList = []
|
not_found: EventList = []
|
||||||
|
|
||||||
def list_callback(request_id: str, response: Any, exception: Exception):
|
def list_callback(
|
||||||
|
request_id: str, response: Any, exception: Optional[Exception]
|
||||||
|
):
|
||||||
found: bool = False
|
found: bool = False
|
||||||
cur_event: EventData = events_by_req[int(request_id)]
|
cur_event: EventData = events_by_req[int(request_id)]
|
||||||
if exception is None:
|
if exception is None:
|
||||||
@ -333,7 +395,7 @@ class GoogleCalendar:
|
|||||||
calendar Resource
|
calendar Resource
|
||||||
"""
|
"""
|
||||||
|
|
||||||
calendar: Dict[str, str] = {"summary": summary}
|
calendar: CalendarData = CalendarData(summary=summary)
|
||||||
if time_zone is not None:
|
if time_zone is not None:
|
||||||
calendar["timeZone"] = time_zone
|
calendar["timeZone"] = time_zone
|
||||||
|
|
||||||
@ -349,12 +411,7 @@ class GoogleCalendar:
|
|||||||
def make_public(self):
|
def make_public(self):
|
||||||
"""make calendar public"""
|
"""make calendar public"""
|
||||||
|
|
||||||
rule_public: Dict[str, Union[str, Dict[str, str]]] = {
|
rule_public: ACLRule = ACLRule(scope=ACLScope(type="default"), role="reader")
|
||||||
"scope": {
|
|
||||||
"type": "default",
|
|
||||||
},
|
|
||||||
"role": "reader",
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
self.service.acl()
|
self.service.acl()
|
||||||
.insert(calendarId=self.calendar_id, body=rule_public)
|
.insert(calendarId=self.calendar_id, body=rule_public)
|
||||||
@ -368,13 +425,9 @@ class GoogleCalendar:
|
|||||||
email -- email to add
|
email -- email to add
|
||||||
"""
|
"""
|
||||||
|
|
||||||
rule_owner: Dict[str, Union[str, Dict[str, str]]] = {
|
rule_owner: ACLRule = ACLRule(
|
||||||
"scope": {
|
scope=ACLScope(type="user", value=email), role="owner"
|
||||||
"type": "user",
|
)
|
||||||
"value": email,
|
|
||||||
},
|
|
||||||
"role": "owner",
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
self.service.acl()
|
self.service.acl()
|
||||||
.insert(calendarId=self.calendar_id, body=rule_owner)
|
.insert(calendarId=self.calendar_id, body=rule_owner)
|
||||||
|
@ -5,7 +5,14 @@ from typing import Union, Dict, Callable, Optional, Mapping, TypeAlias, TypedDic
|
|||||||
from icalendar import Calendar, Event
|
from icalendar import Calendar, Event
|
||||||
from pytz import utc
|
from pytz import utc
|
||||||
|
|
||||||
from .gcal import EventData, EventList, EventDateOrDateTime, EventDateTime, EventDate
|
from .gcal import (
|
||||||
|
EventData,
|
||||||
|
EventList,
|
||||||
|
EventDateOrDateTime,
|
||||||
|
EventDateTime,
|
||||||
|
EventDate,
|
||||||
|
EventDataKey,
|
||||||
|
)
|
||||||
|
|
||||||
DateDateTime: TypeAlias = Union[datetime.date, datetime.datetime]
|
DateDateTime: TypeAlias = Union[datetime.date, datetime.datetime]
|
||||||
|
|
||||||
@ -121,7 +128,7 @@ class EventConverter(Event):
|
|||||||
def _put_to_gcal(
|
def _put_to_gcal(
|
||||||
self,
|
self,
|
||||||
gcal_event: EventData,
|
gcal_event: EventData,
|
||||||
prop: str,
|
prop: EventDataKey,
|
||||||
func: Callable[[str], str],
|
func: Callable[[str], str],
|
||||||
ics_prop: Optional[str] = None,
|
ics_prop: Optional[str] = None,
|
||||||
):
|
):
|
||||||
@ -139,18 +146,18 @@ class EventConverter(Event):
|
|||||||
if ics_prop in self:
|
if ics_prop in self:
|
||||||
gcal_event[prop] = func(ics_prop)
|
gcal_event[prop] = func(ics_prop)
|
||||||
|
|
||||||
def to_gcal(self) -> EventData:
|
def convert(self) -> EventData:
|
||||||
"""Convert
|
"""Convert
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict - google calendar#event resource
|
dict - google calendar#event resource
|
||||||
"""
|
"""
|
||||||
|
|
||||||
event: EventData = {
|
event: EventData = EventData(
|
||||||
"iCalUID": self._str_prop("UID"),
|
iCalUID=self._str_prop("UID"),
|
||||||
"start": self._gcal_start(),
|
start=self._gcal_start(),
|
||||||
"end": self._gcal_end(),
|
end=self._gcal_end(),
|
||||||
}
|
)
|
||||||
|
|
||||||
self._put_to_gcal(event, "summary", self._str_prop)
|
self._put_to_gcal(event, "summary", self._str_prop)
|
||||||
self._put_to_gcal(event, "description", self._str_prop)
|
self._put_to_gcal(event, "description", self._str_prop)
|
||||||
@ -189,6 +196,6 @@ class CalendarConverter:
|
|||||||
ics_events = calendar.walk(name="VEVENT")
|
ics_events = calendar.walk(name="VEVENT")
|
||||||
self.logger.info("%d events read", len(ics_events))
|
self.logger.info("%d events read", len(ics_events))
|
||||||
|
|
||||||
result = list(map(lambda event: EventConverter(event).to_gcal(), ics_events))
|
result = list(map(lambda event: EventConverter(event).convert(), ics_events))
|
||||||
self.logger.info("%d events converted", len(result))
|
self.logger.info("%d events converted", len(result))
|
||||||
return result
|
return result
|
||||||
|
Loading…
x
Reference in New Issue
Block a user