twitch addon

This commit is contained in:
Tabby 2025-04-21 00:17:07 +10:00
parent 2cd7af98a1
commit 07de7179c9
254 changed files with 18420 additions and 1 deletions

View file

@ -0,0 +1,145 @@
@tool
extends Control
const MAX_MESSAGES:int = 50
var line: PackedScene = load("res://addons/very-simple-twitch/chat/vst_chat_dock_line.tscn")
var twitch_chat: VSTChat:
get:
if twitch_chat == null:
twitch_chat = VSTChat.new()
add_child(twitch_chat)
return twitch_chat
@onready var support_button: Button = %SupportButton
@onready var channel_line_edit: LineEdit = %ChannelLineEdit
@onready var connect_button: Button = %ConnectButton
@onready var chat_layout: Control = %ChatLayout
@onready var chat_scroll:ScrollContainer = %ChatScroll
@onready var clear_button:Button = %ClearButton
@onready var disconnect_button:Button = %DisconnectButton
func _ready():
support_button.icon = get_theme_icon("Heart", "EditorIcons")
support_button.tooltip_text = "Support me on Ko-fi"
func _on_button_pressed():
twitch_chat.Connected.connect(on_chat_connected)
twitch_chat.OnMessage.connect(create_chatter_msg)
twitch_chat.login_anon(channel_line_edit.text)
connect_button.disabled = true
channel_line_edit.editable = false
func _on_clear_button_pressed():
clear_all_messages()
func _on_line_edit_text_changed(new_text):
connect_button.disabled = len(new_text) == 0
func _on_disconnect_button_pressed():
twitch_chat.disconnect_api()
clear_all_messages()
show_connect_layout()
if twitch_chat.Connected.is_connected(on_chat_connected):
twitch_chat.Connected.disconnect(on_chat_connected)
if twitch_chat.OnMessage.is_connected(create_chatter_msg):
twitch_chat.OnMessage.disconnect(create_chatter_msg)
func _on_support_button_pressed() -> void:
OS.shell_open("https://ko-fi.com/rothiotome?ref=VST")
func on_chat_connected():
create_system_msg("Connected to chat")
show_chat_layout()
func create_system_msg(message: String):
var msg = line.instantiate()
msg.set_chatter_string("[i]"+message+"[/i]")
chat_layout.add_child(msg)
check_scroll()
func create_chatter_msg(chatter: VSTChatter):
var msg = line.instantiate()
var badges: String = await get_badges(chatter)
chatter.message = escape_bbcode(chatter.message)
await add_emotes(chatter)
msg.set_chatter_msg(badges, chatter)
chat_layout.add_child(msg)
check_scroll()
func check_scroll():
var bottom: bool = is_scroll_bottom()
check_number_messages()
await get_tree().process_frame
if bottom: chat_scroll.scroll_vertical = chat_scroll.get_v_scroll_bar().max_value
func check_number_messages():
if chat_layout.get_child_count() > MAX_MESSAGES:
chat_layout.remove_child(chat_layout.get_children()[0])
# TODO: Can't get badges when the connection is annonymous, we should clear this method
func get_badges(chatter: VSTChatter) -> String:
var badges:= ""
for badge in chatter.tags.badges:
var result = await twitch_chat.get_badge(badge, chatter.tags.badges[badge], chatter.tags.user_id)
if result:
badges += "[img=center]" + result.resource_path + "[/img] "
return badges
func add_emotes(chatter: VSTChatter):
if chatter.tags.emotes.is_empty(): return
var locations: Array = []
for emote in chatter.tags.emotes:
for data in chatter.tags.emotes[emote].split(","):
var start_end = data.split("-")
locations.append(VSTEmoteLocation.new(emote, int(start_end[0]), int(start_end[1])))
locations.sort_custom(Callable(VSTEmoteLocation, "smaller"))
var offset = 0
for loc in locations:
var result = await twitch_chat.get_emote(loc.id)
var emote_string = "[img=center]" + result.resource_path +"[/img]"
var pre: String = chatter.message.substr(0, loc.start + offset)
var post: String = chatter.message.substr(loc.end + offset + 1)
chatter.message = pre + emote_string + post
offset += emote_string.length() + loc.start - loc.end - 1
func is_scroll_bottom() -> bool:
var scroll_bar = chat_scroll.get_v_scroll_bar()
return chat_scroll.scroll_vertical >= scroll_bar.max_value - scroll_bar.get_rect().size.y
# Returns escaped BBCode that won't be parsed by RichTextLabel as tags.
func escape_bbcode(bbcode_text) -> String:
return bbcode_text.replace("[", "[lb]")
func clear_all_messages():
for childen in chat_layout.get_children():
chat_layout.remove_child(childen)
func show_chat_layout():
disconnect_button.visible = true
clear_button.visible = true
channel_line_edit.visible = false
connect_button.visible = false
func show_connect_layout():
disconnect_button.visible = false
clear_button.visible = false
channel_line_edit.editable = true
channel_line_edit.visible = true
connect_button.visible = true
connect_button.disabled = false

