115 lines
3.8 KiB
Python
Executable File
115 lines
3.8 KiB
Python
Executable File
"""Video routes."""
|
|
|
|
import logging
|
|
|
|
from flask import Blueprint, flash, g, redirect, render_template, url_for
|
|
|
|
from customer_portal.services.wordpress_api import WordPressAPI
|
|
from customer_portal.web.routes.auth import login_required
|
|
|
|
bp = Blueprint("videos", __name__)
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@bp.route("/")
|
|
@login_required
|
|
def list_videos():
|
|
"""List customer videos grouped by bundles and courses."""
|
|
try:
|
|
videos = WordPressAPI.get_videos(g.customer.email)
|
|
except ValueError as e:
|
|
logger.error(f"WordPress API not configured: {e}")
|
|
flash("WordPress-Verbindung nicht konfiguriert.", "error")
|
|
videos = []
|
|
except Exception as e:
|
|
logger.error(f"Error fetching videos: {e}")
|
|
flash("Videos konnten nicht geladen werden.", "error")
|
|
videos = []
|
|
|
|
# Group videos by bundles and courses
|
|
bundles = (
|
|
{}
|
|
) # bundle_name -> {bundle_id, courses: {kurs_title -> {kurs_id, videos}}}
|
|
courses = {} # Single course purchases: kurs_title -> {kurs_id, videos}
|
|
|
|
for video in videos:
|
|
bundle_id = video.get("bundle_id")
|
|
bundle_name = video.get("bundle_name")
|
|
kurs_title = video.get("kurs_title", "Sonstige")
|
|
kurs_id = video.get("kurs_id")
|
|
|
|
if bundle_id:
|
|
# Video from a bundle purchase
|
|
if bundle_name not in bundles:
|
|
bundles[bundle_name] = {"bundle_id": bundle_id, "courses": {}}
|
|
if kurs_title not in bundles[bundle_name]["courses"]:
|
|
bundles[bundle_name]["courses"][kurs_title] = {
|
|
"kurs_id": kurs_id,
|
|
"videos": [],
|
|
}
|
|
bundles[bundle_name]["courses"][kurs_title]["videos"].append(video)
|
|
else:
|
|
# Single course purchase
|
|
if kurs_title not in courses:
|
|
courses[kurs_title] = {"kurs_id": kurs_id, "videos": []}
|
|
courses[kurs_title]["videos"].append(video)
|
|
|
|
return render_template(
|
|
"videos/list.html",
|
|
bundles=bundles,
|
|
courses=courses,
|
|
total_videos=len(videos),
|
|
)
|
|
|
|
|
|
@bp.route("/<int:video_id>")
|
|
@login_required
|
|
def watch(video_id: int):
|
|
"""Watch video page."""
|
|
try:
|
|
videos = WordPressAPI.get_videos(g.customer.email)
|
|
except Exception as e:
|
|
logger.error(f"Error fetching videos: {e}")
|
|
flash("Video konnte nicht geladen werden.", "error")
|
|
return redirect(url_for("videos.list_videos"))
|
|
|
|
# Find the requested video
|
|
video = None
|
|
related_videos = []
|
|
for v in videos:
|
|
if v.get("id") == video_id:
|
|
video = v
|
|
else:
|
|
related_videos.append(v)
|
|
|
|
if not video:
|
|
flash("Video nicht gefunden oder kein Zugriff.", "error")
|
|
return redirect(url_for("videos.list_videos"))
|
|
|
|
# Get stream URL from WordPress
|
|
try:
|
|
stream_data = WordPressAPI.get_video_stream(video_id, g.customer.email)
|
|
except Exception as e:
|
|
logger.error(f"Error getting stream URL for video {video_id}: {e}")
|
|
stream_data = None
|
|
|
|
if not stream_data or stream_data.get("error"):
|
|
error_msg = (
|
|
stream_data.get("error", "Stream nicht verfuegbar")
|
|
if stream_data
|
|
else "Stream nicht verfuegbar"
|
|
)
|
|
flash(f"Video-Stream nicht verfuegbar: {error_msg}", "error")
|
|
return redirect(url_for("videos.list_videos"))
|
|
|
|
# Filter related videos to same course, limit to 5
|
|
kurs_id = video.get("kurs_id")
|
|
related_videos = [v for v in related_videos if v.get("kurs_id") == kurs_id][:5]
|
|
|
|
return render_template(
|
|
"videos/watch.html",
|
|
video=video,
|
|
stream_url=stream_data.get("stream_url"),
|
|
related_videos=related_videos,
|
|
)
|