#!/bin/sh . /lib/functions.sh . /usr/share/libubox/jshn.sh CONTAINER="secbx-jellyfin" CONFIG="jellyfin" case "$1" in list) echo '{"status":{},"start":{},"stop":{},"restart":{},"install":{},"uninstall":{},"update":{},"configure_haproxy":{},"backup":{},"restore":{"path":"str"},"logs":{"lines":"int"},"get_wizard_status":{},"set_wizard_complete":{"complete":"int"},"add_media_path":{"path":"str","name":"str","type":"str"},"remove_media_path":{"section":"str"},"get_media_paths":{}}' ;; call) case "$2" in status) json_init enabled=$(uci -q get ${CONFIG}.main.enabled) image=$(uci -q get ${CONFIG}.main.image) port=$(uci -q get ${CONFIG}.main.port) data_path=$(uci -q get ${CONFIG}.main.data_path) timezone=$(uci -q get ${CONFIG}.main.timezone) hw_accel=$(uci -q get ${CONFIG}.transcoding.hw_accel) # Network/domain config domain=$(uci -q get ${CONFIG}.network.domain) haproxy=$(uci -q get ${CONFIG}.network.haproxy) firewall_wan=$(uci -q get ${CONFIG}.network.firewall_wan) # Mesh config mesh_enabled=$(uci -q get ${CONFIG}.mesh.enabled) json_add_boolean "enabled" ${enabled:-0} json_add_string "image" "${image:-jellyfin/jellyfin:latest}" json_add_int "port" ${port:-8096} json_add_string "data_path" "${data_path:-/srv/jellyfin}" json_add_string "timezone" "${timezone:-Europe/Paris}" json_add_boolean "hw_accel" ${hw_accel:-0} json_add_string "domain" "${domain:-jellyfin.secubox.local}" json_add_boolean "haproxy" ${haproxy:-0} json_add_boolean "firewall_wan" ${firewall_wan:-0} json_add_boolean "mesh_enabled" ${mesh_enabled:-0} # Docker availability if command -v docker >/dev/null 2>&1; then json_add_boolean "docker_available" 1 else json_add_boolean "docker_available" 0 fi # Container status if docker ps --filter "name=$CONTAINER" --format '{{.Status}}' 2>/dev/null | grep -q .; then json_add_string "container_status" "running" uptime=$(docker ps --filter "name=$CONTAINER" --format '{{.Status}}' 2>/dev/null) json_add_string "container_uptime" "$uptime" elif docker ps -a --filter "name=$CONTAINER" --format '{{.Status}}' 2>/dev/null | grep -q .; then json_add_string "container_status" "stopped" json_add_string "container_uptime" "" else json_add_string "container_status" "not_installed" json_add_string "container_uptime" "" fi # HAProxy vhost status if [ "${haproxy:-0}" = "1" ]; then vhost_exists=$(uci show haproxy 2>/dev/null | grep "\.domain='${domain:-jellyfin.secubox.local}'" | head -1) if [ -n "$vhost_exists" ]; then json_add_string "haproxy_status" "configured" else json_add_string "haproxy_status" "pending" fi else json_add_string "haproxy_status" "disabled" fi # Disk usage dp="${data_path:-/srv/jellyfin}" if [ -d "$dp" ]; then disk_usage=$(du -sh "$dp" 2>/dev/null | cut -f1) json_add_string "disk_usage" "${disk_usage:-0}" else json_add_string "disk_usage" "" fi # Media paths json_add_array "media_paths" for mp in $(uci -q get ${CONFIG}.media.media_path); do json_add_string "" "$mp" done json_close_array json_dump ;; start) /etc/init.d/jellyfin start >/dev/null 2>&1 echo '{"success":true}' ;; stop) /etc/init.d/jellyfin stop >/dev/null 2>&1 echo '{"success":true}' ;; restart) /etc/init.d/jellyfin restart >/dev/null 2>&1 echo '{"success":true}' ;; install) output=$(/usr/sbin/jellyfinctl install 2>&1) code=$? json_init json_add_boolean "success" $((code == 0)) json_add_string "output" "$output" json_dump ;; uninstall) output=$(/usr/sbin/jellyfinctl uninstall 2>&1) code=$? json_init json_add_boolean "success" $((code == 0)) json_add_string "output" "$output" json_dump ;; update) output=$(/usr/sbin/jellyfinctl update 2>&1) code=$? json_init json_add_boolean "success" $((code == 0)) json_add_string "output" "$output" json_dump ;; configure_haproxy) output=$(/usr/sbin/jellyfinctl configure-haproxy 2>&1) code=$? json_init json_add_boolean "success" $((code == 0)) json_add_string "output" "$output" json_dump ;; backup) backup_file="/tmp/jellyfin-backup-$(date +%Y%m%d-%H%M%S).tar.gz" output=$(/usr/sbin/jellyfinctl backup "$backup_file" 2>&1) code=$? json_init json_add_boolean "success" $((code == 0)) json_add_string "path" "$backup_file" json_add_string "output" "$output" json_dump ;; restore) read -r input path=$(echo "$input" | jsonfilter -e '@.path' 2>/dev/null) if [ -z "$path" ]; then echo '{"success":false,"output":"No backup path specified"}' else output=$(/usr/sbin/jellyfinctl restore "$path" 2>&1) code=$? json_init json_add_boolean "success" $((code == 0)) json_add_string "output" "$output" json_dump fi ;; logs) read -r input lines=$(echo "$input" | jsonfilter -e '@.lines' 2>/dev/null) [ -z "$lines" ] && lines=50 logs=$(docker logs --tail "$lines" "$CONTAINER" 2>&1 | tail -100) json_init json_add_string "logs" "$logs" json_dump ;; get_wizard_status) json_init # Check if container exists and running installed=0 running=0 if docker ps -a --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER}$"; then installed=1 docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER}$" && running=1 fi # Check if any media paths configured media_count=0 for section in $(uci show ${CONFIG} 2>/dev/null | grep "=media$" | cut -d'.' -f2 | cut -d'=' -f1); do media_count=$((media_count + 1)) done # Check if wizard completed wizard_complete=$(uci -q get ${CONFIG}.main.wizard_complete) json_add_boolean "installed" "$installed" json_add_boolean "running" "$running" json_add_int "media_count" "$media_count" json_add_boolean "wizard_complete" "${wizard_complete:-0}" # Show wizard if installed but not complete show=0 [ "$installed" = "1" ] && [ "${wizard_complete:-0}" != "1" ] && show=1 json_add_boolean "show_wizard" "$show" json_dump ;; set_wizard_complete) read -r input complete=$(echo "$input" | jsonfilter -e '@.complete' 2>/dev/null) uci set ${CONFIG}.main.wizard_complete="${complete:-1}" uci commit ${CONFIG} json_init json_add_boolean "success" 1 json_dump ;; add_media_path) read -r input path=$(echo "$input" | jsonfilter -e '@.path' 2>/dev/null) name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null) type=$(echo "$input" | jsonfilter -e '@.type' 2>/dev/null) if [ -z "$path" ]; then json_init json_add_boolean "success" 0 json_add_string "error" "Path required" json_dump exit 0 fi # Generate unique section name section="media_$(echo "${name:-library}" | tr ' ' '_' | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9_')" # Ensure unique count=1 base_section="$section" while uci -q get "${CONFIG}.${section}" >/dev/null 2>&1; do section="${base_section}_${count}" count=$((count + 1)) done uci set "${CONFIG}.${section}=media" uci set "${CONFIG}.${section}.path=$path" uci set "${CONFIG}.${section}.name=${name:-Library}" uci set "${CONFIG}.${section}.type=${type:-movies}" uci commit ${CONFIG} json_init json_add_boolean "success" 1 json_add_string "section" "$section" json_dump ;; remove_media_path) read -r input section=$(echo "$input" | jsonfilter -e '@.section' 2>/dev/null) if [ -z "$section" ]; then json_init json_add_boolean "success" 0 json_add_string "error" "Section required" json_dump exit 0 fi uci delete "${CONFIG}.${section}" 2>/dev/null uci commit ${CONFIG} json_init json_add_boolean "success" 1 json_dump ;; get_media_paths) json_init json_add_array "paths" for section in $(uci show ${CONFIG} 2>/dev/null | grep "=media$" | cut -d'.' -f2 | cut -d'=' -f1); do path=$(uci -q get "${CONFIG}.${section}.path") name=$(uci -q get "${CONFIG}.${section}.name") type=$(uci -q get "${CONFIG}.${section}.type") json_add_object "" json_add_string "section" "$section" json_add_string "path" "$path" json_add_string "name" "${name:-$section}" json_add_string "type" "${type:-movies}" json_close_object done json_close_array json_dump ;; esac ;; esac exit 0