sleeproom 0.4.0 → 0.9.0.beta3

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.
@@ -1,69 +1,63 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "terminal-table"
3
4
 
4
5
  module SleepRoom
5
6
  module Record
6
7
  class Tasks
7
8
  # @return [void]
8
- def self.start
9
- Async do |_task|
10
- count = 0
11
- write_status = WriteStatus.new
12
- SleepRoom.reload_config
13
- if SleepRoom.running?
14
- SleepRoom.error("PID #{SleepRoom.load_pid} Process is already running.")
15
- exit
16
- else
17
- SleepRoom.write_config_file(:status, [])
18
- end
19
- SleepRoom.create_pid(Process.pid)
20
- lists = SleepRoom.load_config(:record)
21
- lists.each do |group, list|
22
- SleepRoom.info("Empty list.") if list.empty?
23
- list.each do |room|
24
- record = SleepRoom::Record::Showroom.new(room: room["room"], group: group, queue: write_status)
25
- record.record
26
- count += 1
9
+ def self.start(verbose: false)
10
+ Async do |task|
11
+ begin
12
+ running_task_count = 0
13
+ write_status = WriteStatus.new
14
+ write_status.run
15
+ if SleepRoom.running?
16
+ SleepRoom.error("PID #{SleepRoom.load_pid} Process is already running.")
17
+ exit
18
+ else
19
+ SleepRoom.write_config_file(:status, [])
27
20
  end
28
- rescue
29
- SleepRoom.error("Cannot parse Recording list.")
21
+ SleepRoom.create_pid(Process.pid)
22
+ lists = SleepRoom.load_config(:record)
23
+ lists.each do |group, list|
24
+ begin
25
+ SleepRoom.info("Empty list.") if list.empty?
26
+ list.each do |room|
27
+ Async do
28
+ running_task_count += 1
29
+ record = SleepRoom::Record::Showroom.new(room: room["room"], group: group, queue: write_status)
30
+ record.record
31
+ end
32
+ end
33
+ rescue StandardError
34
+ SleepRoom.error("Cannot parse Recording list.")
35
+ end
36
+ end
37
+ SleepRoom.info("共启动 #{running_task_count} 个任务.")
38
+ task.children.each(&:wait)
39
+ rescue StandardError => e
40
+ puts e.full_message
30
41
  end
31
- write_status.run
32
- SleepRoom.info("共启动 #{count} 个任务.")
33
- wait
34
- rescue => e
35
- puts e.full_message
36
42
  end
37
- rescue Exception
43
+ rescue Exception => e
44
+ puts e.full_message if verbose
38
45
  SleepRoom.create_pid(nil) unless SleepRoom.running?
39
46
  puts "Exit..."
40
47
  end
41
48
 
42
49
  # @return [void]
43
50
  def self.stop
44
- SleepRoom.reload_config
45
51
  raise "未实现"
46
52
  end
47
53
 
48
54
  # @return [void]
49
55
  def self.status
50
56
  Async do
51
- SleepRoom.reload_config
52
- status = SleepRoom.load_status
57
+ status = SleepRoom.load_status.sort_by { |hash| hash[:group] }
53
58
  pid = SleepRoom.load_config(:pid)
54
59
  if !SleepRoom.running?(pid) || status.empty? || pid.nil?
55
- lists = SleepRoom.load_config(:record)
56
60
  SleepRoom.info("No tasks running.")
57
- lists.each do |group, list|
58
- next if list.empty?
59
- rows = []
60
- title = group
61
- headings = list[0].keys
62
- list.each do |hash|
63
- rows.push(hash.values)
64
- end
65
- puts Terminal::Table.new(title: "[Recording list] Group: #{title}",:rows => rows, headings: headings)
66
- end
67
61
  else
68
62
  rows = []
69
63
  headings = status[0].keys
