94 lines
3.2 KiB
Python
94 lines
3.2 KiB
Python
from datetime import datetime
|
|
import geocoder
|
|
import os
|
|
import requests
|
|
import subprocess
|
|
|
|
|
|
def day_of_week() -> str:
|
|
"""Returns the current day of the week.
|
|
|
|
Returns:
|
|
The name of the current day, such as "Monday" or "Friday".
|
|
"""
|
|
return datetime.now().strftime("%A")
|
|
|
|
|
|
def local_weather() -> str:
|
|
"""Returns a brief description of today's weather at the user's location.
|
|
|
|
Uses the device's IP address to estimate location, then fetches the
|
|
National Weather Service forecast for that location.
|
|
|
|
Returns:
|
|
A short text description of the current weather conditions,
|
|
or an error message if the weather cannot be fetched.
|
|
"""
|
|
location = geocoder.ip("me")
|
|
if not location or not location.latlng:
|
|
return "Unable to determine location for weather."
|
|
lat, lng = location.latlng
|
|
points_url = f"https://api.weather.gov/points/{lat},{lng}"
|
|
points = requests.get(points_url)
|
|
if not points.ok:
|
|
return "Unable to fetch weather data."
|
|
props = points.json()["properties"]
|
|
office = props["gridId"]
|
|
x = props["gridX"]
|
|
y = props["gridY"]
|
|
forecast_url = f"https://api.weather.gov/gridpoints/{office}/{x},{y}/forecast"
|
|
forecast = requests.get(forecast_url)
|
|
if not forecast.ok:
|
|
return "No weather forecast available."
|
|
periods = forecast.json()["properties"]["periods"]
|
|
today = periods[0]
|
|
return (
|
|
f"{today['name']}: {today['shortForecast']}, "
|
|
f"{today['temperature']}°{today['temperatureUnit']}, "
|
|
f"wind {today['windSpeed']} {today['windDirection']}"
|
|
)
|
|
|
|
|
|
def read_file(path: str) -> tuple[bool, str]:
|
|
"""Reads a file and returns its contents as plain text.
|
|
|
|
Supports many file formats including PDF, Word documents, HTML, and Markdown,
|
|
using pdftotext (for PDFs) and pandoc (for everything else). If the required
|
|
program is not installed or conversion fails, returns a description of the error.
|
|
|
|
Args:
|
|
path: The path to the file to read.
|
|
|
|
Returns:
|
|
A tuple of (success, text). When successful, success is True and text
|
|
contains the plain-text contents of the file. When unsuccessful,
|
|
success is False and text explains what went wrong.
|
|
"""
|
|
if not os.path.exists(path):
|
|
return (False, f"File not found: {path}")
|
|
|
|
_, ext = os.path.splitext(path.lower())
|
|
|
|
if ext == ".pdf":
|
|
try:
|
|
result = subprocess.run(
|
|
["pdftotext", path, "-"],
|
|
capture_output=True, text=True, check=True,
|
|
)
|
|
return (True, result.stdout)
|
|
except FileNotFoundError:
|
|
return (False, "pdftotext is not installed. Install poppler-utils to read PDF files.")
|
|
except subprocess.CalledProcessError as e:
|
|
return (False, f"pdftotext failed: {e.stderr.strip()}")
|
|
|
|
try:
|
|
result = subprocess.run(
|
|
["pandoc", path, "--to", "plain"],
|
|
capture_output=True, text=True, check=True,
|
|
)
|
|
return (True, result.stdout)
|
|
except FileNotFoundError:
|
|
return (False, "pandoc is not installed. Install pandoc to read this file format.")
|
|
except subprocess.CalledProcessError as e:
|
|
return (False, f"pandoc failed: {e.stderr.strip()}")
|