soapy_bing 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/Gemfile +1 -0
  4. data/README.md +18 -18
  5. data/Rakefile +1 -0
  6. data/lib/soapy_bing.rb +5 -1
  7. data/lib/soapy_bing/account.rb +1 -0
  8. data/lib/soapy_bing/accounts.rb +13 -17
  9. data/lib/soapy_bing/ads.rb +18 -41
  10. data/lib/soapy_bing/ads/campaign_performance_report.rb +49 -0
  11. data/lib/soapy_bing/ads/campaigns.rb +106 -0
  12. data/lib/soapy_bing/ads/parsers/bulk_csv_parser.rb +34 -0
  13. data/lib/soapy_bing/ads/parsers/report_csv_parser.rb +45 -0
  14. data/lib/soapy_bing/ads/report.rb +93 -0
  15. data/lib/soapy_bing/campaign_management.rb +21 -0
  16. data/lib/soapy_bing/country_codes.rb +17 -0
  17. data/lib/soapy_bing/country_codes.yml +727 -0
  18. data/lib/soapy_bing/customer.rb +1 -0
  19. data/lib/soapy_bing/helpers.rb +1 -1
  20. data/lib/soapy_bing/helpers/zip_downloader.rb +1 -0
  21. data/lib/soapy_bing/oauth_credentials.rb +1 -0
  22. data/lib/soapy_bing/param_guard.rb +1 -0
  23. data/lib/soapy_bing/service.rb +69 -0
  24. data/lib/soapy_bing/service_operation.rb +62 -0
  25. data/lib/soapy_bing/version.rb +2 -1
  26. data/lib/soapy_bing/wsdl/ad_insight.wsdl +1 -0
  27. data/lib/soapy_bing/wsdl/bulk.wsdl +1 -0
  28. data/lib/soapy_bing/wsdl/campaign_management.wsdl +1 -0
  29. data/lib/soapy_bing/wsdl/customer_billing.wsdl +1 -0
  30. data/lib/soapy_bing/wsdl/customer_management.wsdl +1 -0
  31. data/lib/soapy_bing/wsdl/reporting.wsdl +1 -0
  32. data/lib/tasks/console.rake +1 -0
  33. data/lib/tasks/coverage.rake +1 -0
  34. data/lib/tasks/spec.rake +1 -0
  35. data/lib/tasks/upate_wsdl_files.rake +23 -0
  36. data/lib/tasks/update_country_codes.rake +24 -0
  37. data/soapy_bing.gemspec +2 -1
  38. data/spec/fixtures/ads/campaign_performance_report.csv +37 -0
  39. data/spec/fixtures/ads/campaign_performance_report.json +170 -0
  40. data/spec/fixtures/ads/campaigns_by_account_id.csv +7 -0
  41. data/spec/fixtures/{bulk/campaigns.json → ads/campaigns_by_account_id.json} +496 -240
  42. data/spec/fixtures/ads/campaigns_by_campaign_ids.csv +5 -0
  43. data/spec/fixtures/ads/campaigns_by_campaign_ids.json +910 -0
  44. data/spec/fixtures/vcr_cassettes/SoapyBing_Accounts/_list/returns_a_list_of_SoapyBing_Account_objects.yml +27 -27
  45. data/spec/fixtures/vcr_cassettes/SoapyBing_Ads/_campaigns/by_account_id/returns_parsed_rows.yml +301 -0
  46. data/spec/fixtures/vcr_cassettes/SoapyBing_Ads/_campaigns/by_campaign_ids/returns_parsed_rows.yml +300 -0
  47. data/spec/fixtures/vcr_cassettes/SoapyBing_CampaignManagement/_get_geo_locations/returns_a_list_of_geo_locations_hashes.yml +154 -0
  48. data/spec/fixtures/vcr_cassettes/campaign_performance_report/with_pending_status.yml +65 -94
  49. data/spec/fixtures/vcr_cassettes/campaign_performance_report/with_successful_empty_response.yml +511 -0
  50. data/spec/fixtures/vcr_cassettes/campaign_performance_report/with_successful_response.yml +384 -0
  51. data/spec/integration/soapy_bing/accounts_spec.rb +1 -0
  52. data/spec/integration/soapy_bing/ads_campaigns_spec.rb +85 -0
  53. data/spec/integration/soapy_bing/campaign_management_spec.rb +22 -0
  54. data/spec/integration/soapy_bing/oauth_credentials_spec.rb +1 -0
  55. data/spec/simplecov_setup.rb +1 -0
  56. data/spec/soapy_bing/account_spec.rb +6 -2
  57. data/spec/soapy_bing/accounts_spec.rb +47 -0
  58. data/spec/soapy_bing/ads/campaign_performance_report_spec.rb +79 -0
  59. data/spec/soapy_bing/ads/campaigns_spec.rb +99 -0
  60. data/spec/soapy_bing/ads/{bulk/parsers/csv_parser_spec.rb → parsers/bulk_csv_parser_spec.rb} +5 -4
  61. data/spec/soapy_bing/ads/{reports/parsers/csv_parser_spec.rb → parsers/report_csv_parser_spec.rb} +6 -4
  62. data/spec/soapy_bing/country_codes_spec.rb +39 -0
  63. data/spec/soapy_bing/helpers/zip_downloader_spec.rb +2 -0
  64. data/spec/soapy_bing/oauth_credentials_spec.rb +6 -2
  65. data/spec/soapy_bing/param_guard_spec.rb +2 -0
  66. data/spec/soapy_bing/service_spec.rb +56 -0
  67. data/spec/spec_helper.rb +1 -0
  68. data/spec/support/dotenv.rb +1 -0
  69. data/spec/support/vcr.rb +75 -6
  70. metadata +74 -118
  71. data/lib/soapy_bing/ads/bulk.rb +0 -3
  72. data/lib/soapy_bing/ads/bulk/campaigns.rb +0 -65
  73. data/lib/soapy_bing/ads/bulk/parsers.rb +0 -2
  74. data/lib/soapy_bing/ads/bulk/parsers/csv_parser.rb +0 -35
  75. data/lib/soapy_bing/ads/reports.rb +0 -4
  76. data/lib/soapy_bing/ads/reports/base.rb +0 -74
  77. data/lib/soapy_bing/ads/reports/campaign_performance_report.rb +0 -24
  78. data/lib/soapy_bing/ads/reports/parsers.rb +0 -2
  79. data/lib/soapy_bing/ads/reports/parsers/csv_parser.rb +0 -46
  80. data/lib/soapy_bing/helpers/class_name.rb +0 -10
  81. data/lib/soapy_bing/soap.rb +0 -4
  82. data/lib/soapy_bing/soap/request.rb +0 -10
  83. data/lib/soapy_bing/soap/request/base.rb +0 -38
  84. data/lib/soapy_bing/soap/request/download_campaigns_by_account_ids_request.rb +0 -17
  85. data/lib/soapy_bing/soap/request/get_accounts_info_request.rb +0 -17
  86. data/lib/soapy_bing/soap/request/get_ad_groups_by_campaign_id_request.rb +0 -17
  87. data/lib/soapy_bing/soap/request/get_ads_by_ad_group_id_request.rb +0 -17
  88. data/lib/soapy_bing/soap/request/get_bulk_download_status_request.rb +0 -17
  89. data/lib/soapy_bing/soap/request/get_targets_by_campaign_ids_request.rb +0 -17
  90. data/lib/soapy_bing/soap/request/poll_generate_report_request.rb +0 -34
  91. data/lib/soapy_bing/soap/request/submit_generate_report_request.rb +0 -17
  92. data/lib/soapy_bing/soap/response.rb +0 -14
  93. data/lib/soapy_bing/soap/response/base.rb +0 -17
  94. data/lib/soapy_bing/soap/response/download_campaigns_by_account_ids_response.rb +0 -12
  95. data/lib/soapy_bing/soap/response/get_accounts_info_response.rb +0 -12
  96. data/lib/soapy_bing/soap/response/get_ad_groups_by_campaign_id_response.rb +0 -12
  97. data/lib/soapy_bing/soap/response/get_ads_by_ad_group_id_response.rb +0 -12
  98. data/lib/soapy_bing/soap/response/get_bulk_download_status_response.rb +0 -17
  99. data/lib/soapy_bing/soap/response/get_targets_by_campaign_ids_response.rb +0 -12
  100. data/lib/soapy_bing/soap/response/payload.rb +0 -28
  101. data/lib/soapy_bing/soap/response/poll_generate_report_response.rb +0 -14
  102. data/lib/soapy_bing/soap/response/report_status.rb +0 -34
  103. data/lib/soapy_bing/soap/response/submit_generate_report_response.rb +0 -12
  104. data/lib/soapy_bing/soap/template_renderer.rb +0 -22
  105. data/lib/soapy_bing/soap/templates/download_campaigns_by_account_ids.xml.erb +0 -22
  106. data/lib/soapy_bing/soap/templates/get_accounts_info.xml.erb +0 -12
  107. data/lib/soapy_bing/soap/templates/get_ad_groups_by_campaign_id.xml.erb +0 -15
  108. data/lib/soapy_bing/soap/templates/get_ads_by_ad_group_id.xml.erb +0 -15
  109. data/lib/soapy_bing/soap/templates/get_bulk_download_status.xml.erb +0 -15
  110. data/lib/soapy_bing/soap/templates/get_targets_by_campaign_ids.xml.erb +0 -20
  111. data/lib/soapy_bing/soap/templates/poll_generate_report.xml.erb +0 -18
  112. data/lib/soapy_bing/soap/templates/submit_generate_report.xml.erb +0 -46
  113. data/spec/fixtures/bulk/campaigns.csv +0 -8
  114. data/spec/fixtures/get_ad_groups_by_campaign_id.json +0 -587
  115. data/spec/fixtures/get_ads_by_ad_group_id.json +0 -218
  116. data/spec/fixtures/get_targets_by_campaign_ids.json +0 -81
  117. data/spec/fixtures/reports/campaign_performance_report.csv +0 -37
  118. data/spec/fixtures/reports/campaign_performance_report.json +0 -146
  119. data/spec/fixtures/soap_templates/simple.xml.erb +0 -2
  120. data/spec/fixtures/vcr_cassettes/SoapyBing_Ads/_get_ad_groups_by_campaign_id/1_1_1.yml +0 -150
  121. data/spec/fixtures/vcr_cassettes/SoapyBing_Ads/_get_ads_by_ad_group_id/1_2_1.yml +0 -141
  122. data/spec/fixtures/vcr_cassettes/SoapyBing_Ads/_get_targets_by_campaign_ids/1_3_1.yml +0 -111
  123. data/spec/fixtures/vcr_cassettes/SoapyBing_Ads_Bulk_Campaigns/_result_file_url/returns_result_file_url.yml +0 -216
  124. data/spec/fixtures/vcr_cassettes/campaign_performance_report/with_successful_status.yml +0 -284
  125. data/spec/integration/soapy_bing/ads/bulk/campaigns_spec.rb +0 -35
  126. data/spec/integration/soapy_bing/ads/reports/campaign_performance_report_spec.rb +0 -40
  127. data/spec/integration/soapy_bing/ads_spec.rb +0 -32
  128. data/spec/soapy_bing/ads/reports/campaign_performance_report_spec.rb +0 -42
  129. data/spec/soapy_bing/ads_spec.rb +0 -33
  130. data/spec/soapy_bing/helpers/class_name_spec.rb +0 -15
  131. data/spec/soapy_bing/soap/request/base_spec.rb +0 -55
  132. data/spec/soapy_bing/soap/request/poll_generate_report_request_spec.rb +0 -60
  133. data/spec/soapy_bing/soap/response/base_spec.rb +0 -13
  134. data/spec/soapy_bing/soap/response/get_bulk_download_status_response_spec.rb +0 -60
  135. data/spec/soapy_bing/soap/response/payload_spec.rb +0 -48
  136. data/spec/soapy_bing/soap/response/poll_generate_report_response_spec.rb +0 -26
  137. data/spec/soapy_bing/soap/response/report_status_spec.rb +0 -92
  138. data/spec/soapy_bing/soap/response/submit_generate_report_response_spec.rb +0 -20
  139. data/spec/soapy_bing/soap/template_renderer_spec.rb +0 -25
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ostruct'
4
+ require 'soapy_bing/ads/parsers/report_csv_parser'
5
+
6
+ module SoapyBing
7
+ class Ads
8
+ NotCompleted = Class.new(StandardError)
9
+ StatusFailed = Class.new(StandardError)
10
+
11
+ class Report
12
+ DEFAULT_REPORT_SETTINGS = {
13
+ format: 'Csv',
14
+ language: 'English',
15
+ name: 'MyReport',
16
+ aggregation: 'Hourly',
17
+ columns: %w[TimePeriod CampaignName Impressions Clicks Spend CampaignId]
18
+ }.freeze
19
+
20
+ DEFAULT_POLLING_SETTINGS = {
21
+ tries: 20,
22
+ sleep: ->(n) { n < 7 ? 2**n : 120 }
23
+ }.freeze
24
+
25
+ attr_reader :service, :settings, :polling_settings, :status
26
+
27
+ def initialize(options)
28
+ @service = Service.reporting(options.fetch(:service_options))
29
+ @settings = OpenStruct.new(DEFAULT_REPORT_SETTINGS.merge(options.fetch(:settings, {})))
30
+ @polling_settings = DEFAULT_POLLING_SETTINGS.merge(options.fetch(:polling_settings, {}))
31
+ end
32
+
33
+ def rows
34
+ @rows ||= download_and_parse_rows
35
+ end
36
+
37
+ private
38
+
39
+ def download_and_parse_rows
40
+ # https://msdn.microsoft.com/en-us/library/bing-ads-api-migration-guide(v=msads.100).aspx#Report-Download-URL-and-Empty-Reports
41
+ return [] unless download_url
42
+ Parsers::ReportCsvParser.new(Helpers::ZipDownloader.new(download_url).read).rows
43
+ end
44
+
45
+ def download_url
46
+ @download_url ||= begin
47
+ wait_status_complete
48
+ status[:report_download_url]
49
+ end
50
+ end
51
+
52
+ def fetch_status
53
+ response = service.poll_generate_report(report_request_id: report_request_id)
54
+ if response[:report_request_status][:status] == 'Error'
55
+ raise StatusFailed, response[:errors].to_s
56
+ end
57
+ @status = response[:report_request_status].slice(:status, :report_download_url)
58
+ end
59
+
60
+ def wait_status_complete
61
+ Retryable.retryable(polling_settings.merge(on: NotCompleted)) do
62
+ fetch_status
63
+ raise NotCompleted if status[:status] != 'Success'
64
+ end
65
+ end
66
+
67
+ def report_request_id
68
+ @report_request_id ||= submit_generate_report
69
+ end
70
+
71
+ def submit_generate_report
72
+ response = service.submit_generate_report do |namespace_identifier|
73
+ {
74
+ report_request: {
75
+ '@xsi:type' => "#{namespace_identifier}:#{request_type}"
76
+ }.merge(base_message).merge(message)
77
+ }
78
+ end
79
+ response[:report_request_id]
80
+ end
81
+
82
+ def base_message
83
+ {
84
+ # https://msdn.microsoft.com/en-us/library/bing-ads-reporting-campaignperformancereportrequest.aspx#Anchor_2
85
+ format: settings.format,
86
+ language: settings.language,
87
+ report_name: settings.name,
88
+ return_only_completed_data: false
89
+ }
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SoapyBing
4
+ class CampaignManagement
5
+ attr_reader :service
6
+
7
+ def initialize(*args)
8
+ @service = Service.campaign_management(*args)
9
+ end
10
+
11
+ def get_geo_locations # rubocop:disable Style/AccessorMethodName
12
+ response = service.get_geo_locations_file_url(
13
+ version: '1.0',
14
+ language_locale: 'en'
15
+ )
16
+ csv = HTTParty.get(response[:file_url]).body
17
+ header, *body = CSV.parse(csv)
18
+ body.map { |row| header.zip(row).to_h }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yaml'
4
+
5
+ module SoapyBing
6
+ class CountryCodes
7
+ YML_FILE_PATH = File.join(__dir__, 'country_codes.yml').freeze
8
+
9
+ def initialize
10
+ @country_codes = YAML.safe_load(File.read(YML_FILE_PATH))
11
+ end
12
+
13
+ def code(id)
14
+ @country_codes.fetch(id.to_s)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,727 @@
1
+ ---
2
+ '1': AL
3
+ '2': AQ
4
+ '3': DZ
5
+ '4': AS
6
+ '5': AD
7
+ '6': AO
8
+ '7': AG
9
+ '8': AR
10
+ '9': AU
11
+ '10': AT
12
+ '11': BS
13
+ '12': BD
14
+ '13': BB
15
+ '14': BE
16
+ '15': BM
17
+ '16': BT
18
+ '17': BO
19
+ '18': BW
20
+ '20': BR
21
+ '21': BZ
22
+ '23': SB
23
+ '24': VG
24
+ '25': BN
25
+ '26': BG
26
+ '27': MM
27
+ '28': BI
28
+ '29': BY
29
+ '30': KH
30
+ '31': CM
31
+ '32': CA
32
+ '33': CV
33
+ '34': KY
34
+ '35': CF
35
+ '36': LK
36
+ '37': TD
37
+ '38': CL
38
+ '39': CN
39
+ '40': TW
40
+ '41': CX
41
+ '42': CC
42
+ '43': CO
43
+ '44': YT
44
+ '45': CG
45
+ '46': CD
46
+ '47': CK
47
+ '48': CR
48
+ '49': HR
49
+ '51': CZ
50
+ '52': BJ
51
+ '53': DK
52
+ '54': DM
53
+ '55': DO
54
+ '56': EC
55
+ '57': SV
56
+ '58': GQ
57
+ '59': ET
58
+ '60': ER
59
+ '61': EE
60
+ '62': FO
61
+ '63': FK
62
+ '65': FI
63
+ '66': FR
64
+ '67': GF
65
+ '68': PF
66
+ '69': DJ
67
+ '70': GA
68
+ '71': GM
69
+ '72': DE
70
+ '73': GH
71
+ '74': GI
72
+ '75': KI
73
+ '76': GR
74
+ '77': GL
75
+ '78': GD
76
+ '79': GP
77
+ '80': GU
78
+ '81': GT
79
+ '82': GN
80
+ '83': GY
81
+ '84': HT
82
+ '86': VA
83
+ '87': HN
84
+ '88': HU
85
+ '89': IS
86
+ '90': IN
87
+ '91': ID
88
+ '92': IE
89
+ '93': IT
90
+ '94': CI
91
+ '95': JM
92
+ '96': JP
93
+ '97': KZ
94
+ '98': KE
95
+ '100': KR
96
+ '101': KG
97
+ '102': LA
98
+ '103': LS
99
+ '104': LV
100
+ '105': LR
101
+ '106': LY
102
+ '107': LI
103
+ '108': LT
104
+ '109': LU
105
+ '110': MG
106
+ '111': MW
107
+ '112': MY
108
+ '113': MV
109
+ '114': ML
110
+ '115': MT
111
+ '116': MQ
112
+ '117': MR
113
+ '118': MU
114
+ '119': MX
115
+ '120': MC
116
+ '121': MN
117
+ '122': MD
118
+ '123': MS
119
+ '124': MA
120
+ '125': MZ
121
+ '126': NA
122
+ '127': NR
123
+ '128': NP
124
+ '129': NL
125
+ '130': AN
126
+ '131': AW
127
+ '132': NC
128
+ '133': VU
129
+ '134': NZ
130
+ '135': NI
131
+ '136': NE
132
+ '137': NG
133
+ '138': NF
134
+ '139': 'NO'
135
+ '140': MP
136
+ '141': FM
137
+ '142': MH
138
+ '143': PW
139
+ '144': PK
140
+ '145': PA
141
+ '146': PG
142
+ '147': PY
143
+ '148': PE
144
+ '149': PH
145
+ '150': PN
146
+ '151': PL
147
+ '152': PT
148
+ '153': GW
149
+ '154': PR
150
+ '155': RE
151
+ '156': RU
152
+ '157': RW
153
+ '158': AI
154
+ '159': SM
155
+ '160': ST
156
+ '161': SN
157
+ '162': SC
158
+ '163': SL
159
+ '164': SG
160
+ '165': SK
161
+ '166': VN
162
+ '167': SI
163
+ '168': ZA
164
+ '169': ZW
165
+ '170': ES
166
+ '172': SR
167
+ '173': SZ
168
+ '174': SE
169
+ '175': CH
170
+ '176': TJ
171
+ '177': TH
172
+ '178': TG
173
+ '179': TK
174
+ '180': TO
175
+ '181': TT
176
+ '182': TR
177
+ '183': TM
178
+ '184': TC
179
+ '185': UG
180
+ '186': MK
181
+ '187': EG
182
+ '188': GB
183
+ '189': TZ
184
+ '190': US
185
+ '191': BF
186
+ '192': UY
187
+ '193': UZ
188
+ '194': WF
189
+ '195': WS
190
+ '196': ZM
191
+ '198': BA
192
+ '199': FJ
193
+ '200': HK
194
+ '201': MO
195
+ '202': VE
196
+ '203': AZ
197
+ '204': BH
198
+ '205': AM
199
+ '206': CY
200
+ '208': GE
201
+ '210': IL
202
+ '211': JO
203
+ '212': KW
204
+ '213': LB
205
+ '214': OM
206
+ '215': QA
207
+ '216': SA
208
+ '218': AE
209
+ '219': YE
210
+ '220': PS
211
+ '221': AF
212
+ '222': TL
213
+ '223': NU
214
+ '224': RO
215
+ '225': SO
216
+ '226': KM
217
+ '227': TN
218
+ '228': IQ
219
+ '229': SH
220
+ '230': KN
221
+ '231': LC
222
+ '232': PM
223
+ '233': VC
224
+ '234': TV
225
+ '235': UA
226
+ '237': VI
227
+ '4993': RS
228
+ '4994': ME
229
+ '4054': AU-WA
230
+ '4053': AU-VI
231
+ '4049': AU-NT
232
+ '4141': AU-CT
233
+ '4052': AU-TS
234
+ '4050': AU-QL
235
+ '4048': AU-NS
236
+ '4051': AU-SA
237
+ '4065': CA-SK
238
+ '4059': CA-NS
239
+ '4062': CA-ON
240
+ '4058': CA-NB
241
+ '4061': CA-NU
242
+ '4066': CA-YT
243
+ '4064': CA-QC
244
+ '4057': CA-MB
245
+ '4060': CA-NT
246
+ '4056': CA-BC
247
+ '4055': CA-AB
248
+ '4140': CA-NL
249
+ '4063': CA-PE
250
+ '3319': CH-VD
251
+ '3304': CH-GE
252
+ '3313': CH-SH
253
+ '474': AT-9
254
+ '468': AT-3
255
+ '3310': CH-NW
256
+ '3311': CH-OW
257
+ '471': AT-6
258
+ '472': AT-7
259
+ '3302': CH-BS
260
+ '3320': CH-VS
261
+ '3307': CH-JU
262
+ '3303': CH-FR
263
+ '3316': CH-TG
264
+ '3305': CH-GL
265
+ '469': AT-4
266
+ '470': AT-5
267
+ '3297': CH-AG
268
+ '3300': CH-BE
269
+ '3299': CH-AR
270
+ '466': AT-1
271
+ '467': AT-2
272
+ '3308': CH-LU
273
+ '3314': CH-SO
274
+ '3322': CH-ZH
275
+ '3306': CH-GR
276
+ '3317': CH-TI
277
+ '3312': CH-SG
278
+ '473': AT-8
279
+ '615': BE-VWV
280
+ '3315': CH-SZ
281
+ '3301': CH-BL
282
+ '616': BE-WAL
283
+ '610': BE-VAN
284
+ '3318': CH-UR
285
+ '3321': CH-ZG
286
+ '619': BE-WLG
287
+ '621': BE-WNA
288
+ '3298': CH-AI
289
+ '3309': CH-NE
290
+ '1417': DE-TH
291
+ '1406': DE-HB
292
+ '1403': DE-BE
293
+ '1411': DE-NW
294
+ '1414': DE-SL
295
+ '1408': DE-HH
296
+ '1409': DE-MV
297
+ '1410': DE-NI
298
+ '1402': DE-BB
299
+ '1412': DE-RP
300
+ '1405': DE-BY
301
+ '1413': DE-SH
302
+ '1416': DE-ST
303
+ '1407': DE-HE
304
+ '1404': DE-BW
305
+ '1415': DE-SN
306
+ '71113': DK-082
307
+ '71114': DK-083
308
+ '71112': DK-084
309
+ '1054': DK-080
310
+ '71115': DK-085
311
+ '612': BE-VLG
312
+ '613': BE-VLI
313
+ '3229': ES-TO
314
+ '3186': ES-CS
315
+ '3169': ES-AL
316
+ '3178': ES-CA
317
+ '614': BE-VOV
318
+ '620': BE-WLX
319
+ '3226': ES-T
320
+ '3234': ES-Z
321
+ '609': BE-BRU
322
+ '611': BE-VBR
323
+ '3212': ES-O
324
+ '3191': ES-GC
325
+ '617': BE-WBR
326
+ '618': BE-WHT
327
+ '3231': ES-VA
328
+ '3223': ES-SG
329
+ '3195': ES-H
330
+ '3235': ES-ZA
331
+ '675': BR-MT
332
+ '683': BR-RO
333
+ '3206': ES-ML
334
+ '3172': ES-AV
335
+ '666': BR-AP
336
+ '668': BR-CE
337
+ '665': BR-AM
338
+ '685': BR-RS
339
+ '3215': ES-PM
340
+ '3175': ES-BI
341
+ '3192': ES-GE
342
+ '3198': ES-L
343
+ '674': BR-MS
344
+ '682': BR-RN
345
+ '3168': ES-AB
346
+ '3220': ES-S
347
+ '3196': ES-HU
348
+ '3177': ES-C
349
+ '3194': ES-GU
350
+ '3176': ES-BU
351
+ '671': BR-GO
352
+ '684': BR-RR
353
+ '3202': ES-LU
354
+ '3185': ES-CR
355
+ '3179': ES-CC
356
+ '3201': ES-LO
357
+ '3193': ES-GR
358
+ '3221': ES-SA
359
+ '3184': ES-CO
360
+ '3227': ES-TE
361
+ '688': BR-SP
362
+ '669': BR-DF
363
+ '3228': ES-TF
364
+ '3210': ES-NA
365
+ '3167': ES-A
366
+ '3173': ES-B
367
+ '680': BR-PR
368
+ '663': BR-AC
369
+ '3213': ES-OR
370
+ '3224': ES-SO
371
+ '686': BR-SC
372
+ '677': BR-PB
373
+ '3203': ES-M
374
+ '3230': ES-V
375
+ '3233': ES-VI
376
+ '3205': ES-MA
377
+ '689': BR-TO
378
+ '679': BR-PI
379
+ '3199': ES-LE
380
+ '3217': ES-PO
381
+ '681': BR-RJ
382
+ '678': BR-PE
383
+ '3197': ES-J
384
+ '3180': ES-CE
385
+ '672': BR-MA
386
+ '664': BR-AL
387
+ '3214': ES-P
388
+ '3174': ES-BA
389
+ '687': BR-SE
390
+ '670': BR-ES
391
+ '3188': ES-CU
392
+ '3222': ES-SE
393
+ '673': BR-MG
394
+ '676': BR-PA
395
+ '3208': ES-MU
396
+ '3225': ES-SS
397
+ '667': BR-BA
398
+ '902': CN-54
399
+ '899': CN-51
400
+ '890': CN-36
401
+ '885': CN-31
402
+ '882': CN-21
403
+ '2578': NO-11
404
+ '2581': NO-15
405
+ '879': CN-13
406
+ '905': CN-63
407
+ '2579': NO-12
408
+ '2572': NO-05
409
+ '888': CN-34
410
+ '896': CN-45
411
+ '2573': NO-06
412
+ '2570': NO-03
413
+ '893': CN-42
414
+ '901': CN-53
415
+ '2580': NO-14
416
+ '2569': NO-02
417
+ '887': CN-33
418
+ '904': CN-62
419
+ '881': CN-15
420
+ '878': CN-12
421
+ '2577': NO-10
422
+ '2583': NO-17
423
+ '2586': NO-20
424
+ '2584': NO-18
425
+ '2575': NO-08
426
+ '2571': NO-04
427
+ '889': CN-35
428
+ '886': CN-32
429
+ '2582': NO-16
430
+ '2574': NO-07
431
+ '897': CN-46
432
+ '895': CN-44
433
+ '2576': NO-09
434
+ '2568': NO-01
435
+ '2585': NO-19
436
+ '2499': NZ-HKB
437
+ '2508': NZ-TAS
438
+ '2505': NZ-OTA
439
+ '2511': NZ-WKO
440
+ '2510': NZ-WGN
441
+ '2509': NZ-TKI
442
+ '2501': NZ-MWT
443
+ '2500': NZ-MBH
444
+ '2497': NZ-CAN
445
+ '903': CN-61
446
+ '884': CN-23
447
+ '2495': NZ-AUK
448
+ '2498': NZ-GIS
449
+ '2507': NZ-STL
450
+ '2503': NZ-NSN
451
+ '898': CN-50
452
+ '906': CN-64
453
+ '2504': NZ-NTL
454
+ '2496': NZ-BOP
455
+ '880': CN-14
456
+ '894': CN-43
457
+ '2512': NZ-WTC
458
+ '3291': SE-T
459
+ '3280': SE-D
460
+ '3283': SE-G
461
+ '877': CN-11
462
+ '900': CN-52
463
+ '3290': SE-S
464
+ '3294': SE-X
465
+ '891': CN-37
466
+ '883': CN-22
467
+ '3282': SE-F
468
+ '3284': SE-H
469
+ '3296': SE-Z
470
+ '3293': SE-W
471
+ '892': CN-41
472
+ '907': CN-65
473
+ '3276': SE-AB
474
+ '3287': SE-M
475
+ '3286': SE-K
476
+ '3285': SE-I
477
+ '1285': FR-L
478
+ '1301': FR-V
479
+ '3288': SE-N
480
+ '3279': SE-C
481
+ '3278': SE-BD
482
+ '3292': SE-U
483
+ '3289': SE-O
484
+ '3277': SE-AC
485
+ '3295': SE-Y
486
+ '3281': SE-E
487
+ '4108': US-MT
488
+ '4105': US-MO
489
+ '4122': US-RI
490
+ '4114': US-NM
491
+ '4079': US-AK
492
+ '4113': US-NJ
493
+ '1293': FR-PM
494
+ '4116': US-NY
495
+ '4134': US-WV
496
+ '1284': FR-K
497
+ '1275': FR-D
498
+ '4085': US-CO
499
+ '4111': US-NE
500
+ '4094': US-ID
501
+ '4128': US-UT
502
+ '4088': US-DE
503
+ '4131': US-VT
504
+ '1292': FR-PF
505
+ '1286': FR-M
506
+ '4093': US-IA
507
+ '4102': US-ME
508
+ '4125': US-TN
509
+ '4098': US-KY
510
+ '1278': FR-G
511
+ '1295': FR-R
512
+ '4095': US-IL
513
+ '4112': US-NH
514
+ '1272': FR-A
515
+ '1298': FR-T
516
+ '4104': US-MN
517
+ '4096': US-IN
518
+ '4107': US-MS
519
+ '4081': US-AR
520
+ '4132': US-WA
521
+ '4097': US-KS
522
+ '1276': FR-E
523
+ '1289': FR-NC
524
+ '4123': US-SC
525
+ '4129': US-VA
526
+ '1282': FR-I
527
+ '1290': FR-O
528
+ '4103': US-MI
529
+ '4080': US-AL
530
+ '4115': US-NV
531
+ '4120': US-PA
532
+ '4089': US-FL
533
+ '4092': US-HI
534
+ '1273': FR-B
535
+ '1287': FR-MQ
536
+ '4086': US-CT
537
+ '4100': US-MA
538
+ '1281': FR-H
539
+ '1299': FR-TF
540
+ '4117': US-OH
541
+ '4087': US-DC
542
+ '4090': US-GA
543
+ '4126': US-TX
544
+ '4083': US-AZ
545
+ '4109': US-NC
546
+ '1274': FR-C
547
+ '1279': FR-GF
548
+ '4110': US-ND
549
+ '4119': US-OR
550
+ '1296': FR-RE
551
+ '1288': FR-N
552
+ '4133': US-WI
553
+ '4099': US-LA
554
+ '4135': US-WY
555
+ '4084': US-CA
556
+ '1302': FR-WF
557
+ '1297': FR-S
558
+ '4101': US-MD
559
+ '4124': US-SD
560
+ '1280': FR-GP
561
+ '1291': FR-P
562
+ '1294': FR-Q
563
+ '1283': FR-J
564
+ '1277': FR-F
565
+ '1300': FR-U
566
+ '1303': FR-YT
567
+ '4139': GB-WLS
568
+ '4078': GB-SCT
569
+ '4077': GB-NIR
570
+ '4076': GB-ENG
571
+ '1677': IN-WB
572
+ '1654': IN-DN
573
+ '71109': IN-JH
574
+ '4118': US-OK
575
+ '1659': IN-JK
576
+ '1668': IN-NL
577
+ '1676': IN-UP
578
+ '71111': IN-CG
579
+ '1662': IN-LD
580
+ '71110': IN-UK
581
+ '1670': IN-PB
582
+ '1661': IN-KL
583
+ '1653': IN-DL
584
+ '1648': IN-AR
585
+ '1656': IN-GJ
586
+ '1665': IN-MN
587
+ '1673': IN-SK
588
+ '1650': IN-BR
589
+ '1647': IN-AP
590
+ '1667': IN-MZ
591
+ '1664': IN-ML
592
+ '1657': IN-HP
593
+ '1674': IN-TN
594
+ '1658': IN-HR
595
+ '1655': IN-GA
596
+ '1663': IN-MH
597
+ '1672': IN-RJ
598
+ '1649': IN-AS
599
+ '1675': IN-TR
600
+ '1666': IN-MP
601
+ '1660': IN-KA
602
+ '1651': IN-CH
603
+ '1671': IN-PY
604
+ '1669': IN-OR
605
+ '1652': IN-DD
606
+ '1887': IT-RI
607
+ '1904': IT-TS
608
+ '1878': IT-PR
609
+ '1818': IT-AR
610
+ '1844': IT-FI
611
+ '1886': IT-RG
612
+ '71333': IT-MB
613
+ '1861': IT-MI
614
+ '1895': IT-SR
615
+ '1812': IT-AG
616
+ '1821': IT-BA
617
+ '1855': IT-LI
618
+ '1835': IT-CN
619
+ '1838': IT-CS
620
+ '1863': IT-MO
621
+ '1843': IT-FG
622
+ '1826': IT-BO
623
+ '1852': IT-KR
624
+ '1829': IT-BZ
625
+ '1898': IT-TA
626
+ '1875': IT-PI
627
+ '1881': IT-PV
628
+ '1832': IT-CE
629
+ '1841': IT-EN
630
+ '1907': IT-VA
631
+ '1815': IT-AO
632
+ '1864': IT-MS
633
+ '1824': IT-BL
634
+ '1884': IT-RC
635
+ '1901': IT-TO
636
+ '1858': IT-LU
637
+ '71329': IT-BT
638
+ '1889': IT-RN
639
+ '1909': IT-VC
640
+ '1823': IT-BI
641
+ '1866': IT-NA
642
+ '1867': IT-NO
643
+ '71330': IT-CI
644
+ '1840': IT-CZ
645
+ '1883': IT-RA
646
+ '1906': IT-UD
647
+ '1817': IT-AQ
648
+ '1872': IT-PD
649
+ '1849': IT-GR
650
+ '71332': IT-VS
651
+ '1856': IT-LO
652
+ '1890': IT-RO
653
+ '1859': IT-MC
654
+ '1833': IT-CH
655
+ '1847': IT-GE
656
+ '1799': IT-45
657
+ '1839': IT-CT
658
+ '1882': IT-PZ
659
+ '1831': IT-CB
660
+ '1816': IT-AP
661
+ '1899': IT-TE
662
+ '1846': IT-FR
663
+ '1850': IT-IM
664
+ '1873': IT-PE
665
+ '1880': IT-PT
666
+ '1837': IT-CR
667
+ '1860': IT-ME
668
+ '1865': IT-MT
669
+ '1891': IT-SA
670
+ '71331': IT-FM
671
+ '1842': IT-FE
672
+ '1908': IT-VB
673
+ '1834': IT-CL
674
+ '1857': IT-LT
675
+ '1848': IT-GO
676
+ '1825': IT-BN
677
+ '1874': IT-PG
678
+ '1897': IT-SV
679
+ '1914': IT-VV
680
+ '1814': IT-AN
681
+ '1822': IT-BG
682
+ '1900': IT-TN
683
+ '1892': IT-SI
684
+ '1876': IT-PN
685
+ '1853': IT-LC
686
+ '1896': IT-SS
687
+ '1827': IT-BR
688
+ '1813': IT-AL
689
+ '1902': IT-TP
690
+ '1910': IT-VE
691
+ '1819': IT-AT
692
+ '1870': IT-PA
693
+ '1877': IT-PO
694
+ '1854': IT-LE
695
+ '1913': IT-VT
696
+ '1862': IT-MN
697
+ '1836': IT-CO
698
+ '1879': IT-PS
699
+ '1830': IT-CA
700
+ '1893': IT-SO
701
+ '1885': IT-RE
702
+ '1888': IT-RM
703
+ '1868': IT-NU
704
+ '1828': IT-BS
705
+ '1911': IT-VI
706
+ '1871': IT-PC
707
+ '1851': IT-IS
708
+ '1894': IT-SP
709
+ '71334': IT-OG
710
+ '1905': IT-TV
711
+ '1912': IT-VR
712
+ '1903': IT-TR
713
+ '1869': IT-OR
714
+ '1820': IT-AV
715
+ '71335': IT-OT
716
+ '2487': NL-ZE
717
+ '2478': NL-FL
718
+ '2481': NL-GR
719
+ '2486': NL-UT
720
+ '2480': NL-GE
721
+ '2483': NL-NB
722
+ '2477': NL-DR
723
+ '2484': NL-NH
724
+ '2482': NL-LI
725
+ '2485': NL-OV
726
+ '2488': NL-ZH
727
+ '2479': NL-FR