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 +4 -4
- data/README.md +11 -9
- data/lib/chatx.rb +28 -14
- data/lib/chatx/auth.rb +21 -11
- data/lib/chatx/events.rb +2 -1
- data/lib/chatx/hooks.rb +32 -20
- data/lib/chatx/models/message.rb +2 -0
- data/lib/chatx/version.rb +1 -1
- data/lib/chatx/websocket.rb +109 -50
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21350e4e1273f200f9fb7392ef983d0d937669407963ecb1d684a5c8ea9bb5e2
|
4
|
+
data.tar.gz: f1fa848b2d9512a8fcc64aa1ad638414a44014b773a1eda2444eccacc5394d17
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
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).
|
data/lib/chatx.rb
CHANGED
@@ -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?
|
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
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
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
|
data/lib/chatx/auth.rb
CHANGED
@@ -1,19 +1,29 @@
|
|
1
1
|
class ChatBot
|
2
2
|
def authenticate(sites = ["stackexchange"])
|
3
|
-
|
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
|
-
|
6
|
-
|
7
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
18
|
+
@agent.post("https://openid.stackexchange.com/account/login/submit",
|
19
|
+
fkey: fkey,
|
20
|
+
email: @email,
|
21
|
+
password: @password)
|
13
22
|
|
14
|
-
|
15
|
-
|
16
|
-
|
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)
|
data/lib/chatx/events.rb
CHANGED
data/lib/chatx/hooks.rb
CHANGED
@@ -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:
|
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}
|
18
|
+
@ws_json_logger.info "#{event.type_long}: #{event.hash}"
|
19
19
|
@ws_json_logger.info "Currently in rooms #{@rooms.keys} / #{current_rooms}"
|
20
|
-
|
20
|
+
next if @rooms[room_id].nil?
|
21
21
|
@rooms[room_id.to_i][:events].push(event)
|
22
|
-
|
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[
|
42
|
-
@
|
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[
|
78
|
-
@bot.hooks[EVENT_SHORTHAND.index(event)]
|
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[
|
108
|
-
@bot.hooks[EVENT_SHORTHAND.index(event)]
|
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
|
data/lib/chatx/models/message.rb
CHANGED
data/lib/chatx/version.rb
CHANGED
data/lib/chatx/websocket.rb
CHANGED
@@ -1,76 +1,135 @@
|
|
1
1
|
class WSClient
|
2
|
-
attr_reader :url, :thread, :driver, :in_rooms
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
bot
|
13
|
-
@
|
14
|
-
@
|
15
|
-
|
16
|
-
|
17
|
-
@uri
|
18
|
-
@
|
19
|
-
|
20
|
-
|
21
|
-
@
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
@
|
26
|
-
|
27
|
-
|
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
|
-
@
|
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
|
-
@
|
95
|
+
@info_logger.info "WebSocket driver is closing."
|
37
96
|
if @restart
|
38
|
-
|
39
|
-
@driver.start
|
97
|
+
restart
|
40
98
|
end
|
41
99
|
end
|
42
100
|
|
43
|
-
@driver.on :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
|
-
|
128
|
+
parse(@socket.is_a?(TCPSocket) ? @socket.recv(1) : @socket.sysread(1)) until @dead
|
55
129
|
rescue IOError, SystemCallError => e
|
56
|
-
@
|
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.
|
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:
|
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:
|
244
|
+
version: '0'
|
245
245
|
requirements: []
|
246
246
|
rubyforge_project:
|
247
247
|
rubygems_version: 2.7.3
|