sleeproom 0.4.4 → 0.9.0.beta1

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: 6cceff5806149367580bf38a490ac4301887c28390941d68dcbcba58b1e359e3
4
- data.tar.gz: add480c7ae186cdf5cc9b8e7c857d1edd127fd25d6f15ace7ed12e60bf5b0c3b
3
+ metadata.gz: c475d0ffb218cfa389559edacf780caa9e82b2bdeaf4091abb775536b3036308
4
+ data.tar.gz: 107b04198f32b68c03417f9625e6019f080e65fe0bb0a280ad600f6ebd0eba51
5
5
  SHA512:
6
- metadata.gz: 2ec44e1d44f7637a047b1793bb8df34aed091a6610cc00a4a41bcbed8af55ae28bc54d8462724dbaeab48710264e4cd38b746affaa50a97c304db9e5c6173ffa
7
- data.tar.gz: c4d2dfa38c44c479e7a0fd074470e8bf59ea193e719df7f9a4a6cb91678c3efa40ae4965fdc673a0d75fd16dd58ee72c11e412f2e9276e4d79b92bcf909d5812
6
+ metadata.gz: ad6ad5b056aa8b5575f41d93dfb0647d1797bc54d3214581f757bd0bdb0c05950b81fdd20938d4101c8612a1800f926d2de4eb2e777b578d225163d90313161a
7
+ data.tar.gz: bfc3096527de19b9d21e9f6ede44d2cf9818163c9f4dd0fa3a6d316ef36ba7a26ebcb3eca4a5c92b5266e3ab21084e616525e55c7a1495abf8d5c6e7c32aa979
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", "~> 12.0"
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
@@ -1,12 +1,15 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- sleeproom (0.4.4)
4
+ sleeproom (0.9.0.beta1)
5
5
  async (~> 1.26.0)
6
6
  async-http-faraday (~> 0.9.0)
7
7
  async-websocket (~> 0.15.0)
8
8
  colorize (~> 0.8.0)
9
9
  configatron (~> 4.5.0)
10
+ falcon (~> 0.36.0)
11
+ roda (~> 3.33.0)
12
+ ruby-next-core (~> 0.9.0)
10
13
  terminal-table (~> 1.8.0)
11
14
 
12
15
  GEM
@@ -23,6 +26,9 @@ GEM
23
26
  console (~> 1.0)
24
27
  nio4r (~> 2.3)
25
28
  timers (~> 4.1)
29
+ async-container (0.16.6)
30
+ async (~> 1.0)
31
+ async-io (~> 1.26)
26
32
  async-http (0.52.4)
27
33
  async (~> 1.25)
28
34
  async-io (~> 1.28)
@@ -30,6 +36,8 @@ GEM
30
36
  protocol-http (~> 0.20.0)
31
37
  protocol-http1 (~> 0.13.0)
32
38
  protocol-http2 (~> 0.14.0)
39
+ async-http-cache (0.2.0)
40
+ async-http (~> 0.51)
33
41
  async-http-faraday (0.9.0)
34
42
  async-http (~> 0.42)
35
43
  faraday
@@ -41,22 +49,39 @@ GEM
41
49
  async-http (~> 0.51)
42
50
  async-io (~> 1.23)
43
51
  protocol-websocket (~> 0.7.0)
52
+ build-environment (1.13.0)
44
53
  colorize (0.8.1)
45
54
  concurrent-ruby (1.1.6)
46
55
  configatron (4.5.1)
47
56
  console (1.8.2)
48
- diff-lcs (1.4.4)
57
+ diff-lcs (1.3)
58
+ falcon (0.36.4)
59
+ async (~> 1.13)
60
+ async-container (~> 0.16.0)
61
+ async-http (~> 0.52.0)
62
+ async-http-cache (~> 0.2.0)
63
+ async-io (~> 1.22)
64
+ build-environment (~> 1.13)
65
+ localhost (~> 1.1)
66
+ process-metrics (~> 0.2.0)
67
+ rack (>= 1.0)
68
+ samovar (~> 2.1)
49
69
  faraday (1.0.1)
