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.
@@ -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
@@ -4,4 +4,8 @@ Yext::Api::Engine.routes.draw do
4
4
  scope :agreements, module: :agreements do
5
5
  resources :add_request, only: %i[create]
6
6
  end
7
+
8
+ scope :powerlistings, module: :powerlistings do
9
+ resources :listing, only: %i[create]
10
+ end
7
11
  end
@@ -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: PowerListings
423
+ :module_name: Powerlistings
424
424
  :objects:
425
- :publishser:
425
+ :publisher:
426
426
  :actions:
427
427
  - :action: :index
428
428
  :method: :get
@@ -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, Yext::Api::AdministrativeApi::Account].each do |account_class|
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
- args[:id] = args.delete(:account_id) if account_scope
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
@@ -3,6 +3,7 @@
3
3
  module Yext
4
4
  module Api
5
5
  module Enumerations
6
+ # The possible modes to search for when looking up Optimization Links
6
7
  class OptimizationLinkMode
7
8
  include Yext::Api::Concerns::EnumAll
8
9
 
@@ -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