Skip to content

Release 3.0.3: device-code login, Turbo/ad-free login, GQL search, HEVC setting, search & tofu fixes#707

Merged
anxdpanic merged 10 commits into
anxdpanic:masterfrom
einanderson:release/3.0.3
Jul 11, 2026
Merged

Release 3.0.3: device-code login, Turbo/ad-free login, GQL search, HEVC setting, search & tofu fixes#707
anxdpanic merged 10 commits into
anxdpanic:masterfrom
einanderson:release/3.0.3

Conversation

@einanderson

Copy link
Copy Markdown
Contributor

As invited by @MrSprigster in #706 — this is the full release pull request consolidating my open PRs and the community-fork fixes into one reviewed, testable state: 3.0.3.

What's included

From the open PRs (unchanged in substance):

New in this PR (from the community-fork betas people have been testing):

  • Second device-code login for ad-free playback (Turbo/subscriber): the private credentials used by usher get their own auto-refreshed token store; the existing manual private_oauth_token field keeps working as a fallback. Includes a revoke button. No refresh attempt for the default web client id (its tokens never expire; a refresh can only fail and spam the log).
  • Search fix: stopping playback that was started from search results no longer re-pops the keyboard or hangs at "Working…" (fork issue [v3.0.3-beta1] Search dialog doesn't exit cleanly (halts at "Working..." spinner) einanderson/twitch-for-kodi#1). The entered query is remembered in a window property and the previous results are re-rendered on the post-playback container reload; a deliberate new search still prompts.
  • Tofu fix: emoji/symbols the skin font cannot render (empty boxes) are stripped from list labels, plots and info text.
  • InputStream Adaptive modernisation: headers are passed via manifest_headers/stream_headers properties instead of the legacy URL pipe; chooser_resolution_max allows up to 1440p so Twitch 2K plays regardless of screen resolution; sub-720p variants are dropped from quality selection (Source/720p+/audio_only/Adaptive kept).
  • Manual token entry/revoke now go through the race-free token store too.

Behaviour changes to be aware of (deliberate, please push back if unwanted):

  • Defaults changed to video_quality=Adaptive + InputStream Adaptive enabled (this is the tested configuration and what makes HEVC/ad-handling work out of the box; existing installs keep their settings).
  • IRC chat integration removed (it only delegated to the external script.ircchat), along with the obsolete browser-based "Get OAuth token" flow and dead routes (edit_blacklist, collections). The "generate a new token" dialogs now point at the device-code login.
  • Saved per-channel default qualities below 720p are no longer offered (quality floor).

Translations

Only en_gb strings were added/changed — other locales are left for Weblate, per this repo's translation workflow.

Testing

  • The identical feature set has been running as the community-fork betas: @MrSprigster (beta4, daily use), @kuraikaze (LibreELEC x86, Kodi 22 alpha, Turbo — login, 1080p/1440p h264+h265 live & VODs, correct audio, ad-free), plus my two RPi4/LibreELEC boxes (Kodi 21) in daily use since early June.
  • This branch: kodi-addon-checker --branch omega passes (no problems), all modules compile, en_gb PO validated.
  • Delta vs the tested beta4 is minimal and reviewable per commit: the codec setting uses the Add a "Supported codecs" setting (HEVC / Enhanced Broadcasting) #705/Handling no username input when requested #141 mechanism instead of the fork's hardcoded library patch, plus three small review fixes (empty-bandwidth-match guard, token-hint wording, import dedup).

Coupling

Full disclosure, as on the previous PRs: developed with Claude (Anthropic's Claude Code) assisting; it is credited as co-author on the commits.

🤖 Generated with Claude Code

einanderson and others added 10 commits June 5, 2026 16:09
The implicit-grant link flow never returns a refresh token, so the
OAuth token has to be regenerated manually every few weeks/months.

This adds Twitch's Device Code Grant flow ("Login (device code)" under
Settings -> Login): the user authorizes once with a short code at
twitch.tv/activate, and the add-on then refreshes the access token
silently via the stored refresh token (on demand in api.Twitch and
proactively from the background service). The existing manual link
flow is kept as a fallback. No client secret is required (public
client, default Client-ID). New strings are English source strings,
translatable via Weblate.

Refs anxdpanic#701, anxdpanic#698
Adds a Supported codecs setting (Twitch default / H.265 (HEVC)) whose
value is passed to usher via the new supported_codecs parameter, so
users with hardware HEVC decode can receive Enhanced Broadcasting
variants (1440p+).

Default is "Twitch default" (no codec requested) -> behaviour unchanged.
The value is only passed when the installed script.module.python.twitch
accepts the parameter (feature-detected), so it degrades gracefully with
an older library.

Refs anxdpanic#699, anxdpanic#700
A silent refresh is impossible for a confidential client (Twitch replies
'missing client secret'). Detect it, stop retrying, and show a one-time
hint to set a public Client-ID; the manual login keeps working. Public
client ids are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds an optional Search backend using Twitch's GQL searchFor (the same
search twitch.tv uses) for proper fuzzy matching + relevance/live ranking,
which the Helix search/channels endpoint lacks. The result is mapped into
the existing Helix search shape so routes and converters are unchanged. A
new "Search method" setting selects it (default) or the Helix search, and
it falls back to Helix automatically if GQL errors/empties.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…cess lock

