#!/usr/bin/env python3
# File: agenda.py
# Location: https://bgstack15.ddns.net/cgit/agenda
# Author: bgstack15
# Startdate: 2023-05-16-3 14:09
# Title: Generate daily agenda html message
# Purpose: remind myself of what is happening today
# History:
# Usage: See function summarize()
# Reference:
# 1. basic_usage_examples.py from caldav
# 2. https://stackoverflow.com/questions/29643352/converting-hex-to-rgb-value-in-python
# 3. https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color
# Improve:
# Dependencies:
# python3-caldav
import sys, caldav
from datetime import date, datetime, timedelta
def get_calendar_color(calendar):
"""
Author: bgstack15
Purpose: return the hexadecimal color (and alpha channel if present) for the given caldav calendar.
"""
color = prop = None
try:
colorprop = caldav.elements.ical.CalendarColor()
prop = calendar.get_properties(props=[colorprop])
if prop:
for j in prop:
# only the one
color = prop[j]
except Exception as e:
print(f"Debug: no color info available for calendar {calendar}, e: {e}")
return color
def print_calendars_demo(calendars):
"""
This example prints the name and URL for every calendar on the list
"""
if calendars:
## Some calendar servers will include all calendars you have
## access to in this list, and not only the calendars owned by
## this principal.
print("your principal has %i calendars:" % len(calendars))
for c in calendars:
color = get_calendar_color(c)
print("Name: %-36s Color: %-9s URL: %s" % (c.name, color, c.url))
else:
print("your principal has no calendars")
def show_event(event):
response = ""
all_dtstart_dt = []
all_dtstart_str_dt = []
#print(event.data)
#for i in event.icalendar_component:
# print(f"{i} IS {event.icalendar_component[i]}")
dtstart = event.icalendar_component["DTSTART"]
dtstart_dt = dtstart and dtstart.dt
if str(dtstart_dt) not in all_dtstart_str_dt:
all_dtstart_dt.append(dtstart_dt)
all_dtstart_str_dt.append(str(dtstart_dt))
if all_dtstart_dt:
for i in all_dtstart_dt:
summary = event.icalendar_component["SUMMARY"].strip()
thishour = int(i.strftime("%I"))
thistime = str(thishour) + i.strftime(":%M%P")
if type(event.icalendar_component["DTEND"].dt) == date:
thistime = "All day"
response += f"{thistime}: {summary}
\n"
return response
# From reference 2
def hex_to_rgb(value):
value = value.lstrip('#').rstrip(";")
lv = len(value)
return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))
def rgb_to_hex(rgb):
return '#%02x%02x%02x' % rgb
# bgstack15
def get_faded_color(hexcolor):
""" Given hexcolor as string of '#ffccaa', return a faded color """
outcolor = ""
try:
r, g, b = hex_to_rgb(hexcolor)
except:
try:
r, g, b, a = hex_to_rgb(hexcolor)
except:
print(f"Warning! Cannot understand color {hexcolor} for getting a faded value.")
return hexcolor
# so now we have r, g, b. We do not know yet how to use alpha.
if len(hexcolor) == 4:
# that is, if hexcolor is "#fff" or similar
r = r * 16
g = g * 16
b = b * 16
r1 = int((255 + r)/2)
g1 = int((255 + g)/2)
b1 = int((255 + b)/2)
outcolor = rgb_to_hex((r1,g1,b1))
return outcolor
# Adapted from reference 3
def get_text_color_based_on_background_color(bgColor, lightColor, darkColor):
color = bgColor.lstrip("#").rstrip(";")
r, g, b = hex_to_rgb(color)
uicolors = [r/255, g/255, b/255]
adjusted = []
for col in uicolors:
col2 = col
if col <= 0.03928:
col2 = col/12.92
col2 = pow((col2 + 0.055)/1.055,2.4)
adjusted.append(col2)
L = (0.2126 * adjusted[0] + 0.7152 * adjusted[1] + (0.072 * adjusted[2]))
return darkColor if L > 0.179 else lightColor
#function pickTextColorBasedOnBgColorAdvanced(bgColor, lightColor, darkColor) {
# var color = (bgColor.charAt(0) === '#') ? bgColor.substring(1, 7) : bgColor;
# var r = parseInt(color.substring(0, 2), 16); // hexToR
# var g = parseInt(color.substring(2, 4), 16); // hexToG
# var b = parseInt(color.substring(4, 6), 16); // hexToB
# var uicolors = [r / 255, g / 255, b / 255];
# var c = uicolors.map((col) => {
# if (col <= 0.03928) {
# return col / 12.92;
# }
# return Math.pow((col + 0.055) / 1.055, 2.4);
# });
# var L = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2]);
# return (L > 0.179) ? darkColor : lightColor;
#}
def event_key(i):
return i.icalendar_component["DTSTART"].dt
def summarize_calendar(calendar, thisdate = None, count = 0):
"""
Examine calendar for given thisdate (of type datetime.date)
"""
response = ""
#d = date.today()+timedelta(days=-1)
if type(thisdate) == datetime:
thisdate = thisdate.date()
if type(thisdate) != date:
thisdate = datetime.today()
# so now, thisdate should be of type datetime.date
d = thisdate
d2 = d + timedelta(days=1)
year, month, day = d2.year, d2.month, d2.day
events_fetched = calendar.search(
start=d,
end=datetime(year,month,day),
event=True,
expand=True,
)
x = 0
events_wholeday = [i for i in events_fetched if type(i.icalendar_component["DTSTART"].dt) == date]
events_regular = [i for i in events_fetched if type(i.icalendar_component["DTSTART"].dt) != date]
events_sorted = sorted(events_regular, key=event_key)
for i in events_wholeday + events_sorted:
x = x + 1
if 1 == x:
if 1 == count:
datestring = thisdate.strftime("%B %d")
response += f"