Files
scripts/svt.sh
2026-02-22 03:25:12 +01:00

114 lines
3.5 KiB
Bash
Executable File

#!/bin/bash
# SVT Play Stream Launcher - Search and stream SVT Play content with zenity
set -euo pipefail
WAIT_FOR_MPV=0
# Parse options
while [[ $# -gt 0 ]]; do
case "$1" in
--wait) WAIT_FOR_MPV=1; shift ;;
--help|-h)
zenity --info --title="SVT Play" --text="Usage: ./svt.sh [--wait|--help]"
exit 0 ;;
*) break ;;
esac
done
# Force dark mode - works with GTK3 (GTK_THEME) and GTK4/libadwaita (ADW_DEBUG_COLOR_SCHEME)
zenity_dark() { GTK_THEME=Adwaita:dark ADW_DEBUG_COLOR_SCHEME=prefer-dark zenity "$@"; }
check_dependencies() {
local missing=()
for cmd in yt-dlp mpv zenity jq curl; do
command -v "$cmd" &>/dev/null || missing+=("$cmd")
done
if [[ ${#missing[@]} -gt 0 ]]; then
zenity_dark --error --title="Missing Dependencies" --text="Please install: ${missing[*]}"
exit 1
fi
}
search_programs() {
local query="$1"
local response http_code
response=$(curl -s --connect-timeout 10 --max-time 30 -w "\n%{http_code}" -X POST \
"https://api.svt.se/contento/graphql" -H "Content-Type: application/json" \
-d "{\"query\": \"{ searchPage(query: \\\"${query}\\\", maxHits: 50) { flat { hits { teaser { heading item { urls { svtplay } } } } } } }\"}" 2>/dev/null) || return 1
http_code=$(echo "$response" | tail -1)
response=$(echo "$response" | sed '$d')
[[ "$http_code" != "200" ]] && return 1
local results
results=$(echo "$response" | jq -r '
.data.searchPage.flat.hits[].teaser |
select(.heading != null and .item.urls.svtplay != null) |
(.heading | gsub("<[^>]*>"; "")) + "|" + (.item.urls.svtplay | ltrimstr("/"))
' 2>/dev/null)
[[ -z "$results" ]] && return 1
echo "$results"
}
show_search_dialog() {
zenity_dark --entry --title="Search SVT Play" --text="Program name:" --width=400 2>/dev/null
}
show_results_list() {
local results="$1" temp_file="/tmp/svt_$$"
# Build zenity list and mapping file
local idx=0
while IFS='|' read -r title slug; do
[[ -z "$title" || -z "$slug" ]] && continue
((idx++))
title=$(echo "$title" | sed 's/&amp;/\&/g; s/&quot;/"/g; s/&lt;/</g; s/&gt;/>/g')
echo "$title=$slug" >> "$temp_file.map"
[[ $idx -eq 1 ]] && echo "TRUE" >> "$temp_file" || echo "FALSE" >> "$temp_file"
echo "$title" >> "$temp_file"
done <<< "$results"
[[ $idx -eq 0 ]] && { rm -f "$temp_file"*; return 1; }
local selected
selected=$(zenity_dark --list --title="Results" --text="Select program:" \
--column="Select" --column="Program" --radiolist --width=700 --height=500 < "$temp_file" 2>/dev/null)
local slug=""
[[ -n "$selected" ]] && slug=$(grep "^${selected}=" "$temp_file.map" 2>/dev/null | cut -d= -f2)
rm -f "$temp_file"*
[[ -z "$slug" ]] && return 1
echo "$slug"
}
play_program() {
local url="https://www.svtplay.se/$1"
mpv --force-window=immediate "$url" &
[[ "$WAIT_FOR_MPV" == "1" ]] && wait $! 2>/dev/null
}
main() {
check_dependencies
local search_term
search_term=$(show_search_dialog) || exit 0
[[ -z "$search_term" ]] && exit 0
local results
results=$(search_programs "$search_term") || {
zenity_dark --error --title="No Results" --text="No programs found for: $search_term"
exit 0
}
local slug
slug=$(show_results_list "$results") || exit 0
play_program "$slug"
}
[[ "${BASH_SOURCE[0]}" == "${0}" ]] && main "$@"