KV new format fix

This commit is contained in:
Pierre
2026-01-24 22:20:28 +01:00
parent b2303dfdc2
commit 9d22a6f404
3 changed files with 104 additions and 12 deletions
+1 -1
View File
@@ -166,7 +166,7 @@ class Handler(BaseHTTPRequestHandler):
cid = m.group(1)
# Check if file exists by looking up CID in metadata
file_path = fileserver.get_file_path(cid)
if file_path and os.path.exists(file_path):
if file_path and webdav_client.file_exists(file_path):
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Content-Type', 'image/jpeg')
+75 -4
View File
@@ -7,6 +7,7 @@ Handles reconnection when the leader changes or becomes unavailable.
from __future__ import annotations
import os
import json
import threading
from typing import List, Optional, Callable
@@ -301,6 +302,45 @@ class LeaderStorage(StorageProvider):
# Parse tagline
tagline = data.get('tagline')
# Get video/audio codec and resolution from various field formats
# New format: stream/0, stream/1, etc. as JSON strings
# Old format: fileinfo/streamdetails/video/0/... as flat keys
video_codec = data.get('videoCodec')
audio_codec = data.get('audioCodec')
width = parse_int(data.get('width'))
height = parse_int(data.get('height'))
# Try new stream/* JSON format first
if not video_codec or not width or not height or not audio_codec:
for i in range(20): # Check up to 20 streams
stream_key = f'stream/{i}'
stream_json = data.get(stream_key)
if not stream_json:
break
try:
stream = json.loads(stream_json) if isinstance(stream_json, str) else stream_json
stream_type = stream.get('type', '')
if stream_type == 'video' and not video_codec:
video_codec = stream.get('codec')
if not width:
width = parse_int(stream.get('width'))
if not height:
height = parse_int(stream.get('height'))
elif stream_type == 'audio' and not audio_codec:
audio_codec = stream.get('codec')
except (json.JSONDecodeError, TypeError):
pass
# Fall back to old flat key format
if not video_codec:
video_codec = data.get('fileinfo/streamdetails/video/0/codec')
if not audio_codec:
audio_codec = data.get('fileinfo/streamdetails/audio/0/codec')
if not width:
width = parse_int(data.get('fileinfo/streamdetails/video/0/width'))
if not height:
height = parse_int(data.get('fileinfo/streamdetails/video/0/height'))
return VideoMetadata(
hash_id=hash_id,
file_path=resolved_path,
@@ -310,10 +350,10 @@ class LeaderStorage(StorageProvider):
season=parse_int(data.get('season')),
episode=parse_int(data.get('episode')),
duration=parse_float(data.get('duration', data.get('fileinfo/duration'))),
width=parse_int(data.get('width', data.get('fileinfo/streamdetails/video/0/width'))),
height=parse_int(data.get('height', data.get('fileinfo/streamdetails/video/0/height'))),
video_codec=data.get('videoCodec', data.get('fileinfo/streamdetails/video/0/codec')),
audio_codec=data.get('audioCodec', data.get('fileinfo/streamdetails/audio/0/codec')),
width=width,
height=height,
video_codec=video_codec,
audio_codec=audio_codec,
container=data.get('container'),
file_size=parse_int(data.get('fileSize', data.get('sizeByte'))),
audio_tracks=audio_tracks,
@@ -425,6 +465,37 @@ class LeaderStorage(StorageProvider):
return None
def get_file_path_by_cid(self, cid: str) -> Optional[str]:
"""
Get the file path for a file by its CID.
Looks up file:{cid} in Redis and returns the path.
Tries 'path' field first, then falls back to 'filePath'.
This works for any file including poster images.
Returns the relative path if found, None otherwise.
"""
if not self.is_connected():
return None
try:
key = self._get_file_key(cid)
# Try 'path' field first (relative path)
path = self._client.hget(key, 'path')
if path:
return path
# Fall back to 'filePath' (full path from meta-sort)
file_path = self._client.hget(key, 'filePath')
if file_path:
# Convert absolute path to relative by removing /files/ prefix
if file_path.startswith('/files/'):
return file_path[7:] # Remove '/files/'
return file_path
return None
except Exception as e:
print(f"[LeaderStorage] Error getting path for CID {cid}: {e}")
return None
def get_video_count(self) -> int:
"""Get total number of videos."""
if not self.is_connected():
+28 -7
View File
@@ -187,20 +187,41 @@ class RedisStorage(StorageProvider):
tagline = data.get('tagline')
# Get video/audio codec and resolution from various field formats
# meta-sort stores these in fileinfo/streamdetails/video/0/... format
# New format: stream/0, stream/1, etc. as JSON strings
# Old format: fileinfo/streamdetails/video/0/... as flat keys
video_codec = data.get('videoCodec')
audio_codec = data.get('audioCodec')
width = parse_int(data.get('width'))
height = parse_int(data.get('height'))
# Try new stream/* JSON format first
if not video_codec or not width or not height or not audio_codec:
for i in range(20): # Check up to 20 streams
stream_key = f'stream/{i}'
stream_json = data.get(stream_key)
if not stream_json:
break
try:
stream = json.loads(stream_json) if isinstance(stream_json, str) else stream_json
stream_type = stream.get('type', '')
if stream_type == 'video' and not video_codec:
video_codec = stream.get('codec')
if not width:
width = parse_int(stream.get('width'))
if not height:
height = parse_int(stream.get('height'))
elif stream_type == 'audio' and not audio_codec:
audio_codec = stream.get('codec')
except (json.JSONDecodeError, TypeError):
pass
# Fall back to old flat key format
if not video_codec:
video_codec = data.get('fileinfo/streamdetails/video/0/codec')
audio_codec = data.get('audioCodec')
if not audio_codec:
audio_codec = data.get('fileinfo/streamdetails/audio/0/codec')
width = parse_int(data.get('width'))
if not width:
width = parse_int(data.get('fileinfo/streamdetails/video/0/width'))
height = parse_int(data.get('height'))
if not height:
height = parse_int(data.get('fileinfo/streamdetails/video/0/height'))