View file

@ -0,0 +1 @@
uid://dsitslvay5ti1

View file

@ -0,0 +1,111 @@
[gd_scene load_steps=4 format=3 uid="uid://c8jard0jvmfmt"]
[ext_resource type="Script" path="res://addons/very-simple-twitch/chat/vst_chat_dock.gd" id="1_fkddh"]
[sub_resource type="Image" id="Image_dfhsm"]
data = {
"data": PackedByteArray(255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 94, 94, 127, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 231, 255, 94, 94, 54, 255, 94, 94, 57, 255, 93, 93, 233, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 93, 93, 41, 255, 255, 255, 0, 255, 255, 255, 0, 255, 97, 97, 42, 255, 93, 93, 233, 255, 93, 93, 232, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 44, 255, 255, 255, 0, 255, 97, 97, 42, 255, 97, 97, 42, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 96, 96, 45, 255, 93, 93, 235, 255, 94, 94, 234, 255, 95, 95, 43, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 93, 93, 235, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 233, 255, 95, 95, 59, 255, 96, 96, 61, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 93, 93, 255, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0),
"format": "RGBA8",
"height": 16,
"mipmaps": false,
"width": 16
}
[sub_resource type="ImageTexture" id="ImageTexture_lqqxv"]
image = SubResource("Image_dfhsm")
[node name="VstChatDock" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_fkddh")
[node name="TabContainer" type="TabContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
current_tab = 0
[node name="Chat" type="VBoxContainer" parent="TabContainer"]
layout_mode = 2
metadata/_tab_index = 0
[node name="HBoxContainer" type="HBoxContainer" parent="TabContainer/Chat"]
layout_mode = 2
[node name="ChannelLineEdit" type="LineEdit" parent="TabContainer/Chat/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
placeholder_text = "Channel name"
[node name="ConnectButton" type="Button" parent="TabContainer/Chat/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
disabled = true
text = "CONNECT"
[node name="ClearButton" type="Button" parent="TabContainer/Chat/HBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
text = "CLEAR CHAT"
[node name="DisconnectButton" type="Button" parent="TabContainer/Chat/HBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
text = "DISCONNECT"
[node name="VBoxContainer" type="VBoxContainer" parent="TabContainer/Chat"]
layout_mode = 2
size_flags_vertical = 3
[node name="Chat" type="Panel" parent="TabContainer/Chat/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 3
[node name="ChatScroll" type="ScrollContainer" parent="TabContainer/Chat/VBoxContainer/Chat"]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="ChatLayout" type="VBoxContainer" parent="TabContainer/Chat/VBoxContainer/Chat/ChatScroll"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 1
anchor_left = 1.0
anchor_right = 1.0
offset_left = -8.0
offset_bottom = 33.0
grow_horizontal = 0
alignment = 2
[node name="SupportButton" type="Button" parent="HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
tooltip_text = "Support me on Ko-fi"
icon = SubResource("ImageTexture_lqqxv")
flat = true
[connection signal="text_changed" from="TabContainer/Chat/HBoxContainer/ChannelLineEdit" to="." method="_on_line_edit_text_changed"]
[connection signal="pressed" from="TabContainer/Chat/HBoxContainer/ConnectButton" to="." method="_on_button_pressed"]
[connection signal="pressed" from="TabContainer/Chat/HBoxContainer/ClearButton" to="." method="_on_clear_button_pressed"]
[connection signal="pressed" from="TabContainer/Chat/HBoxContainer/DisconnectButton" to="." method="_on_disconnect_button_pressed"]
[connection signal="pressed" from="HBoxContainer/SupportButton" to="." method="_on_support_button_pressed"]

View file

@ -0,0 +1,9 @@
@tool
extends HBoxContainer
func set_chatter_msg(badges: String, chatter: VSTChatter):
set_chatter_string("%02d:%02d" %[chatter.date_time_dict["hour"], chatter.date_time_dict["minute"]] + " " + badges + " [b][color="+ chatter.tags.color_hex + "]" +chatter.tags.display_name +"[/color][/b]: " + chatter.message)
func set_chatter_string(message:String):
$RichTextLabel.text = message
queue_sort()

View file

@ -0,0 +1 @@
uid://t5txndnsmbgp

View file

@ -0,0 +1,16 @@
[gd_scene load_steps=2 format=3 uid="uid://bo1un8cwcrpqr"]
[ext_resource type="Script" path="res://addons/very-simple-twitch/chat/vst_chat_dock_line.gd" id="1_h0lnd"]
[node name="VstChatDockLine" type="HBoxContainer"]
offset_right = 1.0
offset_bottom = 115.0
size_flags_horizontal = 3
script = ExtResource("1_h0lnd")
[node name="RichTextLabel" type="RichTextLabel" parent="."]
layout_mode = 2
size_flags_horizontal = 3
bbcode_enabled = true
fit_content = true
scroll_active = false