Skip to content

Commit d244d01

Browse files
tomballgithubclaude
andcommitted
Finish the upstream/dev merge: compact view on upstream's helpers, Song Count, Sheets timing
Merge repairs: - Restore Logger's terminal_only/log_only/write_styled_line, which the merge had stranded inside load_spotify_tracks_from_file(), and drop the leftover "self.mode = mode" (every Logger would have crashed) - Drop the duplicate COMPACT_VIEW default and restore the compact_view_heart theme colour Compact view, one print per event on upstream's helpers (print_compact_view_song, compact_view_song_text, compact_view_started_at, enter_compact_view_screen_mode): - Keeps the JMK/KEL tag, "Start/End notification sent" with the separator, the 09/27 timestamp, green/red Detected/Cleared lines, the red heart and the coloured shuffle icon - Removes the fork's duplicate banners and song lines and its Logger(mode="log") stdout swap; jmk_send -> initially_active; time_diff_str() now reads compact_view_started_at - JMK ntfy sends gated on JMK_MODE, since --compact-view no longer implies it - print_debug() no longer fails when stdout is not a Logger Playlist Cleared "Song Count" now reports count_played (songs actually played) instead of count_start, which a reported-name match or an override jump-starts to qty_start - one song used to read 3. sheets_helper logs how long each append request itself takes, and the idle time since the previous append, to pin down the slow first writes. Tests: harness and JMK tests use a real Logger instead of log_logger, the harness clock drives time.time() and stubs is_user_removed(), upstream's compact tests expect the 09/27 format, plus new tests for the Song Count and the append timing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 503665b commit d244d01

14 files changed

Lines changed: 906 additions & 241 deletions

‎RELEASE_NOTES.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ This is a high-level summary of the most important changes.
44

55
# Changes in 3.6 (TBD)
66

7-
Version **3.6** shows the **artist context** again for tracks played from an artist page with live activity and no longer reports **full plays as cut short** when the live feed keeps repeating an update. `--list-friends`, Doctor, setup and the monitoring name users by **display name and user ID**. It also fixes webhook alerts that were dropped when a custom header used a placeholder such as `{title}` and the alert text held emoji or non-Latin letters. The test suite no longer opens a Spotify login page when pytest runs with `-s`, no longer contacts Spotify and no longer fails depending on test order, on parallel `pytest -n auto` workers or with `pytest -v`.
7+
Version **3.6** shows the **artist context** again for tracks played from an artist page with live activity and no longer reports **full plays as cut short** when the live feed keeps repeating an update. A new **compact view** shows one line per song on screen while the log file keeps the full report. `--list-friends`, Doctor, setup and the monitoring name users by **display name and user ID**. It also fixes webhook alerts that were dropped when a custom header used a placeholder such as `{title}` and the alert text held emoji or non-Latin letters. The test suite no longer opens a Spotify login page when pytest runs with `-s`, no longer contacts Spotify and no longer fails depending on test order, on parallel `pytest -n auto` workers or with `pytest -v`.
88

99
**Features and improvements**:
1010

