a4tools 1.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.bundle/install.log +38 -0
  3. data/.gitignore +2 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.lock +38 -0
  6. data/a4tools.gemspec +38 -0
  7. data/bin/deploy_latest_clients +32 -0
  8. data/bin/devsite_config_server +48 -0
  9. data/bin/netshell +23 -0
  10. data/bin/update_server +101 -0
  11. data/bin/usher +54 -0
  12. data/lib/a4tools.rb +61 -0
  13. data/lib/a4tools/version.rb +3 -0
  14. data/lib/acres_client.rb +376 -0
  15. data/lib/clients/caching_client.rb +151 -0
  16. data/lib/clients/deployment_client.rb +53 -0
  17. data/lib/clients/kai_config_client.rb +39 -0
  18. data/lib/clients/usher_client.rb +72 -0
  19. data/lib/clients/usher_mgmt_client.rb +201 -0
  20. data/lib/event_manager.rb +24 -0
  21. data/lib/events.json +1 -0
  22. data/lib/net_shell/builtin_command.rb +312 -0
  23. data/lib/net_shell/builtin_commands/build.rb +251 -0
  24. data/lib/net_shell/builtin_commands/cd.rb +12 -0
  25. data/lib/net_shell/builtin_commands/connect.rb +122 -0
  26. data/lib/net_shell/builtin_commands/deploy.rb +280 -0
  27. data/lib/net_shell/builtin_commands/disconnect.rb +15 -0
  28. data/lib/net_shell/builtin_commands/excerpt.rb +97 -0
  29. data/lib/net_shell/builtin_commands/exit.rb +7 -0
  30. data/lib/net_shell/builtin_commands/get.rb +38 -0
  31. data/lib/net_shell/builtin_commands/help.rb +40 -0
  32. data/lib/net_shell/builtin_commands/host.rb +126 -0
  33. data/lib/net_shell/builtin_commands/inject.rb +42 -0
  34. data/lib/net_shell/builtin_commands/jsoncache.rb +80 -0
  35. data/lib/net_shell/builtin_commands/kai_event.rb +151 -0
  36. data/lib/net_shell/builtin_commands/persist.rb +24 -0
  37. data/lib/net_shell/builtin_commands/pwd.rb +6 -0
  38. data/lib/net_shell/builtin_commands/recap.rb +188 -0
  39. data/lib/net_shell/builtin_commands/references.rb +63 -0
  40. data/lib/net_shell/builtin_commands/select.rb +36 -0
  41. data/lib/net_shell/builtin_commands/send.rb +74 -0
  42. data/lib/net_shell/builtin_commands/set.rb +29 -0
  43. data/lib/net_shell/builtin_commands/show.rb +183 -0
  44. data/lib/net_shell/builtin_commands/site.rb +122 -0
  45. data/lib/net_shell/builtin_commands/ssh.rb +62 -0
  46. data/lib/net_shell/builtin_commands/talk.rb +90 -0
  47. data/lib/net_shell/builtin_commands/translate.rb +45 -0
  48. data/lib/net_shell/builtin_commands/unset.rb +14 -0
  49. data/lib/net_shell/builtin_commands/usher.rb +55 -0
  50. data/lib/net_shell/builtin_commands/usher_device.rb +39 -0
  51. data/lib/net_shell/builtin_commands/usher_site.rb +245 -0
  52. data/lib/net_shell/builtin_commands/usherm_connect.rb +21 -0
  53. data/lib/net_shell/colors.rb +149 -0
  54. data/lib/net_shell/command.rb +97 -0
  55. data/lib/net_shell/io.rb +132 -0
  56. data/lib/net_shell/net_shell.rb +396 -0
  57. data/lib/net_shell/prompt.rb +335 -0
  58. data/lib/object_builder/definitions/app_info_for_script.rb +83 -0
  59. data/lib/object_builder/definitions/connection_request.rb +28 -0
  60. data/lib/object_builder/definitions/device_info_for_system.rb +37 -0
  61. data/lib/object_builder/object_builder.rb +145 -0
  62. data/lib/talk.json +1 -0
  63. data/lib/talk_consumer.rb +235 -0
  64. 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
@@ -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