a4tools 1.2.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|