roku_builder 3.11.0 → 3.11.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,31 +6,7 @@ module RokuBuilder
6
6
  class Keyer < Util
7
7
 
8
8
  def genkey(out_file: nil)
9
- telnet_config = {
10
- 'Host' => @roku_ip_address,
11
- 'Port' => 8080
12
- }
13
- connection = Net::Telnet.new(telnet_config)
14
- connection.puts("genkey")
15
- waitfor_config = {
16
- 'Match' => /./,
17
- 'Timeout' => false
18
- }
19
- password = nil
20
- dev_id = nil
21
- while password.nil? or dev_id.nil?
22
- connection.waitfor(waitfor_config) do |txt|
23
- while line = txt.slice!(/^.*\n/) do
24
- words = line.split
25
- if words[0] == "Password:"
26
- password = words[1]
27
- elsif words[0] == "DevID:"
28
- dev_id = words[1]
29
- end
30
- end
31
- end
32
- end
33
- connection.close
9
+ password, dev_id = generate_new_key()
34
10
  @logger.info("Password: "+password)
35
11
  @logger.info("DevID: "+dev_id)
36
12
 
@@ -93,5 +69,38 @@ module RokuBuilder
93
69
  dev_id ||= "none"
94
70
  dev_id
95
71
  end
72
+
73
+ private
74
+
75
+ # Uses the device to generate a new signing key
76
+ # @return [Array<String>] Password and dev_id for the new key
77
+ def generate_new_key()
78
+ telnet_config = {
79
+ 'Host' => @roku_ip_address,
80
+ 'Port' => 8080
81
+ }
82
+ connection = Net::Telnet.new(telnet_config)
83
+ connection.puts("genkey")
84
+ waitfor_config = {
85
+ 'Match' => /./,
86
+ 'Timeout' => false
87
+ }
88
+ password = nil
89
+ dev_id = nil
90
+ while password.nil? or dev_id.nil?
91
+ connection.waitfor(waitfor_config) do |txt|
92
+ while line = txt.slice!(/^.*\n/) do
93
+ words = line.split
94
+ if words[0] == "Password:"
95
+ password = words[1]
96
+ elsif words[0] == "DevID:"
97
+ dev_id = words[1]
98
+ end
99
+ end
100
+ end
101
+ end
102
+ connection.close
103
+ return password, dev_id
104
+ end
96
105
  end
97
106
  end
@@ -15,37 +15,34 @@ module RokuBuilder
15
15
  # @param root_dir [String] Path to the root directory of the roku app
16
16
  # @param content [Hash] Hash containing arrays for folder, files, and excludes. Default: nil
17
17
  # @return [String] Build version on success, nil otherwise
18
- def sideload(update_manifest: false, content: nil, infile: nil)
18
+ def sideload(update_manifest: false, content: nil, infile: nil, out_file: nil)
19
19
  Navigator.new(**@device_config).nav(commands: [:home])
20
20
  result = FAILED_SIDELOAD
21
- outfile = nil
22
21
  build_version = nil
23
22
  if infile
24
23
  build_version = ManifestManager.build_version(root_dir: infile)
25
- return [MISSING_MANIFEST, nil] if outfile == MISSING_MANIFEST
26
- outfile = infile
24
+ out_file = infile
27
25
  else
28
26
  # Update manifest
29
27
  if update_manifest
30
28
  build_version = ManifestManager.update_build(root_dir: @root_dir)
31
- return [MISSING_MANIFEST, nil] if outfile == MISSING_MANIFEST
32
29
  else
33
30
  build_version = ManifestManager.build_version(root_dir: @root_dir)
34
- return [MISSING_MANIFEST, nil] if outfile == MISSING_MANIFEST
35
31
  end
36
- outfile = build(build_version: build_version, content: content)
37
- return [MISSING_MANIFEST, nil] if outfile == MISSING_MANIFEST
32
+ @logger.info "Build: #{out_file}" if out_file
33
+ out_file = build(build_version: build_version, out_file: out_file, content: content)
38
34
  end
35
+ return [MISSING_MANIFEST, nil] if out_file == MISSING_MANIFEST
39
36
  path = "/plugin_install"
