diff options
-rw-r--r-- | spec/irc_spec.cr | 3 | ||||
-rw-r--r-- | src/twitch/irc.cr | 32 | ||||
-rw-r--r-- | src/twitch/irc/connection.cr | 51 |
3 files changed, 69 insertions, 17 deletions
diff --git a/spec/irc_spec.cr b/spec/irc_spec.cr index 0053024..2d5d072 100644 --- a/spec/irc_spec.cr +++ b/spec/irc_spec.cr @@ -3,7 +3,8 @@ require "./spec_helper" describe "PING" do it "responds with PONG" do response = String.build do |io| - client = Twitch::IRC.new(io, "foo", "bar") + connection = Twitch::IRC::Connection.new(io) + client = Twitch::IRC::Client.new(connection, "foo", "bar") client.dispatch FastIRC::Message.new("PING", nil) end response.should eq FastIRC::Message.new("PONG", ["tmi.twitch.tv"]).to_s 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 |