followupboss_client 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.
- checksums.yaml +7 -0
- data/.env.example +12 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.tool-versions +1 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +149 -0
- data/CODE_OF_CONDUCT.md +49 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +882 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/followupboss_client.gemspec +43 -0
- data/lib/followupboss_client.rb +16 -0
- data/lib/fub_client/action_plan.rb +5 -0
- data/lib/fub_client/appointment.rb +42 -0
- data/lib/fub_client/appointment_outcome.rb +51 -0
- data/lib/fub_client/appointment_type.rb +51 -0
- data/lib/fub_client/call.rb +4 -0
- data/lib/fub_client/client.rb +200 -0
- data/lib/fub_client/compatibility.rb +18 -0
- data/lib/fub_client/configuration.rb +54 -0
- data/lib/fub_client/cookie_client.rb +190 -0
- data/lib/fub_client/custom_field.rb +5 -0
- data/lib/fub_client/deal.rb +41 -0
- data/lib/fub_client/deal_attachment.rb +61 -0
- data/lib/fub_client/deal_custom_field.rb +47 -0
- data/lib/fub_client/em_event.rb +5 -0
- data/lib/fub_client/email_template.rb +5 -0
- data/lib/fub_client/event.rb +8 -0
- data/lib/fub_client/group.rb +58 -0
- data/lib/fub_client/her_patch.rb +101 -0
- data/lib/fub_client/identity.rb +33 -0
- data/lib/fub_client/message.rb +41 -0
- data/lib/fub_client/middleware/authentication.rb +26 -0
- data/lib/fub_client/middleware/cookie_authentication.rb +61 -0
- data/lib/fub_client/middleware/parser.rb +59 -0
- data/lib/fub_client/middleware.rb +8 -0
- data/lib/fub_client/note.rb +4 -0
- data/lib/fub_client/people_relationship.rb +34 -0
- data/lib/fub_client/person.rb +5 -0
- data/lib/fub_client/person_attachment.rb +50 -0
- data/lib/fub_client/pipeline.rb +45 -0
- data/lib/fub_client/property.rb +26 -0
- data/lib/fub_client/rails8_patch.rb +39 -0
- data/lib/fub_client/resource.rb +33 -0
- data/lib/fub_client/shared_inbox.rb +389 -0
- data/lib/fub_client/smart_list.rb +5 -0
- data/lib/fub_client/stage.rb +39 -0
- data/lib/fub_client/task.rb +18 -0
- data/lib/fub_client/team.rb +65 -0
- data/lib/fub_client/team_inbox.rb +65 -0
- data/lib/fub_client/text_message.rb +46 -0
- data/lib/fub_client/text_message_template.rb +49 -0
- data/lib/fub_client/user.rb +4 -0
- data/lib/fub_client/version.rb +3 -0
- data/lib/fub_client/webhook.rb +47 -0
- data/lib/fub_client.rb +61 -0
- data/scripts/test_api.rb +110 -0
- data/scripts/test_shared_inbox.rb +90 -0
- metadata +335 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module FubClient
|
|
2
|
+
module Middleware
|
|
3
|
+
class Parser < Faraday::Middleware
|
|
4
|
+
def initialize(app = nil)
|
|
5
|
+
super(app)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def on_complete(env)
|
|
9
|
+
original_json = MultiJson.load(env[:body])
|
|
10
|
+
|
|
11
|
+
# First check if there's an error response
|
|
12
|
+
if original_json.is_a?(Hash) && original_json['errorMessage']
|
|
13
|
+
env[:body] = {
|
|
14
|
+
errors: { message: original_json['errorMessage'] },
|
|
15
|
+
data: nil,
|
|
16
|
+
metadata: nil
|
|
17
|
+
}
|
|
18
|
+
return
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
json = original_json.deep_transform_keys { |k| k.to_s.snakecase.to_sym }
|
|
22
|
+
|
|
23
|
+
# Check if this is an error response in the new format
|
|
24
|
+
if json.is_a?(Hash) && json[:error_message]
|
|
25
|
+
env[:body] = {
|
|
26
|
+
errors: { message: json[:error_message] },
|
|
27
|
+
data: nil,
|
|
28
|
+
metadata: nil
|
|
29
|
+
}
|
|
30
|
+
return
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
metadata = json[:_metadata]
|
|
34
|
+
if metadata.nil?
|
|
35
|
+
result = json
|
|
36
|
+
elsif metadata[:collection].is_a?(String)
|
|
37
|
+
# Make sure the collection key exists and is a string before using it
|
|
38
|
+
collection_key = metadata[:collection].snakecase.to_sym
|
|
39
|
+
result = json[collection_key] || []
|
|
40
|
+
else
|
|
41
|
+
result = []
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
env[:body] = {
|
|
45
|
+
data: result,
|
|
46
|
+
errors: json[:errors],
|
|
47
|
+
metadata: metadata
|
|
48
|
+
}
|
|
49
|
+
rescue StandardError => e
|
|
50
|
+
# Provide a clean error response if JSON parsing fails
|
|
51
|
+
env[:body] = {
|
|
52
|
+
errors: { message: "Parser error: #{e.message}" },
|
|
53
|
+
data: nil,
|
|
54
|
+
metadata: nil
|
|
55
|
+
}
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module FubClient
|
|
2
|
+
class PeopleRelationship < Resource
|
|
3
|
+
collection_path 'peopleRelationships'
|
|
4
|
+
root_element :people_relationship
|
|
5
|
+
include_root_in_json true
|
|
6
|
+
|
|
7
|
+
scope :for_person, ->(person_id) { where(personId: person_id) }
|
|
8
|
+
scope :with_related_person, ->(related_person_id) { where(relatedPersonId: related_person_id) }
|
|
9
|
+
scope :by_type, ->(type) { where(type: type) }
|
|
10
|
+
|
|
11
|
+
def person
|
|
12
|
+
return nil unless respond_to?(:person_id) && person_id
|
|
13
|
+
|
|
14
|
+
FubClient::Person.find(person_id)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def related_person
|
|
18
|
+
return nil unless respond_to?(:related_person_id) && related_person_id
|
|
19
|
+
|
|
20
|
+
FubClient::Person.find(related_person_id)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.create_relationship(person_id, related_person_id, type, description = nil)
|
|
24
|
+
params = {
|
|
25
|
+
personId: person_id,
|
|
26
|
+
relatedPersonId: related_person_id,
|
|
27
|
+
type: type
|
|
28
|
+
}
|
|
29
|
+
params[:description] = description if description
|
|
30
|
+
|
|
31
|
+
post('', params)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module FubClient
|
|
2
|
+
class PersonAttachment < Resource
|
|
3
|
+
collection_path 'personAttachments'
|
|
4
|
+
root_element :person_attachment
|
|
5
|
+
include_root_in_json true
|
|
6
|
+
|
|
7
|
+
scope :for_person, ->(person_id) { where(personId: person_id) }
|
|
8
|
+
scope :by_type, ->(type) { where(type: type) }
|
|
9
|
+
scope :by_name, ->(name) { where(q: name) }
|
|
10
|
+
|
|
11
|
+
def person
|
|
12
|
+
return nil unless respond_to?(:person_id) && person_id
|
|
13
|
+
|
|
14
|
+
FubClient::Person.find(person_id)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.upload(person_id, file_path, name = nil, type = nil, description = nil)
|
|
18
|
+
params = {
|
|
19
|
+
personId: person_id,
|
|
20
|
+
file: File.new(file_path, 'rb')
|
|
21
|
+
}
|
|
22
|
+
params[:name] = name if name
|
|
23
|
+
params[:type] = type if type
|
|
24
|
+
params[:description] = description if description
|
|
25
|
+
|
|
26
|
+
post('', params)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def download
|
|
30
|
+
return nil unless id
|
|
31
|
+
|
|
32
|
+
begin
|
|
33
|
+
self.class.get("#{id}/download")
|
|
34
|
+
rescue StandardError
|
|
35
|
+
nil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def delete
|
|
40
|
+
return false unless id
|
|
41
|
+
|
|
42
|
+
begin
|
|
43
|
+
self.class.delete(id.to_s)
|
|
44
|
+
true
|
|
45
|
+
rescue StandardError
|
|
46
|
+
false
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module FubClient
|
|
2
|
+
class Pipeline < Resource
|
|
3
|
+
collection_path 'pipelines'
|
|
4
|
+
root_element :pipeline
|
|
5
|
+
include_root_in_json true
|
|
6
|
+
|
|
7
|
+
def self.active
|
|
8
|
+
where(active: true)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.inactive
|
|
12
|
+
where(active: false)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def stages
|
|
16
|
+
return [] unless id
|
|
17
|
+
|
|
18
|
+
FubClient::Stage.by_pipeline(id)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def deals
|
|
22
|
+
return [] unless id
|
|
23
|
+
|
|
24
|
+
FubClient::Deal.where(pipelineId: id)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def stats
|
|
28
|
+
return {} unless id
|
|
29
|
+
|
|
30
|
+
begin
|
|
31
|
+
self.class.get("#{id}/stats")
|
|
32
|
+
rescue StandardError
|
|
33
|
+
{}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def move_to_position(position)
|
|
38
|
+
self.class.put("#{id}/move", { position: position })
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def update_stages(stages_data)
|
|
42
|
+
self.class.put("#{id}/stages", { stages: stages_data })
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module FubClient
|
|
2
|
+
class Property < Resource
|
|
3
|
+
collection_path 'properties'
|
|
4
|
+
root_element :property
|
|
5
|
+
include_root_in_json true
|
|
6
|
+
|
|
7
|
+
scope :search, ->(query) { where(q: query) }
|
|
8
|
+
scope :by_price_range, ->(min, max) { where(minPrice: min, maxPrice: max) }
|
|
9
|
+
scope :by_location, lambda { |city, state = nil, zip = nil|
|
|
10
|
+
params = { city: city }
|
|
11
|
+
params[:state] = state if state
|
|
12
|
+
params[:zip] = zip if zip
|
|
13
|
+
where(params)
|
|
14
|
+
}
|
|
15
|
+
scope :by_features, lambda { |beds = nil, baths = nil, sq_ft = nil|
|
|
16
|
+
params = {}
|
|
17
|
+
params[:beds] = beds if beds
|
|
18
|
+
params[:baths] = baths if baths
|
|
19
|
+
params[:minSqFt] = sq_ft if sq_ft
|
|
20
|
+
where(params)
|
|
21
|
+
}
|
|
22
|
+
scope :for_person, ->(person_id) { where(personId: person_id) }
|
|
23
|
+
scope :active, -> { where(active: true) }
|
|
24
|
+
scope :inactive, -> { where(active: false) }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Rails 8 compatibility patch for Her gem
|
|
2
|
+
# Her gem expects: (ActiveSupport.const_defined?('ProxyObject') ? ActiveSupport::ProxyObject : ActiveSupport::BasicObject)
|
|
3
|
+
|
|
4
|
+
unless defined?(ActiveSupport::ProxyObject)
|
|
5
|
+
begin
|
|
6
|
+
if defined?(ActiveSupport::BasicObject)
|
|
7
|
+
ActiveSupport.const_set('ProxyObject', ActiveSupport::BasicObject)
|
|
8
|
+
puts '[FubClient] Created ActiveSupport::ProxyObject from BasicObject'
|
|
9
|
+
else
|
|
10
|
+
ActiveSupport.const_set('ProxyObject', BasicObject)
|
|
11
|
+
puts "[FubClient] Created ActiveSupport::ProxyObject from Ruby's BasicObject"
|
|
12
|
+
end
|
|
13
|
+
rescue NameError
|
|
14
|
+
ActiveSupport.const_set('ProxyObject', BasicObject)
|
|
15
|
+
puts "[FubClient] Created ActiveSupport::ProxyObject from Ruby's BasicObject (fallback)"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
begin
|
|
20
|
+
ActiveSupport::BasicObject
|
|
21
|
+
rescue NameError
|
|
22
|
+
if defined?(ActiveSupport::ProxyObject)
|
|
23
|
+
ActiveSupport.const_set('BasicObject', ActiveSupport::ProxyObject)
|
|
24
|
+
puts '[FubClient] Created ActiveSupport::BasicObject from ProxyObject'
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Faraday 2.x compatibility
|
|
29
|
+
if defined?(Faraday) && !defined?(Faraday::Response::Middleware)
|
|
30
|
+
Faraday::Response.class_eval do
|
|
31
|
+
class Middleware < Faraday::Middleware
|
|
32
|
+
def initialize(app, options = {})
|
|
33
|
+
super(app)
|
|
34
|
+
@options = options
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
puts '[FubClient] Created Faraday::Response::Middleware for Her gem compatibility'
|
|
39
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module FubClient
|
|
2
|
+
class Resource
|
|
3
|
+
include Her::Model
|
|
4
|
+
use_api FubClient::Client.instance.her_api
|
|
5
|
+
|
|
6
|
+
collection_path '/'
|
|
7
|
+
|
|
8
|
+
def self.safe_all
|
|
9
|
+
result = all
|
|
10
|
+
result.nil? ? [] : result
|
|
11
|
+
rescue StandardError
|
|
12
|
+
[]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
scope :by_page, lambda { |page, per_page|
|
|
16
|
+
where(offset: (page - 1) * per_page, limit: per_page)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
def self.total
|
|
20
|
+
by_page(1, 1).metadata[:total]
|
|
21
|
+
rescue StandardError
|
|
22
|
+
0
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.method_missing(method, *args, &blk)
|
|
26
|
+
super
|
|
27
|
+
rescue NoMethodError => e
|
|
28
|
+
return [] if e.message.include?('nil:NilClass') || e.message.include?('for nil:NilClass')
|
|
29
|
+
|
|
30
|
+
raise e
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|