11+
- **NEW:** **Compact view** - `COMPACT_VIEW = True` or `--compact-view` shows **one line per song** during Friend Activity monitoring, with `[NN]` counting minutes since the active banner. Session changes, confirmed visibility loss and return plus actionable errors stay visible. Feed and metadata failures get separate recovery lines and repeated failures stay quiet until they change or recover. Line breaks in song fields become spaces. Full reports plus verbose and debug output go only to the log file. With logging disabled they are not kept. Alerts are unchanged (thanks [@tomballgithub](https://github.com/tomballgithub), [#66](https://github.com/misiektoja/spotify_monitor/pull/66))
1112
- **IMPROVE:** **Users are named, not only their IDs** - The users that only one Friend Activity backend lists at the end of `--list-friends`, the Doctor target check, the setup following check and the message for a target not found when monitoring starts now show **`display name (user ID)`**, or the user ID alone when both are the same. The live feed carries no names, so they are read from the Spotify profile
1213

1314
**Bug fixes**:

‎docs/configuration.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,7 @@ Parts with the same name mean the same thing in [spotify_profile_monitor](https:
671671
| `help_command` | The commands in the help examples |
672672
| `help_comment` | The `#` comment above each help example |
673673
| `help_default` | The `(default: ...)` notes |
674+
| `compact_view_timestamp` | The time at the start of each [compact view](usage.md#compact-view) line |
674675

675676
On Windows, install the optional `colorama` package for the best results in the classic Command Prompt. Windows Terminal needs nothing extra.
676677

‎docs/usage.md‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,22 @@ COLOR_THEME = { "track": "bright_magenta bold", "username": "green" }
326326

327327
See [Terminal Colours](configuration.md#terminal-colours) for every theme key and the accepted colour and style names.
328328

329+
<a id="compact-view"></a>
330+
### Compact View
331+
332+
Compact view shows one line per song, so the screen keeps a running list of what the friend played. Turn it on with `COMPACT_VIEW = True` or for one run with `--compact-view`. It applies to Friend Activity monitoring.
333+
334+
```text
335+
27 Sep, 17:10:18: *** Friend is Active...
336+
27 Sep, 17:10:18: [00] Sunday Bloody Sunday - U2 (War) [U2 Radio] (by Spotify)
337+
27 Sep, 17:14:41: [04] What's Up? - 4 Non Blondes (Bigger, Better, Faster, More !) [U2 Radio] (by Spotify)
338+
27 Sep, 17:19:02: *** Friend is Inactive...
339+
```
340+
341+
The startup summary and first full report print as usual. After that, only listening activity, track changes, visibility changes, actionable errors or warnings and recovery messages are shown. Repeated failures are reported only when they change or recover.
342+
343+
Everything else goes to the log file only. That covers the full song reports, session summaries, replies to [control signals](#signal-controls-macoslinuxunix) plus verbose and debug output. Email and webhook alerts are sent as usual. With logging disabled (`-d`) this output is not kept anywhere and the startup summary says so.
344+
329345
<a id="listing-mode"></a>
330346
## Listing Mode
331347

‎sheets_helper.py‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,11 @@ def _date_to_serial(iso_date_str):
251251
_MAX_WRITE_ATTEMPTS = 3
252252
_RETRY_BACKOFF_SECONDS = 2 # 2s before the 2nd attempt, 4s before the 3rd
253253

254+
# When the last append request finished, so each append's timing line can say how long the
255+
# connection sat idle before it - slow appends have been showing up mostly on the first write after
256+
# a quiet spell, and this is what shows whether that holds
257+
_last_append_finished_at = None
258+
254259

255260
def _is_retryable(e):
256261
"""Whether e looks like one of the transient blips Google's API explicitly expects
@@ -260,6 +265,12 @@ def _is_retryable(e):
260265
return status_code in _RETRYABLE_STATUS_CODES
261266

262267

268+
def _describe_idle(started_at):
269+
if _last_append_finished_at is None:
270+
return "first append this run"
271+
return f"{started_at - _last_append_finished_at:.0f}s since the previous append"
272+
273+
263274
def _write_row(spreadsheet_id, tab_name, row, client_file, token_file, on_checking=None, on_reauth_silent=None, on_reauth_required=None, debug_log=None):
264275
# A single batchUpdate call that appends the row and writes its cell formats atomically - one
265276
# API request instead of append_row() + a separate format() call. Sheets rows inherit the
@@ -285,11 +296,14 @@ def _write_row(spreadsheet_id, tab_name, row, client_file, token_file, on_checki
285296
# specific to this being the first write of a run) are retried inline with a short backoff
286297
# before falling back to the queue, so a 2-6 second Google-side hiccup resolves silently
287298
# instead of triggering a full queue+alert+email cycle.
299+
global _last_append_finished_at
288300
last_error = None
289301
for attempt in range(_MAX_WRITE_ATTEMPTS):
302+
append_started_at = None
290303
try:
291304
ws = _get_worksheet(spreadsheet_id, tab_name, client_file, token_file, on_checking, on_reauth_silent, on_reauth_required, debug_log)
292305
date_serial = _date_to_serial(row[0])
306+
append_started_at = time.time()
293307
ws.spreadsheet.batch_update({
294308
"requests": [
295309
{
@@ -312,9 +326,15 @@ def _write_row(spreadsheet_id, tab_name, row, client_file, token_file, on_checki
312326
},
313327
]
314328
})
329+
finished_at = time.time()
330+
if debug_log:
331+
debug_log(f"sheets_helper: append to tab '{tab_name}' took {finished_at - append_started_at:.2f}s (attempt {attempt + 1}, {_describe_idle(append_started_at)})")
332+
_last_append_finished_at = finished_at
315333
return True, None
316334
except Exception as e:
317335
last_error = e
336+
if debug_log and append_started_at is not None:
337+
debug_log(f"sheets_helper: append to tab '{tab_name}' failed after {time.time() - append_started_at:.2f}s (attempt {attempt + 1}, {_describe_idle(append_started_at)}): {type(e).__name__}")
318338
if attempt < _MAX_WRITE_ATTEMPTS - 1 and _is_retryable(e):
319339
delay = _RETRY_BACKOFF_SECONDS * (attempt + 1)
320340
print(f"* Google Sheet write to tab '{tab_name}' hit a transient error ({e}) - retrying in {delay}s (attempt {attempt + 2}/{_MAX_WRITE_ATTEMPTS})...")

0 commit comments

Comments
 (0)