executrix 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 1.9.3-p392
1
+ 1.9.3-p429
data/.travis.yml CHANGED
@@ -3,7 +3,7 @@ bundler_args: --without documentation production
3
3
  rvm:
4
4
  - 1.9.3
5
5
  - 2.0.0
6
- - jruby-19mode
6
+ - jruby-19mode-1.7.4
7
7
  - rbx-19mode
8
8
  matrix:
9
9
  allow_failures:
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ ## 1.1.0 (June 16th, 2013)
2
+
3
+ - Add possibility to fetch OrgId after login
4
+ - Update default Salesforce API version to 28.0
5
+
6
+ ## 1.0.0 (May 13th, 2013)
7
+
8
+ - initial release (rewrite of [salesforce_bulk](https://github.com/jorgevaldivia/salesforce_bulk))
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Executrix
2
2
 
3
- DISCLAIMER: This gem is a rewrite of the [salesforce_bulk](https://github.com/jorgevaldivia/salesforce_bulk) gem. As the original maintainer didn't respon to my [pull-request](https://github.com/jorgevaldivia/salesforce_bulk/pull/14) I decided to rerelease the gem under different name. This is it.
3
+ [![Build Status](https://travis-ci.org/propertybase/executrix.png?branch=master)](https://travis-ci.org/propertybase/executrix) [![Coverage Status](https://coveralls.io/repos/propertybase/executrix/badge.png?branch=master)](https://coveralls.io/r/propertybase/executrix) [![Code Climate](https://codeclimate.com/github/propertybase/executrix.png)](https://codeclimate.com/github/propertybase/executrix) [![Dependency Status](https://gemnasium.com/propertybase/executrix.png)](https://gemnasium.com/propertybase/executrix) [![Gem Version](https://badge.fury.io/rb/executrix.png)](http://badge.fury.io/rb/executrix)
4
+
5
+ DISCLAIMER: This gem is a rewrite of the [salesforce_bulk](https://github.com/jorgevaldivia/salesforce_bulk) gem. As the original maintainer didn't respon to my [pull-request](https://github.com/jorgevaldivia/salesforce_bulk/pull/14) I decided to rerelease the gem under different name.
4
6
 
5
7
  The original Copyright Notice and all the original commit logs have been retained.
6
8
 
@@ -33,6 +35,16 @@ salesforce = Executrix::Api.new('YOUR_SALESFORCE_SANDBOX_USERNAME', 'YOUR_SALESF
33
35
 
34
36
  Note: the second parameter is a combination of your Salesforce token and password. So if your password is xxxx and your token is yyyy, the second parameter will be xxxxyyyy
35
37
 
38
+ #### OrgId
39
+
40
+ After you created the client object you can fetch the OrgId via `org_id`.
41
+
42
+ This will fetch the 15 digit OrgId.
43
+
44
+ ~~~ ruby
45
+ salesforce.org_id # '00D50000000IehZ'
46
+ ~~~
47
+
36
48
  ### Operations
37
49
 
38
50
  ~~~ ruby
data/executrix.gemspec CHANGED
@@ -6,8 +6,8 @@ require 'executrix/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = 'executrix'
8
8
  gem.version = Executrix::VERSION
9
- gem.authors = ["Jorge Valdivia"]
10
- gem.email = ["jorge@valdivia.me"]
9
+ gem.authors = ['Jorge Valdivia', 'Leif Gensert']
10
+ gem.email = ['jorge@valdivia.me', 'leif@propertybase.com']
11
11
  gem.homepage = 'https://github.com/propertybase/executrix'
12
12
  gem.summary = %q{Ruby support for the Salesforce Bulk API}
13
13
  gem.description = %q{This gem provides a super simple interface for the Salesforce Bulk API. It provides support for insert, update, upsert, delete, and query.}
@@ -20,8 +20,8 @@ Gem::Specification.new do |gem|
20
20
  gem.require_paths = ["lib"]
21
21
 
22
22
  gem.add_dependency 'rake'
23
- gem.add_dependency 'nori', '~> 2.0'
24
- gem.add_dependency 'nokogiri', '~> 1.5'
25
- gem.add_development_dependency 'rspec', '~> 2.13'
26
- gem.add_development_dependency 'webmock', '~> 1.11'
23
+ gem.add_dependency 'nori', '< 2.3'
24
+ gem.add_dependency 'nokogiri', '< 1.7'
25
+ gem.add_development_dependency 'rspec', '< 2.14'
26
+ gem.add_development_dependency 'webmock', '< 1.12'
27
27
  end
data/lib/executrix.rb CHANGED
@@ -6,7 +6,7 @@ require 'executrix/connection'
6
6
 
7
7
  module Executrix
8
8
  class Api
9
- SALESFORCE_API_VERSION = '27.0'
9
+ SALESFORCE_API_VERSION = '28.0'
10
10
 
11
11
  def initialize(username, password, sandbox = false, api_version = SALESFORCE_API_VERSION)
12
12
  @connection = Executrix::Connection.connect(
@@ -19,6 +19,11 @@ module Executrix
19
19
  self
20
20
  end
21
21
 
22
+ def org_id
23
+ raise 'please login first' unless @session_id
24
+ @session_id.split('!').first
25
+ end
26
+
22
27
  def create_job operation, sobject, external_field
23
28
  Executrix::Http.create_job(
24
29
  @instance,
@@ -1,3 +1,3 @@
1
1
  module Executrix
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0'
3
3
  end
@@ -15,7 +15,7 @@ describe Executrix::Batch do
15
15
  b = described_class.new nil, nil, -1
16
16
  expected_status = {
17
17
  state: 'Completed',
18
- state_message: 'Empty Request'
18
+ state_message: 'Empty Request',
19
19
  }
20
20
  b.should_not_receive(:status)
21
21
  expect(b.final_status).to eq(expected_status)
@@ -41,8 +41,8 @@ describe Executrix::Batch do
41
41
  b.should_receive(:status).once.and_return(expected_running_state)
42
42
  b.should_receive(:status).once.and_return(expected_final_state)
43
43
  b.should_receive(:results).once.and_return({g: :tfo})
44
- expect{|blk| b.final_status(0, &blk)}.
45
- to yield_successive_args(expected_running_state, expected_final_state)
44
+ expect{|blk| b.final_status(0, &blk)}
45
+ .to yield_successive_args(expected_running_state, expected_final_state)
46
46
  end
47
47
 
48
48
  it 'should raise exception when batch fails' do
@@ -52,8 +52,8 @@ describe Executrix::Batch do
52
52
  {
53
53
  state: 'Failed',
54
54
  state_message: expected_error_message})
55
- expect{b.final_status}.
56
- to raise_error(StandardError, expected_error_message)
55
+ expect{b.final_status}
56
+ .to raise_error(StandardError, expected_error_message)
57
57
  end
58
58
  end
59
59
  end
@@ -11,13 +11,12 @@ describe Executrix::Connection do
11
11
  query_batch: 2,
12
12
  query_batch_result_id: 2,
13
13
  query_batch_result_data: 3,
14
-
15
14
  }.each do |method_name, num_of_params|
16
15
  describe "##{method_name}" do
17
16
  it 'should delegate correctly to Http class' do
18
- Executrix::Http.
19
- should_receive(method_name).
20
- and_return({})
17
+ Executrix::Http
18
+ .should_receive(method_name)
19
+ .and_return({})
21
20
  subject.send(method_name, *Array.new(num_of_params))
22
21
  end
23
22
  end
@@ -25,18 +24,33 @@ describe Executrix::Connection do
25
24
 
26
25
  describe '#add_query' do
27
26
  it 'should delegate correctly to Http class' do
28
- Executrix::Http.should_receive(:add_batch).
29
- and_return({})
27
+ Executrix::Http.should_receive(:add_batch)
28
+ .and_return({})
30
29
  subject.add_query(nil, nil)
31
30
  end
32
31
  end
33
32
 
33
+ describe '#org_id' do
34
+ it 'should raise exception when not logged in' do
35
+ expect {subject.org_id}.to raise_error(RuntimeError)
36
+ end
37
+
38
+ it 'should return correct OrgId after login' do
39
+ org_id = '00D50000000IehZ'
40
+ Executrix::Http
41
+ .should_receive(:login)
42
+ .and_return({session_id: "#{org_id}!AQcAQH0dMHZfz972Szmpkb58urFRkgeBGsxL_QJWwYMfAbUeeG7c1E6LYUfiDUkWe6H34r1AAwOR8B8fLEz6n04NPGRrq0FM"})
43
+ expect(subject.login.org_id).to eq(org_id)
44
+ end
45
+ end
46
+
47
+
34
48
  describe '#add_batch' do
35
49
  it 'should delegate correctly to underlying classes' do
36
- Executrix::Http.should_receive(:add_batch).
37
- and_return({})
38
- Executrix::Helper.should_receive(:records_to_csv).
39
- and_return('My,Awesome,CSV')
50
+ Executrix::Http.should_receive(:add_batch)
51
+ .and_return({})
52
+ Executrix::Helper.should_receive(:records_to_csv)
53
+ .and_return('My,Awesome,CSV')
40
54
  subject.add_batch(nil, 'non emtpy records')
41
55
  end
42
56
 
@@ -18,11 +18,11 @@ describe Executrix::Http do
18
18
 
19
19
  it 'should return a response object' do
20
20
  expected_body = 'correct result'
21
- stub_request(:post, 'https://test.host').
22
- with(
21
+ stub_request(:post, 'https://test.host')
22
+ .with(
23
23
  body: post_request.body,
24
- headers: post_request.headers).
25
- to_return(:body => expected_body)
24
+ headers: post_request.headers)
25
+ .to_return(:body => expected_body)
26
26
  res = Executrix::Http.process_http_request(post_request)
27
27
  expect(res).to eq(expected_body)
28
28
  end
@@ -141,16 +141,16 @@ describe Executrix::Http do
141
141
  end
142
142
 
143
143
  it 'should raise an error for faulty login' do
144
- Executrix::Http.should_receive(:process_http_request).
145
- and_return(login_error)
146
- expect{ Executrix::Http.login('a','b','c', 'd') }.
147
- to raise_error(RuntimeError, login_error_message)
144
+ Executrix::Http.should_receive(:process_http_request)
145
+ .and_return(login_error)
146
+ expect{ Executrix::Http.login('a','b','c', 'd') }
147
+ .to raise_error(RuntimeError, login_error_message)
148
148
  end
149
149
 
150
150
  it 'should return hash for correct login' do
151
151
  [login_success, login_success_new].each do |login_response|
152
- Executrix::Http.should_receive(:process_http_request).
153
- and_return(login_response)
152
+ Executrix::Http.should_receive(:process_http_request)
153
+ .and_return(login_response)
154
154
  result = Executrix::Http.login('a','b','c', 'd')
155
155
  expect(result).to be_a(Hash)
156
156
  expect(result).to have_key(:session_id)
@@ -190,8 +190,8 @@ describe Executrix::Http do
190
190
  end
191
191
 
192
192
  it 'should return hash for creating job' do
193
- Executrix::Http.should_receive(:process_http_request).
194
- and_return(create_job_success)
193
+ Executrix::Http.should_receive(:process_http_request)
194
+ .and_return(create_job_success)
195
195
  result = Executrix::Http.create_job('a','b','c','d', 'e')
196
196
  expect(result).to be_a(Hash)
197
197
  expect(result).to have_key(:id)
@@ -219,8 +219,8 @@ describe Executrix::Http do
219
219
  end
220
220
 
221
221
  it 'should return hash for adding batch' do
222
- Executrix::Http.should_receive(:process_http_request).
223
- and_return(add_batch_success)
222
+ Executrix::Http.should_receive(:process_http_request)
223
+ .and_return(add_batch_success)
224
224
  result = Executrix::Http.add_batch(:post,'a','b','c','d')
225
225
  expect(result).to be_a(Hash)
226
226
  expect(result).to have_key(:id)
@@ -259,8 +259,8 @@ describe Executrix::Http do
259
259
  end
260
260
 
261
261
  it 'should return hash for closing job' do
262
- Executrix::Http.should_receive(:process_http_request).
263
- and_return(close_job_success)
262
+ Executrix::Http.should_receive(:process_http_request)
263
+ .and_return(close_job_success)
264
264
  result = Executrix::Http.close_job('a','b','c','d')
265
265
  expect(result).to be_a(Hash)
266
266
  expect(result).to have_key(:id)
@@ -281,10 +281,10 @@ describe Executrix::Http do
281
281
  end
282
282
 
283
283
  it 'should raise an exception on faulty authorization' do
284
- Executrix::Http.should_receive(:process_http_request).
285
- and_return(invalid_session_id)
286
- expect{Executrix::Http.query_batch('a','b','c','d','e')}.
287
- to raise_error(RuntimeError, 'InvalidSessionId: Invalid session id')
284
+ Executrix::Http.should_receive(:process_http_request)
285
+ .and_return(invalid_session_id)
286
+ expect{Executrix::Http.query_batch('a','b','c','d','e')}
287
+ .to raise_error(RuntimeError, 'InvalidSessionId: Invalid session id')
288
288
  end
289
289
  end
290
290
 
@@ -296,8 +296,8 @@ describe Executrix::Http do
296
296
  end
297
297
 
298
298
  it 'should return hash including the result id' do
299
- Executrix::Http.should_receive(:process_http_request).
300
- and_return(batch_result_success)
299
+ Executrix::Http.should_receive(:process_http_request)
300
+ .and_return(batch_result_success)
301
301
  result = Executrix::Http.query_batch_result_id('a','b','c','d','e')
302
302
  expect(result).to be_a(Hash)
303
303
  expect(result).to have_key(:result)
@@ -318,8 +318,8 @@ describe Executrix::Http do
318
318
  end
319
319
 
320
320
  it 'should return array of arrays for data' do
321
- Executrix::Http.should_receive(:process_http_request).
322
- and_return(batch_result_data_success)
321
+ Executrix::Http.should_receive(:process_http_request)
322
+ .and_return(batch_result_data_success)
323
323
  result = Executrix::Http.query_batch_result_data('a','b','c','d','e','f')
324
324
  expect(result).to eq([
325
325
  {'Id' => '003M000057GH39aIAD', 'my_external_id__c' => 'K-00J799'},
@@ -327,8 +327,8 @@ describe Executrix::Http do
327
327
  end
328
328
 
329
329
  it 'should return correct array with spaces' do
330
- Executrix::Http.should_receive(:process_http_request).
331
- and_return(batch_result_data_with_spaces_success)
330
+ Executrix::Http.should_receive(:process_http_request)
331
+ .and_return(batch_result_data_with_spaces_success)
332
332
  result = Executrix::Http.query_batch_result_data('a','b','c','d','e','f')
333
333
  expect(result).to eq([
334
334
  {'Id' => '003K000057GH39aIAD', 'Name' => 'Master of Disaster'},
@@ -18,19 +18,19 @@ describe Executrix::Api do
18
18
  }.each do |method_name, num_of_params|
19
19
  describe "##{method_name}" do
20
20
  it 'should delegate to #start_job' do
21
- Executrix::Connection.
22
- should_receive(:connect).
23
- and_return(empty_connection)
21
+ Executrix::Connection
22
+ .should_receive(:connect)
23
+ .and_return(empty_connection)
24
24
  s = described_class.new(nil, nil)
25
- s.should_receive(:start_job).
26
- with(method_name.to_s, *Array.new(num_of_params))
25
+ s.should_receive(:start_job)
26
+ .with(method_name.to_s, *Array.new(num_of_params))
27
27
  s.send(method_name, *Array.new(num_of_params))
28
28
  end
29
29
 
30
30
  it 'should trigger correct workflow' do
31
- Executrix::Connection.
32
- should_receive(:connect).
33
- and_return(empty_connection)
31
+ Executrix::Connection
32
+ .should_receive(:connect)
33
+ .and_return(empty_connection)
34
34
  s = described_class.new(nil, nil)
35
35
  empty_connection.should_receive(:create_job).ordered
36
36
  empty_connection.should_receive(:add_batch).ordered
@@ -43,12 +43,12 @@ describe Executrix::Api do
43
43
 
44
44
  describe '#query' do
45
45
  it 'should trigger correct workflow' do
46
- Executrix::Connection.
47
- should_receive(:connect).
48
- and_return(empty_connection)
49
- Executrix::Batch.
50
- should_receive(:new).
51
- and_return(empty_batch)
46
+ Executrix::Connection
47
+ .should_receive(:connect)
48
+ .and_return(empty_connection)
49
+ Executrix::Batch
50
+ .should_receive(:new)
51
+ .and_return(empty_batch)
52
52
 
53
53
  s = described_class.new(nil, nil)
54
54
  sobject_input = 'sobject_stub'
metadata CHANGED
@@ -1,89 +1,101 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: executrix
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ prerelease:
5
+ version: 1.1.0
5
6
  platform: ruby
6
7
  authors:
7
8
  - Jorge Valdivia
8
- autorequire:
9
+ - Leif Gensert
10
+ autorequire:
9
11
  bindir: bin
10
12
  cert_chain: []
11
- date: 2013-05-13 00:00:00.000000000 Z
13
+ date: 2013-06-16 00:00:00.000000000 Z
12
14
  dependencies:
13
15
  - !ruby/object:Gem::Dependency
14
16
  name: rake
15
- requirement: !ruby/object:Gem::Requirement
17
+ version_requirements: !ruby/object:Gem::Requirement
16
18
  requirements:
17
- - - ! '>='
19
+ - - '>='
18
20
  - !ruby/object:Gem::Version
19
21
  version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
22
+ none: false
23
+ requirement: !ruby/object:Gem::Requirement
23
24
  requirements:
24
- - - ! '>='
25
+ - - '>='
25
26
  - !ruby/object:Gem::Version
26
27
  version: '0'
28
+ none: false
29
+ prerelease: false
30
+ type: :runtime
27
31
  - !ruby/object:Gem::Dependency
28
32
  name: nori
33
+ version_requirements: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - <
36
+ - !ruby/object:Gem::Version
37
+ version: '2.3'
38
+ none: false
29
39
  requirement: !ruby/object:Gem::Requirement
30
40
  requirements:
31
- - - ~>
41
+ - - <
32
42
  - !ruby/object:Gem::Version
33
- version: '2.0'
34
- type: :runtime
43
+ version: '2.3'
44
+ none: false
35
45
  prerelease: false
46
+ type: :runtime
47
+ - !ruby/object:Gem::Dependency
48
+ name: nokogiri
36
49
  version_requirements: !ruby/object:Gem::Requirement
37
50
  requirements:
38
- - - ~>
51
+ - - <
39
52
  - !ruby/object:Gem::Version
40
- version: '2.0'
41
- - !ruby/object:Gem::Dependency
42
- name: nokogiri
53
+ version: '1.7'
54
+ none: false
43
55
  requirement: !ruby/object:Gem::Requirement
44
56
  requirements:
45
- - - ~>
57
+ - - <
46
58
  - !ruby/object:Gem::Version
47
- version: '1.5'
48
- type: :runtime
59
+ version: '1.7'
60
+ none: false
49
61
  prerelease: false
62
+ type: :runtime
63
+ - !ruby/object:Gem::Dependency
64
+ name: rspec
50
65
  version_requirements: !ruby/object:Gem::Requirement
51
66
  requirements:
52
- - - ~>
67
+ - - <
53
68
  - !ruby/object:Gem::Version
54
- version: '1.5'
55
- - !ruby/object:Gem::Dependency
56
- name: rspec
69
+ version: '2.14'
70
+ none: false
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - ~>
73
+ - - <
60
74
  - !ruby/object:Gem::Version
61
- version: '2.13'
62
- type: :development
75
+ version: '2.14'
76
+ none: false
63
77
  prerelease: false
78
+ type: :development
79
+ - !ruby/object:Gem::Dependency
80
+ name: webmock
64
81
  version_requirements: !ruby/object:Gem::Requirement
65
82
  requirements:
66
- - - ~>
83
+ - - <
67
84
  - !ruby/object:Gem::Version
68
- version: '2.13'
69
- - !ruby/object:Gem::Dependency
70
- name: webmock
85
+ version: '1.12'
86
+ none: false
71
87
  requirement: !ruby/object:Gem::Requirement
72
88
  requirements:
73
- - - ~>
89
+ - - <
74
90
  - !ruby/object:Gem::Version
75
- version: '1.11'
76
- type: :development
91
+ version: '1.12'
92
+ none: false
77
93
  prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ~>
81
- - !ruby/object:Gem::Version
82
- version: '1.11'
83
- description: This gem provides a super simple interface for the Salesforce Bulk API.
84
- It provides support for insert, update, upsert, delete, and query.
94
+ type: :development
95
+ description: This gem provides a super simple interface for the Salesforce Bulk API. It provides support for insert, update, upsert, delete, and query.
85
96
  email:
86
97
  - jorge@valdivia.me
98
+ - leif@propertybase.com
87
99
  executables: []
88
100
  extensions: []
89
101
  extra_rdoc_files: []
@@ -92,6 +104,7 @@ files:
92
104
  - .rspec
93
105
  - .ruby-version
94
106
  - .travis.yml
107
+ - CHANGELOG.md
95
108
  - Gemfile
96
109
  - Guardfile
97
110
  - LICENSE
@@ -112,26 +125,33 @@ files:
112
125
  - spec/spec_helper.rb
113
126
  homepage: https://github.com/propertybase/executrix
114
127
  licenses: []
115
- metadata: {}
116
- post_install_message:
128
+ post_install_message:
117
129
  rdoc_options: []
118
130
  require_paths:
119
131
  - lib
120
132
  required_ruby_version: !ruby/object:Gem::Requirement
121
133
  requirements:
122
- - - ! '>='
134
+ - - '>='
123
135
  - !ruby/object:Gem::Version
136
+ segments:
137
+ - 0
138
+ hash: 2
124
139
  version: '0'
140
+ none: false
125
141
  required_rubygems_version: !ruby/object:Gem::Requirement
126
142
  requirements:
127
- - - ! '>='
143
+ - - '>='
128
144
  - !ruby/object:Gem::Version
145
+ segments:
146
+ - 0
147
+ hash: 2
129
148
  version: '0'
149
+ none: false
130
150
  requirements: []
131
151
  rubyforge_project: executrix
132
- rubygems_version: 2.0.0
133
- signing_key:
134
- specification_version: 4
152
+ rubygems_version: 1.8.24
153
+ signing_key:
154
+ specification_version: 3
135
155
  summary: Ruby support for the Salesforce Bulk API
136
156
  test_files:
137
157
  - spec/lib/executrix/batch_spec.rb
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- M2I4ZDNlY2E3NzEyMjNiOThiMDFjMTg0Yjk0ZmM0ZDIxOThlOTgxNw==
5
- data.tar.gz: !binary |-
6
- MzllZDVhODY1NDNhNTY4ZmIwMmE0M2NjZmM1NWNhZDA1NTE4MzA2Nw==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- NDg4ODI3NWZhYjU0MjZiNWE5MzIwYmNjOTg0YTUzODE5ODlkYmMxMjMxODE3
10
- MTVjYWU5ZGQxZjIwNzVkNzBiZmQ4ZWJlNGU5OGE1MWEyZDY4Nzk5NTQ1ZjRm
11
- NzRlYjgwYzA3YWFmOTQ3ZmMwMTcwYzY5MDgyMjdkMzFjYTQ3OTM=
12
- data.tar.gz: !binary |-
13
- NjM0ZjQ3YTg1MWJiNDBmYWM2YWE2YTI2ZTZiNmY3YzYyZGI1ZDBhOGEwYmIx
14
- M2RkZTRlOTQ2ODI1Y2E3ZDhjOWIwZjEwNDc1M2QzOGY5MDRjZWY0MWY2M2Q3
15
- ZDU3MjRmYWVkOWM2YmViYTNhYzBhMjk0YTZiMDEyNTJjMzdlZjM=