chatx 0.0.0.pre.pre3 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9cc5eac4b2cb23bd725fc867b2f9fca4ac7376c1bc6c9e9ac282d0914d0e0192
4
- data.tar.gz: bee11dafb91d70ab00a3ac536da183289941cd8e69a823e7b53a060fd25e91a6
3
+ metadata.gz: 21350e4e1273f200f9fb7392ef983d0d937669407963ecb1d684a5c8ea9bb5e2
4
+ data.tar.gz: f1fa848b2d9512a8fcc64aa1ad638414a44014b773a1eda2444eccacc5394d17
5
5
  SHA512:
6
- metadata.gz: a9b73297e51bf6bced36b85be3863d7939f53389e5ec49d2a76a1c684d4f80800d94a11f380ac45a51141af8871626c46b4f3be637d180a150636a7cf782e77d
7
- data.tar.gz: db034d9d9525a8d2da916924f793cf1f2ad1ff1aff92ea66fa6c685b212e27a9d1c38bdbbeaef11c1380b35c11fadee374addd05fd9102d3746e1a3c05f98324
6
+ metadata.gz: a881419f0f69339cde92ec726860aaf7d9ffc79066d64cbdf1abf1035bab1fa91c8f6ff8ba619c756dd1faf4cf6d980a20c05d1511a64989b966500ff2db1c00
7
+ data.tar.gz: ef288b1b5932541dde877a838b92d4556c74f77f939b3831976c71e90a0a263788d00073c551fa51e47bc9eff8d034169d597ceacc3948e271afa38af26e1c56
data/README.md CHANGED
@@ -1,34 +1,32 @@
1
1
  # ChatX
2
2
 
3
- ChatX is a shorter and better and more ruby version of the ChatExchange python library for interacting with
3
+ ChatX is a more ruby version of the ChatExchange python library for interacting with
4
4
  Stack Exchange Chat, Stack Overflow Chat, and Meta Stack Exchange Chat.
5
5
 
6
- The first thing to do is to go and make a chat account on the servers you want to use. Then, you can start with this
7
- gem.
6
+ The first thing to do is to go and make a chat account on the servers you want to use. Then, you can start with this gem.
8
7
 
9
8
  ## Installation
10
9
 
11
10
  Add this line to your application's Gemfile:
12
11
 
13
12
  ```ruby
14
- gem 'chatx'
13
+ gem 'chatx', git: 'https://gitlab.com/izwick-schachter/ChatX.git', branch: 'master'
15
14
  ```
16
15
 
17
16
  And then execute:
18
17
 
19
18
  $ bundle
20
19
 
21
- Or install it yourself as:
20
+ Or install it yourself from rubygems (NOT RECOMMENDED) as:
22
21
 
23
22
  $ gem install chatx
24
-
25
23
  ## Usage
26
24
 
27
25
  The first thing you need is to create a new `ChatBot` and tell it what username you used, the password you used. If you
28
26
  want it to operate on a site besides chat.stackexchange.com, you'll have to specify it:
29
27
 
30
28
  ```ruby
31
- my_chatbot = ChatBot.new("smartbot@example.com", "correct horse battery staple")
29
+ my_chatbot = ChatBot.new("smartbot@example.com", "correct horse battery staple", default_server: 'stackexchange')
32
30
  ```
33
31
 
34
32
  If you want to improve your security a bit further, you could also get the username and password from environment
@@ -61,7 +59,7 @@ Or, if you wanted to make that a reply to the "!!/alive" message, you could do:
61
59
 
62
60
  ```ruby
63
61
  my_chatbot.add_hook 1, "message" do |msg|
64
- msg.reply "Yup, I'm here"
62
+ reply_to msg, "Yup, I'm here"
65
63
  end
66
64
  ```
67
65
 
@@ -109,6 +107,10 @@ my_chatbot.gen_hooks do
109
107
  e.reply "Good #{tod} to you as well!"
110
108
  end
