sleeproom 0.4.3 → 0.9.0.pre1
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 +3 -2
- data/Gemfile.lock +51 -17
- data/Rakefile +3 -1
- data/bin/sleeproom +1 -2
- data/lib/sleeproom/async/websocket.rb +8 -6
- data/lib/sleeproom/cli.rb +21 -19
- data/lib/sleeproom/record.rb +8 -5
- data/lib/sleeproom/record/api/api.rb +3 -7
- data/lib/sleeproom/record/api/room.rb +2 -1
- data/lib/sleeproom/record/api/room_api.rb +2 -1
- data/lib/sleeproom/record/api/streaming_api.rb +4 -3
- data/lib/sleeproom/record/record.rb +134 -182
- data/lib/sleeproom/record/tasks.rb +64 -55
- data/lib/sleeproom/record/web/app.rb +53 -0
- data/lib/sleeproom/record/websocket.rb +81 -66
- data/lib/sleeproom/record/write_status.rb +29 -2
- data/lib/sleeproom/utils.rb +37 -6
- data/lib/sleeproom/version.rb +1 -1
- data/sleeproom.gemspec +7 -3
- metadata +68 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1164a0ff4adcb7d05b1a089972e1d895a10a334eb0d42be870a13198efbeec65
|
|
4
|
+
data.tar.gz: a22e22bc58e4db57da69b233d81026f6449645a4755a93c2353cb40430ab3ad9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2999e46c33eaf5eed3fe5687e7815f74fcf0b0b702a9fc25113f10234c4d8e2d54d4023d460e7fb54a1f84a02b266c3d3f27dfb823ec0e16a0db2292ae6e8dad
|
|
7
|
+
data.tar.gz: 284d500d464e090b83dc7d72a4e1ed1e6db3322095e60f93e079359a0c25a8cef12804b3c9eb3f3a0a7a6fd45aaf32dbd684b03284eacd3317cbb33df367e968
|
data/Gemfile
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
source "https://rubygems.org"
|
|
2
4
|
|
|
3
5
|
# Specify your gem's dependencies in sleeproom.gemspec
|
|
4
6
|
gemspec
|
|
5
7
|
|
|
6
|
-
gem "rake", "~>
|
|
8
|
+
gem "rake", "~> 13.0"
|
|
7
9
|
gem "rspec", "~> 3.0"
|
|
8
|
-
gem "rubocop", "~> 0.79.0"
|
|
9
10
|
gem "rubocop-github"
|
|
10
11
|
gem "rubocop-performance", require: false
|
data/Gemfile.lock
CHANGED
|
@@ -1,28 +1,35 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
sleeproom (0.
|
|
4
|
+
sleeproom (0.9.0.pre1)
|
|
5
5
|
async (~> 1.26.0)
|
|
6
6
|
async-http-faraday (~> 0.9.0)
|
|
7
7
|
async-websocket (~> 0.15.0)
|
|
8
|
+
backports (~> 3.0)
|
|
8
9
|
colorize (~> 0.8.0)
|
|
9
10
|
configatron (~> 4.5.0)
|
|
11
|
+
falcon (~> 0.36.0)
|
|
12
|
+
roda (~> 3.33.0)
|
|
13
|
+
ruby-next-core (~> 0.9.0)
|
|
10
14
|
terminal-table (~> 1.8.0)
|
|
11
15
|
|
|
12
16
|
GEM
|
|
13
17
|
remote: https://rubygems.org/
|
|
14
18
|
specs:
|
|
15
|
-
activesupport (6.0.3.
|
|
19
|
+
activesupport (6.0.3.2)
|
|
16
20
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
17
21
|
i18n (>= 0.7, < 2)
|
|
18
22
|
minitest (~> 5.1)
|
|
19
23
|
tzinfo (~> 1.1)
|
|
20
24
|
zeitwerk (~> 2.2, >= 2.2.2)
|
|
21
|
-
ast (2.4.
|
|
22
|
-
async (1.26.
|
|
25
|
+
ast (2.4.1)
|
|
26
|
+
async (1.26.2)
|
|
23
27
|
console (~> 1.0)
|
|
24
28
|
nio4r (~> 2.3)
|
|
25
29
|
timers (~> 4.1)
|
|
30
|
+
async-container (0.16.6)
|
|
31
|
+
async (~> 1.0)
|
|
32
|
+
async-io (~> 1.26)
|
|
26
33
|
async-http (0.52.4)
|
|
27
34
|
async (~> 1.25)
|
|
28
35
|
async-io (~> 1.28)
|
|
@@ -30,6 +37,8 @@ GEM
|
|
|
30
37
|
protocol-http (~> 0.20.0)
|
|
31
38
|
protocol-http1 (~> 0.13.0)
|
|
32
39
|
protocol-http2 (~> 0.14.0)
|
|
40
|
+
async-http-cache (0.2.0)
|
|
41
|
+
async-http (~> 0.51)
|
|
33
42
|
async-http-faraday (0.9.0)
|
|
34
43
|
async-http (~> 0.42)
|
|
35
44
|
faraday
|
|
@@ -41,22 +50,40 @@ GEM
|
|
|
41
50
|
async-http (~> 0.51)
|
|
42
51
|
async-io (~> 1.23)
|
|
43
52
|
protocol-websocket (~> 0.7.0)
|
|
53
|
+
backports (3.18.1)
|
|
54
|
+
build-environment (1.13.0)
|
|
44
55
|
colorize (0.8.1)
|
|
45
56
|
concurrent-ruby (1.1.6)
|
|
46
57
|
configatron (4.5.1)
|
|
47
58
|
console (1.8.2)
|
|
48
59
|
diff-lcs (1.3)
|
|
60
|
+
falcon (0.36.4)
|
|
61
|
+
async (~> 1.13)
|
|
62
|
+
async-container (~> 0.16.0)
|
|
63
|
+
async-http (~> 0.52.0)
|
|
64
|
+
async-http-cache (~> 0.2.0)
|
|
65
|
+
async-io (~> 1.22)
|
|
66
|
+
build-environment (~> 1.13)
|
|
67
|
+
localhost (~> 1.1)
|
|
68
|
+
process-metrics (~> 0.2.0)
|
|
69
|
+
rack (>= 1.0)
|
|
70
|
+
samovar (~> 2.1)
|
|
49
71
|
faraday (1.0.1)
|
|
50
72
|
multipart-post (>= 1.2, < 3)
|
|
51
73
|
i18n (1.8.3)
|
|
52
74
|
concurrent-ruby (~> 1.0)
|
|
53
75
|
jaro_winkler (1.5.4)
|
|
76
|
+
localhost (1.1.6)
|
|
77
|
+
mapping (1.1.1)
|
|
54
78
|
minitest (5.14.1)
|
|
55
79
|
multipart-post (2.1.1)
|
|
56
80
|
nio4r (2.5.2)
|
|
57
|
-
parallel (1.19.
|
|
58
|
-
parser (2.7.1.
|
|
59
|
-
ast (~> 2.4.
|
|
81
|
+
parallel (1.19.2)
|
|
82
|
+
parser (2.7.1.4)
|
|
83
|
+
ast (~> 2.4.1)
|
|
84
|
+
process-metrics (0.2.1)
|
|
85
|
+
console (~> 1.8)
|
|
86
|
+
samovar (~> 2.1)
|
|
60
87
|
protocol-hpack (1.4.2)
|
|
61
88
|
protocol-http (0.20.0)
|
|
62
89
|
protocol-http1 (0.13.0)
|
|
@@ -67,9 +94,12 @@ GEM
|
|
|
67
94
|
protocol-websocket (0.7.4)
|
|
68
95
|
protocol-http (~> 0.2)
|
|
69
96
|
protocol-http1 (~> 0.2)
|
|
70
|
-
rack (2.2.
|
|
97
|
+
rack (2.2.3)
|
|
71
98
|
rainbow (3.0.0)
|
|
72
|
-
rake (
|
|
99
|
+
rake (13.0.1)
|
|
100
|
+
rexml (3.2.4)
|
|
101
|
+
roda (3.33.0)
|
|
102
|
+
rack
|
|
73
103
|
rspec (3.9.0)
|
|
74
104
|
rspec-core (~> 3.9.0)
|
|
75
105
|
rspec-expectations (~> 3.9.0)
|
|
@@ -83,31 +113,36 @@ GEM
|
|
|
83
113
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
84
114
|
rspec-support (~> 3.9.0)
|
|
85
115
|
rspec-support (3.9.3)
|
|
86
|
-
rubocop (0.
|
|
116
|
+
rubocop (0.82.0)
|
|
87
117
|
jaro_winkler (~> 1.5.1)
|
|
88
118
|
parallel (~> 1.10)
|
|
89
119
|
parser (>= 2.7.0.1)
|
|
90
120
|
rainbow (>= 2.2.2, < 4.0)
|
|
121
|
+
rexml
|
|
91
122
|
ruby-progressbar (~> 1.7)
|
|
92
|
-
unicode-display_width (>= 1.4.0, <
|
|
123
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
|
93
124
|
rubocop-github (0.16.0)
|
|
94
125
|
rubocop (<= 0.82.0)
|
|
95
126
|
rubocop-performance (~> 1.0)
|
|
96
127
|
rubocop-rails (~> 2.0)
|
|
97
128
|
rubocop-performance (1.6.1)
|
|
98
129
|
rubocop (>= 0.71.0)
|
|
99
|
-
rubocop-rails (2.
|
|
100
|
-
activesupport
|
|
130
|
+
rubocop-rails (2.6.0)
|
|
131
|
+
activesupport (>= 4.2.0)
|
|
101
132
|
rack (>= 1.1)
|
|
102
|
-
rubocop (>= 0.
|
|
133
|
+
rubocop (>= 0.82.0)
|
|
134
|
+
ruby-next-core (0.9.2)
|
|
103
135
|
ruby-progressbar (1.10.1)
|
|
136
|
+
samovar (2.1.4)
|
|
137
|
+
console (~> 1.0)
|
|
138
|
+
mapping (~> 1.0)
|
|
104
139
|
terminal-table (1.8.0)
|
|
105
140
|
unicode-display_width (~> 1.1, >= 1.1.1)
|
|
106
141
|
thread_safe (0.3.6)
|
|
107
142
|
timers (4.3.0)
|
|
108
143
|
tzinfo (1.2.7)
|
|
109
144
|
thread_safe (~> 0.1)
|
|
110
|
-
unicode-display_width (1.
|
|
145
|
+
unicode-display_width (1.7.0)
|
|
111
146
|
zeitwerk (2.3.0)
|
|
112
147
|
|
|
113
148
|
PLATFORMS
|
|
@@ -115,9 +150,8 @@ PLATFORMS
|
|
|
115
150
|
x64-mingw32
|
|
116
151
|
|
|
117
152
|
DEPENDENCIES
|
|
118
|
-
rake (~>
|
|
153
|
+
rake (~> 13.0)
|
|
119
154
|
rspec (~> 3.0)
|
|
120
|
-
rubocop (~> 0.79.0)
|
|
121
155
|
rubocop-github
|
|
122
156
|
rubocop-performance
|
|
123
157
|
sleeproom!
|
data/Rakefile
CHANGED
data/bin/sleeproom
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "async/websocket/connection"
|
|
2
4
|
class WebSocketConnection < Async::WebSocket::Connection
|
|
3
5
|
def read
|
|
@@ -5,16 +7,16 @@ class WebSocketConnection < Async::WebSocket::Connection
|
|
|
5
7
|
parse(buffer)
|
|
6
8
|
end
|
|
7
9
|
end
|
|
8
|
-
|
|
10
|
+
|
|
9
11
|
def write(object)
|
|
10
12
|
super(dump(object))
|
|
11
13
|
end
|
|
12
|
-
|
|
14
|
+
|
|
13
15
|
def parse(buffer)
|
|
14
|
-
|
|
16
|
+
buffer
|
|
15
17
|
end
|
|
16
|
-
|
|
18
|
+
|
|
17
19
|
def dump(object)
|
|
18
|
-
|
|
20
|
+
object
|
|
19
21
|
end
|
|
20
|
-
end
|
|
22
|
+
end
|
data/lib/sleeproom/cli.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "backports/2.5" if RUBY_VERSION < "2.5.0"
|
|
4
|
+
require "ruby-next"
|
|
3
5
|
require "optparse"
|
|
4
6
|
require "yaml"
|
|
5
7
|
require "sleeproom/record"
|
|
@@ -11,15 +13,16 @@ module SleepRoom
|
|
|
11
13
|
SleepRoom.reload_config
|
|
12
14
|
@options = {}
|
|
13
15
|
build
|
|
14
|
-
|
|
16
|
+
if argv.empty? == false
|
|
15
17
|
@parser.parse!(argv)
|
|
16
18
|
action = argv.shift
|
|
17
|
-
|
|
19
|
+
case action
|
|
20
|
+
when "status"
|
|
18
21
|
SleepRoom::Record::Tasks.status
|
|
19
|
-
|
|
20
|
-
SleepRoom::Record::Tasks.start
|
|
21
|
-
|
|
22
|
-
SleepRoom::Record::Tasks.
|
|
22
|
+
when "start"
|
|
23
|
+
SleepRoom::Record::Tasks.start(**@options)
|
|
24
|
+
when "lists"
|
|
25
|
+
SleepRoom::Record::Tasks.lists
|
|
23
26
|
end
|
|
24
27
|
exit(0)
|
|
25
28
|
else
|
|
@@ -28,22 +31,20 @@ module SleepRoom
|
|
|
28
31
|
end
|
|
29
32
|
end
|
|
30
33
|
|
|
31
|
-
# @return [void]
|
|
32
|
-
def run
|
|
33
|
-
SleepRoom::Record::Tasks.start
|
|
34
|
-
end
|
|
35
|
-
|
|
36
34
|
# @return [void]
|
|
37
35
|
def build
|
|
38
36
|
@parser = OptionParser.new do |opt|
|
|
39
37
|
opt.version = "SleepRoom / #{SleepRoom::VERSION}"
|
|
40
|
-
opt.banner =
|
|
38
|
+
opt.banner = opt.version.to_s
|
|
41
39
|
opt.banner += "\nUsage: sleeproom [Options]\n\n"
|
|
42
40
|
|
|
43
41
|
opt.banner += "Action:\n"
|
|
44
42
|
opt.banner += "status".rjust(10)
|
|
45
43
|
opt.banner += "显示任务状态".rjust(33)
|
|
46
44
|
opt.banner += "\n"
|
|
45
|
+
opt.banner += "list".rjust(8)
|
|
46
|
+
opt.banner += "显示录制列表".rjust(35)
|
|
47
|
+
opt.banner += "\n"
|
|
47
48
|
opt.banner += "exit".rjust(8)
|
|
48
49
|
opt.banner += "关闭任务队列".rjust(35)
|
|
49
50
|
opt.banner += "\n\nCommands:\n"
|
|
@@ -57,19 +58,20 @@ module SleepRoom
|
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
opt.on("-d", "--download [ROOM]", "录制指定房间") do |room|
|
|
60
|
-
raise Error
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
end
|
|
61
|
+
raise Error, "房间名不能为空" if room.nil?
|
|
62
|
+
|
|
63
|
+
room = room.match(%r{https://www.showroom-live.com/(.*)})[1] if room.match?("https://www.showroom-live.com/")
|
|
64
64
|
write_status = SleepRoom::Record::WriteStatus.new
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
Async do
|
|
66
|
+
record = SleepRoom::Record::Showroom.new(room: room, group: "download", queue: write_status)
|
|
67
|
+
record.record
|
|
68
|
+
end
|
|
67
69
|
end
|
|
68
70
|
|
|
69
71
|
opt.on("-v", "--verbose", "Print log") do
|
|
70
72
|
@options[:verbose] = true
|
|
71
73
|
end
|
|
72
|
-
|
|
74
|
+
|
|
73
75
|
opt.on_tail("--version", "Print version") do
|
|
74
76
|
STDOUT.puts(opt.version)
|
|
75
77
|
end
|
data/lib/sleeproom/record.rb
CHANGED
|
@@ -8,13 +8,16 @@ require "sleeproom/record/record"
|
|
|
8
8
|
require "sleeproom/record/tasks"
|
|
9
9
|
require "sleeproom/record/websocket"
|
|
10
10
|
require "sleeproom/record/api/api"
|
|
11
|
+
require "sleeproom/record/web/app"
|
|
11
12
|
require "async"
|
|
13
|
+
require "roda"
|
|
14
|
+
require "rack/handler/falcon"
|
|
12
15
|
require "shellwords"
|
|
13
16
|
module SleepRoom
|
|
14
17
|
module Record
|
|
15
18
|
# Okite!!!
|
|
16
19
|
# @param url [String]
|
|
17
|
-
# @return [
|
|
20
|
+
# @return [Integer]
|
|
18
21
|
def self.call_minyami(url:, is_live: true, threads: configatron.minyami.threads, output:, retries: configatron.minyami.retries)
|
|
19
22
|
command = "minyami -d #{Shellwords.escape(url)}"
|
|
20
23
|
command += " --retries #{retries.to_i}" if retries
|
|
@@ -24,23 +27,23 @@ module SleepRoom
|
|
|
24
27
|
command += " --output #{Shellwords.escape(output)}" if output
|
|
25
28
|
download_dir_check(output)
|
|
26
29
|
pid = exec_command(command, output)
|
|
27
|
-
|
|
30
|
+
pid
|
|
28
31
|
end
|
|
29
32
|
|
|
30
33
|
# @param command [String]
|
|
31
|
-
# @return [
|
|
34
|
+
# @return [Integer]
|
|
32
35
|
def self.exec_command(command, output)
|
|
33
36
|
SleepRoom.info("Call command: #{command}")
|
|
34
37
|
SleepRoom.info("STDOUT: #{output}.out , STDERR: #{output}.err")
|
|
35
38
|
pid = spawn(command, out: "#{output}.out", err: "#{output}.err")
|
|
36
39
|
SleepRoom.info("PID: #{pid}")
|
|
37
40
|
Process.detach(pid)
|
|
38
|
-
|
|
41
|
+
pid
|
|
39
42
|
end
|
|
40
43
|
|
|
41
44
|
def self.download_dir_check(output)
|
|
42
45
|
dir = File.dirname(output)
|
|
43
|
-
|
|
46
|
+
unless Dir.exist?(dir)
|
|
44
47
|
SleepRoom.info("#{dir} does not exist, creating...")
|
|
45
48
|
SleepRoom.mkdir(dir)
|
|
46
49
|
end
|
|
@@ -11,15 +11,11 @@ module SleepRoom
|
|
|
11
11
|
module API
|
|
12
12
|
class Error < StandardError; end
|
|
13
13
|
class NotFoundError < Error; end
|
|
14
|
-
ROOM_URL = "https://www.showroom-live.com"
|
|
15
|
-
ROOM_API = "https://www.showroom-live.com/api/room/status"
|
|
16
|
-
STREAMING_API = "https://www.showroom-live.com/api/live/streaming_url"
|
|
17
|
-
|
|
18
14
|
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"
|
|
19
15
|
|
|
20
|
-
def self.get(url)
|
|
21
|
-
|
|
22
|
-
http = Faraday.get(url, nil, {"User-Agent": USER_AGENT})
|
|
16
|
+
def self.get(url, task: Async::Task.current)
|
|
17
|
+
task.async do
|
|
18
|
+
http = Faraday.get(url, nil, { "User-Agent": USER_AGENT })
|
|
23
19
|
if http.status == 200
|
|
24
20
|
@json = JSON.parse(http.body)
|
|
25
21
|
elsif http.status == 404
|
|
@@ -4,11 +4,12 @@ module SleepRoom
|
|
|
4
4
|
module Record
|
|
5
5
|
module API
|
|
6
6
|
class Room
|
|
7
|
+
ROOM_URL = "https://www.showroom-live.com"
|
|
7
8
|
def initialize(room_name)
|
|
8
9
|
@url = ROOM_URL + "/" + room_name
|
|
9
10
|
end
|
|
10
11
|
|
|
11
|
-
def get
|
|
12
|
+
def get
|
|
12
13
|
@json = API.get(@url).wait
|
|
13
14
|
end
|
|
14
15
|
end
|
|
@@ -4,13 +4,14 @@ module SleepRoom
|
|
|
4
4
|
module Record
|
|
5
5
|
module API
|
|
6
6
|
class RoomAPI
|
|
7
|
+
ROOM_API = "https://www.showroom-live.com/api/room/status"
|
|
7
8
|
def initialize(room_url_key)
|
|
8
9
|
@url = ROOM_API + "?room_url_key=" + room_url_key
|
|
9
10
|
@json = nil
|
|
10
11
|
get
|
|
11
12
|
end
|
|
12
13
|
|
|
13
|
-
def get
|
|
14
|
+
def get
|
|
14
15
|
@json = API.get(@url).wait
|
|
15
16
|
end
|
|
16
17
|
|
|
@@ -4,21 +4,22 @@ module SleepRoom
|
|
|
4
4
|
module Record
|
|
5
5
|
module API
|
|
6
6
|
class StreamingAPI
|
|
7
|
+
STREAMING_API = "https://www.showroom-live.com/api/live/streaming_url"
|
|
7
8
|
def initialize(room_id)
|
|
8
9
|
@url = STREAMING_API + "?room_id=" + room_id.to_s + "&ignore_low_stream=1"
|
|
9
10
|
@json = nil
|
|
10
11
|
get
|
|
11
12
|
end
|
|
12
13
|
|
|
13
|
-
def get
|
|
14
|
+
def get
|
|
14
15
|
@json = API.get(@url).wait
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def streaming_url
|
|
18
19
|
if @json["streaming_url_list"].nil?
|
|
19
|
-
raise Error
|
|
20
|
+
raise Error, "streaming url is null."
|
|
20
21
|
else
|
|
21
|
-
@json["streaming_url_list"].
|
|
22
|
+
@json["streaming_url_list"].min_by { |hash| -hash["quality"] }["url"]
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
end
|
|
@@ -1,148 +1,97 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require "sleeproom/record/write_status"
|
|
3
4
|
|
|
4
5
|
module SleepRoom
|
|
5
6
|
module Record
|
|
7
|
+
# showroom-live.com
|
|
6
8
|
class Showroom
|
|
7
|
-
|
|
9
|
+
# Showroom Downloader
|
|
10
|
+
# @param room [String]
|
|
11
|
+
# @param group [String]
|
|
12
|
+
# @param queue [WriteStatus]
|
|
8
13
|
def initialize(room:, group: "default", queue:)
|
|
9
14
|
@room = room
|
|
10
15
|
@group = group
|
|
11
|
-
@
|
|
16
|
+
@status = queue
|
|
12
17
|
@running = false
|
|
13
|
-
@downlaoding = false
|
|
14
|
-
@reconnection = false
|
|
15
18
|
end
|
|
16
19
|
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if status = SleepRoom.load_config(:status).find{|hash| hash[:room] == room}
|
|
26
|
-
if !status[:pid].nil?
|
|
27
|
-
break if SleepRoom.running?(status[:pid]) == false
|
|
28
|
-
else
|
|
29
|
-
break
|
|
30
|
-
end
|
|
31
|
-
else
|
|
32
|
-
break
|
|
33
|
-
end
|
|
34
|
-
t.sleep 60
|
|
35
|
-
end
|
|
36
|
-
end.wait
|
|
37
|
-
if @is_live
|
|
38
|
-
start_time = Time.now
|
|
39
|
-
log("Live broadcast.")
|
|
40
|
-
streaming_url = parse_streaming_url
|
|
41
|
-
output = build_output
|
|
42
|
-
pid = SleepRoom::Record.call_minyami(url: streaming_url, output: output)
|
|
43
|
-
downloading(streaming_url, pid, start_time)
|
|
44
|
-
record
|
|
45
|
-
else
|
|
46
|
-
log("Status: Stop.")
|
|
47
|
-
waiting_live(ws: :init)
|
|
48
|
-
Async do |task|
|
|
49
|
-
while true
|
|
50
|
-
if @running == false && @reconnection == false
|
|
51
|
-
start_websocket
|
|
52
|
-
elsif @reconnection == true
|
|
53
|
-
set_room_info
|
|
54
|
-
start_websocket
|
|
55
|
-
@reconnection = false
|
|
56
|
-
end
|
|
57
|
-
task.sleep 10
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
rescue => e
|
|
62
|
-
add_error(e)
|
|
63
|
-
SleepRoom.error(e.full_message)
|
|
64
|
-
log("Retry...")
|
|
65
|
-
task.sleep 5
|
|
66
|
-
retry
|
|
20
|
+
# Record Room
|
|
21
|
+
def recore
|
|
22
|
+
set_room_info
|
|
23
|
+
if @is_live
|
|
24
|
+
log("Status: broadcast.")
|
|
25
|
+
download_process
|
|
26
|
+
else
|
|
27
|
+
log("Status: Stop.")
|
|
67
28
|
end
|
|
29
|
+
start_websocket
|
|
30
|
+
rescue => e
|
|
31
|
+
error(e.full_message)
|
|
32
|
+
Async::Task.current.sleep 5
|
|
33
|
+
retry
|
|
68
34
|
end
|
|
69
35
|
|
|
36
|
+
# Print log
|
|
37
|
+
# @param str [String]
|
|
70
38
|
def log(str)
|
|
71
39
|
SleepRoom.info("[#{@room}] #{str}")
|
|
72
40
|
end
|
|
73
|
-
|
|
41
|
+
|
|
42
|
+
# Print log
|
|
43
|
+
# @param str [String]
|
|
44
|
+
def error(str)
|
|
45
|
+
SleepRoom.error("[#{@room}] #{str}")
|
|
46
|
+
end
|
|
47
|
+
|
|
74
48
|
private
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
ws.connect(task: sub) do |message|
|
|
49
|
+
|
|
50
|
+
# Websocket connect
|
|
51
|
+
def start_websocket(task: Async::Task.current)
|
|
52
|
+
log("Broadcast Key: #{@broadcast_key}")
|
|
53
|
+
ws = WebSocket.new(room: @room, broadcast_key: @broadcast_key, url: @broadcast_host)
|
|
54
|
+
@running = true
|
|
55
|
+
update_status
|
|
56
|
+
begin
|
|
57
|
+
ws.connect do |event, message|
|
|
58
|
+
if event == :websocket
|
|
86
59
|
case message["t"].to_i
|
|
87
60
|
when 101
|
|
88
61
|
log("Live stop.")
|
|
62
|
+
@is_live = false
|
|
89
63
|
ws.running = false
|
|
90
|
-
@running = false
|
|
91
|
-
record
|
|
92
64
|
when 104
|
|
93
65
|
log("Live start.")
|
|
94
|
-
|
|
95
|
-
streaming_url = parse_streaming_url
|
|
96
|
-
output = build_output
|
|
97
|
-
pid = SleepRoom::Record.call_minyami(url: streaming_url, output: output)
|
|
98
|
-
downloading(streaming_url, pid, start_time)
|
|
99
|
-
ws.running = false
|
|
100
|
-
@running = false
|
|
101
|
-
@reconnection = true
|
|
102
|
-
else
|
|
103
|
-
# other
|
|
66
|
+
download_process
|
|
104
67
|
end
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
|
130
|
-
ws.running = false
|
|
131
|
-
@running = false
|
|
132
|
-
task.stop
|
|
68
|
+
elsif event == :status
|
|
69
|
+
case message[:event]
|
|
70
|
+
when :ack
|
|
71
|
+
update_status
|
|
72
|
+
when :close
|
|
73
|
+
log("WebSocket Close.")
|
|
74
|
+
task.sleep 5
|
|
75
|
+
record
|
|
76
|
+
when :error
|
|
77
|
+
error("Network Error.")
|
|
78
|
+
log("Try to reconnect server.")
|
|
79
|
+
task.sleep 5
|
|
80
|
+
record
|
|
133
81
|
end
|
|
134
|
-
|
|
135
|
-
|
|
82
|
+
else
|
|
83
|
+
# TODO
|
|
136
84
|
end
|
|
137
85
|
end
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
@running = false
|
|
86
|
+
rescue => e
|
|
87
|
+
error("WebSocket stopped.")
|
|
88
|
+
puts(e.full_message)
|
|
142
89
|
end
|
|
90
|
+
ensure
|
|
91
|
+
@running = false
|
|
143
92
|
end
|
|
144
|
-
|
|
145
|
-
def set_room_info
|
|
93
|
+
|
|
94
|
+
def set_room_info(task: Async::Task.current)
|
|
146
95
|
api = API::RoomAPI.new(@room)
|
|
147
96
|
@room_id = api.room_id
|
|
148
97
|
@room_name = api.room_name
|
|
@@ -150,94 +99,97 @@ module SleepRoom
|
|
|
150
99
|
@broadcast_host = api.broadcast_host
|
|
151
100
|
@broadcast_key = api.broadcast_key
|
|
152
101
|
rescue API::NotFoundError
|
|
153
|
-
|
|
102
|
+
error("The room does not exist.")
|
|
154
103
|
log("Task stopped.")
|
|
155
|
-
|
|
104
|
+
task.stop
|
|
156
105
|
rescue => e
|
|
157
|
-
|
|
158
|
-
log("
|
|
106
|
+
error(e.message)
|
|
107
|
+
log("获取房间信息失败.")
|
|
108
|
+
log("等待5秒...")
|
|
109
|
+
task.sleep 5
|
|
159
110
|
retry
|
|
160
111
|
end
|
|
161
112
|
|
|
162
|
-
def parse_streaming_url
|
|
113
|
+
def parse_streaming_url
|
|
163
114
|
api = API::StreamingAPI.new(@room_id)
|
|
164
|
-
|
|
115
|
+
api.streaming_url
|
|
165
116
|
rescue => e
|
|
166
117
|
SleepRoom.error(e.full_message)
|
|
167
|
-
log("
|
|
118
|
+
log("获取 HLS 地址失败.")
|
|
168
119
|
retry
|
|
169
120
|
end
|
|
170
121
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
room: @room,
|
|
184
|
-
start_time: start_time,
|
|
185
|
-
name: @room_name,
|
|
186
|
-
group: @group,
|
|
187
|
-
live: true,
|
|
188
|
-
status: :downloading,
|
|
189
|
-
streaming_url: streaming_url,
|
|
190
|
-
download_pid: pid
|
|
191
|
-
})
|
|
122
|
+
# Downloader
|
|
123
|
+
def download_process(task: Async::Task.current)
|
|
124
|
+
completed = false
|
|
125
|
+
log("Download start.")
|
|
126
|
+
streaming_url = parse_streaming_url
|
|
127
|
+
output = build_output
|
|
128
|
+
# Call time
|
|
129
|
+
call_time = Time.now
|
|
130
|
+
pid = SleepRoom::Record.call_minyami(url: streaming_url, output: output)
|
|
131
|
+
@status.downloading(room: @room, url: streaming_url, pid: pid, start_time: call_time)
|
|
132
|
+
log("Waiting for download process.")
|
|
133
|
+
# Status
|
|
192
134
|
task.async do |t|
|
|
193
135
|
loop do
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
status
|
|
204
|
-
|
|
136
|
+
if SleepRoom.running?(pid) && @is_live
|
|
137
|
+
# Downloading
|
|
138
|
+
elsif SleepRoom.running?(pid) && @is_live == false
|
|
139
|
+
# Live stopped, Minyami process running.
|
|
140
|
+
retries = 0
|
|
141
|
+
while retries < 3
|
|
142
|
+
set_room_info
|
|
143
|
+
break if @is_live == true
|
|
144
|
+
|
|
145
|
+
log("Waiting for latest status...")
|
|
146
|
+
task.sleep 20
|
|
147
|
+
retries += 1
|
|
148
|
+
end
|
|
149
|
+
completed = true if retries == 3 && @is_live == false
|
|
150
|
+
elsif (SleepRoom.running?(pid) == false && @is_live == false) || completed
|
|
151
|
+
# Live stopped, Minyami process stopped.
|
|
152
|
+
@status.add(room: @room, status: :completed, live: false)
|
|
153
|
+
log("Download completed.")
|
|
154
|
+
log("Find minyami temp files...")
|
|
155
|
+
tmp_path = SleepRoom.find_tmp_directory(output, call_time)
|
|
156
|
+
if tmp_path
|
|
157
|
+
log("Temp files in #{tmp_path}.")
|
|
158
|
+
save_path = File.dirname("#{configatron.save_path}/#{output}")
|
|
159
|
+
dir_name = File.basename(output).sub(".ts", "")
|
|
160
|
+
SleepRoom.move_ts_to_archive(tmp_path, save_path, dir_name)
|
|
161
|
+
log("Save chunks to #{save_path}/#{dir_name}.")
|
|
162
|
+
else
|
|
163
|
+
log("Can not find temp file")
|
|
164
|
+
end
|
|
165
|
+
record
|
|
166
|
+
@running = false
|
|
205
167
|
break
|
|
206
|
-
elsif
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
168
|
+
elsif SleepRoom.running?(pid) == false && @is_live == true
|
|
169
|
+
# Live broadcast, Minyami process stopped.
|
|
170
|
+
set_room_info
|
|
171
|
+
next if @is_live == false
|
|
172
|
+
|
|
173
|
+
log("Minyami stopped, Try to call Minyami again.")
|
|
174
|
+
download_process
|
|
213
175
|
end
|
|
214
|
-
t.sleep
|
|
215
|
-
rescue Faraday::ConnectionFailed
|
|
216
|
-
log("Network error.")
|
|
217
|
-
retry
|
|
176
|
+
t.sleep 1
|
|
218
177
|
end
|
|
219
|
-
end
|
|
178
|
+
end
|
|
220
179
|
end
|
|
221
180
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
181
|
+
# @return [String]
|
|
182
|
+
def build_output
|
|
183
|
+
room = @room
|
|
184
|
+
group = @group
|
|
185
|
+
tmp_str = configatron.default_save_name
|
|
186
|
+
tmp_str = tmp_str.sub("\%TIME\%", Time.now.strftime("%Y-%m-%d-%H-%M-%S")) if tmp_str.include?("\%TIME\%")
|
|
187
|
+
tmp_str = tmp_str.sub("\%ROOMNAME\%", room) if tmp_str.include?("\%ROOMNAME\%")
|
|
188
|
+
File.join(group, room, tmp_str)
|
|
230
189
|
end
|
|
231
190
|
|
|
232
|
-
def
|
|
233
|
-
@
|
|
234
|
-
room: @room,
|
|
235
|
-
live: false,
|
|
236
|
-
group: @group,
|
|
237
|
-
name: @room_name,
|
|
238
|
-
status: :waiting,
|
|
239
|
-
ws: status
|
|
240
|
-
})
|
|
191
|
+
def update_status
|
|
192
|
+
@status.waiting(room: @room, group: @group, room_name: @room_name)
|
|
241
193
|
end
|
|
242
194
|
end
|
|
243
195
|
end
|