mirror of
https://codeberg.org/StreamGraph/StreamGraph.git
synced 2024-11-13 19:49:55 +01:00
131 lines
3.9 KiB
GDScript
131 lines
3.9 KiB
GDScript
extends Node
|
|
class_name Twitch_Connection
|
|
|
|
## Handler for a Connection to a Single Twitch Account
|
|
##
|
|
## Used for getting authentication and handling websocket connections.
|
|
|
|
signal token_received(token : String)
|
|
|
|
@export var client_id := "qyjg1mtby1ycs5scm1pvctos7yvyc1"
|
|
@export var redirect_uri := "http://localhost"
|
|
## Port that the redirect_uri will head to on your local system. Defaults to 80 for most cases. Linux tends to prefer 8000 or possibly 1338
|
|
@export var redirect_port := "80"
|
|
|
|
var twitch_url := "https://id.twitch.tv/oauth2/authorize?response_type=token&"
|
|
|
|
var auth_server : TCPServer
|
|
## Websocket used for handling the chat connection.
|
|
var chat_socket = preload("res://addons/no_twitch/chat_socket.gd").new()
|
|
|
|
var state := make_state()
|
|
var token : String
|
|
|
|
func _ready():
|
|
|
|
chat_socket.chat_received.connect(check_chat_socket)
|
|
|
|
|
|
## Handles the basic Twitch Authentication process to request and then later receive a Token (using [method check_auth_peer])
|
|
func authenticate_with_twitch(client_id = client_id):
|
|
auth_server = TCPServer.new()
|
|
|
|
OS.shell_open(create_auth_url())
|
|
auth_server.listen(int(redirect_port))
|
|
|
|
|
|
## Sets up a single chat connection. Joining 1 room with [param token] as it's "PASS" specifying what account it's on. And the optional [param default_chat] specifying the default room to join. While [param nick] specifies the "nickname" (Not the username on Twitch)
|
|
func setup_chat_connection(default_chat : String = "", token : String = token, request_twitch_info = true, nick = "terribletwitch"):
|
|
|
|
# Temporary, closes the socket to allow connecting multiple times without needing to reset.
|
|
chat_socket.close()
|
|
# Connects to the Twitch IRC server.
|
|
chat_socket.connect_to_chat(token, request_twitch_info)
|
|
await chat_socket.socket_open
|
|
|
|
if !default_chat.is_empty():
|
|
|
|
chat_socket.join_chat(default_chat)
|
|
|
|
|
|
|
|
## Joins the given [param channel] over IRC. Essentially just sending JOIN #[param channel]
|
|
func join_channel(channel : String):
|
|
|
|
chat_socket.join_chat(channel)
|
|
|
|
|
|
func send_chat(msg : String, channel : String = ""):
|
|
|
|
chat_socket.send_chat(msg, channel)
|
|
|
|
|
|
func _process(delta):
|
|
|
|
if auth_server and auth_server.is_listening() and auth_server.is_connection_available():
|
|
|
|
check_auth_peer(auth_server.take_connection())
|
|
|
|
|
|
if chat_socket:
|
|
|
|
chat_socket.poll_socket()
|
|
|
|
|
|
|
|
## Utility function for creating a Twitch Authentication URL with the given
|
|
## [param scopes], Twitch Client ID ([param id]) and [param redirect_uri].
|
|
## [param id] defaults to [member client_id] and both [param redirect] and
|
|
## [param redirect_port]
|
|
func create_auth_url(scopes : Array[String] = ["chat:read", "chat:edit"], port := redirect_port, id : String = client_id, redirect : String = redirect_uri):
|
|
|
|
var str_scopes : String
|
|
|
|
for all in scopes:
|
|
|
|
str_scopes += " " + all
|
|
str_scopes = str_scopes.strip_edges()
|
|
|
|
var url = twitch_url + "client_id=" + id + "&redirect_uri=" + redirect + ":" + port + "&scope=" + str_scopes + "&state=" + str(state)
|
|
|
|
return url
|
|
|
|
## Utility function for creating a "state" used for different requests for some extra security as a semi password.
|
|
func make_state(len : int = 16) -> String:
|
|
|
|
var crypto = Crypto.new()
|
|
var state = crypto.generate_random_bytes(len).hex_encode()
|
|
|
|
return state
|
|
|
|
|
|
func check_auth_peer(peer : StreamPeerTCP):
|
|
|
|
var info = peer.get_utf8_string(peer.get_available_bytes())
|
|
printraw(info)
|
|
|
|
var script = "<script>fetch('http://localhost/' + window.location.hash.substr(1))</script>"
|
|
|
|
peer.put_data(str("HTTP/1.1 200\n\n" + script).to_utf8_buffer())
|
|
|
|
|
|
var resp_state = info.split("&state=")
|
|
|
|
# Ensures that the received state is correct.
|
|
if !resp_state.size() > 1 or resp_state[0] == state:
|
|
|
|
return
|
|
|
|
|
|
var token = info.split("access_token=")[1].split("&scope=")[0].strip_edges()
|
|
printraw("Token: ", token, "\n")
|
|
self.token = token
|
|
token_received.emit(token)
|
|
|
|
|
|
func check_chat_socket(dict):
|
|
|
|
prints(dict.user, dict.message)
|
|
|
|
|
|
|