yext-api 0.1.5 → 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|