bitly 1.1.2 → 2.0.0.beta.1
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 +5 -5
- data/.gitignore +36 -3
- data/.rspec +3 -0
- data/.travis.yml +5 -2
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +5 -2
- data/History.txt +18 -1
- data/LICENSE.md +1 -1
- data/README.md +151 -58
- data/Rakefile +4 -9
- data/bin/console +14 -0
- data/bin/oauth +10 -0
- data/bin/setup +8 -0
- data/bitly.gemspec +24 -29
- data/config/env.yml.example +5 -0
- data/docs/authentication.md +51 -0
- data/docs/bitlinks.md +2 -0
- data/docs/branded_short_domains.md +20 -0
- data/docs/groups.md +80 -0
- data/docs/oauth_apps.md +20 -0
- data/docs/organizations.md +74 -0
- data/docs/premium_apis.md +0 -0
- data/docs/users.md +1 -0
- data/lib/bitly.rb +6 -7
- data/lib/bitly/api.rb +16 -0
- data/lib/bitly/api/base.rb +22 -0
- data/lib/bitly/api/bitlink.rb +341 -0
- data/lib/bitly/api/bitlink/clicks_summary.rb +35 -0
- data/lib/bitly/api/bitlink/deeplink.rb +29 -0
- data/lib/bitly/api/bitlink/link_click.rb +74 -0
- data/lib/bitly/api/bitlink/paginated_list.rb +51 -0
- data/lib/bitly/api/bsd.rb +24 -0
- data/lib/bitly/api/click_metric.rb +185 -0
- data/lib/bitly/api/client.rb +588 -0
- data/lib/bitly/api/group.rb +232 -0
- data/lib/bitly/api/group/preferences.rb +73 -0
- data/lib/bitly/api/list.rb +22 -0
- data/lib/bitly/api/oauth_app.rb +26 -0
- data/lib/bitly/api/organization.rb +104 -0
- data/lib/bitly/api/shorten_counts.rb +61 -0
- data/lib/bitly/api/user.rb +107 -0
- data/lib/bitly/error.rb +33 -0
- data/lib/bitly/http.rb +6 -0
- data/lib/bitly/http/adapters/net_http.rb +27 -0
- data/lib/bitly/http/client.rb +33 -0
- data/lib/bitly/http/request.rb +116 -0
- data/lib/bitly/http/response.rb +65 -0
- data/lib/bitly/oauth.rb +109 -0
- data/lib/bitly/version.rb +3 -1
- metadata +88 -108
- data/Manifest +0 -37
- data/lib/bitly/url.rb +0 -103
- data/lib/bitly/utils.rb +0 -57
- data/lib/bitly/v3.rb +0 -14
- data/lib/bitly/v3/bitly.rb +0 -7
- data/lib/bitly/v3/country.rb +0 -13
- data/lib/bitly/v3/day.rb +0 -13
- data/lib/bitly/v3/missing_url.rb +0 -15
- data/lib/bitly/v3/oauth.rb +0 -41
- data/lib/bitly/v3/realtime_link.rb +0 -18
- data/lib/bitly/v3/referrer.rb +0 -13
- data/lib/bitly/v3/url.rb +0 -154
- data/test/bitly/test_client.rb +0 -266
- data/test/bitly/test_config.rb +0 -28
- data/test/bitly/test_url.rb +0 -167
- data/test/bitly/test_utils.rb +0 -79
- data/test/fixtures/cnn.json +0 -1
- data/test/fixtures/cnn_and_google.json +0 -1
- data/test/fixtures/expand_cnn.json +0 -1
- data/test/fixtures/expand_cnn_and_google.json +0 -1
- data/test/fixtures/google_and_cnn_info.json +0 -1
- data/test/fixtures/google_info.json +0 -1
- data/test/fixtures/google_stats.json +0 -1
- data/test/fixtures/shorten_error.json +0 -1
- data/test/test_helper.rb +0 -39
data/lib/bitly/url.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
module Bitly
|
2
|
-
|
3
|
-
class Url
|
4
|
-
include Bitly::Utils
|
5
|
-
|
6
|
-
attr_accessor :long_url, :short_url, :hash, :user_hash
|
7
|
-
VARIABLES = ['long_url', 'short_url', 'hash', 'user_hash']
|
8
|
-
|
9
|
-
def initialize(login,api_key,obj=nil)
|
10
|
-
unless obj.nil?
|
11
|
-
raise BitlyError.new(obj['errorMessage'],obj['errorCode']) if obj['statusCode'] == "ERROR"
|
12
|
-
instance_variablise(obj, VARIABLES)
|
13
|
-
@info = obj.fetch(:info, nil)
|
14
|
-
@stats = obj.fetch(:stats, nil)
|
15
|
-
end
|
16
|
-
@login = login
|
17
|
-
@api_key = api_key
|
18
|
-
raise ArgumentError.new("Please provide a login and api_key") if @login.nil? || @api_key.nil?
|
19
|
-
end
|
20
|
-
|
21
|
-
def shorten(opts = {})
|
22
|
-
return @short_url if defined? @short_url
|
23
|
-
if defined? @long_url
|
24
|
-
request = create_url("shorten", :longUrl => @long_url, :history => (opts[:history] ? 1 : nil))
|
25
|
-
result = get_result(request)[@long_url.gsub(/\/$/,'')]
|
26
|
-
if result['statusCode'] == "ERROR"
|
27
|
-
raise BitlyError.new(result['errorMessage'],result['errorCode'])
|
28
|
-
else
|
29
|
-
instance_variablise(result,VARIABLES)
|
30
|
-
return @short_url
|
31
|
-
end
|
32
|
-
else
|
33
|
-
raise ArgumentError.new("You need a long_url in order to shorten it")
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def expand
|
38
|
-
return @long_url if defined? @long_url
|
39
|
-
unless !(short_url || hash)
|
40
|
-
unless defined? @hash
|
41
|
-
@hash = create_hash_from_url(@short_url)
|
42
|
-
end
|
43
|
-
request = create_url("expand", :hash => @hash)
|
44
|
-
result = get_result(request)[@hash]
|
45
|
-
if result['statusCode'] == "ERROR"
|
46
|
-
raise BitlyError.new(result['errorMessage'],result['errorCode'])
|
47
|
-
else
|
48
|
-
instance_variablise(result,VARIABLES)
|
49
|
-
return @long_url
|
50
|
-
end
|
51
|
-
else
|
52
|
-
raise ArgumentError.new("You need a short_url or a hash in order to expand it")
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def info
|
57
|
-
if @info.nil?
|
58
|
-
if defined? @hash
|
59
|
-
request = create_url "info", :hash => @hash
|
60
|
-
result = get_result(request)[@hash]
|
61
|
-
instance_variablise(result, VARIABLES)
|
62
|
-
@info = result
|
63
|
-
elsif defined? @short_url
|
64
|
-
@hash = create_hash_from_url(@short_url)
|
65
|
-
request = create_url "info", :hash => hash
|
66
|
-
result = get_result(request)[hash]
|
67
|
-
instance_variablise(result, VARIABLES)
|
68
|
-
@info = result
|
69
|
-
else
|
70
|
-
raise ArgumentError.new("You need a hash or short_url in order to get info")
|
71
|
-
end
|
72
|
-
return @info
|
73
|
-
else
|
74
|
-
@info
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def stats
|
79
|
-
if @stats.nil?
|
80
|
-
if defined? @hash
|
81
|
-
request = create_url "stats", :hash => @hash
|
82
|
-
elsif defined? @short_url
|
83
|
-
@hash = create_hash_from_url(@short_url)
|
84
|
-
request = create_url "stats", :hash => @hash
|
85
|
-
else
|
86
|
-
raise ArgumentError.new("You need a hash or short_url in order to get stats")
|
87
|
-
end
|
88
|
-
@stats = get_result(request)
|
89
|
-
else
|
90
|
-
@stats
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def bitly_url
|
95
|
-
@short_url.nil? ? nil : @short_url.gsub(/j\.mp/,'bit.ly')
|
96
|
-
end
|
97
|
-
|
98
|
-
def jmp_url
|
99
|
-
@short_url.nil? ? nil : @short_url.gsub(/bit\.ly/,'j.mp')
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|
data/lib/bitly/utils.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
|
3
|
-
module Bitly
|
4
|
-
module Utils
|
5
|
-
def underscore(camel_cased_word) # stolen from rails
|
6
|
-
camel_cased_word.to_s.gsub(/::/, '/').
|
7
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
8
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
9
|
-
tr("-", "_").
|
10
|
-
downcase
|
11
|
-
end
|
12
|
-
|
13
|
-
def create_hash_from_url(url)
|
14
|
-
url.gsub(/^.*(bit\.ly|j\.mp)\//,'')
|
15
|
-
end
|
16
|
-
|
17
|
-
def attr_define(k,v)
|
18
|
-
instance_variable_set("@#{k}", v)
|
19
|
-
end
|
20
|
-
|
21
|
-
def instance_variablise(obj,variables)
|
22
|
-
if obj.is_a? Hash
|
23
|
-
obj.each do |k,v|
|
24
|
-
if v.is_a? Hash
|
25
|
-
instance_variablise(v,variables)
|
26
|
-
else
|
27
|
-
attr_define(underscore(k),v) if variables.include?(underscore(k))
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def create_url(resource="",args={})
|
34
|
-
args = args.merge({:login => @login, :apiKey => @api_key, :version => API_VERSION})
|
35
|
-
url = URI.join(API_URL,resource)
|
36
|
-
long_urls = args.delete(:long_urls)
|
37
|
-
url.query = args.map { |k,v| "%s=%s" % [CGI.escape(k.to_s), CGI.escape(v.to_s)] }.join("&")
|
38
|
-
url.query << "&" + long_urls.map { |long_url| "longUrl=#{CGI.escape(long_url)}" }.join("&") unless long_urls.nil?
|
39
|
-
url
|
40
|
-
end
|
41
|
-
|
42
|
-
def get_result(request)
|
43
|
-
begin
|
44
|
-
json = Net::HTTP.get(request)
|
45
|
-
result = MultiJson.load(json)
|
46
|
-
rescue MultiJson::DecodeError
|
47
|
-
result = {'errorMessage' => 'JSON Parse Error(Bit.ly messed up)', 'errorCode' => 69, 'statusCode' => 'ERROR'}
|
48
|
-
end
|
49
|
-
if result['statusCode'] == "OK"
|
50
|
-
result = result['results']
|
51
|
-
else
|
52
|
-
raise BitlyError.new(result['errorMessage'],result['errorCode'])
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
end
|
57
|
-
end
|
data/lib/bitly/v3.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'httparty'
|
2
|
-
require 'cgi'
|
3
|
-
require 'oauth2'
|
4
|
-
|
5
|
-
require 'bitly/v3/bitly'
|
6
|
-
require 'bitly/v3/client'
|
7
|
-
require 'bitly/v3/url'
|
8
|
-
require 'bitly/v3/referrer'
|
9
|
-
require 'bitly/v3/day'
|
10
|
-
require 'bitly/v3/country'
|
11
|
-
require 'bitly/v3/missing_url'
|
12
|
-
require 'bitly/v3/realtime_link'
|
13
|
-
require 'bitly/v3/oauth'
|
14
|
-
require 'bitly/v3/user'
|
data/lib/bitly/v3/bitly.rb
DELETED
data/lib/bitly/v3/country.rb
DELETED
data/lib/bitly/v3/day.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
module Bitly
|
2
|
-
module V3
|
3
|
-
# Day objects are created by the clicks_by_day method of a url
|
4
|
-
class Day
|
5
|
-
attr_reader :clicks, :day_start
|
6
|
-
|
7
|
-
def initialize(opts)
|
8
|
-
@clicks = opts['clicks']
|
9
|
-
@day_start = Time.at(opts['day_start']) if opts['day_start']
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
data/lib/bitly/v3/missing_url.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
module Bitly
|
2
|
-
module V3
|
3
|
-
class MissingUrl
|
4
|
-
attr_accessor :short_url, :user_hash, :long_url, :error
|
5
|
-
def initialize(opts={})
|
6
|
-
if opts
|
7
|
-
@short_url = opts['short_url']
|
8
|
-
@user_hash = opts['hash']
|
9
|
-
@long_url = opts['long_url']
|
10
|
-
@error = opts['error']
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
data/lib/bitly/v3/oauth.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
module Bitly
|
2
|
-
module V3
|
3
|
-
# OAuth consumer for authentication
|
4
|
-
class OAuth
|
5
|
-
attr_reader :access_token
|
6
|
-
def initialize(consumer_token, consumer_secret)
|
7
|
-
@consumer_token, @consumer_secret = consumer_token, consumer_secret
|
8
|
-
end
|
9
|
-
|
10
|
-
# Get the OAuth 2 client
|
11
|
-
def client
|
12
|
-
@client ||= ::OAuth2::Client.new(
|
13
|
-
@consumer_token,
|
14
|
-
@consumer_secret,
|
15
|
-
:site => 'https://api-ssl.bitly.com',
|
16
|
-
:token_url => '/oauth/access_token'
|
17
|
-
)
|
18
|
-
end
|
19
|
-
|
20
|
-
# Get the url to redirect a user to, pass the url you want the user
|
21
|
-
# to be redirected back to.
|
22
|
-
def authorize_url(redirect_url, state=nil)
|
23
|
-
params = {:redirect_uri => redirect_url}
|
24
|
-
params[:state] = state if state
|
25
|
-
client.auth_code.authorize_url(params).gsub(/api-ssl\./,'')
|
26
|
-
end
|
27
|
-
|
28
|
-
# Get the access token. You must pass the exact same redirect_url passed
|
29
|
-
# to the authorize_url method
|
30
|
-
def get_access_token_from_code(code,redirect_url)
|
31
|
-
@access_token ||= client.auth_code.get_token(code, :redirect_uri => redirect_url, :parse => :query)
|
32
|
-
end
|
33
|
-
|
34
|
-
# If you already have a user token, this method gets the access token
|
35
|
-
def get_access_token_from_token(token, params={})
|
36
|
-
params = params.inject({}) { |options, (key, value)| options[key.to_s] = value; options }
|
37
|
-
@access_token ||= ::OAuth2::AccessToken.new(client, token, params)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Bitly
|
2
|
-
module V3
|
3
|
-
# Day objects are created by the realtime_links method of a user
|
4
|
-
class RealtimeLink
|
5
|
-
attr_reader :clicks, :user_hash
|
6
|
-
|
7
|
-
def initialize(opts)
|
8
|
-
@clicks = opts['clicks']
|
9
|
-
@user_hash = opts['user_hash']
|
10
|
-
end
|
11
|
-
|
12
|
-
# A convenience method to create a Bitly::Url from the data
|
13
|
-
def create_url(client)
|
14
|
-
Bitly::V3::Url.new(client, 'user_clicks' => clicks, 'user_hash' => user_hash)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/lib/bitly/v3/referrer.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
module Bitly
|
2
|
-
module V3
|
3
|
-
class Referrer
|
4
|
-
attr_reader :clicks, :referrer, :referrer_app, :url
|
5
|
-
|
6
|
-
def initialize(opts)
|
7
|
-
['clicks', 'referrer', 'referrer_app', 'url'].each do |attribute|
|
8
|
-
instance_variable_set("@#{attribute}".to_sym, opts[attribute])
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
data/lib/bitly/v3/url.rb
DELETED
@@ -1,154 +0,0 @@
|
|
1
|
-
module Bitly
|
2
|
-
module V3
|
3
|
-
# Url objects should only be created by the client object as it collects the correct information
|
4
|
-
# from the API.
|
5
|
-
class Url
|
6
|
-
attr_reader :short_url, :long_url, :user_hash, :global_hash, :aggregate_link
|
7
|
-
|
8
|
-
# Initialize with a bitly client and optional hash to fill in the details for the url.
|
9
|
-
def initialize(client, opts={})
|
10
|
-
@client = client
|
11
|
-
if opts
|
12
|
-
@short_url = opts['url'] || opts['short_url']
|
13
|
-
@long_url = opts['long_url']
|
14
|
-
@user_hash = opts['hash'] || opts['user_hash']
|
15
|
-
@global_hash = opts['global_hash']
|
16
|
-
@new_hash = (opts['new_hash'] == 1)
|
17
|
-
@user_clicks = opts['user_clicks']
|
18
|
-
@global_clicks = opts['global_clicks']
|
19
|
-
@title = opts['title']
|
20
|
-
@created_by = opts['created_by']
|
21
|
-
@created_at = Time.at opts['created_at'] if opts['created_at']
|
22
|
-
@aggregate_link = opts['aggregate_link']
|
23
|
-
@referrers = opts['referrers'].inject([]) do |results, referrer|
|
24
|
-
results << Bitly::V3::Referrer.new(referrer)
|
25
|
-
end if opts['referrers']
|
26
|
-
@countries = opts['countries'].inject([]) do |results, country|
|
27
|
-
results << Bitly::V3::Country.new(country)
|
28
|
-
end if opts['countries']
|
29
|
-
if opts['clicks'] && opts['clicks'][0].is_a?(Hash)
|
30
|
-
@clicks_by_day = opts['clicks'].inject([]) do |results, day|
|
31
|
-
results << Bitly::V3::Day.new(day)
|
32
|
-
end
|
33
|
-
else
|
34
|
-
@clicks_by_minute = opts['clicks']
|
35
|
-
end
|
36
|
-
end
|
37
|
-
@short_url = "http://bit.ly/#{@user_hash}" unless @short_url
|
38
|
-
end
|
39
|
-
|
40
|
-
# Returns true if the user hash was created first for this call
|
41
|
-
def new_hash?
|
42
|
-
@new_hash
|
43
|
-
end
|
44
|
-
|
45
|
-
# If the url already has click statistics, returns the user clicks.
|
46
|
-
# IF there are no click statistics or <tt>:force => true</tt> is passed,
|
47
|
-
# updates the stats and returns the user clicks
|
48
|
-
def user_clicks(opts={})
|
49
|
-
update_clicks_data if @global_clicks.nil? || opts[:force]
|
50
|
-
@user_clicks
|
51
|
-
end
|
52
|
-
|
53
|
-
# If the url already has click statistics, returns the global clicks.
|
54
|
-
# IF there are no click statistics or <tt>:force => true</tt> is passed,
|
55
|
-
# updates the stats and returns the global clicks
|
56
|
-
def global_clicks(opts={})
|
57
|
-
update_clicks_data if @global_clicks.nil? || opts[:force]
|
58
|
-
@global_clicks
|
59
|
-
end
|
60
|
-
|
61
|
-
# If the url already has the title, return it.
|
62
|
-
# IF there is no title or <tt>:force => true</tt> is passed,
|
63
|
-
# updates the info and returns the title
|
64
|
-
def title(opts={})
|
65
|
-
update_info if @title.nil? || opts[:force]
|
66
|
-
@title
|
67
|
-
end
|
68
|
-
|
69
|
-
# If the url already has the creator, return it.
|
70
|
-
# IF there is no creator or <tt>:force => true</tt> is passed,
|
71
|
-
# updates the info and returns the creator
|
72
|
-
def created_by(opts={})
|
73
|
-
update_info if @created_by.nil? || opts[:force]
|
74
|
-
@created_by
|
75
|
-
end
|
76
|
-
|
77
|
-
# If the url already has referrer data, return it.
|
78
|
-
# IF there is no referrer or <tt>:force => true</tt> is passed,
|
79
|
-
# updates the referrers and returns them
|
80
|
-
def referrers(opts={})
|
81
|
-
update_referrers if @referrers.nil? || opts[:force]
|
82
|
-
@referrers
|
83
|
-
end
|
84
|
-
|
85
|
-
# If the url already has country data, return it.
|
86
|
-
# IF there is no country or <tt>:force => true</tt> is passed,
|
87
|
-
# updates the countries and returns them
|
88
|
-
def countries(opts={})
|
89
|
-
update_countries if @countries.nil? || opts[:force]
|
90
|
-
@countries
|
91
|
-
end
|
92
|
-
|
93
|
-
# If the url already has created at data, return it.
|
94
|
-
# If there is no created at data or <tt>:force => true</tt> is passed,
|
95
|
-
# updates the info and returns it
|
96
|
-
def created_at(opts={})
|
97
|
-
update_info if @created_at.nil? || opts[:force]
|
98
|
-
@created_at
|
99
|
-
end
|
100
|
-
|
101
|
-
def clicks_by_minute(opts={})
|
102
|
-
if @clicks_by_minute.nil? || opts[:force]
|
103
|
-
full_url = @client.clicks_by_minute(@user_hash || @short_url)
|
104
|
-
@clicks_by_minute = full_url.clicks_by_minute
|
105
|
-
end
|
106
|
-
@clicks_by_minute
|
107
|
-
end
|
108
|
-
|
109
|
-
def clicks_by_day(opts={})
|
110
|
-
if @clicks_by_day.nil? || opts[:force]
|
111
|
-
full_url = @client.clicks_by_day(@user_hash || @short_url)
|
112
|
-
@clicks_by_day = full_url.clicks_by_day
|
113
|
-
end
|
114
|
-
@clicks_by_day
|
115
|
-
end
|
116
|
-
|
117
|
-
def jmp_url
|
118
|
-
@short_url.nil? ? nil : @short_url.gsub(/bit\.ly/,'j.mp')
|
119
|
-
end
|
120
|
-
|
121
|
-
# QR code is automatically created and can be incorporated
|
122
|
-
# into mobile applications.
|
123
|
-
def qrcode_url(opts={})
|
124
|
-
qrcode = opts.has_key?(:s) ? ".qrcode?s=#{opts[:s]}" : ".qrcode"
|
125
|
-
@short_url + qrcode
|
126
|
-
end
|
127
|
-
|
128
|
-
private
|
129
|
-
|
130
|
-
def update_clicks_data
|
131
|
-
full_url = @client.clicks(@user_hash || @short_url)
|
132
|
-
@global_clicks = full_url.global_clicks
|
133
|
-
@user_clicks = full_url.user_clicks
|
134
|
-
end
|
135
|
-
|
136
|
-
def update_info
|
137
|
-
full_url = @client.info(@user_hash || @short_url)
|
138
|
-
@created_by = full_url.created_by
|
139
|
-
@title = full_url.title
|
140
|
-
@created_at = full_url.created_at
|
141
|
-
end
|
142
|
-
|
143
|
-
def update_referrers
|
144
|
-
full_url = @client.referrers(@user_hash || @short_url)
|
145
|
-
@referrers = full_url.referrers
|
146
|
-
end
|
147
|
-
|
148
|
-
def update_countries
|
149
|
-
full_url = @client.countries(@user_hash || @short_url)
|
150
|
-
@countries = full_url.countries
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|