yext-api 0.1.5 → 0.1.11
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 +5 -5
- data/.circleci/config.yml +53 -0
- data/.ruby-version +1 -1
- data/Gemfile +0 -2
- data/Gemfile.lock +81 -68
- data/README.md +41 -1
- data/app/controllers/yext/api/agreements/add_request_controller.rb +31 -43
- data/app/controllers/yext/api/powerlistings/listing_controller.rb +62 -0
- data/config/routes.rb +4 -0
- data/lib/config/api.yml +2 -2
- data/lib/yext-api.rb +65 -0
- data/lib/yext/api/administrative_api/account.rb +0 -20
- data/lib/yext/api/administrative_api/add_request.rb +21 -0
- data/lib/yext/api/concerns/account_child.rb +26 -2
- data/lib/yext/api/concerns/account_relations.rb +28 -0
- data/lib/yext/api/enumerations/add_request_location_mode.rb +15 -0
- data/lib/yext/api/enumerations/listing_status.rb +19 -0
- data/lib/yext/api/enumerations/optimization_link_mode.rb +1 -0
- data/lib/yext/api/knowledge_api/knowledge_manager/location.rb +24 -0
- data/lib/yext/api/knowledge_api/powerlistings/listing.rb +59 -0
- data/lib/yext/api/knowledge_api/powerlistings/publisher.rb +25 -0
- data/lib/yext/api/utils/configuration.rb +0 -89
- data/lib/yext/api/validators/account_validator.rb +3 -2
- data/lib/yext/api/version.rb +1 -1
- data/yext-api.gemspec +2 -1
- metadata +26 -7
- data/lib/yext/api/utils/params.rb +0 -69
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Yext
|
4
|
+
module Api
|
5
|
+
module Powerlistings
|
6
|
+
# This controller processes Yext listing webhook callbacks.
|
7
|
+
#
|
8
|
+
# The controller will instrument the "listing.powerlistings.yext" ActiveSupport Notification.
|
9
|
+
# The params hash will include:
|
10
|
+
# * meta - the `meta` value of the webhook.
|
11
|
+
# * listing - a Yext::Api::KnowledgeApi::Powerlistings::Listing object that is the Listing
|
12
|
+
# being reported on.
|
13
|
+
|
14
|
+
# :webhooks:
|
15
|
+
# :listing:
|
16
|
+
# :endpoint: https://[your_hostname]/[your_listings_webhook_path]
|
17
|
+
# :default_version: 20161012
|
18
|
+
# :documentation: http://developer.yext.com/docs/webhooks/#operation/listingsWebhook
|
19
|
+
# :sandbox_only: false
|
20
|
+
class ListingController < Yext::Api::ApplicationController
|
21
|
+
extend Memoist
|
22
|
+
|
23
|
+
def create
|
24
|
+
listing = Yext::Api::KnowledgeApi::Powerlistings::Listing.new(listing_hash[:listing])
|
25
|
+
|
26
|
+
ActiveSupport::Notifications.instrument "listing.powerlistings.yext",
|
27
|
+
meta: listing_hash[:meta],
|
28
|
+
listing: listing do
|
29
|
+
# do your custom stuff here
|
30
|
+
end
|
31
|
+
|
32
|
+
head :ok
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# rubocop:disable MethodLength
|
38
|
+
|
39
|
+
def listing_hash
|
40
|
+
params.
|
41
|
+
permit(meta: %i[eventType uuid timestamp accountId actor appSpecificAccountId],
|
42
|
+
listing: [:id,
|
43
|
+
:locationId,
|
44
|
+
:publisherId,
|
45
|
+
:status,
|
46
|
+
:additionalStatus,
|
47
|
+
:listingUrl,
|
48
|
+
:loginUrl,
|
49
|
+
:screenshotUrl,
|
50
|
+
{ statusDetails: %i[code message type] },
|
51
|
+
{ alternateBrands: %i[brandName listingUrl] }]).
|
52
|
+
to_hash.
|
53
|
+
with_indifferent_access
|
54
|
+
end
|
55
|
+
|
56
|
+
# rubocop:enable MethodLength
|
57
|
+
|
58
|
+
memoize :listing_hash
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/config/routes.rb
CHANGED
data/lib/config/api.yml
CHANGED
@@ -420,9 +420,9 @@
|
|
420
420
|
:documentation: http://developer.yext.com/docs/api-reference/#operation/deleteAsset
|
421
421
|
:sandbox_only: false
|
422
422
|
:power_listings:
|
423
|
-
:module_name:
|
423
|
+
:module_name: Powerlistings
|
424
424
|
:objects:
|
425
|
-
:
|
425
|
+
:publisher:
|
426
426
|
:actions:
|
427
427
|
- :action: :index
|
428
428
|
:method: :get
|
data/lib/yext-api.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spyke"
|
4
|
+
require "memoist"
|
5
|
+
require "validation"
|
6
|
+
require "validation/validator"
|
7
|
+
require "validation/rule/not_empty"
|
8
|
+
require "yext/api"
|
9
|
+
require "yext/api/engine"
|
10
|
+
require "yext/api/concerns/enum_all"
|
11
|
+
require "yext/api/enumerations/add_request_location_mode"
|
12
|
+
require "yext/api/enumerations/add_request_status"
|
13
|
+
require "yext/api/enumerations/error_codes/agreements_errors"
|
14
|
+
require "yext/api/enumerations/error_codes/analytics_errors"
|
15
|
+
require "yext/api/enumerations/error_codes/customers_errros"
|
16
|
+
require "yext/api/enumerations/error_codes/ecl_errors"
|
17
|
+
require "yext/api/enumerations/error_codes/feedback_errors"
|
18
|
+
require "yext/api/enumerations/error_codes/general_errors"
|
19
|
+
require "yext/api/enumerations/error_codes/live_api_errors"
|
20
|
+
require "yext/api/enumerations/error_codes/locations_errors"
|
21
|
+
require "yext/api/enumerations/error_codes/optimizations_errors"
|
22
|
+
require "yext/api/enumerations/error_codes/publisher_suggestions_errors"
|
23
|
+
require "yext/api/enumerations/error_codes/reviews_errors"
|
24
|
+
require "yext/api/enumerations/error_codes/social_errors"
|
25
|
+
require "yext/api/enumerations/error_codes/subscriptions_errors"
|
26
|
+
require "yext/api/enumerations/error_codes/suppression_errors"
|
27
|
+
require "yext/api/enumerations/error_codes/users_errors"
|
28
|
+
require "yext/api/enumerations/error_codes"
|
29
|
+
require "yext/api/enumerations/listing_status"
|
30
|
+
require "yext/api/enumerations/location_type"
|
31
|
+
require "yext/api/enumerations/optimization_link_mode"
|
32
|
+
require "yext/api/enumerations/validation"
|
33
|
+
require "yext/api/utils/configuration"
|
34
|
+
require "yext/api/concerns/rate_limits"
|
35
|
+
require "yext/api/live_api"
|
36
|
+
require "yext/api/utils/api_finder"
|
37
|
+
require "yext/api/utils/middleware/api_rate_limits"
|
38
|
+
require "yext/api/utils/middleware/default_parameters"
|
39
|
+
require "yext/api/utils/middleware/response_parser"
|
40
|
+
require "yext/api/utils/middleware/uri_cleanup"
|
41
|
+
require "yext/api/concerns/faraday_connection"
|
42
|
+
require "yext/api/concerns/default_scopes"
|
43
|
+
require "yext/api/utils/api_base"
|
44
|
+
require "yext/api/concerns/account_child"
|
45
|
+
require "yext/api/concerns/account_relations"
|
46
|
+
require "yext/api/knowledge_api"
|
47
|
+
require "yext/api/knowledge_api/account_settings/account"
|
48
|
+
require "yext/api/administrative_api"
|
49
|
+
require "yext/api/administrative_api/account"
|
50
|
+
require "yext/api/live_api/location"
|
51
|
+
require "yext/api/validators/account_validator"
|
52
|
+
require "yext/api/administrative_api/add_request"
|
53
|
+
require "yext/api/administrative_api/service"
|
54
|
+
require "yext/api/knowledge_api/account_settings/role"
|
55
|
+
require "yext/api/knowledge_api/account_settings/user"
|
56
|
+
require "yext/api/knowledge_api/health_check/health"
|
57
|
+
require "yext/api/knowledge_api/knowledge_manager/category"
|
58
|
+
require "yext/api/knowledge_api/knowledge_manager/location"
|
59
|
+
require "yext/api/knowledge_api/optimization_tasks/optimization_link"
|
60
|
+
require "yext/api/knowledge_api/optimization_tasks/optimization_task"
|
61
|
+
require "yext/api/knowledge_api/powerlistings/listing"
|
62
|
+
require "yext/api/knowledge_api/powerlistings/publisher"
|
63
|
+
require_relative "../app/controllers/yext/api/application_controller"
|
64
|
+
require_relative "../app/controllers/yext/api/agreements/add_request_controller"
|
65
|
+
require_relative "../app/controllers/yext/api/powerlistings/listing_controller"
|
@@ -30,8 +30,6 @@ module Yext
|
|
30
30
|
class Account < Yext::Api::Utils::ApiBase
|
31
31
|
include Yext::Api::Concerns::AccountRelations
|
32
32
|
|
33
|
-
after_save :save_account_id
|
34
|
-
|
35
33
|
# The save action only allows the saving of the account_id and the accountName
|
36
34
|
#
|
37
35
|
# Furthermore, the account_id cannot be changed by the partner, but only by the customer
|
@@ -48,24 +46,6 @@ module Yext
|
|
48
46
|
|
49
47
|
save_account_id
|
50
48
|
end
|
51
|
-
|
52
|
-
# rubocop:disable Naming/MethodName
|
53
|
-
|
54
|
-
# Yext field names don't match the Ruby naming standard, this is the field name they use.
|
55
|
-
# Because I use `account_id` in the route, I need that attribute defined. Because
|
56
|
-
# Yext uses accountId, when it is set, I need to set `account_id` so they will match.
|
57
|
-
def accountId=(value)
|
58
|
-
super
|
59
|
-
attributes[:account_id] ||= value
|
60
|
-
end
|
61
|
-
|
62
|
-
# rubocop:enable Naming/MethodName
|
63
|
-
|
64
|
-
private
|
65
|
-
|
66
|
-
def save_account_id
|
67
|
-
attributes[:account_id] = accountId
|
68
|
-
end
|
69
49
|
end
|
70
50
|
end
|
71
51
|
end
|
@@ -47,6 +47,19 @@ module Yext
|
|
47
47
|
|
48
48
|
include Yext::Api::Concerns::AccountChild
|
49
49
|
|
50
|
+
# rubocop:disable Naming/MethodName
|
51
|
+
|
52
|
+
# helper function to extract the affected location ID based on the locationMode
|
53
|
+
def locationId
|
54
|
+
if locationMode == Yext::Api::Enumerations::AddRequestLocationMode::NEW
|
55
|
+
newLocationId
|
56
|
+
else
|
57
|
+
existingLocationId
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# rubocop:enable Naming/MethodName
|
62
|
+
|
50
63
|
# This is a helper method to try to simplify changing the status of an AddRequest if you
|
51
64
|
# don't have an AddRequest object.
|
52
65
|
#
|
@@ -89,6 +102,8 @@ module Yext
|
|
89
102
|
post
|
90
103
|
end)
|
91
104
|
|
105
|
+
# After successfully creating a new add request, the object attributes will be updated/
|
106
|
+
# changed to the values of the created add request.
|
92
107
|
def save
|
93
108
|
if persisted?
|
94
109
|
change_status
|
@@ -104,6 +119,12 @@ module Yext
|
|
104
119
|
with(Yext::Api::Concerns::AccountChild.with_account_path("newlocationaddrequests")).
|
105
120
|
where(attributes.reverse_merge(account_id: Yext::Api.configuration.param_account_id)).
|
106
121
|
post
|
122
|
+
|
123
|
+
if Yext::Api::AdministrativeApi.last_status.between?(200, 299)
|
124
|
+
self.attributes = Yext::Api::AdministrativeApi.last_data.dup
|
125
|
+
else
|
126
|
+
self
|
127
|
+
end
|
107
128
|
end
|
108
129
|
|
109
130
|
def change_status
|
@@ -25,10 +25,12 @@ module Yext
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def ensure_relation(klass)
|
28
|
-
[Yext::Api::KnowledgeApi::AccountSettings::Account
|
28
|
+
%w[Yext::Api::KnowledgeApi::AccountSettings::Account Yext::Api::AdministrativeApi::Account].each do |account_class_name|
|
29
|
+
account_class = account_class_name.constantize
|
29
30
|
next if account_class.association?(klass)
|
30
31
|
|
31
32
|
klass_uri = klass.instance_variable_get(:@uri)
|
33
|
+
|
32
34
|
klass_uri ||= klass.send(:default_uri)
|
33
35
|
helper_warnings(account_class, klass, klass_uri)
|
34
36
|
|
@@ -79,6 +81,8 @@ module Yext
|
|
79
81
|
end)
|
80
82
|
|
81
83
|
Yext::Api::Concerns::AccountChild.ensure_relation(self)
|
84
|
+
|
85
|
+
after_save :save_account_id
|
82
86
|
end
|
83
87
|
|
84
88
|
class_methods do
|
@@ -110,11 +114,31 @@ module Yext
|
|
110
114
|
|
111
115
|
args[:account_id] ||= Yext::Api.configuration.param_account_id
|
112
116
|
|
113
|
-
|
117
|
+
# account_scope means that the scope will be applied to an Account rather than a
|
118
|
+
# relation off of an Account.
|
119
|
+
args[:id] = args.delete(:account_id) if account_scope
|
114
120
|
|
115
121
|
args
|
116
122
|
end
|
117
123
|
end
|
124
|
+
|
125
|
+
# rubocop:disable Naming/MethodName
|
126
|
+
|
127
|
+
# Yext field names don't match the Ruby naming standard, this is the field name they use.
|
128
|
+
# Because I use `account_id` in the route, I need that attribute defined. Because
|
129
|
+
# Yext uses accountId, when it is set, I need to set `account_id` so they will match.
|
130
|
+
def accountId=(value)
|
131
|
+
super
|
132
|
+
attributes[:account_id] = value
|
133
|
+
end
|
134
|
+
|
135
|
+
# rubocop:enable Naming/MethodName
|
136
|
+
|
137
|
+
private
|
138
|
+
|
139
|
+
def save_account_id
|
140
|
+
attributes[:account_id] = attributes[:accountId] if attributes.key?(:accountId)
|
141
|
+
end
|
118
142
|
end
|
119
143
|
end
|
120
144
|
end
|
@@ -34,8 +34,36 @@ module Yext
|
|
34
34
|
class_name: "Yext::Api::KnowledgeApi::OptimizationTasks::OptimizationLink",
|
35
35
|
uri: Yext::Api::Concerns::AccountChild.with_account_path("optimizationlink")
|
36
36
|
|
37
|
+
# KnowledgeApi::Powerlistings
|
38
|
+
has_many :listings,
|
39
|
+
class_name: "Yext::Api::KnowledgeApi::Powerlistings::Listing",
|
40
|
+
uri: Yext::Api::Concerns::AccountChild.with_account_path("powerlistings/listings/(:id)")
|
41
|
+
has_many :publishers,
|
42
|
+
class_name: "Yext::Api::KnowledgeApi::Powerlistings::Publisher",
|
43
|
+
uri: Yext::Api::Concerns::AccountChild.with_account_path("powerlistings/publishers/(:id)")
|
44
|
+
|
37
45
|
# LiveApi
|
38
46
|
has_many :live_locations, class_name: "Yext::Api::LiveApi::Location"
|
47
|
+
|
48
|
+
after_save :save_account_id
|
49
|
+
end
|
50
|
+
|
51
|
+
# rubocop:disable Naming/MethodName
|
52
|
+
|
53
|
+
# Yext field names don't match the Ruby naming standard, this is the field name they use.
|
54
|
+
# Because I use `account_id` in the route, I need that attribute defined. Because
|
55
|
+
# Yext uses accountId, when it is set, I need to set `account_id` so they will match.
|
56
|
+
def accountId=(value)
|
57
|
+
super
|
58
|
+
attributes[:account_id] ||= value
|
59
|
+
end
|
60
|
+
|
61
|
+
# rubocop:enable Naming/MethodName
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def save_account_id
|
66
|
+
attributes[:account_id] = accountId
|
39
67
|
end
|
40
68
|
|
41
69
|
class_methods do
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Yext
|
4
|
+
module Api
|
5
|
+
module Enumerations
|
6
|
+
# The type of the location in an AddRequest
|
7
|
+
class AddRequestLocationMode
|
8
|
+
include Yext::Api::Concerns::EnumAll
|
9
|
+
|
10
|
+
EXISTING = "EXISTING"
|
11
|
+
NEW = "NEW"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Yext
|
4
|
+
module Api
|
5
|
+
module Enumerations
|
6
|
+
# An enumeration class to contain the possible status values for a listing.
|
7
|
+
class ListingStatus
|
8
|
+
include Yext::Api::Concerns::EnumAll
|
9
|
+
|
10
|
+
WAITING_ON_YEXT = "WAITING_ON_YEXT"
|
11
|
+
WAITING_ON_CUSTOMER = "WAITING_ON_CUSTOMER"
|
12
|
+
WAITING_ON_PUBLISHER = "WAITING_ON_PUBLISHER"
|
13
|
+
LIVE = "LIVE"
|
14
|
+
UNAVAILABLE = "UNAVAILABLE"
|
15
|
+
OPTED_OUT = "OPTED_OUT"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -46,6 +46,30 @@ module Yext
|
|
46
46
|
class Location < Yext::Api::Utils::ApiBase
|
47
47
|
include Yext::Api::Concerns::AccountChild
|
48
48
|
|
49
|
+
scope(:search, lambda do |*filters|
|
50
|
+
args = scope_args true
|
51
|
+
args[:filters] = Array.wrap(filters).to_json
|
52
|
+
|
53
|
+
Yext::Api::AdministrativeApi::Account.
|
54
|
+
where(args).
|
55
|
+
with(:locationsearch).
|
56
|
+
get
|
57
|
+
end)
|
58
|
+
|
59
|
+
def save(*fields_to_update)
|
60
|
+
return super if fields_to_update.blank?
|
61
|
+
|
62
|
+
# To save only certain fields, slice those fields into a new Location so that everything
|
63
|
+
# is sent (which is only the fields we want)
|
64
|
+
location = Yext::Api::KnowledgeApi::KnowledgeManager::Location.
|
65
|
+
new(attributes.with_indifferent_access.slice(*fields_to_update))
|
66
|
+
|
67
|
+
location.id = id
|
68
|
+
location.accountId = accountId
|
69
|
+
|
70
|
+
location.save
|
71
|
+
end
|
72
|
+
|
49
73
|
# http://developer.yext.com/docs/administrative-api/#operation/createExistingLocationAddRequest
|
50
74
|
def add_services!(skus:, agreement_id: nil, force_review: false)
|
51
75
|
args = { existingAccountId: account_id, existingLocationId: id }
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Yext
|
4
|
+
module Api
|
5
|
+
module KnowledgeApi
|
6
|
+
module Powerlistings
|
7
|
+
# :knowledge_api:
|
8
|
+
# :powerlistings:
|
9
|
+
# :listing:
|
10
|
+
# - :action: :index
|
11
|
+
# :method: :get
|
12
|
+
# :endpoint: https://api.yext.com/v2/accounts/{accountId}/powerlistings/listings
|
13
|
+
# :path_regex: v2/accounts/[^/]+?/powerlistings/listings
|
14
|
+
# :default_version: 20161012
|
15
|
+
# :documentation: http://developer.yext.com/docs/api-reference/#operation/listListings
|
16
|
+
# :sandbox_only: false
|
17
|
+
# - :action: :opt_in
|
18
|
+
# :method: :put
|
19
|
+
# :endpoint: https://api.yext.com/v2/accounts/{accountId}/powerlistings/listings/optin
|
20
|
+
# :path_regex: v2/accounts/[^/]+?/powerlistings/listings/optin
|
21
|
+
# :default_version: 20161012
|
22
|
+
# :documentation: http://developer.yext.com/docs/api-reference/#operation/optInListings
|
23
|
+
# :sandbox_only: false
|
24
|
+
# - :action: :opt_out
|
25
|
+
# :method: :put
|
26
|
+
# :endpoint: https://api.yext.com/v2/accounts/{accountId}/powerlistings/listings/optout
|
27
|
+
# :path_regex: v2/accounts/[^/]+?/powerlistings/listings/optout
|
28
|
+
# :default_version: 20161012
|
29
|
+
# :documentation: http://developer.yext.com/docs/api-reference/#operation/optOutListings
|
30
|
+
# :sandbox_only: false
|
31
|
+
class Listing < Yext::Api::Utils::ApiBase
|
32
|
+
uri "powerlistings/#{default_uri}"
|
33
|
+
|
34
|
+
include Yext::Api::Concerns::AccountChild
|
35
|
+
|
36
|
+
# rubocop:disable Style/Lambda
|
37
|
+
|
38
|
+
scope(:opt_in!, ->(location_ids: nil, publisher_ids: nil) do
|
39
|
+
params = {}
|
40
|
+
params[:locationIds] = Array.wrap(location_ids).join(",") if location_ids.present?
|
41
|
+
params[:publisherIds] = Array.wrap(publisher_ids).join(",") if publisher_ids.present?
|
42
|
+
|
43
|
+
where(params).with(:optin).put
|
44
|
+
end)
|
45
|
+
|
46
|
+
scope(:opt_out!, ->(location_ids: nil, publisher_ids: nil) do
|
47
|
+
params = {}
|
48
|
+
params[:locationIds] = Array.wrap(location_ids) if location_ids.present?
|
49
|
+
params[:publisherIds] = Array.wrap(publisher_ids) if publisher_ids.present?
|
50
|
+
|
51
|
+
where(params).with(:optout).put
|
52
|
+
end)
|
53
|
+
|
54
|
+
# rubocop:enable Style/Lambda
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|