40
37
  # Connect to roku and upload file
41
38
  conn = multipart_connection
42
39
  payload = {
43
40
  mysubmit: "Replace",
44
- archive: Faraday::UploadIO.new(outfile, 'application/zip')
41
+ archive: Faraday::UploadIO.new(out_file, 'application/zip')
45
42
  }
46
43
  response = conn.post path, payload
47
44
  # Cleanup
48
- File.delete(outfile) unless infile
45
+ File.delete(out_file) if infile.nil? and out_file.nil?
49
46
  result = SUCCESS if response.status==200 and response.body=~/Install Success/
50
47
  result = IDENTICAL_SIDELOAD if response.status==200 and response.body=~/Identical to previous version/
51
48
  [result, build_version]
@@ -55,23 +52,20 @@ module RokuBuilder
55
52
  # Build an app to sideload later
56
53
  # @param root_dir [String] Path to the root directory of the roku app
57
54
  # @param build_version [String] Version to assigne to the build. If nil will pull the build version form the manifest. Default: nil
58
- # @param outfile [String] Path for the output file. If nil will create a file in /tmp. Default: nil
55
+ # @param out_file [String] Path for the output file. If nil will create a file in /tmp. Default: nil
59
56
  # @param content [Hash] Hash containing arrays for folder, files, and excludes. Default: nil
60
57
  # @return [String] Path of the build
61
- def build(build_version: nil, outfile: nil, content: nil)
58
+ def build(build_version: nil, out_file: nil, content: nil)
62
59
  build_version = ManifestManager.build_version(root_dir: @root_dir) unless build_version
63
60
  return MISSING_MANIFEST if build_version == MISSING_MANIFEST
64
61
  content ||= {}
65
- unless content and content[:folders]
66
- content[:folders] = Dir.entries(@root_dir).select {|entry| File.directory? File.join(@root_dir, entry) and !(entry =='.' || entry == '..') }
67
- end
68
- unless content and content[:files]
69
- content[:files] = Dir.entries(@root_dir).select {|entry| File.file? File.join(@root_dir, entry)}
70
- end
71
- content[:excludes] = [] unless content and content[:excludes]
72
- outfile = "/tmp/build_#{build_version}.zip" unless outfile
73
- File.delete(outfile) if File.exist?(outfile)
74
- io = Zip::File.open(outfile, Zip::File::CREATE)
62
+ content[:folders] ||= Dir.entries(@root_dir).select {|entry| File.directory? File.join(@root_dir, entry) and !(entry =='.' || entry == '..') }
63
+ content[:files] ||= Dir.entries(@root_dir).select {|entry| File.file? File.join(@root_dir, entry)}
64
+ content[:excludes] ||= []
65
+ out_file = "/tmp/#{build_version}" unless out_file
66
+ out_file = out_file+".zip" unless out_file.end_with?(".zip")
67
+ File.delete(out_file) if File.exist?(out_file)
68
+ io = Zip::File.open(out_file, Zip::File::CREATE)
75
69
  # Add folders to zip
76
70
  content[:folders].each do |folder|
77
71
  base_folder = File.join(@root_dir, folder)
@@ -87,7 +81,7 @@ module RokuBuilder
87
81
  # Add file to zip
88
82
  writeEntries(@root_dir, content[:files], "", content[:excludes], io)
89
83
  io.close()
90
- outfile
84
+ out_file
91
85
  end
92
86
 
93
87
  # Remove the currently sideloaded app
@@ -22,14 +22,8 @@ module RokuBuilder
22
22
  # Monitor a development log on the Roku device
23
23
  # @param type [Symbol] The log type to monitor
24
24
  def monitor(type:)
25
- telnet_config = {
26
- 'Host' => @roku_ip_address,
27
- 'Port' => @ports[type]
28
- }
29
- waitfor_config = {
30
- 'Match' => /./,
31
- 'Timeout' => false
32
- }
25
+ telnet_config = { 'Host' => @roku_ip_address, 'Port' => @ports[type] }
26
+ waitfor_config = { 'Match' => /./, 'Timeout' => false }
33
27
 
