roku_builder 3.13.0 → 4.0.0
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/.travis.yml +1 -1
- data/CHANGELOG +12 -0
- data/Gemfile.lock +22 -7
- data/Guardfile +3 -3
- data/README.md +22 -398
- data/bin/roku +1 -194
- data/config.json.example +1 -1
- data/intergration/roku_builder/test_core.rb +52 -0
- data/intergration/roku_builder/test_files/core_intergration_test/manifest_template +7 -0
- data/intergration/roku_builder/test_files/core_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/components/rectanglescene.xml +28 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/source/main.brs +23 -0
- data/intergration/roku_builder/test_files/inspector_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/linker_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/loader_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/monitor_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/navigator_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/packager_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/profiler_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/scripter_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/components/rectanglescene.xml +29 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_mm_focus_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_splash_fhd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rde_splash_sd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rsgde_bg_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rsgde_mm_focus_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/images/rsgde_splash_hd.jpg +0 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/manifest +21 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/source/main.brs +21 -0
- data/intergration/roku_builder/test_files/tester_intergration_test/test.pkg +0 -0
- data/intergration/roku_builder/test_helper.rb +138 -0
- data/intergration/roku_builder/test_inspector.rb +35 -0
- data/intergration/roku_builder/test_linker.rb +32 -0
- data/intergration/roku_builder/test_loader.rb +38 -0
- data/intergration/roku_builder/test_monitor.rb +21 -0
- data/intergration/roku_builder/test_navigator.rb +34 -0
- data/intergration/roku_builder/test_packager.rb +41 -0
- data/intergration/roku_builder/test_profiler.rb +48 -0
- data/intergration/roku_builder/test_scripter.rb +38 -0
- data/intergration/roku_builder/test_tester.rb +21 -0
- data/lib/roku_builder.rb +143 -154
- data/lib/roku_builder/config.rb +17 -40
- data/lib/roku_builder/config_parser.rb +49 -200
- data/lib/roku_builder/config_validator.rb +1 -1
- data/lib/roku_builder/errors.rb +12 -0
- data/lib/roku_builder/git.rb +28 -0
- data/lib/roku_builder/hash.rb +8 -0
- data/lib/roku_builder/manifest.rb +121 -0
- data/lib/roku_builder/options.rb +68 -29
- data/lib/roku_builder/plugin.rb +30 -0
- data/lib/roku_builder/plugins/core.rb +117 -0
- data/lib/roku_builder/plugins/inspector.rb +104 -0
- data/lib/roku_builder/{linker.rb → plugins/linker.rb} +38 -12
- data/lib/roku_builder/plugins/loader.rb +152 -0
- data/lib/roku_builder/{monitor.rb → plugins/monitor.rb} +20 -9
- data/lib/roku_builder/{navigator.rb → plugins/navigator.rb} +136 -88
- data/lib/roku_builder/plugins/packager.rb +194 -0
- data/lib/roku_builder/plugins/profiler.rb +135 -0
- data/lib/roku_builder/plugins/scripter.rb +53 -0
- data/lib/roku_builder/{tester.rb → plugins/tester.rb} +28 -19
- data/lib/roku_builder/stager.rb +48 -12
- data/lib/roku_builder/string.rb +20 -0
- data/lib/roku_builder/util.rb +10 -34
- data/lib/roku_builder/version.rb +1 -1
- data/rakefile +5 -1
- data/roku_builder.gemspec +2 -0
- data/test/roku_builder/plugins/test_core.rb +112 -0
- data/test/roku_builder/plugins/test_inspector.rb +165 -0
- data/test/roku_builder/plugins/test_linker.rb +123 -0
- data/test/roku_builder/plugins/test_loader.rb +115 -0
- data/test/roku_builder/plugins/test_monitor.rb +141 -0
- data/test/roku_builder/plugins/test_navigator.rb +274 -0
- data/test/roku_builder/plugins/test_packager.rb +202 -0
- data/test/roku_builder/plugins/test_profiler.rb +127 -0
- data/test/roku_builder/plugins/test_scripter.rb +110 -0
- data/test/roku_builder/plugins/test_tester.rb +109 -0
- data/test/roku_builder/test_config.rb +51 -35
- data/test/roku_builder/test_config_parser.rb +76 -154
- data/test/roku_builder/test_config_validator.rb +18 -1
- data/test/roku_builder/test_files/{loader_test/manifest → config_parser_test/test.pkg} +0 -0
- data/test/roku_builder/test_files/config_test/config.json +3 -0
- data/test/roku_builder/test_files/controller_commands_test/manifest_template +7 -0
- data/test/roku_builder/test_files/core_test/manifest_template +7 -0
- data/test/roku_builder/test_files/core_test/test.pkg +0 -0
- data/test/roku_builder/test_files/inspector_test/manifest +6 -0
- data/test/roku_builder/test_files/inspector_test/test.pkg +0 -0
- data/test/roku_builder/test_files/linker_test/manifest +6 -0
- data/test/roku_builder/test_files/linker_test/test.pkg +0 -0
- data/test/roku_builder/test_files/loader_test/manifest_template +6 -0
- data/test/roku_builder/test_files/loader_test/test.pkg +0 -0
- data/test/roku_builder/test_files/loader_test/test.zip +0 -0
- data/test/roku_builder/test_files/manifest_test/manifest_comments +6 -0
- data/test/roku_builder/test_files/manifest_test/manifest_template +7 -0
- data/test/roku_builder/test_files/manifest_test/test.zip +0 -0
- data/test/roku_builder/test_files/packager_test/manifest +6 -0
- data/test/roku_builder/test_files/packager_test/scripter_test/manifest +6 -0
- data/test/roku_builder/test_files/packager_test/test.pkg +0 -0
- data/test/roku_builder/test_files/roku_builder_test/config.json +32 -0
- data/test/roku_builder/test_files/scripter_test/manifest +6 -0
- data/test/roku_builder/test_files/scripter_test/test.pkg +0 -0
- data/test/roku_builder/test_files/stager_test/test.pkg +0 -0
- data/test/roku_builder/test_files/tester_test/manifest +6 -0
- data/test/roku_builder/test_files/tester_test/test.pkg +0 -0
- data/test/roku_builder/test_helper.rb +44 -11
- data/test/roku_builder/test_logger.rb +1 -0
- data/test/roku_builder/test_manifest.rb +99 -0
- data/test/roku_builder/test_options.rb +106 -77
- data/test/roku_builder/test_options_plugins.rb +111 -0
- data/test/roku_builder/test_plugin.rb +48 -0
- data/test/roku_builder/test_roku_builder.rb +239 -0
- data/test/roku_builder/test_stager.rb +49 -101
- data/test/roku_builder/test_util.rb +19 -4
- metadata +241 -47
- data/lib/roku_builder/controller.rb +0 -98
- data/lib/roku_builder/controller_commands.rb +0 -224
- data/lib/roku_builder/error_handler.rb +0 -142
- data/lib/roku_builder/inspector.rb +0 -82
- data/lib/roku_builder/keyer.rb +0 -106
- data/lib/roku_builder/loader.rb +0 -131
- data/lib/roku_builder/manifest_manager.rb +0 -126
- data/lib/roku_builder/packager.rb +0 -43
- data/lib/roku_builder/profiler.rb +0 -96
- data/lib/roku_builder/scripter.rb +0 -39
- data/test/roku_builder/test_controller.rb +0 -70
- data/test/roku_builder/test_controller_commands.rb +0 -465
- data/test/roku_builder/test_error_handler.rb +0 -90
- data/test/roku_builder/test_inspector.rb +0 -298
- data/test/roku_builder/test_keyer.rb +0 -176
- data/test/roku_builder/test_linker.rb +0 -110
- data/test/roku_builder/test_loader.rb +0 -337
- data/test/roku_builder/test_manifest_manager.rb +0 -103
- data/test/roku_builder/test_monitor.rb +0 -137
- data/test/roku_builder/test_navigator.rb +0 -280
- data/test/roku_builder/test_packager.rb +0 -127
- data/test/roku_builder/test_profiler.rb +0 -35
- data/test/roku_builder/test_scripter.rb +0 -102
- data/test/roku_builder/test_tester.rb +0 -130
|
@@ -4,15 +4,42 @@ module RokuBuilder
|
|
|
4
4
|
|
|
5
5
|
# Launch application, sending parameters
|
|
6
6
|
class Linker < Util
|
|
7
|
+
extend Plugin
|
|
8
|
+
|
|
9
|
+
def self.commands
|
|
10
|
+
{
|
|
11
|
+
deeplink: {device: true, stage: true},
|
|
12
|
+
applist: {device: true}
|
|
13
|
+
}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.parse_options(parser:, options:)
|
|
17
|
+
parser.separator "Commands:"
|
|
18
|
+
parser.on("-o", "--deeplink OPTIONS", "Deeplink into app. Define options as keypairs. (eg. a:b, c:d,e:f)") do |o|
|
|
19
|
+
options[:deeplink] = o
|
|
20
|
+
end
|
|
21
|
+
parser.on("-A", "--app-list", "List currently installed apps") do
|
|
22
|
+
options[:applist] = true
|
|
23
|
+
end
|
|
24
|
+
parser.separator "Options:"
|
|
25
|
+
parser.on("-a", "--app ID", "Send App id for deeplinking") do |a|
|
|
26
|
+
options[:app_id] = a
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.dependencies
|
|
31
|
+
[Loader]
|
|
32
|
+
end
|
|
33
|
+
|
|
7
34
|
# Deeplink to an app
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
35
|
+
def deeplink(options:)
|
|
36
|
+
if options.has_source?
|
|
37
|
+
Loader.new(config: @config).sideload(options: options)
|
|
38
|
+
end
|
|
39
|
+
app_id = options[:app_id]
|
|
40
|
+
app_id ||= "dev"
|
|
14
41
|
path = "/launch/#{app_id}"
|
|
15
|
-
payload =
|
|
42
|
+
payload = RokuBuilder.options_parse(options: options[:deeplink])
|
|
16
43
|
|
|
17
44
|
unless payload.keys.count > 0
|
|
18
45
|
@logger.warn "No options sent to launched app"
|
|
@@ -25,15 +52,13 @@ module RokuBuilder
|
|
|
25
52
|
@logger.info "curl -d '' '#{@url}:8060#{path}'"
|
|
26
53
|
end
|
|
27
54
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
response = conn.post path
|
|
31
|
-
return response.success?
|
|
55
|
+
response = multipart_connection(port: 8060).post path
|
|
56
|
+
@logger.fatal("Failed Deeplinking") unless response.success?
|
|
32
57
|
end
|
|
33
58
|
|
|
34
59
|
# List currently installed apps
|
|
35
60
|
# @param logger [Logger] System Logger
|
|
36
|
-
def
|
|
61
|
+
def applist(options:)
|
|
37
62
|
path = "/query/apps"
|
|
38
63
|
conn = multipart_connection(port: 8060)
|
|
39
64
|
response = conn.get path
|
|
@@ -58,4 +83,5 @@ module RokuBuilder
|
|
|
58
83
|
params.collect{|k,v| "#{k}=#{CGI.escape(v)}"}.join('&')
|
|
59
84
|
end
|
|
60
85
|
end
|
|
86
|
+
RokuBuilder.register_plugin(Linker)
|
|
61
87
|
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# ********** Copyright Viacom, Inc. Apache 2.0 **********
|
|
2
|
+
|
|
3
|
+
module RokuBuilder
|
|
4
|
+
|
|
5
|
+
# Load/Unload/Build roku applications
|
|
6
|
+
class Loader < Util
|
|
7
|
+
extend Plugin
|
|
8
|
+
|
|
9
|
+
def self.commands
|
|
10
|
+
{
|
|
11
|
+
sideload: {source: true, device: true, stage: true},
|
|
12
|
+
build: {source: true, stage: true, exclude: true},
|
|
13
|
+
delete: {device: true}
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.parse_options(parser:, options:)
|
|
18
|
+
parser.separator "Commands:"
|
|
19
|
+
parser.on("-l", "--sideload", "Sideload an app") do
|
|
20
|
+
options[:sideload] = true
|
|
21
|
+
end
|
|
22
|
+
parser.on("-d", "--delete", "Delete the currently sideloaded app") do
|
|
23
|
+
options[:delete] = true
|
|
24
|
+
end
|
|
25
|
+
parser.on("-b", "--build", "Build a zip to be sideloaded") do
|
|
26
|
+
options[:build] = true
|
|
27
|
+
end
|
|
28
|
+
parser.separator "Options:"
|
|
29
|
+
parser.on("-x", "--exclude", "Apply exclude config to sideload") do
|
|
30
|
+
options[:exclude] = true
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.dependencies
|
|
35
|
+
[Navigator]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Sideload an app onto a roku device
|
|
39
|
+
def sideload(options:)
|
|
40
|
+
Navigator.new(config: @config).nav(options:{nav: "home"})
|
|
41
|
+
did_build = false
|
|
42
|
+
unless options[:in]
|
|
43
|
+
did_build = true
|
|
44
|
+
build(options: options)
|
|
45
|
+
end
|
|
46
|
+
upload
|
|
47
|
+
# Cleanup
|
|
48
|
+
File.delete(file_path(:in)) if did_build and not options[:out]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# Build an app to sideload later
|
|
53
|
+
def build(options:)
|
|
54
|
+
@options = options
|
|
55
|
+
build_zip(setup_build_content)
|
|
56
|
+
@config.in = @config.out #setting in path for possible sideload
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Remove the currently sideloaded app
|
|
60
|
+
def delete(options:)
|
|
61
|
+
payload = {mysubmit: "Delete", archive: ""}
|
|
62
|
+
response = multipart_connection.post "/plugin_install", payload
|
|
63
|
+
unless response.status == 200 and response.body =~ /Delete Succeeded/
|
|
64
|
+
raise ExecutionError, "Failed Unloading"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def upload
|
|
71
|
+
payload = {
|
|
72
|
+
mysubmit: "Replace",
|
|
73
|
+
archive: Faraday::UploadIO.new(file_path(:in), 'application/zip')
|
|
74
|
+
}
|
|
75
|
+
response = multipart_connection.post "/plugin_install", payload
|
|
76
|
+
if response.status==200 and response.body=~/Identical to previous version/
|
|
77
|
+
@logger.warn("Sideload identival to previous version")
|
|
78
|
+
elsif not (response.status==200 and response.body=~/Install Success/)
|
|
79
|
+
@logger.debug("Status: #{response.status}, Body: #{response.body}")
|
|
80
|
+
raise ExecutionError, "Failed Sideloading"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def file_path(type)
|
|
85
|
+
file = @config.send(type)[:file]
|
|
86
|
+
file ||= Manifest.new(config: @config).build_version
|
|
87
|
+
file = file+".zip" unless file.end_with?(".zip")
|
|
88
|
+
File.join(@config.send(type)[:folder], file)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def setup_build_content()
|
|
92
|
+
content = {}
|
|
93
|
+
content[:excludes] = []
|
|
94
|
+
if @options[:current]
|
|
95
|
+
content[:folders] = Dir.entries(@config.root_dir).select {|entry| File.directory? File.join(@config.root_dir, entry) and !(entry =='.' || entry == '..') }
|
|
96
|
+
content[:files] = Dir.entries(@config.root_dir).select {|entry| File.file? File.join(@config.root_dir, entry)}
|
|
97
|
+
else
|
|
98
|
+
content[:folders] = @config.project[:folders]
|
|
99
|
+
content[:files] = @config.project[:files]
|
|
100
|
+
content[:exclude] if @options[:exclude] or @options.exclude_command?
|
|
101
|
+
end
|
|
102
|
+
content
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def build_zip(content)
|
|
106
|
+
path = file_path(:out)
|
|
107
|
+
File.delete(path) if File.exist?(path)
|
|
108
|
+
io = Zip::File.open(path, Zip::File::CREATE)
|
|
109
|
+
# Add folders to zip
|
|
110
|
+
content[:folders].each do |folder|
|
|
111
|
+
base_folder = File.join(@config.root_dir, folder)
|
|
112
|
+
if File.exist?(base_folder)
|
|
113
|
+
entries = Dir.entries(base_folder)
|
|
114
|
+
entries.delete(".")
|
|
115
|
+
entries.delete("..")
|
|
116
|
+
writeEntries(@config.root_dir, entries, folder, content[:excludes], io)
|
|
117
|
+
else
|
|
118
|
+
@logger.warn "Missing Folder: #{base_folder}"
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
# Add file to zip
|
|
122
|
+
writeEntries(@config.parsed[:root_dir], content[:files], "", content[:excludes], io)
|
|
123
|
+
io.close()
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Recursively write directory contents to a zip archive
|
|
127
|
+
# @param root_dir [String] Path of the root directory
|
|
128
|
+
# @param entries [Array<String>] Array of file paths of files/directories to store in the zip archive
|
|
129
|
+
# @param path [String] The path of the current directory starting at the root directory
|
|
130
|
+
# @param io [IO] zip IO object
|
|
131
|
+
def writeEntries(root_dir, entries, path, excludes, io)
|
|
132
|
+
entries.each { |e|
|
|
133
|
+
zipFilePath = path == "" ? e : File.join(path, e)
|
|
134
|
+
diskFilePath = File.join(root_dir, zipFilePath)
|
|
135
|
+
if File.directory?(diskFilePath)
|
|
136
|
+
io.mkdir(zipFilePath)
|
|
137
|
+
subdir =Dir.entries(diskFilePath); subdir.delete("."); subdir.delete("..")
|
|
138
|
+
writeEntries(root_dir, subdir, zipFilePath, excludes, io)
|
|
139
|
+
else
|
|
140
|
+
unless excludes.include?(zipFilePath)
|
|
141
|
+
if File.exist?(diskFilePath)
|
|
142
|
+
io.get_output_stream(zipFilePath) { |f| f.puts(File.open(diskFilePath, "rb").read()) }
|
|
143
|
+
else
|
|
144
|
+
@logger.warn "Missing File: #{diskFilePath}"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
}
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
RokuBuilder.register_plugin(Loader)
|
|
152
|
+
end
|
|
@@ -4,25 +4,35 @@ module RokuBuilder
|
|
|
4
4
|
|
|
5
5
|
# Monitor development Logs
|
|
6
6
|
class Monitor < Util
|
|
7
|
+
extend Plugin
|
|
8
|
+
|
|
9
|
+
def self.commands
|
|
10
|
+
{ monitor: {device: true}}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.parse_options(parser:, options:)
|
|
14
|
+
parser.separator "Commands:"
|
|
15
|
+
parser.on("-m", "--monitor [TYPE]", "Run telnet to monitor roku log") do |m|
|
|
16
|
+
options[:monitor] = m || "main"
|
|
17
|
+
end
|
|
18
|
+
parser.separator "Options:"
|
|
19
|
+
parser.on("-R", "--regexp REGEXP", "A regular expression used to filter monitor logs") do |r|
|
|
20
|
+
options[:regexp] = r
|
|
21
|
+
end
|
|
22
|
+
end
|
|
7
23
|
|
|
8
24
|
# Initialize port config
|
|
9
25
|
def init()
|
|
10
26
|
@ports = {
|
|
11
27
|
main: 8085,
|
|
12
|
-
sg: 8089,
|
|
13
|
-
task1: 8090,
|
|
14
|
-
task2: 8091,
|
|
15
|
-
task3: 8092,
|
|
16
|
-
taskX: 8093,
|
|
17
28
|
profiler: 8080,
|
|
18
29
|
}
|
|
19
30
|
@show_prompt = false
|
|
20
31
|
end
|
|
21
32
|
|
|
22
33
|
# Monitor a development log on the Roku device
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def monitor(type:, regexp: nil)
|
|
34
|
+
def monitor(options:)
|
|
35
|
+
type = options[:monitor].to_sym
|
|
26
36
|
telnet_config = { 'Host' => @roku_ip_address, 'Port' => @ports[type] }
|
|
27
37
|
waitfor_config = { 'Match' => /./, 'Timeout' => false }
|
|
28
38
|
|
|
@@ -33,7 +43,7 @@ module RokuBuilder
|
|
|
33
43
|
all_text = ""
|
|
34
44
|
while true
|
|
35
45
|
connection.waitfor(waitfor) do |txt|
|
|
36
|
-
all_text = manage_text(all_text: all_text, txt: txt, regexp: regexp)
|
|
46
|
+
all_text = manage_text(all_text: all_text, txt: txt, regexp: options[:regexp])
|
|
37
47
|
end
|
|
38
48
|
end
|
|
39
49
|
}
|
|
@@ -118,4 +128,5 @@ module RokuBuilder
|
|
|
118
128
|
all_text
|
|
119
129
|
end
|
|
120
130
|
end
|
|
131
|
+
RokuBuilder.register_plugin(Monitor)
|
|
121
132
|
end
|
|
@@ -4,9 +4,39 @@ module RokuBuilder
|
|
|
4
4
|
|
|
5
5
|
# Navigation methods
|
|
6
6
|
class Navigator < Util
|
|
7
|
+
extend Plugin
|
|
8
|
+
|
|
9
|
+
def self.commands
|
|
10
|
+
{
|
|
11
|
+
nav: {device: true},
|
|
12
|
+
navigate: {device: true},
|
|
13
|
+
type: {device: true},
|
|
14
|
+
screen: {device: true},
|
|
15
|
+
screens: {}
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.parse_options(parser:, options:)
|
|
20
|
+
parser.separator("Commands:")
|
|
21
|
+
parser.on("-N", "--nav CMD", "Send the given command to the roku") do |n|
|
|
22
|
+
options[:nav] = n
|
|
23
|
+
end
|
|
24
|
+
parser.on("--navigate", "Run interactive navigator") do
|
|
25
|
+
options[:navigate] = true
|
|
26
|
+
end
|
|
27
|
+
parser.on("-y", "--type TEXT", "Type the given text on the roku device") do |t|
|
|
28
|
+
options[:type] = t
|
|
29
|
+
end
|
|
30
|
+
parser.on("--screen SCREEN", "Show a screen") do |s|
|
|
31
|
+
options[:screen] = s
|
|
32
|
+
end
|
|
33
|
+
parser.on("--screens", "Show possible screens") do
|
|
34
|
+
options[:screens] = true
|
|
35
|
+
end
|
|
36
|
+
end
|
|
7
37
|
|
|
8
38
|
# Setup navigation commands
|
|
9
|
-
def init(
|
|
39
|
+
def init()
|
|
10
40
|
@commands = {
|
|
11
41
|
home: "Home", rew: "Rev", ff: "Fwd",
|
|
12
42
|
play: "Play", select: "Select", left: "Left",
|
|
@@ -33,67 +63,33 @@ module RokuBuilder
|
|
|
33
63
|
@runable = [
|
|
34
64
|
:secret, :channels
|
|
35
65
|
]
|
|
36
|
-
mappings_init
|
|
66
|
+
mappings_init
|
|
37
67
|
end
|
|
38
68
|
|
|
39
|
-
# Init Mappings
|
|
40
|
-
def mappings_init(mappings: nil)
|
|
41
|
-
@mappings = {
|
|
42
|
-
"\e[1~": [ "home", "Home" ],
|
|
43
|
-
"<": [ "rew", "<" ],
|
|
44
|
-
">": [ "ff", ">" ],
|
|
45
|
-
"=": [ "play", "=" ],
|
|
46
|
-
"\r": [ "select", "Enter" ],
|
|
47
|
-
"\e[D": [ "left", "Left Arrow" ],
|
|
48
|
-
"\e[C": [ "right", "Right Arrow" ],
|
|
49
|
-
"\e[B": [ "down", "Down Arrow" ],
|
|
50
|
-
"\e[A": [ "up", "Up Arrow" ],
|
|
51
|
-
"\t": [ "back", "Tab" ],
|
|
52
|
-
#"": [ "replay", "" ],
|
|
53
|
-
"*": [ "info", "*" ],
|
|
54
|
-
"\u007f": [ "backspace", "Backspace" ],
|
|
55
|
-
"?": [ "search", "?" ],
|
|
56
|
-
"\e\r": [ "enter", "Alt + Enter" ],
|
|
57
|
-
"\e[5~": [ "volumeup", "Page Up" ],
|
|
58
|
-
"\e[6~": [ "volumedown", "Page Down" ],
|
|
59
|
-
"\e[4~": [ "mute", "End" ],
|
|
60
|
-
#"": [ "channeldown", "" ],
|
|
61
|
-
#"": [ "channelup", "" ],
|
|
62
|
-
#"": [ "tuner", "" ],
|
|
63
|
-
#"": [ "hdmi1", "" ],
|
|
64
|
-
#"": [ "hdmi2", "" ],
|
|
65
|
-
#"": [ "hdmi3", "" ],
|
|
66
|
-
#"": [ "hdmi4", "" ],
|
|
67
|
-
#"": [ "avi", "" ]
|
|
68
|
-
}
|
|
69
|
-
@mappings.merge!(mappings) if mappings
|
|
70
|
-
end
|
|
71
69
|
|
|
72
70
|
# Send a navigation command to the roku device
|
|
73
71
|
# @param command [Symbol] The smbol of the command to send
|
|
74
72
|
# @return [Boolean] Success
|
|
75
|
-
def nav(
|
|
73
|
+
def nav(options:)
|
|
74
|
+
commands = options[:nav].split(/, */).map{|c| c.to_sym}
|
|
76
75
|
commands.each do |command|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
path = "/keypress/#{@commands[command]}"
|
|
81
|
-
@logger.debug("Send Command: "+path)
|
|
82
|
-
response = conn.post path
|
|
83
|
-
return false unless response.success?
|
|
84
|
-
else
|
|
85
|
-
return false
|
|
76
|
+
unless @commands.has_key?(command)
|
|
77
|
+
raise ExecutionError, "Unknown Navigation Command"
|
|
86
78
|
end
|
|
79
|
+
conn = multipart_connection(port: 8060)
|
|
80
|
+
path = "/keypress/#{@commands[command]}"
|
|
81
|
+
@logger.debug("Send Command: "+path)
|
|
82
|
+
response = conn.post path
|
|
83
|
+
raise ExecutionError, "Navigation Failed" unless response.success?
|
|
87
84
|
end
|
|
88
|
-
return true
|
|
89
85
|
end
|
|
90
86
|
|
|
91
87
|
# Type text on the roku device
|
|
92
88
|
# @param text [String] The text to type on the device
|
|
93
89
|
# @return [Boolean] Success
|
|
94
|
-
def type(
|
|
90
|
+
def type(options:)
|
|
95
91
|
conn = multipart_connection(port: 8060)
|
|
96
|
-
|
|
92
|
+
options[:type].split(//).each do |c|
|
|
97
93
|
path = "/keypress/LIT_#{CGI::escape(c)}"
|
|
98
94
|
@logger.debug("Send Letter: "+path)
|
|
99
95
|
response = conn.post path
|
|
@@ -102,7 +98,7 @@ module RokuBuilder
|
|
|
102
98
|
return true
|
|
103
99
|
end
|
|
104
100
|
|
|
105
|
-
def
|
|
101
|
+
def navigate(options:)
|
|
106
102
|
running = true
|
|
107
103
|
@logger.info("Key Mappings:")
|
|
108
104
|
@mappings.each_value {|key|
|
|
@@ -115,64 +111,83 @@ module RokuBuilder
|
|
|
115
111
|
if char == "\u0003"
|
|
116
112
|
running = false
|
|
117
113
|
else
|
|
118
|
-
Thread.new(char) {|character|
|
|
119
|
-
if @mappings[character.to_sym] != nil
|
|
120
|
-
nav(commands:[@mappings[character.to_sym][0].to_sym])
|
|
121
|
-
elsif character.inspect.force_encoding("UTF-8").ascii_only?
|
|
122
|
-
type(text: character)
|
|
123
|
-
end
|
|
124
|
-
}
|
|
114
|
+
Thread.new(char) {|character| handle_navigate_input(character)}
|
|
125
115
|
end
|
|
126
116
|
end
|
|
127
117
|
end
|
|
128
118
|
|
|
119
|
+
|
|
129
120
|
# Show the commands for one of the roku secret screens
|
|
130
121
|
# @param type [Symbol] The type of screen to show
|
|
131
122
|
# @return [Boolean] Screen found
|
|
132
|
-
def screen(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
display, count, string = [], [], ""
|
|
140
|
-
@screens[type].each do |command|
|
|
141
|
-
if display.count > 0 and display[-1] == command
|
|
142
|
-
count[-1] = count[-1] + 1
|
|
143
|
-
else
|
|
144
|
-
display.push(command)
|
|
145
|
-
count.push(1)
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
display.each_index do |i|
|
|
149
|
-
if count[i] > 1
|
|
150
|
-
string = string + @commands[display[i]]+" x "+count[i].to_s+", "
|
|
151
|
-
else
|
|
152
|
-
string = string + @commands[display[i]]+", "
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
if @runable.include?(type)
|
|
156
|
-
@logger.info(string.strip)
|
|
157
|
-
else
|
|
158
|
-
@logger.unknown(string.strip)
|
|
159
|
-
end
|
|
123
|
+
def screen(options:)
|
|
124
|
+
type = options[:screen].to_sym
|
|
125
|
+
unless @screens.has_key?(type)
|
|
126
|
+
raise ExecutionError, "Unknown Screen"
|
|
127
|
+
end
|
|
128
|
+
if @runable.include?(type)
|
|
129
|
+
nav(options: {nav: @screens[type].join(", ")})
|
|
160
130
|
else
|
|
161
|
-
|
|
131
|
+
@logger.unknown("Cannot run command automatically")
|
|
162
132
|
end
|
|
163
|
-
|
|
133
|
+
display_screen_command(type)
|
|
164
134
|
end
|
|
165
135
|
|
|
166
136
|
# Show avaiable roku secret screens
|
|
167
|
-
def screens
|
|
137
|
+
def screens(options:)
|
|
168
138
|
@screens.keys.each {|screen| @logger.unknown(screen)}
|
|
169
139
|
end
|
|
170
140
|
|
|
141
|
+
private
|
|
142
|
+
|
|
143
|
+
def mappings_init()
|
|
144
|
+
@mappings = {
|
|
145
|
+
"\e[1~": [ "home", "Home" ],
|
|
146
|
+
"<": [ "rew", "<" ],
|
|
147
|
+
">": [ "ff", ">" ],
|
|
148
|
+
"=": [ "play", "=" ],
|
|
149
|
+
"\r": [ "select", "Enter" ],
|
|
150
|
+
"\e[D": [ "left", "Left Arrow" ],
|
|
151
|
+
"\e[C": [ "right", "Right Arrow" ],
|
|
152
|
+
"\e[B": [ "down", "Down Arrow" ],
|
|
153
|
+
"\e[A": [ "up", "Up Arrow" ],
|
|
154
|
+
"\t": [ "back", "Tab" ],
|
|
155
|
+
#"": [ "replay", "" ],
|
|
156
|
+
"*": [ "info", "*" ],
|
|
157
|
+
"\u007f": [ "backspace", "Backspace" ],
|
|
158
|
+
"?": [ "search", "?" ],
|
|
159
|
+
"\e\r": [ "enter", "Alt + Enter" ],
|
|
160
|
+
"\e[5~": [ "volumeup", "Page Up" ],
|
|
161
|
+
"\e[6~": [ "volumedown", "Page Down" ],
|
|
162
|
+
"\e[4~": [ "mute", "End" ],
|
|
163
|
+
#"": [ "channeldown", "" ],
|
|
164
|
+
#"": [ "channelup", "" ],
|
|
165
|
+
#"": [ "tuner", "" ],
|
|
166
|
+
#"": [ "hdmi1", "" ],
|
|
167
|
+
#"": [ "hdmi2", "" ],
|
|
168
|
+
#"": [ "hdmi3", "" ],
|
|
169
|
+
#"": [ "hdmi4", "" ],
|
|
170
|
+
#"": [ "avi", "" ]
|
|
171
|
+
}
|
|
172
|
+
@mappings.merge!(generate_maggings) if @config.input_mappings
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def generate_maggings
|
|
176
|
+
mappings = {}
|
|
177
|
+
if @config.input_mappings
|
|
178
|
+
@config.input_mappings.each_pair {|key, value|
|
|
179
|
+
unless "".to_sym == key
|
|
180
|
+
key = key.to_s.sub(/\\e/, "\e").to_sym
|
|
181
|
+
mappings[key] = value
|
|
182
|
+
end
|
|
183
|
+
}
|
|
184
|
+
end
|
|
185
|
+
mappings
|
|
186
|
+
end
|
|
187
|
+
|
|
171
188
|
def read_char
|
|
172
189
|
STDIN.echo = false
|
|
173
190
|
STDIN.raw!
|
|
174
|
-
|
|
175
|
-
|
|
176
191
|
input = STDIN.getc.chr
|
|
177
192
|
if input == "\e" then
|
|
178
193
|
input << STDIN.read_nonblock(3) rescue nil
|
|
@@ -183,5 +198,38 @@ module RokuBuilder
|
|
|
183
198
|
STDIN.echo = true
|
|
184
199
|
STDIN.cooked!
|
|
185
200
|
end
|
|
201
|
+
|
|
202
|
+
def handle_navigate_input(char)
|
|
203
|
+
if @mappings[char.to_sym] != nil
|
|
204
|
+
nav(options: {nav: @mappings[char.to_sym][0]})
|
|
205
|
+
elsif char.inspect.force_encoding("UTF-8").ascii_only?
|
|
206
|
+
type(options: {type: char})
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def display_screen_command(type)
|
|
211
|
+
display, count, string = [], [], ""
|
|
212
|
+
@screens[type].each do |command|
|
|
213
|
+
if display.count > 0 and display[-1] == command
|
|
214
|
+
count[-1] = count[-1] + 1
|
|
215
|
+
else
|
|
216
|
+
display.push(command)
|
|
217
|
+
count.push(1)
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
display.each_index do |i|
|
|
221
|
+
if count[i] > 1
|
|
222
|
+
string = string + @commands[display[i]]+" x "+count[i].to_s+", "
|
|
223
|
+
else
|
|
224
|
+
string = string + @commands[display[i]]+", "
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
if @runable.include?(type)
|
|
228
|
+
@logger.info(string.strip)
|
|
229
|
+
else
|
|
230
|
+
@logger.unknown(string.strip)
|
|
231
|
+
end
|
|
232
|
+
end
|
|
186
233
|
end
|
|
234
|
+
RokuBuilder.register_plugin(Navigator)
|
|
187
235
|
end
|