moved example into subfolder
This commit is contained in:
156
example/Example.gd
Normal file
156
example/Example.gd
Normal file
@@ -0,0 +1,156 @@
|
||||
extends Control
|
||||
|
||||
# Your client id. You can share this publicly. Default is my own client_id.
|
||||
# Please do not ship your project with my client_id, but feel free to test with it.
|
||||
# Visit https://dev.twitch.tv/console/apps/create to create a new application.
|
||||
# You can then find your client id at the bottom of the application console.
|
||||
# DO NOT SHARE THE CLIENT SECRET. If you do, regenerate it.
|
||||
@export var client_id : String = "9x951o0nd03na7moohwetpjjtds0or"
|
||||
# The name of the channel we want to connect to.
|
||||
@export var channel : String
|
||||
# The username of the bot account.
|
||||
@export var username : String
|
||||
|
||||
var id : TwitchIDConnection
|
||||
var api : TwitchAPIConnection
|
||||
var irc : TwitchIRCConnection
|
||||
var eventsub : TwitchEventSubConnection
|
||||
|
||||
var cmd_handler : GIFTCommandHandler = GIFTCommandHandler.new()
|
||||
|
||||
var iconloader : TwitchIconDownloader
|
||||
|
||||
func _ready() -> void:
|
||||
# We will login using the Implicit Grant Flow, which only requires a client_id.
|
||||
# Alternatively, you can use the Authorization Code Grant Flow or the Client Credentials Grant Flow.
|
||||
# Note that the Client Credentials Grant Flow will only return an AppAccessToken, which can not be used
|
||||
# for the majority of the Twitch API or to join a chat room.
|
||||
var auth : ImplicitGrantFlow = ImplicitGrantFlow.new()
|
||||
# For the auth to work, we need to poll it regularly.
|
||||
get_tree().process_frame.connect(auth.poll) # You can also use a timer if you don't want to poll on every frame.
|
||||
|
||||
# Next, we actually get our token to authenticate. We want to be able to read and write messages,
|
||||
# so we request the required scopes. See https://dev.twitch.tv/docs/authentication/scopes/#twitch-access-token-scopes
|
||||
var token : UserAccessToken = await(auth.login(client_id, ["chat:read", "chat:edit"]))
|
||||
if (token == null):
|
||||
# Authentication failed. Abort.
|
||||
return
|
||||
|
||||
# Store the token in the ID connection, create all other connections.
|
||||
id = TwitchIDConnection.new(token)
|
||||
irc = TwitchIRCConnection.new(id)
|
||||
api = TwitchAPIConnection.new(id)
|
||||
iconloader = TwitchIconDownloader.new(api)
|
||||
# For everything to work, the id connection has to be polled regularly.
|
||||
get_tree().process_frame.connect(id.poll)
|
||||
|
||||
# Connect to the Twitch chat.
|
||||
if(!await(irc.connect_to_irc(username))):
|
||||
# Authentication failed. Abort.
|
||||
return
|
||||
# Request the capabilities. By default only twitch.tv/commands and twitch.tv/tags are used.
|
||||
# Refer to https://dev.twitch.tv/docs/irc/capabilities/ for all available capapbilities.
|
||||
irc.request_capabilities()
|
||||
# Join the channel specified in the exported 'channel' variable.
|
||||
irc.join_channel(channel)
|
||||
|
||||
# Add a helloworld command.
|
||||
cmd_handler.add_command("helloworld", hello)
|
||||
# The helloworld command can now also be executed with "hello"!
|
||||
cmd_handler.add_alias("helloworld", "hello")
|
||||
# Add a list command that accepts between 1 and infinite args.
|
||||
cmd_handler.add_command("list", list, -1, 1)
|
||||
|
||||
# For the cmd handler to receive the messages, we have to forward them.
|
||||
irc.chat_message.connect(cmd_handler.handle_command)
|
||||
# If you also want to accept whispers, connect the signal and bind true as the last arg.
|
||||
irc.whisper_message.connect(cmd_handler.handle_command.bind(true))
|
||||
|
||||
# For the chat example to work, we forward the messages received to the put_chat function.
|
||||
irc.chat_message.connect(put_chat)
|
||||
|
||||
# When we press enter on the chat bar or press the send button, we want to execute the send_message
|
||||
# function.
|
||||
%LineEdit.text_submitted.connect(send_message.unbind(1))
|
||||
%Button.pressed.connect(send_message)
|
||||
|
||||
# This part of the example only works if GIFT is logged in to your broadcaster account.
|
||||
# If you are, you can uncomment this to also try receiving follow events.
|
||||
# eventsub = TwitchEventSubConnection.new(api)
|
||||
# eventsub.connect_to_eventsub()
|
||||
# eventsub.event.connect(on_event)
|
||||
# var user_ids : Dictionary = await(api.get_users_by_name([username]))
|
||||
# print(user_ids)
|
||||
# if (user_ids.has("data") && user_ids["data"].size() > 0):
|
||||
# var user_id : String = user_ids["data"][0]["id"]
|
||||
# eventsub.subscribe_event("channel.follow", 2, {"broadcaster_user_id": user_id, "moderator_user_id": user_id})
|
||||
|
||||
func hello(cmd_info : CommandInfo) -> void:
|
||||
irc.chat("Hello World!")
|
||||
|
||||
func list(cmd_info : CommandInfo, arg_ary : PackedStringArray) -> void:
|
||||
irc.chat(", ".join(arg_ary))
|
||||
|
||||
func on_event(type : String, data : Dictionary) -> void:
|
||||
match(type):
|
||||
"channel.follow":
|
||||
print("%s followed your channel!" % data["user_name"])
|
||||
|
||||
func send_message() -> void:
|
||||
irc.chat(%LineEdit.text)
|
||||
%LineEdit.text = ""
|
||||
|
||||
func put_chat(senderdata : SenderData, msg : String):
|
||||
var bottom : bool = %ChatScrollContainer.scroll_vertical == %ChatScrollContainer.get_v_scroll_bar().max_value - %ChatScrollContainer.get_v_scroll_bar().get_rect().size.y
|
||||
var label : RichTextLabel = RichTextLabel.new()
|
||||
var time = Time.get_time_dict_from_system()
|
||||
label.fit_content = true
|
||||
label.selection_enabled = true
|
||||
label.push_font_size(12)
|
||||
label.push_color(Color.WEB_GRAY)
|
||||
label.add_text("%02d:%02d " % [time["hour"], time["minute"]])
|
||||
label.pop()
|
||||
label.push_font_size(14)
|
||||
var badges : Array[Texture2D]
|
||||
for badge in senderdata.tags["badges"].split(",", false):
|
||||
label.add_image(await(iconloader.get_badge(badge, senderdata.tags["room-id"])), 0, 0, Color.WHITE, INLINE_ALIGNMENT_CENTER)
|
||||
label.push_bold()
|
||||
if (senderdata.tags["color"] != ""):
|
||||
label.push_color(Color(senderdata.tags["color"]))
|
||||
label.add_text(" %s" % senderdata.tags["display-name"])
|
||||
label.push_color(Color.WHITE)
|
||||
label.push_normal()
|
||||
label.add_text(": ")
|
||||
var locations : Array[EmoteLocation] = []
|
||||
if (senderdata.tags.has("emotes")):
|
||||
for emote in senderdata.tags["emotes"].split("/", false):
|
||||
var data : PackedStringArray = emote.split(":")
|
||||
for d in data[1].split(","):
|
||||
var start_end = d.split("-")
|
||||
locations.append(EmoteLocation.new(data[0], int(start_end[0]), int(start_end[1])))
|
||||
locations.sort_custom(Callable(EmoteLocation, "smaller"))
|
||||
if (locations.is_empty()):
|
||||
label.add_text(msg)
|
||||
else:
|
||||
var offset = 0
|
||||
for loc in locations:
|
||||
label.add_text(msg.substr(offset, loc.start - offset))
|
||||
label.add_image(await(iconloader.get_emote(loc.id)), 0, 0, Color.WHITE, INLINE_ALIGNMENT_CENTER)
|
||||
offset = loc.end + 1
|
||||
%Messages.add_child(label)
|
||||
await(get_tree().process_frame)
|
||||
if (bottom):
|
||||
%ChatScrollContainer.scroll_vertical = %ChatScrollContainer.get_v_scroll_bar().max_value
|
||||
|
||||
class EmoteLocation extends RefCounted:
|
||||
var id : String
|
||||
var start : int
|
||||
var end : int
|
||||
|
||||
func _init(emote_id, start_idx, end_idx):
|
||||
self.id = emote_id
|
||||
self.start = start_idx
|
||||
self.end = end_idx
|
||||
|
||||
static func smaller(a : EmoteLocation, b : EmoteLocation):
|
||||
return a.start < b.start
|
||||
51
example/Example.tscn
Normal file
51
example/Example.tscn
Normal file
@@ -0,0 +1,51 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://bculs28gstcxk"]
|
||||
|
||||
[ext_resource type="Script" path="res://example/Example.gd" id="1_8267x"]
|
||||
|
||||
[node name="Example" 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_8267x")
|
||||
|
||||
[node name="ChatContainer" type="VBoxContainer" parent="."]
|
||||
layout_mode = 0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
|
||||
[node name="Chat" type="Panel" parent="ChatContainer"]
|
||||
show_behind_parent = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="ChatScrollContainer" type="ScrollContainer" parent="ChatContainer/Chat"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
follow_focus = true
|
||||
|
||||
[node name="Messages" type="VBoxContainer" parent="ChatContainer/Chat/ChatScrollContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="ChatContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="ChatContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
caret_blink = true
|
||||
|
||||
[node name="Button" type="Button" parent="ChatContainer/HBoxContainer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 2
|
||||
text = "Send"
|
||||
Reference in New Issue
Block a user