50
70
  multipart-post (>= 1.2, < 3)
51
71
  i18n (1.8.3)
52
72
  concurrent-ruby (~> 1.0)
53
73
  jaro_winkler (1.5.4)
74
+ localhost (1.1.6)
75
+ mapping (1.1.1)
54
76
  minitest (5.14.1)
55
77
  multipart-post (2.1.1)
56
78
  nio4r (2.5.2)
57
79
  parallel (1.19.2)
58
80
  parser (2.7.1.4)
59
81
  ast (~> 2.4.1)
82
+ process-metrics (0.2.1)
83
+ console (~> 1.8)
84
+ samovar (~> 2.1)
60
85
  protocol-hpack (1.4.2)
61
86
  protocol-http (0.20.0)
62
87
  protocol-http1 (0.13.0)
@@ -69,7 +94,10 @@ GEM
69
94
  protocol-http1 (~> 0.2)
70
95
  rack (2.2.3)
71
96
  rainbow (3.0.0)
72
- rake (12.3.3)
97
+ rake (13.0.1)
98
+ rexml (3.2.4)
99
+ roda (3.33.0)
100
+ rack
73
101
  rspec (3.9.0)
74
102
  rspec-core (~> 3.9.0)
75
103
  rspec-expectations (~> 3.9.0)
@@ -83,41 +111,45 @@ GEM
83
111
  diff-lcs (>= 1.2.0, < 2.0)
84
112
  rspec-support (~> 3.9.0)
85
113
  rspec-support (3.9.3)
86
- rubocop (0.79.0)
114
+ rubocop (0.82.0)
87
115
  jaro_winkler (~> 1.5.1)
88
116
  parallel (~> 1.10)
89
117
  parser (>= 2.7.0.1)
90
118
  rainbow (>= 2.2.2, < 4.0)
119
+ rexml
91
120
  ruby-progressbar (~> 1.7)
92
- unicode-display_width (>= 1.4.0, < 1.7)
121
+ unicode-display_width (>= 1.4.0, < 2.0)
93
122
  rubocop-github (0.16.0)
94
123
  rubocop (<= 0.82.0)
95
124
  rubocop-performance (~> 1.0)
96
125
  rubocop-rails (~> 2.0)
97
126
  rubocop-performance (1.6.1)
98
127
  rubocop (>= 0.71.0)
99
- rubocop-rails (2.5.2)
100
- activesupport
128
+ rubocop-rails (2.6.0)
129
+ activesupport (>= 4.2.0)
101
130
  rack (>= 1.1)
102
- rubocop (>= 0.72.0)
131
+ rubocop (>= 0.82.0)
132
+ ruby-next-core (0.9.2)
103
133
  ruby-progressbar (1.10.1)
134
+ samovar (2.1.4)
135
+ console (~> 1.0)
136
+ mapping (~> 1.0)
104
137
  terminal-table (1.8.0)
105
138
  unicode-display_width (~> 1.1, >= 1.1.1)
106
139
  thread_safe (0.3.6)
107
140
  timers (4.3.0)
108
141
  tzinfo (1.2.7)
109
142
  thread_safe (~> 0.1)
110
- unicode-display_width (1.6.1)
111
- zeitwerk (2.3.1)
143
+ unicode-display_width (1.7.0)
144
+ zeitwerk (2.3.0)
112
145
 
113
146
  PLATFORMS
114
147
  ruby
115
148
  x64-mingw32
116
149
 
117
150
  DEPENDENCIES
118
- rake (~> 12.0)
151
+ rake (~> 13.0)
119
152
  rspec (~> 3.0)
120
- rubocop (~> 0.79.0)
121
153
  rubocop-github
122
154
  rubocop-performance
