Enhancements
This commit is contained in:
1 parent
2698fe7114
commit
b3e3a97c2b
2 files changed
+71
-48
No files matched your search
@@ -111,15 +111,19 @@ def index():
|
|||||||
|
|
||||||
@app.route("/api/report")
|
@app.route("/api/report")
|
||||||
def report():
|
def report():
|
||||||
week_start, week_end, cutoff_utc = current_week()
|
week_start, week_end, _ = current_week() # This is the week range for display (e.g., Feb 15-21)
|
||||||
total_episodes = int(os.environ.get("TOTAL_EPISODES", 1155))
|
total_episodes = int(os.environ.get("TOTAL_EPISODES", 1155))
|
||||||
latest = get_latest_sunday()
|
latest = get_latest_sunday() # This is the cutoff for searching (e.g., Feb 21 16:00 UTC)
|
||||||
previous = get_previous_sunday()
|
previous = get_previous_sunday()
|
||||||
|
|
||||||
jellyfin.clear_debug_logs()
|
jellyfin.clear_debug_logs()
|
||||||
|
|
||||||
|
# Convert latest_sunday string back to datetime for cutoff
|
||||||
|
latest_sunday_dt = datetime.fromisoformat(latest.replace("Z", "+00:00"))
|
||||||
|
user_id = os.environ["JELLYFIN_USER_ID"]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ep_info = jellyfin.find_last_one_piece_before(cutoff_utc)
|
ep_info = jellyfin.find_last_one_piece_episode(latest_sunday_dt, user_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug_output = jellyfin.get_debug_logs()
|
debug_output = jellyfin.get_debug_logs()
|
||||||
return jsonify({"error": str(e), "debug": debug_output}), 502
|
return jsonify({"error": str(e), "debug": debug_output}), 502
|
||||||
|
|||||||
+64
-45
@@ -103,18 +103,23 @@ def extract_episode_number(name: str) -> int:
|
|||||||
return int(match.group(1))
|
return int(match.group(1))
|
||||||
|
|
||||||
|
|
||||||
def find_last_one_piece_before(cutoff_utc: datetime) -> dict:
|
def find_last_one_piece_episode(cutoff_utc: datetime, user_id: str) -> dict:
|
||||||
"""Return info about the last One Piece episode watched before cutoff_utc.
|
"""Find the last One Piece episode watched BEFORE cutoff_utc by the given user.
|
||||||
|
|
||||||
|
Filters:
|
||||||
|
1. Entry date must be strictly before cutoff_utc
|
||||||
|
2. UserId must match
|
||||||
|
3. Name must start with '{user} has finished playing One Piece'
|
||||||
|
4. Type must be VideoPlaybackStopped
|
||||||
|
|
||||||
|
Returns the most recent matching entry.
|
||||||
Returns: {episode_number, item_id, watched_at (ISO str), media_name}
|
Returns: {episode_number, item_id, watched_at (ISO str), media_name}
|
||||||
"""
|
"""
|
||||||
c = _cfg()
|
|
||||||
min_date = cutoff_utc - timedelta(days=14)
|
min_date = cutoff_utc - timedelta(days=14)
|
||||||
cutoff_utc_str = cutoff_utc.isoformat()
|
|
||||||
|
|
||||||
_debug.add(f"Searching for One Piece episodes before {cutoff_utc_str}")
|
_debug.add(f"Searching for One Piece episodes watched before: {cutoff_utc.isoformat()}")
|
||||||
_debug.add(f"User ID: {c['user']}")
|
_debug.add(f"User ID: {user_id}")
|
||||||
_debug.add(f"Search window: {min_date.isoformat()} to {cutoff_utc_str}")
|
_debug.add(f"Search window: {min_date.isoformat()} to {cutoff_utc.isoformat()}")
|
||||||
_debug.add("")
|
_debug.add("")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -124,47 +129,61 @@ def find_last_one_piece_before(cutoff_utc: datetime) -> dict:
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
_debug.add("")
|
_debug.add("")
|
||||||
one_piece_count = 0
|
|
||||||
|
# Filter: Type == VideoPlaybackStopped, UserId matches, Date before cutoff, Name pattern
|
||||||
|
candidates = []
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
entry_type = entry.get("Type")
|
if entry.get("Type") != "VideoPlaybackStopped":
|
||||||
is_playback = entry_type == "VideoPlaybackStopped"
|
continue
|
||||||
user_id = entry.get("UserId")
|
if entry.get("UserId") != user_id:
|
||||||
is_user = user_id == c["user"]
|
continue
|
||||||
name = entry.get("Name", "")
|
if not entry.get("Name", "").startswith(f"{user_id.split('@')[0] if '@' in user_id else 'pat'} has finished playing One Piece"):
|
||||||
is_one_piece = "One Piece" in name
|
# Try simple pattern: contains "has finished playing One Piece"
|
||||||
|
if "has finished playing One Piece" not in entry.get("Name", ""):
|
||||||
|
continue
|
||||||
|
|
||||||
if is_playback and is_user and is_one_piece:
|
date_str = entry.get("Date", "")
|
||||||
one_piece_count += 1
|
try:
|
||||||
date_str = entry.get("Date", "")
|
entry_dt = datetime.fromisoformat(date_str.replace("Z", "+00:00"))
|
||||||
try:
|
if entry_dt < cutoff_utc:
|
||||||
entry_dt = datetime.fromisoformat(date_str.replace("Z", "+00:00"))
|
candidates.append((entry_dt, entry))
|
||||||
is_before_cutoff = entry_dt < cutoff_utc
|
except ValueError:
|
||||||
|
continue
|
||||||
|
|
||||||
if is_before_cutoff:
|
if not candidates:
|
||||||
_debug.add(f"✓ Found One Piece entry: {name}")
|
_debug.add(f"✗ No matching One Piece episodes found before cutoff")
|
||||||
_debug.add(f" Date: {date_str} (before cutoff)")
|
raise RuntimeError("No One Piece episode found before the Sunday cutoff")
|
||||||
|
|
||||||
item_id = entry.get("ItemId")
|
# Sort by date descending (newest first) and take the first
|
||||||
if item_id:
|
candidates.sort(key=lambda x: x[0], reverse=True)
|
||||||
try:
|
latest_dt, latest_entry = candidates[0]
|
||||||
source = get_playback_info(item_id)
|
|
||||||
ep_num = extract_episode_number(source["Name"])
|
|
||||||
_debug.add(f" Extracted episode: {ep_num}")
|
|
||||||
_debug.add("")
|
|
||||||
return {
|
|
||||||
"episode_number": ep_num,
|
|
||||||
"item_id": item_id,
|
|
||||||
"watched_at": date_str,
|
|
||||||
"media_name": source["Name"],
|
|
||||||
}
|
|
||||||
except Exception as e:
|
|
||||||
_debug.add(f" ✗ Error extracting episode: {e}")
|
|
||||||
else:
|
|
||||||
_debug.add(f" No ItemId in entry")
|
|
||||||
except ValueError as ve:
|
|
||||||
_debug.add(f"✗ Failed to parse date {date_str}: {ve}")
|
|
||||||
|
|
||||||
_debug.add(f"✗ No One Piece episode found before cutoff")
|
name = latest_entry.get("Name", "")
|
||||||
_debug.add(f" Found {one_piece_count} One Piece entries total (some may be after cutoff)")
|
date_str = latest_entry.get("Date", "")
|
||||||
raise RuntimeError("No One Piece episode found before the Sunday cutoff in the last 14 days")
|
item_id = latest_entry.get("ItemId")
|
||||||
|
|
||||||
|
_debug.add(f"✓ Found {len(candidates)} matching One Piece entries")
|
||||||
|
_debug.add(f"✓ Latest: {name}")
|
||||||
|
_debug.add(f" Watched at: {date_str}")
|
||||||
|
_debug.add("")
|
||||||
|
|
||||||
|
if not item_id:
|
||||||
|
_debug.add(f"✗ No ItemId in entry")
|
||||||
|
raise RuntimeError("Entry has no ItemId")
|
||||||
|
|
||||||
|
try:
|
||||||
|
source = get_playback_info(item_id)
|
||||||
|
ep_num = extract_episode_number(source["Name"])
|
||||||
|
_debug.add(f"✓ Extracted episode: {ep_num}")
|
||||||
|
_debug.add("")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"episode_number": ep_num,
|
||||||
|
"item_id": item_id,
|
||||||
|
"watched_at": date_str,
|
||||||
|
"media_name": source["Name"],
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
_debug.add(f"✗ Error extracting episode: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
Reference in new issue
Block a user