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.
132 lines
4.9 KiB
Python
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}')
|