123
155
  sleeproom!
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/gem_tasks"
2
4
  require "rspec/core/rake_task"
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
@@ -3,5 +3,4 @@
3
3
 
4
4
  require "sleeproom/cli"
5
5
 
6
- cli = SleepRoom::CLI.new(ARGV)
7
- cli.run
6
+ SleepRoom::CLI.new(ARGV)
@@ -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
- return buffer
16
+ buffer
15
17
  end
16
-
18
+
17
19
  def dump(object)
18
- return object
20
+ object
19
21
  end
20
- end
22
+ end
@@ -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
- unless argv.empty?
16
+ if argv.empty? == false
15
17
  @parser.parse!(argv)
16
18
  action = argv.shift
17
- if action == "status"
19
+ case action
20
+ when "status"
18
21
  SleepRoom::Record::Tasks.status
19
- elsif action == "start"
20
- SleepRoom::Record::Tasks.start
21
- elsif action == "exit"
22
- SleepRoom::Record::Tasks.stop
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 = "#{opt.version}"
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.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
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
- record = SleepRoom::Record::Showroom.new(room: room, group: "download", queue: write_status)
66
- record.record
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
@@ -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 [Boolean]
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
- return pid
30
+ pid
28
31
  end
29
32
 
30
33
  # @param command [String]
31
- # @return [Boolean]
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
- return pid
41
+ pid
39
42
  end
40
43
 
41
44
  def self.download_dir_check(output)
42
45
  dir = File.dirname(output)
43
- if !Dir.exist?(dir)
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
- Async do
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(task: Async::Task.current)
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(task: Async::Task.current)
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(task: Async::Task.current)
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.new("streaming url is null.")
20
+ raise Error, "streaming url is null."
20
21
  else
21
- @json["streaming_url_list"].sort_by{|hash| -hash["quality"]}.first["url"]
22
+ @json["streaming_url_list"].min_by { |hash| -hash["quality"] }["url"]
22
23
  end
23
24
  end
24
25
  end
@@ -1,148 +1,102 @@
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
- SITE = "showroom"
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
- @queue = queue
16
+ @status = queue
12
17
  @running = false
13
- @downlaoding = false
14
- @reconnection = false
18
+ @downloading = false
15
19
  end
16
20
 
17
- # @param user [String]
18
- # @return [Boolean]
19
- def record(reconnection: false)
20
- room = @room
21
- Async do |task|
22
- set_room_info
23
- task.async do |t|
24
- while @is_live
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
21
+ # Record Room
22
+ def record
23
+ set_room_info
24
+ if @is_live
25
+ log("Status: broadcast.")
26
+ download_process if @downloading == false
27
+ else
28
+ log("Status: Stop.")
67
29
  end
30
+ start_websocket
31
+ rescue => e
32
+ error(e.full_message)
33
+ Async::Task.current.sleep 5
34
+ retry
68
35
  end
69
36
 
37
+ # Print log
38
+ # @param str [String]
70
39
  def log(str)
71
40
  SleepRoom.info("[#{@room}] #{str}")
72
41
  end
73
-
42
+
43
+ # Print log
44
+ # @param str [String]
45
+ def error(str)
46
+ SleepRoom.error("[#{@room}] #{str}")
47
+ end
48
+
74
49
  private
75
- def start_websocket()
76
- Async do |task|
77
- @running = true
50
+
51
+ # Websocket connect
52
+ def start_websocket(task: Async::Task.current)
53
+ main = task.async do |task|
78
54
  log("Broadcast Key: #{@broadcast_key}")
79
- waiting_live(ws: :init)
80
55
  ws = WebSocket.new(room: @room, broadcast_key: @broadcast_key, url: @broadcast_host)
