twitch addon
This commit is contained in:
parent
2cd7af98a1
commit
07de7179c9
254 changed files with 18420 additions and 1 deletions
61
example/ChatContainer.gd
Normal file
61
example/ChatContainer.gd
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
class_name VSTChatContainer extends VBoxContainer
|
||||
|
||||
var msg_node: PackedScene = preload("res://example/ChatMessage.tscn")
|
||||
@onready var scroll_container = $Chat/ScrollContainer
|
||||
@onready var chat_message_container = $Chat/ScrollContainer/ChatMessageContainer
|
||||
|
||||
func _ready():
|
||||
VerySimpleTwitch.chat_message_received.connect(create_chatter_msg)
|
||||
|
||||
func create_chatter_msg(chatter: VSTChatter):
|
||||
var msg: VSTChatMessage = msg_node.instantiate()
|
||||
|
||||
var badges: String = await get_badges(chatter)
|
||||
chatter.message = escape_bbcode(chatter.message)
|
||||
await add_emotes(chatter)
|
||||
|
||||
var bottom: bool = is_scroll_bottom()
|
||||
|
||||
msg.set_chatter_msg(badges, chatter)
|
||||
chat_message_container.add_child(msg)
|
||||
await get_tree().process_frame
|
||||
if bottom: scroll_container.scroll_vertical = scroll_container.get_v_scroll_bar().max_value
|
||||
|
||||
func get_badges(chatter: VSTChatter) -> String:
|
||||
var badges:= ""
|
||||
for badge in chatter.tags.badges:
|
||||
var result = await VerySimpleTwitch.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 VerySimpleTwitch.get_emote(loc.id)
|
||||
var emote_string = "[img=center]" + result.resource_path +"[/img]"
|
||||
chatter.message = chatter.message.substr(0, loc.start + offset) + \
|
||||
emote_string + chatter.message.substr(loc.end + offset + 1)
|
||||
offset += emote_string.length() + loc.start - loc.end - 1
|
||||
|
||||
func is_scroll_bottom() -> bool:
|
||||
return scroll_container.scroll_vertical == scroll_container.get_v_scroll_bar().max_value -\
|
||||
scroll_container.get_v_scroll_bar().get_rect().size.y
|
||||
|
||||
# Returns escaped BBCode that won't be parsed by RichTextLabel as tags.
|
||||
func escape_bbcode(bbcode_text):
|
||||
return bbcode_text.replace("[", "[lb]")
|
||||
|
||||
func clear():
|
||||
for child in chat_message_container.get_children():
|
||||
chat_message_container.remove_child(child)
|
||||
1
example/ChatContainer.gd.uid
Normal file
1
example/ChatContainer.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://cfus1c8y3wwo5
|
||||
6
example/ChatMessage.gd
Normal file
6
example/ChatMessage.gd
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
class_name VSTChatMessage extends HBoxContainer
|
||||
|
||||
func set_chatter_msg(badges: String, chatter: VSTChatter):
|
||||
$RichTextLabel.text = "%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
|
||||
|
||||
queue_sort()
|
||||
1
example/ChatMessage.gd.uid
Normal file
1
example/ChatMessage.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://dv1vgugc4bwjw
|
||||
15
example/ChatMessage.tscn
Normal file
15
example/ChatMessage.tscn
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://d3asrgnlj151a"]
|
||||
|
||||
[ext_resource type="Script" path="res://example/ChatMessage.gd" id="1_h3nqp"]
|
||||
|
||||
[node name="ChatMessage" type="HBoxContainer"]
|
||||
size_flags_horizontal = 3
|
||||
script = ExtResource("1_h3nqp")
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
bbcode_enabled = true
|
||||
text = "Testg"
|
||||
fit_content = true
|
||||
scroll_active = false
|
||||
159
example/Demo.tscn
Normal file
159
example/Demo.tscn
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
[gd_scene load_steps=4 format=3 uid="uid://rr154c1ykwoh"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://yhuh0huitds8" path="res://example/TwitchChat.tscn" id="1_o6alc"]
|
||||
[ext_resource type="Script" path="res://example/demo.gd" id="1_uj756"]
|
||||
[ext_resource type="Texture2D" uid="uid://yarcej88qjri" path="res://example/arrow_down.svg" id="2_nmg8t"]
|
||||
|
||||
[node name="Demo" 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_uj756")
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="TabContainer" type="TabContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
current_tab = 0
|
||||
|
||||
[node name="Oauth Connection" type="PanelContainer" parent="VBoxContainer/TabContainer"]
|
||||
layout_mode = 2
|
||||
metadata/_tab_index = 0
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TabContainer/Oauth Connection"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 20
|
||||
theme_override_constants/margin_top = 20
|
||||
theme_override_constants/margin_right = 20
|
||||
theme_override_constants/margin_bottom = 20
|
||||
|
||||
[node name="OauthConnectionLayout" type="VBoxContainer" parent="VBoxContainer/TabContainer/Oauth Connection/MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="OauthTitleToggle" type="Button" parent="VBoxContainer/TabContainer/Oauth Connection/MarginContainer/OauthConnectionLayout"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
text = "Get Token and login to channel"
|
||||
icon = ExtResource("2_nmg8t")
|
||||
alignment = 0
|
||||
|
||||
[node name="Description" type="RichTextLabel" parent="VBoxContainer/TabContainer/Oauth Connection/MarginContainer/OauthConnectionLayout"]
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
text = "You can use [color=#d2a8ff] VerySimpleTwitch.get_token_and_login_chat()[/color] to retrieve the token and automatically login to the twitch chat.
|
||||
|
||||
| [color=gray]Note: You will need to set up the CLIENT_ID in the Settings tab and configure the Twitch app accordingly."
|
||||
fit_content = true
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/TabContainer/Oauth Connection/MarginContainer/OauthConnectionLayout"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 20
|
||||
|
||||
[node name="LoginToken" type="Button" parent="VBoxContainer/TabContainer/Oauth Connection/MarginContainer/OauthConnectionLayout"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Get Token and Login Chat"
|
||||
|
||||
[node name="Anonymous Connection" type="PanelContainer" parent="VBoxContainer/TabContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
metadata/_tab_index = 1
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/TabContainer/Anonymous Connection"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/margin_left = 20
|
||||
theme_override_constants/margin_top = 20
|
||||
theme_override_constants/margin_right = 20
|
||||
theme_override_constants/margin_bottom = 20
|
||||
|
||||
[node name="AnonymousConnectionLayout" type="VBoxContainer" parent="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="AnonymousTitleToggle" type="Button" parent="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
toggle_mode = true
|
||||
button_pressed = true
|
||||
text = "Simple anonymous connection"
|
||||
icon = ExtResource("2_nmg8t")
|
||||
alignment = 0
|
||||
|
||||
[node name="Description" type="RichTextLabel" parent="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout"]
|
||||
layout_mode = 2
|
||||
bbcode_enabled = true
|
||||
text = "This is the easiest way to use the plugin. You can use [color=#d2a8ff]VerySimpleTwitch.login_chat_anon(\"channel_name\")[/color] to connect to the channel without needing a token or any settings customization."
|
||||
fit_content = true
|
||||
|
||||
[node name="HSeparator" type="HSeparator" parent="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 20
|
||||
|
||||
[node name="LoginChat" type="VBoxContainer" parent="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout/LoginChat"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout/LoginChat/HBoxContainer"]
|
||||
layout_mode = 2
|
||||
text = "Channel Name: "
|
||||
|
||||
[node name="ChannelName" type="LineEdit" parent="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout/LoginChat/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 4
|
||||
placeholder_text = "MyChannelName"
|
||||
|
||||
[node name="LoginAnon" type="Button" parent="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout/LoginChat"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Login Anon"
|
||||
|
||||
[node name="LoggedLayout" type="HBoxContainer" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
alignment = 1
|
||||
|
||||
[node name="LogoutButton" type="Button" parent="VBoxContainer/LoggedLayout"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Logout"
|
||||
|
||||
[node name="ClearChar" type="Button" parent="VBoxContainer/LoggedLayout"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
text = "Clear chat"
|
||||
|
||||
[node name="ConnectedLabel" type="Label" parent="VBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
text = "Connected to channel"
|
||||
|
||||
[node name="TwitchChat" parent="VBoxContainer" instance=ExtResource("1_o6alc")]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[connection signal="toggled" from="VBoxContainer/TabContainer/Oauth Connection/MarginContainer/OauthConnectionLayout/OauthTitleToggle" to="." method="_on_oauth_title_toggle_toggled"]
|
||||
[connection signal="toggled" from="VBoxContainer/TabContainer/Oauth Connection/MarginContainer/OauthConnectionLayout/OauthTitleToggle" to="VBoxContainer/TabContainer/Oauth Connection/MarginContainer/OauthConnectionLayout/Description" method="set_visible"]
|
||||
[connection signal="pressed" from="VBoxContainer/TabContainer/Oauth Connection/MarginContainer/OauthConnectionLayout/LoginToken" to="." method="login_token"]
|
||||
[connection signal="toggled" from="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout/AnonymousTitleToggle" to="." method="_on_anonymous_title_toggle_toggled"]
|
||||
[connection signal="toggled" from="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout/AnonymousTitleToggle" to="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout/Description" method="set_visible"]
|
||||
[connection signal="pressed" from="VBoxContainer/TabContainer/Anonymous Connection/MarginContainer/AnonymousConnectionLayout/LoginChat/LoginAnon" to="." method="login_anon"]
|
||||
[connection signal="pressed" from="VBoxContainer/LoggedLayout/LogoutButton" to="." method="logout"]
|
||||
[connection signal="pressed" from="VBoxContainer/LoggedLayout/ClearChar" to="." method="clear_chat"]
|
||||
28
example/TwitchChat.tscn
Normal file
28
example/TwitchChat.tscn
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
[gd_scene load_steps=2 format=3 uid="uid://yhuh0huitds8"]
|
||||
|
||||
[ext_resource type="Script" path="res://example/ChatContainer.gd" id="2_f56i7"]
|
||||
|
||||
[node name="TwitchChat" type="VBoxContainer"]
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
script = ExtResource("2_f56i7")
|
||||
|
||||
[node name="Chat" type="Panel" parent="."]
|
||||
layout_mode = 2
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="Chat"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
grow_horizontal = 2
|
||||
grow_vertical = 2
|
||||
|
||||
[node name="ChatMessageContainer" type="VBoxContainer" parent="Chat/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
1
example/arrow_down.svg
Normal file
1
example/arrow_down.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M480-344 240-584l56-56 184 184 184-184 56 56-240 240Z"/></svg>
|
||||
|
After Width: | Height: | Size: 178 B |
37
example/arrow_down.svg.import
Normal file
37
example/arrow_down.svg.import
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://yarcej88qjri"
|
||||
path="res://.godot/imported/arrow_down.svg-87daaaad8be1a207d564c640aec7c7c9.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://example/arrow_down.svg"
|
||||
dest_files=["res://.godot/imported/arrow_down.svg-87daaaad8be1a207d564c640aec7c7c9.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
1
example/arrow_right.svg
Normal file
1
example/arrow_right.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#e8eaed"><path d="M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z"/></svg>
|
||||
|
After Width: | Height: | Size: 178 B |
37
example/arrow_right.svg.import
Normal file
37
example/arrow_right.svg.import
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://c3rgh75lgvj1a"
|
||||
path="res://.godot/imported/arrow_right.svg-5de23ade3dd4ccfc5abe74276afcee24.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://example/arrow_right.svg"
|
||||
dest_files=["res://.godot/imported/arrow_right.svg-5de23ade3dd4ccfc5abe74276afcee24.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=false
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
54
example/demo.gd
Normal file
54
example/demo.gd
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
extends Node
|
||||
|
||||
func login_anon():
|
||||
await VerySimpleTwitch.login_chat_anon(%ChannelName.text)
|
||||
_show_logout_layout()
|
||||
|
||||
func login_token():
|
||||
await VerySimpleTwitch.get_token_and_login_chat()
|
||||
_show_logout_layout()
|
||||
|
||||
func logout():
|
||||
VerySimpleTwitch.end_chat_client()
|
||||
%TwitchChat.clear()
|
||||
_show_login_layout()
|
||||
|
||||
|
||||
#region Local methods to simplify demo
|
||||
func _show_login_layout():
|
||||
%TabContainer.set_tab_disabled(0, false)
|
||||
%TabContainer.set_tab_disabled(1, false)
|
||||
%LoggedLayout.hide()
|
||||
%LoginToken.show()
|
||||
%LoginAnon.show()
|
||||
%ChannelName.editable = true
|
||||
%ChannelName.selecting_enabled = true
|
||||
|
||||
func _show_logout_layout():
|
||||
%TabContainer.set_tab_disabled(0, true)
|
||||
%TabContainer.set_tab_disabled(1, true)
|
||||
%LoginAnon.hide()
|
||||
%LoggedLayout.show()
|
||||
%LoginToken.hide()
|
||||
%ChannelName.editable = false
|
||||
%ChannelName.selecting_enabled = false
|
||||
|
||||
|
||||
func clear_chat() -> void:
|
||||
%TwitchChat.clear()
|
||||
|
||||
|
||||
func _on_oauth_title_toggle_toggled(toggled_on: bool) -> void:
|
||||
_update_toggle_icon(%OauthTitleToggle, toggled_on)
|
||||
|
||||
|
||||
func _on_anonymous_title_toggle_toggled(toggled_on: bool) -> void:
|
||||
_update_toggle_icon(%AnonymousTitleToggle, toggled_on)
|
||||
|
||||
|
||||
func _update_toggle_icon(toggle_button: Button, toggled_on: bool) -> void:
|
||||
var icon_path = "res://example/arrow_down.svg" if toggled_on else "res://example/arrow_right.svg"
|
||||
var icon = load(icon_path)
|
||||
toggle_button.icon = icon
|
||||
|
||||
#endregion
|
||||
1
example/demo.gd.uid
Normal file
1
example/demo.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://dqriw7oihq74w
|
||||
Loading…
Add table
Add a link
Reference in a new issue