Merge pull request #947 from arivarton/gcalendar_fixes

Added a max_chars parameter to be able to control the widget width.
This commit is contained in:
tobi-wan-kenobi 2023-01-29 17:04:24 +01:00 committed by GitHub
commit 098f03ac52
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -3,7 +3,9 @@
Events that are set as 'all-day' will not be shown. Events that are set as 'all-day' will not be shown.
Requires credentials.json from a google api application where the google calendar api is installed. Requires credentials.json from a google api application where the google calendar api is installed.
On first time run the browser will open and google will ask for permission for this app to access the google calendar and then save a .gcalendar_token.json file to the credentials_path directory which stores this permission. On first time run the browser will open and google will ask for permission for this app to access
the google calendar and then save a .gcalendar_token.json file to the credentials_path directory
which stores this permission.
A refresh is done every 15 minutes. A refresh is done every 15 minutes.
@ -27,10 +29,12 @@ from dateutil.parser import parse as dtparse
import core.module import core.module
import core.widget import core.widget
import core.decorators import core.decorators
import util.format
import datetime import datetime
import os.path import os.path
import locale import locale
import time
from google.auth.transport.requests import Request from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials from google.oauth2.credentials import Credentials
@ -38,11 +42,15 @@ from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build from googleapiclient.discovery import build
from googleapiclient.errors import HttpError from googleapiclient.errors import HttpError
# Minutes
update_every = 15
class Module(core.module.Module): class Module(core.module.Module):
@core.decorators.every(minutes=15) @core.decorators.every(minutes=update_every)
def __init__(self, config, theme): def __init__(self, config, theme):
super().__init__(config, theme, core.widget.Widget(self.first_event)) super().__init__(config, theme, [core.widget.Widget(self.__datetime), core.widget.Widget(self.__summary)])
self.__error = False
self.__time_format = self.parameter("time_format", "%H:%M") self.__time_format = self.parameter("time_format", "%H:%M")
self.__date_format = self.parameter("date_format", "%d.%m.%y") self.__date_format = self.parameter("date_format", "%d.%m.%y")
self.__credentials_path = os.path.expanduser( self.__credentials_path = os.path.expanduser(
@ -60,32 +68,44 @@ class Module(core.module.Module):
except Exception: except Exception:
locale.setlocale(locale.LC_TIME, ("en_US", "UTF-8")) locale.setlocale(locale.LC_TIME, ("en_US", "UTF-8"))
def first_event(self, widget): self.__last_update = time.time()
self.__gcalendar_date, self.__gcalendar_summary = self.__fetch_from_calendar()
def hidden(self):
return self.__error
def __datetime(self, _):
return self.__gcalendar_date
@core.decorators.scrollable
def __summary(self, _):
return self.__gcalendar_summary
def __fetch_from_calendar(self):
SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"] SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"]
"""Shows basic usage of the Google Calendar API.
Prints the start and name of the next 10 events on the user's calendar.
"""
creds = None creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists(self.__token):
creds = Credentials.from_authorized_user_file(self.__token, SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
self.__credentials, SCOPES
)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open(self.__token, "w") as token:
token.write(creds.to_json())
try: try:
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists(self.__token):
creds = Credentials.from_authorized_user_file(self.__token, SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
self.__credentials, SCOPES
)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open(self.__token, "w") as token:
token.write(creds.to_json())
service = build("calendar", "v3", credentials=creds) service = build("calendar", "v3", credentials=creds)
# Call the Calendar API # Call the Calendar API
@ -125,33 +145,27 @@ class Module(core.module.Module):
} }
) )
sorted_list = sorted(event_list, key=lambda t: t["date"]) sorted_list = sorted(event_list, key=lambda t: t["date"])
next_event = sorted_list[0]
for gevent in sorted_list: if next_event["date"] >= datetime.datetime.now(datetime.timezone.utc):
if gevent["date"] >= datetime.datetime.now(datetime.timezone.utc): if next_event["date"].date() == datetime.datetime.utcnow().date():
if gevent["date"].date() == datetime.datetime.utcnow().date(): dt = next_event["date"].astimezone()\
return str( .strftime(f"{self.__time_format}")
"%s %s" else:
% ( dt = next_event["date"].astimezone()\
gevent["date"] .strftime(f"{self.__date_format} {self.__time_format}")
.astimezone() return (dt, next_event["summary"])
.strftime(f"{self.__time_format}"),
gevent["summary"],
)
)
else:
return str(
"%s %s"
% (
gevent["date"]
.astimezone()
.strftime(f"{self.__date_format} {self.__time_format}"),
gevent["summary"],
)
)
return "No upcoming events found."
return (None, "No upcoming events.")
except: except:
return None self.__error = True
def update(self):
# Since scrolling runs the update command and therefore negates the
# every decorator, this need to be stopped
# to not break the API rules of google.
if self.__last_update+(update_every*60) < time.time():
self.__last_update = time.time()
self.__gcalendar_date, self.__gcalendar_summary = self.__fetch_from_calendar()
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4