freshsales 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b588a2ecb49dd8ab5de0d2c2e43d3f45ca6048e9
4
+ data.tar.gz: 531664c1425cfc9b14ea3eaaafb0a7b0ed1ceba3
5
+ SHA512:
6
+ metadata.gz: db59e03d374712a35b2fdf5d539c887864b326029c4930527d4cc03ea7e49dda72411084eb38615ffe2a58c1e6b191188bb0111c25c064735a5aea756b333313
7
+ data.tar.gz: db23ff551d53a5c1d74d19da05d97cb3ca4590881f79a5cb1019e68b6a27a8ab650dd8e7a6a3082ebd63a0116bdeb1d5bb4ca75b2f8d8fb628b4622a9d993162
@@ -0,0 +1,54 @@
1
+ # Ruby CircleCI 2.0 configuration file
2
+ #
3
+ # Check https://circleci.com/docs/2.0/language-ruby/ for more details
4
+ #
5
+ version: 2
6
+ jobs:
7
+ build:
8
+ docker:
9
+ # specify the version you desire here
10
+ - image: circleci/ruby:2.4.1-node-browsers
11
+
12
+ # Specify service dependencies here if necessary
13
+ # CircleCI maintains a library of pre-built images
14
+ # documented at https://circleci.com/docs/2.0/circleci-images/
15
+ # - image: circleci/postgres:9.4
16
+
17
+ working_directory: ~/repo
18
+
19
+ steps:
20
+ - checkout
21
+
22
+ # Download and cache dependencies
23
+ - restore_cache:
24
+ keys:
25
+ - v1-dependencies-{{ checksum "Gemfile.lock" }}
26
+ # fallback to using the latest cache if no exact match is found
27
+ - v1-dependencies-
28
+
29
+ - run:
30
+ name: install dependencies
31
+ command: |
32
+ bundle install --jobs=4 --retry=3 --path .bundle
33
+
34
+ - save_cache:
35
+ paths:
36
+ - ./venv
37
+ key: v1-dependencies-{{ checksum "Gemfile.lock" }}
38
+
39
+ # Database setup
40
+ # - run: bundle exec rake db:create
41
+ # - run: bundle exec rake db:schema:load
42
+
43
+ # run tests!
44
+ - run:
45
+ name: run tests
46
+ command: |
47
+ bundle exec rake
48
+
49
+ # collect reports
50
+ - store_test_results:
51
+ path: /tmp/rspec/
52
+ - store_artifacts:
53
+ path: /tmp/rspec/
54
+ destination: test-results
@@ -0,0 +1,18 @@
1
+ <!--
2
+ Thank you for helping freshsales to get better!
3
+ Before you post your issue, please make sure that you checked the boxes! (put an x in the [ ] without spaces)
4
+ If possible, try to indicate what type of issue you are facing with the tags!
5
+ -->
6
+
7
+ ### Issue Checklist
8
+
9
+ - [ ] I'm using the latest freshsales version
10
+ - [ ] I ran `freshsales --help`
11
+ - [ ] I read the [README](https://github.com/DragonBox/freshsales/blob/master/README.md)
12
+ - [ ] I made sure that a similar [issue](https://github.com/DragonBox/freshsales/issues) doesn't exit
13
+
14
+ ### Issue Description
15
+
16
+ <!-- Please describe your issue with as much precision as possible. Write there the command you ran, its output, the behaviour you expect... -->
17
+
18
+ [DESCRIBE YOUR ISSUE HERE]
@@ -0,0 +1,20 @@
1
+ <!--
2
+ Thank you for contributing to freshsales!
3
+ Before you post your pull request, please make sure that you checked the boxes! (put an x in the [ ] without spaces)
4
+ If possible, try to name your pull request by prefixing it with <SUBJECT>. For instance, if you're modifying the downloading, you could prefix it with freshsales/download:
5
+ -->
6
+
7
+ ### Pull Request Checklist
8
+
9
+ - [ ] My pull request has been rebased on master
10
+ - [ ] I ran `bundle exec rspec` to make sure that my PR didn't break any test
11
+ - [ ] I ran `bundle exec rubocop` to make sure that my PR is inline with our code style
12
+ - [ ] I have read the [code of conduct](https://github.com/DragonBox/freshsales/blob/master/CODE_OF_CONDUCT.md)
13
+
14
+ ### Pull Request Description
15
+
16
+ <!-- If this pull request is related to a specific issue, please specify here "Fixes #ISSUE_NO" -->
17
+ <!-- Please describe your pull request with as much precision as possible. Write here why you think this change is required, what problem it solves, how it solves it... -->
18
+ <!-- Please describe to what extent you tested your modifications -->
19
+
20
+ [DESCRIBE YOUR PULL REQUEST HERE]
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ pkg/
2
+ coverage/
3
+ gems/
4
+ doc/
5
+ LOCAL/
6
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --require spec_helper --format d
data/.rubocop.yml ADDED
@@ -0,0 +1,58 @@
1
+ #
2
+ # File.chmod(0777, f)
3
+ #
4
+ # is easier to read than
5
+ #
6
+ # File.chmod(0o777, f)
7
+ #
8
+ #AllCops:
9
+ #Include:
10
+ # - '**/fastlane/Fastfile'
11
+
12
+ # broken in 0.52.1
13
+ Layout/EmptyLinesAroundArguments:
14
+ Enabled: false
15
+
16
+ Style/NumericLiteralPrefix:
17
+ Enabled: false
18
+
19
+ Style/StringLiterals:
20
+ Enabled: false # we're not there yet
21
+
22
+ Metrics/AbcSize:
23
+ Enabled: false
24
+
25
+ Metrics/BlockLength:
26
+ Enabled: false
27
+
28
+ Metrics/CyclomaticComplexity:
29
+ Enabled: false
30
+
31
+ Metrics/ParameterLists:
32
+ Max: 8
33
+
34
+ Metrics/PerceivedComplexity:
35
+ Max: 10
36
+
37
+ Metrics/MethodLength:
38
+ Enabled: false
39
+
40
+ # Configuration parameters: AllowURI, URISchemes.
41
+ Metrics/LineLength:
42
+ Max: 370
43
+
44
+ # We're not there yet
45
+ Style/Documentation:
46
+ Enabled: false
47
+
48
+ # Better too much 'return' than one missing
49
+ Style/RedundantReturn:
50
+ Enabled: false
51
+
52
+ # Tell Windows to look the other way
53
+ Layout/EndOfLine:
54
+ EnforcedStyle: lf
55
+
56
+ # Some issues with rspec style
57
+ Lint/AmbiguousBlockAssociation:
58
+ Enabled: false
@@ -0,0 +1,46 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ Examples of behavior that contributes to creating a positive environment include:
10
+
11
+ * Using welcoming and inclusive language
12
+ * Being respectful of differing viewpoints and experiences
13
+ * Gracefully accepting constructive criticism
14
+ * Focusing on what is best for the community
15
+ * Showing empathy towards other community members
16
+
17
+ Examples of unacceptable behavior by participants include:
18
+
19
+ * The use of sexualized language or imagery and unwelcome sexual attention or advances
20
+ * Trolling, insulting/derogatory comments, and personal or political attacks
21
+ * Public or private harassment
22
+ * Publishing others' private information, such as a physical or electronic address, without explicit permission
23
+ * Other conduct which could reasonably be considered inappropriate in a professional setting
24
+
25
+ ## Our Responsibilities
26
+
27
+ Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28
+
29
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30
+
31
+ ## Scope
32
+
33
+ This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34
+
35
+ ## Enforcement
36
+
37
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at support@dragonbox.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38
+
39
+ Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40
+
41
+ ## Attribution
42
+
43
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44
+
45
+ [homepage]: http://contributor-covenant.org
46
+ [version]: http://contributor-covenant.org/version/1/4/
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gemspec
6
+ # gem "rails"
data/Gemfile.lock ADDED
@@ -0,0 +1,121 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ freshsales (0.0.1)
5
+ faraday (~> 0.9.1)
6
+ multi_json (~> 1.11.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (5.1.6)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (>= 0.7, < 2)
14
+ minitest (~> 5.1)
15
+ tzinfo (~> 1.1)
16
+ addressable (2.5.2)
17
+ public_suffix (>= 2.0.2, < 4.0)
18
+ ast (2.4.0)
19
+ builder (3.2.3)
20
+ byebug (10.0.2)
21
+ coderay (1.1.2)
22
+ concurrent-ruby (1.0.5)
23
+ coveralls (0.8.21)
24
+ json (>= 1.8, < 3)
25
+ simplecov (~> 0.14.1)
26
+ term-ansicolor (~> 1.3)
27
+ thor (~> 0.19.4)
28
+ tins (~> 1.6)
29
+ diff-lcs (1.3)
30
+ docile (1.1.5)
31
+ faraday (0.9.2)
32
+ multipart-post (>= 1.2, < 3)
33
+ faraday-http-cache (2.0.0)
34
+ faraday (~> 0.8)
35
+ github_changelog_generator (1.14.3)
36
+ activesupport
37
+ faraday-http-cache
38
+ multi_json
39
+ octokit (~> 4.6)
40
+ rainbow (>= 2.1)
41
+ rake (>= 10.0)
42
+ retriable (~> 2.1)
43
+ i18n (1.0.0)
44
+ concurrent-ruby (~> 1.0)
45
+ json (2.1.0)
46
+ method_source (0.9.0)
47
+ minitest (5.11.3)
48
+ multi_json (1.11.3)
49
+ multipart-post (2.0.0)
50
+ octokit (4.8.0)
51
+ sawyer (~> 0.8.0, >= 0.5.3)
52
+ parallel (1.12.1)
53
+ parser (2.5.0.5)
54
+ ast (~> 2.4.0)
55
+ powerpack (0.1.1)
56
+ pry (0.11.3)
57
+ coderay (~> 1.1.0)
58
+ method_source (~> 0.9.0)
59
+ pry-byebug (3.6.0)
60
+ byebug (~> 10.0)
61
+ pry (~> 0.10)
62
+ public_suffix (3.0.2)
63
+ rainbow (3.0.0)
64
+ rake (10.5.0)
65
+ retriable (2.1.0)
66
+ rspec (3.1.0)
67
+ rspec-core (~> 3.1.0)
68
+ rspec-expectations (~> 3.1.0)
69
+ rspec-mocks (~> 3.1.0)
70
+ rspec-core (3.1.7)
71
+ rspec-support (~> 3.1.0)
72
+ rspec-expectations (3.1.2)
73
+ diff-lcs (>= 1.2.0, < 2.0)
74
+ rspec-support (~> 3.1.0)
75
+ rspec-mocks (3.1.3)
76
+ rspec-support (~> 3.1.0)
77
+ rspec-support (3.1.2)
78
+ rspec_junit_formatter (0.2.3)
79
+ builder (< 4)
80
+ rspec-core (>= 2, < 4, != 2.12.0)
81
+ rubocop (0.52.1)
82
+ parallel (~> 1.10)
83
+ parser (>= 2.4.0.2, < 3.0)
84
+ powerpack (~> 0.1)
85
+ rainbow (>= 2.2.2, < 4.0)
86
+ ruby-progressbar (~> 1.7)
87
+ unicode-display_width (~> 1.0, >= 1.0.1)
88
+ ruby-progressbar (1.9.0)
89
+ sawyer (0.8.1)
90
+ addressable (>= 2.3.5, < 2.6)
91
+ faraday (~> 0.8, < 1.0)
92
+ simplecov (0.14.1)
93
+ docile (~> 1.1.0)
94
+ json (>= 1.8, < 3)
95
+ simplecov-html (~> 0.10.0)
96
+ simplecov-html (0.10.2)
97
+ term-ansicolor (1.6.0)
98
+ tins (~> 1.0)
99
+ thor (0.19.4)
100
+ thread_safe (0.3.6)
101
+ tins (1.16.3)
102
+ tzinfo (1.2.5)
103
+ thread_safe (~> 0.1)
104
+ unicode-display_width (1.3.0)
105
+
106
+ PLATFORMS
107
+ ruby
108
+
109
+ DEPENDENCIES
110
+ bundler (~> 1.13)
111
+ coveralls
112
+ freshsales!
113
+ github_changelog_generator
114
+ pry-byebug
115
+ rake (~> 10.0)
116
+ rspec (~> 3.1.0)
117
+ rspec_junit_formatter (~> 0.2.3)
118
+ rubocop (~> 0.52.1)
119
+
120
+ BUNDLED WITH
121
+ 1.16.1
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018-present WeWantToKnow AS
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 all
13
+ 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 THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # U3D
2
+
3
+ [![License](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/DragonBox/freshsales/blob/master/LICENSE)
4
+ [![Gem](https://img.shields.io/gem/v/u3d.svg?style=flat)](https://rubygems.org/gems/freshsales)
5
+ [![Build Status](https://img.shields.io/circleci/project/DragonBox/freshsales/master.svg?style=flat)](https://circleci.com/gh/DragonBox/freshsales)
6
+ [![Coverage Status](https://coveralls.io/repos/github/DragonBox/freshsales/badge.svg?branch=master)](https://coveralls.io/github/DragonBox/freshsales?branch=master)
7
+
8
+ Freshsales is a ruby wrapper around Freshsales API.
9
+
10
+ ---
11
+
12
+ ## Installation
13
+
14
+ ```shell
15
+ gem install freshsales
16
+ ```
17
+
18
+ ## Getting started
19
+
20
+ ```ruby
21
+ config = {}
22
+ config[:freshsales_token] = "...."
23
+ config[:freshsales_domain] = "yourdomain" # from https://yourdomain.freshsales.io/
24
+ Freshsales::API.new(config)
25
+ ```
26
+
27
+ ## Examples
28
+
29
+ * Create / Update / Get / Delete
30
+
31
+ ```ruby
32
+ email = "sample@sample.com"
33
+
34
+ lead_data = %({"lead":{"last_name":"Sampleton (sample)", "email": "#{email}"}})
35
+
36
+ # create lead
37
+ result = freshsales.leads.post(body: lead_data)
38
+ lead_id = result.body['lead']['id']
39
+
40
+ updated_lead_data = %({"lead":{"mobile_number":"1-926-555-9999", "email": "#{email}"}})
41
+
42
+ # update the lead
43
+ freshsales.leads(lead_id).put(body: updated_lead_data).body
44
+
45
+ # get the lead
46
+ freshsales.leads(lead_id).get.body
47
+
48
+ # search the lead by email
49
+ sample = freshsales.search.get(params: {include: "lead", q: email}).body.first
50
+
51
+ # delete it
52
+ freshsales.leads(lead_id).delete
53
+ ```
54
+
55
+ ### Troubleshoot
56
+
57
+ Enable the `debug` option
58
+
59
+ ### Solve SSL Errors
60
+
61
+ If you face an issue similar to this one
62
+
63
+ ```shell
64
+ SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
65
+ ```
66
+ your ruby setup to work with OpenSSL probably needs to be fixed.
67
+
68
+ * __On MacOS:__
69
+
70
+ Your version of OpenSSL may be be outdated, make sure you are using the last one.
71
+
72
+ * __On Windows:__
73
+
74
+ A fix to the issue stated above has been found on [StackOverflow](http://stackoverflow.com/questions/5720484/how-to-solve-certificate-verify-failed-on-windows). If you follow the steps described in this topic, you will most likely get rid of this issue.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ ## --- BEGIN LICENSE BLOCK ---
2
+ # Copyright (c) 2018-present WeWantToKnow AS
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ # SOFTWARE.
21
+ ## --- END LICENSE BLOCK ---
22
+
23
+ require "bundler/gem_tasks"
24
+ require "rspec/core/rake_task"
25
+ require 'rubocop/rake_task'
26
+
27
+ RSpec::Core::RakeTask.new(:spec)
28
+ RuboCop::RakeTask.new
29
+
30
+ desc 'Run all rspec tests'
31
+ task :test_all do
32
+ formatter = "--format progress"
33
+ if ENV["CIRCLECI"]
34
+ Dir.mkdir("/tmp/rspec/")
35
+ formatter += " -r rspec_junit_formatter --format RspecJunitFormatter -o /tmp/rspec/rspec.xml"
36
+ TEST_FILES = `(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)`.tr!("\n", ' ')
37
+ rspec_args = "#{formatter} #{TEST_FILES}"
38
+ else
39
+ formatter += ' --pattern "./spec/**/*_spec.rb"'
40
+ rspec_args = formatter
41
+ end
42
+ sh "rspec #{rspec_args}"
43
+ end
44
+
45
+ task default: %i[rubocop test_all]
data/TODO ADDED
@@ -0,0 +1,6 @@
1
+ * code cleanup
2
+ # clean pagination API
3
+ # handle errors (Faraday::Error::ClientError)
4
+ # configuration options
5
+
6
+ * rspecs
data/appveyor.yml ADDED
@@ -0,0 +1,21 @@
1
+ # https://www.appveyor.com/docs/appveyor-yml/
2
+
3
+ version: "{build}"
4
+
5
+ init:
6
+ - git config --global core.autocrlf false
7
+
8
+ # cloning the repository happens here
9
+
10
+ install:
11
+ - set PATH=C:\Ruby24-x64\bin;%PATH%
12
+ - bundle install
13
+
14
+ environment:
15
+ LC_ALL: en_US.UTF-8
16
+ LANG: en_US.UTF-8
17
+
18
+ build: off
19
+
20
+ test_script:
21
+ - bundle exec rake
@@ -0,0 +1,37 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'freshsales/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'freshsales'
7
+ spec.version = Freshsales::VERSION
8
+ spec.authors = ["Jerome Lacoste"]
9
+ spec.email = 'jerome@wewanttoknow.com'
10
+
11
+ spec.required_ruby_version = '>= 2.1.0'
12
+
13
+ spec.summary = "Freshsales"
14
+ spec.description = 'A wrapper for Freshsales API'
15
+
16
+ spec.homepage = 'https://github.com/DragonBox/freshsales'
17
+ spec.license = 'MIT'
18
+
19
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
20
+ f.match(%r{^(test|spec|features)/})
21
+ end
22
+ spec.require_paths = ["lib"]
23
+
24
+ # using same minimal dependencies as gibbon, for the sake of compatibility
25
+ spec.add_dependency 'faraday', '~> 0.9.1'
26
+ spec.add_dependency 'multi_json', '~> 1.11.0'
27
+
28
+ # Development only
29
+ spec.add_development_dependency "bundler", "~> 1.13"
30
+ spec.add_development_dependency "coveralls"
31
+ spec.add_development_dependency "github_changelog_generator"
32
+ spec.add_development_dependency "pry-byebug"
33
+ spec.add_development_dependency "rake", "~> 10.0"
34
+ spec.add_development_dependency "rspec", "~> 3.1.0"
35
+ spec.add_development_dependency 'rspec_junit_formatter', '~> 0.2.3'
36
+ spec.add_development_dependency 'rubocop', '~> 0.52.1'
37
+ end
@@ -0,0 +1,29 @@
1
+ module Freshsales
2
+ class API
3
+ attr_accessor :freshsales_token, :freshsales_domain, :debug, :symbolize_keys, :logger, :adapter, :proxy
4
+
5
+ def initialize(opts = {})
6
+ @freshsales_token = opts.fetch(:freshsales_token, ENV["FRESHSALES_TOKEN"])
7
+ @freshsales_domain = opts.fetch(:freshsales_domain, ENV["FRESHSALES_DOMAIN"])
8
+ @symbolize_keys = false
9
+ @debug = opts.fetch(:debug, false)
10
+ @logger = ::Logger.new(STDOUT)
11
+ @adapter = Faraday.default_adapter
12
+ @proxy = nil
13
+
14
+ @client = Client.new(self)
15
+ end
16
+
17
+ # rubocop:disable Style/MethodMissing
18
+ def method_missing(method, *args)
19
+ request = RequestBuilder.new(@client)
20
+ request.send(method, *args)
21
+ request
22
+ end
23
+ # rubocop:enable Style/MethodMissing
24
+
25
+ def respond_to_missing?(_method_name, _include_private = false)
26
+ true
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,69 @@
1
+ module Freshsales
2
+ class Client
3
+ def initialize(config)
4
+ @config = config
5
+ end
6
+
7
+ def httprequest(method_name, path, args = {})
8
+ parse_response(freshsales_request(method_name, path, args))
9
+ end
10
+
11
+ def logger
12
+ @config.logger
13
+ end
14
+
15
+ private
16
+
17
+ def parse_response(response)
18
+ parsed_response = nil
19
+
20
+ if response.body && !response.body.empty?
21
+ begin
22
+ headers = response.headers
23
+ body = MultiJson.load(response.body, symbolize_keys: @config.symbolize_keys)
24
+ parsed_response = Response.new(headers: headers, body: body)
25
+ rescue MultiJson::ParseError
26
+ error_params = { title: "UNPARSEABLE_RESPONSE", status_code: 500 }
27
+ error = FreshsalesError.new("Unparseable response: '#{response.body}'", error_params)
28
+ raise error
29
+ end
30
+ end
31
+
32
+ parsed_response
33
+ end
34
+
35
+ def freshsales_domain
36
+ "https://#{@config.freshsales_domain}.freshsales.io"
37
+ end
38
+
39
+ def freshsales_request(method, path, params: nil, headers: nil, body: nil)
40
+ connection.send(method) do |request|
41
+ request.headers['Content-Type'] = 'application/json'
42
+ request.headers.update(headers) if headers
43
+ request.params.update(params) if params
44
+ if body
45
+ body = MultiJson.dump(body) unless body.is_a? String
46
+ request.body = body
47
+ end
48
+ request.url path
49
+ end
50
+ end
51
+
52
+ def connection
53
+ @connection ||=
54
+ begin
55
+ Faraday.new(freshsales_domain, proxy: @config.proxy, ssl: { version: "TLSv1_2" }) do |c|
56
+ # c.request :url_encoded
57
+ c.response :raise_error
58
+ c.use Faraday::Request::Authorization, 'Token', "token=#{@config.freshsales_token}"
59
+ if @config.debug
60
+ c.response :logger, @config.logger, bodies: true do |logger|
61
+ logger.filter(/(Token token=)(\w+)/, '\1[HIDDEN]')
62
+ end
63
+ end
64
+ c.adapter @config.adapter
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,84 @@
1
+ module Freshsales
2
+ class Cursor
3
+ include Enumerable
4
+
5
+ def initialize(client, path, type, collection_name, args)
6
+ @client = client
7
+ @path = path
8
+ @type = type
9
+ @collection_name = collection_name
10
+ @args = args
11
+
12
+ @collection = []
13
+ @page = params.fetch(:page, 0)
14
+ end
15
+
16
+ def params
17
+ (@args[:params] || {})
18
+ end
19
+
20
+ def each(start = 0)
21
+ return to_enum(:each, start) unless block_given?
22
+
23
+ Array(@collection[start..-1]).each do |element|
24
+ yield(element)
25
+ end
26
+
27
+ return if last?
28
+
29
+ start = [@collection.size, start].max
30
+
31
+ fetch_next_page
32
+
33
+ each(start, &Proc.new)
34
+ end
35
+
36
+ private
37
+
38
+ attr_reader :client
39
+
40
+ def logger
41
+ @client.logger
42
+ end
43
+
44
+ MAX = 100_000 # FIXME: get rid off or configure
45
+
46
+ def fetch_next_page
47
+ nextpage = @page + 1
48
+ @args[:params] = params.merge(page: nextpage)
49
+ response = client.httprequest(:get, @path, @args)
50
+ j = response.body
51
+
52
+ # might have been symbolized
53
+ if j.is_a? Hash
54
+ meta = (j['meta'] || j[:meta])
55
+ total_pages = (meta['total_pages'] || meta[:total_pages])
56
+ last = nextpage == total_pages
57
+ logger.debug "Found #{nextpage}/#{total_pages} #{@type} #{@collection_name} (#{j.keys.map { |k| [k, j[k].count] }.join(',')}) last? #{last}"
58
+ data =
59
+ case @type
60
+ when :page
61
+ [j]
62
+ when :elt
63
+ j[@collection_name]
64
+ end
65
+ elsif j.is_a? Array
66
+ # most probably searching
67
+ last = true
68
+ logger.debug "Found #{j.count} elements #{@type} #{@collection_name}"
69
+
70
+ data = j
71
+ else
72
+ raise "Unexpected data type received #{j.class}"
73
+ end
74
+
75
+ @last_response = last
76
+ @collection += data
77
+ @page = nextpage
78
+ end
79
+
80
+ def last?
81
+ @last_response || @collection.size >= MAX
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,14 @@
1
+ module Freshsales
2
+ class FreshsalesError < StandardError
3
+ attr_reader :params
4
+
5
+ def initialize(message = "", params = {})
6
+ @params = params
7
+ super(message)
8
+ end
9
+
10
+ def to_s
11
+ super + " " + params.to_s
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,42 @@
1
+ module Freshsales
2
+ class RequestBuilder
3
+ def initialize(client)
4
+ @client = client
5
+ @httpmethods = %i[get put post delete]
6
+
7
+ @path_parts = []
8
+ end
9
+
10
+ def get_all_pages(*args)
11
+ Cursor.new(@client, path, :page, @path_parts[0], *args)
12
+ end
13
+
14
+ def get_all(*args)
15
+ Cursor.new(@client, path, :elt, @path_parts[0], *args)
16
+ end
17
+
18
+ # rubocop:disable Style/MethodMissing
19
+ def method_missing(method, *args)
20
+ if @httpmethods.include? method
21
+ @client.httprequest(method.to_s, path, *args)
22
+ else
23
+ @path_parts << method.to_s
24
+ args.each do |arg|
25
+ @path_parts << arg
26
+ end
27
+ self
28
+ end
29
+ end
30
+ # rubocop:enable Style/MethodMissing
31
+
32
+ def respond_to_missing?(_method_name, _include_private = false)
33
+ true
34
+ end
35
+
36
+ private
37
+
38
+ def path
39
+ "/api/#{@path_parts.join('/')}"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,10 @@
1
+ module Freshsales
2
+ class Response
3
+ attr_accessor :headers, :body
4
+
5
+ def initialize(headers: {}, body: {})
6
+ @headers = headers
7
+ @body = body
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,3 @@
1
+ module Freshsales
2
+ VERSION = "0.0.1".freeze
3
+ end
data/lib/freshsales.rb ADDED
@@ -0,0 +1,37 @@
1
+ ## --- BEGIN LICENSE BLOCK ---
2
+ # Copyright (c) 2018-present WeWantToKnow AS
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ # SOFTWARE.
21
+ ## --- END LICENSE BLOCK ---
22
+
23
+ require 'logger'
24
+ require 'uri'
25
+ require 'cgi'
26
+ require 'multi_json'
27
+ require 'pry'
28
+ require 'faraday'
29
+
30
+ require 'freshsales/version'
31
+
32
+ require 'freshsales/api'
33
+ require 'freshsales/freshsales_error'
34
+ require 'freshsales/request_builder'
35
+ require 'freshsales/response'
36
+ require 'freshsales/client'
37
+ require 'freshsales/cursor'
metadata ADDED
@@ -0,0 +1,206 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: freshsales
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jerome Lacoste
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.9.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: multi_json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.11.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.11.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.13'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.13'
55
+ - !ruby/object:Gem::Dependency
56
+ name: coveralls
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: github_changelog_generator
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 3.1.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 3.1.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec_junit_formatter
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.2.3
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.2.3
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 0.52.1
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 0.52.1
153
+ description: A wrapper for Freshsales API
154
+ email: jerome@wewanttoknow.com
155
+ executables: []
156
+ extensions: []
157
+ extra_rdoc_files: []
158
+ files:
159
+ - ".circleci/config.yml"
160
+ - ".github/ISSUE_TEMPLATE.md"
161
+ - ".github/PULL_REQUEST_TEMPLATE.md"
162
+ - ".gitignore"
163
+ - ".rspec"
164
+ - ".rubocop.yml"
165
+ - CODE_OF_CONDUCT.md
166
+ - Gemfile
167
+ - Gemfile.lock
168
+ - LICENSE
169
+ - README.md
170
+ - Rakefile
171
+ - TODO
172
+ - appveyor.yml
173
+ - freshsales.gemspec
174
+ - lib/freshsales.rb
175
+ - lib/freshsales/api.rb
176
+ - lib/freshsales/client.rb
177
+ - lib/freshsales/cursor.rb
178
+ - lib/freshsales/freshsales_error.rb
179
+ - lib/freshsales/request_builder.rb
180
+ - lib/freshsales/response.rb
181
+ - lib/freshsales/version.rb
182
+ homepage: https://github.com/DragonBox/freshsales
183
+ licenses:
184
+ - MIT
185
+ metadata: {}
186
+ post_install_message:
187
+ rdoc_options: []
188
+ require_paths:
189
+ - lib
190
+ required_ruby_version: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: 2.1.0
195
+ required_rubygems_version: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ version: '0'
200
+ requirements: []
201
+ rubyforge_project:
202
+ rubygems_version: 2.6.12
203
+ signing_key:
204
+ specification_version: 4
205
+ summary: Freshsales
206
+ test_files: []