daily_sunrise_video.sh: use \$MOVIES_DIR instead of \$BASE_DIR/movies so the override in sky-cam.conf is respected when videos live on a separate drive. capture.sh: default camera name falls back to \$SUNRISE_CAM (not the undefined \$CAM_NAME) when no argument is passed. sunrise2mm.py: also loads .env after sky-cam.conf so Mattermost credentials moved to .env are actually visible to the upload script. sunrise.py: raise a clear error message when LATITUDE/LONGITUDE/TIMEZONE are missing from sky-cam.conf instead of an opaque KeyError. 4-seasons.sh, montage-mvt.sh: capture season_info.py output before eval so a Python failure exits cleanly with a diagnostic message rather than silently continuing with undefined variables. bootstrap.sh: add system package install step (ffmpeg bc fonts-dejavu) and show the .env setup step after install.sh generates .env.example. README.md: correct Python package names and add fonts-dejavu dependency. https://claude.ai/code/session_01C4jbd3waXG3eKZYbGUjLUQ
128 lines
4.5 KiB
Python
Executable File
128 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import requests
|
|
import os
|
|
import subprocess
|
|
from datetime import datetime
|
|
|
|
import pathlib
|
|
|
|
# Locate sky-cam.conf next to this script (works regardless of cwd).
|
|
_here = pathlib.Path(__file__).resolve().parent
|
|
config_file_path = str(_here / 'sky-cam.conf')
|
|
|
|
# Function to read configuration from the config file
|
|
def read_config(config_file_path):
|
|
config = {}
|
|
try:
|
|
with open(config_file_path, 'r') as f:
|
|
for line in f:
|
|
# Ignore comments and empty lines
|
|
if line.strip() and not line.startswith('#'):
|
|
key, value = line.strip().split('=', 1)
|
|
config[key.strip()] = value.strip()
|
|
except FileNotFoundError:
|
|
print(f"Error: The configuration file {config_file_path} was not found.")
|
|
exit(1)
|
|
except Exception as e:
|
|
print(f"Error reading the configuration file: {e}")
|
|
exit(1)
|
|
return config
|
|
|
|
# Read configuration — sky-cam.conf first, then .env overrides (credentials)
|
|
config = read_config(config_file_path)
|
|
_env_path = str(_here / '.env')
|
|
if os.path.isfile(_env_path):
|
|
config.update(read_config(_env_path))
|
|
|
|
# Get the values from the configuration file
|
|
mattermost_url = config.get('mattermost_url')
|
|
access_token = config.get('access_token')
|
|
channel_id = config.get('channel_id')
|
|
|
|
# Check if all required values are provided
|
|
if not mattermost_url or not access_token or not channel_id:
|
|
print("Error: Missing one or more configuration values.")
|
|
exit(1)
|
|
|
|
# Get today's date
|
|
today = datetime.now()
|
|
today_date_str = today.strftime("%Y-%m-%d") # e.g., "2024-11-05"
|
|
today_month_str = today.strftime("%Y-%m") # e.g., "2024-11"
|
|
|
|
# Set the full folder path for today's video
|
|
base_video_folder = os.path.join(config.get('MOVIES_DIR', ''), config.get('SUNRISE_CAM', 'sunrise'))
|
|
output_dir = os.path.join(base_video_folder, today_month_str, "sunrise-only")
|
|
|
|
# Check if the directory exists
|
|
if not os.path.isdir(output_dir):
|
|
print(f"Error: The directory {output_dir} does not exist. The video may not have been created yet.")
|
|
exit(1)
|
|
|
|
final_video_file = os.path.join(output_dir, f"{today_date_str}-daily-sunrise.mp4")
|
|
|
|
# Debugging: print the full path of the video file to make sure it's correct
|
|
print(f"Looking for video file: {final_video_file}")
|
|
|
|
# Check if the video file exists
|
|
if os.path.isfile(final_video_file):
|
|
# Upload the video file
|
|
with open(final_video_file, 'rb') as f:
|
|
response = requests.post(
|
|
f"{mattermost_url}/api/v4/files",
|
|
headers={'Authorization': f'Bearer {access_token}'},
|
|
files={'files': f},
|
|
data={'channel_id': channel_id}
|
|
)
|
|
|
|
if response.status_code == 201:
|
|
print(f"Successfully uploaded {final_video_file}")
|
|
|
|
# Get the file ID from the response
|
|
file_id = response.json().get('file_infos', [{}])[0].get('id')
|
|
|
|
# Send a message with the file reference
|
|
message_data = {
|
|
'channel_id': channel_id,
|
|
'message': f"Here is a video of the sunrise for {today_date_str}",
|
|
'file_ids': [file_id] # Attach the uploaded file
|
|
}
|
|
|
|
message_response = requests.post(
|
|
f"{mattermost_url}/api/v4/posts",
|
|
headers={'Authorization': f'Bearer {access_token}'},
|
|
json=message_data
|
|
)
|
|
|
|
if message_response.status_code == 201:
|
|
print("Message posted successfully.")
|
|
subprocess.run(
|
|
[str(_here / 'notify.sh'),
|
|
f"Sunrise uploaded: {today_date_str}",
|
|
f"Video posted to Mattermost successfully"],
|
|
check=False
|
|
)
|
|
else:
|
|
print(f"Failed to post message: {message_response.text}")
|
|
subprocess.run(
|
|
[str(_here / 'notify.sh'),
|
|
f"FAILED: sunrise Mattermost post {today_date_str}",
|
|
f"File uploaded but post failed: {message_response.status_code}"],
|
|
check=False
|
|
)
|
|
else:
|
|
print(f"Failed to upload {final_video_file}: {response.text}")
|
|
subprocess.run(
|
|
[str(_here / 'notify.sh'),
|
|
f"FAILED: sunrise upload {today_date_str}",
|
|
f"Mattermost file upload failed: {response.status_code}"],
|
|
check=False
|
|
)
|
|
else:
|
|
print(f"No video file found at {final_video_file}.")
|
|
subprocess.run(
|
|
[str(_here / 'notify.sh'),
|
|
f"FAILED: sunrise upload {today_date_str}",
|
|
f"Video file not found: {final_video_file}"],
|
|
check=False
|
|
)
|