One_Eleven_Android/addons/godot-twicil/godot_twicil.gd
2024-11-10 03:34:28 +03:00

257 lines
6.6 KiB
GDScript

extends IrcClientSecure
class_name TwiCIL
signal raw_response_recieved(response)
signal user_appeared(user)
signal user_disappeared(user)
signal message_recieved(sender, text, emotes)
signal emote_recieved(user, emote_reference)
signal texture_recieved(texture)
enum IRCCommands{PING, PONG, PRIVMSG, JOIN, PART, NAMES}
const TWITCH_IRC_CHAT_HOST = "wss://irc-ws.chat.twitch.tv"
const TWITCH_IRC_CHAT_PORT = 443
onready var tools = HelperTools.new()
onready var commands = InteractiveCommands.new()
onready var chat_list = ChatList.new()
var twitch_emotes_cache:TwitchEmotesCache
var bttv_emotes_cache:BttvEmotesCache
var ffz_emotes_cache:FfzEmotesCache
var twitch_api_wrapper:TwitchApiWrapper
var irc_commands = {
IRCCommands.PING:"PING",
IRCCommands.PONG:"PONG",
IRCCommands.PRIVMSG:"PRIVMSG",
IRCCommands.JOIN:"JOIN",
IRCCommands.PART:"PART",
IRCCommands.NAMES:"/NAMES"
}
var curr_channel = ""
var user_emotes_queue: = Dictionary()
func connect_to_twitch_chat()->bool:
return .connect_to_host(TWITCH_IRC_CHAT_HOST, TWITCH_IRC_CHAT_PORT)
func connect_to_channel(channel, client_id, password, nickname, realname = ""):
_connect_to(
channel,
nickname,
nickname if realname == "" else realname,
password,
client_id
)
twitch_api_wrapper.set_credentials(client_id, password)
func _connect_to(channel, nickname, realname, password, client_id):
.send_command("PASS %s" % password)
.send_command("NICK " + nickname)
.send_command(str("USER ", client_id, " ", _host, " bla:", realname))
.send_command("JOIN #" + channel)
.send_command("CAP REQ :twitch.tv/tags twitch.tv/commands twitch.tv/membership")
curr_channel = channel
func Disconnect():
.Disconnect();
func IsConnected()->bool:
return .IsConnected();
func send_message(text):
.send_command(str("PRIVMSG #", curr_channel, " :", text))
func send_whisper(recepient, text):
send_message(str("/w ", recepient, " ", text))
func request_twitch_emote(user_name:String, id:int)->void :
if not user_emotes_queue.has(id):
user_emotes_queue[id] = []
user_emotes_queue[id].append(user_name)
twitch_emotes_cache.get_emote(id)
func request_bttv_emote(user_name:String, code:String)->void :
var id:String = bttv_emotes_cache.available_emotes.get(code)
if not user_emotes_queue.has(id):
user_emotes_queue[id] = []
user_emotes_queue[id].append(user_name)
bttv_emotes_cache.get_emote(code)
func request_ffz_emote(user_name:String, code:String)->void :
var id:String = ffz_emotes_cache.available_emotes.get(code, {}).get("id", "")
if not user_emotes_queue.has(id):
user_emotes_queue[id] = []
user_emotes_queue[id].append(user_name)
ffz_emotes_cache.get_emote(code)
func request_emote_from(emotes:Array, user_name:String, index:int)->void :
if emotes.empty():
return
var emote = emotes[index]
if emote.get("type") == TwitchMessage.EmoteType.TWITCH:
var emote_id: = int(emote.get("id"))
request_twitch_emote(user_name, emote_id)
elif emote.get("type") == TwitchMessage.EmoteType.BTTV:
var emote_code: = emote.get("code") as String
request_bttv_emote(user_name, emote_code)
elif emote.get("type") == TwitchMessage.EmoteType.FFZ:
var emote_code: = emote.get("code") as String
request_ffz_emote(user_name, emote_code)
func __init_emotes_caches()->void :
twitch_emotes_cache = TwitchEmotesCache.new()
add_child(twitch_emotes_cache)
bttv_emotes_cache = BttvEmotesCache.new()
add_child(bttv_emotes_cache)
ffz_emotes_cache = FfzEmotesCache.new()
add_child(ffz_emotes_cache)
func __init_twitch_api()->void :
twitch_api_wrapper = TwitchApiWrapper.new(http_request_queue, "")
func __connect_signals():
connect("message_recieved", commands, "_on_message_recieved")
connect("response_recieved", self, "_on_response_recieved")
connect("http_response_recieved", self, "_on_http_response_recieved")
twitch_emotes_cache.connect("emote_retrieved", self, "_on_emote_retrieved")
bttv_emotes_cache.connect("emote_retrieved", self, "_on_emote_retrieved")
ffz_emotes_cache.connect("emote_retrieved", self, "_on_emote_retrieved")
twitch_api_wrapper.connect("api_user_info", self, "_on_twitch_api_api_user_info")
func __parse(string:String)->TwitchIrcServerMessage:
var args = []
var twitch_prefix = ""
var prefix = ""
var trailing = []
var command
if string == null:
return TwitchIrcServerMessage.new("", "", "", [])
if string.substr(0, 1) == "@":
var temp = tools.split_string(string.substr(1, string.length() - 1), " ", 1)
twitch_prefix = temp[0]
string = temp[1]
if string.substr(0, 1) == ":":
var temp = tools.split_string(string.substr(1, string.length() - 1), " ", 1)
prefix = temp[0]
string = temp[1]
if string.find(" :") != - 1:
var temp = tools.split_string(string, " :", 1)
string = temp[0]
trailing = temp[1]
args = tools.split_string(string, [" ", " ", "\n"])
args.append(trailing)
else :
args = tools.split_string(string, [" ", " ", "\n"])
command = args[0]
args.pop_front()
return TwitchIrcServerMessage.new(twitch_prefix, prefix, command, args)
func _ready():
__init_twitch_api()
__init_emotes_caches()
__connect_signals()
func _on_response_recieved(response):
emit_signal("raw_response_recieved", response)
for single_response in response.split("\n", false):
single_response = __parse(single_response.strip_edges(false))
if single_response.command == irc_commands[IRCCommands.PING]:
.send_command(str(irc_commands[IRCCommands.PONG], " ", single_response.params[0]))
elif single_response.command == irc_commands[IRCCommands.PRIVMSG]:
var twitch_message:TwitchMessage = TwitchMessage.new(
single_response,
bttv_emotes_cache.available_emotes,
ffz_emotes_cache.available_emotes
)
emit_signal(
"message_recieved",
twitch_message.chat_message.name,
twitch_message.chat_message.text,
twitch_message.emotes
)
elif single_response.command == irc_commands[IRCCommands.JOIN]:
var user_name = MessageWrapper.get_sender_name(single_response)
chat_list.add_user(user_name)
._log(str(user_name, " has joined chat"))
emit_signal("user_appeared", user_name)
elif single_response.command == irc_commands[IRCCommands.PART]:
var user_name = MessageWrapper.get_sender_name(single_response)
chat_list.remove_user(user_name)
._log(str(user_name, " has left chat"))
emit_signal("user_disappeared", user_name)
func _on_emote_retrieved(emote_reference:Reference)->void :
var emote_id:String = emote_reference.id
var user:String = (user_emotes_queue.get(emote_id, []) as Array).pop_front()
emit_signal("emote_recieved", user, emote_reference)
func _on_twitch_api_api_user_info(data):
var user_id: = str(data.get("data", [{}])[0].get("id", 0))
ffz_emotes_cache.init_emotes(user_id)