34
28
  thread = Thread.new(telnet_config, waitfor_config) {|telnet,waitfor|
35
29
  @logger.info "Monitoring #{type} console(#{telnet['Port']}) on #{telnet['Host'] }"
@@ -42,8 +36,16 @@ module RokuBuilder
42
36
  end
43
37
  end
44
38
  }
45
- # setup readline
46
39
 
40
+ init_readline()
41
+
42
+ run_prompt(thread: thread)
43
+ end
44
+
45
+ private
46
+
47
+ # Setup tab completeion for Readline
48
+ def init_readline
47
49
  libedit = false
48
50
  begin
49
51
  Readline.vi_editing_mode
@@ -62,8 +64,10 @@ module RokuBuilder
62
64
 
63
65
  Readline.completion_append_character = " "
64
66
  Readline.completion_proc = comp
67
+ end
65
68
 
66
-
69
+ # Check if needs to display prompt, displays prompt, and processes input
70
+ def run_prompt(thread:)
67
71
  running = true
68
72
  @logger.unknown "Q to exit"
69
73
  while running
@@ -90,9 +94,7 @@ module RokuBuilder
90
94
  end
91
95
  end
92
96
 
93
- private
94
-
95
- # Handel text from telnet
97
+ # Handle text from telnet
96
98
  # @param all_text [String] remaining partial line text
97
99
  # @param txt [String] current string from telnet
98
100
  # @return [String] remaining partial line text
@@ -8,34 +8,36 @@ module RokuBuilder
8
8
  # Setup navigation commands
9
9
  def init(mappings: nil)
10
10
  @commands = {
11
- home: "Home",
12
- rew: "Rev",
13
- ff: "Fwd",
14
- play: "Play",
15
- select: "Select",
16
- left: "Left",
17
- right: "Right",
18
- down: "Down",
19
- up: "Up",
20
- back: "Back",
21
- replay: "InstantReplay",
22
- info: "Info",
23
- backspace: "Backspace",
24
- search: "Search",
25
- enter: "Enter",
26
- volumedown: "VolumeDown",
27
- volumeup: "VolumeUp",
28
- mute: "VolumeMute",
29
- channelup: "ChannelUp",
30
- channeldown: "ChannelDown",
31
- tuner: "InputTuner",
32
- hdmi1: "InputHDMI1",
33
- hdmi2: "InputHDMI2",
34
- hdmi3: "InputHDMI3",
35
- hdmi4: "InputHDMI4",
36
- avi: "InputAVI"
11
+ home: "Home", rew: "Rev", ff: "Fwd",
12
+ play: "Play", select: "Select", left: "Left",
13
+ right: "Right", down: "Down", up: "Up",
14
+ back: "Back", replay: "InstantReplay", info: "Info",
15
+ backspace: "Backspace", search: "Search", enter: "Enter",
16
+ volumedown: "VolumeDown", volumeup: "VolumeUp", mute: "VolumeMute",
17
+ channelup: "ChannelUp", channeldown: "ChannelDown", tuner: "InputTuner",
18
+ hdmi1: "InputHDMI1", hdmi2: "InputHDMI2", hdmi3: "InputHDMI3",
19
+ hdmi4: "InputHDMI4", avi: "InputAVI"
37
20
  }
21
+ @screens = {
22
+ platform: [:home, :home, :home, :home, :home, :ff, :play, :rew, :play, :ff],
23
+ secret: [:home, :home, :home, :home, :home, :ff, :ff, :ff, :rew, :rew],
24
+ secret2: [:home, :home, :home, :home, :home, :up, :right, :down, :left, :up],
25
+ channels: [:home, :home, :home, :up, :up, :left, :right, :left, :right, :left],
26
+ developer: [:home, :home, :home, :up, :up, :right, :left, :right, :left, :right],
27
+ wifi: [:home, :home, :home, :home, :home, :up, :down, :up, :down, :up],
28
+ antenna: [:home, :home, :home, :home, :home, :ff, :down, :rew, :down, :ff],
29
+ bitrate: [:home, :home, :home, :home, :home, :rew, :rew, :rew, :ff, :ff],
30
+ network: [:home, :home, :home, :home, :home, :right, :left, :right, :left, :right],
31
+ reboot: [:home, :home, :home, :home, :home, :up, :rew, :rew, :ff, :ff]
32
+ }
33
+ @runable = [
34
+ :secret, :channels
35
+ ]
36
+ mappings_init(mappings: mappings)
37
+ end
38
38
 