The rotating, single-use refresh token could be lost under Kodi's multi-process
settings race: several add-on processes (service + plugin calls) refreshing at
once and consuming the same single-use token, or one clobbering another's
settings.xml write from its in-memory cache. This surfaced as "Invalid refresh
token" and broke the silent auto-refresh after a while.

Keep the tokens in addon_data/oauth_tokens.json instead: read fresh on every
access, written atomically via os.replace, and guarded by a cross-process fcntl
lock around the whole refresh with a re-check inside the lock so a rotated token
is never consumed twice. Migrates once from the legacy settings (mirrored back
for backward compatibility) and preserves the confidential-client handling.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts:
#	resources/language/resource.language.en_gb/strings.po
# Conflicts:
#	resources/language/resource.language.en_gb/strings.po
…ter, ISA headers/1440p, cleanup

- Turbo/ad-free device login: second device-code login with the private
  client id, stored in its own race-free token store
  (oauth_private_tokens.json, atomic write + cross-process lock) with
  silent refresh; get_private_oauth_token() prefers the store and falls
  back to the manual private_oauth_token setting. Server-side revoke for
  both (routes/revoke_private_token.py, device_oauth.revoke_token).
  No refresh attempt for the kimne78 web client (confidential, tokens
  never expire) to avoid a doomed POST + warning per API call.
- Search: remember the query in a window property so the post-playback
  container reload re-renders the previous results instead of re-popping
  the keyboard or hanging at 'Working...' (fork issue anxdpanic#1); the search
  menus clear the property so a deliberate New Search still prompts.
- Strip emoji/symbols Kodi's skin font cannot render (tofu boxes) from
  list labels, plot, tagline and info dialog text.
- InputStream Adaptive: pass headers via manifest_headers/stream_headers
  properties instead of the legacy URL pipe; allow up to 1440p via
  chooser_resolution_max so Twitch 2K plays regardless of screen res;
  drop sub-720p variants from quality selection (Source/720p+/audio_only
  /Adaptive kept); default video_quality=Adaptive + IA enabled.
- Manual token entry / revoke now go through the race-free token store.
- Cleanup: remove IRC chat integration (script.ircchat), the obsolete
  browser-based 'Get OAuth token' flow (token_url, google_firebase) and
  dead routes (edit_blacklist, collections); raw-string regex fixes in
  common/kodi.py.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e login, dedup import

- get_video_for_quality: with sub-720p variants filtered out, the
  bandwidth-limited selection can end up with no candidate; guard the
  max() so it falls through to the quality dialog instead of raising
  ValueError.
- The 'generate a new token' dialogs still pointed at the removed
  'Get OAuth token' settings entry; point them at 'Login (device code)'.
- new_search: import search_results once.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MrSprigster

Copy link
Copy Markdown
Collaborator

@anxdpanic I've realised I only have access to this repository and not the script.python.twitch . Are you able to do the merge? Thanks.

@kuraikaze

Copy link
Copy Markdown

Can confirm community-fork beta has been running without issue for me for the last ~month. 👍

@anxdpanic

Copy link
Copy Markdown
Owner

@MrSprigster Just checked, you should have acccess on both

@anxdpanic
anxdpanic merged commit 6482bc1 into anxdpanic:master Jul 11, 2026
2 checks passed
@anxdpanic

Copy link
Copy Markdown
Owner

I am going to have to manually submit to the official repository. Can you guys try the release zip's and let me know if all is in order?

@kuraikaze

kuraikaze commented Jul 11, 2026

Copy link
Copy Markdown

With the release zips manually installed, a quick scoot around the updated features shows no issues for me.
(Auth/HEVC/Search/settings etc.)

@einanderson

Copy link
Copy Markdown
Contributor Author

Checked both release zips, everything looks in order to me. 👍

Packaging:

  • Zip contents are identical to the v3.0.3 tags in both repos (only repo-level files like .github, README, docs are stripped, as expected)
  • addon.xml versions are 3.0.3 in both zips, no stray __pycache__/CI leftovers
  • kodi-addon-checker --branch omega: no problems on either addon (only the known website-redirect warnings + the LICENSES/GPL-3.0-only filename warning)
  • py_compile clean across all Python files in both zips

Runtime (RPi4, LibreELEC 12.2, Kodi 21.3):

  • Installed both zips over an existing install — existing device-login tokens in addon_data were picked up without re-auth
  • Main menu, followed channels, GQL search (fuzzy results confirmed) all fine
  • Live playback via InputStream Adaptive: manifest parsed, stream plays (h264 1080p on a non-Enhanced-Broadcasting channel, which is the expected maximum there)
  • No tracebacks in the log

Thanks for getting this released!

@MrSprigster

Copy link
Copy Markdown
Collaborator

@MrSprigster Just checked, you should have acccess on both

Oh sorry, I just assumed I only had access to this one, my bad I should have checked. Thanks for sorting. I'll give the zips a test now.

@MrSprigster

Copy link
Copy Markdown
Collaborator

Yup, all good. Both zips install fine and the addon loads and works as expected for me.

@einanderson

Copy link
Copy Markdown
Contributor Author

@kuraikaze thanks for testing your log was very helpful!

@kuraikaze

Copy link
Copy Markdown

Thank you for putting in the effort, and making the time.
(and a little pat on the head for sidekick Claude too ✴️)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants