Add the cherrypick-log Claude Code skill (.claude/skills/cherrypick-log): a script that lists yuzono and @secozzi commits not yet picked into this repo, with its config, docs and tests. yuzono commits that only touch src/ or lib-multisrc/ are left out unless they change at least 5 modules.
Add cherrypick_log.md, generated against master and reviewed.
StringsTest covers both hex cases, paired and lone surrogate halves, other and malformed escapes being left untouched, and the escaped-backslash case the KDoc describes. CollectionsTest covers chunkedPairs on empty, even-length and odd-length lists and on a sequence.
Only tests are added, so nothing needs bumping or building.
fixUrl returned `http://example.comhttps://example.com/path` unchanged because any input starting with `http` was passed through as-is, so UrlUtilsTest's missing-protocol-prefix case failed. Both overloads now drop the leading origin when another `http(s)://` follows it directly. The match can't cross `/`, `?` or `#`, so a URL embedded in the path or query of a valid URL is left alone; new tests cover the two-parameter overload and both embedded cases.
Valid URLs come out unchanged, so nothing needs bumping or building.
core's UrlUtilsTest imported kotlin.test, but core only declares libs.junit, so :core:compileDebugUnitTestKotlin failed. lib/unpacker used kotlin-test-junit instead, and src/en/hanime configured a test/ source directory and hardcoded test dependencies although no tests were ever committed there.
Settle on JUnit, which NextJsTest (from upstream) and lib/megaextractor already use: switch UrlUtilsTest and the lib/unpacker tests to org.junit, declare libs.junit in lib/unpacker, and drop hanime's unused test setup. JUnit takes the assertion message first, so the 9 assertTrue/assertFalse calls in lib/unpacker that pass one have their arguments swapped.
Only test code and configuration change, so nothing needs bumping or building. Without the prefix, CI would bump every extension that depends on lib/unpacker.
`window.streams` is a JSON array, but each server URL was cut out with a regex and only `\/` and `&` were decoded, so any other escape was left in the URL. Parse the array into a DTO instead, which decodes every JSON escape. A missing or unparsable array still falls back to the plain master playlist.
Add String.unescapeUnicode() (decodes \uXXXX escapes) and chunkedPairs() (groups consecutive items into non-overlapping pairs, dropping an unpaired trailing item) to keiyoushi.utils, and use them in place of local implementations:
- unescapeUnicode: rezka, veranime, animeid
- chunkedPairs: nimegami
Output is unchanged for every well-formed input, so no version bumps or builds are needed.
decodeUnicodeEscape matched `uXXXX` without a backslash because the old pipeline stripped every backslash from the decrypted script first. Fix hikari (#963) replaced that with the WebView resolver, which returns the raw script, so `Français` became `Fran\çais`, and any label with `u` followed by four hex letters was corrupted. Use unescapeUnicode() instead, which only decodes real `\uXXXX` escapes.
No extension depends on lib/chillxextractor, so there is nothing to bump or build.
Cherry-picks from keiyoushi/extensions-source:
- Use CipherSource to decrypt responses by streaming (keiyoushi/extensions-source#10253): HLS segments are now decrypted as they stream through a new helper in `lib/hlssegment`, instead of loadingeach whole body with `bytes()`. Applied to AnimePahe and UniqueStream.
- Use core decodeHex/rc4/toHex instead of local copies (keiyoushi/extensions-source#15640): replaces hand-written hex/RC4 copies in 4 libs, the anikoto theme and 17 extensions with the shared `keiyoushi.utils` helpers. Output is identical for every valid input.
- Update auto-close messages in the issue moderator (keiyoushi/extensions-source#14845)
- Update issue request templates (keiyoushi/extensions-source#13281)
- Add *.jks to .gitignore (keiyoushi/extensions-source#9004)
- Only mirror main branch to Codeberg
Version bumps: AnimePahe 54 → 55, UniqueStream 8 → 9. The anikoto theme is not bumped since its output is unchanged. CI will auto-bump extensions that depend on the edited libs (`lib/m3u8server`, `lib/vidguardextractor`, `lib/vidsrcextractor`, `lib/googledriveepisodes`, `lib/hlssegment`).
This removes some usages of `ResponseBody.bytes()` that loads entire images into the memory for decryption.
Instead, we should use `CipherSource` provided by Okio to decrypt the response in a streaming fashion.
Lura Toon is not bumped because it has various issues outstanding.
Reference: https://square.github.io/okio/recipes/#encryption-and-decryption
commit 3fa42d95750f2b018d2bcc9e9b462b0523b6c378 from keiyoushi/extensions-source#10253
Replace hand-rolled hex decoding, RC4 and hex encoding with the shared keiyoushi.utils helpers, following keiyoushi/extensions-source#15640. The output is identical for every valid input, so no version bumps.
- decodeHex: lib/m3u8server, lib/vidguardextractor, animepahe, uniquestream, gotaku, tioanimeh
- rc4: anikototheme, lib/vidsrcextractor, aniwaves
- toHex: lib/googledriveepisodes, googledrive, missav, serienstream, hanime, hexawatch, kayoanime, kickassanime, funanimetv, tranimeizle, cycity, iyf, xfani
commit a96c552e11b22ef6bedb34b097de4a101e9455cf from keiyoushi/extensions-source#15640
* Jellyfin [ALL]: Fix 404 on season and episode lists
Build the /Shows/{id}/Seasons and /Shows/{id}/Episodes requests from the
configured server URL instead of resetting the path to "/", so servers
hosted under a sub-path (reverse proxy base URL) no longer return 404.
Also stop assuming the item id is at a fixed path index, request all
episodes when a series (not a season) is opened, and return an empty
episode list for box sets instead of requesting /Shows/boxSet/Episodes.
Closes#118
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Jellyfin [ALL]: Clean up unused code
- Remove never-set DeviceProfileDto.ProfileDto fields (`codec`, `conditions`) and the orphaned ProfileConditionDto
- Replace the `buildJsonObject` login body with a @Serializable LoginRequestDto
- Use `firstInstance` instead of `filterIsInstance().first()`
- Turn @Serializable DTOs and TranscodingInfo into regular classes (no data class features used)
- Cache the format() expression Regex instead of recompiling it for every episode
- Drop explicit `", "` joinToString separators, a redundant `else` branch in fetch_type, and trivial comments
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Jellyfin [ALL]: Expose media sources through lib 16 hosters
* Jellyfin [ALL]: Address review nits
- Fall back to the season id when a season has no series id, instead of
requesting Shows/null/Episodes (400). Jellyfin ignores the series
segment when seasonId is set.
- Map every ItemType explicitly when choosing the fetch type.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Jellyfin [ALL]: Allow logging in with an empty password
Jellyfin accounts can have no password, but the settings only logged in
when the password was non-blank, and clearing it logged out. Such users
never got a library list, so popular and latest failed with "Select
library in extension settings".
Pass the edited value to logIn directly: the preference change listener
runs before the new value is persisted.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Jellyfin [ALL]: Fix transcoded videos and WebView links
- Encode TranscodingInfo with the source's Json. It was written with the
default instance (videoBitrate) but read with the PascalCase one
(VideoBitrate), so resolveVideo always threw and every transcoded
quality failed to play.
- Open items in the Jellyfin web client from WebView. Anime and episode
urls are API endpoints that return JSON and need a token.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Jellyfin [ALL]: Seekable transcodes and clearer hoster names
- Ask Jellyfin for MPEG-TS HLS segments when transcoding to H.264. The
app's FFmpeg can't seek fMP4 HLS. Other codecs still get fMP4 segments,
which are now served as DASH over loopback with lib-hlsdash.
- Resolve the transcode of the requested media source rather than the
first one in the session.
- Name the hoster "Source" when an item has a single media source, since
that source is just named after the item, and drop the repeated
"Source -" prefix from the direct stream.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Update MoviesMod.kt
* Update cookie parsing to avoid null pointer exception
Handle potential null cookie parsing gracefully.
* Update build.gradle
* Refactor getHosterList and getDomainPrefSummary methods
* Rename sortVideos to sortVideosByPreference
* Trying to fis missing ep
Refactor getEpisodeList to use withContext for IO operations and update regex patterns for quality, season, and movie title extraction.
* Removed redundant comments
Removed redundant comments and clarified episode logic.
* Fis estension name
* Add newline at end of build.gradle file
* Seasons
* MoviesMod: Fix redirector bypass for new LinkPilot chain
The ?sid= redirector moved to a new script: the landing forms are now
form#lp-land / form#lp-s1-form, the final link uses ?lp_go= with the
cookie set via sc("name","value"), and the last hop redirects with
window.location.replace() instead of a meta refresh. Handle both the
old and new formats.
Also bump extVersionCode (master is already at 3) and use the named
Video constructor.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* MoviesMod: Drop unplayable driveseed buttons, label videos by button and file size
Resume Cloud, Direct Links and Telegram File were exposed as "Direct"
videos, but they are login/captcha/Telegram pages and never play. Only
the Instant Download buttons resolve to a stream. Name each video after
its button and take the size from the file info list, which also makes
the size sort preference work again.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* MoviesMod: Parse redirect targets more strictly
Read the meta refresh target case-insensitively instead of taking
everything after "url=", and accept either quote style for the href
and location.replace targets.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* MoviesMod: Extract driveseed Direct Links worker servers
Follow the Direct Links button to its server pages and expose the
workers.dev links. Those workers often fail with a Google Drive quota
error, so each link is probed with a one-byte range request and only
kept when it serves the file. Resume Cloud stays skipped: it serves a
zip, which the player can't play.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* MoviesMod: Group videos into a hoster per server and speed up resolving
Return one hoster per driveseed server (Instant Download, Instant
Download V2, Direct Server N) with its videos filled in, and title the
videos with just the resolution and file size. Movies list the same
file under two server buttons, so drop duplicate titles per hoster.
Resolving was ~10s per quality: the instant links were followed to the
slow video-seed.dev page, one button after another. Read the stream URL
from the redirect's Location header instead and resolve the buttons in
parallel.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* MoviesMod: Don't follow redirects when probing worker links
Over-quota workers answer a ranged GET with a 301 to driveseed's HTML
404 page. The probe followed it and saw a 200, so the player got the
HTML page ("unrecognized file format"). Probe without following
redirects and also reject text and JSON responses.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* MoviesMod: Drop the domain setting and resolve it from mmodlist
The custom domain preference was overridden by the redirect/mmodlist
resolution anyway. Take the domain from mmodlist, which always points
at the current one, check that it responds, and otherwise fall back to
wherever moviesmod.zone redirects.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* [temp] MoviesMod: Point mmodlist at the Bollywood list for a test build
Will be reverted once CI has built the APK.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Revert "[temp] MoviesMod: Point mmodlist at the Bollywood list for a test build"
This reverts commit 5801a7525; the test APK has been built.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: 7heMech <83923848+7heMech@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* MKissa [EN]: Resolve streams through the site's own app in a WebView
The stream query is signed and its reply encrypted with constants the site
reshuffles in its obfuscated bundle every few days, so the native port keeps
breaking. Let the site's app request the episode in a hidden WebView and read
the sourceUrls as it decrypts them, and drop the native crypto.
* MKissa [EN]: Fix Uni Cloudflare 403 and force MPEG-TS on Uni TikTok
The `cf` master only works through the player's own signing loader and answers
403 when fetched directly; `cfNative` carries the token in its URLs.
* MKissa [EN]: Wait out a throttled episode query before failing
* MKissa [EN]: Fail fast when a throttled query can't retry before the timeout
* MKissa [EN]: Honor disabled hosts before player fallback
Identify the most specific named host before checking its selection, and apply that selection before generic player or URL extraction. This keeps disabled Fm-Hls sources out of playback even with player enabled or older alternative-host settings, and prevents Ac-Hls from falling back to Ac.
Caused by: Dailymotion Extractor: Fix fMP4 audio and seeking with DASH (#1052)
Serve Dailymotion fMP4 variants with separate audio through the shared HLS-to-DASH server, preserving alternative audio choices, subtitles and request headers. Keep variants without separate audio on their original HLS streams to preserve embedded audio. Correct DASH seeking for short final segments and variable segment durations; reuse the shared server in HentaiHaven.
The PlaylistUtils ordering improvement was merged separately in #1114 with version bumps skipped. This commit contains no PlaylistUtils changes; normal CI dependency bumps apply to the 12 Dailymotion/hlsdash consumers.
Validation: FFmpeg/FFprobe fixtures, 611 embedded-audio packets retained, separate-audio playback, fixed/variable-duration seeking, audio selection, headers, subtitles, cached playlists, scoped compilation, formatting, and fresh PR CI/Inspector passed. Live/on-device playback remains untested.
Closes#969
Built on commit: 2a4e45ef4a
Serve Dailymotion fMP4 variants with separate audio through the shared HLS-to-DASH server, preserving alternative audio choices, subtitles and request headers. Keep variants without separate audio on their original HLS streams to preserve embedded audio. Correct DASH seeking for short final segments and variable segment durations; reuse the shared server in HentaiHaven.
The PlaylistUtils ordering improvement was merged separately in #1114 with version bumps skipped. This commit contains no PlaylistUtils changes; normal CI dependency bumps apply to the 12 Dailymotion/hlsdash consumers.
Validation: FFmpeg/FFprobe fixtures, 611 embedded-audio packets retained, separate-audio playback, fixed/variable-duration seeking, audio selection, headers, subtitles, cached playlists, scoped compilation, formatting, and fresh PR CI/Inspector passed. Live/on-device playback remains untested.
Closes#969
Prioritize DEFAULT and AUTOSELECT audio renditions within the selected group, and keep referenced-group renditions ahead of unreferenced fallbacks. Stable ordering fixtures and 42 cached HLS master playlists passed.
Version bumps are intentionally skipped; Dailymotion/hlsdash consumers will be released separately through #1052 after it is updated from master.
Caused by: FilmiFen [BG]: Add source and shared YouTube extractor (#1094)
* FilmiFen [BG]: Add lib 16 source
* FilmiFen: Add trailers and fix episode titles and BSE playback
* FilmiFen: Retry transient BSE challenge failures
* Add shared YouTube extractor with audio and codec labels
* Preserve PlaylistUtils compatibility and opt in to detailed HLS extraction
* FilmiFen: Remove repeated hoster names from quality labels
* fix(youtube): normalize JavaScript hex escapes in API responses
* fix(youtube): prefer direct streams to avoid HLS metadata crash
* feat(filmifen): prefer efficient YouTube codecs and show data usage
* fix(youtube): simplify estimated data usage labels
* fix(filmifen): hide automatically selected YouTube codecs
* fix(filmifen): simplify bandwidth labels and handle extraction failures
* fix(filmifen): use VOE MP4 only when HLS is unavailable
VOE's MP4 duplicates the top HLS variant, so FilmiFen now lists it only
as a fallback. Bandwidth labels are formatted with Locale.ROOT.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(voe): offer MP4 only as a fallback for all sources
Drops the opt-in parameter so VoeExtractor keeps its existing API, and
restores locale-aware bandwidth labels.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Built on commit: 82c55caa14
* FilmiFen [BG]: Add lib 16 source
* FilmiFen: Add trailers and fix episode titles and BSE playback
* FilmiFen: Retry transient BSE challenge failures
* Add shared YouTube extractor with audio and codec labels
* Preserve PlaylistUtils compatibility and opt in to detailed HLS extraction
* FilmiFen: Remove repeated hoster names from quality labels
* fix(youtube): normalize JavaScript hex escapes in API responses
* fix(youtube): prefer direct streams to avoid HLS metadata crash
* feat(filmifen): prefer efficient YouTube codecs and show data usage
* fix(youtube): simplify estimated data usage labels
* fix(filmifen): hide automatically selected YouTube codecs
* fix(filmifen): simplify bandwidth labels and handle extraction failures
* fix(filmifen): use VOE MP4 only when HLS is unavailable
VOE's MP4 duplicates the top HLS variant, so FilmiFen now lists it only
as a fallback. Bandwidth labels are formatted with Locale.ROOT.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(voe): offer MP4 only as a fallback for all sources
Drops the opt-in parameter so VoeExtractor keeps its existing API, and
restores locale-aware bandwidth labels.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
android.util.LruCache is a stub on the JVM, so building it in the
constructor made the extensions inspector crash while publishing.
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* AniDB [EN]: Switch to the Anilab2 app API and move to lib 16
anidb.app now redirects to the Anilab2 app landing page, so the HTML
scraper no longer returns anything. Use the endpoints the Anilab2 app
and its KYOTO Player companion call instead:
- catalogue/details: anilab2.amdapi.click/api (home, latest, search,
category, post)
- episodes/servers/streams: play.anidb.app/api
Existing library entries keep working: old "/anime/<slug>-<id>" URLs
map to post id = id + 1e9.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* AniDB [EN]: Accept legacy URLs with a trailing slash
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* AniDB [EN]: Stop paging past short pages and use fillermark
Every list endpoint returns 30 posts per page, so a shorter page is the
last one. Previously search requested one more page and showed
"No results found".
Drop the filler name-tag/hide preferences in favour of SEpisode.fillermark.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* AniDB [EN]: Use keiyoushi.network client helpers
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* AniDB [EN]: Name hosters by audio language
Servers are keyed by a language code (jpn/eng/chi/kor), so Korean and
Chinese titles showed two indistinguishable "SUB" hosters. Name them
Japanese/English/Chinese/Korean and let the preference pick any of them.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* AniDB [EN]: Compute the episode offset from numeric numbers only
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* AniDB [EN]: Drop the language from video names
The hoster already carries it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>