39
+ # Init Mappings
40
+ def mappings_init(mappings: nil)
39
41
  @mappings = {
40
42
  "\e[1~": [ "home", "Home" ],
41
43
  "<": [ "rew", "<" ],
@@ -64,25 +66,7 @@ module RokuBuilder
64
66
  #"": [ "hdmi4", "" ],
65
67
  #"": [ "avi", "" ]
66
68
  }
67
-
68
69
  @mappings.merge!(mappings) if mappings
69
-
70
- @screens = {
71
- platform: [:home, :home, :home, :home, :home, :ff, :play, :rew, :play, :ff],
72
- secret: [:home, :home, :home, :home, :home, :ff, :ff, :ff, :rew, :rew],
73
- secret2: [:home, :home, :home, :home, :home, :up, :right, :down, :left, :up],
74
- channels: [:home, :home, :home, :up, :up, :left, :right, :left, :right, :left],
75
- developer: [:home, :home, :home, :up, :up, :right, :left, :right, :left, :right],
76
- wifi: [:home, :home, :home, :home, :home, :up, :down, :up, :down, :up],
77
- antenna: [:home, :home, :home, :home, :home, :ff, :down, :rew, :down, :ff],
78
- bitrate: [:home, :home, :home, :home, :home, :rew, :rew, :rew, :ff, :ff],
79
- network: [:home, :home, :home, :home, :home, :right, :left, :right, :left, :right],
80
- reboot: [:home, :home, :home, :home, :home, :up, :rew, :rew, :ff, :ff]
81
- }
82
-
83
- @runable = [
84
- :secret, :channels
85
- ]
86
70
  end
87
71
 
88
72
  # Send a navigation command to the roku device
@@ -152,8 +136,7 @@ module RokuBuilder
152
136
  else
153
137
  @logger.unknown("Cannot run command automatically")
154
138
  end
155
- display = []
156
- count = []
139
+ display, count, string = [], [], ""
157
140
  @screens[type].each do |command|
158
141
  if display.count > 0 and display[-1] == command
159
142
  count[-1] = count[-1] + 1
@@ -162,7 +145,6 @@ module RokuBuilder
162
145
  count.push(1)
163
146
  end
164
147
  end
165
- string = ""
166
148
  display.each_index do |i|
167
149
  if count[i] > 1
168
150
  string = string + @commands[display[i]]+" x "+count[i].to_s+", "
@@ -170,7 +152,6 @@ module RokuBuilder
170
152
  string = string + @commands[display[i]]+", "
171
153
  end
172
154
  end
173
-
174
155
  if @runable.include?(type)
175
156
  @logger.info(string.strip)
176
157
  else
@@ -191,16 +172,16 @@ module RokuBuilder
191
172
  STDIN.echo = false
192
173
  STDIN.raw!
193
174
 
175
+
194
176
  input = STDIN.getc.chr
195
177
  if input == "\e" then
196
178
  input << STDIN.read_nonblock(3) rescue nil
197
179
  input << STDIN.read_nonblock(2) rescue nil
198
180
  end
181
+ input
199
182
  ensure
200
183
  STDIN.echo = true
201
184
  STDIN.cooked!
202
-
203
- return input
204
185
  end
205
186
  end
206
187
  end
@@ -35,7 +35,7 @@ module RokuBuilder
35
35
  end
36
36
  response = conn.get path
37
37
  return false if response.status != 200
38
-
38
+ out_file = out_file+".pkg" unless out_file.end_with?(".pkg")
39
39
  File.open(out_file, 'w+') {|fp| fp.write(response.body)}
40
40
  true
41
41
  end
@@ -25,7 +25,7 @@ module RokuBuilder
25
25
  connection = Net::Telnet.new(telnet_config)
