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.
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.
@ -15,7 +17,7 @@ Parameters:
Requires these pip packages:
* google-api-python-client >= 1.8.0
* google-auth-httplib2
* google-auth-httplib2
* google-auth-oauthlib
"""
@ -27,10 +29,12 @@ from dateutil.parser import parse as dtparse
import core.module
import core.widget
import core.decorators
import util.format
import datetime
import os.path
import locale
import time
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
@ -38,11 +42,15 @@ from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# Minutes
update_every = 15
class Module(core.module.Module):
@core.decorators.every(minutes=15)
@core.decorators.every(minutes=update_every)
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.__date_format = self.parameter("date_format", "%d.%m.%y")
self.__credentials_path = os.path.expanduser(
@ -60,32 +68,44 @@ class Module(core.module.Module):
except Exception:
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"]
"""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
# 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:
# 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)
# Call the Calendar API
@ -125,33 +145,27 @@ class Module(core.module.Module):
}
)
sorted_list = sorted(event_list, key=lambda t: t["date"])
next_event = sorted_list[0]
for gevent in sorted_list:
if gevent["date"] >= datetime.datetime.now(datetime.timezone.utc):
if gevent["date"].date() == datetime.datetime.utcnow().date():
return str(
"%s %s"
% (
gevent["date"]
.astimezone()
.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."
if next_event["date"] >= datetime.datetime.now(datetime.timezone.utc):
if next_event["date"].date() == datetime.datetime.utcnow().date():
dt = next_event["date"].astimezone()\
.strftime(f"{self.__time_format}")
else:
dt = next_event["date"].astimezone()\
.strftime(f"{self.__date_format} {self.__time_format}")
return (dt, next_event["summary"])
return (None, "No upcoming events.")
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