a4tools 1.2.7
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 +7 -0
- data/.bundle/install.log +38 -0
- data/.gitignore +2 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +38 -0
- data/a4tools.gemspec +38 -0
- data/bin/deploy_latest_clients +32 -0
- data/bin/devsite_config_server +48 -0
- data/bin/netshell +23 -0
- data/bin/update_server +101 -0
- data/bin/usher +54 -0
- data/lib/a4tools.rb +61 -0
- data/lib/a4tools/version.rb +3 -0
- data/lib/acres_client.rb +376 -0
- data/lib/clients/caching_client.rb +151 -0
- data/lib/clients/deployment_client.rb +53 -0
- data/lib/clients/kai_config_client.rb +39 -0
- data/lib/clients/usher_client.rb +72 -0
- data/lib/clients/usher_mgmt_client.rb +201 -0
- data/lib/event_manager.rb +24 -0
- data/lib/events.json +1 -0
- data/lib/net_shell/builtin_command.rb +312 -0
- data/lib/net_shell/builtin_commands/build.rb +251 -0
- data/lib/net_shell/builtin_commands/cd.rb +12 -0
- data/lib/net_shell/builtin_commands/connect.rb +122 -0
- data/lib/net_shell/builtin_commands/deploy.rb +280 -0
- data/lib/net_shell/builtin_commands/disconnect.rb +15 -0
- data/lib/net_shell/builtin_commands/excerpt.rb +97 -0
- data/lib/net_shell/builtin_commands/exit.rb +7 -0
- data/lib/net_shell/builtin_commands/get.rb +38 -0
- data/lib/net_shell/builtin_commands/help.rb +40 -0
- data/lib/net_shell/builtin_commands/host.rb +126 -0
- data/lib/net_shell/builtin_commands/inject.rb +42 -0
- data/lib/net_shell/builtin_commands/jsoncache.rb +80 -0
- data/lib/net_shell/builtin_commands/kai_event.rb +151 -0
- data/lib/net_shell/builtin_commands/persist.rb +24 -0
- data/lib/net_shell/builtin_commands/pwd.rb +6 -0
- data/lib/net_shell/builtin_commands/recap.rb +188 -0
- data/lib/net_shell/builtin_commands/references.rb +63 -0
- data/lib/net_shell/builtin_commands/select.rb +36 -0
- data/lib/net_shell/builtin_commands/send.rb +74 -0
- data/lib/net_shell/builtin_commands/set.rb +29 -0
- data/lib/net_shell/builtin_commands/show.rb +183 -0
- data/lib/net_shell/builtin_commands/site.rb +122 -0
- data/lib/net_shell/builtin_commands/ssh.rb +62 -0
- data/lib/net_shell/builtin_commands/talk.rb +90 -0
- data/lib/net_shell/builtin_commands/translate.rb +45 -0
- data/lib/net_shell/builtin_commands/unset.rb +14 -0
- data/lib/net_shell/builtin_commands/usher.rb +55 -0
- data/lib/net_shell/builtin_commands/usher_device.rb +39 -0
- data/lib/net_shell/builtin_commands/usher_site.rb +245 -0
- data/lib/net_shell/builtin_commands/usherm_connect.rb +21 -0
- data/lib/net_shell/colors.rb +149 -0
- data/lib/net_shell/command.rb +97 -0
- data/lib/net_shell/io.rb +132 -0
- data/lib/net_shell/net_shell.rb +396 -0
- data/lib/net_shell/prompt.rb +335 -0
- data/lib/object_builder/definitions/app_info_for_script.rb +83 -0
- data/lib/object_builder/definitions/connection_request.rb +28 -0
- data/lib/object_builder/definitions/device_info_for_system.rb +37 -0
- data/lib/object_builder/object_builder.rb +145 -0
- data/lib/talk.json +1 -0
- data/lib/talk_consumer.rb +235 -0
- metadata +279 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
module A4Tools
|
2
|
+
class DeploymentClient < CachingClient
|
3
|
+
attr_accessor :cache_timeout
|
4
|
+
|
5
|
+
cache :buildList, :authenticate => true do
|
6
|
+
{
|
7
|
+
allowedAppIds:nil,
|
8
|
+
allowedCommitIds:nil
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
query :buildPublicationList, :authenticate => true do |site_id|
|
13
|
+
{
|
14
|
+
siteId:site_id
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def publish_build(build, sites)
|
19
|
+
sites = [*sites]
|
20
|
+
return false unless authenticate_if_needed
|
21
|
+
|
22
|
+
request = {
|
23
|
+
commitId:build[:commitId],
|
24
|
+
appIds:[build[:appId]],
|
25
|
+
publicationTime:0,
|
26
|
+
siteIds:sites
|
27
|
+
}
|
28
|
+
|
29
|
+
result = send_message(wrapped_message("buildPublish", "com.acres4.common.info.build.BuildPublishRequest", request))
|
30
|
+
return false unless result.code.to_i >= 200 and result.code.to_i < 300
|
31
|
+
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
def index_list_by_app
|
36
|
+
builds = cache(:buildList)
|
37
|
+
apps = {}
|
38
|
+
builds.each do |build|
|
39
|
+
apps[build[:appId]] ||= []
|
40
|
+
apps[build[:appId]].push build
|
41
|
+
end
|
42
|
+
|
43
|
+
apps.values.each { |app_builds| app_builds.sort! { |a,b| a[:postDate] <=> b[:postDate] } }
|
44
|
+
apps
|
45
|
+
end
|
46
|
+
|
47
|
+
def builds_for_milestone(milestone, builds=nil)
|
48
|
+
index = index_list_by_app(builds)
|
49
|
+
in_milestone = []
|
50
|
+
(index.map { |app, builds| (builds.select { |b| b[:branches].is_a? Array and b[:branches].include? milestone }).last }).compact
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module A4Tools
|
2
|
+
class KaiConfigClient < CachingClient
|
3
|
+
attr_accessor :cache_timeout
|
4
|
+
|
5
|
+
#cache :getConfigWebVersion, :authenticate => true
|
6
|
+
|
7
|
+
query :configValueRequest, :authenticate => true do |id_config|
|
8
|
+
{
|
9
|
+
idConfig:id_config
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def strip_wrapper(result)
|
14
|
+
body = result[:configValueWrappers][0][:wrappedConfigValues][0][:body]
|
15
|
+
body[:__class] = result[:configValueWrappers][0][:wrappedConfigValues][0][:className]
|
16
|
+
body
|
17
|
+
end
|
18
|
+
|
19
|
+
def site_version
|
20
|
+
response_body(send_message(empty_query(:getConfigWebVersion)))[:stringValue] rescue nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def section_bank_info
|
24
|
+
strip_wrapper(query(:configValueRequest, talk["SECTION_BANK_LOCATION_VALUES"]))
|
25
|
+
end
|
26
|
+
|
27
|
+
def machines
|
28
|
+
(section_bank_info[:locations].map { |loc| loc[:location] })
|
29
|
+
end
|
30
|
+
|
31
|
+
def sections
|
32
|
+
(section_bank_info[:sections].map { |sect| sect[:sectionName] })
|
33
|
+
end
|
34
|
+
|
35
|
+
def banks
|
36
|
+
(section_bank_info[:banks].map { |bank| bank[:bankName] })
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module A4Tools
|
2
|
+
class UsherClient < AcresClient
|
3
|
+
class << self
|
4
|
+
def mirrors
|
5
|
+
[
|
6
|
+
"http://s01.ushers.acres4.net:8080/usher2/json?wrap",
|
7
|
+
"http://s02.ushers.acres4.net:8080/usher2/json?wrap",
|
8
|
+
"http://s03.ushers.acres4.net:8080/usher2/json?wrap"
|
9
|
+
]
|
10
|
+
end
|
11
|
+
|
12
|
+
def random_mirror
|
13
|
+
_m = mirrors
|
14
|
+
_m[rand(_m.length)]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :response
|
19
|
+
|
20
|
+
def initialize(uri=nil)
|
21
|
+
super(uri || self.class.random_mirror)
|
22
|
+
end
|
23
|
+
|
24
|
+
def usher_request_for_params(params)
|
25
|
+
request = {
|
26
|
+
app: app_info,
|
27
|
+
device: device_info
|
28
|
+
}
|
29
|
+
|
30
|
+
request[:device][:serialNumber] = params[:serial] if params.has_key?(:serial)
|
31
|
+
request[:ipOverride] = params[:ip] if params.has_key?(:ip)
|
32
|
+
|
33
|
+
request
|
34
|
+
end
|
35
|
+
|
36
|
+
def list_servers_raw(params={})
|
37
|
+
response = send_message(wrapped_message(params[:full] ? "usherAlt" : "usher", "com.acres4.common.info.usher.UsherRequest", usher_request_for_params(params)))
|
38
|
+
@list = response_body response
|
39
|
+
response
|
40
|
+
end
|
41
|
+
|
42
|
+
def list_servers(params={})
|
43
|
+
list_servers_raw
|
44
|
+
@list
|
45
|
+
end
|
46
|
+
|
47
|
+
def dump_usher_response(response=nil)
|
48
|
+
response ||= @list
|
49
|
+
s = "Site #{response['siteID']} (#{response['siteName']})\n"
|
50
|
+
|
51
|
+
response[:hosts].each do |host|
|
52
|
+
s += "\t#{host["product"]}, #{host["url"]}#{host["context"]}\n"
|
53
|
+
end
|
54
|
+
s += "\n"
|
55
|
+
end
|
56
|
+
|
57
|
+
def locate_service(service, response=nil)
|
58
|
+
list_servers unless @list
|
59
|
+
response ||= @list
|
60
|
+
|
61
|
+
products = response[:hosts].select do |h|
|
62
|
+
h[:product].match("^#{service}(-(Secure|Server))?$")
|
63
|
+
end
|
64
|
+
|
65
|
+
products.sort! do |h,o|
|
66
|
+
h[:product] <=> o[:product]
|
67
|
+
end
|
68
|
+
|
69
|
+
products.first
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
module A4Tools
|
4
|
+
class UsherMgmtClient < CachingClient
|
5
|
+
attr_accessor :cache_timeout
|
6
|
+
def initialize(destination, username, password, timeout=300)
|
7
|
+
super(destination || "https://usherm.acres4.net:8181/usher2/json", username, password, timeout)
|
8
|
+
end
|
9
|
+
|
10
|
+
cache :usherSystemId
|
11
|
+
cache :devSiteInfoSync
|
12
|
+
cache :usherInfo, :authenticate => true do
|
13
|
+
{
|
14
|
+
force:false,
|
15
|
+
crc:nil
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_device_in_info(serial, site_info_list=nil, sync=false)
|
20
|
+
if site_info_list.nil? then
|
21
|
+
site_info_list = cache(:devSiteInfoSync, sync)
|
22
|
+
return nil if site_info_list.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
site_info_list ||= @site_info_list
|
26
|
+
|
27
|
+
site_info_list[:devSiteInfoArray].each do |info|
|
28
|
+
return info if info[:serialNumber] == serial
|
29
|
+
end
|
30
|
+
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def make_device(serial, description, site)
|
35
|
+
{
|
36
|
+
idDevSiteInfo: 0,
|
37
|
+
serialNumber: serial,
|
38
|
+
description: description,
|
39
|
+
idSite: site,
|
40
|
+
__class: "com.acres4.common.info.usher.DevSiteInfo"
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
def make_edit_for_device(device)
|
45
|
+
{
|
46
|
+
editObj: {
|
47
|
+
className:"com.acres4.common.info.usher.DevSiteInfo",
|
48
|
+
body:device
|
49
|
+
},
|
50
|
+
tok:@token
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def update_device(serial, description, site, default_description="Added via API")
|
55
|
+
return nil unless authenticate_if_needed
|
56
|
+
device = find_device_in_info(serial) || make_device(serial, description || default_description, site)
|
57
|
+
device[:description] = description unless description.nil?
|
58
|
+
device[:idSite] = site
|
59
|
+
|
60
|
+
result = send_message(jsonrpc_message("usherEdit", nil, "com.acres4.common.info.usher.UsherEditRequest", make_edit_for_device(device)))
|
61
|
+
dirty
|
62
|
+
response_body(result)
|
63
|
+
end
|
64
|
+
|
65
|
+
def delete_device(serial)
|
66
|
+
return nil unless authenticate_if_needed
|
67
|
+
device = find_device_in_info(serial) || make_device(serial, description || default_description, site)
|
68
|
+
return nil if device.nil?
|
69
|
+
|
70
|
+
device[:idDevSiteInfo] = -1 * device[:idDevSiteInfo]
|
71
|
+
|
72
|
+
result = send_message(jsonrpc_message("usherEdit", nil, "com.acres4.common.info.usher.UsherEditRequest", make_edit_for_device(device)))
|
73
|
+
response_body(result)
|
74
|
+
end
|
75
|
+
|
76
|
+
def datacenter(id, sync=false)
|
77
|
+
cache(:usherSystemId,sync)[:dataCenters].each { |ctr| return ctr if ctr[:idDataCenter] == id }
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
|
81
|
+
def provider(id, sync=false)
|
82
|
+
cache(:usherSystemId,sync)[:systemProviders].each { |provider| return provider if provider[:idSystemProvider].to_i == id.to_i }
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
def env_type(type)
|
87
|
+
case type
|
88
|
+
when 0
|
89
|
+
"Development"
|
90
|
+
when 1
|
91
|
+
"QA"
|
92
|
+
when 2
|
93
|
+
"Production"
|
94
|
+
else
|
95
|
+
"Unknown (#{type})"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def system_type(type)
|
100
|
+
case type
|
101
|
+
when -1
|
102
|
+
"All"
|
103
|
+
when -2
|
104
|
+
"Development"
|
105
|
+
when -3
|
106
|
+
"Production"
|
107
|
+
else
|
108
|
+
"Unknown (#{type})"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def host_named(hostname, sync=false)
|
113
|
+
(cache(:usherSystemId, sync)[:systemHosts].each { |host| return host if host[:hostName] == hostname }) rescue nil
|
114
|
+
nil
|
115
|
+
end
|
116
|
+
|
117
|
+
def host_with_id(host_id, sync=false)
|
118
|
+
(cache(:usherSystemId, sync)[:systemHosts].each { |host| return host if host[:idSystemHost] == host_id.to_i }) rescue nil
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
|
122
|
+
def site_with_id(site_id, sync=false)
|
123
|
+
(cache(:usherSystemId, sync)[:usherSites].each { |site| return site if site[:idSite] == site_id.to_i }) rescue nil
|
124
|
+
nil
|
125
|
+
end
|
126
|
+
|
127
|
+
def site_with_name(site_name, sync=false)
|
128
|
+
(cache(:usherSystemId, sync)[:usherSites].each { |site| return site if site[:name] == site_name }) rescue nil
|
129
|
+
nil
|
130
|
+
end
|
131
|
+
|
132
|
+
def acls_for_host_id(id, sync=false)
|
133
|
+
(cache(:usherInfo, sync)[:systemAcls].select { |acl| acl[:idSystemHost] == id }) rescue nil
|
134
|
+
end
|
135
|
+
|
136
|
+
def service_for_id(id, sync=false)
|
137
|
+
(cache(:usherInfo, sync)[:services].each { |service| return service if service[:idService] == id }) rescue nil
|
138
|
+
end
|
139
|
+
|
140
|
+
def acl_for_service(host, name)
|
141
|
+
begin
|
142
|
+
host = host_named(host) if host.is_a? String
|
143
|
+
acls = acls_for_host_id(host[:idSystemHost])
|
144
|
+
acls.each do |acl|
|
145
|
+
service = service_for_id(acl[:idService])
|
146
|
+
return acl if service[:name] == name
|
147
|
+
end
|
148
|
+
rescue
|
149
|
+
host
|
150
|
+
end
|
151
|
+
nil
|
152
|
+
end
|
153
|
+
|
154
|
+
def providers_for_site(site_id)
|
155
|
+
providers = self[:usherSystemId][:systemProviders]
|
156
|
+
providers = providers.sort { |a,b| a[:product] <=> b[:product] }
|
157
|
+
providers = providers.reject { |p| p[:idSites].nil? or not p[:idSites].include?(site_id.to_i) }
|
158
|
+
end
|
159
|
+
|
160
|
+
def hosts_for_provider(provider)
|
161
|
+
internal = provider[:usherHostsInternal] || []
|
162
|
+
external = provider[:usherHostsExternal] || []
|
163
|
+
hosts = internal + external
|
164
|
+
secure = hosts.select { |host| host[:product] == provider[:product] + "-Secure" }
|
165
|
+
return hosts if secure.empty?
|
166
|
+
secure
|
167
|
+
end
|
168
|
+
|
169
|
+
def provider_for_product(site_id, product)
|
170
|
+
providers = providers_for_site(site_id)
|
171
|
+
return nil if providers.nil?
|
172
|
+
providers.each { |prov| return prov if prov[:product] == product }
|
173
|
+
nil
|
174
|
+
end
|
175
|
+
|
176
|
+
def url_for_provider(provider)
|
177
|
+
opts = hosts_for_provider(provider).map { |host| { :host => host[:host], :port => host[:port], :url => host[:url] } }
|
178
|
+
result = try_connection_options(opts)
|
179
|
+
return (result[:url] rescue nil)
|
180
|
+
end
|
181
|
+
|
182
|
+
def host_for_url(url)
|
183
|
+
url = URI(url) unless url.is_a? URI
|
184
|
+
|
185
|
+
self[:usherSystemId][:systemProviders].each do |prov|
|
186
|
+
hosts_for_provider(prov).each do |host|
|
187
|
+
return host[:hostName] if host_matches_url(host, url)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
nil
|
192
|
+
end
|
193
|
+
|
194
|
+
def host_matches_url(host, url)
|
195
|
+
host_url = URI(host[:url]) rescue nil
|
196
|
+
return true if host_url and url.host == host_url.host and url.port == host_url.port and url.scheme == host_url.scheme
|
197
|
+
return true if url.host == host[:hostName] and url.port == host[:port]
|
198
|
+
false
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module A4Tools
|
2
|
+
class EventManager
|
3
|
+
attr_accessor :events
|
4
|
+
|
5
|
+
def initialize(events=nil)
|
6
|
+
events = File.read(File.join(File.dirname(__FILE__), "events.json")) if events.nil?
|
7
|
+
events = File.read(events) if events.is_a? String and File.exists? events
|
8
|
+
events = JSON.parse(events) if events.is_a? String
|
9
|
+
|
10
|
+
@events = transform_events(events)
|
11
|
+
end
|
12
|
+
|
13
|
+
def transform_events(events)
|
14
|
+
events.map do |event|
|
15
|
+
{ code:event["code"].to_i, key:event["key"].to_sym, description:event["description"] }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def event(id)
|
20
|
+
@events.each { |event| return event if event[:code] == id.to_i or event[:key] == id.to_sym }
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/events.json
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
[{"code":10,"description":"Ticket printed - cashable voucher","key":"ticket_print"},{"code":20,"description":"Cash out button pressed","key":"cash_out"},{"code":30,"description":"Ticket inserted","key":"ticket_insert"},{"code":40,"description":"Ticket redeemed","key":"ticket_redeem"},{"code":50,"description":"Card removed","key":"card_remove"},{"code":70,"description":"Player card inserted","key":"card_insert_player"},{"code":80,"description":"Bill 20 inserted","key":"bill_insert_20"},{"code":90,"description":"Bill 5 inserted","key":"bill_insert_5"},{"code":100,"description":"Cash out occurred","key":"cash_out"},{"code":110,"description":"Bill 1 inserted","key":"bill_insert_1"},{"code":120,"description":"Bill acceptor bill rejected","key":"bill_reject"},{"code":130,"description":"Machine link up","key":"machine_link_up"},{"code":140,"description":"Machine link down","key":"machine_link_down"},{"code":150,"description":"Xtra Credit Played","key":"extra_credit_played"},{"code":160,"description":"Main door closed","key":"door_closed"},{"code":170,"description":"Bill 100 inserted","key":"bill_insert_100"},{"code":180,"description":"Bill 10 inserted","key":"bill_insert_10"},{"code":190,"description":"Change light off","key":"change_light_off"},{"code":200,"description":"Change light on","key":"change_light_on"},{"code":210,"description":"Illegal machine door opened","key":"door_open_illegal"},{"code":220,"description":"General tilt","key":"tilt_general"},{"code":230,"description":"Belly door closed","key":"belly_door_closed"},{"code":240,"description":"Cash box door closed","key":"cashbox_door_close"},{"code":250,"description":"Hopper Paid Progressive","key":"hopper_paid_progressive"},{"code":260,"description":"Cash box door opened","key":"cashbox_door_open"},{"code":270,"description":"Main door opened","key":"main_door_open"},{"code":280,"description":"Employee card inserted","key":"card_insert_employee"},{"code":290,"description":"Bill acceptor removed","key":"bill_acceptor_remove"},{"code":300,"description":"Bill acceptor inserted","key":"bill_acceptor_insert"},{"code":310,"description":"Belly door opened","key":"belly_door_open"},{"code":320,"description":"Printer paper low","key":"printer_paper_low"},{"code":330,"description":"Poker Bonus","key":"poker_bonus"},{"code":340,"description":"Invalid Player card inserted","key":"card_insert_invalid"},{"code":350,"description":"Totals zeroed","key":"totals_zeroed"},{"code":360,"description":"Points -> XtraCredits","key":"points_to_credit"},{"code":370,"description":"Illegal belly door open ","key":"belly_door_open_illegal"},{"code":380,"description":"Drop door closed","key":"drop_door_close"},{"code":390,"description":"Illegal drop door opened","key":"drop_door_open_illegal"},{"code":400,"description":"New Member Player card inserted","key":"card_insert_new_player"},{"code":410,"description":"Game buffer full","key":"game_buffer_full"},{"code":420,"description":"Bill 50 inserted","key":"bill_insert_50"},{"code":430,"description":"BE2 Online","key":"be2_online"},{"code":440,"description":"Bill acceptor hardware error","key":"bill_acceptor_hardware_error"},{"code":450,"description":"Printer paper out","key":"printer_paper_out"},{"code":460,"description":"BE2 Offline","key":"be2_offline"},{"code":470,"description":"Ticket rejected - rejected by","key":"ticket_reject_1"},{"code":480,"description":"Logic cage opened","key":"logiccage_open"},{"code":490,"description":"Logic cage closed","key":"logiccage_close"},{"code":500,"description":"Hot Player","key":"hot_player"},{"code":510,"description":"Display meters entered","key":"display_meters_enter"},{"code":520,"description":"Display meters exited","key":"display_meters_exit"},{"code":530,"description":"Game power on","key":"game_power_on"},{"code":540,"description":"Printer carriage jam","key":"printer_carriage_jam"},{"code":550,"description":"Game power off","key":"game_power_off"},{"code":560,"description":"Game recall","key":"game_recall"},{"code":570,"description":"Illegal cash box door opened","key":"cashbox_door_illegal"},{"code":580,"description":"Ticket rejected - amt not mult","key":"ticket_reject_2"},{"code":590,"description":"Account PIN locked","key":"account_pin_lock"},{"code":600,"description":"Time discrepancy","key":"time_discrepency"},{"code":610,"description":"Ticket rejected - redemption d","key":"ticket_reject_3"},{"code":620,"description":"Self test entered","key":"self_test_enter"},{"code":630,"description":"Self test exited","key":"self_test_exit"},{"code":640,"description":"Card PIN locked","key":"card_pin_lock"},{"code":650,"description":"OP changed","key":"op_change"},{"code":660,"description":"Printer on","key":"printer_on"},{"code":670,"description":"BE2 reset","key":"be2_reset"},{"code":680,"description":"Account PIN unlocked","key":"account_pin_unlock"},{"code":690,"description":"Printer comm error","key":"printer_comm_error"},{"code":700,"description":"Ticket rejected - timeout","key":"ticket_reject_4"},{"code":710,"description":"Power off slot door access ","key":"door_access_power_off"},{"code":720,"description":"FJP Ticket printed","key":"fjp_ticket_print"},{"code":730,"description":"Printer off","key":"printer_off"},{"code":740,"description":"Coin-in runaway limit exceeded","key":"coinin_runaway_limit"},{"code":750,"description":"Bill acceptor jam","key":"bill_acceptor_jam"},{"code":760,"description":"Handpay reset","key":"handpay_reset"},{"code":770,"description":"Power off cashbox door access ","key":"cashbox_door_open_power_off"},{"code":780,"description":"Logic cage door closed","key":"logiccage_door_close"},{"code":790,"description":"Illegal logic cage door opened","key":"logiccage_door_open_illegal"},{"code":800,"description":"FJP Handpay Ticket","key":"fjp_handpay_ticket"},{"code":820,"description":"Ticket printed - jackpot recor","key":"ticket_print_jackpot_record"},{"code":830,"description":"Drop door opened ","key":"drop_door_open"},{"code":840,"description":"Out of service","key":"out_of_service"},{"code":850,"description":"Bill acceptor full","key":"bill_acceptor_full"},{"code":860,"description":"Ticket rejected - unable to ac","key":"ticket_reject_5"},{"code":870,"description":"Device passed CRC","key":"device_passed_crc"},{"code":880,"description":"Ticket rejected - validator fa","key":"ticket_reject_6"},{"code":890,"description":"Ticket accepted/rejected","key":"ticket_accepted_rejected"},{"code":900,"description":"Activate paytable(s) ","key":"paytable_activate"},{"code":910,"description":"FJP Cancel Credit Ticket","key":"fjp_cancel_credit_ticket"},{"code":920,"description":"Reel tilt","key":"tilt_reel"},{"code":930,"description":"Abandoned Player card inserted","key":"card_insert_abandoned"},{"code":940,"description":"Ticket rejected - amt > credit","key":"ticket_reject_7"},{"code":950,"description":"XC used during session","key":"extra_credit_used_during_session"},{"code":960,"description":"Cancel credit reset","key":"cancel_credit_reset"},{"code":970,"description":"Coin test card inserted","key":"card_insert_cointest"},{"code":980,"description":"Abandoned Card","key":"abandoned_card"},{"code":990,"description":"Bonus changed","key":"bonus_changed"},{"code":1000,"description":"Ticket printed - handpay recor","key":"ticket_print_handpay_record"},{"code":1010,"description":"Reel disconnected","key":"reel_disconnected"},{"code":1020,"description":"Cancel credit pending","key":"cancel_credit_pending"},{"code":1030,"description":"Reel 3 tilt","key":"tilt_reel_3"},{"code":1040,"description":"Deactivate paytable(s) ","key":"paytable_deactivate"},{"code":1050,"description":"Ticket rejected - out of cycle","key":"ticket_reject_8"},{"code":1060,"description":"KDC node added","key":"kdc_node_add"},{"code":1070,"description":"Memory error reset","key":"memory_error_reset"},{"code":1080,"description":"KDC node removed","key":"kdc_node_remove"},{"code":1090,"description":"Reel 5 tilt","key":"tilt_reel_5"},{"code":1100,"description":"EGM removed from bonus","key":"egm_remove_from_bonus"},{"code":1110,"description":"Meter zeroed","key":"meter_zeroed"},{"code":1120,"description":"FJP Short Pay Ticket","key":"fjp_short_pay_ticket"},{"code":1140,"description":"Power off card cage access ","key":"card_cage_access_power_off"},{"code":1150,"description":"Progressive Jackpot pending W2","key":"progressive_jackpot_pending_w2"},{"code":1160,"description":"Power off drop door access ","key":"drop_door_open_power_off"},{"code":1170,"description":"Ticket rejected - bad transfer","key":"ticket_reject_9"},{"code":1180,"description":"Low battery","key":"low_battery"},{"code":1190,"description":"EGM added to bonus","key":"egm_add_to_bonus"},{"code":1200,"description":"FJP Progressive Ticket","key":"fjp_progressive_jackpot"},{"code":1210,"description":"Reel 2 tilt","key":"tilt_reel_2"},{"code":1220,"description":"Progressive Link failure","key":"progressive_link_failure"},{"code":1230,"description":"KDC node updated","key":"kdc_node_update"},{"code":1240,"description":"Card Inserted","key":"card_insert"},{"code":1250,"description":"Coin in tilt","key":"tilt_coin_in"},{"code":1260,"description":"Reel 1 tilt","key":"tilt_reel_1"},{"code":1270,"description":"Pay out reset","key":"pay_out_reset"},{"code":1280,"description":"Jackpot pending","key":"jackpot_pending"},{"code":1281,"description":"Tilt: Reel #1","key":"tilt_reel_1a"},{"code":1282,"description":"Tilt: Reel #2","key":"tilt_reel_2a"},{"code":1283,"description":"Tilt: Reel #3","key":"tilt_reel_3a"},{"code":1284,"description":"Tilt: Reel #4","key":"tilt_reel_4a"},{"code":1285,"description":"Tilt: Reel #5","key":"tilt_reel_5a"},{"code":1290,"description":"Reel 4 tilt","key":"tilt_reel_4"},{"code":1300,"description":"Node on line","key":"node_online"},{"code":1310,"description":"Enabled games or denoms changed ","key":"change_game_config"},{"code":1320,"description":"Node off line","key":"node_offline"},{"code":1330,"description":"Logic cage door opened","key":"logiccage_door_open"},{"code":1340,"description":"Unknown handpay","key":"unknown_handpay"},{"code":1350,"description":"Logic cage ram error data recovered","key":"logiccage_ram_error_recover"},{"code":1360,"description":"Eprom data error","key":"eprom_data_error"},{"code":1370,"description":"Device passed SHA","key":"device_passed_sha"},{"code":1380,"description":"Hopper full","key":"hopper_full"},{"code":1390,"description":"No response to SHA challenge","key":"sha_no_response"},{"code":1400,"description":"Bill acceptor bill reversed","key":"bill_acceptor_bill_reverse"},{"code":1410,"description":"Reverse coin in","key":"coin_in_reverse"},{"code":1420,"description":"BE2 door opened","key":"be2_door_open"},{"code":1430,"description":"Logic cage ram error data lost","key":"logiccage_ram_error_lost"},{"code":1440,"description":"Ticket rejected - number doesn","key":"ticket_reject_10"},{"code":1450,"description":"Cashout Ticket Printed","key":"ticket_print_cashout"},{"code":1460,"description":"PEprom bad checksum version","key":"eprom_checksum_error"},{"code":1500,"description":"Bonus Card Out","key":"bonus_card_out"},{"code":1510,"description":"Cash Transfer Tracking","key":"cash_transfer_tracking"},{"code":1520,"description":"Hopper low","key":"hopper_low"},{"code":1530,"description":"Jackpot Reset Key","key":"jackpot_reset_key"},{"code":1550,"description":"Mechanic In","key":"mechanic_in"},{"code":1560,"description":"Mechanic Out","key":"mechanic_out"},{"code":1570,"description":"Meter Comparison In","key":"meter_comparison_in"},{"code":1580,"description":"Meter Comparison Out","key":"meter_comparison_out"},{"code":1590,"description":"Personal Banker","key":"personal_banker"},{"code":1600,"description":"Player Update","key":"player_update"},{"code":1610,"description":"Possible Bad Card Reader","key":"cardreader_bad_reader"},{"code":1620,"description":"Progressive JP - Hopper Paid","key":"progressive_jackpot_hopper_paid"},{"code":1630,"description":"Progressive Level 0","key":"progressive_level_0"},{"code":1640,"description":"Progressive Level 1","key":"progressive_level_1"},{"code":1650,"description":"Progressive Level 2","key":"progressive_level_2"},{"code":1660,"description":"Progressive Level 3","key":"progressive_level_3"},{"code":1670,"description":"Progressive Level 4","key":"progressive_level_4"},{"code":1680,"description":"Progressive Level 5","key":"progressive_level_5"},{"code":1690,"description":"Progressive Level 6","key":"progressive_level_6"},{"code":1700,"description":"Progressive Level 7","key":"progressive_level_7"},{"code":1710,"description":"Progressive Level 8","key":"progressive_level_8"},{"code":1720,"description":"Progressive Level 9","key":"progressive_level_9"},{"code":1730,"description":"Request system validation #","key":"request_system_validation"},{"code":1740,"description":"Request Ticket Information","key":"request_ticket_information"},{"code":1750,"description":"Ticket Processing","key":"ticket_processing"},{"code":1760,"description":"Ticket Printed, System Val #","key":"ticket_printed"},{"code":1770,"description":"Comp Ticket Printed","key":"comp_ticket_printed"},{"code":1780,"description":"Machine rejected voucher","key":"voucher_rejected"},{"code":1790,"description":"Ticket confiscated by machine","key":"ticket_confiscated"},{"code":1800,"description":"Print status unknown","key":"print_status_unknown"},{"code":1810,"description":"Game timeout awaiting val #","key":"game_timeout_waiting"},{"code":1820,"description":"Invalid print message","key":"print_message_invalid"},{"code":1830,"description":"Printer failure, unable to print","key":"printer_failure_no_print"},{"code":1840,"description":"Unknow vend ticket status","key":"ticket_status"},{"code":1850,"description":"Reply timeout","key":"reply_timeout"},{"code":1860,"description":"Incompatible denomination","key":"incompatible_denomination"},{"code":1870,"description":"Ticket over limit","key":"ticket_over_limit"},{"code":1880,"description":"Ticket over credit limit","key":"ticket_over_credit_limit"},{"code":1890,"description":"Validator failure","key":"validator_failure"},{"code":1900,"description":"Vend request denied by DPU","key":"vend_request_denied"},{"code":1910,"description":"Val # request denied by DPU","key":"val_request_denied"},{"code":1920,"description":"ROM warning, version change","key":"rom_warning_version"},{"code":1930,"description":"Send Configuration","key":"configuration_send"},{"code":1940,"description":"Sentinel On, Memory OK","key":"sentinel_on"},{"code":1950,"description":"Serial Communications Down","key":"serial_comm_down"},{"code":1960,"description":"Serial Communications Up","key":"serial_comm_up"},{"code":1970,"description":"Soft Drop In","key":"soft_drop_in"},{"code":1980,"description":"Soft Drop Out","key":"soft_drop_out"},{"code":1990,"description":"Stacker Installed","key":"stacker_installed"},{"code":2000,"description":"Stacker Removed","key":"stacker_removed"},{"code":2010,"description":"Tilt: Hopper","key":"tilt_hopper"},{"code":2020,"description":"Tilt: Printer hardware failure","key":"tilt_printer_hardware_failure"},{"code":2030,"description":"Top Award","key":"top_award"},{"code":2040,"description":"Unknown","key":"unknown"},{"code":2050,"description":"Hopper Empty","key":"hopper_empty"}]
|
@@ -0,0 +1,312 @@
|
|
1
|
+
module A4Tools
|
2
|
+
class BuiltinCommand
|
3
|
+
attr_accessor :input, :error, :output, :args, :shell, :params
|
4
|
+
attr_reader :status, :result
|
5
|
+
|
6
|
+
class << self
|
7
|
+
attr_reader :category_text, :description_text, :usage_text, :help_text, :validator, :tab_completors, :run_block, :opts, :is_user_defined
|
8
|
+
attr_accessor :sha1, :filepath, :command
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@description_text = ""
|
12
|
+
@usage_text = ""
|
13
|
+
@help_text = ""
|
14
|
+
@category_text = "General"
|
15
|
+
@validator = proc { true }
|
16
|
+
@tab_completors = { default: proc { [] } }
|
17
|
+
@run_block = proc { "" }
|
18
|
+
@opts = []
|
19
|
+
end
|
20
|
+
|
21
|
+
## Command category.
|
22
|
+
## Used to sort items in help.
|
23
|
+
def category(category)
|
24
|
+
@category_text = category
|
25
|
+
end
|
26
|
+
|
27
|
+
## Summary of command
|
28
|
+
## One-line description of command for use in help
|
29
|
+
def description(description)
|
30
|
+
@description_text = description
|
31
|
+
end
|
32
|
+
|
33
|
+
## Command line usage
|
34
|
+
## Added to end of usage argment. e.g. return "arg1 arg2" to get a string like "usage: my_command arg1 arg2"
|
35
|
+
def usage(usage)
|
36
|
+
@usage_text = usage
|
37
|
+
end
|
38
|
+
|
39
|
+
## Help text
|
40
|
+
## Supplemental help added to end of --help.
|
41
|
+
def help(help)
|
42
|
+
@help_text = help
|
43
|
+
end
|
44
|
+
|
45
|
+
## Command line validation
|
46
|
+
## Return true to indicate command line is valid.
|
47
|
+
## Return false to generate error and return usage help.
|
48
|
+
## Return a string to generate error and display the returned string.
|
49
|
+
def validate(&validator)
|
50
|
+
@validator = validator
|
51
|
+
end
|
52
|
+
|
53
|
+
## Tab completion
|
54
|
+
## Return an array of possible values. You are not responsible for filtering these values for those matching the current argument.
|
55
|
+
## If an index is supplied, the block will only be invoked for that argument.
|
56
|
+
def tab(index=nil, &tab_completor)
|
57
|
+
if index.nil? then
|
58
|
+
@tab_completors[:default] = tab_completor
|
59
|
+
else
|
60
|
+
@tab_completors[index] = tab_completor
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
## Defines a command line argument. Identical syntax to Trollop.
|
65
|
+
## opt :name, "Supplies a name", :type => :string
|
66
|
+
def opt(key, description, params={})
|
67
|
+
@opts.push({ key:key, description:description, params:params })
|
68
|
+
end
|
69
|
+
|
70
|
+
## Actual code block to execute when the command is run
|
71
|
+
def run(&block)
|
72
|
+
@run_block = block
|
73
|
+
end
|
74
|
+
|
75
|
+
###
|
76
|
+
# Load from a file (don't call this directly)
|
77
|
+
def load_command(file, userdefined=false)
|
78
|
+
cmdname = File.basename(file.to_s, ".rb")
|
79
|
+
subclass = Class.new(A4Tools::BuiltinCommand) {}
|
80
|
+
contents = IO.read(file)
|
81
|
+
|
82
|
+
subclass.setup
|
83
|
+
subclass.command = cmdname
|
84
|
+
subclass.filepath = file
|
85
|
+
subclass.sha1 = Digest::SHA1.hexdigest contents
|
86
|
+
subclass.user_defined if userdefined
|
87
|
+
subclass.class_eval( contents, file )
|
88
|
+
subclass
|
89
|
+
end
|
90
|
+
|
91
|
+
# Identify a command as user-defined (called automatically)
|
92
|
+
def user_defined
|
93
|
+
@is_user_defined = true
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
####
|
99
|
+
# convenience methods you might want to be aware of
|
100
|
+
|
101
|
+
def usher
|
102
|
+
if @shell.shared[:usher].nil? then
|
103
|
+
@shell.shared[:usher] = A4Tools::UsherClient.new()
|
104
|
+
end
|
105
|
+
@shell.shared[:usher]
|
106
|
+
end
|
107
|
+
|
108
|
+
def usherm
|
109
|
+
@shell.client(:usherm)
|
110
|
+
end
|
111
|
+
|
112
|
+
def client
|
113
|
+
@shell.active_client
|
114
|
+
end
|
115
|
+
|
116
|
+
def deployment
|
117
|
+
@shell.client(:deployment)
|
118
|
+
end
|
119
|
+
|
120
|
+
def qa
|
121
|
+
@shell.client(:qa)
|
122
|
+
end
|
123
|
+
|
124
|
+
def kaiconfig
|
125
|
+
@shell.client(:kaiconfig)
|
126
|
+
end
|
127
|
+
|
128
|
+
def show_error(msg)
|
129
|
+
@error.write "!!".style(:error) + " #{args[0].style(:command)}: #{msg}\n"
|
130
|
+
return "", 1
|
131
|
+
end
|
132
|
+
|
133
|
+
def show_exception(exception)
|
134
|
+
@error.write "\n"
|
135
|
+
@error.write "!!".style(:error) + "#{command} crashed: #{exception.class.to_s} #{exception.message}\n"
|
136
|
+
@error.write "Stack trace: #{exception.backtrace.map {|l| " #{l}\n"}.join}"
|
137
|
+
""
|
138
|
+
end
|
139
|
+
|
140
|
+
####
|
141
|
+
# don't override these unless you really know what you're doing and have a good reason
|
142
|
+
|
143
|
+
def initialize(shell, input=nil, output=nil, error=nil)
|
144
|
+
@shell = shell
|
145
|
+
@parser = parser
|
146
|
+
|
147
|
+
@input = input || StandardInput.new
|
148
|
+
@output = output || StandardOutput.new
|
149
|
+
@error = error || StandardOutput.new
|
150
|
+
end
|
151
|
+
|
152
|
+
def category
|
153
|
+
self.class.category_text
|
154
|
+
end
|
155
|
+
|
156
|
+
def command
|
157
|
+
self.class.command
|
158
|
+
end
|
159
|
+
|
160
|
+
def description
|
161
|
+
self.class.description_text
|
162
|
+
end
|
163
|
+
|
164
|
+
def usage
|
165
|
+
self.class.usage_text
|
166
|
+
end
|
167
|
+
|
168
|
+
def help
|
169
|
+
self.class.help_text
|
170
|
+
end
|
171
|
+
|
172
|
+
def validate
|
173
|
+
block_call(&self.class.validator)
|
174
|
+
end
|
175
|
+
|
176
|
+
def user_defined?
|
177
|
+
self.class.is_user_defined
|
178
|
+
end
|
179
|
+
|
180
|
+
def block_call(&block)
|
181
|
+
self.class.send(:define_method, :__block_call, &block)
|
182
|
+
self.class.send(:instance_method, :__block_call).bind(self).call
|
183
|
+
end
|
184
|
+
|
185
|
+
def sym_for_param(param)
|
186
|
+
param[2..-1].to_sym rescue ""
|
187
|
+
end
|
188
|
+
|
189
|
+
def tab
|
190
|
+
# only include --command-arguments if we already have a dash
|
191
|
+
param_mix = []
|
192
|
+
param_mix = all_opts.map { |opt| "--" + opt[:key].to_s.gsub("_","-") } if @realargs.last[0] == '-'
|
193
|
+
|
194
|
+
key = if @realargs.length >= 2 and self.class.tab_completors.has_key? sym_for_param(@realargs[-2])
|
195
|
+
sym_for_param(@realargs[-2])
|
196
|
+
elsif self.class.tab_completors.has_key?(args.length-2)
|
197
|
+
args.length - 2
|
198
|
+
else
|
199
|
+
:default
|
200
|
+
end
|
201
|
+
|
202
|
+
param_mix + block_call(&(self.class.tab_completors[key]))
|
203
|
+
end
|
204
|
+
|
205
|
+
def perform
|
206
|
+
return [educate, 1] if params[:help]
|
207
|
+
|
208
|
+
errmsg = validate
|
209
|
+
return show_error(errmsg) if errmsg.is_a? String
|
210
|
+
return show_error(usage_msg) if errmsg.nil? or errmsg == false
|
211
|
+
|
212
|
+
begin
|
213
|
+
block_call(&self.class.run_block)
|
214
|
+
rescue Interrupt
|
215
|
+
@error.write "Killed\n"
|
216
|
+
return ["", 1]
|
217
|
+
rescue SystemExit # allow commands to call exit
|
218
|
+
raise
|
219
|
+
rescue Exception => exception
|
220
|
+
return show_exception(exception)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def execute(input, output, error, args)
|
225
|
+
@input = input
|
226
|
+
@output = output
|
227
|
+
@error = error
|
228
|
+
parse(args)
|
229
|
+
|
230
|
+
r = perform
|
231
|
+
r = [r, 0] unless r.is_a? Array
|
232
|
+
@result = r[0] || ""
|
233
|
+
@status = r[1]
|
234
|
+
|
235
|
+
txt = @result.to_s
|
236
|
+
unless txt.empty? then
|
237
|
+
txt += "\n" unless txt.end_with? "\n"
|
238
|
+
@output.write txt
|
239
|
+
end
|
240
|
+
|
241
|
+
@status
|
242
|
+
end
|
243
|
+
|
244
|
+
def global_opts
|
245
|
+
[ { key: :help, description:"Show help", params:{} } ]
|
246
|
+
end
|
247
|
+
|
248
|
+
def all_opts
|
249
|
+
global_opts + self.class.opts
|
250
|
+
end
|
251
|
+
|
252
|
+
def parser
|
253
|
+
Trollop::Parser.new(all_opts) do |opts|
|
254
|
+
opts.each do |option|
|
255
|
+
opt option[:key], option[:description], option[:params]
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def parse(args)
|
261
|
+
@realargs = Array.new(args)
|
262
|
+
|
263
|
+
begin
|
264
|
+
@params = @parser.parse(args)
|
265
|
+
rescue Trollop::HelpNeeded
|
266
|
+
@params = {help:true}
|
267
|
+
rescue Trollop::VersionNeeded
|
268
|
+
@params = {help:true}
|
269
|
+
rescue Trollop::CommandlineError
|
270
|
+
@params = {help:true}
|
271
|
+
end
|
272
|
+
@args = @parser.leftovers
|
273
|
+
@args = args if @args.nil? or @args.empty?
|
274
|
+
end
|
275
|
+
|
276
|
+
def usage_msg
|
277
|
+
u = usage
|
278
|
+
if usage.is_a? Array then
|
279
|
+
"usage:\n" + (u.map { |line| "\t#{command} [flags] #{line}" }).join("\n")
|
280
|
+
else
|
281
|
+
"usage: #{command} [flags] #{usage}"
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
def educate
|
286
|
+
buffer = PipeBuffer.new
|
287
|
+
@parser.educate buffer
|
288
|
+
intro_line = "#{command.style(:command)}: #{description}"
|
289
|
+
userdef_line = user_defined? ? "User defined".style(:userdefined) : nil
|
290
|
+
|
291
|
+
top_section = [intro_line, category.style(:category), userdef_line ].compact.join("\n")
|
292
|
+
|
293
|
+
[top_section+"\n", usage_msg+"\n", buffer.buffer, help].compact.join("\n")
|
294
|
+
end
|
295
|
+
|
296
|
+
def print(s="")
|
297
|
+
@output.print s
|
298
|
+
end
|
299
|
+
|
300
|
+
def puts(s="")
|
301
|
+
@output.puts s
|
302
|
+
end
|
303
|
+
|
304
|
+
def console_puts(s)
|
305
|
+
$stdout.puts s.gsub("\n","\r\n")
|
306
|
+
end
|
307
|
+
|
308
|
+
def console_print(s)
|
309
|
+
$stdout.print s.gsub("\n","\r\n")
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|