26
26
  code, _build_version = loader.sideload(**sideload_config)
27
27
 
28
- if code = SUCCESS
28
+ if code == SUCCESS
29
29
  in_tests = false
30
30
  connection.waitfor(@end_reg) do |txt|
31
31
  in_tests = handle_text(txt: txt, in_tests: in_tests)
@@ -2,5 +2,5 @@
2
2
 
3
3
  module RokuBuilder
4
4
  # Version of the RokuBuilder Gem
5
- VERSION = "3.11.0"
5
+ VERSION = "3.11.1"
6
6
  end
data/roku_builder.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.required_ruby_version = "~> 2.3"
22
22
 
23
23
  spec.add_dependency "rubyzip", "~> 1.2"
24
- spec.add_dependency "faraday", "~> 0.10"
24
+ spec.add_dependency "faraday", "~> 0.11"
25
25
  spec.add_dependency "faraday-digestauth", "~> 0.2"
26
26
  spec.add_dependency "git", "~> 1.3"
27
27
  spec.add_dependency "net-ping", "~> 2.0"
@@ -280,4 +280,62 @@ class ConfigManagerTest < Minitest::Test
280
280
  assert_equal 2, config[:projects][:p2][:folders].count
281
281
  File.delete(target_config) if File.exist?(target_config)
282
282
  end
283
+
284
+ def test_config_manager_update_configs
285
+ configs = {
286
+ project_config: { app_name: "<app_name>" },
287
+ package_config: {},
288
+ stage: "<stage>",
289
+ out: { file: nil, folder: "/tmp" }
290
+ }
291
+ options = {
292
+ build_version: "<build_version>"
293
+ }
294
+ configs = RokuBuilder::ConfigManager.update_configs(configs: configs, options: options)
295
+ assert_equal "<app_name> - <stage> - <build_version>", configs[:package_config][:app_name_version]
296
+ assert_equal "<app_name>_<stage>_<build_version>", configs[:out][:file]
297
+ assert_equal "/tmp/<app_name>_<stage>_<build_version>", configs[:package_config][:out_file]
298
+
299
+ configs = {
300
+ project_config: { app_name: "<app_name>" },
301
+ package_config: {},
302
+ stage: "<stage>",
303
+ out: { file: "file.pkg", folder: "/home/user" }
304
+ }
305
+ options = {
306
+ build_version: "<build_version>"
307
+ }
308
+ configs = RokuBuilder::ConfigManager.update_configs(configs: configs, options: options)
309
+ assert_equal "<app_name> - <stage> - <build_version>", configs[:package_config][:app_name_version]
310
+ assert_equal "file.pkg", configs[:out][:file]
311
+ assert_equal "/home/user/file.pkg", configs[:package_config][:out_file]
312
+
313
+ configs = {
314
+ project_config: { app_name: "<app_name>" },
315
+ build_config: {},
316
+ stage: "<stage>",
317
+ out: { file: nil, folder: "/tmp" }
318
+ }
319
+ options = {
320
+ build_version: "<build_version>"
321
+ }
322
+ configs = RokuBuilder::ConfigManager.update_configs(configs: configs, options: options)
323
+ assert_equal "<app_name>_<stage>_<build_version>", configs[:out][:file]
324
+ assert_equal "/tmp/<app_name>_<stage>_<build_version>", configs[:build_config][:out_file]
325
+
326
+ configs = {
327
+ project_config: { app_name: "<app_name>" },
328
+ inspect_config: {},
329
+ package_config: {},
330
+ stage: "<stage>",
331
+ out: { file: nil, folder: "/tmp" }
332
+ }
333
+ options = {
334
+ build_version: "<build_version>"
335
+ }
336
+ configs = RokuBuilder::ConfigManager.update_configs(configs: configs, options: options)
337
+ assert_equal "<app_name>_<stage>_<build_version>", configs[:out][:file]
338
+ assert_equal "/tmp/<app_name>_<stage>_<build_version>", configs[:package_config][:out_file]
339
+ assert_equal "/tmp/<app_name>_<stage>_<build_version>", configs[:inspect_config][:pkg]
340
+ end
283
341
  end