miggor-StreamGraph/addons/no_twitch/chat_socket.gd
2024-01-21 21:42:11 -07:00

171 lines
4.9 KiB
GDScript

extends Websocket_Client
class_name Chat_Socket
## Wrapper class around [Websocket_Client] that handles Twitch Chat
signal chat_received
signal chat_received_raw
signal chat_received_rich
signal chat_connected
var channels : Array[String]
var extra_info : bool
var user_regex := RegEx.new()
var user_pattern := r":([\w]+)!"
func _init(owner : Twitch_Connection):
chat_received_rich.connect(owner.check_chat_socket.bind(true))
chat_received.connect(owner.check_chat_socket)
packet_received.connect(data_received)
user_regex.compile(user_pattern)
## Connects to the Twitch IRC server.
func connect_to_chat(token, extra = false, nick = "terribletwitch"):
extra_info = extra
connect_to_url("wss://irc-ws.chat.twitch.tv:443")
await socket_open
send_text("PASS oauth:" + token)
send_text("NICK " + nick)
if extra:
send_text("CAP REQ :twitch.tv/commands twitch.tv/tags")
## Handles checking the received packet from [signal Websocket_Client.packet_received]
func data_received(packet : PackedByteArray):
# Gets the text from the packet, strips the end and splits the different lines
var messages = packet.get_string_from_utf8().strip_edges(false).split("\r\n")
for msg in messages:
# Checks if this is a message that has tags enabled and if so, parses out the tags.
var tags : Dictionary
if msg.begins_with("@"):
# Grabs the actual end of the string with the message in it.
var real_msg = msg.split(" ", false, 1)
msg = real_msg[1]
# Loops through all the tags splitting them up by ; and then by = to get the keys and values.
for tag in real_msg[0].split(";"):
var key_value = tag.split("=")
tags[key_value[0]] = key_value[1]
parse_chat_msg(msg, tags)
#@badge-info=subscriber/34;badges=broadcaster/1,subscriber/6,game-developer/1;client-nonce=b5009ae3ee034a7706d86fe221882925;color=#2E8B57;display-name=EroAxee;emotes=;first-msg=0;flags=;id=be05dae8-4067-4edf-83f2-e6be02974904;mod=0;returning-chatter=0;room-id=160349129;subscriber=1;tmi-sent-ts=1702009303249;turbo=0;user-id=160349129;user-type= :eroaxee!eroaxee@eroaxee.tmi.twitch.tv PRIVMSG #eroaxee :More
## Parses the given [param msg] [String]
func parse_chat_msg(msg : String, tags : Dictionary):
var msg_dict : Dictionary
if msg == "PING :tmi.twitch.tv":
send_text(msg.replace("PING", "PONG"))
return
var msg_notice = msg.split(" ")[1]
match msg_notice:
"PRIVMSG":
var space_split = msg.split(" ", true, 3)
msg_dict["username"] = user_regex.search(msg).get_string(1)
msg_dict["message"] = space_split[3].trim_prefix(":")
msg_dict["channel"] = space_split[2].trim_prefix("#")
msg_dict.merge(parse_tags(tags))
prints(msg_dict.username, msg_dict.message, msg_dict.channel)
#(__username_regex.search(split[0]).get_string(1), split[3].right(1), split[2], tags)
if !tags.is_empty():
chat_received_rich.emit(msg_dict)
return
chat_received.emit(msg_dict)
# Connection Message
"001":
prints("Connection Established", msg)
chat_connected.emit()
# Chat Joining Message
"JOIN":
pass
# Chat Leaving Message
"PART":
pass
#@badge-info=subscriber/34;badges=broadcaster/1,subscriber/6,game-developer/1;client-nonce=02d73777ab1fab1aee33ada1830d52b5;color=#2E8B57;display-name=EroAxee;emotes=;first-msg=0;flags=;id=4ff91a8c-b965-43f8-85a1-ddd541a2b438;mod=0;returning-chatter=0;room-id=160349129;subscriber=1;tmi-sent-ts=1701850826667;turbo=0;user-id=160349129;user-type= :eroaxee!eroaxee@eroaxee.tmi.twitch.tv PRIVMSG #eroaxee :Stuff
## Utility function that takes a Dictionary of tags from a Twitch message and parses them to be slightly more usable.
func parse_tags(tags : Dictionary):
var new_tags : Dictionary
for all in tags.keys():
if all == "badges":
tags[all] = tags[all].split(",")
new_tags[all.replace("-", "_")] = tags[all]
return new_tags
#{ "@badge-info": "subscriber/34", "badges": "broadcaster/1,subscriber/6,game-developer/1", "client-nonce": "b2e3524806f51c94cadd61d338bc14ed", "color": "#2E8B57", "display-name": "EroAxee", "emotes": "", "first-msg": "0", "flags": "", "id": "494dc47e-0d9c-4407-83ec-309764e1adf3", "mod": "0", "returning-chatter": "0", "room-id": "160349129", "subscriber": "1", "tmi-sent-ts": "1701853794297", "turbo": "0", "user-id": "160349129", "user-type": "" }
## Wrapper function around [method WebSocketPeer.send_text]
func send_chat(msg : String, channel : String = ""):
if channel.is_empty():
channel = channels[0]
channel = channel.strip_edges()
send_text("PRIVMSG #" + channel + " :" + msg + "\r\n")
## Utility function that handles joining the supplied [param channel]'s chat.
func join_chat(channel : String):
send_text("JOIN #" + channel + "\r\n")
channels.append(channel)
## Utility function that handles leaving the supplied [param channel]'s chat.
func leave_chat(channel : String):
send_chat("PART #" + channel)
channels.erase(channel)