Skip to content

Commit 77c70aa

Browse files
authored
Feat/batch match storyteller and Logging Standardization (#127)
* [Refactor] Standardize logging across all src/ modules * [Refactor] Complete logging standardization — final verification pass Finishes the repository-wide logging refactor across all src/ Python files. This commit covers Group 4 light-touch files and a comprehensive final verification sweep that caught and fixed remaining emoji/level mismatches. Changes: - storyteller_api.py: Full emoji pass, variable quoting - hardcover_client.py: Errors use empty, date-setting info calls use empty - hardcover_routes.py: Empty on all error/warning calls - config_loader.py: Fixed wrong emoji on two error-level calls - database_service.py: Full emoji pass - forge_service.py: Fixed 13 instances of wrong emoji on error/warning level - sync_manager.py: Fixed missing emojis, trailing period, daemon started - transcriber.py: Full error/warning emoji pass, fixed SMIL rejection warning - ebook_utils.py: Full emoji pass across all exception handlers - smil_extractor.py: Emoji fixes, variable quoting - cwa_client.py: Emoji fixes on remaining undecorated calls - kosync_server.py: Emoji fixes on all remaining error/warning calls - hardcover_sync_client.py: Fixed wrong emoji on warning level - migration_service.py: Emoji fixes on all error/warning calls - library_service.py, json_db.py, logging_utils.py: Emoji fixes Verification confirms zero bracket tags, zero level/emoji mismatches, all logger.warning start with the warning emoji, all logger.error start with the error emoji across the entire src/ directory. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * [Feature] Add checkmark badge on selected cards in batch match page * [Feature] Add Storyteller support to batch match (GET search, add_to_queue, process_queue tri-link logic) * [Feature] Unify card layout: resource-grid/resource-card system across match and batch match pages * Delete PLAN_OF_ACTION.md
1 parent d2613f6 commit 77c70aa

28 files changed

+760
-496
lines changed

src/api/api_clients.py

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,13 @@ def check_connection(self):
4949
return True
5050
else:
5151
# Keep failure visible as warning
52-
logger.warning(f"❌ Audiobookshelf Connection Failed: {r.status_code} - {sanitize_log_data(r.text)}")
52+
logger.error(f"❌ Audiobookshelf Connection Failed: {r.status_code} - {sanitize_log_data(r.text)}")
5353
return False
5454
except requests.exceptions.ConnectionError:
55-
logger.warning(f"❌ Could not connect to Audiobookshelf at {self.base_url}. Check URL and Docker Network.")
55+
logger.error(f"❌ Could not connect to Audiobookshelf at {self.base_url}Check URL and Docker Network")
5656
return False
5757
except Exception as e:
58-
logger.warning(f"❌ Audiobookshelf Error: {e}")
58+
logger.error(f"❌ Audiobookshelf Error: {e}")
5959
return False
6060

6161
def get_all_audiobooks(self):
@@ -71,7 +71,7 @@ def get_all_audiobooks(self):
7171
all_audiobooks.extend(r_items)
7272
return all_audiobooks
7373
except Exception as e:
74-
logger.error(f"Exception fetching audiobooks: {e}")
74+
logger.error(f"Exception fetching audiobooks: {e}")
7575
return []
7676

7777
def get_audiobooks_for_lib(self, lib: str):
@@ -81,7 +81,7 @@ def get_audiobooks_for_lib(self, lib: str):
8181
r_items = self.session.get(items_url, params=params, timeout=self.timeout)
8282
if r_items.status_code == 200:
8383
return r_items.json().get('results', [])
84-
logger.warning("⚠️ ABS - Failed to fetch audiobooks for library " + lib)
84+
logger.warning(f"⚠️ ABS - Failed to fetch audiobooks for library '{lib}'")
8585
return []
8686

8787
def get_audio_files(self, item_id):
@@ -106,7 +106,7 @@ def get_audio_files(self, item_id):
106106
return files
107107
return []
108108
except Exception as e:
109-
logger.error(f"Error getting audio files: {e}")
109+
logger.error(f"Error getting audio files: {e}")
110110
return []
111111

112112
def get_ebook_files(self, item_id):
@@ -133,7 +133,7 @@ def get_ebook_files(self, item_id):
133133
return ebook_files
134134
return []
135135
except Exception as e:
136-
logger.error(f"Error getting ebook files: {e}")
136+
logger.error(f"Error getting ebook files: {e}")
137137
return []
138138

139139
def search_ebooks(self, query):
@@ -144,7 +144,7 @@ def search_ebooks(self, query):
144144
# Get all libraries first
145145
r_libs = self.session.get(f"{self.base_url}/api/libraries", timeout=self.timeout)
146146
if r_libs.status_code != 200:
147-
logger.warning(f"ABS Search: Failed to get libraries (status {r_libs.status_code})")
147+
logger.warning(f"⚠️ ABS Search: Failed to get libraries (status {r_libs.status_code})")
148148
return []
149149

150150
libraries = r_libs.json().get('libraries', [])
@@ -194,11 +194,11 @@ def search_ebooks(self, query):
194194
else:
195195
logger.debug(f" No items found in library '{lib_name}'")
196196
else:
197-
logger.warning(f" Search failed for library '{lib_name}' (status {r.status_code})")
197+
logger.warning(f"⚠️ Search failed for library '{lib_name}' (status {r.status_code})")
198198

199199
return results
200200
except Exception as e:
201-
logger.error(f"Error searching ABS ebooks: {e}")
201+
logger.error(f"Error searching ABS ebooks: {e}")
202202
return []
203203

204204
def download_file(self, stream_url, output_path):
@@ -251,7 +251,7 @@ def update_ebook_progress(self, item_id, progress, location):
251251
"""
252252
# Validate required parameters
253253
if location is None:
254-
logger.error("Ebook location is required for progress updates")
254+
logger.error("Ebook location is required for progress updates")
255255
return False
256256

257257
# Ensure we use a float for the progress
@@ -268,10 +268,10 @@ def update_ebook_progress(self, item_id, progress, location):
268268
logger.debug(f"ABS ebook progress updated: {item_id} -> {progress} at location: {location[:50]}...")
269269
return True
270270
else:
271-
logger.error(f"ABS ebook update failed: {r.status_code} - {r.text}")
271+
logger.error(f"ABS ebook update failed: {r.status_code} - {r.text}")
272272
return False
273273
except Exception as e:
274-
logger.error(f"Failed to update ABS ebook progress: {e}")
274+
logger.error(f"Failed to update ABS ebook progress: {e}")
275275
return False
276276

277277
def update_progress(self, abs_id, timestamp, time_listened):
@@ -297,7 +297,7 @@ def update_progress(self, abs_id, timestamp, time_listened):
297297
def update_progress_using_payload(self, abs_id, payload: dict):
298298
session_id = self.create_session(abs_id)
299299
if not session_id:
300-
logger.error(f"Failed to create ABS session for item {abs_id}")
300+
logger.error(f"Failed to create ABS session for item '{abs_id}'")
301301
return {"success": False, "code": None, "reason": f"Failed to create ABS session for item {abs_id}"}
302302

303303
try:
@@ -308,13 +308,13 @@ def update_progress_using_payload(self, abs_id, payload: dict):
308308
self.close_session(session_id)
309309
return {"success": True, "code": r.status_code, "response": r.text}
310310
elif r.status_code == 404:
311-
logger.warning(f"ABS session not found (404): {session_id}")
311+
logger.warning(f"⚠️ ABS session not found (404): '{session_id}'")
312312
return {"success": False, "code": 404, "response": r.text}
313313
else:
314-
logger.error(f"ABS session sync failed: {r.status_code} - {r.text}")
314+
logger.error(f"ABS session sync failed: {r.status_code} - {r.text}")
315315
return {"success": False, "code": r.status_code, "response": r.text}
316316
except Exception as e:
317-
logger.error(f"Failed to sync ABS session progress: {e}")
317+
logger.error(f"Failed to sync ABS session progress: {e}")
318318
return {"success": False, "code": None, "reason": str(e)}
319319

320320
def get_all_progress_raw(self):
@@ -331,7 +331,7 @@ def get_all_progress_raw(self):
331331
return mapped_items
332332
elif r.status_code == 404:
333333
# Fallback to /api/me
334-
logger.debug("⚠️ /api/me/progress not found (404), falling back to /api/me")
334+
logger.warning("⚠️ /api/me/progress not found (404), falling back to /api/me")
335335
url_fallback = f"{self.base_url}/api/me"
336336
r2 = self.session.get(url_fallback, timeout=self.timeout)
337337
if r2.status_code == 200:
@@ -350,10 +350,10 @@ def get_all_progress_raw(self):
350350

351351
return {}
352352
except Exception as e:
353-
logger.error(f"Error fetching all ABS progress: {e}")
353+
logger.error(f"Error fetching all ABS progress: {e}")
354354
return {}
355355
except Exception as e:
356-
logger.error(f"Error fetching all ABS progress: {e}")
356+
logger.error(f"Error fetching all ABS progress: {e}")
357357
return {}
358358

359359
def get_in_progress(self, min_progress=0.01):
@@ -394,7 +394,7 @@ def get_in_progress(self, min_progress=0.01):
394394
})
395395
return active_items
396396
except Exception as e:
397-
logger.error(f"Error fetching ABS in-progress: {e}")
397+
logger.error(f"Error fetching ABS in-progress: {e}")
398398
return []
399399

400400
def create_session(self, abs_id):
@@ -422,9 +422,9 @@ def create_session(self, abs_id):
422422
logger.debug(f"Created new ABS session for item {abs_id}, id: {id}")
423423
return id
424424
else:
425-
logger.error(f"Failed to create ABS session: {r.status_code} - {r.text}")
425+
logger.error(f"Failed to create ABS session: {r.status_code} - {r.text}")
426426
except Exception as e:
427-
logger.error(f"Exception creating ABS session: {e}")
427+
logger.error(f"Exception creating ABS session: {e}")
428428
return None
429429

430430
def close_session(self, session_id):
@@ -474,7 +474,7 @@ def add_to_collection(self, item_id, collection_name=None):
474474
return True
475475
return False
476476
except Exception as e:
477-
logger.error(f"Error adding item to ABS collection: {e}")
477+
logger.error(f"Error adding item to ABS collection: {e}")
478478
return False
479479

480480
def remove_from_collection(self, item_id, collection_name="abs-kosync"):
@@ -484,29 +484,29 @@ def remove_from_collection(self, item_id, collection_name="abs-kosync"):
484484
collections_url = f"{self.base_url}/api/collections"
485485
r = self.session.get(collections_url)
486486
if r.status_code != 200:
487-
logger.warning(f"Failed to fetch collections to remove item {item_id}")
487+
logger.warning(f"⚠️ Failed to fetch collections to remove item '{item_id}'")
488488
return False
489489

490490
collections = r.json().get('collections', [])
491491
target_collection = next((c for c in collections if c.get('name') == collection_name), None)
492492

493493
if not target_collection:
494-
logger.warning(f"Collection '{collection_name}' not found, cannot remove item {item_id}")
494+
logger.warning(f"⚠️ Collection '{collection_name}' not found, cannot remove item '{item_id}'")
495495
return False
496496

497497
# Remove from collection
498498
remove_url = f"{self.base_url}/api/collections/{target_collection['id']}/book/{item_id}"
499499
r_remove = self.session.delete(remove_url)
500500

501501
if r_remove.status_code in [200, 201, 204]:
502-
logger.info(f"🗑️ Removed item {item_id} from ABS Collection: {collection_name}")
502+
logger.info(f"🗑️ Removed item '{item_id}' from ABS Collection: '{collection_name}'")
503503
return True
504504
else:
505-
logger.warning(f"Failed to remove item {item_id} from collection {collection_name}: {r_remove.status_code} - {r_remove.text}")
505+
logger.warning(f"⚠️ Failed to remove item '{item_id}' from collection '{collection_name}': {r_remove.status_code} - {r_remove.text}")
506506
return False
507507

508508
except Exception as e:
509-
logger.error(f"Error removing item from ABS collection: {e}")
509+
logger.error(f"Error removing item from ABS collection: {e}")
510510
return False
511511

512512
class KoSyncClient:
@@ -565,14 +565,14 @@ def check_connection(self):
565565
r = self.session.get(url_sync, headers=headers, timeout=5)
566566
if r.status_code == 200:
567567
return True
568-
logger.warning(f"❌ KoSync connection failed (Response: {r.status_code})")
568+
logger.error(f"❌ KoSync connection failed (Response: {r.status_code})")
569569
return False
570570
except Exception as e:
571571
if is_local:
572572
# Expected race condition during startup
573573
logger.debug(f"ℹ️ KoSync (Internal): Server check skipped during startup (will be ready shortly)")
574574
return True
575-
logger.warning(f"❌ KoSync Error: {e}")
575+
logger.error(f"❌ KoSync Error: {e}")
576576
return False
577577

578578
def get_progress(self, doc_id):
@@ -591,7 +591,7 @@ def get_progress(self, doc_id):
591591
xpath = data.get('progress')
592592
return pct, xpath
593593
except Exception as e:
594-
logger.error(f"Error fetching KoSync progress for doc {doc_id}: {e}")
594+
logger.error(f"Error fetching KoSync progress for doc '{doc_id}': {e}")
595595
pass
596596
return None, None
597597

@@ -622,9 +622,9 @@ def update_progress(self, doc_id, percentage, xpath=None):
622622
logger.debug(f" 📡 KoSync Updated: {percentage:.1%} with progress '{progress_val}' for doc {doc_id}")
623623
return True
624624
else:
625-
logger.error(f"Failed to update KoSync: {r.status_code} - {r.text}")
625+
logger.error(f"Failed to update KoSync: {r.status_code} - {r.text}")
626626
return False
627627
except Exception as e:
628-
logger.error(f"Failed to update KoSync: {e}")
628+
logger.error(f"Failed to update KoSync: {e}")
629629
return False
630630
# [END FILE]

0 commit comments

Comments
 (0)