81
- @ws = ws
82
- # ws status
83
- ws_task = task.async do |sub|
84
- ws.running = true
85
- ws.connect(task: sub) do |message|
86
- case message["t"].to_i
87
- when 101
88
- log("Live stop.")
89
- ws.running = false
90
- @running = false
91
- record
92
- when 104
93
- log("Live start.")
94
- start_time = Time.now
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
56
+ @running = true
57
+ update_status
58
+ begin
59
+ ws.connect do |event, message|
60
+ if event == :websocket
61
+ case message["t"].to_i
62
+ when 101
63
+ log("Live stop.")
64
+ @is_live = false
65
+ ws.running = false
66
+ when 104
67
+ log("Live start.")
68
+ download_process
69
+ end
70
+ elsif event == :status
71
+ case message[:event]
72
+ when :ack
73
+ update_status
74
+ when :close
75
+ log("WebSocket Close.")
76
+ task&.stop
77
+ when :error
78
+ error("Network Error.")
79
+ task&.stop
80
+ end
102
81
  else
103
- # other
82
+ # TODO
104
83
  end
105
84
  end
106
85
  rescue => e
107
- SleepRoom.error("WS Stop.")
108
- SleepRoom.error(e.full_message)
109
- ws.running = false
110
- @running = false
111
- add_error(e)
112
- end
113
-
114
- Async do |task|
115
- last_ack = nil
116
- last_ping = nil
117
- while @running && @downlaoding == false
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
133
- end
134
- waiting_live({last_ack: last_ack})
135
- task.sleep 1
136
- end
86
+ error("WebSocket stopped.")
87
+ puts(e.full_message)
88
+ task&.stop
137
89
  end
138
- task.children.each(&:wait)
139
- ensure
140
- ws.running = false
141
- @running = false
142
90
  end
91
+ main.wait
92
+ ensure
93
+ @running = false
94
+ task.sleep 5
95
+ main&.stop
96
+ start_websocket
143
97
  end
144
-
145
- def set_room_info
98
+
99
+ def set_room_info(task: Async::Task.current)
146
100
  api = API::RoomAPI.new(@room)
147
101
  @room_id = api.room_id
148
102
  @room_name = api.room_name
@@ -150,94 +104,100 @@ module SleepRoom
150
104
  @broadcast_host = api.broadcast_host
151
105
  @broadcast_key = api.broadcast_key
152
106
  rescue API::NotFoundError
153
- SleepRoom.error("[#{@room}] The room does not exist.")
107
+ error("The room does not exist.")
154
108
  log("Task stopped.")
155
- Async::Task.current.stop
109
+ task.stop
156
110
  rescue => e
157
- SleepRoom.error(e.message)
158
- log("[setRoomInfo] Retry...")
111
+ error(e.message)
112
+ log("获取房间信息失败.")
113
+ log("等待5秒...")
114
+ task.sleep 5
159
115
  retry
160
116
  end
161
117
 
162
- def parse_streaming_url(task: Async::Task.current)
118
+ def parse_streaming_url
163
119
  api = API::StreamingAPI.new(@room_id)
164
- streaming_url_list = api.streaming_url
120
+ api.streaming_url
165
121
  rescue => e
166
122
  SleepRoom.error(e.full_message)
167
- log("[parseStreamingUrl] Retry...")
123
+ log("获取 HLS 地址失败.")
168
124
  retry
169
125
  end
170
126
 
171
- def build_output(task: Async::Task.current)
172
- room = @room
173
- group = @group
174
- tmp_str = configatron.default_save_name
175
- tmp_str = tmp_str.sub("\%TIME\%", Time.now.strftime("%Y-%m-%d-%H-%M-%S")) if tmp_str.include?("\%TIME\%")
176
- tmp_str = tmp_str.sub("\%ROOMNAME\%", room) if tmp_str.include?("\%ROOMNAME\%")
177
- File.join(group, room, "showroom", tmp_str)
178
- end
179
-
180
- def downloading(streaming_url, pid, start_time, task: Async::Task.current)
181
- @downlaoding = true
182
- @queue.add({
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
- })
127
+ # Downloader
128
+ def download_process(task: Async::Task.current)
129
+ completed = false
130
+ @downloading = true
131
+ log("Download start.")
132
+ streaming_url = parse_streaming_url
133
+ output = build_output
134
+ # Call time
135
+ call_time = Time.now
136
+ pid = SleepRoom::Record.call_minyami(url: streaming_url, output: output)
137
+ @status.downloading(room: @room, url: streaming_url, pid: pid, start_time: call_time, output: output)
138
+ log("Waiting for download process.")
139
+ # Status
192
140
  task.async do |t|
