From 3132621245630ac2ae345d331bb742ddeb88bfa2 Mon Sep 17 00:00:00 2001 From: Daniel Worrall Date: Wed, 22 May 2019 00:31:25 +0100 Subject: Add IRC::Connection, support SSL & WS, support tags --- src/twitch/irc.cr | 32 +++++++++++++-------------- src/twitch/irc/connection.cr | 51 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 src/twitch/irc/connection.cr (limited to 'src') diff --git a/src/twitch/irc.cr b/src/twitch/irc.cr index 8fe0d22..4e43349 100644 --- a/src/twitch/irc.cr +++ b/src/twitch/irc.cr @@ -1,18 +1,16 @@ -require "socket" require "fast_irc" require "./rate_limiter" +require "./irc/*" -class Twitch::IRC - private getter socket : IO - private getter limiter : RateLimiter(String) - private getter tags : Array(String) - private getter log_mode : Bool +class Twitch::IRC::Client + private getter connection, limiter, tags, log_mode - def self.new(nick : String, token : String, log_mode = false) - new(TCPSocket.new("irc.chat.twitch.tv", 6667), nick, token, log_mode: log_mode) + def self.new(nick : String, token : String, websocket = false, ssl = true, log_mode = false) + connection = Twitch::IRC::Connection.new(websocket, ssl) + new(connection, nick, token, log_mode: log_mode) end - def initialize(@socket : IO, @nick : String, @token : String, @log_mode : Bool) + def initialize(@connection : Twitch::IRC::Connection, @nick : String, @token : String, @log_mode = false) @limiter = RateLimiter(String).new @tags = [] of String limiter.bucket(:join, 50_u32, 15.seconds) @@ -23,9 +21,10 @@ class Twitch::IRC authenticate spawn join_channels(channels) @connected = true - FastIRC.parse(socket) do |message| + connection.on_message do |message| spawn dispatch(message) end + connection.run end def message(channel : String, message : String) @@ -50,6 +49,10 @@ class Twitch::IRC raw_write("PART", ["##{channel}"]) end + def tags=(tags : Array(String)) + @tags = tags + end + def dispatch(message : FastIRC::Message) puts "> " + message.to_s if log_mode case message.command @@ -60,10 +63,6 @@ class Twitch::IRC end end - def tags=(tags : Array(String)) - @tags = tags - end - private def authenticate request_tags raw_write("PASS", [@token]) @@ -87,7 +86,8 @@ class Twitch::IRC end private def raw_write(command, params, prefix = nil, tags = nil) - puts "< " + FastIRC::Message.new(command, params, prefix: prefix, tags: tags).to_s if log_mode - FastIRC::Message.new(command, params, prefix: prefix, tags: tags).to_s(socket) + message = FastIRC::Message.new(command, params, prefix: prefix, tags: tags) + puts "< " + message.to_s if log_mode + connection.send(message) end end diff --git a/src/twitch/irc/connection.cr b/src/twitch/irc/connection.cr new file mode 100644 index 0000000..daf6a05 --- /dev/null +++ b/src/twitch/irc/connection.cr @@ -0,0 +1,51 @@ +require "socket" +require "http/web_socket" +require "openssl" + +class Twitch::IRC::Connection + def self.new(websocket = false, ssl = true) + socket = if websocket + HTTP::WebSocket.new("irc-ws.chat.twitch.tv", "", tls: ssl) + else + tcp = TCPSocket.new("irc.chat.twitch.tv", ssl ? 6697 : 6667) + if ssl + tcp = OpenSSL::SSL::Socket::Client.new(tcp, OpenSSL::SSL::Context::Client.new) + tcp.sync = true + end + tcp + end + new(socket, websocket, ssl) + end + + def initialize(@socket : IO | HTTP::WebSocket, websocket = false, ssl = true) + end + + def send(message) + socket = @socket + if socket.is_a?(IO) + message.to_s(socket) + else + socket.send(message.to_s) + end + end + + def run + socket = @socket + if socket.is_a?(IO) + FastIRC.parse(socket) do |message| + @on_message.try &.call(message) + end + else + socket.on_message do |message| + reader = FastIRC::Reader.new(IO::Memory.new(message)) + while m = reader.next + @on_message.try &.call(m) + end + end + socket.run + end + end + + def on_message(&@on_message : FastIRC::Message ->) + end +end -- cgit v1.2.3