espn 0.1.3 → 0.2.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.
- checksums.yaml +8 -8
- data/README.md +91 -6
- data/lib/espn.rb +5 -0
- data/lib/espn/arguments.rb +41 -0
- data/lib/espn/client.rb +29 -5
- data/lib/espn/client/athletes.rb +39 -21
- data/lib/espn/client/audio.rb +20 -19
- data/lib/espn/client/headlines.rb +58 -27
- data/lib/espn/client/medals.rb +8 -0
- data/lib/espn/client/notes.rb +31 -21
- data/lib/espn/client/now.rb +11 -8
- data/lib/espn/client/scores.rb +33 -21
- data/lib/espn/client/sports.rb +20 -14
- data/lib/espn/client/standings.rb +20 -16
- data/lib/espn/client/teams.rb +39 -21
- data/lib/espn/client/video.rb +14 -17
- data/lib/espn/configuration.rb +29 -12
- data/lib/espn/error.rb +15 -3
- data/lib/espn/helpers.rb +39 -0
- data/lib/espn/mapper.rb +142 -0
- data/lib/espn/request.rb +86 -7
- data/lib/espn/version.rb +1 -1
- data/lib/faraday/response/raise_espn_error.rb +33 -11
- data/spec/espn/arguments_spec.rb +76 -0
- data/spec/espn/client/athletes_spec.rb +38 -47
- data/spec/espn/client/audio_spec.rb +30 -29
- data/spec/espn/client/headlines_spec.rb +80 -35
- data/spec/espn/client/medals_spec.rb +1 -1
- data/spec/espn/client/notes_spec.rb +39 -45
- data/spec/espn/client/now_spec.rb +1 -2
- data/spec/espn/client/scores_spec.rb +56 -39
- data/spec/espn/client/sports_spec.rb +56 -18
- data/spec/espn/client/standings_spec.rb +42 -19
- data/spec/espn/client/teams_spec.rb +61 -43
- data/spec/espn/client/video_spec.rb +9 -13
- data/spec/espn/helpers_spec.rb +31 -0
- data/spec/espn/mapper_spec.rb +136 -0
- data/spec/espn/request_spec.rb +65 -0
- data/spec/espn_spec.rb +11 -2
- data/spec/faraday/response/raise_espn_error_spec.rb +80 -0
- data/spec/responses/athletes.json +51 -0
- data/spec/responses/audio.json +101 -0
- data/spec/responses/headlines.json +174 -0
- data/spec/responses/medals.json +273 -0
- data/spec/responses/notes.json +100 -0
- data/spec/responses/now.json +44 -0
- data/spec/responses/scores.json +209 -0
- data/spec/responses/sports.json +164 -0
- data/spec/responses/standings.json +2689 -0
- data/spec/responses/teams.json +51 -0
- data/spec/responses/videos.json +28 -0
- data/spec/spec_helper.rb +11 -2
- metadata +37 -3
- data/lib/espn/connection.rb +0 -32
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class MockHelper
|
4
|
+
include ESPN::Helpers
|
5
|
+
end
|
6
|
+
|
7
|
+
describe ESPN::Helpers do
|
8
|
+
before do
|
9
|
+
@helper = MockHelper.new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#blank?' do
|
13
|
+
it 'should be true for an empty string' do
|
14
|
+
@helper.blank?('').should be_true
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should be false for a non empty string' do
|
18
|
+
@helper.blank?('foo').should be_false
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should be true for a nil object' do
|
22
|
+
@helper.blank?(nil).should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should be false for a non nil object' do
|
26
|
+
@helper.blank?(Object.new).should be_false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class MockMapper
|
4
|
+
include ESPN::Mapper
|
5
|
+
end
|
6
|
+
|
7
|
+
describe ESPN::Mapper do
|
8
|
+
before do
|
9
|
+
@mapper = MockMapper.new
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#map_league_to_sport' do
|
13
|
+
describe 'param types' do
|
14
|
+
it 'should accept a string' do
|
15
|
+
@mapper.map_league_to_sport('nhl').should include(sport: 'hockey')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should accept a symbol' do
|
19
|
+
@mapper.map_league_to_sport(:mlb).should include(sport: 'baseball')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'with a league that has no mapping' do
|
24
|
+
it 'should include nil for the sport' do
|
25
|
+
@mapper.map_league_to_sport('foobar').should include(sport: nil)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with a given league (mma)' do
|
30
|
+
ESPN::Mapper::LEAGUE_MAP[:mma].each do |league|
|
31
|
+
it "should map #{league} to mma" do
|
32
|
+
@mapper.map_league_to_sport(league).should include(sport: 'mma')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#sport?' do
|
39
|
+
context 'with a valid sport' do
|
40
|
+
it 'should return true with a symbol' do
|
41
|
+
@mapper.sport?(:'horse-racing').should be_true
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should return true with a string' do
|
45
|
+
@mapper.sport?(:baseball).should be_true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with an invalid sport' do
|
50
|
+
it 'should return false' do
|
51
|
+
@mapper.sport?(:mlb).should be_false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#league?' do
|
57
|
+
context 'with a valid league' do
|
58
|
+
it 'should return true with a symbol' do
|
59
|
+
@mapper.league?(:mlb).should be_true
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should return true with a string' do
|
63
|
+
@mapper.league?('concacaf.champions_cup').should be_true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with an invalid league' do
|
68
|
+
it 'should return false' do
|
69
|
+
@mapper.league?(:baseball).should be_false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#extract_sport_and_league' do
|
75
|
+
context 'with a league' do
|
76
|
+
it 'should return the sport, league' do
|
77
|
+
@mapper.extract_sport_and_league(['mlb']).should eq(['baseball', 'mlb'])
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should convert symbols to strings' do
|
81
|
+
@mapper.extract_sport_and_league([:mlb]).should eq(['baseball', 'mlb'])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'with a sport' do
|
86
|
+
it 'should return the sport and a blank string' do
|
87
|
+
results = @mapper.extract_sport_and_league(['horse-racing'])
|
88
|
+
results.should eq(['horse-racing', ''])
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should convert symbols to strings' do
|
92
|
+
results = @mapper.extract_sport_and_league([:baseball])
|
93
|
+
results.should eq(['baseball', ''])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'with a league and a sport' do
|
98
|
+
it 'should return the first two args' do
|
99
|
+
results = @mapper.extract_sport_and_league(['foo', 'bar'])
|
100
|
+
results.should eq(['foo', 'bar'])
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should convert symbols to strings' do
|
104
|
+
results = @mapper.extract_sport_and_league([:foo, :bar])
|
105
|
+
results.should eq(['foo', 'bar'])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'with more than two arguments' do
|
110
|
+
it 'should return the first two args' do
|
111
|
+
results = @mapper.extract_sport_and_league(['foo', 'bar', 'baz'])
|
112
|
+
results.should eq(['foo', 'bar'])
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'with sport in the opts hash' do
|
117
|
+
it 'should return the sport from the opts hash' do
|
118
|
+
results = @mapper.extract_sport_and_league(['foo'], sport: 'bar')
|
119
|
+
results.should eq(['bar', ''])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'with league in the opts hash' do
|
124
|
+
it 'should return the league from the opts hash' do
|
125
|
+
results = @mapper.extract_sport_and_league(['mlb'], league: 'foo')
|
126
|
+
results.should eq(['baseball', 'foo'])
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should map the league to a sport' do
|
130
|
+
results = @mapper.extract_sport_and_league([], league: 'mlb')
|
131
|
+
results.should eq(['baseball', 'mlb'])
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ESPN::Request do
|
4
|
+
before do
|
5
|
+
@client = ESPN::Client.new
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#get' do
|
9
|
+
it 'should build a url from a template' do
|
10
|
+
opts = { foo: 'bar' }
|
11
|
+
pattern = '/:foo/baz'
|
12
|
+
@client.should_receive(:request).with(:get, '/bar/baz', opts)
|
13
|
+
@client.get(pattern, opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should call request' do
|
17
|
+
opts = { foo: 'bar' }
|
18
|
+
pattern = '/foo/bar'
|
19
|
+
@client.should_receive(:request).with(:get, pattern, opts)
|
20
|
+
@client.get(pattern, opts)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#build_url' do
|
25
|
+
it 'should remove duplicate slashes' do
|
26
|
+
@client.send(:build_url, '/foo///bar', {}).should eq('/foo/bar')
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should remove trailing slashes' do
|
30
|
+
@client.send(:build_url, '/foo/bar/', {}).should eq('/foo/bar')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should expand a pattern' do
|
34
|
+
fragments = { foo: 'bar' }
|
35
|
+
mock_uri = double('URITemplate')
|
36
|
+
URITemplate.stub(:new).and_return(mock_uri)
|
37
|
+
mock_uri.should_receive(:expand).with(fragments).and_return('/')
|
38
|
+
@client.send(:build_url, '/:some/pattern', fragments)
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'when sport is not a fragment' do
|
42
|
+
it 'should delete the league fragment' do
|
43
|
+
fragments = { league: 'somerandomleague' }
|
44
|
+
fragments.should_receive(:delete).with(:league)
|
45
|
+
@client.send(:build_url, ':some/pattern', fragments)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when sport is a fragment' do
|
50
|
+
it 'should not delete the league fragment' do
|
51
|
+
fragments = { league: 'mlb', sport: 'baseball' }
|
52
|
+
fragments.should_not_receive(:delete)
|
53
|
+
@client.send(:build_url, ':some/pattern', fragments)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when method is not a fragment' do
|
58
|
+
it 'should remove headlines from the pattern' do
|
59
|
+
pattern = ':sport/:league/news/headlines/:method'
|
60
|
+
pattern.should_receive(:gsub!).with('headlines', '')
|
61
|
+
@client.send(:build_url, pattern, {})
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/spec/espn_spec.rb
CHANGED
@@ -9,12 +9,21 @@ describe ESPN do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
describe '.method_missing' do
|
12
|
+
before do
|
13
|
+
@mock_espn = double('ESPN')
|
14
|
+
ESPN.stub(:new).and_return(@mock_espn)
|
15
|
+
end
|
16
|
+
|
12
17
|
it 'should call super if ESPN::Client does not respond to the method' do
|
13
|
-
|
18
|
+
@mock_espn.stub(:respond_to?).with(:to_s).and_return(false)
|
19
|
+
@mock_espn.should_not_receive(:to_s)
|
20
|
+
ESPN.to_s
|
14
21
|
end
|
15
22
|
|
16
23
|
it 'should send the method to a new ESPN::Client if it responds' do
|
17
|
-
|
24
|
+
@mock_espn.stub(:respond_to?).with(:foobar).and_return(true)
|
25
|
+
@mock_espn.should_receive(:send).with(:foobar)
|
26
|
+
ESPN.foobar
|
18
27
|
end
|
19
28
|
end
|
20
29
|
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Faraday::Response::RaiseESPNError do
|
4
|
+
before do
|
5
|
+
@class = described_class.new
|
6
|
+
end
|
7
|
+
|
8
|
+
context 'when used' do
|
9
|
+
before do
|
10
|
+
@response = Hashie::Mash.new(method: :get, url: 'http://test')
|
11
|
+
@response.body = Hashie::Mash.new(status: 'error', message: 'foobar')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'does not raise an error if the response has no body' do
|
15
|
+
@response.body = nil
|
16
|
+
lambda {
|
17
|
+
@class.on_complete(@response)
|
18
|
+
}.should_not raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'does not raise an error for HTTP 200' do
|
22
|
+
@response.body.code = 200
|
23
|
+
lambda {
|
24
|
+
@class.on_complete(@response)
|
25
|
+
}.should_not raise_error
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'raises an error for HTTP 400' do
|
29
|
+
@response.body.code = 400
|
30
|
+
lambda {
|
31
|
+
@class.on_complete(@response)
|
32
|
+
}.should raise_error(ESPN::BadRequest)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'raises an error for HTTP 401' do
|
36
|
+
@response.body.code = 401
|
37
|
+
lambda {
|
38
|
+
@class.on_complete(@response)
|
39
|
+
}.should raise_error(ESPN::Unauthorized)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'raises an error for HTTP 403' do
|
43
|
+
@response.body.code = 403
|
44
|
+
lambda {
|
45
|
+
@class.on_complete(@response)
|
46
|
+
}.should raise_error(ESPN::Forbidden)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'raises an error for HTTP 404' do
|
50
|
+
@response.body.code = 404
|
51
|
+
lambda {
|
52
|
+
@class.on_complete(@response)
|
53
|
+
}.should raise_error(ESPN::NotFound)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'raises an error for HTTP 500' do
|
57
|
+
@response.body.code = 500
|
58
|
+
lambda {
|
59
|
+
@class.on_complete(@response)
|
60
|
+
}.should raise_error(ESPN::InternalServerError)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'raises an error fro HTTP 504' do
|
64
|
+
@response.body.code = 504
|
65
|
+
lambda {
|
66
|
+
@class.on_complete(@response)
|
67
|
+
}.should raise_error(ESPN::GatewayTimeout)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#error_message' do
|
72
|
+
it 'should be formatted correctly' do
|
73
|
+
response = Hashie::Mash.new(method: :get, url: 'http://test')
|
74
|
+
response.body = Hashie::Mash.new(status: 'error', message: 'some error')
|
75
|
+
result = @class.error_message(response)
|
76
|
+
result.should eq('GET http://test: error - some error')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
{
|
2
|
+
"sports": [{
|
3
|
+
"name": "baseball",
|
4
|
+
"id": 1,
|
5
|
+
"uid": "s:1",
|
6
|
+
"leagues": [{
|
7
|
+
"name": "Major League Baseball",
|
8
|
+
"abbreviation": "mlb",
|
9
|
+
"id": 10,
|
10
|
+
"uid": "s:1~l:10",
|
11
|
+
"groupId": 9,
|
12
|
+
"shortName": "MLB",
|
13
|
+
"athletes": [{
|
14
|
+
"id": 5383,
|
15
|
+
"firstName": "Chase",
|
16
|
+
"lastName": "Utley",
|
17
|
+
"fullName": "Chase Utley",
|
18
|
+
"displayName": "Chase Utley",
|
19
|
+
"shortName": "C. Utley",
|
20
|
+
"links": {
|
21
|
+
"api": {
|
22
|
+
"athletes": {
|
23
|
+
"href": "http://api.espn.com/v1/sports/baseball/mlb/athletes/5383"
|
24
|
+
},
|
25
|
+
"news": {
|
26
|
+
"href": "http://api.espn.com/v1/sports/baseball/mlb/athletes/5383/news"
|
27
|
+
},
|
28
|
+
"notes": {
|
29
|
+
"href": "http://api.espn.com/v1/sports/baseball/mlb/athletes/5383/news/notes"
|
30
|
+
}
|
31
|
+
},
|
32
|
+
"web": {
|
33
|
+
"athletes": {
|
34
|
+
"href": "http://espn.go.com/mlb/player/_/id/5383/chase-utley?ex_cid=espnapi_public"
|
35
|
+
}
|
36
|
+
},
|
37
|
+
"mobile": {
|
38
|
+
"athletes": {
|
39
|
+
"href": "http://m.espn.go.com/mlb/playercard?playerId=5383&ex_cid=espnapi_public"
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}]
|
44
|
+
}]
|
45
|
+
}],
|
46
|
+
"resultsOffset": 0,
|
47
|
+
"resultsLimit": 50,
|
48
|
+
"resultsCount": 1,
|
49
|
+
"timestamp": "2013-08-27T17:15:39Z",
|
50
|
+
"status": "success"
|
51
|
+
}
|
@@ -0,0 +1,101 @@
|
|
1
|
+
{
|
2
|
+
"resultsCount":29,
|
3
|
+
"resultsOffset":0,
|
4
|
+
"resultsLimit":10,
|
5
|
+
"recordings":[
|
6
|
+
{
|
7
|
+
"id":8656148,
|
8
|
+
"published":"2012-11-20T17:27:56Z",
|
9
|
+
"premium":false,
|
10
|
+
"headline":"First Take",
|
11
|
+
"shortDescription":"",
|
12
|
+
"description":"Skip Bayless and Stephen A. Smith debate the Bears, the 49ers and Colin Kaepernick, Ed Reed hits, Steelers, Patriots and NFC East.",
|
13
|
+
"links":{
|
14
|
+
"api":{
|
15
|
+
"recordings":{
|
16
|
+
"href":"http://api.espn.com/v1/audio/recordings/8656148"
|
17
|
+
}
|
18
|
+
},
|
19
|
+
"web":{
|
20
|
+
"href":"http://espn.go.com/espnradio/play?id=8656148&ex_cid=espnapi_internal"
|
21
|
+
},
|
22
|
+
"mobile":{
|
23
|
+
"href":"http://m.espn.go.com/general/play?id=8656148&ex_cid=espnapi_internal"
|
24
|
+
},
|
25
|
+
"source":{
|
26
|
+
"default":{
|
27
|
+
"href":"http://c.espnradio.com/audio/1259102/firsttake_2012-11-20-122302.mp3"
|
28
|
+
},
|
29
|
+
"bitrate32k":{
|
30
|
+
"href":"http://c.espnradio.com/audio/1259102/firsttake_2012-11-20-122302.32.mp3"
|
31
|
+
},
|
32
|
+
"bitrate48k":{
|
33
|
+
"href":"http://c.espnradio.com/audio/1259102/firsttake_2012-11-20-122302.48.mp3"
|
34
|
+
},
|
35
|
+
"bitrate128k":{
|
36
|
+
"href":"http://c.espnradio.com/audio/1259102/firsttake_2012-11-20-122302.128.mp3"
|
37
|
+
}
|
38
|
+
}
|
39
|
+
},
|
40
|
+
"thumbnails":{
|
41
|
+
"xsmall":{
|
42
|
+
"href":"http://a.espncdn.com/i/espnradio/stations/espn/podcasts/first_take_90.jpg",
|
43
|
+
"width":90,
|
44
|
+
"height":90
|
45
|
+
},
|
46
|
+
"small":{
|
47
|
+
"href":"http://a.espncdn.com/i/espnradio/stations/espn/podcasts/first_take_134.jpg",
|
48
|
+
"width":134,
|
49
|
+
"height":75
|
50
|
+
},
|
51
|
+
"large":{
|
52
|
+
"href":"http://a.espncdn.com/i/espnradio/stations/espn/podcasts/first_take_288.jpg",
|
53
|
+
"width":288,
|
54
|
+
"height":162
|
55
|
+
},
|
56
|
+
"medium":{
|
57
|
+
"href":"http://a.espncdn.com/i/espnradio/stations/espn/podcasts/first_take_203.jpg",
|
58
|
+
"width":203,
|
59
|
+
"height":114
|
60
|
+
},
|
61
|
+
"xlarge":{
|
62
|
+
"href":"http://a.espncdn.com/i/espnradio/stations/espn/podcasts/first_take_300.jpg",
|
63
|
+
"width":300,
|
64
|
+
"height":300
|
65
|
+
}
|
66
|
+
},
|
67
|
+
"categories":[
|
68
|
+
{
|
69
|
+
"podcastId":6247496,
|
70
|
+
"podcast":{
|
71
|
+
"id":6247496,
|
72
|
+
"description":"ESPN: First Take",
|
73
|
+
"links":{
|
74
|
+
"api":{
|
75
|
+
"podcasts":{
|
76
|
+
"href":"http://api.espn.com/v1/audio/podcasts/6247496"
|
77
|
+
}
|
78
|
+
},
|
79
|
+
"web":{
|
80
|
+
"href":"http://espn.go.com/espnradio/podcast/archive?id=6247496&ex_cid=espnapi_internal"
|
81
|
+
},
|
82
|
+
"mobile":{
|
83
|
+
"href":"http://m.espn.go.com/general/cast?id=6247496&ex_cid=espnapi_internal"
|
84
|
+
}
|
85
|
+
}
|
86
|
+
},
|
87
|
+
"description":"ESPN: First Take",
|
88
|
+
"type":"podcast"
|
89
|
+
}
|
90
|
+
],
|
91
|
+
"keywords":[
|
92
|
+
"1st and 10",
|
93
|
+
"first take",
|
94
|
+
"Skip Bayless",
|
95
|
+
"Stephen A. Smith"
|
96
|
+
]
|
97
|
+
}
|
98
|
+
],
|
99
|
+
"timestamp":"2012-11-21T17:21:21Z",
|
100
|
+
"status":"success"
|
101
|
+
}
|