From 5c80a758b1800ac74bdfa36cf2f0274013ba58dc Mon Sep 17 00:00:00 2001 From: Dominic Bytes <305052051+dominicbytes@users.noreply.github.com> Date: Tue, 4 Aug 2026 11:41:17 -0500 Subject: [PATCH] Rebrand as Twitcher for Redot --- README.md | 117 ++++++++---------- addons/twitcher/chat/twitch_command_help.gd | 2 +- .../api_generator/twitch_api_generator.gd | 2 +- .../editor/api_generator/twitch_gen_field.gd | 2 +- .../editor/project_setting_property.gd | 2 +- .../editor/twitch_editor_node_utils.gd | 2 +- .../twitcher/example/chat/eventsub_chat.tscn | 2 +- addons/twitcher/example/reward/reward.gd | 2 +- addons/twitcher/generated/twitch_api.gd | 2 +- addons/twitcher/lib/README.md | 2 +- addons/twitcher/lib/http/http_server.gd | 2 +- addons/twitcher/lib/oOuch/oauth.gd | 2 +- addons/twitcher/lib/regex/regex_util.gd | 2 +- .../media/native_image_transformer.gd | 2 +- .../media/twitch_image_transformer.gd | 2 +- addons/twitcher/plugin.cfg | 6 +- project.godot | 2 +- 17 files changed, 70 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 11808ba2..5aa5e9e1 100644 --- a/README.md +++ b/README.md @@ -1,91 +1,78 @@ -# Twitcher +# Twitcher for Redot -> **Redot compatibility fork:** This branch preserves Twitcher's Godot support while targeting -> Redot LTS 26.2. The editor plugin, setup wizard, and runtime `TwitchService` are validated with -> Redot `26.2.stable.official.4f5b14aba`. +[![Redot 26.2](https://img.shields.io/badge/Redot-26.2-EA4335?style=flat-square)](https://github.com/Redot-Engine/redot-engine/releases/tag/redot-26.2-stable) +[![Redot compatibility](https://github.com/dominicbytes/twitcher/actions/workflows/redot-compatibility.yml/badge.svg)](https://github.com/dominicbytes/twitcher/actions/workflows/redot-compatibility.yml) +[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE) -[![Godot Asset Library](https://img.shields.io/badge/Godot%20Asset%20Library-Twitcher-blue?style=flat-square)](https://godotengine.org/asset-library/asset/2629) -[![License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://github.com/kanimaru/twitcher/blob/v2/LICENSE) -[![Twitch](https://img.shields.io/badge/Support_on_Twitch-kani_dev-purple?style=flat-square&logo=twitch)](https://www.twitch.tv/kani_dev/) -[![Documentation](https://img.shields.io/badge/Twitcher-Documentation-purple?style=flat-square&logo=readthedocs)](https://twitcher.kani.dev/) +**Twitch integration for Redot 26.2 LTS.** -**Seamless Twitch Integration for Godot 4.4+ and Redot 26.2** +Twitcher for Redot connects Redot games, overlays, and applications to Twitch. It supports +EventSub, the Helix API, chat commands, OAuth flows, channel-point rewards, emotes, badges, and +Cheermotes. -Twitcher provides a comprehensive toolkit to effortlessly connect your Godot Engine games, -overlays, or applications to the Twitch platform. Integrate real-time chat, respond to events like -follows and subscriptions, manage rewards, handle chat commands, and utilize the full Twitch API with ease. +This is an independent Redot project derived from +[kani_dev's original Twitcher](https://github.com/kanimaru/twitcher). It is maintained separately +and is not intended to merge back into the original project. Twitcher for Redot preserves the +original public API and `res://addons/twitcher` paths while maintaining and testing Redot support. -## Key Features +## Features -* **Modern Twitch Integration:** Utilizes EventSub for real-time events and the Helix API for robust interactions (moving away from deprecated IRC features for core functionality). -* **Simplified Authentication:** Supports multiple OAuth flows (Authorization Code, Client Credentials, Device Code) with helpers for secure token management. -* **Easy Event Handling:** Dedicated `TwitchEventListener` node to react to specific EventSub events (Follows, Subs, Cheers, Rewards, etc.). -* **API Coverage:** Auto-generated, type-safe wrapper methods for the Twitch Helix REST API. -* **Chat Command Framework:** `TwitchCommand` nodes for defining and handling chat commands with permission checks. Includes an automated `!help` command generator. -* **Editor Tools:** Built-in helpers for configuring OAuth Scopes, EventSub subscriptions, and testing credentials directly within the Godot editor. -* **Media Loading:** Handles fetching and caching Twitch Emotes (including animated GIFs via optional transformers), Badges, and Cheermotes as Godot `SpriteFrames`. +- EventSub listeners for follows, subscriptions, cheers, rewards, and other Twitch events +- Generated, typed wrappers for the Twitch Helix REST API +- OAuth Authorization Code, Client Credentials, and Device Code flows +- Twitch chat commands with permission checks and help generation +- Redot editor tools for authentication, scopes, EventSub configuration, and rewards +- Twitch emote, badge, and Cheermote loading as Redot `SpriteFrames` -## Installation - -1. **Get the Addon:** - * **Recommended (AssetLib):** Search for "Twitcher" in the Godot AssetLib tab and click Download. - * **Manual (GitHub):** Download from [GitHub](https://github.com/kanimaru/twitcher/releases). Extract the `addons/twitcher` folder into your project's directory. - * **Important:** The addon *must* reside in the exact path `res://addons/twitcher` for internal resources to load correctly. -2. **Enable Plugin:** Go to `Project -> Project Settings -> Plugins` and check the `Enable` box next to "Twitcher". - -### Redot - -Copy `addons/twitcher` to the same path in your Redot project, then enable Twitcher under -`Project -> Project Settings -> Plugins`. This fork uses the same public API and scene paths as -upstream Twitcher. +## Requirements -The development project can be checked with: +- [Redot 26.2 LTS](https://github.com/Redot-Engine/redot-engine/releases/tag/redot-26.2-stable) +- A Twitch developer application for features that require authentication -```powershell -redot --headless --path . --import -redot --headless --path . --script res://tests/redot_compatibility.gd -``` - -The probe loads the editor plugin, both setup-wizard variants, and an instantiated runtime -`TwitchService`. Live Twitch authentication and EventSub delivery require Twitch credentials and -are intentionally separate integration tests. - -## Quick Start & Documentation +## Installation -1. **Run Setup Wizard:** After enabling the plugin, the easiest way to configure authentication is via the Setup Wizard: - * Navigate to `Project -> Tools -> Twitcher Setup`. - * Follow the on-screen instructions to enter your Twitch Application credentials and select required OAuth scopes. -2. **Explore the Documentation:** For detailed guides, tutorials, API reference, and advanced configuration (like setting up GIF support), please refer to the **[Full Twitcher Documentation](https://twitcher.kani.dev)**. +1. Download or clone this repository. +2. Copy `addons/twitcher` into your Redot project at exactly `res://addons/twitcher`. +3. In Redot, open **Project → Project Settings → Plugins** and enable **Twitcher for Redot**. +4. Open **Project → Tools → Twitcher → Setup** to configure your Twitch application and scopes. -## Image Transformers (for Animated Emotes) +## Documentation -Godot doesn't natively support animated GIFs. Twitcher uses configurable "Image Transformers" to handle them: +The [upstream Twitcher documentation](https://twitcher.kani.dev/) describes the public API and +core workflows shared by this fork. Where its editor screenshots or engine-version guidance +differs, use Redot 26.2 and the setup path above. -* **`TwitchImageTransformer` (Default):** Static images only. Works out-of-the-box. -* **`MagickImageTransformer`:** Requires [ImageMagick](https://imagemagick.org) to be installed separately. Converts GIFs to `SpriteFrames`. -* **`NativeImageTransformer`:** Experimental, uses native gdscript implementation (based on [vbousquet/godot-gif-importer](https://github.com/vbousquet/godot-gif-importer)). No external programs needed, but may struggle with malformed GIFs. +## Animated emotes -**See the [Full Documentation](https://twitcher.kani.dev/core-nodes/twitch-image-transformer.html)** for instructions on how to configure and use `MagickImageTransformer` or `NativeImageTransformer`. +Twitcher offers three image transformers: -## Support +- `TwitchImageTransformer`: static images; works without external tools +- `MagickImageTransformer`: GIF support through a separate + [ImageMagick](https://imagemagick.org/) installation +- `NativeImageTransformer`: experimental GDScript GIF support based on + [vbousquet/godot-gif-importer](https://github.com/vbousquet/godot-gif-importer) -Need help or have questions? Find kani_dev streaming development and answering questions on [Twitch](https://www.twitch.tv/kani_dev/). Feel free to open an Issue on GitHub for bugs or feature requests. +## Development and validation -## Development +Run the Redot compatibility checks from the repository root: -To prevent accidental commit of your Twitch `client_id` and `client_secret`, this repository includes a pre-commit hook and a GitHub Action. -This is only for Twitcher development. In your project it's fine to commit them because they got encrypted beforehand. -When you want to share your project with other devs, you should also share the key so that the other devs can use -the credentials. +```powershell +redot --headless --path . --import +redot --headless --path . --script res://tests/redot_compatibility.gd +``` -### Setting up the local Pre-commit Hook +The probe loads the editor plugin and setup scenes and instantiates the runtime `TwitchService`. +Live OAuth, Twitch API, and EventSub delivery require credentials and remain integration tests. -To enable the local pre-commit hook that automatically clears secrets from your OAuth settings before committing, run the following command in your terminal: +To enable the local secret-clearing pre-commit hook: ```bash git config core.hooksPath .githooks ``` -## License +## Original project and license -Twitcher is released under the MIT License. See the [LICENSE](https://github.com/kanimaru/twitcher/blob/master/LICENSE) file for details. +Twitcher for Redot is derived from the original +[kanimaru/twitcher](https://github.com/kanimaru/twitcher), created by kani_dev. This repository is +an independent Redot continuation and does not replace or represent the original project. Both are +distributed under the [MIT License](LICENSE). diff --git a/addons/twitcher/chat/twitch_command_help.gd b/addons/twitcher/chat/twitch_command_help.gd index 5cce0be4..2daa8a8e 100644 --- a/addons/twitcher/chat/twitch_command_help.gd +++ b/addons/twitcher/chat/twitch_command_help.gd @@ -56,7 +56,7 @@ func _on_command_receive(from_username: String, info: TwitchCommandInfo, args: P twitch_api.send_whisper(message_body, message["to_user_id"], message["from_user_id"]) -## Needed because when you debug and change code etc. Godot will add the commands multiple times. +## Needed because Redot can add the commands multiple times while debugging and reloading scripts. func cleanup_redundant_commands() -> void: var command_set: Dictionary = {} for command in TwitchCommand.ALL_COMMANDS: diff --git a/addons/twitcher/editor/api_generator/twitch_api_generator.gd b/addons/twitcher/editor/api_generator/twitch_api_generator.gd index 0d097ca0..c1ac11aa 100644 --- a/addons/twitcher/editor/api_generator/twitch_api_generator.gd +++ b/addons/twitcher/editor/api_generator/twitch_api_generator.gd @@ -87,7 +87,7 @@ func request(path: String, method: int, body: Variant = "", content_type: String var req: BufferedHTTPClient.RequestData = client.request(api_host + path, method, header, request_body) var res: BufferedHTTPClient.ResponseData = await client.wait_for_request(req) - # Try to fix Godot TLS Bug + # Work around an engine TLS issue. if res.result == 5: return await retry(req, res, path, method, body, content_type, error_count + 1) diff --git a/addons/twitcher/editor/api_generator/twitch_gen_field.gd b/addons/twitcher/editor/api_generator/twitch_gen_field.gd index 1f2d4821..954742c9 100644 --- a/addons/twitcher/editor/api_generator/twitch_gen_field.gd +++ b/addons/twitcher/editor/api_generator/twitch_gen_field.gd @@ -16,7 +16,7 @@ var _is_typed_array: bool: get(): return _is_array && _type.begins_with("#") -## Couple of names from the Twitch API are messed up like keywords for godot or numbers +## Some Twitch API names conflict with GDScript keywords or begin with numbers. func _update_name(val: String) -> void: _original_name = val match val: diff --git a/addons/twitcher/editor/project_setting_property.gd b/addons/twitcher/editor/project_setting_property.gd index 697418ee..f29d85cf 100644 --- a/addons/twitcher/editor/project_setting_property.gd +++ b/addons/twitcher/editor/project_setting_property.gd @@ -43,7 +43,7 @@ func as_select(values: Array[String], optional: bool = true) -> ProjectSettingPr return _add_type_def(TYPE_STRING, enum_hint, hint_string) -# Won't work in godot 4.4 the resource is not loaded when you select the project and it will just drop it out of the list. +# The resource is not loaded when selecting the project, so it would be dropped from the list. #func as_resoruce(resource_name: StringName) -> ProjectSettingProperty: # return _add_type_def(TYPE_OBJECT, PROPERTY_HINT_RESOURCE_TYPE, resource_name) diff --git a/addons/twitcher/editor/twitch_editor_node_utils.gd b/addons/twitcher/editor/twitch_editor_node_utils.gd index 289ee8f2..86624286 100644 --- a/addons/twitcher/editor/twitch_editor_node_utils.gd +++ b/addons/twitcher/editor/twitch_editor_node_utils.gd @@ -20,7 +20,7 @@ static func create_media_loader(api: TwitchAPI) -> TwitchMediaLoader: return media_loader -## Ugly but no better way in godot right now +## Redot currently provides no cleaner equivalent. static func new_scene() -> bool: var base_control: Control = EditorInterface.get_base_control() var title_bar: Node = base_control.find_child("*EditorTitleBar*", true, false) diff --git a/addons/twitcher/example/chat/eventsub_chat.tscn b/addons/twitcher/example/chat/eventsub_chat.tscn index b05c7921..ebe60e65 100644 --- a/addons/twitcher/example/chat/eventsub_chat.tscn +++ b/addons/twitcher/example/chat/eventsub_chat.tscn @@ -220,5 +220,5 @@ metadata/_custom_type_script = "uid://bmluckfvgm1c2" [node name="TwitchCommandRespond" type="Node" parent="TwitcherCommand" unique_id=1368511142] script = ExtResource("22_viivw") -respond_message = "You can find Twitcher here: https://github.com/kanimaru/twitcher/" +respond_message = "You can find Twitcher for Redot here: https://github.com/dominicbytes/twitcher/" metadata/_custom_type_script = "uid://dyslkjssasxnk" diff --git a/addons/twitcher/example/reward/reward.gd b/addons/twitcher/example/reward/reward.gd index 48f1fd24..f7276ec7 100644 --- a/addons/twitcher/example/reward/reward.gd +++ b/addons/twitcher/example/reward/reward.gd @@ -27,7 +27,7 @@ func setup_twitcher() -> void: twitch_reward_service = TwitchRewardService.new(api, twitch_media_loader) await twitch_reward_service.save_reward(TEST_REWARD) - # Prevent godot from just quitting to actually cleanup the test reward + # Prevent Redot from quitting before the test reward is cleaned up. get_tree().auto_accept_quit = false diff --git a/addons/twitcher/generated/twitch_api.gd b/addons/twitcher/generated/twitch_api.gd index 73d71239..3234493d 100644 --- a/addons/twitcher/generated/twitch_api.gd +++ b/addons/twitcher/generated/twitch_api.gd @@ -79,7 +79,7 @@ func request(path: String, method: int, body: Variant = "", content_type: String var req: BufferedHTTPClient.RequestData = client.request(api_host + path, method, header, request_body) var res: BufferedHTTPClient.ResponseData = await client.wait_for_request(req) - # Try to fix Godot TLS Bug + # Work around an engine TLS issue. if res.result == 5: return await retry(req, res, path, method, body, content_type, error_count + 1) diff --git a/addons/twitcher/lib/README.md b/addons/twitcher/lib/README.md index a7ea5d08..eb9b2fe6 100644 --- a/addons/twitcher/lib/README.md +++ b/addons/twitcher/lib/README.md @@ -1,4 +1,4 @@ -Because Godot doesn't have a good system to handle dependencies and +Because Redot doesn't have a package manager for addon dependencies and I want to have standalone modules that could be technically their own plugins. Requirements: diff --git a/addons/twitcher/lib/http/http_server.gd b/addons/twitcher/lib/http/http_server.gd index 898b5cac..5c34a4a1 100644 --- a/addons/twitcher/lib/http/http_server.gd +++ b/addons/twitcher/lib/http/http_server.gd @@ -175,7 +175,7 @@ func stop_listening() -> void: func send_response(client: Client, response_code : String, body : PackedByteArray) -> void: var peer: StreamPeerTCP = client.peer peer.put_data(("HTTP/1.1 %s\r\n" % response_code).to_utf8_buffer()) - peer.put_data("Server: Godot Engine (Twitcher)\r\n".to_utf8_buffer()) + peer.put_data("Server: Redot Engine (Twitcher)\r\n".to_utf8_buffer()) peer.put_data(("Content-Length: %d\r\n"% body.size()).to_utf8_buffer()) peer.put_data("Connection: close\r\n".to_utf8_buffer()) peer.put_data("Content-Type: text/html charset=UTF-8\r\n".to_utf8_buffer()) diff --git a/addons/twitcher/lib/oOuch/oauth.gd b/addons/twitcher/lib/oOuch/oauth.gd index 01a828f7..948379b5 100644 --- a/addons/twitcher/lib/oOuch/oauth.gd +++ b/addons/twitcher/lib/oOuch/oauth.gd @@ -340,7 +340,7 @@ func _process_implicit_request(client: OAuthHTTPServer.Client, server: OAuthHTTP body: JSON.stringify(params) }) .then(() => window.close()) - .catch(err => console.error('Failed to send payload to Godot:', err)); + .catch(err => console.error('Failed to send payload to Redot:', err)); """ % oauth_setting.redirect_url diff --git a/addons/twitcher/lib/regex/regex_util.gd b/addons/twitcher/lib/regex/regex_util.gd index 34299a5b..b13b2adc 100644 --- a/addons/twitcher/lib/regex/regex_util.gd +++ b/addons/twitcher/lib/regex/regex_util.gd @@ -1,4 +1,4 @@ -## This one should be Godot Core but isn't sadly... +## This belongs in the engine core but is not available there. class_name RegexUtil static func escape(input:String) -> String: diff --git a/addons/twitcher/media/native_image_transformer.gd b/addons/twitcher/media/native_image_transformer.gd index ac86857a..15ce2921 100644 --- a/addons/twitcher/media/native_image_transformer.gd +++ b/addons/twitcher/media/native_image_transformer.gd @@ -2,7 +2,7 @@ @tool extends TwitchImageTransformer -## Native GIF parser written in GDScript and ported to Godot 4. Most of the time stable but there +## Native GIF parser written in GDScript and ported for Redot. Most of the time stable but there ## are GIF's that may not work cause the file didn't follow the GIF specification. class_name NativeImageTransformer diff --git a/addons/twitcher/media/twitch_image_transformer.gd b/addons/twitcher/media/twitch_image_transformer.gd index b617f557..0dd0b734 100644 --- a/addons/twitcher/media/twitch_image_transformer.gd +++ b/addons/twitcher/media/twitch_image_transformer.gd @@ -2,7 +2,7 @@ @tool extends Resource -## Most simple image transformer that doesn't support GIF's uses builtin functionalities of godot. +## Basic image transformer without GIF support, using Redot's built-in image functionality. class_name TwitchImageTransformer static var _log: TwitchLogger = TwitchLogger.new("TwitchImageTransformer") diff --git a/addons/twitcher/plugin.cfg b/addons/twitcher/plugin.cfg index 99f473c2..149006af 100644 --- a/addons/twitcher/plugin.cfg +++ b/addons/twitcher/plugin.cfg @@ -1,7 +1,7 @@ [plugin] -name="Twitcher" -description="A plugin to use the Twitch API in Godot and Redot." -author="kani_dev" +name="Twitcher for Redot" +description="Twitch API, EventSub, chat, OAuth, and media integration for Redot." +author="kani_dev; Redot port by dominicbytes" version="2.5.1-redot.1" script="plugin.gd" diff --git a/project.godot b/project.godot index dd1a6bc4..b529064d 100644 --- a/project.godot +++ b/project.godot @@ -10,7 +10,7 @@ config_version=5 [application] -config/name="Twitcher" +config/name="Twitcher for Redot" run/main_scene="uid://5lyf04rwo1mf" config/features=PackedStringArray("26.2", "Redot") config/icon="res://addons/twitcher/assets/twitcher-icon.svg"