Skip to content

Feature/eventsub definition generator - #137

Merged
kanimaru merged 12 commits into
masterfrom
feature/eventsub-definition-generator
Sep 4, 2026
Merged

Feature/eventsub definition generator#137
kanimaru merged 12 commits into
masterfrom
feature/eventsub-definition-generator

Conversation

@Temptica

@Temptica Temptica commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

Just like TwitcherSharp, I added a code generator that will now generate the Static definitions for us, so we no longer need to manually check and update them constantly.

Adds TwitchEventsubDefinitionParser/Generator, mirroring the approach
already used for the Eventsub payload classes: fetches and regex-parses
the eventsub-subscription-types docs page (there's no swagger/openapi
source for it, unlike eventsub-reference), cross-referencing condition
fields against the already-parsed eventsub swagger schemas via
TwitchAPIParser instead of re-parsing the reference page.

Wired into generate_all_apis.tscn as a third "Generate Definitions"
column, reusing the existing Eventsub SwaggerParser node to avoid a
duplicate fetch.

Regenerated twitch_eventsub_definition.gd against live Twitch docs, which
picks up the same 5 new subscription types found on the C# side
(AutomodMessageHoldV2, AutomodMessageUpdateV2, ChannelBitsUse,
ChannelChannelPointsAutomaticRewardRedemptionAddV2,
ChannelCustomPowerUpRedemptionAdd) plus a couple of condition/version
corrections. Verified the data matches the C# TwitcherSharp generator's
output exactly.

Also switches response_script resolution from a compile-time class_name
reference to a runtime load() by script name: with a bare identifier, a
definition for a script that doesn't exist yet in generated_eventsub
would fail the whole file to parse, taking every other definition down
with it - a real risk given generated_eventsub isn't reliably kept in
sync with Twitch. load() degrades to a null response_script for that one
entry with a logged error instead.
For each entry in OVERRIDES (e.g. channel.hype_train.begin -> hype_train_begin),
also emit a second "*Legacy" Type + static var pointing at the pre-override,
mechanically-derived script name (e.g. CHANNEL_HYPE_TRAIN_BEGIN_LEGACY ->
channel_hype_train_begin). Anyone already depending on that name keeps working;
it's marked deprecated (## @deprecated: ...) and shouldn't be used going forward.

response_script for a legacy alias whose file genuinely doesn't exist (most of
them, since the override exists precisely because the mechanical name was
wrong) degrades to null with a logged load error rather than breaking the
whole file - verified end to end.
@Temptica Temptica self-assigned this Aug 22, 2026
@Temptica
Temptica requested a review from kanimaru August 22, 2026 18:32
Comment thread addons/twitcher/editor/eventsub_generator/twitch_eventsub_definition_generator.gd Outdated
Comment thread addons/twitcher/editor/eventsub_generator/twitch_eventsub_definition_generator.gd Outdated
Comment thread addons/twitcher/editor/eventsub_generator/twitch_eventsub_definition_generator.gd Outdated
Comment thread addons/twitcher/editor/eventsub_generator/twitch_eventsub_definition_generator.gd Outdated
…review feedback

Instead of a separate "Generate Definitions" button, TwitchEventsubGenerator.generate_api()
now also regenerates twitch_eventsub_definition.gd right after the payload classes -
one click on "Generate Eventsub" does both, reusing the same parsed swagger schemas.
Removes the now-unneeded generate_definitions.gd/.tscn.

Also applies kani's review feedback on PR #137: explicit type annotations on the
`for info in definitions` loops. Left _screaming_snake() as-is rather than switching to
to_snake_case().to_upper() as suggested - that splits a trailing version digit off its
letter ("ChannelModerateV2" -> "CHANNEL_MODERATE_V_2"), which would break every V2 entry.
generate_api() ran the Definitions step after prepare_component(), which mutates
every parsed component's _classname (prefixing it with "TwitchES") to build the
payload class names. By the time the Definitions parser searched for e.g.
"HypeTrainBeginCondition" it had already become "TwitchESHypeTrainBeginCondition",
so every condition lookup silently failed and every definition ended up with an
empty conditions array.

Move the Definitions step to the start of generate_api(), before component names
get mutated. Verified: 0 lookup warnings and non-empty conditions across all 83
definitions (was 71/83 failing).
@github-actions

github-actions Bot commented Aug 30, 2026

Copy link
Copy Markdown

GUT Results

126 tests  ±0   126 ✅ ±0   0s ⏱️ ±0s
  9 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 614c3a6. ± Comparison against base commit 08acc25.

♻️ This comment has been updated with latest results.

Temptica and others added 5 commits August 30, 2026 21:00
The "double enable" cleanup dropped res://addons/twitcher/plugin.cfg instead
of a duplicate. The merge from main had correctly produced the two-entry list
that master carries (gut + twitcher) - the branch base simply predated gut
being added, so it was a real merge result, not a duplicate. Without it the
addon under development is disabled in its own project.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The generated definitions now list every condition field the docs mention,
including optional and mutually exclusive ones - channel.raid takes either
from_broadcaster_user_id or to_broadcaster_user_id, never both, and
conduit.shard.disabled has an optional conduit_id. get_conditions() copied
every listed key unconditionally, so the unused one went out as an empty
string and Twitch rejected the subscription.

Skip empty values, and read through Dictionary.get() so a config built via
create() with a partial condition dictionary no longer crashes here - which
is exactly the case create() already logs "You miss probably following
condition" about.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Derive the enum version suffix from the digit the header regex already
  captures, so a future "channel.moderate v3" becomes CHANNEL_MODERATE_V3
  instead of a second CHANNEL_MODERATE_V2.
- Warn loudly when a definition references a generated_eventsub script that
  doesn't exist. Definitions are emitted before the payload classes and refer
  to them by global class name, so a subscription type with no swagger schema
  would otherwise turn into a project-wide parse error. Runs after the
  components are written, since an existence check before that would reject
  types that are about to be generated.
- Emit the same "CLASS GOT AUTOGENERATED" banner the other generators use,
  and add it to the checked-in file so it stays identical to generator output.
- Add the missing uid= to both new ext_resource lines in generate_all_apis.tscn.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@kanimaru
kanimaru merged commit a56c985 into master Sep 4, 2026
4 checks passed
@kanimaru
kanimaru deleted the feature/eventsub-definition-generator branch September 4, 2026 09:38
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.

2 participants