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 +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
|