plex und threadfin

This commit is contained in:
sandro committed 2026-10-02 06:46:35 +02:00
1 parent 66e53b4be4
commit fcb87cf881
7 files changed
+221 -40

No files matched your search

+78 -33
View File
@@ -1,6 +1,7 @@
import requests import requests
import json import json
import os import os
import time
# --- KONFIGURATION --- # --- KONFIGURATION ---
JELLYFIN_URL = "http://localhost:8096" # Oder 192.168.188.124 JELLYFIN_URL = "http://localhost:8096" # Oder 192.168.188.124
@@ -9,7 +10,7 @@ EPG_PATH = "/home/sandro/m3u/sky_epg.xml"
ID_FILE = "last_provider_id.txt" # Lokaler Cache für die ID ID_FILE = "last_provider_id.txt" # Lokaler Cache für die ID
HEADERS = { HEADERS = {
"X-Emby-Token": API_KEY, "Authorization": 'Mediabrowser Token="' + API_KEY + '"',
"Content-Type": "application/json" "Content-Type": "application/json"
} }
@@ -17,9 +18,9 @@ def get_provider_id():
"""Versucht die ID des XMLTV-Providers von Jellyfin zu holen.""" """Versucht die ID des XMLTV-Providers von Jellyfin zu holen."""
try: try:
# Liste aller Live-TV Provider abfragen # Liste aller Live-TV Provider abfragen
response = requests.get(f"{JELLYFIN_URL}/LiveTv/ListingProviders", headers=HEADERS) response = requests.get(f"{JELLYFIN_URL}/System/Configuration/livetv", headers=HEADERS)
response.raise_for_status() response.raise_for_status()
providers = response.json().get("Listings", []) providers = response.json().get("ListingProviders", [])
# Suche den Provider, der unseren Pfad nutzt # Suche den Provider, der unseren Pfad nutzt
for p in providers: for p in providers:
@@ -38,6 +39,7 @@ def sync_jellyfin_epg():
# 1. ID finden (aus API oder Cache) # 1. ID finden (aus API oder Cache)
provider_id = get_provider_id() provider_id = get_provider_id()
# 2. Wenn ID vorhanden, alten Provider löschen # 2. Wenn ID vorhanden, alten Provider löschen
if provider_id: if provider_id:
print(f"Lösche Provider mit ID: {provider_id}") print(f"Lösche Provider mit ID: {provider_id}")
@@ -46,40 +48,83 @@ def sync_jellyfin_epg():
except Exception as e: except Exception as e:
print(f"Löschen fehlgeschlagen (evtl. schon weg): {e}") print(f"Löschen fehlgeschlagen (evtl. schon weg): {e}")
# 3. Provider neu anlegen with open("/home/sandro/m3u/sky_epg.xml","r") as epg_file:
print(f"Lege Provider neu an für: {EPG_PATH}") epg_file_content = epg_file.read()
payload = { if "<title>None</title>" not in epg_file_content:
"Type": "xmltv", # 3. Provider neu anlegen
"Path": EPG_PATH, print(f"Lege Provider neu an für: {EPG_PATH}")
"MoviePrefix": None, payload = {
"UserAgent": None, "Type": "xmltv",
"MovieCategories": [], "Path": EPG_PATH,
"KidsCategories": [], "MoviePrefix": None,
"NewsCategories": [], "UserAgent": None,
"SportsCategories": ["sports"], "MovieCategories": [],
"EnableAllTuners": True, "KidsCategories": [],
"EnabledTuners": [] "NewsCategories": [],
} "SportsCategories": ["sports"],
"EnableAllTuners": True,
"EnabledTuners": []
}
try:
response = requests.post(f"{JELLYFIN_URL}/LiveTv/ListingProviders?ValidateListings=true",
headers=HEADERS, json=payload)
response.raise_for_status()
# Die neue ID aus der Antwort holen und zwischenspeichern
new_data = response.json()
new_id = new_data.get("Id")
if new_id:
with open(ID_FILE, "w") as f:
f.write(new_id)
print(f"Erfolgreich! Neue ID {new_id} im Cache gespeichert.")
# 4. Optional: Sofortigen Refresh der Daten triggern
requests.post(f"{JELLYFIN_URL}/LiveTv/Refresh?api_key={API_KEY}")
except Exception as e:
print(f"Fehler beim Neuerstellen: {e}")
def sync_threadfin_epg():
url = "http://192.168.189.116:34400/api/"
payload = {"cmd": "update.xmltv"}
print("🚀 Sende EPG-Update-Befehl an Threadfin...")
try:
# Das requests-Modul wandelt das dict mit 'json=' automatisch in ein sauberes JSON-Payload um
response = requests.post(url, json=payload, timeout=10)
response.raise_for_status() # Wirft einen Fehler bei HTTP-Codes wie 4xx oder 5xx
print(f"✅ Erfolgreich! Status: {response.status_code}")
print(f"Antwort: {response.text}")
# Kommandozeilen-Parameter definieren
time.sleep(10)
print(f"Wartezeit für Threadfin vorbei, weiter gehts")
except requests.exceptions.RequestException as e:
print(f"❌ Fehler beim API-Aufruf: {e}")
sys.exit(1)
def sync_plex_epg():
PLEX_IP = "192.168.188.124"
PLEX_PORT = "32400"
PLEX_DVR_ID = "16" # Deine DVR-ID (aus der XML)
PLEX_TOKEN = "xnxczzsEyHyTN1BAveeq" # Dein Plex-Token
plex_url = f"http://{PLEX_IP}:{PLEX_PORT}/livetv/dvrs/{PLEX_DVR_ID}/reloadGuide?X-Plex-Token={PLEX_TOKEN}"
try: try:
response = requests.post(f"{JELLYFIN_URL}/LiveTv/ListingProviders?ValidateListings=true", print("Sende Guide-Reload-Befehl an Plex...")
headers=HEADERS, json=payload) res_plex = requests.post(plex_url, timeout=10)
response.raise_for_status() res_plex.raise_for_status()
print(f"Plex erfolgreich getriggert (Status: {res_plex.status_code})")
except requests.exceptions.RequestException as e:
print(f"Fehler beim API-Aufruf von Plex: {e}")
# Die neue ID aus der Antwort holen und zwischenspeichern
new_data = response.json()
new_id = new_data.get("Id")
if new_id:
with open(ID_FILE, "w") as f:
f.write(new_id)
print(f"Erfolgreich! Neue ID {new_id} im Cache gespeichert.")
# 4. Optional: Sofortigen Refresh der Daten triggern
requests.post(f"{JELLYFIN_URL}/LiveTv/Refresh?api_key={API_KEY}")
except Exception as e:
print(f"Fehler beim Neuerstellen: {e}")
if __name__ == "__main__": if __name__ == "__main__":
sync_jellyfin_epg() sync_jellyfin_epg()
sync_threadfin_epg()
sync_plex_epg()
+85
View File
@@ -0,0 +1,85 @@
import requests
import json
import os
# --- KONFIGURATION ---
JELLYFIN_URL = "http://localhost:8096" # Oder 192.168.188.124
API_KEY = "5ba10da6cca145feb8feff8f6b4b5e55" # Hier den API Key eintragen
EPG_PATH = "/home/sandro/m3u/sky_epg.xml"
ID_FILE = "last_provider_id.txt" # Lokaler Cache für die ID
HEADERS = {
"X-Emby-Token": API_KEY,
"Content-Type": "application/json"
}
def get_provider_id():
"""Versucht die ID des XMLTV-Providers von Jellyfin zu holen."""
try:
# Liste aller Live-TV Provider abfragen
response = requests.get(f"{JELLYFIN_URL}/LiveTv/ListingProviders", headers=HEADERS)
response.raise_for_status()
providers = response.json().get("Listings", [])
# Suche den Provider, der unseren Pfad nutzt
for p in providers:
if p.get("Path") == EPG_PATH:
return p.get("Id")
except Exception as e:
print(f"Fehler beim Abrufen der Provider-Liste: {e}")
# Falls in der API nicht gefunden, schau im lokalen Cache nach
if os.path.exists(ID_FILE):
with open(ID_FILE, "r") as f:
return f.read().strip()
return None
def sync_jellyfin_epg():
# 1. ID finden (aus API oder Cache)
provider_id = get_provider_id()
# 2. Wenn ID vorhanden, alten Provider löschen
if provider_id:
print(f"Lösche Provider mit ID: {provider_id}")
try:
requests.delete(f"{JELLYFIN_URL}/LiveTv/ListingProviders?id={provider_id}", headers=HEADERS)
except Exception as e:
print(f"Löschen fehlgeschlagen (evtl. schon weg): {e}")
# 3. Provider neu anlegen
print(f"Lege Provider neu an für: {EPG_PATH}")
payload = {
"Type": "xmltv",
"Path": EPG_PATH,
"MoviePrefix": None,
"UserAgent": None,
"MovieCategories": [],
"KidsCategories": [],
"NewsCategories": [],
"SportsCategories": ["sports"],
"EnableAllTuners": True,
"EnabledTuners": []
}
try:
response = requests.post(f"{JELLYFIN_URL}/LiveTv/ListingProviders?ValidateListings=true",
headers=HEADERS, json=payload)
response.raise_for_status()
# Die neue ID aus der Antwort holen und zwischenspeichern
new_data = response.json()
new_id = new_data.get("Id")
if new_id:
with open(ID_FILE, "w") as f:
f.write(new_id)
print(f"Erfolgreich! Neue ID {new_id} im Cache gespeichert.")
# 4. Optional: Sofortigen Refresh der Daten triggern
requests.post(f"{JELLYFIN_URL}/LiveTv/Refresh?api_key={API_KEY}")
except Exception as e:
print(f"Fehler beim Neuerstellen: {e}")
if __name__ == "__main__":
sync_jellyfin_epg()
+12 -3
View File
@@ -2,6 +2,7 @@ import subprocess
from flask import Flask, request, jsonify from flask import Flask, request, jsonify
from lxml import etree from lxml import etree
from datetime import datetime, timedelta from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
app = Flask(__name__) app = Flask(__name__)
@@ -12,11 +13,19 @@ def update_sky():
data = request.json data = request.json
channel_name = data.get('channel', 'Unbekannt') channel_name = data.get('channel', 'Unbekannt')
content_title = data.get('content', 'Keine Information') content_title = data.get('content', 'Keine Information')
skyq_media_type = data.get('type', 'Keine Information')
if skyq_media_type == 'app':
content_title = "App-TV"
# Zeitstempel für XMLTV (Start jetzt, Ende in 1 Std als Platzhalter) # Zeitstempel für XMLTV (Start jetzt, Ende in 1 Std als Platzhalter)
now = datetime.now() tz = ZoneInfo("Europe/Berlin")
start_time = now.strftime("%Y%m%d%H%M%S +0100") now = datetime.now(tz)
stop_time = (now + timedelta(hours=12)).strftime("%Y%m%d%H%M%S +0100")
start_time = now.strftime("%Y%m%d%H%M%S %z")
stop_time = (now + timedelta(hours=12)).strftime("%Y%m%d%H%M%S %z")
print(start_time)
print(stop_time)
# XML Struktur aufbauen # XML Struktur aufbauen
root = etree.Element("tv") root = etree.Element("tv")
+1 -1
View File
@@ -1 +1 @@
ba629a20463c446085ff4ebcf7845269 0a1b1777aefb4c4fb861ecae7ae88aae
Executable
+26
View File
@@ -0,0 +1,26 @@
#!/bin/bash
# Falls du das Skript von überall ausführen willst,
# wechsle hier in dein Repo-Verzeichnis:
# cd /home/sandro/dein-repo-pfad || exit
# 1. Alle Änderungen stagen
git add .
# 2. Commit-Nachricht festlegen
# Wenn ein Argument übergeben wurde, nimm das, sonst Zeitstempel
if [ -z "$1" ]; then
MSG="Update vom $(date '+%Y-%m-%d %H:%M:%S')"
else
MSG="$1"
fi
# 3. Committen
git commit -m "$MSG"
# 4. Zum Gitea-Server pushen
# Wir gehen davon aus, dass der Remote 'origin' heißt und der Branch 'main'
git push origin main
echo "---------------------------------------"
echo "✅ Änderungen wurden erfolgreich zu Gitea gepusht!"
+3 -3
View File
@@ -3,8 +3,8 @@
<channel id="cftv"> <channel id="cftv">
<display-name>cftv</display-name> <display-name>cftv</display-name>
</channel> </channel>
<programme start="20260317095223 +0100" stop="20260317215223 +0100" channel="cftv"> <programme start="20261001203205 +0200" stop="20261002083205 +0200" channel="cftv">
<title>Bundesliga 25/26: Borussia M'gladbach - FC St. Pauli</title> <title>App-TV</title>
<icon src="https://de.imageservice.sky.com/pd-image/aeba6166-d2d1-49fa-8f96-d4ef91cede11/16-9/1024?territory=DE&amp;provider=SKY&amp;proposition=SKYQ"/> <icon src="/api/media_player_proxy/media_player.sky_q_receiver?token=6155c61b839e5d3be133521531cf4c676eb975ca8272026dd9d62128f53f19db&amp;cache=78286cb0aeb8fc41"/>
</programme> </programme>
</tv> </tv>
+16
View File
@@ -0,0 +1,16 @@
import http.server
import socketserver
PORT = 8889
FILE_NAME = "sky_epg.xml" # Trage hier den Namen deiner Datei ein
class SingleFileHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
# Leitet jede Anfrage zwingend auf diese eine Datei um
self.path = '/' + FILE_NAME
return super().do_GET()
with socketserver.TCPServer(("", PORT), SingleFileHandler) as httpd:
print(f"Server läuft: http://localhost:{PORT}")
print(f"Stellt ausschließlich '{FILE_NAME}' bereit. Zum Beenden STRG+C drücken.")
httpd.serve_forever()