111
109
  end
110
+
111
+ command '!!/add' do |*args|
112
+ say args.map(&:to_i).sum
113
+ end
112
114
  end
113
115
  end
114
116
  ```
@@ -138,4 +140,4 @@ The gem is available as open source under the terms of the [MIT License](http://
138
140
  ## Code of Conduct
139
141
 
140
142
  Everyone interacting in the ChatX project’s codebases, issue trackers, chat rooms and mailing lists is expected to
141
- follow the [code of conduct](https://github.com/[USERNAME]/chatx/blob/master/CODE_OF_CONDUCT.md).
143
+ follow the [code of conduct](https://github.com/[USERNAME]/chatx/blob/master/CODE_OF_CONDUCT.md).
@@ -4,6 +4,7 @@ require "websocket/driver"
4
4
  require "json"
5
5
  require "permessage_deflate"
6
6
  require "open-uri"
7
+ require "htmlentities"
7
8
  require_relative "chatx/events"
8
9
  require_relative "chatx/auth"
9
10
  require_relative "chatx/websocket"
@@ -32,7 +33,7 @@ class ChatBot
32
33
  # the URL is managed internally.
33
34
  # @!attribute [rw] hooks
34
35
  # @return [Array] An array of the {Hook}s for the bot.
35
- attr_reader :rooms, :websockets, :logger
36
+ attr_reader :rooms, :websockets, :logger, :agent
36
37
  attr_accessor :default_server, :hooks
37
38
 
38
39
  # Creates a bot.
@@ -56,12 +57,13 @@ class ChatBot
56
57
 
57
58
  @ws_json_logger = Logger.new 'websockets_json.log'
58
59
 
60
+ # Both of these can be overriden in #login with cookie:
59
61
  @email = email
60
62
  @password = password
61
63
  @agent = Mechanize.new
62
64
  @rooms = {} # room_id => {events}
63
65
  @default_server = opts[:default_server]
64
- @hooks = {}
66
+ @hooks = {'*' => []}
65
67
  @websockets = {}
66
68
  at_exit { rejoin }
67
69
  end
@@ -71,8 +73,9 @@ class ChatBot
71
73
  # @return [Boolean] A bool indicating the result of authentication: true if all three
72
74
  # servers were authenticated successfully, false otherwise.
73
75
  def login(servers = @default_server)
74
- servers = [servers] unless servers.is_a? Array
75
- authenticate(servers)
76
+ servers = [servers] unless servers.is_a?(Array) || servers.is_a?(Hash)
77
+ return if authenticate(servers)
78
+ throw "Login failed; Exiting."
76
79
  end
77
80
 
78
81
  # Attempts to join a room, and for every room joined opens a websocket.
@@ -88,7 +91,7 @@ class ChatBot
88
91
  # default value is set by the @default_server instance variable.
89
92
  # @return [Hash] The hash of currently active websockets.
90
93
  def join_room(room_id, server: @default_server)
91
- @logger.info "Joining #{room_id}"
94
+ @logger.info "Joining #{room_id} on server #{server}"
92
95
 
93
96
  fkey = get_fkey(server, "rooms/#{room_id}")
94
97
 
@@ -122,18 +125,24 @@ class ChatBot
122
125
 
123
126
  @logger.info "Rooms: #{@rooms.keys}"
124
127
 
125
- unless @websockets[server].nil?
126
- @websockets[server].driver.close
128
+ unless @websockets[server].nil? || @websockets[server].dead
127
129
  @logger.info "Websocket #{@websockets[server]} already open; clearing."
130
+ @websockets[server].close
128
131
  @websockets[server] = nil
129
132
  end
133
+ @logger.info "SOOOOOOOOOOOOOOOOOOOOOOOOOOOO"
130
134
  ws_uri = JSON.parse(ws_auth_data.body)["url"]
131
135
  last_event_time = events.max_by { |event| event['time_stamp'] }['time_stamp']
132
136
  cookies = (@agent.cookies.map { |cookie| "#{cookie.name}=#{cookie.value}" if cookie.domain == "chat.#{server}.com" || cookie.domain == "#{server}.com" } - [nil]).join("; ")
137
+ @logger.info "Launching new WSCLient"
133
138
  @websockets[server] = WSClient.new("#{ws_uri}?l=#{last_event_time}", cookies, self, server)
134
139
  @logger.info "New websocket open (#{@websockets[server]}"
135
140
  end
136
141
 
142
+ def join_rooms(*rooms, server: @default_server)
143
+ rooms.flatten.each { |rid| join_room(rid) }
144
+ end
145
+
137
146
  # Leaves the room. Not much else to say...
138
147
  # @param room_id [#to_i] The ID of the room to leave
139
148
  # @keyword server [String] The chat server that room is on.
@@ -155,17 +164,22 @@ class ChatBot
155
164
  # @return A meaningless value
156
165
  def say(content, room_id, server: @default_server)
157
166
  fkey = get_fkey(server, "/rooms/#{room_id}")
158
- @logger.warn "Message too long, truncating each line to 500 chars: #{content}" if content.to_s.split("\n").any? { |line| line.length > 500 }
159
167
  if content.to_s.empty?
160
168
  @logger.warn "Message is empty, not posting: '#{content}'"
161
169
  return
162
170
  end
163
- begin
164
- resp = @agent.post("https://chat.#{server}.com/chats/#{room_id}/messages/new", fkey: fkey, text: content.to_s.split("\n").map { |line| line[0...500] }.join("\n"))
165
- rescue Mechanize::ResponseCodeError
166
- @logger.error "Posting message to room #{room_id} failed. Retrying... #{content.to_s.split("\n").map { |line| line[0...500] }.join("\n")}"
167
- sleep 0.3 # A magic number I just chose for no reason
168
- retry
171
+ @logger.warn "Message too long, truncating each line to 500 chars: #{content}" if content.to_s.split("\n").any? { |line| line.length > 500 }
172
+ resp ||= nil
173
+ loop do
174
+ begin
175
+ resp = @agent.post("https://chat.#{server}.com/chats/#{room_id}/messages/new", fkey: fkey, text: content.to_s.split("\n").map { |line| line[0...500] }.join("\n"))
176
+ rescue Mechanize::ResponseCodeError
177
+ @logger.error "Posting message to room #{room_id} failed. Retrying... #{content.to_s.split("\n").map { |line| line[0...500] }.join("\n")}"
178
+ sleep 0.3 # A magic number I just chose for no reason
179
+ retry
180
+ end
181
+ break unless JSON.parse(resp.content)["id"].nil?
182
+ content = " #{content}"
169
183
  end
170
184
  return JSON.parse(resp.content)["id"].to_i
171
185
  end
@@ -1,19 +1,29 @@
1
1
  class ChatBot
2
2
  def authenticate(sites = ["stackexchange"])
3
- sites = [sites] unless sites.is_a?(Array)
3
+ if sites.is_a? Hash
4
+ sites.each do |site, cookie_str|
5
+ cookie = Mechanize::Cookie.new("acct", cookie_str)
6
+ cookie.domain = ".#{site}.com"
7
+ cookie.path = "/"
8
+ @agent.cookie_jar.add!(cookie)
9
+ end
10
+ true
11
+ else
12
+ sites = [sites] unless sites.is_a?(Array)
4
13
 
5
- openid = @agent.get "https://openid.stackexchange.com/account/login"
6
- fkey_input = openid.search "//input[@name='fkey']"
7
- fkey = fkey_input.empty? ? "" : fkey_input.attribute("value")
14
+ openid = @agent.get "https://openid.stackexchange.com/account/login"
15
+ fkey_input = openid.search "//input[@name='fkey']"
16
+ fkey = fkey_input.empty? ? "" : fkey_input.attribute("value")
8
17
 
9
- @agent.post("https://openid.stackexchange.com/account/login/submit",
10
- fkey: fkey,
11
- email: @email,
12
- password: @password)
18
+ @agent.post("https://openid.stackexchange.com/account/login/submit",
19
+ fkey: fkey,
20
+ email: @email,
21
+ password: @password)
13
22
 
14
- auth_results = sites.map { |s| site_auth(s) }
15
- failed = auth_results.any?(&:!)
16
- !failed
23
+ auth_results = sites.map { |s| site_auth(s) }
24
+ failed = auth_results.any?(&:!)
25
+ !failed
26
+ end
17
27
  end
18
28
 
19
29
  def site_auth(site)
@@ -65,7 +65,8 @@ module ChatX
65
65
  content: 'content',
66
66
  room_id: 'room_id',
67
67
  user_id: 'user_id',
68
- message_id: 'message_id'
68
+ message_id: 'message_id',
69
+ parent_id: 'parent_id'
69
70
  }
70
71
  },
71
72
  2 => {
@@ -8,22 +8,22 @@ class ChatBot
8
8
  #
9
9
  # @note This method is strictly internal.
10
10
  # @param data [Hash] It's the JSON passed by the websocket
11
- def handle(data, server: @default_server)
11
+ def handle(data, server:)
12
12
  data.each do |room, evt|
13
13
  next if evt.keys.first != 'e'
14
14
  evt['e'].each do |e|
15
15
  event_type = e['event_type'].to_i - 1
16
16
  room_id = room[1..-1].to_i
17
17
  event = ChatX::Event.new e, server, self
18
- @ws_json_logger.info "#{event.type_long}: #{event.hash} #{event.inspect}"
18
+ @ws_json_logger.info "#{event.type_long}: #{event.hash}"
19
19
  @ws_json_logger.info "Currently in rooms #{@rooms.keys} / #{current_rooms}"
20
- break if @rooms[room_id].nil?
20
+ next if @rooms[room_id].nil?
21
21
  @rooms[room_id.to_i][:events].push(event)
22
- next if @hooks[event_type.to_i].nil?
23
- @hooks[event_type.to_i].each do |rm_id, hook|
22
+ @hooks[server] ||= {}
23
+ (Array(@hooks[server][event_type.to_i])+Array(@hooks[server]['*'])+Array(@hooks['*'][event_type.to_i])).each do |rm_id, hook|
24
24
  Thread.new do
25
25
  @hook.current_room = room_id
26
- hook.call(event) if rm_id == room_id || rm_id == '*'
26
+ hook.call(event, room_id) if rm_id == room_id || rm_id == '*'
27
27
  end
28
28
  end
29
29
  end
@@ -37,9 +37,16 @@ class ChatBot
37
37
  # is triggered. It is passed one parameter, which is the event.
38
38
  # It is important to note that it will NOT be passed an {Event},
39
39
  # rather, it will be passed a sub event designated in {Event::EVENT_CLASSES}.
40
- def add_hook(room_id, event, &action)
41
- @hooks[EVENT_SHORTHAND.index(event)] ||= []
42
- @hooks[EVENT_SHORTHAND.index(event)].push [room_id, action]
40
+ def add_hook(room_id, event, server: @default_server, &action)
41
+ @hooks[server] ||= {}
42
+ @hook ||= Hook.new(self)
43
+ if event == '*'
44
+ @hooks[server]['*'] ||= []
45
+ @hooks[server]['*'].push [room_id, action]
46
+ else
47
+ @hooks[server][EVENT_SHORTHAND.index(event)] ||= []
48
+ @hooks[server][EVENT_SHORTHAND.index(event)].push [room_id, action]
49
+ end
43
50
  end
44
51
 
45
52
  # A simpler syntax for creating {add_hook} to the "Message Posted" event.
@@ -60,22 +67,25 @@ class Hook
60
67
  attr_reader :bot
61
68
  attr_accessor :current_room
62
69
 
63
- def initialize(bot)
70
+ def initialize(bot, server: nil)
64
71
  @bot = bot
72
+ @default_server = server || @bot.default_server
65
73
  end
66
74
 
67
75
  def say(message, room_id = @current_room)
68
76
  @bot.say(message, room_id)
69
77
  end
70
78
 
71
- def room(room_id, &block)
72
- room = Room.new(room_id, self)
79
+ def room(room_id, autojoin: true, server: @default_server, &block)
80
+ room = Room.new(room_id, self, server: server)
81
+ @bot.join_room(room_id.to_i, server: server) unless !autojoin || @bot.rooms.keys.include?(room_id)
73
82
  room.instance_eval(&block)
74
83
  end
75
84
 
76
- def on(event, &block)
77
- @bot.hooks[EVENT_SHORTHAND.index(event)] ||= []
78
- @bot.hooks[EVENT_SHORTHAND.index(event)].push ['*', block]
85
+ def on(event, server: @default_server, &block)
86
+ @bot.hooks[server] ||= {}
87
+ @bot.hooks[server][EVENT_SHORTHAND.index(event)] ||= []
88
+ @bot.hooks[server][EVENT_SHORTHAND.index(event)].push ['*', block]
79
89
  end
80
90
 
81
91
  def command(prefix, &block)
@@ -89,23 +99,25 @@ class Hook
89
99
  end
90
100
 
91
101
  class Room < Hook
92
- def initialize(room_id, hook)
102
+ def initialize(room_id, hook, server: nil)
93
103
  @hook = hook
94
104
  @bot = hook.bot
95
105
  @room_id = room_id
106
+ @default_server = server || @bot.default_server
96
107
  end
97
108
 
98
109
  def say(msg)
99
- @bot.say(msg, @room_id)
110
+ @bot.say(msg, @room_id, server: @default_server)
100
111
  end
101
112
 
102
113
  def reply_to(msg, reply)
103
114
  msg.reply(@bot, reply)
104
115
  end
105
116
 
106
- def on(event, &block)
107
- @bot.hooks[EVENT_SHORTHAND.index(event)] ||= []
108
- @bot.hooks[EVENT_SHORTHAND.index(event)].push [@room_id, block]
117
+ def on(event, server: @default_server, &block)
118
+ @bot.hooks[server] ||= {}
119
+ @bot.hooks[server][EVENT_SHORTHAND.index(event)] ||= []
120
+ @bot.hooks[server][EVENT_SHORTHAND.index(event)].push [@room_id, block]
109
121
  end
110
122
  end
111
123
  end
@@ -27,6 +27,8 @@ module ChatX
27
27
  @parent_id = opts[:parent_id]
28
28
  end
29
29
 
30
+ alias_method :body, :content
31
+
30
32
  def reply(bot, content)
31
33
  bot.say ":#{id} #{content}", @room.id, server: @server
32
34
  end
@@ -1,3 +1,3 @@
1
1
  class ChatBot
2
- VERSION = '0.0.0-pre3'.freeze
2
+ VERSION = '0.0.1'.freeze
3
3
  end
@@ -1,76 +1,135 @@
1
1
  class WSClient
2
- attr_reader :url, :thread, :driver, :in_rooms
3
-
4
- # Opens a websocket. This was really annoying. To open a websocket, you've got
5
- # to grab a weird uri (see {#join_room}) and pass some cookies and set the origin
6
- # header. Anywho, it opens a new socket in a new thread.
7
- # @note This method is internal. Do not use.
8
- # @param uri [String] See {#join_room}
9
- # @param cookies [String] See {#join_room}
10
- # @param server [String] The chat server to use.
11
- def initialize(url, cookies, bot, server)
12
- bot.logger.info "Opening on #{url}"
13
- @logger = Logger.new 'websocket_raw.log'
14
- @url = url
15
- @bot = bot
16
- @in_rooms = {rooms: [], last_updated: Time.now}
17
- @uri = URI.parse(url)
18
- @driver = WebSocket::Driver.client(self)
19
- @tcp = TCPSocket.new(@uri.host, 80) # (@uri.scheme == "wss" || @uri.scheme == "ws" ? 80 : 443))
20
- @restart = true
21
- @driver.add_extension(PermessageDeflate)
22
- @driver.set_header("Cookie", cookies)
23
- @driver.set_header("Origin", "https://chat.#{server}.com")
24
-
25
- @driver.on :connect, ->(_e) {}
26
-
27
- @driver.on :open, ->(_e) { @bot.logger.info "WebSocket is open!" }
2
+ attr_reader :url, :thread, :driver, :in_rooms, :dead
3
+ attr_accessor :handler
4
+
5
+ def initialize(url, cookies, bot, server, message_log: 'ws_messages.log', error_log: 'ws_errors.log', info_log: 'ws_info.log', dev_log: 'ws_dev.log')
6
+ # Setup loggers
7
+ @message_logger = Logger.new(message_log) if message_log
8
+ @error_logger = Logger.new(error_log) if error_log
9
+ @info_logger = Logger.new(info_log) if info_log
10
+ @dev_logger = Logger.new(dev_log) if dev_log
11
+
12
+ @bot = bot
13
+ @in_rooms = {rooms: [], last_update: Time.now}
14
+ @server = server
15
+
16
+ # Get WS(S) URI
17
+ @uri = URI.parse(url)
18
+ @url = "ws#{@uri.scheme.split("")[4]}://#{@uri.host}#{@uri.path}?#{@uri.query}"
19
+
20
+ # Setup handler (the action that's executed on message)
21
+ @handler = handler
22
+
23
+ # Auto-restart unless you don't
24
+ @restart = true
25
+ @dev_logger.info "Set @restart to #{@restart}"
26
+
27
+ setup(cookies: cookies, origin: "https://chat.#{@server}.com")
28
+ end
29
+
30
+ def send(message)
31
+ @message_logger.info(message)
32
+ @driver.text(message)
33
+ end
34
+
35
+ def write(data)
36
+ @socket.write(data)
37
+ end
38
+
39
+ def close
40
+ @info_logger.warn "Was told to close. Was sad."
41
+ @dead = true
42
+ @driver.close
43
+ @socket.is_a?(TCPSocket) ? @socket.shutdown : @socket.sysclose
44
+ @info_logger.info "Closed sucessfully"
45
+ rescue IOError, Errno::ENOTCONN => e
46
+ @logger.error "Recieved #{e.class} trying to close websocket. Ignoring..."
47
+ end
48
+
49
+ private
50
+
51
+ def setup(cookies: nil, origin: nil)
52
+ initialize_socket
53
+ initialize_driver(cookies: cookies, origin: origin)
54
+ launch_thread
55
+ end
56
+
57
+ def initialize_socket
58
+ if @uri.scheme[-1] == 's'
59
+ @socket = TCPSocket.new(@uri.host, 443)
60
+ @info_logger.info "Opened TCP socket for (port 443) #{@uri} (#{@socket})"
61
+ @socket = OpenSSL::SSL::SSLSocket.new(@socket)
62
+ @socket.connect
63
+ @info_logger.info "Upgrade TCP socket to SSL socket socket for #{@uri} (#{@socket})"
64
+ @info_logger.info "Current socket state: #{@socket.state}"
65
+ else
66
+ @socket = TCPSocket.new(@uri.host, 80)
67
+ @info_logger.info "Opened TCP socket for (port 80) #{@uri} (#{@socket})"
68
+ end
69
+ end
70
+
71
+ def initialize_driver(cookies: nil, origin: nil)
72
+ @driver = WebSocket::Driver.client(self)
73
+ @driver.add_extension PermessageDeflate
74
+ @driver.set_header "Cookies", cookies if cookies
75
+ origin = origin || "#{@uri.scheme}://#{@uri.host.split('.')[-2..-1].join('.')}"
76
+ @driver.set_header "Origin", origin
77
+
78
+ @info_logger.info "Creating new driver with origin: #{origin} and with#{'out' if !cookies} cookies"
79
+
80
+ @driver.on :connect, ->(_e) do
81
+ @info_logger.info "Sucessfully connected!"
82
+ end
83
+
84
+ @driver.on :open, ->(e) do
85
+ @info_logger.info "WebSocket is open!"
86
+ end
28
87
 
29
88
  @driver.on :message do |e|
30
- @logger.info "Read: #{e.data}"
31
- @bot.handle(JSON.parse(e.data))
89
+ @message_logger.info(e.data)
90
+ @bot.handle(JSON.parse(e.data), server: @server)
32
91
  @in_rooms = {rooms: JSON.parse(e.data).keys.map { |k| k[1..-1].to_i }, last_updated: Time.now}
33
92
  end
34
93
 
35
94
  @driver.on :close, ->(_e) do
36
- @bot.logger.error "The websocket is closing."
95
+ @info_logger.info "WebSocket driver is closing."
37
96
  if @restart
38
- @bot.logger.info "Attempting to reopen websocket..."
39
- @driver.start
97
+ restart
40
98
  end
41
99
  end
42
100
 
43
- @driver.on :error, ->(e) { @bot.logger.error e }
101
+ @driver.on :error, ->(e) { @error_logger.error e }
44
102
 
45
103
  @driver.start
104
+ end
105
+
106
+ def restart
107
+ @info_logger.info "Attempting ro rejoin rooms #{@in_rooms[:rooms]}"
108
+ @bot.join_rooms(@in_rooms[:rooms])
109
+ end
110
+
111
+ def parse(data)
112
+ @driver.parse(data)
113
+ end
46
114
 
115
+ def launch_thread
116
+ # @info_logger.info "Waiting for old thread to complete..." if @thread
117
+ # @thread.join if @thread
118
+ # @info_logger.info "Starting new thread!"
119
+ @dead = false
47
120
  @thread = Thread.new do
48
121
  trap("SIGINT") do
49
122
  @restart = false
123
+ @dead = true
50
124
  close
51
125
  Thread.exit
52
126
  end
53
127
  begin
54
- loop { @driver.parse(@tcp.recv(1)) }
128
+ parse(@socket.is_a?(TCPSocket) ? @socket.recv(1) : @socket.sysread(1)) until @dead
55
129
  rescue IOError, SystemCallError => e
56
- @bot.logger.debug "Recieved #{e} closing TCP socket. You shouldn't be worried :)"
130
+ @info_logger.warn "Recieved #{e} closing TCP socket. You shouldn't be worried :)"
57
131
  end
132
+ @info_logger.warn "Left TCPSocket.recv loop. If you're reading this, panic."
58
133
  end
59
134
  end
60
-
61
- def send(message)
62
- @logger.info "Write: #{message}"
63
- @driver.text(message)
64
- end
65
-
66
- def write(data)
67
- @tcp.write(data)
68
- end
69
-
70
- def close
71
- @driver.close
72
- @tcp.shutdown
73
- rescue IOError, Errno::ENOTCONN => e
74
- @bot.logger.error "Recieved #{e.class} trying to close websocket. Ignoring..."
75
- end
76
135
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chatx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0.pre.pre3
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - izwick-schachter
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-25 00:00:00.000000000 Z
11
+ date: 2018-05-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -239,9 +239,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
239
239
  version: '0'
240
240
  required_rubygems_version: !ruby/object:Gem::Requirement
241
241
  requirements:
242
- - - ">"
242
+ - - ">="
243
243
  - !ruby/object:Gem::Version
244
- version: 1.3.1
244
+ version: '0'
245
245
  requirements: []
246
246
  rubyforge_project:
247
247
  rubygems_version: 2.7.3