agilecrm-wrapper 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 926e3d0e0645d675a68fdec939471f5e3693b2f6
4
+ data.tar.gz: e295958f5c71c25e047de65096a77ce2d1c0f128
5
+ SHA512:
6
+ metadata.gz: 405466b4f3e9e937ef85c714da1615d1283ff213ad69bb471c2496082747f7509a5208eeeeb2ff3d7d4b1e4b0749119dd74ef53f5ffa15d63ad34b7a8216d353
7
+ data.tar.gz: 904226678f44055def597b3f0684e49500b7473367944cd577b1c30d587a00d144b44018bcc7bd3dfd862fdb47fcbf56851717f293fe9f38caeafd3f6961d7b7
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+ todo.txt
20
+ agile.js
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,9 @@
1
+ Style/Documentation:
2
+ Enabled: false
3
+
4
+ Style/RaiseArgs:
5
+ Enabled: false
6
+
7
+ Metrics/MethodLength:
8
+ CountComments: false
9
+ Max: 15
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in agilecrm-ruby-api.gemspec
4
+ gemspec
@@ -0,0 +1,89 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ agilecrm-wrapper (1.0.0)
5
+ faraday
6
+ faraday_middleware
7
+ hashie
8
+ json
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.3.6)
14
+ ast (2.0.0)
15
+ astrolabe (1.3.0)
16
+ parser (>= 2.2.0.pre.3, < 3.0)
17
+ awesome_print (1.2.0)
18
+ coderay (1.1.0)
19
+ crack (0.4.2)
20
+ safe_yaml (~> 1.0.0)
21
+ diff-lcs (1.2.5)
22
+ faraday (0.9.0)
23
+ multipart-post (>= 1.2, < 3)
24
+ faraday_middleware (0.9.1)
25
+ faraday (>= 0.7.4, < 0.10)
26
+ hashie (3.3.1)
27
+ json (1.8.1)
28
+ method_source (0.8.2)
29
+ multipart-post (2.0.0)
30
+ parser (2.2.0.pre.5)
31
+ ast (>= 1.1, < 3.0)
32
+ slop (~> 3.4, >= 3.4.5)
33
+ powerpack (0.0.9)
34
+ pry (0.10.1)
35
+ coderay (~> 1.1.0)
36
+ method_source (~> 0.8.1)
37
+ slop (~> 3.4)
38
+ rack (1.5.2)
39
+ rack-protection (1.5.3)
40
+ rack
41
+ rainbow (2.0.0)
42
+ rake (10.3.2)
43
+ rspec (3.1.0)
44
+ rspec-core (~> 3.1.0)
45
+ rspec-expectations (~> 3.1.0)
46
+ rspec-mocks (~> 3.1.0)
47
+ rspec-core (3.1.5)
48
+ rspec-support (~> 3.1.0)
49
+ rspec-expectations (3.1.2)
50
+ diff-lcs (>= 1.2.0, < 2.0)
51
+ rspec-support (~> 3.1.0)
52
+ rspec-its (1.0.1)
53
+ rspec-core (>= 2.99.0.beta1)
54
+ rspec-expectations (>= 2.99.0.beta1)
55
+ rspec-mocks (3.1.2)
56
+ rspec-support (~> 3.1.0)
57
+ rspec-support (3.1.1)
58
+ rubocop (0.26.1)
59
+ astrolabe (~> 1.3)
60
+ parser (>= 2.2.0.pre.4, < 3.0)
61
+ powerpack (~> 0.0.6)
62
+ rainbow (>= 1.99.1, < 3.0)
63
+ ruby-progressbar (~> 1.4)
64
+ ruby-progressbar (1.6.0)
65
+ safe_yaml (1.0.4)
66
+ sinatra (1.4.5)
67
+ rack (~> 1.4)
68
+ rack-protection (~> 1.4)
69
+ tilt (~> 1.3, >= 1.3.4)
70
+ slop (3.6.0)
71
+ tilt (1.4.1)
72
+ webmock (1.19.0)
73
+ addressable (>= 2.3.6)
74
+ crack (>= 0.3.2)
75
+
76
+ PLATFORMS
77
+ ruby
78
+
79
+ DEPENDENCIES
80
+ agilecrm-wrapper!
81
+ awesome_print
82
+ bundler (~> 1.6)
83
+ pry
84
+ rake
85
+ rspec
86
+ rspec-its
87
+ rubocop
88
+ sinatra
89
+ webmock
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Cogmation Robotics Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,119 @@
1
+ AgileCRMWrapper
2
+ =================
3
+
4
+ This project is a ruby client that wraps the [AgileCRM REST API](https://www.agilecrm.com/api/rest). **Note: This is not an official project, you're welcome to use it but don't expect the AgileCRM team to support it.**
5
+
6
+ At present, only operations related to the **contact** and **note** resources are supported. Need something added? Make a feature request in the issues tab. Pull requests are always welcome.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'agilecrm-wrapper'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ # Usage
19
+
20
+ To begin using this gem, Initialize the library using a configuration block including your agile **API key**, **email**, and **domain**, like this:
21
+
22
+ ```ruby
23
+ AgileCRMWrapper.configure do |config|
24
+ config.api_key = 'XXXXXXXXXXX'
25
+ config.domain = 'my-agile-domain'
26
+ config.email = 'myemail@example.com'
27
+ end
28
+ ```
29
+
30
+ ### 1. Working with Contacts
31
+
32
+ **GET** operations return one or more `AgileCRMWrapper::Contact` objects. These are just `Hashie::Mash` objects with a few utility methods sprinkled on. You can access any of the Contact fields returned by AgileCRM's REST API, see [here](https://www.agilecrm.com/api/rest#contact-fields) for what that entails. Example:
33
+ ```ruby
34
+ contact = AgileCRMWrapper::Contact.find(123)
35
+ contact.tags #=> ["tag", "your", "it"]
36
+ contact.id #=> 123
37
+ contact.properties #=> [{ type: 'SYSTEM', name: "email", value: "blah@mail.com" }]
38
+ ```
39
+
40
+ ###### To retrieve a list of contacts
41
+ ```ruby
42
+ AgileCRMWrapper::Contact.all
43
+ ```
44
+
45
+ ###### To get an individual contact by ID
46
+ ```ruby
47
+ AgileCRMWrapper::Contact.find(123)
48
+ ```
49
+
50
+ ###### To find contacts by email
51
+ ```ruby
52
+ contact = AgileCRMWrapper::Contact.search_by_email("foo@example.com")
53
+ # or pass multiple emails as seperate arguments or an array
54
+ contacts = AgileCRMWrapper::Contact.search_by_email(
55
+ "foo@example.com", "bar@example.com"
56
+ )
57
+ ```
58
+
59
+ ###### To create a new contact
60
+ ```ruby
61
+ AgileCRMWrapper::Contact.create(
62
+ tags: ["tag", "your", "it"],
63
+ first_name: "Justin",
64
+ last_name: "Case",
65
+ email: "blah@mail.com",
66
+ my_custom_field: "im a custom field!"
67
+ )
68
+ ```
69
+
70
+ ###### To update a single contact
71
+ ```ruby
72
+ contact.update(first_name: "Foo", last_name: "Bar", tags: ["new_tag"])
73
+ ```
74
+
75
+ Note, tags specified in `update` will simply be added to the existing list of tags.
76
+
77
+ ###### To delete a single contact
78
+ ```ruby
79
+ # perform operation directly
80
+ AgileCRMWrapper::Contact.delete(123)
81
+ # or
82
+ AgileCRMWrapper::Contact.find(123).destroy
83
+ ```
84
+
85
+ ###### Convenient access to properties hash values
86
+ ```ruby
87
+ contact.get_property("email") #=> "blah@mail.com"
88
+ contact.get_propety("my_custom_field") #=> "im a custom field!"
89
+ contact.get_property("unkown_attribute") #=> nil
90
+ ```
91
+
92
+ ### 2. Working with Notes
93
+
94
+ ###### To create a new note
95
+ ```ruby
96
+ AgileCRMWrapper::Note.create(
97
+ subject: "My Note",
98
+ description: "My notes's description.",
99
+ contact_ids: ["123"]
100
+ )
101
+ ```
102
+
103
+ ###### To add a Note to a Contact using Email-ID
104
+ ```ruby
105
+ AgileCRMWrapper::Note.add_by_email(
106
+ email: "blah@mail.com",
107
+ subject: "My Note",
108
+ description: "My notes's description."
109
+ )
110
+ ```
111
+
112
+
113
+ ## Contributing
114
+
115
+ 1. Fork it ( https://github.com/nozpheratu/agilecrm-wrapper/fork )
116
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
117
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
118
+ 4. Push to the branch (`git push origin my-new-feature`)
119
+ 5. Create a new Pull Request
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
7
+
8
+ task :console do
9
+ exec 'pry -r agilecrm-wrapper -I ./lib'
10
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'agilecrm-wrapper/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'agilecrm-wrapper'
8
+ spec.version = AgileCRMWrapper::VERSION
9
+ spec.authors = ['Cyle']
10
+ spec.email = ['cylehunter33@gmail.com']
11
+ spec.summary = 'Ruby wrapper for Agile CRM API.'
12
+ spec.description = 'Ruby wrapper for Agile CRM API.'
13
+ spec.homepage = 'https://github.com/nozpheratu/agilecrm-wrapper'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(/^bin/) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(/^(test|spec|features)/)
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_dependency 'faraday'
22
+ spec.add_dependency 'faraday_middleware'
23
+ spec.add_dependency 'hashie'
24
+ spec.add_dependency 'json'
25
+
26
+ spec.add_development_dependency 'rubocop'
27
+ spec.add_development_dependency 'bundler', '~> 1.6'
28
+ spec.add_development_dependency 'rake'
29
+ spec.add_development_dependency 'rspec'
30
+ spec.add_development_dependency 'pry'
31
+ spec.add_development_dependency 'webmock'
32
+ spec.add_development_dependency 'rspec-its'
33
+ spec.add_development_dependency 'awesome_print'
34
+ spec.add_development_dependency 'sinatra'
35
+ end
@@ -0,0 +1,47 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'json'
4
+ require 'agilecrm-wrapper/version'
5
+ require 'agilecrm-wrapper/configuration'
6
+ require 'agilecrm-wrapper/contact'
7
+ require 'agilecrm-wrapper/note'
8
+ require 'agilecrm-wrapper/response/raise_error'
9
+
10
+ module AgileCRMWrapper
11
+ class << self
12
+ attr_accessor :configuration
13
+
14
+ def configuration
15
+ @configuration ||= Configuration.new
16
+ end
17
+
18
+ def reset
19
+ @configuration = Configuration.new
20
+ end
21
+
22
+ def configure
23
+ yield(configuration)
24
+ end
25
+
26
+ def endpoint
27
+ "https://#{configuration.domain}.agilecrm.com/dev/api"
28
+ end
29
+
30
+ def connection
31
+ @connection ||= default_connection
32
+ end
33
+
34
+ def default_connection
35
+ options = {
36
+ headers: { 'Accept' => 'application/json' }
37
+ }
38
+ Faraday.new(endpoint, options) do |conn|
39
+ conn.request(:json)
40
+ conn.request(:basic_auth, configuration.email, configuration.api_key)
41
+ conn.response(:json, content_type: /\bjson$/)
42
+ conn.response(:agilecrm_error)
43
+ conn.adapter(Faraday.default_adapter)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,11 @@
1
+ module AgileCRMWrapper
2
+ class Configuration
3
+ attr_accessor :domain, :api_key, :email
4
+
5
+ def initialize
6
+ @domain = ''
7
+ @api_key = ''
8
+ @email = ''
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,119 @@
1
+ require 'agilecrm-wrapper/error'
2
+ require 'hashie'
3
+
4
+ module AgileCRMWrapper
5
+ class Contact < Hashie::Mash
6
+ SYSTEM_PROPERTIES = %w(first_name last_name company title email)
7
+ CONTACT_FIELDS = %w(id type tags lead_score star_value)
8
+
9
+ class << self
10
+ def all
11
+ response = AgileCRMWrapper.connection.get('contacts')
12
+ if response.status == 200
13
+ return response.body.map { |body| new body }
14
+ else
15
+ return response
16
+ end
17
+ end
18
+
19
+ def find(id)
20
+ response = AgileCRMWrapper.connection.get("contacts/#{id}")
21
+ if response.status == 200
22
+ new(response.body)
23
+ elsif response.status == 204
24
+ fail(AgileCRMWrapper::NotFound.new(response))
25
+ end
26
+ end
27
+
28
+ def search_by_email(*emails)
29
+ emails = emails.flatten.compact.uniq
30
+ response = AgileCRMWrapper.connection.post(
31
+ 'contacts/search/email', "email_ids=#{emails}",
32
+ 'content-type' => 'application/x-www-form-urlencoded'
33
+ )
34
+ if response.body.size > 1
35
+ response.body.reject(&:nil?).map { |body| new body }
36
+ else
37
+ res = new(response.body.first)
38
+ res.empty? ? nil : res
39
+ end
40
+ end
41
+
42
+ def create(options = {})
43
+ payload = parse_contact_fields(options)
44
+ AgileCRMWrapper.connection.post('contacts', payload)
45
+ end
46
+
47
+ def delete(arg)
48
+ AgileCRMWrapper.connection.delete("contacts/#{arg}")
49
+ end
50
+
51
+ def parse_contact_fields(options)
52
+ payload = { 'properties' => [] }
53
+ options.each do |key, value|
54
+ if contact_field?(key)
55
+ payload[key.to_s] = value
56
+ else
57
+ payload['properties'] << parse_property(key, value)
58
+ end
59
+ end
60
+ payload
61
+ end
62
+
63
+ private
64
+
65
+ def parse_property(key, value)
66
+ if system_propety?(key)
67
+ { 'type' => 'SYSTEM', 'name' => key.to_s, 'value' => value }
68
+ else
69
+ { 'type' => 'CUSTOM', 'name' => key.to_s, 'value' => value }
70
+ end
71
+ end
72
+
73
+ def system_propety?(key)
74
+ SYSTEM_PROPERTIES.include?(key.to_s)
75
+ end
76
+
77
+ def contact_field?(key)
78
+ CONTACT_FIELDS.include?(key.to_s)
79
+ end
80
+ end
81
+
82
+ def destroy
83
+ self.class.delete(id)
84
+ end
85
+
86
+ def notes
87
+ response = AgileCRMWrapper.connection.get("contacts/#{id}/notes")
88
+ response.body.map { |note| AgileCRMWrapper::Note.new(note) }
89
+ end
90
+
91
+ def update(options = {})
92
+ payload = self.class.parse_contact_fields(options)
93
+ payload['properties'] = merge_properties(payload['properties'])
94
+ merge!(payload)
95
+ response = AgileCRMWrapper.connection.put('contacts', self)
96
+ merge!(response.body)
97
+ end
98
+
99
+ def get_property(property_name)
100
+ return unless respond_to?(:properties)
101
+ prop = properties.select { |a| a['name'] == property_name.to_s }
102
+ OpenStruct.new(*prop).value
103
+ end
104
+
105
+ private
106
+
107
+ def merge_properties(new_properties)
108
+ properties.map do |h|
109
+ new_properties.delete_if do |h2|
110
+ if h['name'] == h2['name']
111
+ h['value'] = h2['value']
112
+ true
113
+ end
114
+ end
115
+ h
116
+ end + new_properties
117
+ end
118
+ end
119
+ end