Commit Graph
57 Commits
Author SHA1 Message Date
kfj001 41723227c0 Slight copy update
CI / test (pull_request) Successful in 5m32s
2026-08-31 04:22:12 +00:00
robot 5da2003cd0 docs: draft PR description
CI / test (pull_request) Successful in 5m31s
2026-08-31 03:27:06 +00:00
robot 97abaf42d9 feat: add user instructions to viewer popup 2026-08-31 03:26:50 +00:00
kfj001 c366f0b8c4 Merge pull request 'Rebrand: rename 'goon' -> 'vidplex' + docs' (#6) from rebrand/vidplex-rename-kj into master
CI / test (push) Successful in 5m39s
Reviewed-on: http://192.168.1.74:30008/kfj001/goon_plugin/pulls/6
Reviewed-by: kfj001 <kfj001@gmail.com>
2026-08-30 19:19:26 -07:00
robot c826669c7d rename log prefixes: '[goon' -> '[vidplex' in runtime logs
CI / test (pull_request) Successful in 5m34s
2026-08-31 01:55:27 +00:00
kfj001 64d792632d Merge pull request 'refactor: decouple from site-specific CDN references' (#5) from feature/no_mention_of_pornhub into master
CI / test (push) Successful in 5m34s
Reviewed-on: http://192.168.1.74:30008/kfj001/goon_plugin/pulls/5
Reviewed-by: robot <robot@westerntechnologies.duckdns.org>
2026-08-30 17:07:51 -07:00
kfj001 3e02a6ae74 F1 BLOCKING — walk() cycle detection (src/viewer/index.js:161)
CI / test (pull_request) Successful in 5m41s
Added a per-tree WeakSet visited-guard so the probe terminates. The depth cap alone didn't stop the infinite recursion: window/_parent/_top/frames/_globalObject/_globalProxy are mutually-reachable circular Proxies, so Strategy H's window scan re-walked the same identities along exponentially many paths. The set is declared inside walk (not the outer function) so the separate player trees stay independent. This is what was hanging npm test (exit 124); it now completes in ~15s.
F2 SHOULD-FIX — doc/behavior mismatch (src/background/background.js:299-322)
Reworded the referer-capture comment block. It claimed the referer was read "via onBeforeSendHeaders, which sees the request headers," but the code uses onBeforeRequest + chrome.tabs.get (deriving the referer from the source tab's URL). Now states the actual mechanism and documents why onBeforeSendHeaders+extraHeaders was avoided (extraInfoSpec is rejected by some Chromium builds and fails the whole SW).
F3 SHOULD-FIX — leaked settings file
git rm --cached .claude/settings.local.json and added it to .gitignore. It carried machine-specific absolute paths (/Users/kyle/.claude/...).
F4 FYI — package-lock churn (package-lock.json)
Removed the spurious root "dependencies": { @rollup/rollup-darwin-arm64 } and restored the dev: true / optional: true flags on that platform package so it matches the rest of the @rollup/rollup-* siblings.
F5 FYI — real provider hostnames in test fixtures
Swapped phncdn.com→neutral example.net (registrable-domain sibling test) and thisvid.com→example.com in data_flow/hls_qa/simple_video/referer_proxy test files, rewording comments that named the real sites. src/ and __tests__/ now have zero phncdn/thisvid/pornhub references.
2026-08-30 21:56:05 +00:00
kfj001 ff463c107a fixes broken tests
CI / test (pull_request) Successful in 5m32s
2026-08-30 06:34:44 +00:00
kfj001 bd7d5bfcd0 removes unneeded dependency
CI / test (pull_request) Failing after 5m34s
2026-08-30 05:48:15 +00:00
kfj001 4357ce4094 Fixes issue with pornhub. Removes references.
CI / test (pull_request) Failing after 20s
2026-08-30 04:48:23 +00:00
kfj001 7b43d260a2 Additional fixes
CI / test (pull_request) Successful in 5m42s
2026-08-28 18:03:14 +00:00
kfj001 d3c8c85c58 removes thisvid reference from comment
CI / test (pull_request) Successful in 5m42s
2026-08-28 08:51:49 +00:00
kfj001 62d1244558 additional files 2026-08-28 08:51:27 +00:00
kfj001andClaude 0030d031f1 fix(scan): recover simple <video> detection site-agnostically
The no-mention-of-pornhub branch stopped finding plain <video> elements on
pages like thisvid.com. Two site-agnostic causes, both fixed without any
site-specific references:

1. Predicate over-rejection: isValidManifestUrl (and the nested isManifestUrl
   in m3u8DeepProbeFn) ran the placeholder/`%`/trailing-slash rejections
   BEFORE the concrete media signals. thisvid serves its direct MP4 WITH a
   trailing slash (.../14644093.mp4/?rnd=...), so `path.endsWith('/')`
   rejected a real, fetchable source. Concrete media signals (.mp4/.webm/.ogv/
   .mpd/.m4s/.m3u8/.hlsvod//hls/) now win outright, so a coincidental '%' or
   trailing slash never sinks a real source — while genuine route templates
   (/playlists/, /playlist/%1%/, /videos/{id}/) are still rejected.

2. Runtime cause on ad-iframe-heavy pages: scrapeTab ran only a MAIN-world
   scrape. A MAIN-world + allFrames injection can reject on pages with
   sandboxed/opaque-origin ad iframes, returning 0 videos even when a <video>
   is visible. scrapeTab now falls back to an isolated-world scrape (no `world`
   key — always permitted) when the MAIN-world run finds nothing. The per-frame
   reduction was extracted into a shared reduceScrapeFrames helper.

Adds __tests__/simple_video.test.mjs: a thisvid isValidManifestUrl battery
(trailing-slash MP4 accepted, templates still rejected, %2B/%2F tokens
preserved) plus a structural guard that scrapeTab keeps both a MAIN-world
primary and an isolated-world fallback.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-28 01:17:35 -07:00
kfj001 7139c5ea6f fix(scan): run deep probe/scraper in MAIN world; reject route-template "manifests"
CI / test (pull_request) Successful in 5m48s
The video-detection pipeline was finding nothing on pages that have a bare
<video> element. Two root causes:

1. world: 'MAIN' placement. The deep probe + scraper are injected with
   chrome.scripting.executeScript. Their code (and its own comments) requires
   the MAIN world to see page globals — window.Hls, per-<video> Hls instances,
   video._goon_hls_manifest, and window.__goon_plugin_data (written by the
   main-world interceptors). The calls were missing it, so every main-world
   strategy (A/A2/E/H) found 0. It was also briefly placed inside `target`,
   which chrome.scripting rejects ("Unexpected property: 'world'"); `world` is
   a sibling of `target` on ScriptInjection. Restore it as a sibling of target.

2. fake "manifest" classification. Strategy H was reporting 10 nav links /
   server-side route TEMPLATES as manifests — e.g. /playlists/,
   /playlists/liked/, /playlist/%1%/video/%2%/, /members/%ID%/playlists/ —
   because the old /playlist|/manifest substring check matches nav menus and
   leaves %1%/%ID%/%DIR% template placeholders intact. Those then became the
   stored "video" entries, drowning out the real element.

   isManifestUrl and isValidManifestUrl now reject:
     - dynamic route templates (%NAME% or {name} tokens), using a negative
       lookahead so genuine %-encoded tokens like %2B/%2F are preserved
       (the invariant the codebase explicitly protects),
     - plural collection paths (/playlists, /manifests),
     - trailing-slash directory listings.

   The 'World: ISOLATED' probe log was also misleading (typeof chrome is not a
   world discriminator — the probe provably runs in MAIN); replaced it.

Adds a regression test (hls_qa) reproducing thisvid's pageContext.langUrls
scenario: all 10 templates are rejected while a real .m3u8 carrying a %2B token
is still detected. 90/90 tests pass; 0 lint errors; build OK.
2026-08-25 20:27:14 -07:00
kfj001 e3b904783f fix(proxy): stop per-tab referer wipe and concurrent DNR rule race
CI / test (pull_request) Successful in 28s
Address robot's review on PR #5:

- [Blocking] 'goon_referers' is a host-keyed GLOBAL store and must outlive
  its capture tab; it was wrongly added to the per-tab onRemoved cleanup, so
  closing any tab wiped referers captured by still-open source tabs (-> 412).
  It is no longer removed on tab close. Stale referers are now pruned
  opportunistically in persistReferer via a per-host timestamp + TTL.

- [Should-fix] the DNR referer rule used a single shared REFERER_RULE_ID with
  a non-atomic check+update, so concurrent proxy fetches for two hosts could
  interleave and leave the wrong host's referer live. Each host now gets its
  own stable rule id (refererRuleIdFor) and the install+record is serialized
  per host via an async lock (refererRuleLocks).

- [Coverage] add __tests__/referer_proxy.test.mjs exercising the new
  referer-capture / proxy-host / onRemoved paths: closing a tab preserves
  goon_referers, two hosts proxied concurrently keep distinct per-host rules,
  and same-host proxy is idempotent.
2026-08-25 15:35:24 -07:00
kfj001 66c621825f refactor: decouple from site-specific CDN references
CI / test (pull_request) Successful in 37s
The extension had hard-coupled itself to one provider's CDN throughout
background.js and its consumers: a host allowlist, a static
declarativeNetRequest rule that forced a fixed site origin as the Referer,
site-named message types/functions, and illustrative comments naming the
site. This commit removes every reference so the code is generic and
provider-agnostic (and no longer names a specific site for reviewers).

What changed:

  - background.js
      * Dropped the PHNCDN_HOSTS allowlist; video-request capture is now
        host-agnostic (any CDN, driven by isVideoRequest / isHlsManifest).
      * Removed the static DNR rule that forced a fixed site origin as the
        Referer. Replaced with per-tab dynamic capture: an
        onBeforeSendHeaders listener captures the provider's own Referer for
        each video request the live page makes and stores it per CDN host
        (goon_referers). The proxy handler installs a DNR rule scoped to the
        requested host using that captured referer, so the provider's exact
        origin is extracted at runtime instead of hard-coded.
      * Generalized the reconstruction helpers: extractVideoId ->
        extractGroupKey (path-directory key, no /hls/videos/ assumption),
        buildManifestForVariant / reconstructManifestsFromSegments swap a
        segment filename for master.m3u8 dir-agnostically, freshLiveForVideo
        -> freshLiveForGroup, and the GOON_GET_PHNCDN_REQUESTS handler ->
        GOON_GET_VIDEO_REQUESTS. Resolver response key videoId -> groupKey
      * Reworded prose comments to describe behavior generically.

  - manifest.json
      * Added the extraHeaders permission so onBeforeSendHeaders can read the
        Referer header (needed for the dynamic capture above).

  - viewer.js / index.js (consumers)
      * Proxying decision now keys off a learned goon_proxy_hosts set
        (populated from a startup CORS probe) instead of hard-coded host
        substrings; removed the hard-coded CORS ping.
      * filterManifests / isValidManifestUrl generalized (kept the
        .m3u8 / .hlsvod / .ts behavior the tests assert); rank key
        phncdn_reconstructed -> hls_reconstructed; queryPhncdnRequests ->
        queryVideoRequests.

  - content.js, interceptors.js, and two test-prose strings: the illustrative
    "sites like <site>" comments generalized.

Verification: 83/83 tests pass, 0 lint errors. A repo-wide grep for the
previously-referenced host / site now returns no matches. The pre-existing
tsc errors in vite.config.ts are unrelated (present on the prior commit).

Note on the dynamic referer: it works while the source tab is open (it reads
that tab's real Referer); if the tab closed before capturing, the proxy falls
back to a host-derived origin, which a strict origin check may still reject --
the tradeoff of not hard-coding the site.
2026-08-25 02:26:16 -07:00
kfj001 dc2c8092f0 Merge pull request 'Feature/rebrand' (#4) from feature/rebrand into master
CI / test (push) Successful in 27s
Reviewed-on: http://192.168.1.74:30008/kfj001/goon_plugin/pulls/4
Reviewed-by: robot <robot@westerntechnologies.duckdns.org>
2026-08-24 18:42:42 -07:00
kfj001 cb607306bc Reverts plugin changes unrelated to rebranding efforts.
CI / test (pull_request) Successful in 26s
2026-08-24 23:58:57 +00:00
kfj001 7d56e836c9 minor changes to reccomended plugins
CI / test (pull_request) Successful in 25s
2026-08-24 22:53:13 +00:00
Your Name 602d6b774b more changes 2026-08-24 22:43:05 +00:00
Your Name a54d094bef work complete from phase 1 rebrand 2026-08-24 22:42:29 +00:00
kfj001 9420bce9c1 Merge pull request 'fix(tests): stop hls_qa deep-probe suite hanging under jsdom (test-only)' (#3) from fix/jsdom-cycle-hang-hls-qa into master
CI / test (push) Successful in 36s
Reviewed-on: http://192.168.1.74:30008/kfj001/goon_plugin/pulls/3
Reviewed-by: kfj001 <kfj001@gmail.com>
2026-08-24 10:28:08 -07:00
robot fd8c36d72e fix(tests): stop hls_qa deep-probe suite hanging under jsdom
CI / test (pull_request) Successful in 1m56s
CI times out on the 7 "HLS QA: Deep probe strategies" tests. Root cause
is a jsdom-only artifact, not a production bug: jsdom exposes the
self-referential cyclic globals (_globalObject/_globalProxy/_top/_parent/
window/self/top/parent/frames) as ENUMERABLE own-props on the window.
Strategy H in m3u8DeepProbeFn() runs Object.keys(window) and a no-
visited-set walk() over each, which explodes to O(204^5) ≈ 3.5e11 ops and
never terminates within the depth-5 cap, so the whole suite hangs forever.

A real Chrome MAIN-world window does NOT expose those keys as enumerable
own-props, so this is purely a test-environment mismatch. The fix is
test-only: sanitizeJsdomWinForProbe() marks the jsdom cyclic globals
non-enumerable in runProbeInWin() before eval, mirroring a real page.
No production/underlying source (src/viewer/index.js) is modified.

Local (Node 22.22.3 / Linux == CI ubuntu-latest + Node 22):
before: npm test hangs indefinitely (no Results line; CI job killed)
after:  npm run build && npm test -> 83/83 passed in ~12.5s
2026-08-24 05:10:56 +00:00
kfj001 7336643ea4 Merge pull request 'feat: full HLS.js support — detection via interceptors + deep probe, playback via hls.js in viewer' (#2) from hls-fix into master
CI / test (push) Failing after 16m10s
Reviewed-on: http://192.168.1.74:30008/kfj001/goon_plugin/pulls/2
Reviewed-by: kfj001 <kfj001@gmail.com>
2026-08-23 18:22:41 -07:00
kfj001 63e5c600dc Adds step to generate artifacts in ci/cd env.
CI / test (pull_request) Successful in 11m30s
2026-08-24 01:10:08 +00:00
kfj001 b6a11d9e46 fixes broken unit test
CI / test (pull_request) Failing after 11m2s
2026-08-23 17:38:14 -07:00
kfj001 c9f49b58d8 Working on pornhub
CI / test (pull_request) Failing after 10m34s
2026-08-20 10:59:05 -07:00
kfj001 001cf146ee Attempted fix at pornhub video
CI / test (pull_request) Failing after 10m39s
2026-08-16 23:00:47 -07:00
kfj001 b234c8dcae fix: HLS playback — CORS proxy for phncdn.com + diagnostic logging
Problem: Even after fixing the hls.js file naming (was 'hls.min.js', now
'hls.js'), videos don't play in the viewer. Likely root cause is CORS
blocking chrome-extension:// requests to phncdn.com CDN URLs that lack
CORS headers for extension origins.

Solution — two-layer fix:

1. Service worker proxy (background.js):
   - New GOON_PROXY_FETCH handler fetches any URL via native fetch()
     (no CORS restrictions in the service worker)
   - Returns base64-encoded response data to the viewer

2. Custom HLS loader (viewer/viewer.js):
   - HlsLoader implements hls.js Loader interface
   - For phncdn.com/pornhubcdn URLs: proxies via GOON_PROXY_FETCH
   - For all other URLs: uses native XHR (bypasses proxy overhead)
   - Config passed to hls.js only when manifest URL needs proxying

3. Diagnostics (viewer/viewer.js):
   - CORS check at page load for phncdn.com and per-video URL
   - Full storage dump of video entries in console
   - Manifest URL logging on each HLS load attempt
   - Proxy activation logging for debugging
2026-08-16 16:42:12 -07:00
kfj001 fa0a0d76cd fix: rename hls.min.js -> hls.js to match vite build output
The vite config outputs 'hls.js' but manifest.json and viewer.js
both referenced 'hls.min.js', causing chrome.runtime.getURL() to
return a 404 — triggering 'HLS player unavailable'.

- Update web_accessible_resources entry in manifest.json
- Update loadHlsJs() chrome.runtime.getURL reference
- Add debug log of manifest URL being loaded for diagnostics
2026-08-16 16:28:55 -07:00
kfj001 509948def1 feat: deep probe strategies G (non-enumerable/Symbol) and H (full window scan)
Strategy G — Independent non-enumerable + Symbol property detection on video elements.
Uses Object.getOwnPropertyNames/Symbols to catch properties hidden by enumerable:false or Symbol keys.
Walks nested objects for URL/levels/config signatures matching HLS instance heuristics.

Strategy H — Full window global enumeration with player-like key filtering.
Catches previously-unknown globals the player wrapper exposes internally.

Content script bridge — merge content-level intercepted manifests into
window.__goon_plugin_data so both interceptors and executeScript share findings.

Add phncdn_reconstructed to dedup priority ranking.
2026-08-16 16:22:07 -07:00
kfj001 877feec731 feat: Strategy 8 — enhance phncdn.com network fallback detection
- Log ALL phncdn.com requests (not just .m3u8) to chrome.storage.local
- Reconstruct manifest URLs from segment URL patterns (/videos/{id}/playlist.m3u8)
- Add GOON_GET_PHNCDN_REQUESTS message handler for popup consumption
- Add queryPhncdnRequests() consumer in viewer/index.js
- Integrate reconstructed manifests into scan pipeline (step 1.6)
2026-08-16 16:17:29 -07:00
robot a1f4d2241b fix: vendor hls.js locally (CSP) and handle null executeScript results
CI / test (pull_request) Failing after 24s
Two fixes addressing kfj001 review #37 on commit b19035a:

1. Vendor hls.js bundle locally — chrome.runtime.getURL('hls.min.js')
   instead of CDN, bypassing site CSP (script-src 'self') blocks.
   Added hls.min.js to vite.config.ts entry points, manifest web_accessible_resources.

2. Handle null entries in executeScript results — destroyed frames
   return null when allFrames:true, causing 'Cannot read properties of
   null (reading 'result')' in probeHlsManifests() and scrapeTab().
   Added null guards before accessing .result.

83/83 tests pass. Build: 10 modules, 413KB hls bundle.
2026-08-13 08:55:04 +00:00
robot b19035ad29 fix: capture HLS segment playback state — prevent fragmented / lost overlay states
CI / test (pull_request) Successful in 22s
Bug fixes:
- FRAG_LOADING: stop updating lastActivity and re-rendering during active
  playback. It fires continuously as hls.js proactively fetches future
  segments, causing overlay flickering between buffering/playing.
- BUFFER_RESET: stop clearing segmentsLoaded. The event fires during
  quality switches when hls.js flushes and rebuilds the MediaSource buffer,
  but segments were already played. Clearing the counter made the overlay
  show '0 seg' mid-playback.
- FRAG_BUFFERED: add bufferedAhead update immediately after a fragment is
  buffered, instead of waiting for the next 1s monitor tick.
- LEVEL_SWITCHED: only set phase='switching' when buffer is low (< 2s).
  With meaningful buffer the switch is instant (already-buffered segments),
  so skip the intermediate state to avoid panels getting stuck.
- Buffer monitor: add change-detection so renderPanelState only fires when
  phase, segments, or quality actually changed — not every second.
- wireVideoEvents: add 'ended' event handler for completeness.
2026-08-13 06:29:22 +00:00
robot 8e9f7f96f1 refactor: audit fixes — clean up bugs, dead code, and type mismatches
CI / test (pull_request) Successful in 23s
- viewer.js: remove undefined state.segmentsBuffered assignment in BUFFER_RESET
- viewer.js: add missing 'switching' and 'ended' phases to PHASE_ICONS
- index.js: remove redundant Strategy B3 (duplicated B1 video-element walk)
- index.js: filter standard <video> DOM attributes from custom-property scans
  (m3u8DeepProbeFn B1 and scrapeFn Priority 3) to avoid iterating built-in
  properties that can never contain HLS data
- background.js: remove unconditional return true (handlers are synchronous)
  and remove dead error-response for unknown message types
- types.ts: align MediaType union ('direct' | 'hls') with actual runtime
  value used in code ('video' | 'hls')
- package.json: remove hls.js from dependencies (loaded from CDN at runtime,
  never imported as an npm module)
2026-08-13 04:59:59 +00:00
Hermes QA ae8608148d refactor: clean up and refactor PR code
CI / test (pull_request) Successful in 23s
- Refactor duplicated video event listener boilerplate in wireVideoEvents()
  into onVideoEvent() helper (viewer.js: -57 lines)
- Fix 3 ESLint no-unused-vars warnings (bare catch instead of unused _e)
- Fix 1 additional no-unused-vars: unused 'data' param in MANIFEST_LOADED
- Remove dead 'Hls.cast' entry from playerRank map (no strategy produces it)
- Remove deprecated .eslintignore file (ESLint v9 uses flat config only)
- Add __tests__/ to ESLint ignores in flat config

Net: -20 lines (46 ins, 66 del). 83/83 tests pass, lint clean (0 warnings)
2026-08-13 02:58:41 +00:00
robot e11be9a20a fix: HLS playback tracking and detection fallback for sandboxed iframes
CI / test (pull_request) Successful in 23s
Viewer fixes (6):
- FRAG_LOADING: only set buffering phase when video is actually stalled
  (paused or readyState < HAVE_FUTURE_DATA), prevents overlay flicker
- FRAG_BUFFERED: allow playing transition from any phase except error,
  require readyState >= 3 and video not paused
- Add FRAG_DECRYPTED, FRAG_PARSING_INIT_SEGMENT, FRAG_PARSING_USERDATA
  event tracking for full fragment pipeline visibility
- BUFFER_RESET: also reset segmentsBuffered counter (was missing)
- LEVEL_SWITCHED: set phase to 'switching' for accurate UI feedback
- Fatal network errors: track in segmentsFailed counter
- Add ENDLIST event handler for stream completion detection

Detection fixes:
- Add filterManifests(): prefer .m3u8 manifest URLs over .ts segments,
  reconstruct manifest URL from segment paths when needed
- Add fallback in scanVideos(): when scrapeFn returns no visible <video>
  elements (sandboxed iframe), create video entries from intercepted
  manifest data. Fixes '0 videos detected' issue on Pornhub and similar
  sites where the video player is in an inaccessible iframe.
2026-08-12 23:51:32 +00:00
robot 3cf402d3c7 fix: Hls.cast dead code, double-patch interceptors, manifest URL patterns
CI / test (pull_request) Successful in 32s
Hls.cast() is a TypeScript identity cast in hls.js — returns input unchanged,
NOT a reverse-lookup. Replaced with scanning video element properties for
HLS instance references real players store as custom properties.

Fixed double-patching bug in interceptors.js and expanded URL pattern
matching to cover /hls/, /playlist/, /manifest/, .hlsvod paths.

83/83 tests pass, clean build (9 modules).
2026-08-12 21:21:03 +00:00
robot 542c5786be feat: add HLS playback support with hls.js and modular viewer architecture
CI / test (pull_request) Successful in 23s
This PR adds end-to-end HLS stream detection, interception, and playback
to the viewer. The following root causes from the QA audit are fixed:

- Restore dropped HLS detection strategies (6-strategy per-tab query)
- Add deep-probe scanning for config globals and iframe manifests
- Add standalone interceptors.js for CSP-compliant runtime injection
- Fix viewer.js string entry handling for legacy storage entries
- Fix manifest.json web_accessible_resources for interceptors.js
- Disable modulePreload polyfill for Chrome MV3 compatibility
- Run deep probe and scraper in MAIN world for page global access
- Fallback to src as HLS manifest when hlsManifest field is missing

The viewer.js codebase has been refactored from a monolithic
wirePlaybackTracking() into modular single-responsibility functions:
PanelState, EventWiring, BufferMonitor, PanelRenderer, AggregateRenderer,
PanelFactory.

Additionally:
- Remove debug console.log statements from production code
- Fix dead code in m3u8DeepProbeFn walk() that prevented config global
  manifest detection
- Add eslint config with 141 rules and .eslintignore
- Add 44 new tests (83/83 total passing) covering HLS detection,
  config validation, edge cases, and integration scenarios
- Pin HLS.js CDN version to 1.5.17 (not floating/latest)
- Add grid-optimized HLS config with 10s buffer cap
- Add cleanup hooks for HLS instance destruction on page unload

Changed files (18):
- src/viewer/viewer.js (+834)
- src/viewer/index.js (+870)
- src/viewer/viewer.test.js (+976, new)
- src/viewer/index.test.js (+481, new)
- src/inject/interceptors.js (+169, new)
- src/content/content.js (+139)
- __tests__/hls_qa.test.mjs (+1168, new)
- manifest.json (+6)
- vite.config.ts (+5)
- __tests__/run.mjs (+2)
- __tests__/config_validation.test.mjs (+102, new)
- eslint.config.js (+24, new)
- .eslintignore (+1, new)
- QA_REPORT_HLS.md (+160, new)
- __tests__/data_flow.test.mjs (+/-5)
- __tests__/schema.test.mjs (+/-5)
- __tests__/viewer_integration.test.mjs (+/-4)
- src/background/background.js (-2)
2026-08-12 14:13:55 +00:00
kfj001 7416ae8ff9 Merge pull request 'feat: add HLS playback support with hls.js' (#1) from robot/goon_plugin:master into master
CI / test (push) Successful in 24s
Reviewed-on: http://192.168.1.74:30008/kfj001/goon_plugin/pulls/1
2026-08-10 20:50:43 -07:00
robot c59c96ce19 fix: integrate child task improvements (poster rendering, HLS cleanup, hls.js dependency)
CI / test (pull_request) Canceled after 0s
2026-08-10 22:42:48 +00:00
hermes e17b228ee0 fix: redesign HLS detection with 6-strategy per-tab query
CI / test (pull_request) Canceled after 0s
- Query HLS data structures directly from page JS state per tab
- Strategies: video element HLS instances, window-level player vars,
  intercepted data, inline scripts, global config objects, content script
- Fixed merge logic: index.js now correctly processes interceptedManifests
  and hlsQueryResults instead of non-existent playerData
- Skip blob: URLs in DOM scan (HLS-internal, can't be played directly)
- Only attach HLS manifest when actually detected for that tab
2026-08-10 20:39:49 +00:00
hermes c22631d1f1 fix: real-time HLS interception via content script (architectural overhaul)
CI / test (pull_request) Canceled after 0s
Previous approach (DOM snapshot via executeScript) failed on Pornhub because:
- Video player loads asynchronously via JavaScript
- HLS manifest arrives via XHR/fetch AFTER page render
- <video> element only shows blob: URL, not the actual manifest

New approach:
- Content script injects interceptor into MAIN world at document_start
- Interceptor patches XMLHttpRequest and fetch() to capture .m3u8 URLs
- Periodic DOM scans detect HLS player instances on <video> elements
- Global config object scanning for embedded stream URLs
- Popup queries content script via chrome.tabs.sendMessage for real-time data
- If no DOM videos found but content script has data, create entries from intercepted sources

Changes:
- content.js: Full rewrite with main-world injection + XHR/fetch interception
- index.js: Query content scripts via messages, merge with DOM snapshot
- manifest.json: all_frames + document_start for early injection
2026-08-10 18:53:27 +00:00
hermes db52db7799 fix: add HLS manifest extraction to scrapeFn (3 strategies)
CI / test (pull_request) Canceled after 0s
- Strategy 1: scan inline <script> blocks for .m3u8 URLs (skip subtitles/captions)
- Strategy 2: check video element HLS player instances (hlsInstance, _hls)
- Strategy 3: probe common global config objects (hlsConfig, playerConfig, etc.)
- Storage items now include hlsManifest and mediaType fields
- When HLS detected and src is blob:/empty, promote manifest URL to primary
- Backward compatible: direct MP4 entries unaffected
2026-08-10 17:07:55 +00:00
hermes 90c3425200 feat: add HLS playback support with hls.js
CI / test (pull_request) Canceled after 0s
- viewer.js: dynamic hls.js loading, HLS-aware panel creation, error handling
- schema.json: hlsManifest and mediaType fields (optional, backward compatible)
- types.ts: VideoEntry interface with MediaType type
- isHls() null guard fix
- tests: 39 tests (schema, viewer units, data flow, integration)
- CI: GitHub/Gitea Actions workflow (npm test on push/PR)
- deps: ajv, ajv-formats, jsdom for testing
2026-08-10 06:18:27 +00:00
Your Name baa72a4c33 Fixes css reference issue 2026-07-17 22:37:47 +00:00
kfj001 72d0a2dfe4 Updated gitignore 2026-06-08 20:13:51 +00:00
kfj001andClaude Opus 4.8 6122f67df3 Untrack icons/ — they are build artifacts, not source
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 20:13:19 +00:00
kfj001 93879bc8f7 Updates extensions in workspace. Alters plugin to scrape for NxN tabs for videos to display in the matrix. 2026-06-08 08:40:06 +00:00