@@ -71,7 +65,7 @@ module SleepRoom
71
65
  rows.push(
72
66
  hash.values.map do |s|
73
67
  if s.is_a?(Hash)
74
- "#{(s[:last_ack].is_a?(Time) ? "[ACK]" + s[:last_ack].strftime("%H:%M:%S").to_s : "nil")}"
68
+ ((s[:last_ack].is_a?(Time) ? "[ACK]" + s[:last_ack].strftime("%H:%M:%S").to_s : "nil")).to_s
75
69
  elsif s.is_a?(Time)
76
70
  s.strftime("%H:%M:%S")
77
71
  else
@@ -80,18 +74,40 @@ module SleepRoom
80
74
  end
81
75
  )
82
76
  end
83
- puts Terminal::Table.new(title: "Status [PID #{pid}] (#{status.count})",:rows => rows, headings: headings)
77
+ puts Terminal::Table.new(title: "Status [PID #{pid}] (#{status.count})", rows: rows, headings: headings)
84
78
  end
85
79
  end
86
80
  end
87
81
 
82
+ def self.lists
83
+ lists = SleepRoom.load_config(:record)
84
+ puts "[Record list]"
85
+ lists.each do |group, list|
86
+ next if list.empty?
87
+
88
+ rows = []
89
+ title = group
90
+ headings = list[0].keys
91
+ list.each do |hash|
92
+ rows.push(hash.values)
93
+ end
94
+ puts Terminal::Table.new(title: title, rows: rows, headings: headings)
95
+ end
96
+ end
97
+
88
98
  def self.add(room, group)
89
99
  Async do
90
- group = "default" if group.empty?
100
+ if group.empty?
101
+ if group_match = room.match(/(?<=[((]).*?(?=[))])/)
102
+ group = group_match[0]
103
+ else
104
+ group = "default"
105
+ end
106
+ end
91
107
  old_record = SleepRoom.load_config(:record)
92
108
  name = API::RoomAPI.new(room).room_name
93
- input_record = {"room" => room, "name" => name}
94
- if !old_record[group].nil? && new_record = old_record[group].find{|h| h = input_record if h["room"] == room}
109
+ input_record = { "room" => room, "name" => name }
110
+ if !old_record[group].nil? && old_record[group].find { |h| h = input_record if h["room"] == room }
95
111
  SleepRoom.error("Room #{room} already exists.")
96
112
  else
97
113
  old_record[group] = [] if old_record[group].nil?
@@ -105,19 +121,10 @@ module SleepRoom
105
121
 
106
122
  def self.remove(room)
107
123
  old_record = SleepRoom.load_config(:record)
108
- new_record = old_record.each {|k, v| v.delete_if { |h| h["room"] == room }}
124
+ new_record = old_record.each { |_k, v| v.delete_if { |h| h["room"] == room } }
109
125
  SleepRoom.write_config_file(:record, new_record)
110
126
  SleepRoom.info("Remove success.")
111
127
  end
112
-
113
- private
114
- def self.wait
115
- Async do |task|
116
- while true
117
- task.sleep 1
118
- end
119
- end
120
- end
121
128
  end
122
129
  end
123
130
  end
@@ -1,86 +1,92 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "sleeproom/async/websocket"
2
4
  require "async/http/endpoint"
3
5
  require "async/websocket/client"
4
6
  require "json"
5
7
 
6
8
  module SleepRoom
7
- module Record
8
- class WebSocket
9
- attr_accessor :queue
10
- def initialize(room:, broadcast_key:, url:)
11
- @room = room
12
- @url = "wss://" + url
13
- @broadcast_key = broadcast_key
14
- @running = false
15
- @queue = Async::Queue.new
16
- end
9
+ module Record
10
+ class WebSocket
11
+ def initialize(room:, broadcast_key:, url:, open_handler:, message_handler:, close_handler:, error_handler:, ping_handler:)
12
+ @room = room
13
+ @url = "wss://" + url
14
+ @broadcast_key = broadcast_key
15
+ @running = false
16
+ @endpoint = Async::HTTP::Endpoint.parse(@url)
17
+ @open_handler = open_handler
18
+ @message_handler = message_handler
19
+ @close_handler = close_handler
20
+ @error_handler = error_handler
21
+ @ping_handler = ping_handler
22
+ end
17
23
 
