Watch Later — user-curated antidote to algorithm feeds + MED-8 SB size cap
Cobb 2026-05-23: 'trending on youtube is cancer. only braindead zombies
will want what is trending on youtube.' So no Trending entry. Instead:
Watch Later — pure user-curated. Pin a video from any listing context
menu ('Add to Watch Later'); it persists to watch_later.json under
addon_data with full metadata {id, name, channel, duration, thumbnail}
so re-rendering the list doesn't need to re-fetch from rustypipe.
Newest first, dedupe on id, cap WATCH_LATER_MAX=500.
New ops + actions:
- _watch_later_directory (action=watch_later) — renders saved videos
with _add_video_items(in_watch_later=True). Each item gets a
'Remove from Watch Later' context entry; the Add entry is suppressed.
- _wl_add_action (action=wl_add) — RunPlugin-style handler that gets
the id from the URL, calls sidecar 'resolve' for fresh metadata
(falls back to id-only if resolve fails), saves into watch_later.json,
notification toast.
- _wl_remove_action (action=wl_remove) — symmetric remove. Triggers
Container.Refresh so the item disappears immediately from the list.
- Root menu gains a 'Watch Later (N)' entry, always present, with the
count when N>0.
- _add_video_items now accepts in_watch_later=bool and adds either Add
or Remove to the context menu accordingly.
MED-8 from the audit: SponsorBlock response capped at 1 MiB before
JSON parse. Normal SponsorBlock responses are tens of KB; a degenerate
prefix collision or malicious mirror returning gigabytes would
otherwise be deserialized into memory before we filter. resp.bytes()
+ length check + serde_json::from_slice.
Verified live via JSON-RPC (browse-only, Leia not interrupted):
- Empty WL → notification path
- Addons.ExecuteAddon wl_add for LTT 2T8x5antlnc → watch_later.json
has full metadata block
- watch_later dir lists 'The Internet was WRONG: Trump Phone is
Shipping · Linus Tech Tips · 14:08'
- Root menu shows 'Watch Later (1)' alongside Search + Play by URL +
Recent searches.
Saved feedback memory at memory/feedback_no_youtube_trending.md so
future me doesn't propose Trending again.
Addon v0.0.15.
This commit is contained in:
parent
f1c7264e75
commit
503dbef5df
3 changed files with 192 additions and 12 deletions
|
|
@ -63,7 +63,20 @@ pub(crate) async fn fetch(id: &str, categories: &[String]) -> anyhow::Result<ser
|
|||
anyhow::bail!("sponsorblock http {}", resp.status());
|
||||
}
|
||||
|
||||
let body: Vec<ApiResponse> = resp.json().await?;
|
||||
// Cap the response body at 1 MiB. A normal prefix collision returns
|
||||
// tens of KB; a degenerate response (or a hostile API mirror) returning
|
||||
// gigabytes would otherwise be deserialized straight into memory before
|
||||
// we filter to our target video_id.
|
||||
const SPONSORBLOCK_MAX_BYTES: usize = 1 * 1024 * 1024;
|
||||
let bytes = resp.bytes().await?;
|
||||
if bytes.len() > SPONSORBLOCK_MAX_BYTES {
|
||||
anyhow::bail!(
|
||||
"sponsorblock response too large: {} bytes (cap {})",
|
||||
bytes.len(),
|
||||
SPONSORBLOCK_MAX_BYTES
|
||||
);
|
||||
}
|
||||
let body: Vec<ApiResponse> = serde_json::from_slice(&bytes)?;
|
||||
|
||||
// Filter to the exact video id (the API returns all videos sharing the prefix).
|
||||
let segments: Vec<&ApiSegment> = body
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue