Files
webcal-dashboard/server/app/views.py
Anthony Correa e96ef0e44e Improve Dockerfile, compose configuration, Kindle script, and UI styles for better maintainability and functionality
This commit introduces several enhancements across multiple files to improve maintainability, functionality, and overall code quality. Key updates are as follows:
	1.	.gitignore
	•	Added exclusion for kindle/data/* to prevent Kindle-specific data from being tracked.
	2.	Dockerfile
	•	Added installation of OpenMoji font:
	•	Downloads and unzips OpenMoji font to /usr/share/fonts/openmoji.
	•	Updates font cache with fc-cache.
	•	Verifies installation with fc-list | grep "OpenMoji".
	•	Improves container setup for rendering Kindle dashboards with proper font support.
	3.	compose.yml
	•	Port mapping now uses an environment variable ${HOST_PORT} instead of hardcoding 56733:80.
	•	Enhances flexibility for port management.
	4.	kindle/ascwebdash.py
	•	Significant refactoring and cleanup:
	•	Removed unused signal handling and daemonization logic.
	•	Simplified logging configuration and added optional arguments using argparse for flexibility.
	•	Abstracted repetitive paths using constants for maintainability.
	•	Consolidated functionality for fetching images and refreshing the screen.
	•	Removed unused Wi-Fi and GUI toggling code.
	•	Focused the script’s functionality on image fetching and display for Kindle extensions.
	5.	CSS (style.css)
	•	Removed visual debugging borders (red, green, yellow).
	•	Improved layout styles:
	•	Set fixed widths for better rendering of event columns.
	•	Adjusted margins and paddings for cleaner alignment.
	•	Added a new .day .events class for consistent padding.
	6.	views.py
	•	Added error handling when fetching calendar data:
	•	Ensures the application doesn’t crash if calendar URLs are inaccessible.
	•	Logs errors to console for debugging.

Impact:
	•	Maintainability: Refactored scripts, improved code structure, and enhanced readability.
	•	Flexibility: Environment variable support for ports and dynamic script arguments.
	•	Functionality: Added OpenMoji font support in the Docker container.
	•	UI/UX: Cleaned up CSS for better layout and appearance.
	•	Resilience: Improved error handling in views.py to handle calendar fetch failures gracefully.

Files Modified:
	•	.gitignore
	•	Dockerfile
	•	compose.yml
	•	kindle/ascwebdash/bin/asc-webdash.py
	•	server/app/templates/style.css
	•	server/app/views.py

This ensures better extensibility and robustness across the codebase.
2024-12-17 06:59:54 -06:00

132 lines
4.9 KiB
Python

from app import app
from datetime import datetime, timedelta, timezone
import os
import caldav
import datetime
from icalendar import cal, Event
from flask import render_template, url_for, send_file, send_from_directory, request
from .models import Event
import requests
import imgkit
from PIL import Image, ImageOps
import io
caldav_url = os.getenv('caldav_url')
username = os.getenv('username')
password = os.getenv('password')
cal_id = os.getenv('cal_id')
from .weather import weather
def remove_emoji(string):
import re
emoji_pattern = re.compile("["
u"\U0001F600-\U0001F64F" # emoticons
u"\U0001F300-\U0001F5FF" # symbols & pictographs
u"\U0001F680-\U0001F6FF" # transport & map symbols
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
u"\U00002500-\U00002BEF" # chinese char
u"\U00002702-\U000027B0"
u"\U00002702-\U000027B0"
u"\U000024C2-\U0001F251"
u"\U0001f926-\U0001f937"
u"\U00010000-\U0010ffff"
u"\u2640-\u2642"
u"\u2600-\u2B55"
u"\u200d"
u"\u23cf"
u"\u23e9"
u"\u231a"
u"\ufe0f" # dingbats
u"\u3030"
"]+", flags=re.UNICODE)
return emoji_pattern.sub(r'', string)
def daterange(start_date, end_date):
for n in range(int((end_date - start_date).days)):
yield datetime.datetime.date(start_date + timedelta(n))
@app.route('/')
def dashboard():
today = datetime.datetime.now(tz=datetime.datetime.now(timezone.utc).astimezone().tzinfo)
# today = datetime.datetime(2022,6,5, tzinfo=datetime.datetime.now(timezone.utc).astimezone().tzinfo)
start_of_week = today - timedelta(days=(today.weekday()+1)) # Monday
end_of_week = start_of_week + timedelta(days=8) # Sunday
events = []
for url in [
'https://www.calendarlabs.com/ical-calendar/ics/76/US_Holidays.ics',
]:
try:
raise Exception
r = requests.get(url)
c = cal.Calendar.from_ical(r.content)
events += Event.fromIcalendar(c)
except Exception as e:
print(f"Error: {e}")
with caldav.DAVClient(url=caldav_url, username=username, password=password) as client:
my_principal = client.principal()
calendars = my_principal.calendars()
for id in [cal_id]:
calendar = my_principal.calendar(cal_id=id)
events += Event.fromCalDavEvents(calendar.date_search(
start=start_of_week, end=end_of_week, expand=False))
for url in [
'http://ical-cdn.teamsnap.com/team_schedule/5f1ddc9e-15b0-4912-84a2-11cc70e9e375.ics'
]:
r = requests.get(url)
c = cal.Calendar.from_ical(r.content)
events += Event.fromIcalendar(c)
days = []
for single_date in daterange(start_of_week, end_of_week):
days_events = []
for e in events:
if (e.dtstart.date() <= single_date <= e.dtend.date()):
e.summary = remove_emoji(e.summary)
days_events.append(e)
days.append((single_date, days_events))
extra_debug = request.args.get('extra', '')
# r = "<br>".join([event.vobject_instance.vevent.summary.value for event in events_fetched if event.vobject_instance.vevent.dtstart.value < datetime.now()])
return render_template("dashboard.html",
days=days,
today=today,
weather=weather(),
extra_debug=extra_debug,
HOST = os.getenv('HOST'),
HOST_PORT = os.getenv('HOST_PORT')
)
@app.route('/image')
def dashboard_image():
extension = "png"
page = dashboard()
out_file = os.path.join(os.path.dirname(__file__),
'static', f'out.{extension}'
)
s = imgkit.from_string(
page,
out_file,
options={
'width':600,
'height':800,
"disable-smart-width": "",
'enable-local-file-access': "",
'allow': os.path.join(os.path.dirname(__file__),
'static',
)
},
# css=os.path.join(os.path.dirname(__file__),'static','style.css')
)
image_file = Image.open(out_file) # open colour image
# image_file = ImageOps.grayscale(image_file)
image_file.save(out_file, 'BMP')
return send_from_directory(directory = 'static', path=f'out.{extension}', as_attachment=False, attachment_filename=f'out.{extension}')