18
- def connect(task: Async::Task.current)
19
- url = @url
20
- endpoint = Async::HTTP::Endpoint.parse(url)
21
- Async::WebSocket::Client.connect(endpoint, handler: WebSocketConnection) do |connection|
22
- @connection = connection
23
- @running = true
24
- connection.write("SUB\t#{@broadcast_key}")
25
- connection.flush
26
- log("Connect to websocket server.")
27
- @queue.enqueue({event: :connect, time: Time.now})
28
-
29
- ping_task = task.async do |sub|
30
- while @running
31
- sub.sleep 60
32
- @queue.enqueue({event: :ping, time: Time.now})
33
- connection.write("PING\tshowroom")
34
- connection.flush
35
- end
36
- end
24
+ def connect(task: Async::Task.current)
25
+ websocket = Async::WebSocket::Client.connect(@endpoint, handler: WebSocketConnection) do |connection|
26
+ @connection = connection
27
+ @running = true
28
+ send("SUB\t#{@broadcast_key}")
37
29
 
38
- status_task = task.async do |sub|
39
- while true
40
- sub.sleep 1
41
- if @running == false
42
- connection.close
43
- end
44
- end
45
- end
30
+ log("Connect to websocket server.")
31
+ @open_handler.call
46
32
 
47
- while message = connection.read
48
- if message == "ACK\tshowroom"
49
- @queue.enqueue({event: :ack, time: Time.now}) if message == "ACK\tshowroom"
50
- end
51
- if message.start_with?("MSG")
52
- begin
53
- yield JSON.parse(message.split("\t")[2])
54
- rescue => e
55
- SleepRoom.error(e.message)
56
- end
57
- end
58
- end
59
- rescue => e
60
- SleepRoom.error(e.message)
61
- ensure
62
- ping_task&.stop
63
- connection.close
64
- log("WebSocket closed.")
65
- end
66
- end
67
-
68
- def running?
69
- @running
33
+ ping = task.async do |task|
34
+ loop do
35
+ task.sleep 60
36
+ send("PING\tshowroom")
37
+ end
70
38
  end
71
39
 
72
- def running=(bool)
73
- @running = bool
74
- end
40
+ while message = connection.read
41
+ debug("ACK: #{message}")
42
+ @ping_handler.call if message == "ACK\tshowroom"
75
43
 
76
- def stop
77
- @running = false
78
- @connection.close
79
- end
44
+ next unless message.start_with?("MSG")
80
45
 
81
- def log(str)
82
- SleepRoom.info("[#{@room}] #{str}")
46
+ begin
47
+ @message_handler.call(JSON.parse(message.split("\t")[2]))
48
+ rescue JSON::ParserError => e
49
+ @error_handler.call(e)
50
+ log(e.message)
51
+ end
83
52
  end
53
+ rescue => e
54
+ error "error"
55
+ @error_handler.call(e)
56
+ log(e.full_message)
57
+ ensure
58
+ ping&.stop
59
+ @close_handler.call(nil)
60
+ @running = false
61
+ log("WebSocket closed.")
62
+ end
63
+ end
64
+
65
+ def send(data)
66
+ debug("SEND: #{data}")
67
+ @connection.write(data)
68
+ @connection.flush
69
+ end
70
+
71
+ def running?
72
+ @running
73
+ end
74
+
75
+ def stop
76
+ @connection.close
77
+ end
78
+
79
+ def log(str)
80
+ SleepRoom.info("[#{@room}] #{str}")
81
+ end
82
+
83
+ def error(str)
84
+ SleepRoom.error("[#{@room}] #{str}")
85
+ end
86
+
87
+ def debug(str)
88
+ SleepRoom.debug("[#{@room}] #{str}")
84
89
  end
85
90
  end
91
+ end
86
92
  end
@@ -15,9 +15,11 @@ module SleepRoom
15
15
  status[:update] = Time.now
