hubspot-ruby 0.1.2 → 0.1.3
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 +7 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +37 -2
- data/Guardfile +9 -0
- data/Rakefile +1 -1
- data/hubspot-ruby.gemspec +26 -6
- data/lib/hubspot-ruby.rb +3 -1
- data/lib/hubspot/blog.rb +133 -0
- data/lib/hubspot/contact.rb +1 -1
- data/lib/hubspot/topic.rb +53 -0
- data/lib/hubspot/utils.rb +22 -2
- data/lib/hubspot/version.rb +2 -2
- data/spec/fixtures/vcr_cassettes/blog_list.yml +180 -0
- data/spec/fixtures/vcr_cassettes/blog_posts.yml +107 -0
- data/spec/fixtures/vcr_cassettes/blog_posts_list.yml +6463 -0
- data/spec/fixtures/vcr_cassettes/form_post.yml +31 -0
- data/spec/fixtures/vcr_cassettes/one_month_blog_posts_filter_state.yml +11243 -0
- data/spec/fixtures/vcr_cassettes/one_month_blog_posts_list.yml +34963 -0
- data/spec/fixtures/vcr_cassettes/topic_list.yml +48 -0
- data/spec/fixtures/vcr_cassettes/topics_list.yml +86 -0
- data/spec/lib/hubspot/blog_spec.rb +114 -0
- data/spec/lib/hubspot/topic_spec.rb +26 -0
- data/spec/lib/hubspot/utils_spec.rb +13 -0
- metadata +73 -59
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d569b6dba8fd40bb8ab265cdd39642c2051f3d23
|
4
|
+
data.tar.gz: ddc2d7586ac345b9f8bcbf7b0e43e13e1eaba2f8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 96b6ac6cfee35ba8850562928fc598c34c37b0eceed5110376b7bcfc25263c2cdd8a0e4198354512468a17934b3a11c1c07d794718dc8c21ea472e9c75be8d24
|
7
|
+
data.tar.gz: ed7de706aa07a1752d0048cdcb28df121f237e51d5c4897f39e7dddcdbdb37b6143afd73a61483a5812e04a10ea471626db14f119e31eb6669cbc8bb556ad1ef
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -6,9 +6,24 @@ GEM
|
|
6
6
|
multi_json (~> 1.0)
|
7
7
|
addressable (2.3.3)
|
8
8
|
awesome_print (1.1.0)
|
9
|
+
celluloid (0.16.0)
|
10
|
+
timers (~> 4.0.0)
|
11
|
+
coderay (1.1.0)
|
9
12
|
crack (0.3.2)
|
10
13
|
diff-lcs (1.2.1)
|
14
|
+
ffi (1.9.6)
|
15
|
+
formatador (0.2.5)
|
11
16
|
git (1.2.5)
|
17
|
+
guard (2.6.1)
|
18
|
+
formatador (>= 0.2.4)
|
19
|
+
listen (~> 2.7)
|
20
|
+
lumberjack (~> 1.0)
|
21
|
+
pry (>= 0.9.12)
|
22
|
+
thor (>= 0.18.1)
|
23
|
+
guard-rspec (3.1.0)
|
24
|
+
guard (>= 1.8)
|
25
|
+
rspec (~> 2.13)
|
26
|
+
hitimes (1.2.2)
|
12
27
|
httparty (0.10.2)
|
13
28
|
multi_json (~> 1.0)
|
14
29
|
multi_xml (>= 0.5.2)
|
@@ -19,9 +34,22 @@ GEM
|
|
19
34
|
rake
|
20
35
|
rdoc
|
21
36
|
json (1.7.7)
|
37
|
+
listen (2.7.11)
|
38
|
+
celluloid (>= 0.15.2)
|
39
|
+
rb-fsevent (>= 0.9.3)
|
40
|
+
rb-inotify (>= 0.9)
|
41
|
+
lumberjack (1.0.9)
|
42
|
+
method_source (0.8.2)
|
22
43
|
multi_json (1.6.1)
|
23
44
|
multi_xml (0.5.3)
|
45
|
+
pry (0.10.1)
|
46
|
+
coderay (~> 1.1.0)
|
47
|
+
method_source (~> 0.8.1)
|
48
|
+
slop (~> 3.4)
|
24
49
|
rake (10.0.3)
|
50
|
+
rb-fsevent (0.9.4)
|
51
|
+
rb-inotify (0.9.5)
|
52
|
+
ffi (>= 0.5.0)
|
25
53
|
rdoc (4.0.0)
|
26
54
|
json (~> 1.4)
|
27
55
|
rr (1.0.4)
|
@@ -29,7 +57,7 @@ GEM
|
|
29
57
|
rspec-core (~> 2.13.0)
|
30
58
|
rspec-expectations (~> 2.13.0)
|
31
59
|
rspec-mocks (~> 2.13.0)
|
32
|
-
rspec-core (2.13.
|
60
|
+
rspec-core (2.13.1)
|
33
61
|
rspec-expectations (2.13.0)
|
34
62
|
diff-lcs (>= 1.1.3, < 2.0)
|
35
63
|
rspec-mocks (2.13.0)
|
@@ -37,8 +65,13 @@ GEM
|
|
37
65
|
multi_json (~> 1.0)
|
38
66
|
simplecov-html (~> 0.7.1)
|
39
67
|
simplecov-html (0.7.1)
|
68
|
+
slop (3.6.0)
|
69
|
+
thor (0.19.1)
|
70
|
+
timecop (0.7.1)
|
71
|
+
timers (4.0.1)
|
72
|
+
hitimes
|
40
73
|
vcr (2.4.0)
|
41
|
-
webmock (1.
|
74
|
+
webmock (1.11.0)
|
42
75
|
addressable (>= 2.2.7)
|
43
76
|
crack (>= 0.3.2)
|
44
77
|
|
@@ -49,11 +82,13 @@ DEPENDENCIES
|
|
49
82
|
activesupport (>= 3.0.0)
|
50
83
|
awesome_print
|
51
84
|
bundler
|
85
|
+
guard-rspec
|
52
86
|
httparty (>= 0.10.0)
|
53
87
|
jeweler
|
54
88
|
rdoc
|
55
89
|
rr
|
56
90
|
rspec
|
57
91
|
simplecov
|
92
|
+
timecop
|
58
93
|
vcr
|
59
94
|
webmock
|
data/Guardfile
ADDED
data/Rakefile
CHANGED
@@ -20,7 +20,7 @@ Jeweler::Tasks.new do |gem|
|
|
20
20
|
#gem.license = "MIT"
|
21
21
|
gem.summary = %Q{hubspot-ruby is a wrapper for the HubSpot REST API}
|
22
22
|
gem.description = %Q{hubspot-ruby is a wrapper for the HubSpot REST API}
|
23
|
-
gem.email = "
|
23
|
+
gem.email = "hello@omadahealth.com"
|
24
24
|
gem.authors = ["Andrew DiMichele"]
|
25
25
|
gem.version = Hubspot::Version::STRING
|
26
26
|
|
data/hubspot-ruby.gemspec
CHANGED
@@ -2,16 +2,18 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: hubspot-ruby 0.1.3 ruby lib
|
5
6
|
|
6
7
|
Gem::Specification.new do |s|
|
7
8
|
s.name = "hubspot-ruby"
|
8
|
-
s.version = "0.1.
|
9
|
+
s.version = "0.1.3"
|
9
10
|
|
10
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib"]
|
11
13
|
s.authors = ["Andrew DiMichele"]
|
12
|
-
s.date = "
|
14
|
+
s.date = "2014-10-27"
|
13
15
|
s.description = "hubspot-ruby is a wrapper for the HubSpot REST API"
|
14
|
-
s.email = "
|
16
|
+
s.email = "hello@omadahealth.com"
|
15
17
|
s.extra_rdoc_files = [
|
16
18
|
"LICENSE.txt",
|
17
19
|
"README.md"
|
@@ -21,17 +23,23 @@ Gem::Specification.new do |s|
|
|
21
23
|
".rspec",
|
22
24
|
"Gemfile",
|
23
25
|
"Gemfile.lock",
|
26
|
+
"Guardfile",
|
24
27
|
"LICENSE.txt",
|
25
28
|
"README.md",
|
26
29
|
"Rakefile",
|
27
30
|
"hubspot-ruby.gemspec",
|
28
31
|
"lib/hubspot-ruby.rb",
|
32
|
+
"lib/hubspot/blog.rb",
|
29
33
|
"lib/hubspot/config.rb",
|
30
34
|
"lib/hubspot/contact.rb",
|
31
35
|
"lib/hubspot/exceptions.rb",
|
32
36
|
"lib/hubspot/form.rb",
|
37
|
+
"lib/hubspot/topic.rb",
|
33
38
|
"lib/hubspot/utils.rb",
|
34
39
|
"lib/hubspot/version.rb",
|
40
|
+
"spec/fixtures/vcr_cassettes/blog_list.yml",
|
41
|
+
"spec/fixtures/vcr_cassettes/blog_posts.yml",
|
42
|
+
"spec/fixtures/vcr_cassettes/blog_posts_list.yml",
|
35
43
|
"spec/fixtures/vcr_cassettes/contact_create.yml",
|
36
44
|
"spec/fixtures/vcr_cassettes/contact_create_existing_email.yml",
|
37
45
|
"spec/fixtures/vcr_cassettes/contact_create_invalid_email.yml",
|
@@ -42,22 +50,28 @@ Gem::Specification.new do |s|
|
|
42
50
|
"spec/fixtures/vcr_cassettes/contact_find_by_id.yml",
|
43
51
|
"spec/fixtures/vcr_cassettes/contact_find_by_utk.yml",
|
44
52
|
"spec/fixtures/vcr_cassettes/contact_update.yml",
|
53
|
+
"spec/fixtures/vcr_cassettes/form_post.yml",
|
54
|
+
"spec/fixtures/vcr_cassettes/one_month_blog_posts_filter_state.yml",
|
55
|
+
"spec/fixtures/vcr_cassettes/one_month_blog_posts_list.yml",
|
56
|
+
"spec/fixtures/vcr_cassettes/topic_list.yml",
|
57
|
+
"spec/fixtures/vcr_cassettes/topics_list.yml",
|
45
58
|
"spec/lib/hubspot-ruby_spec.rb",
|
59
|
+
"spec/lib/hubspot/blog_spec.rb",
|
46
60
|
"spec/lib/hubspot/config_spec.rb",
|
47
61
|
"spec/lib/hubspot/contact_spec.rb",
|
48
62
|
"spec/lib/hubspot/form_spec.rb",
|
63
|
+
"spec/lib/hubspot/topic_spec.rb",
|
49
64
|
"spec/lib/hubspot/utils_spec.rb",
|
50
65
|
"spec/live/contacts_integration_spec.rb",
|
51
66
|
"spec/spec_helper.rb",
|
52
67
|
"spec/support/cassette_helper.rb"
|
53
68
|
]
|
54
69
|
s.homepage = "http://github.com/omadahealth/hubspot-ruby"
|
55
|
-
s.
|
56
|
-
s.rubygems_version = "1.8.25"
|
70
|
+
s.rubygems_version = "2.2.2"
|
57
71
|
s.summary = "hubspot-ruby is a wrapper for the HubSpot REST API"
|
58
72
|
|
59
73
|
if s.respond_to? :specification_version then
|
60
|
-
s.specification_version =
|
74
|
+
s.specification_version = 4
|
61
75
|
|
62
76
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
63
77
|
s.add_runtime_dependency(%q<activesupport>, [">= 3.0.0"])
|
@@ -71,6 +85,8 @@ Gem::Specification.new do |s|
|
|
71
85
|
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
72
86
|
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
73
87
|
s.add_development_dependency(%q<awesome_print>, [">= 0"])
|
88
|
+
s.add_development_dependency(%q<timecop>, [">= 0"])
|
89
|
+
s.add_development_dependency(%q<guard-rspec>, [">= 0"])
|
74
90
|
else
|
75
91
|
s.add_dependency(%q<activesupport>, [">= 3.0.0"])
|
76
92
|
s.add_dependency(%q<httparty>, [">= 0.10.0"])
|
@@ -83,6 +99,8 @@ Gem::Specification.new do |s|
|
|
83
99
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
84
100
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
85
101
|
s.add_dependency(%q<awesome_print>, [">= 0"])
|
102
|
+
s.add_dependency(%q<timecop>, [">= 0"])
|
103
|
+
s.add_dependency(%q<guard-rspec>, [">= 0"])
|
86
104
|
end
|
87
105
|
else
|
88
106
|
s.add_dependency(%q<activesupport>, [">= 3.0.0"])
|
@@ -96,6 +114,8 @@ Gem::Specification.new do |s|
|
|
96
114
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
97
115
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
98
116
|
s.add_dependency(%q<awesome_print>, [">= 0"])
|
117
|
+
s.add_dependency(%q<timecop>, [">= 0"])
|
118
|
+
s.add_dependency(%q<guard-rspec>, [">= 0"])
|
99
119
|
end
|
100
120
|
end
|
101
121
|
|
data/lib/hubspot-ruby.rb
CHANGED
@@ -4,9 +4,11 @@ require 'hubspot/exceptions'
|
|
4
4
|
require 'hubspot/config'
|
5
5
|
require 'hubspot/contact'
|
6
6
|
require 'hubspot/form'
|
7
|
+
require 'hubspot/blog'
|
8
|
+
require 'hubspot/topic'
|
7
9
|
|
8
10
|
module Hubspot
|
9
11
|
def self.configure(config={})
|
10
12
|
Hubspot::Config.configure(config)
|
11
13
|
end
|
12
|
-
end
|
14
|
+
end
|
data/lib/hubspot/blog.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'hubspot/utils'
|
2
|
+
require 'httparty'
|
3
|
+
|
4
|
+
module Hubspot
|
5
|
+
#
|
6
|
+
# HubSpot Contacts API
|
7
|
+
#
|
8
|
+
# {https://developers.hubspot.com/docs/endpoints#contacts-api}
|
9
|
+
#
|
10
|
+
class Blog
|
11
|
+
class InvalidParams < StandardError
|
12
|
+
end
|
13
|
+
|
14
|
+
BLOG_LIST_PATH = "/content/api/v2/blogs"
|
15
|
+
BLOG_POSTS_PATH = "/content/api/v2/blog-posts"
|
16
|
+
GET_BLOG_BY_ID_PATH = "/content/api/v2/blogs/:blog_id"
|
17
|
+
|
18
|
+
class << self
|
19
|
+
# Lists the blogs
|
20
|
+
# {https://developers.hubspot.com/docs/methods/blogv2/get_blogs}
|
21
|
+
# No param filtering is currently implemented
|
22
|
+
# @return [Hubspot::Blog, []] the first 20 blogs or empty_array
|
23
|
+
def list
|
24
|
+
url = Hubspot::Utils.generate_url(BLOG_LIST_PATH)
|
25
|
+
resp = HTTParty.get(url, format: :json)
|
26
|
+
if resp.success?
|
27
|
+
resp.parsed_response['objects'].map do |blog_hash|
|
28
|
+
Blog.new(blog_hash)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
[]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Finds a specific blog by its ID
|
36
|
+
# {https://developers.hubspot.com/docs/methods/blogv2/get_blogs_blog_id}
|
37
|
+
# @return Hubspot::Blog or nil
|
38
|
+
def find_by_id(id)
|
39
|
+
url = Hubspot::Utils.generate_url(GET_BLOG_BY_ID_PATH, blog_id: id)
|
40
|
+
resp = HTTParty.get(url, format: :json)
|
41
|
+
if resp.success?
|
42
|
+
Blog.new(resp.parsed_response)
|
43
|
+
else
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
attr_reader :properties
|
50
|
+
|
51
|
+
def initialize(response_hash)
|
52
|
+
@properties = response_hash #no need to parse anything, we have properties
|
53
|
+
end
|
54
|
+
|
55
|
+
def [](property)
|
56
|
+
@properties[property]
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
# Returns the posts for this blog instance.
|
61
|
+
# defaults to returning the last 2 months worth of published blog posts
|
62
|
+
# in date descending order (i.e. most recent first)
|
63
|
+
# {https://developers.hubspot.com/docs/methods/blogv2/get_blog_posts}
|
64
|
+
# @return [Hubspot::BlogPost] or []
|
65
|
+
def posts(params = {})
|
66
|
+
default_params = {
|
67
|
+
content_group_id: self["id"],
|
68
|
+
order_by: '-created',
|
69
|
+
created__gt: Time.now - 2.month,
|
70
|
+
state: 'PUBLISHED'
|
71
|
+
}
|
72
|
+
raise InvalidParams.new('params must be passed as a hash') unless params.is_a?(Hash)
|
73
|
+
params = default_params.merge(params)
|
74
|
+
|
75
|
+
raise InvalidParams.new('State parameter was invalid') unless [false, 'PUBLISHED', 'DRAFT'].include?(params[:state])
|
76
|
+
params.each { |k, v| params.delete(k) if v == false }
|
77
|
+
|
78
|
+
url = Hubspot::Utils.generate_url(BLOG_POSTS_PATH, params)
|
79
|
+
|
80
|
+
resp = HTTParty.get(url, format: :json)
|
81
|
+
if resp.success?
|
82
|
+
blog_post_objects = resp.parsed_response['objects']
|
83
|
+
blog_post_objects.map do |blog_post_hash|
|
84
|
+
BlogPost.new(blog_post_hash)
|
85
|
+
end
|
86
|
+
else
|
87
|
+
[]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class BlogPost
|
93
|
+
GET_BLOG_POST_BY_ID_PATH = "/content/api/v2/blog-posts/:blog_post_id"
|
94
|
+
|
95
|
+
# Returns a specific blog post by ID
|
96
|
+
# {https://developers.hubspot.com/docs/methods/blogv2/get_blog_posts_blog_post_id}
|
97
|
+
# @return [Hubspot::BlogPost] or nil
|
98
|
+
def self.find_by_blog_post_id(id)
|
99
|
+
url = Hubspot::Utils.generate_url(GET_BLOG_POST_BY_ID_PATH, blog_post_id: id)
|
100
|
+
resp = HTTParty.get(url, format: :json)
|
101
|
+
if resp.success?
|
102
|
+
BlogPost.new(resp.parsed_response)
|
103
|
+
else
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def initialize(response_hash)
|
109
|
+
@properties = response_hash #no need to parse anything, we have properties
|
110
|
+
end
|
111
|
+
|
112
|
+
def [](property)
|
113
|
+
@properties[property]
|
114
|
+
end
|
115
|
+
|
116
|
+
def created_at
|
117
|
+
Time.at(@properties['created'] / 1000)
|
118
|
+
end
|
119
|
+
|
120
|
+
def topics
|
121
|
+
@topics ||= begin
|
122
|
+
if @properties['topic_ids'].empty?
|
123
|
+
[]
|
124
|
+
else
|
125
|
+
@properties['topic_ids'].map do |topic_id|
|
126
|
+
Hubspot::Topic.find_by_topic_id(topic_id)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
data/lib/hubspot/contact.rb
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'hubspot/utils'
|
2
|
+
require 'httparty'
|
3
|
+
|
4
|
+
module Hubspot
|
5
|
+
#
|
6
|
+
# HubSpot Topics API
|
7
|
+
#
|
8
|
+
class Topic
|
9
|
+
TOPIC_LIST_PATH = "/content/api/v2/topics"
|
10
|
+
GET_TOPIC_BY_ID_PATH = "/content/api/v2/topics/:topic_id"
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# Lists the topics
|
14
|
+
# {https://developers.hubspot.com/docs/methods/blogv2/get_topics)
|
15
|
+
# @return [Hubspot::Topic, []] array of topics or empty_array
|
16
|
+
def list
|
17
|
+
url = Hubspot::Utils.generate_url(TOPIC_LIST_PATH)
|
18
|
+
resp = HTTParty.get(url, format: :json)
|
19
|
+
if resp.success?
|
20
|
+
resp.parsed_response['objects'].map do |topic_hash|
|
21
|
+
Topic.new(topic_hash)
|
22
|
+
end
|
23
|
+
else
|
24
|
+
[]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Finds the details for a specific topic_id
|
29
|
+
# {https://developers.hubspot.com/docs/methods/blogv2/get_topics_topic_id }
|
30
|
+
# @return Hubspot::Topic or nil
|
31
|
+
|
32
|
+
def find_by_topic_id(id)
|
33
|
+
url = Hubspot::Utils.generate_url(GET_TOPIC_BY_ID_PATH, topic_id: id)
|
34
|
+
resp = HTTParty.get(url, format: :json)
|
35
|
+
if resp.success?
|
36
|
+
Topic.new(resp.parsed_response)
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_reader :properties
|
44
|
+
|
45
|
+
def initialize(response_hash)
|
46
|
+
@properties = response_hash #no need to parse anything, we have properties
|
47
|
+
end
|
48
|
+
|
49
|
+
def [](property)
|
50
|
+
@properties[property]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/hubspot/utils.rb
CHANGED
@@ -39,10 +39,30 @@ module Hubspot
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
raise(Hubspot::MissingInterpolation.new("Interpolation not resolved")) if path =~ /:/
|
42
|
-
query = params.map{ |k,v|
|
42
|
+
query = params.map{ |k,v| param_string(k,v) }.join("&")
|
43
43
|
path += "?" if query.present?
|
44
44
|
base_url + path + query
|
45
45
|
end
|
46
|
+
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def converted_value(value)
|
51
|
+
if (value.is_a?(Time))
|
52
|
+
(value.to_i * 1000) # convert into milliseconds since epoch
|
53
|
+
else
|
54
|
+
value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def param_string(key,value)
|
59
|
+
if (key =~ /range/)
|
60
|
+
raise "Value must be a range" unless value.is_a?(Range)
|
61
|
+
"#{key}=#{converted_value(value.begin)}&#{key}=#{converted_value(value.end)}"
|
62
|
+
else
|
63
|
+
"#{key}=#{converted_value(value)}"
|
64
|
+
end
|
65
|
+
end
|
46
66
|
end
|
47
67
|
end
|
48
|
-
end
|
68
|
+
end
|