Skip to content

Commit

Permalink
Use CalendarEntity instead of CalendarEventDevice
Browse files Browse the repository at this point in the history
Also break schema's into separate schema.py
  • Loading branch information
RogerSelwyn committed May 2, 2022
1 parent 3962a23 commit 712daf5
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 269 deletions.
44 changes: 28 additions & 16 deletions custom_components/o365/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from functools import partial

from aiohttp import web_response
from homeassistant.components import configurator
from homeassistant.components.http import HomeAssistantView
from homeassistant.core import callback
from homeassistant.helpers import discovery
Expand Down Expand Up @@ -36,9 +37,8 @@
DEFAULT_CACHE_PATH,
DEFAULT_NAME,
DOMAIN,
PRIMARY_DOMAIN_SCHEMA,
SECONDARY_DOMAIN_SCHEMA,
)
from .schema import LEGACY_SCHEMA, MULTI_ACCOUNT_SCHEMA
from .utils import (
build_config_file_path,
build_minimum_permissions,
Expand All @@ -55,10 +55,10 @@ async def async_setup(hass, config):
# validate_permissions(hass)
conf = config.get(DOMAIN, {})
if CONF_ACCOUNTS not in conf:
accounts = [PRIMARY_DOMAIN_SCHEMA(conf)]
accounts = [LEGACY_SCHEMA(conf)]
conf_type = CONST_CONFIG_TYPE_DICT
else:
accounts = SECONDARY_DOMAIN_SCHEMA(conf)[CONF_ACCOUNTS]
accounts = MULTI_ACCOUNT_SCHEMA(conf)[CONF_ACCOUNTS]
conf_type = CONST_CONFIG_TYPE_LIST

for account in accounts:
Expand Down Expand Up @@ -143,7 +143,7 @@ def _request_configuration(hass, url, callback_view, account_name):
if DOMAIN not in hass.data:
hass.data[DOMAIN] = {}

request_content = _create_request_content(url, callback_view, account_name)
request_content = _create_request_content(hass, url, callback_view, account_name)
hass.data[DOMAIN][account_name] = request_content


Expand All @@ -152,16 +152,19 @@ def _request_configuration_alt(hass, url, callback_view, account_name):
if DOMAIN not in hass.data:
hass.data[DOMAIN] = {}

request_content = _create_request_content_alt(url, callback_view, account_name)
request_content = _create_request_content_alt(
hass, url, callback_view, account_name
)
hass.data[DOMAIN][account_name] = request_content


def _create_request_content(url, callback_view, account_name):
configurator = callback_view.configurator
def _create_request_content(hass, url, callback_view, account_name):
o365configurator = callback_view.configurator

display_name = f" - {account_name}" if account_name != CONST_PRIMARY else ""
view_name = f"{DEFAULT_NAME}{display_name}"
return configurator.async_request_config(
return o365configurator.async_request_config(
hass,
view_name,
lambda _: None,
link_name=CONFIGURATOR_LINK_NAME,
Expand All @@ -171,11 +174,12 @@ def _create_request_content(url, callback_view, account_name):
)


def _create_request_content_alt(url, callback_view, account_name):
configurator = callback_view.configurator
def _create_request_content_alt(hass, url, callback_view, account_name):
o365configurator = callback_view.configurator
display_name = f" - {account_name}" if account_name != CONST_PRIMARY else ""
view_name = f"{DEFAULT_NAME}{display_name} - Alternative configuration"
return configurator.async_request_config(
return o365configurator.async_request_config(
hass,
view_name,
callback_view.alt_callback,
link_name=CONFIGURATOR_LINK_NAME,
Expand All @@ -193,7 +197,7 @@ def _request_authorization(hass, conf, account, account_name, conf_type):
url, state = account.con.get_authorization_url(
requested_scopes=scope, redirect_uri=callback_url
)
_LOGGER.info(
_LOGGER.warning(
"No token, or token doesn't have all required permissions; requesting authorization"
)
callback_view = O365AuthCallbackView(
Expand Down Expand Up @@ -230,7 +234,7 @@ def __init__(
self._callback = callback_url
self._hass = hass
self._account_name = account_name
self.configurator = self._hass.components.configurator
self.configurator = configurator
self._conf_type = conf_type

@callback
Expand All @@ -257,8 +261,9 @@ async def get(self, request):
do_setup(
self._hass, self._config, self._account, self._account_name, self._conf_type
)
self.configurator.async_request_done(account_data)
self.configurator.async_request_done(self._hass, account_data)

self._log_authenticated()
return web_response.Response(
headers={"content-type": "text/html"},
text="<script>window.close()</script>Success! This window can be closed",
Expand All @@ -273,13 +278,20 @@ def alt_callback(self, data):
)
if not result:
self.configurator.notify_errors(
self._hass,
self._hass.data[DOMAIN][self._account_name],
"Error while authenticating, please see logs for more info.",
)
return

account_data = self._hass.data[DOMAIN][self._account_name]
do_setup(
self._hass, self._config, self._account, self._account_name, self._conf_type
)
self.configurator.async_request_done(account_data)
self.configurator.async_request_done(self._hass, account_data)

self._log_authenticated()
return

def _log_authenticated(self):
_LOGGER.info("Succesfully authenticated")
82 changes: 42 additions & 40 deletions custom_components/o365/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
from datetime import datetime, timedelta
from operator import attrgetter, itemgetter

from homeassistant.components.calendar import CalendarEventDevice, is_offset_reached

try:
from homeassistant.components.calendar import calculate_offset
except ImportError:
from homeassistant.components.calendar import extract_offset

from homeassistant.components.calendar import (
CalendarEntity,
CalendarEvent,
extract_offset,
is_offset_reached,
)
from homeassistant.const import CONF_NAME
from homeassistant.helpers.entity import generate_entity_id
from homeassistant.util import dt
Expand All @@ -21,10 +20,6 @@
ATTR_CALENDAR_ID,
ATTR_ENTITY_ID,
CALENDAR_ENTITY_ID_FORMAT,
CALENDAR_SERVICE_CREATE_SCHEMA,
CALENDAR_SERVICE_MODIFY_SCHEMA,
CALENDAR_SERVICE_REMOVE_SCHEMA,
CALENDAR_SERVICE_RESPOND_SCHEMA,
CONF_ACCOUNT,
CONF_ACCOUNT_NAME,
CONF_CAL_IDS,
Expand All @@ -44,6 +39,12 @@
PERM_CALENDARS_READWRITE,
PERM_MINIMUM_CALENDAR_WRITE,
)
from .schema import (
CALENDAR_SERVICE_CREATE_SCHEMA,
CALENDAR_SERVICE_MODIFY_SCHEMA,
CALENDAR_SERVICE_REMOVE_SCHEMA,
CALENDAR_SERVICE_RESPOND_SCHEMA,
)
from .utils import (
add_call_data_to_event,
build_config_file_path,
Expand Down Expand Up @@ -142,7 +143,7 @@ def _setup_register_services(hass, conf):
)


class O365CalendarEventDevice(CalendarEventDevice):
class O365CalendarEventDevice(CalendarEntity):
"""O365 Calendar Event Processing."""

def __init__(self, account, calendar_id, entity, entity_id):
Expand All @@ -163,6 +164,7 @@ def _init_data(self, account, calendar_id, entity):
# _LOGGER.debug("Initialising calendar: %s", calendar_id)
return O365CalendarData(
account,
self.entity_id,
calendar_id,
search,
max_results,
Expand All @@ -173,7 +175,7 @@ def extra_state_attributes(self):
"""Device state property."""
if self._event:
return {
"all_day": self._event.get("all_day", False)
"all_day": self._event.all_day
if self.data.event is not None
else False,
"offset_reached": self._offset_reached,
Expand Down Expand Up @@ -203,15 +205,9 @@ async def async_update(self):
await self.data.async_update(self.hass)
event = deepcopy(self.data.event)
if event:
try:
event = calculate_offset(event, DEFAULT_OFFSET)
self._offset_reached = is_offset_reached(event)
except NameError:
event["summary"], offset = extract_offset(
event.get("summary", ""), DEFAULT_OFFSET
)
start = O365CalendarData.to_datetime(event["start"])
self._offset_reached = is_offset_reached(start, offset)
event.summary, offset = extract_offset(event.summary, DEFAULT_OFFSET)
start = O365CalendarData.to_datetime(event.start)
self._offset_reached = is_offset_reached(start, offset)
results = await self.data.async_o365_get_events(
self.hass,
dt.utcnow() + timedelta(hours=self._start_offset),
Expand All @@ -236,6 +232,7 @@ class O365CalendarData:
def __init__(
self,
account,
entity_id,
calendar_id,
search=None,
limit=999,
Expand All @@ -247,6 +244,7 @@ def __init__(
self.calendar = schedule.get_calendar(calendar_id=calendar_id)
self._search = search
self.event = None
self._entity_id = entity_id

async def async_o365_get_events(self, hass, start_date, end_date):
"""Get the events."""
Expand Down Expand Up @@ -276,11 +274,19 @@ async def async_get_events(self, hass, start_date, end_date):
vevent_list = list(results)
vevent_list.sort(key=attrgetter("start"))
event_list = []
for event in vevent_list:
data = format_event_data(event, self.calendar.calendar_id)
data["start"] = self.get_hass_date(data["start"], event.is_all_day)
data["end"] = self.get_hass_date(data["end"], event.is_all_day)
event_list.append(data)
for vevent in vevent_list:
# data = format_event_data(event, self.calendar.calendar_id)
# data["start"] = self.get_hass_date(data["start"], event.is_all_day)
# data["end"] = self.get_hass_date(data["end"], event.is_all_day)
# event_list.append(data)
event = CalendarEvent(
self.get_hass_date(vevent.start, vevent.is_all_day),
self.get_hass_date(self.get_end_date(vevent), vevent.is_all_day),
vevent.subject,
clean_html(vevent.body),
vevent.location["displayName"],
)
event_list.append(event)

return event_list

Expand All @@ -304,19 +310,18 @@ async def async_update(self, hass):
_LOGGER.debug(
"No matching event found in the %d results for %s",
len(results),
self.calendar.name,
self._entity_id,
)
self.event = None
return

self.event = {
"summary": vevent.subject,
"start": self.get_hass_date(vevent.start, vevent.is_all_day),
"end": self.get_hass_date(self.get_end_date(vevent), vevent.is_all_day),
"location": vevent.location,
"description": clean_html(vevent.body),
"all_day": vevent.is_all_day,
}
self.event = CalendarEvent(
self.get_hass_date(vevent.start, vevent.is_all_day),
self.get_hass_date(self.get_end_date(vevent), vevent.is_all_day),
vevent.subject,
clean_html(vevent.body),
vevent.location["displayName"],
)

def _get_root_event(self, results):
started_event = None
Expand Down Expand Up @@ -370,10 +375,7 @@ def is_finished(vevent):
@staticmethod
def get_hass_date(obj, is_all_day):
"""Get the date."""
if isinstance(obj, datetime) and not is_all_day:
return {"dateTime": obj.isoformat()}

return {"date": obj.date().isoformat()}
return obj if isinstance(obj, datetime) and not is_all_day else obj.date()

@staticmethod
def to_datetime(obj):
Expand Down
Loading

0 comments on commit 712daf5

Please sign in to comment.