16
16
  old_status = SleepRoom.load_config(:status)
17
17
  room = status[:room]
18
- if old_status.find { |h| h[:room] == room }
18
+ if tmp_status = old_status.find { |h| h[:room] == room }
19
19
  new_status = old_status.delete_if { |h| h[:room] == room }
20
- new_status.push(status)
20
+ unless tmp_status[:status] == :downloading && status[:status] == :waiting
21
+ new_status.push(tmp_status.merge!(status))
22
+ end
21
23
  else
22
24
  new_status = old_status.push(status)
23
25
  end
@@ -31,6 +33,34 @@ module SleepRoom
31
33
  @queue.enqueue(status)
32
34
  end
33
35
  end
36
+
37
+ def downloading(room:, url:, pid:, start_time:, output:)
38
+ add(
39
+ {
40
+ room: room,
41
+ live: true,
42
+ status: :downloading,
43
+ streaming_url: url,
44
+ pid: pid,
45
+ start_time: start_time
46
+ }
47
+ )
48
+ end
49
+
50
+ def waiting(room:, group:, room_name:, key:)
51
+ add(
52
+ {
53
+ room: room,
54
+ live: false,
55
+ group: group,
56
+ name: room_name,
57
+ status: :waiting,
58
+ websocket: {
59
+ key: key
60
+ }
61
+ }
62
+ )
63
+ end
34
64
  end
35
65
  end
36
66
  end
@@ -3,11 +3,17 @@
3
3
  require "configatron"
4
4
  require "colorize"
5
5
  require "fileutils"
6
+ require "tmpdir"
6
7
  require "yaml"
7
8
  require "logger"
9
+ require "dry/files"
8
10
 
9
11
  module SleepRoom
10
12
  class Error < StandardError; end
13
+ def self.files
14
+ Dry::Files.new
15
+ end
16
+
11
17
  # @return [String]
12
18
  def self.root_path
13
19
  Dir.pwd
@@ -64,6 +70,7 @@ module SleepRoom
64
70
  def self.create_config_file(config, settings)
65
71
  path = config_path(config)
66
72
  return false if File.exist?(path)
73
+
67
74
  mkdir(File.dirname(path)) unless Dir.exist?(File.dirname(path))
68
75
  write_config_file(config, settings)
69
76
  end
@@ -83,15 +90,10 @@ module SleepRoom
83
90
 
84
91
  def self.init_base
