amorail 0.1.4

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9c91d42f4e1991fe27ebde64b7e88f8537c90ad7
4
+ data.tar.gz: 18665c9622339679e5d419d7dec829e1c736ad6c
5
+ SHA512:
6
+ metadata.gz: 2b4b928c8a32c0a3ed07fa0e8aed9c916cfd401ebed5c97bcc989d9e71dd37d9ee5b6b9f559a0a504949c0a78198c05dacb7b3efcd7217279e603838f442c713
7
+ data.tar.gz: 514dc9cbbfc728f82d240208b71d202f0fb129e3ee3457c19ecb08c6c6a0b951df45749652e75e44dde6903113af66e80ad175bbce274840babcf22e0091a1f5
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /lib/amorail/entities/
11
+ *.bundle
12
+ *.so
13
+ *.o
14
+ *.a
15
+ mkmf.log
16
+ *.gem
data/.hound.yml ADDED
@@ -0,0 +1,2 @@
1
+ ruby:
2
+ enabled: true
data/.rubocop.yml ADDED
@@ -0,0 +1,18 @@
1
+ AllCops:
2
+ # Include gemspec and Rakefile
3
+ Include:
4
+ - 'lib/**/*.rb'
5
+ - 'lib/**/*.rake'
6
+ - 'spec/**/*.rb'
7
+ Exclude:
8
+ - 'bin/**/*'
9
+ RunRailsCops: true
10
+ DisplayCopNames: true
11
+ StyleGuideCopsOnly: false
12
+
13
+ Style/Documentation:
14
+ Exclude:
15
+ - 'spec/**/*.rb'
16
+
17
+ Style/StringLiterals:
18
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 2.2
5
+
6
+ notifications:
7
+ email: false
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in amorail.gemspec
4
+ gem 'pry-byebug'
5
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 alekseenkoss
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,33 @@
1
+ [![Build Status](https://travis-ci.org/teachbase/amorail.svg?branch=master)](https://travis-ci.org/teachbase/amorail)
2
+
3
+ # Amorail
4
+
5
+ AmoCRM client
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'amorail'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install amorail
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Contributing
28
+
29
+ 1. Fork it ( https://github.com/[my-github-username]/amorail/fork )
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+ Dir.glob('lib/tasks/*.rake').each {|r| import r}
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
data/amorail.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'amorail/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "amorail"
8
+ spec.version = Amorail::VERSION
9
+ spec.authors = ["alekseenkoss", "palkan"]
10
+ spec.email = ["alekseenkoss@gmail.com", "dementiev.vm@gmail.com"]
11
+ spec.summary = %q{Ruby API client for AmoCRM}
12
+ spec.description = %q{Ruby API client for AmoCRM. You can integrate your system with it.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "webmock"
25
+ spec.add_development_dependency 'pry'
26
+ spec.add_development_dependency 'shoulda-matchers'
27
+ spec.add_dependency "anyway_config", "~> 0", ">= 0.3"
28
+ spec.add_dependency "faraday"
29
+ spec.add_dependency "faraday_middleware"
30
+ spec.add_dependency 'activemodel'
31
+ spec.add_dependency 'json'
32
+ end
@@ -0,0 +1,81 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+ require 'json'
4
+ require 'active_support'
5
+
6
+ module Amorail
7
+ class Client
8
+ attr_accessor :cookies
9
+
10
+ def initialize
11
+ @host = Amorail.config.api_endpoint
12
+ @connect = Faraday.new(url: @host) do |faraday|
13
+ faraday.adapter Faraday.default_adapter
14
+ faraday.response :json, :content_type => /\bjson$/
15
+ faraday.use :instrumentation
16
+ end
17
+ end
18
+
19
+ def connect
20
+ @connect || self.class.new
21
+ end
22
+
23
+ def authorize
24
+ response = post(Amorail.config.auth_url, {'USER_LOGIN' => Amorail.config.usermail, 'USER_HASH' => Amorail.config.api_key})
25
+ cookie_handler(response)
26
+ response
27
+ end
28
+
29
+ def safe_request(method, url, params={})
30
+ self.send(method, url, params)
31
+ rescue ::Amorail::AmoUnauthorizedError => e
32
+ authorize
33
+ self.send(method, url, params)
34
+ end
35
+
36
+ def get(url, params={})
37
+ response = connect.get(url, params) do |request|
38
+ request.headers['Cookie'] = self.cookies if self.cookies.present?
39
+ end
40
+ handle_response(response)
41
+ end
42
+
43
+ def post(url, params={})
44
+ response = connect.post(url) do |request|
45
+ request.headers['Cookie'] = self.cookies if self.cookies.present?
46
+ request.headers['Content-Type'] = 'application/json'
47
+ request.body = params.to_json
48
+ end
49
+ handle_response(response)
50
+ end
51
+
52
+ def cookie_handler(response)
53
+ self.cookies = response.headers['set-cookie'].split('; ')[0]
54
+ end
55
+
56
+ def handle_response(response)
57
+ return response if response.status == 200 or response.status == 204
58
+
59
+ case response.status
60
+ when 301
61
+ raise ::Amorail::AmoMovedPermanentlyError
62
+ when 400
63
+ raise ::Amorail::AmoBadRequestError
64
+ when 401
65
+ raise ::Amorail::AmoUnauthorizedError
66
+ when 403
67
+ raise ::Amorail::AmoForbiddenError
68
+ when 404
69
+ raise ::Amorail::AmoNotFoudError
70
+ when 500
71
+ raise ::Amorail::AmoInternalError
72
+ when 502
73
+ raise ::Amorail::AmoBadGatewayError
74
+ when 503
75
+ raise ::Amorail::AmoServiceUnaviableError
76
+ else
77
+ raise ::Amorail::AmoUnknownError(response.body)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,11 @@
1
+ require 'anyway'
2
+
3
+ module Amorail
4
+ class Config < Anyway::Config
5
+ attr_config :usermail,
6
+ :api_key,
7
+ :api_endpoint,
8
+ api_path: "/private/api/v2/json/",
9
+ auth_url: "/private/api/auth.php?type=json"
10
+ end
11
+ end
@@ -0,0 +1,109 @@
1
+ module Amorail
2
+
3
+ module MethodMissing
4
+ def method_missing(method_sym, *arguments, &block)
5
+ if data.has_key?(method_sym.to_s)
6
+ data.fetch(method_sym.to_s)
7
+ else
8
+ super
9
+ end
10
+ end
11
+ end
12
+
13
+ class Property
14
+ class PropertyItem
15
+ include MethodMissing
16
+
17
+ attr_reader :data
18
+
19
+ def initialize(data)
20
+ @data = data
21
+ end
22
+
23
+ def [](key)
24
+ @data[key]
25
+ end
26
+ end
27
+
28
+ class StatusItem
29
+ attr_reader :statuses
30
+
31
+ def initialize(data)
32
+ @statuses = data
33
+ end
34
+ end
35
+
36
+ attr_reader :client, :data, :contacts,
37
+ :company, :leads, :tasks
38
+
39
+ def initialize(client)
40
+ @client = client
41
+ reload
42
+ end
43
+
44
+ def reload
45
+ @data = load_fields
46
+ parse_all_data
47
+ end
48
+
49
+ def load_fields
50
+ response = client.safe_request(:get, '/private/api/v2/json/accounts/current')
51
+ response.body["response"]["account"]
52
+ end
53
+
54
+ def inspect
55
+ @data
56
+ end
57
+
58
+ private
59
+
60
+ def parse_all_data
61
+ @contacts = Contact.parse(data)
62
+ @company = Company.parse(data)
63
+ @leads = Lead.parse(data)
64
+ @tasks = Task.parse(data)
65
+ end
66
+
67
+ class Contact < PropertyItem
68
+ def self.parse(data)
69
+ hash = {}
70
+ data['custom_fields']['contacts'].each do |contact|
71
+ hash[contact['code'].downcase] = PropertyItem.new(contact)
72
+ end
73
+ new hash
74
+ end
75
+ end
76
+
77
+ class Company < PropertyItem
78
+ def self.parse(data)
79
+ hash = {}
80
+ data['custom_fields']['companies'].each do |company|
81
+ hash[company['code'].downcase] = PropertyItem.new(company)
82
+ end
83
+ new hash
84
+ end
85
+ end
86
+
87
+ class Lead < StatusItem
88
+ def self.parse(data)
89
+ hash = {}
90
+ data['leads_statuses'].each do |prop|
91
+ hash[prop['name']] = PropertyItem.new(prop)
92
+ end
93
+ new hash
94
+ end
95
+ end
96
+
97
+ class Task < PropertyItem
98
+ def self.parse(data)
99
+ hash = {}
100
+ data['task_types'].each do |tt|
101
+ prop_item = PropertyItem.new(tt)
102
+ hash[tt['code'].downcase] = prop_item
103
+ hash[tt['code']] = prop_item
104
+ end
105
+ new hash
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,11 @@
1
+ require 'amorail'
2
+ require 'rails'
3
+
4
+ module Amorail
5
+ class Engine < Rails::Engine
6
+ rake_tasks do
7
+ load File.expand_path("../../tasks/amorail.rake", __FILE__)
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,20 @@
1
+ module Amorail
2
+ class AmoCompany < Amorail::AmoEntity
3
+ include Leadable
4
+ amo_names 'company', 'contacts'
5
+
6
+ amo_field :name
7
+ amo_property :email, enum: 'WORK'
8
+ amo_property :phone, enum: 'WORK'
9
+ amo_property :address
10
+ amo_property :web
11
+
12
+ validates :name, presence: true
13
+
14
+ def params
15
+ data = super
16
+ data[:type] = 'contact'
17
+ data
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ module Amorail
2
+ class AmoContact < Amorail::AmoEntity
3
+ include Leadable
4
+ amo_names 'contacts'
5
+
6
+ amo_field :name, :company_name
7
+
8
+ amo_property :email, enum: 'MOB'
9
+ amo_property :phone, enum: 'WORK'
10
+ amo_property :position
11
+
12
+ validates :name, presence: true
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module Amorail
2
+ class AmoLead < Amorail::AmoEntity
3
+ amo_names "leads"
4
+
5
+ amo_field :name, :price, :status_id, :tags
6
+
7
+ validates :name, :status_id, presence: true
8
+ end
9
+ end
@@ -0,0 +1,46 @@
1
+ module Amorail
2
+ class AmoTask < Amorail::AmoEntity
3
+ amo_names "tasks"
4
+
5
+ amo_field :element_id, :element_type, :text,
6
+ :task_type, complete_till: :timestamp
7
+
8
+ validates :text, :element_id,
9
+ :element_type, :complete_till,
10
+ :task_type,
11
+ presence: true
12
+
13
+ validates :element_type, inclusion: 1..2
14
+
15
+ def params
16
+ {
17
+ id: id,
18
+ text: text,
19
+ date_create: to_timestamp(date_create),
20
+ last_modified: to_timestamp(last_modified) || Time.now.to_i,
21
+ request_id: request_id,
22
+ responsible_user_id: responsible_user_id,
23
+ element_id: element_id,
24
+ element_type: element_type,
25
+ task_type: task_type,
26
+ complete_till: to_timestamp(complete_till)
27
+ }
28
+ end
29
+
30
+ [{ name: "contact", val: 1 }, { name: "lead", val: 2 }].each do |prop|
31
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
32
+ def #{prop[:name]}=(val)
33
+ #{prop[:name]}! if val
34
+ end
35
+
36
+ def #{prop[:name]}?
37
+ self.element_type == #{prop[:val]}
38
+ end
39
+
40
+ def #{prop[:name]}!
41
+ self.element_type = #{prop[:val]}
42
+ end
43
+ CODE
44
+ end
45
+ end
46
+ end