sleeproom 0.1.1 → 0.4.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/Gemfile.lock +7 -7
- data/bin/sleeproom +2 -1
- data/lib/sleeproom/cli.rb +13 -8
- data/lib/sleeproom/record/api/api.rb +3 -0
- data/lib/sleeproom/record/api/streaming_api.rb +5 -1
- data/lib/sleeproom/record/record.rb +55 -21
- data/lib/sleeproom/record/websocket.rb +5 -10
- data/lib/sleeproom/utils.rb +29 -7
- data/lib/sleeproom/version.rb +1 -1
- data/sleeproom.gemspec +6 -6
- metadata +26 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e8ca3fc07a7a4dc3ed69aec76ad0d267bcaa60a9b4ef5c0adea7d068fe2c592
|
4
|
+
data.tar.gz: 78b13ce764ae80d0b48d9ca5fa59c8bfe929572b90f3baa248d8412068ff606d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69ebf1096e11fe91773de30d73b2c6801a851e85680bbcf5e94839a9e546f0268528bea9f7940862c882eda2da838c5485f957fbabe03fa57ca718b9e1c324b1
|
7
|
+
data.tar.gz: 076171c25ac3a74bcde2104f7db59e3cfbd549319a820a35e689eaee267f539fa6c17d104510b9a6c364c6d3dbca0bae83fff13bd5008a5a9f4915ab88cf05c5
|
data/Gemfile.lock
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sleeproom (0.
|
5
|
-
async
|
6
|
-
async-http-faraday
|
7
|
-
async-websocket
|
8
|
-
colorize
|
9
|
-
configatron
|
10
|
-
terminal-table
|
4
|
+
sleeproom (0.4.1)
|
5
|
+
async (~> 1.26.0)
|
6
|
+
async-http-faraday (~> 0.9.0)
|
7
|
+
async-websocket (~> 0.15.0)
|
8
|
+
colorize (~> 0.8.0)
|
9
|
+
configatron (~> 4.5.0)
|
10
|
+
terminal-table (~> 1.8.0)
|
11
11
|
|
12
12
|
GEM
|
13
13
|
remote: https://rubygems.org/
|
data/bin/sleeproom
CHANGED
data/lib/sleeproom/cli.rb
CHANGED
@@ -8,6 +8,7 @@ module SleepRoom
|
|
8
8
|
class CLI
|
9
9
|
# @param argv [Array]
|
10
10
|
def initialize(argv)
|
11
|
+
SleepRoom.reload_config
|
11
12
|
@options = {}
|
12
13
|
build
|
13
14
|
unless argv.empty?
|
@@ -17,8 +18,6 @@ module SleepRoom
|
|
17
18
|
SleepRoom::Record::Tasks.status
|
18
19
|
elsif action == "start"
|
19
20
|
SleepRoom::Record::Tasks.start
|
20
|
-
elsif action == "download"
|
21
|
-
raise "未实现"
|
22
21
|
elsif action == "exit"
|
23
22
|
SleepRoom::Record::Tasks.stop
|
24
23
|
end
|
@@ -53,18 +52,24 @@ module SleepRoom
|
|
53
52
|
SleepRoom::Record::Tasks.add(room[0].to_s, room[1].to_s)
|
54
53
|
end
|
55
54
|
|
56
|
-
opt.on("-r", "--remove [
|
55
|
+
opt.on("-r", "--remove [ROOM]", "从监视列表移除") do |room|
|
57
56
|
SleepRoom::Record::Tasks.remove(room)
|
58
57
|
end
|
59
58
|
|
60
|
-
opt.on("-
|
61
|
-
|
59
|
+
opt.on("-d", "--download [ROOM]", "录制指定房间") do |room|
|
60
|
+
raise Error.new("房间名不能为空") if room.nil?
|
61
|
+
if room.match?("https://www.showroom-live.com/")
|
62
|
+
room = room.match(/https:\/\/www.showroom-live.com\/(.*)/)[1]
|
63
|
+
end
|
64
|
+
write_status = SleepRoom::Record::WriteStatus.new
|
65
|
+
record = SleepRoom::Record::Showroom.new(room: room, group: "download", queue: write_status)
|
66
|
+
record.record
|
62
67
|
end
|
63
68
|
|
64
|
-
opt.on("-
|
65
|
-
@options[:
|
69
|
+
opt.on("-v", "--verbose", "Print log") do
|
70
|
+
@options[:verbose] = true
|
66
71
|
end
|
67
|
-
|
72
|
+
|
68
73
|
opt.on_tail("--version", "Print version") do
|
69
74
|
STDOUT.puts(opt.version)
|
70
75
|
end
|
@@ -10,6 +10,7 @@ module SleepRoom
|
|
10
10
|
module Record
|
11
11
|
module API
|
12
12
|
class Error < StandardError; end
|
13
|
+
class NotFoundError < Error; end
|
13
14
|
ROOM_URL = "https://www.showroom-live.com"
|
14
15
|
ROOM_API = "https://www.showroom-live.com/api/room/status"
|
15
16
|
STREAMING_API = "https://www.showroom-live.com/api/live/streaming_url"
|
@@ -21,6 +22,8 @@ module SleepRoom
|
|
21
22
|
http = Faraday.get(url, nil, {"User-Agent": USER_AGENT})
|
22
23
|
if http.status == 200
|
23
24
|
@json = JSON.parse(http.body)
|
25
|
+
elsif http.status == 404
|
26
|
+
raise NotFoundError
|
24
27
|
else
|
25
28
|
raise Error, "HTTP Error: #{http.status}"
|
26
29
|
end
|
@@ -15,7 +15,11 @@ module SleepRoom
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def streaming_url
|
18
|
-
@json["streaming_url_list"].
|
18
|
+
if @json["streaming_url_list"].nil?
|
19
|
+
raise Error.new("streaming url is null.")
|
20
|
+
else
|
21
|
+
@json["streaming_url_list"].sort_by{|hash| -hash["quality"]}.first["url"]
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
@@ -19,12 +19,12 @@ module SleepRoom
|
|
19
19
|
def record(reconnection: false)
|
20
20
|
room = @room
|
21
21
|
Async do |task|
|
22
|
-
|
22
|
+
set_room_info
|
23
23
|
task.async do |t|
|
24
|
-
while
|
24
|
+
while @is_live
|
25
25
|
if status = SleepRoom.load_config(:status).find{|hash| hash[:room] == room}
|
26
26
|
if !status[:pid].nil?
|
27
|
-
break if SleepRoom.running?(pid) == false
|
27
|
+
break if SleepRoom.running?(status[:pid]) == false
|
28
28
|
else
|
29
29
|
break
|
30
30
|
end
|
@@ -34,11 +34,6 @@ module SleepRoom
|
|
34
34
|
t.sleep 60
|
35
35
|
end
|
36
36
|
end.wait
|
37
|
-
@room_id = api.room_id
|
38
|
-
@room_name = api.room_name
|
39
|
-
@is_live = api.live?
|
40
|
-
@broadcast_host = api.broadcast_host
|
41
|
-
@broadcast_key = api.broadcast_key
|
42
37
|
if @is_live
|
43
38
|
start_time = Time.now
|
44
39
|
log("Live broadcast.")
|
@@ -55,12 +50,7 @@ module SleepRoom
|
|
55
50
|
if @running == false && @reconnection == false
|
56
51
|
start_websocket
|
57
52
|
elsif @reconnection == true
|
58
|
-
|
59
|
-
@room_id = api.room_id
|
60
|
-
@room_name = api.room_name
|
61
|
-
@is_live = api.live?
|
62
|
-
@broadcast_host = api.broadcast_host
|
63
|
-
@broadcast_key = api.broadcast_key
|
53
|
+
set_room_info
|
64
54
|
start_websocket
|
65
55
|
@reconnection = false
|
66
56
|
end
|
@@ -122,15 +112,27 @@ module SleepRoom
|
|
122
112
|
end
|
123
113
|
|
124
114
|
Async do |task|
|
115
|
+
last_ack = nil
|
116
|
+
last_ping = nil
|
125
117
|
while @running && @downlaoding == false
|
126
|
-
|
127
|
-
if !
|
118
|
+
queue = ws.queue.items
|
119
|
+
if !queue.empty?
|
120
|
+
queue.each do |event|
|
121
|
+
case event[:event]
|
122
|
+
when :ack
|
123
|
+
last_ack = event[:time]
|
124
|
+
when :ping
|
125
|
+
last_ping = event[:ping]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
if !last_ack.nil? && Time.now.to_i - last_ack.to_i > 65
|
128
130
|
ws.running = false
|
129
131
|
@running = false
|
130
132
|
task.stop
|
131
133
|
end
|
132
|
-
waiting_live(
|
133
|
-
task.sleep
|
134
|
+
waiting_live({last_ack: last_ack})
|
135
|
+
task.sleep 1
|
134
136
|
end
|
135
137
|
end
|
136
138
|
task.children.each(&:wait)
|
@@ -139,10 +141,31 @@ module SleepRoom
|
|
139
141
|
@running = false
|
140
142
|
end
|
141
143
|
end
|
144
|
+
|
145
|
+
def set_room_info
|
146
|
+
api = API::RoomAPI.new(@room)
|
147
|
+
@room_id = api.room_id
|
148
|
+
@room_name = api.room_name
|
149
|
+
@is_live = api.live?
|
150
|
+
@broadcast_host = api.broadcast_host
|
151
|
+
@broadcast_key = api.broadcast_key
|
152
|
+
rescue API::NotFoundError
|
153
|
+
SleepRoom.error("[#{@room}] The room does not exist.")
|
154
|
+
log("Task stopped.")
|
155
|
+
Async::Task.current.stop
|
156
|
+
rescue => e
|
157
|
+
SleepRoom.error(e.message)
|
158
|
+
log("[setRoomInfo] Retry...")
|
159
|
+
retry
|
160
|
+
end
|
142
161
|
|
143
162
|
def parse_streaming_url(task: Async::Task.current)
|
144
163
|
api = API::StreamingAPI.new(@room_id)
|
145
164
|
streaming_url_list = api.streaming_url
|
165
|
+
rescue => e
|
166
|
+
SleepRoom.error(e.full_message)
|
167
|
+
log("[parseStreamingUrl] Retry...")
|
168
|
+
retry
|
146
169
|
end
|
147
170
|
|
148
171
|
def build_output(task: Async::Task.current)
|
@@ -167,8 +190,9 @@ module SleepRoom
|
|
167
190
|
download_pid: pid
|
168
191
|
})
|
169
192
|
task.async do |t|
|
170
|
-
|
171
|
-
|
193
|
+
loop do
|
194
|
+
live = API::RoomAPI.new(@room).live?
|
195
|
+
if !SleepRoom.running?(pid) && !live
|
172
196
|
log("Download complete.")
|
173
197
|
@downlaoding = false
|
174
198
|
@queue.add({
|
@@ -179,8 +203,18 @@ module SleepRoom
|
|
179
203
|
status: :complete,
|
180
204
|
})
|
181
205
|
break
|
206
|
+
elsif live && !SleepRoom.running?(pid)
|
207
|
+
log("Minyami crash.")
|
208
|
+
streaming_url = parse_streaming_url
|
209
|
+
output = build_output
|
210
|
+
pid = SleepRoom::Record.call_minyami(url: streaming_url, output: output)
|
211
|
+
elsif !live && SleepRoom.running?(pid)
|
212
|
+
log("Live stop.")
|
182
213
|
end
|
183
|
-
t.sleep
|
214
|
+
t.sleep 120
|
215
|
+
rescue Faraday::ConnectionFailed
|
216
|
+
log("Network error.")
|
217
|
+
retry
|
184
218
|
end
|
185
219
|
end.wait
|
186
220
|
end
|
@@ -6,12 +6,13 @@ require "json"
|
|
6
6
|
module SleepRoom
|
7
7
|
module Record
|
8
8
|
class WebSocket
|
9
|
+
attr_accessor :queue
|
9
10
|
def initialize(room:, broadcast_key:, url:)
|
10
11
|
@room = room
|
11
12
|
@url = "wss://" + url
|
12
13
|
@broadcast_key = broadcast_key
|
13
14
|
@running = false
|
14
|
-
@
|
15
|
+
@queue = Async::Queue.new
|
15
16
|
end
|
16
17
|
|
17
18
|
def connect(task: Async::Task.current)
|
@@ -23,12 +24,12 @@ module SleepRoom
|
|
23
24
|
connection.write("SUB\t#{@broadcast_key}")
|
24
25
|
connection.flush
|
25
26
|
log("Connect to websocket server.")
|
26
|
-
@
|
27
|
+
@queue.enqueue({event: :connect, time: Time.now})
|
27
28
|
|
28
29
|
ping_task = task.async do |sub|
|
29
30
|
while @running
|
30
31
|
sub.sleep 60
|
31
|
-
@
|
32
|
+
@queue.enqueue({event: :ping, time: Time.now})
|
32
33
|
connection.write("PING\tshowroom")
|
33
34
|
connection.flush
|
34
35
|
end
|
@@ -44,12 +45,10 @@ module SleepRoom
|
|
44
45
|
end
|
45
46
|
|
46
47
|
while message = connection.read
|
47
|
-
@status[:last_update]
|
48
48
|
if message == "ACK\tshowroom"
|
49
|
-
@
|
49
|
+
@queue.enqueue({event: :ack, time: Time.now}) if message == "ACK\tshowroom"
|
50
50
|
end
|
51
51
|
if message.start_with?("MSG")
|
52
|
-
@status[:last_msg] = Time.now
|
53
52
|
begin
|
54
53
|
yield JSON.parse(message.split("\t")[2])
|
55
54
|
rescue => e
|
@@ -79,10 +78,6 @@ module SleepRoom
|
|
79
78
|
@connection.close
|
80
79
|
end
|
81
80
|
|
82
|
-
def status
|
83
|
-
@status
|
84
|
-
end
|
85
|
-
|
86
81
|
def log(str)
|
87
82
|
SleepRoom.info("[#{@room}] #{str}")
|
88
83
|
end
|
data/lib/sleeproom/utils.rb
CHANGED
@@ -4,6 +4,7 @@ require "configatron"
|
|
4
4
|
require "colorize"
|
5
5
|
require "fileutils"
|
6
6
|
require "yaml"
|
7
|
+
require "logger"
|
7
8
|
|
8
9
|
module SleepRoom
|
9
10
|
class Error < StandardError; end
|
@@ -111,10 +112,6 @@ module SleepRoom
|
|
111
112
|
file: {
|
112
113
|
use: true,
|
113
114
|
path: "#{sleeproom_dir}/log"
|
114
|
-
},
|
115
|
-
websocket: {
|
116
|
-
log: true,
|
117
|
-
ping_log: false
|
118
115
|
}
|
119
116
|
}
|
120
117
|
}
|
@@ -197,18 +194,43 @@ module SleepRoom
|
|
197
194
|
# @param string [String]
|
198
195
|
# @return [nil]
|
199
196
|
def self.info(string)
|
200
|
-
|
197
|
+
log(:info, "[INFO] #{string}".colorize(:white))
|
201
198
|
end
|
202
199
|
|
203
200
|
# @param string [String]
|
204
201
|
# @return [nil]
|
205
202
|
def self.warning(string)
|
206
|
-
|
203
|
+
log(:warning, "[WARN] #{string}".colorize(:yellow))
|
207
204
|
end
|
208
205
|
|
209
206
|
# @param string [String]
|
210
207
|
# @return [nil]
|
211
208
|
def self.error(string)
|
212
|
-
|
209
|
+
log(:error, "[ERROR] #{string}".colorize(:red))
|
210
|
+
end
|
211
|
+
|
212
|
+
def self.log(type, log)
|
213
|
+
case type
|
214
|
+
when :info
|
215
|
+
puts(log)
|
216
|
+
when :warning
|
217
|
+
warn(log)
|
218
|
+
when :error
|
219
|
+
puts(log)
|
220
|
+
end
|
221
|
+
file_logger(type, log) if configatron.logger.file.use == true
|
222
|
+
end
|
223
|
+
|
224
|
+
def self.file_logger(type, log)
|
225
|
+
path = configatron.logger.file.path
|
226
|
+
logger = Logger.new(path)
|
227
|
+
case type
|
228
|
+
when :info
|
229
|
+
logger.info(log)
|
230
|
+
when :warning
|
231
|
+
logger.warning(log)
|
232
|
+
when :error
|
233
|
+
logger.error(log)
|
234
|
+
end
|
213
235
|
end
|
214
236
|
end
|
data/lib/sleeproom/version.rb
CHANGED
data/sleeproom.gemspec
CHANGED
@@ -25,12 +25,12 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.executables = ["sleeproom"]
|
26
26
|
spec.require_paths = ["lib"]
|
27
27
|
|
28
|
-
spec.add_runtime_dependency("colorize")
|
29
|
-
spec.add_runtime_dependency("async")
|
30
|
-
spec.add_runtime_dependency("async-websocket")
|
31
|
-
spec.add_runtime_dependency("configatron")
|
32
|
-
spec.add_runtime_dependency("async-http-faraday")
|
33
|
-
spec.add_runtime_dependency("terminal-table")
|
28
|
+
spec.add_runtime_dependency("colorize", "~> 0.8.0")
|
29
|
+
spec.add_runtime_dependency("async", "~> 1.26.0")
|
30
|
+
spec.add_runtime_dependency("async-websocket", "~> 0.15.0")
|
31
|
+
spec.add_runtime_dependency("configatron", "~> 4.5.0")
|
32
|
+
spec.add_runtime_dependency("async-http-faraday", "~> 0.9.0")
|
33
|
+
spec.add_runtime_dependency("terminal-table", "~> 1.8.0")
|
34
34
|
|
35
35
|
spec.post_install_message = <<~STR
|
36
36
|
SleepRoom 需要:
|
metadata
CHANGED
@@ -1,99 +1,99 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sleeproom
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Koell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-06-
|
11
|
+
date: 2020-06-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.8.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.8.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: async
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 1.26.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 1.26.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: async-websocket
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 0.15.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 0.15.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: configatron
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version:
|
61
|
+
version: 4.5.0
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version:
|
68
|
+
version: 4.5.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: async-http-faraday
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: 0.9.0
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: 0.9.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: terminal-table
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
89
|
+
version: 1.8.0
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
96
|
+
version: 1.8.0
|
97
97
|
description:
|
98
98
|
email:
|
99
99
|
- i@wug.moe
|