chatx 0.0.0.pre.pre3 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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