85
92
  base = {
86
- web: {
87
- use: true,
88
- server: "localhost",
89
- port: 3000
90
- },
91
93
  proxy: {
92
94
  use: false,
93
95
  server: "localhost",
94
- port: 8080,
96
+ port: 1080,
95
97
  type: "socks5"
96
98
  },
97
99
  record: {
@@ -106,11 +108,12 @@ module SleepRoom
106
108
  minyami: {
107
109
  threads: 8,
108
110
  retries: 999,
111
+ no_merge: false,
109
112
  },
110
113
  logger: {
111
114
  console: true,
112
115
  file: {
113
- use: true,
116
+ use: false,
114
117
  path: "#{sleeproom_dir}/log"
115
118
  }
116
119
  }
@@ -122,9 +125,9 @@ module SleepRoom
122
125
  mkdir(config_dir) unless Dir.exist?(config_dir)
123
126
 
124
127
  mkdir("#{config_dir}/tmp") unless Dir.exist?("#{config_dir}/tmp")
125
-
128
+
126
129
  init_base
127
-
130
+
128
131
  record = {
129
132
  "default" => []
130
133
  }
@@ -142,13 +145,15 @@ module SleepRoom
142
145
  end
143
146
  true
144
147
  rescue Errno::ENOENT => e
145
- error("Could not load file. \n#{e.message}")
148
+ info("Creating configuration...")
149
+ init_base
146
150
  false
147
151
  end
148
152
 
149
153
  def self.settings
150
154
  configatron
151
155
  end
156
+
152
157
  def self.load_status
153
158
  SleepRoom.load_config(:status)
154
159
  rescue Error
@@ -163,11 +168,11 @@ module SleepRoom
163
168
  retry
164
169
  end
165
170
 
166
- def self.running?(pid=nil)
171
+ def self.running?(pid = nil)
167
172
  pid = SleepRoom.load_config(:pid) if pid.nil?
168
- Process.getpgid(pid)
173
+ Process.kill(0, pid)
169
174
  true
170
- rescue
175
+ rescue StandardError
171
176
  false
172
177
  end
173
178
 
@@ -182,7 +187,7 @@ module SleepRoom
182
187
  SleepRoom.create_config_file(:status, status)
183
188
  end
184
189
 
185
- def self.create_record(record = {default: []})
190
+ def self.create_record(record = { default: [] })
186
191
  SleepRoom.create_config_file(:record, record)
187
192
  end
188
193
 
@@ -191,38 +196,81 @@ module SleepRoom
191
196
  SleepRoom.write_config_file(:pid, pid)
192
197
  end
193
198
 
199
+ def self.plugins
200
+
201
+ end
202
+
203
+ def self.find_tmp_directory(output, call_time)
204
+ regex = /Proccessing (.*) finished./
205
+ output = "#{configatron.save_path}/#{output}"
206
+ log = "#{output}.out"
207
+ if media_name = File.readlines(log).select { |line| line =~ regex }.last.match(regex)[1]
208
+ directories = Dir["#{Dir.tmpdir}/minyami_#{call_time.to_i / 10}*"]
209
+ directories.each do |path|
210
+ if Dir.glob("#{path}/*.ts").select{ |e| e.include?(media_name)}
211
+ next unless Dir.glob("#{path}/*.ts").last.include?(media_name)
212
+
213
+ return path
214
+ end
215
+ end
216
+ end
217
+ return false
218
+ rescue => e
219
+ puts e.full_message
220
+ SleepRoom.error("寻找失败.")
221
+ end
222
+
223
+ def self.move_ts_to_archive(tmp, path, name)
224
+ FileUtils.cp_r(tmp, path)
225
+ FileUtils.mv(File.join(path, File.basename(tmp)), File.join(path, name))
226
+ rescue => e
227
+ puts e.full_message
228
+ SleepRoom.error("复制失败.")
229
+ end
230
+
194
231
  # @param string [String]
195
232
  # @return [nil]
196
233
  def self.info(string)
197
- log(:info, "[INFO] #{string}".colorize(:white))
234
+ log(:info, string)
235
+ end
236
+
237
+ # @param string [String]
238
+ # @return [nil]
239
+ def self.debug(string)
240
+ log(:debug, string) if ENV["SR_DEBUG"]
198
241
  end
199
242
 
200
243
  # @param string [String]
201
244
  # @return [nil]
202
245
  def self.warning(string)
203
- log(:warning, "[WARN] #{string}".colorize(:yellow))
246
+ log(:warning, string)
204
247
  end
205
248
 
206
249
  # @param string [String]
207
250
  # @return [nil]
208
251
  def self.error(string)
209
- log(:error, "[ERROR] #{string}".colorize(:red))
252
+ log(:error, string)
210
253
  end
211
254
 
212
255
  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)
256
+ if configatron.logger.console == true
257
+ case type
258
+ when :info
259
+ puts("[INFO] #{log}".colorize(:white))
260
+ when :warning
261
+ warn("[WARN] #{log}".colorize(:yellow))
262
+ when :error
263
+ puts("[ERROR] #{log}".colorize(:red))
264
+ when :debug
265
+ puts("[DEBUG] #{log}".colorize(:gray))
266
+ end
220
267
  end
221
268
  file_logger(type, log) if configatron.logger.file.use == true
222
269
  end
223
270
 
224
271
  def self.file_logger(type, log)
225
272
  path = configatron.logger.file.path
273
+ mkdir(File.dirname(path)) unless Dir.exist?(File.dirname(path))
226
274
  logger = Logger.new(path)
227
275
  case type
228
276
  when :info