193
141
  loop do
194
- live = API::RoomAPI.new(@room).live?
195
- if !SleepRoom.running?(pid) && !live
196
- log("Download complete.")
197
- @downlaoding = false
198
- @queue.add({
199
- room: @room,
200
- name: @room_name,
201
- group: @group,
202
- live: API::RoomAPI.new(@room).live?,
203
- status: :complete,
204
- })
142
+ if SleepRoom.running?(pid) && @is_live
143
+ # Downloading
144
+ elsif SleepRoom.running?(pid) && @is_live == false
145
+ # Live stopped, Minyami process running.
146
+ retries = 0
147
+ while retries < 3
148
+ set_room_info
149
+ break if @is_live == true
150
+
151
+ log("Waiting for latest status...")
152
+ task.sleep 20
153
+ retries += 1
154
+ end
155
+ completed = true if retries == 3 && @is_live == false
156
+ elsif (SleepRoom.running?(pid) == false && @is_live == false) || completed
157
+ # Live stopped, Minyami process stopped.
158
+ @status.add(room: @room, status: :completed, live: false)
159
+ log("Download completed.")
160
+ log("Find minyami temp files...")
161
+ tmp_path = SleepRoom.find_tmp_directory(output, call_time)
162
+ if tmp_path
163
+ log("Temp files in #{tmp_path}.")
164
+ save_path = File.dirname("#{configatron.save_path}/#{output}")
165
+ dir_name = File.basename(output).sub(".ts", "")
166
+ SleepRoom.move_ts_to_archive(tmp_path, save_path, dir_name)
167
+ log("Save chunks to #{save_path}/#{dir_name}.")
168
+ else
169
+ log("Can not find temp file")
170
+ end
171
+ record
172
+ @running = false
205
173
  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.")
174
+ elsif SleepRoom.running?(pid) == false && @is_live == true
175
+ # Live broadcast, Minyami process stopped.
176
+ set_room_info
177
+ next if @is_live == false
178
+
179
+ log("Minyami stopped, Try to call Minyami again.")
180
+ download_process
213
181
  end
214
- t.sleep 120
215
- rescue Faraday::ConnectionFailed
216
- log("Network error.")
217
- retry
182
+ t.sleep 1
218
183
  end
219
- end.wait
184
+ end
185
+ ensure
186
+ @downloading = false
220
187
  end
221
188
 
222
- def add_error(error)
223
- @queue.add({
224
- room: @room,
225
- name: @room_name,
226
- group: @group,
227
- status: :retry,
228
- error: error.message
229
- })
189
+ # @return [String]
190
+ def build_output
191
+ room = @room
192
+ group = @group
193
+ tmp_str = configatron.default_save_name
194
+ tmp_str = tmp_str.sub("\%TIME\%", Time.now.strftime("%Y-%m-%d-%H-%M-%S")) if tmp_str.include?("\%TIME\%")
195
+ tmp_str = tmp_str.sub("\%ROOMNAME\%", room) if tmp_str.include?("\%ROOMNAME\%")
196
+ File.join(group, room, tmp_str)
230
197
  end
231
198
 
232
- def waiting_live(status)
233
- @queue.add({
234
- room: @room,
235
- live: false,
236
- group: @group,
237
- name: @room_name,
238
- status: :waiting,
239
- ws: status
240
- })
199
+ def update_status
200
+ @status.waiting(room: @room, group: @group, room_name: @room_name, key: @broadcast_key)
241
201
  end
242
202
  end
243
203
  end