forem-ruby 0.1.0.beta1
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/LICENSE +21 -0
- data/forem-ruby.gemspec +17 -0
- data/lib/forem/api_operations/create.rb +47 -0
- data/lib/forem/api_operations/delete.rb +88 -0
- data/lib/forem/api_operations/list.rb +70 -0
- data/lib/forem/api_operations/request.rb +83 -0
- data/lib/forem/api_operations/retrieve.rb +43 -0
- data/lib/forem/api_operations/save.rb +53 -0
- data/lib/forem/api_operations/update.rb +47 -0
- data/lib/forem/api_requestor.rb +283 -0
- data/lib/forem/api_resource.rb +77 -0
- data/lib/forem/client.rb +279 -0
- data/lib/forem/configuration.rb +74 -0
- data/lib/forem/connection_manager.rb +75 -0
- data/lib/forem/errors.rb +118 -0
- data/lib/forem/forem_object.rb +264 -0
- data/lib/forem/forem_response.rb +50 -0
- data/lib/forem/list_object.rb +171 -0
- data/lib/forem/resources/admin_concept.rb +169 -0
- data/lib/forem/resources/admin_user.rb +152 -0
- data/lib/forem/resources/agent_session.rb +110 -0
- data/lib/forem/resources/analytics.rb +151 -0
- data/lib/forem/resources/article.rb +256 -0
- data/lib/forem/resources/billboard.rb +76 -0
- data/lib/forem/resources/comment.rb +43 -0
- data/lib/forem/resources/concept.rb +192 -0
- data/lib/forem/resources/follow.rb +78 -0
- data/lib/forem/resources/follower.rb +56 -0
- data/lib/forem/resources/health_check.rb +70 -0
- data/lib/forem/resources/organization.rb +79 -0
- data/lib/forem/resources/page.rb +52 -0
- data/lib/forem/resources/podcast_episode.rb +36 -0
- data/lib/forem/resources/profile_image.rb +44 -0
- data/lib/forem/resources/reaction.rb +61 -0
- data/lib/forem/resources/reading_list.rb +29 -0
- data/lib/forem/resources/recommended_articles_list.rb +45 -0
- data/lib/forem/resources/request_redirect.rb +60 -0
- data/lib/forem/resources/segment.rb +103 -0
- data/lib/forem/resources/survey.rb +96 -0
- data/lib/forem/resources/tag.rb +27 -0
- data/lib/forem/resources/trend.rb +80 -0
- data/lib/forem/resources/user.rb +229 -0
- data/lib/forem/resources/video.rb +28 -0
- data/lib/forem/services/admin_concept_service.rb +138 -0
- data/lib/forem/services/admin_user_service.rb +114 -0
- data/lib/forem/services/agent_session_service.rb +87 -0
- data/lib/forem/services/analytics_service.rb +93 -0
- data/lib/forem/services/article_service.rb +233 -0
- data/lib/forem/services/base_service.rb +45 -0
- data/lib/forem/services/billboard_service.rb +91 -0
- data/lib/forem/services/comment_service.rb +51 -0
- data/lib/forem/services/concept_service.rb +143 -0
- data/lib/forem/services/follow_service.rb +61 -0
- data/lib/forem/services/follower_service.rb +34 -0
- data/lib/forem/services/health_check_service.rb +46 -0
- data/lib/forem/services/organization_service.rb +103 -0
- data/lib/forem/services/page_service.rb +107 -0
- data/lib/forem/services/podcast_episode_service.rb +34 -0
- data/lib/forem/services/profile_image_service.rb +32 -0
- data/lib/forem/services/reaction_service.rb +72 -0
- data/lib/forem/services/reading_list_service.rb +35 -0
- data/lib/forem/services/recommended_articles_list_service.rb +87 -0
- data/lib/forem/services/request_redirect_service.rb +118 -0
- data/lib/forem/services/segment_service.rb +83 -0
- data/lib/forem/services/survey_service.rb +48 -0
- data/lib/forem/services/tag_service.rb +32 -0
- data/lib/forem/services/trend_service.rb +70 -0
- data/lib/forem/services/user_service.rb +61 -0
- data/lib/forem/services/video_service.rb +33 -0
- data/lib/forem/util.rb +43 -0
- data/lib/forem/version.rb +4 -0
- data/lib/forem.rb +91 -0
- metadata +111 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Forem
|
|
2
|
+
# Represents an article with an associated video on a Forem instance.
|
|
3
|
+
#
|
|
4
|
+
# Video articles are a special content type where the primary content is a
|
|
5
|
+
# video rather than text. The public API supports listing video articles,
|
|
6
|
+
# returned ordered by publication date.
|
|
7
|
+
#
|
|
8
|
+
# Returns published articles with video, ordered by descending popularity.
|
|
9
|
+
# Default: 24 per page.
|
|
10
|
+
#
|
|
11
|
+
# Available operations (via mixins):
|
|
12
|
+
# - +List+ — GET /api/videos
|
|
13
|
+
#
|
|
14
|
+
# @example List video articles
|
|
15
|
+
# videos = client.videos.list(per_page: 10)
|
|
16
|
+
# videos.data.each { |v| puts v.title }
|
|
17
|
+
#
|
|
18
|
+
# @example Iterate over all video articles using auto-pagination
|
|
19
|
+
# client.videos.list.auto_paging_each { |v| puts "#{v.title}: #{v.video_source_url}" }
|
|
20
|
+
#
|
|
21
|
+
# @see https://developers.forem.com/api/v1#/operations/videos
|
|
22
|
+
class Video < APIResource
|
|
23
|
+
extend APIOperations::List
|
|
24
|
+
|
|
25
|
+
OBJECT_NAME = "video"
|
|
26
|
+
RESOURCE_PATH = "/api/videos"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
module Forem
|
|
2
|
+
module Services
|
|
3
|
+
# Service for interacting with the Forem Admin Concepts API.
|
|
4
|
+
#
|
|
5
|
+
# Provides full CRUD over concepts — the curated topics Forem uses to
|
|
6
|
+
# classify articles and comments — plus the +trigger_lookback+ action that
|
|
7
|
+
# re-runs classification over older content. Every endpoint requires an API
|
|
8
|
+
# key with super admin privileges; regular user keys receive HTTP 401.
|
|
9
|
+
#
|
|
10
|
+
# Access via {Client#admin_concepts}. All methods inject the client's
|
|
11
|
+
# requestor automatically so no additional configuration is required.
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# client = Forem::Client.new("admin-api-key")
|
|
15
|
+
# concept = client.admin_concepts.create(name: "Machine Learning")
|
|
16
|
+
# client.admin_concepts.trigger_lookback(concept.id, days: 90)
|
|
17
|
+
#
|
|
18
|
+
# @see AdminConcept
|
|
19
|
+
# @see Forem::Concept
|
|
20
|
+
# @see https://developers.forem.com/api/v1
|
|
21
|
+
class AdminConceptService < BaseService
|
|
22
|
+
# List concepts, ordered by name.
|
|
23
|
+
#
|
|
24
|
+
# Returns a trimmed projection of each concept: +id+, +name+, +slug+,
|
|
25
|
+
# +description+, +parent_id+, +similarity_threshold+,
|
|
26
|
+
# +max_lookback_days+, +created_at+, and +updated_at+.
|
|
27
|
+
#
|
|
28
|
+
# @param params [Hash] query parameters
|
|
29
|
+
# @option params [Integer] :page page number (default: 1)
|
|
30
|
+
# @option params [Integer] :per_page results per page (default: 50, max: 100)
|
|
31
|
+
# @param opts [Hash] per-request options
|
|
32
|
+
# @return [ListObject] the current page of {AdminConcept} records
|
|
33
|
+
#
|
|
34
|
+
# @example
|
|
35
|
+
# client.admin_concepts.list(per_page: 100)
|
|
36
|
+
def list(params = {}, opts = {})
|
|
37
|
+
AdminConcept.list(params, opts_with_requestor(opts))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Retrieve a single concept by ID.
|
|
41
|
+
#
|
|
42
|
+
# Returns the full concept record, unlike {#list} which returns a
|
|
43
|
+
# trimmed projection.
|
|
44
|
+
#
|
|
45
|
+
# @param id [Integer, String] the concept ID
|
|
46
|
+
# @param opts [Hash] per-request options
|
|
47
|
+
# @return [AdminConcept] the requested concept
|
|
48
|
+
# @raise [NotFoundError] if no concept has that ID
|
|
49
|
+
#
|
|
50
|
+
# @example
|
|
51
|
+
# client.admin_concepts.retrieve(7)
|
|
52
|
+
def retrieve(id, opts = {})
|
|
53
|
+
AdminConcept.retrieve(id, opts_with_requestor(opts))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Create a new concept.
|
|
57
|
+
#
|
|
58
|
+
# Attributes are sent wrapped in a +concept+ object for you. The API
|
|
59
|
+
# generates the slug, and generates a description and the anchor
|
|
60
|
+
# embedding from +name+, so only +name+ is required.
|
|
61
|
+
#
|
|
62
|
+
# @param params [Hash] concept attributes
|
|
63
|
+
# @option params [String] :name the concept name, max 100 chars (required)
|
|
64
|
+
# @option params [String] :description human-readable description
|
|
65
|
+
# @option params [Integer] :parent_id ID of the parent concept
|
|
66
|
+
# @option params [Float] :similarity_threshold classification cutoff (0.0–1.0)
|
|
67
|
+
# @option params [Float] :score ranking score for the concept
|
|
68
|
+
# @param opts [Hash] per-request options
|
|
69
|
+
# @return [AdminConcept] the newly created concept
|
|
70
|
+
# @raise [InvalidRequestError] on HTTP 422 (validation errors)
|
|
71
|
+
#
|
|
72
|
+
# @example
|
|
73
|
+
# client.admin_concepts.create(
|
|
74
|
+
# name: "Machine Learning",
|
|
75
|
+
# description: "Posts about ML and AI",
|
|
76
|
+
# similarity_threshold: 0.8
|
|
77
|
+
# )
|
|
78
|
+
def create(params = {}, opts = {})
|
|
79
|
+
AdminConcept.create(params, opts_with_requestor(opts))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Update an existing concept.
|
|
83
|
+
#
|
|
84
|
+
# Attributes are sent wrapped in a +concept+ object for you. Only
|
|
85
|
+
# +name+, +description+, +parent_id+, +similarity_threshold+, and
|
|
86
|
+
# +score+ are writable; +slug+ and +max_lookback_days+ are ignored.
|
|
87
|
+
# Changing +name+ or +description+ regenerates the anchor embedding.
|
|
88
|
+
#
|
|
89
|
+
# @param id [Integer, String] the concept ID
|
|
90
|
+
# @param params [Hash] attributes to change (see {#create})
|
|
91
|
+
# @param opts [Hash] per-request options
|
|
92
|
+
# @return [AdminConcept] the updated concept
|
|
93
|
+
# @raise [NotFoundError] if no concept has that ID
|
|
94
|
+
# @raise [InvalidRequestError] on HTTP 422 (validation errors)
|
|
95
|
+
#
|
|
96
|
+
# @example
|
|
97
|
+
# client.admin_concepts.update(7, similarity_threshold: 0.9)
|
|
98
|
+
def update(id, params = {}, opts = {})
|
|
99
|
+
AdminConcept.update(id, params, opts_with_requestor(opts))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Delete a concept.
|
|
103
|
+
#
|
|
104
|
+
# The API responds with HTTP 204 and no body on success.
|
|
105
|
+
#
|
|
106
|
+
# @param id [Integer, String] the concept ID
|
|
107
|
+
# @param opts [Hash] per-request options
|
|
108
|
+
# @return [AdminConcept, nil] +nil+ for the usual empty response
|
|
109
|
+
# @raise [NotFoundError] if no concept has that ID
|
|
110
|
+
#
|
|
111
|
+
# @example
|
|
112
|
+
# client.admin_concepts.delete(7)
|
|
113
|
+
def delete(id, opts = {})
|
|
114
|
+
AdminConcept.delete(id, opts_with_requestor(opts))
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Queue a classification lookback for a concept.
|
|
118
|
+
#
|
|
119
|
+
# Enqueues a background job that classifies records from the last
|
|
120
|
+
# +days+ days. The value must be positive and strictly greater than the
|
|
121
|
+
# concept's current +max_lookback_days+, otherwise the API responds with
|
|
122
|
+
# HTTP 422.
|
|
123
|
+
#
|
|
124
|
+
# @param id [Integer, String] the concept ID
|
|
125
|
+
# @param params [Hash] request body
|
|
126
|
+
# @option params [Integer] :days how many days back to classify (required)
|
|
127
|
+
# @param opts [Hash] per-request options
|
|
128
|
+
# @return [ForemObject] an object carrying a +message+
|
|
129
|
+
# @raise [InvalidRequestError] on HTTP 422 when +days+ is out of range
|
|
130
|
+
#
|
|
131
|
+
# @example
|
|
132
|
+
# client.admin_concepts.trigger_lookback(7, days: 90).message
|
|
133
|
+
def trigger_lookback(id, params = {}, opts = {})
|
|
134
|
+
AdminConcept.trigger_lookback(id, params, opts_with_requestor(opts))
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module Forem
|
|
2
|
+
module Services
|
|
3
|
+
# Service for interacting with the Forem Admin Users API.
|
|
4
|
+
#
|
|
5
|
+
# Provides administrative operations on user accounts. These endpoints
|
|
6
|
+
# require an API key with admin-level privileges.
|
|
7
|
+
# Access via {Client#admin_users}. All methods inject the client's
|
|
8
|
+
# requestor automatically so no additional configuration is required.
|
|
9
|
+
#
|
|
10
|
+
# @example
|
|
11
|
+
# client = Forem::Client.new("admin-api-key")
|
|
12
|
+
# user = client.admin_users.create(
|
|
13
|
+
# email: "newuser@example.com",
|
|
14
|
+
# name: "New User"
|
|
15
|
+
# )
|
|
16
|
+
#
|
|
17
|
+
# @see AdminUser
|
|
18
|
+
# @see https://developers.forem.com/api/v1#/operations/postAdminUsersCreate
|
|
19
|
+
class AdminUserService < BaseService
|
|
20
|
+
# Invite a new user to the Forem instance.
|
|
21
|
+
#
|
|
22
|
+
# Creates a user account and sends them an invitation email.
|
|
23
|
+
# Requires admin privileges.
|
|
24
|
+
#
|
|
25
|
+
# @param params [Hash] user attributes
|
|
26
|
+
# @option params [String] :email the new user's email address (required)
|
|
27
|
+
# @option params [String] :name display name for the new user
|
|
28
|
+
# @option params [String] :username desired username (generated if omitted)
|
|
29
|
+
# @param opts [Hash] per-request options
|
|
30
|
+
# @return [AdminUser] the newly created user record
|
|
31
|
+
#
|
|
32
|
+
# @example
|
|
33
|
+
# client.admin_users.create(
|
|
34
|
+
# email: "jane@example.com",
|
|
35
|
+
# name: "Jane Doe"
|
|
36
|
+
# )
|
|
37
|
+
#
|
|
38
|
+
# @see https://developers.forem.com/api/v1#/operations/postAdminUsersCreate
|
|
39
|
+
def create(params = {}, opts = {})
|
|
40
|
+
AdminUser.create(params, opts_with_requestor(opts))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Link an external identity to a user.
|
|
44
|
+
#
|
|
45
|
+
# @param user_id [Integer, String] the Forem user ID.
|
|
46
|
+
# @param provider [String] the identity provider name.
|
|
47
|
+
# @param uid [String] the provider's stable user identifier.
|
|
48
|
+
# @param opts [Hash] per-request options.
|
|
49
|
+
# @return [ForemObject] the linked identity.
|
|
50
|
+
def link_identity(user_id, provider:, uid:, **opts)
|
|
51
|
+
AdminUser.link_identity(
|
|
52
|
+
user_id,
|
|
53
|
+
provider: provider,
|
|
54
|
+
uid: uid,
|
|
55
|
+
**opts_with_requestor(opts)
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Submit multiple external identity links in one request.
|
|
60
|
+
#
|
|
61
|
+
# @param provider [String] the identity provider shared by the identities.
|
|
62
|
+
# @param identities [Array<Hash>] identity hashes containing +user_id+ and
|
|
63
|
+
# +uid+.
|
|
64
|
+
# @param opts [Hash] per-request options.
|
|
65
|
+
# @return [Array<ForemObject>] per-item results containing +user_id+,
|
|
66
|
+
# +status+, and an +error_code+ when that item fails.
|
|
67
|
+
def bulk_link_identities(provider:, identities:, **opts)
|
|
68
|
+
AdminUser.bulk_link_identities(
|
|
69
|
+
provider: provider,
|
|
70
|
+
identities: identities,
|
|
71
|
+
**opts_with_requestor(opts)
|
|
72
|
+
)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# List a user's linked external identities.
|
|
76
|
+
#
|
|
77
|
+
# @param user_id [Integer, String] the Forem user ID.
|
|
78
|
+
# @param opts [Hash] per-request options.
|
|
79
|
+
# @return [Array<ForemObject>] the user's linked identities.
|
|
80
|
+
def identities(user_id, **opts)
|
|
81
|
+
AdminUser.identities(user_id, **opts_with_requestor(opts))
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Unlink an external identity from a user.
|
|
85
|
+
#
|
|
86
|
+
# @param user_id [Integer, String] the Forem user ID.
|
|
87
|
+
# @param identity_id [Integer, String] the linked identity ID.
|
|
88
|
+
# @param opts [Hash] per-request options.
|
|
89
|
+
# @return [ForemObject, nil] the unlinked identity, or +nil+ for an empty
|
|
90
|
+
# response.
|
|
91
|
+
def unlink_identity(user_id, identity_id, **opts)
|
|
92
|
+
AdminUser.unlink_identity(
|
|
93
|
+
user_id,
|
|
94
|
+
identity_id,
|
|
95
|
+
**opts_with_requestor(opts)
|
|
96
|
+
)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Update the email newsletter notification setting for a user.
|
|
100
|
+
#
|
|
101
|
+
# @param user_id [Integer, String] the Forem user ID.
|
|
102
|
+
# @param email_newsletter [Boolean] whether newsletter email is enabled.
|
|
103
|
+
# @param opts [Hash] per-request options.
|
|
104
|
+
# @return [ForemObject] the updated notification setting.
|
|
105
|
+
def update_notification_settings(user_id, email_newsletter:, **opts)
|
|
106
|
+
AdminUser.update_notification_settings(
|
|
107
|
+
user_id,
|
|
108
|
+
email_newsletter: email_newsletter,
|
|
109
|
+
**opts_with_requestor(opts)
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module Forem
|
|
2
|
+
module Services
|
|
3
|
+
# Service for interacting with the Forem Agent Sessions API.
|
|
4
|
+
#
|
|
5
|
+
# Agent sessions enable automated or AI-driven interactions with the Forem
|
|
6
|
+
# platform. The presign endpoint provides a pre-signed URL for uploading
|
|
7
|
+
# assets associated with a session.
|
|
8
|
+
# Access via {Client#agent_sessions}. All methods inject the client's
|
|
9
|
+
# requestor automatically so no additional configuration is required.
|
|
10
|
+
#
|
|
11
|
+
# @example
|
|
12
|
+
# client = Forem::Client.new("your-api-key")
|
|
13
|
+
# sessions = client.agent_sessions.list
|
|
14
|
+
# session = client.agent_sessions.create(name: "My Agent")
|
|
15
|
+
#
|
|
16
|
+
# @see AgentSession
|
|
17
|
+
# @see https://developers.forem.com/api/v1#/operations/getAgentSessions
|
|
18
|
+
class AgentSessionService < BaseService
|
|
19
|
+
# List all agent sessions.
|
|
20
|
+
#
|
|
21
|
+
# @param params [Hash] query parameters
|
|
22
|
+
# @option params [Integer] :page page number (default: 1)
|
|
23
|
+
# @option params [Integer] :per_page number of results per page
|
|
24
|
+
# @param opts [Hash] per-request options
|
|
25
|
+
# @return [Array<AgentSession>] list of agent sessions
|
|
26
|
+
#
|
|
27
|
+
# @example
|
|
28
|
+
# client.agent_sessions.list
|
|
29
|
+
#
|
|
30
|
+
# @see https://developers.forem.com/api/v1#/operations/getAgentSessions
|
|
31
|
+
def list(params = {}, opts = {})
|
|
32
|
+
AgentSession.list(params, opts_with_requestor(opts))
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Create a new agent session.
|
|
36
|
+
#
|
|
37
|
+
# @param params [Hash] session attributes
|
|
38
|
+
# @option params [String] :name display name for the session
|
|
39
|
+
# @param opts [Hash] per-request options
|
|
40
|
+
# @return [AgentSession] the newly created agent session
|
|
41
|
+
#
|
|
42
|
+
# @example
|
|
43
|
+
# session = client.agent_sessions.create(name: "Content Generation Bot")
|
|
44
|
+
#
|
|
45
|
+
# @see https://developers.forem.com/api/v1#/operations/createAgentSession
|
|
46
|
+
def create(params = {}, opts = {})
|
|
47
|
+
AgentSession.create(params, opts_with_requestor(opts))
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Retrieve a single agent session by its numeric ID.
|
|
51
|
+
#
|
|
52
|
+
# @param id [Integer, String] the session ID
|
|
53
|
+
# @param opts [Hash] per-request options
|
|
54
|
+
# @return [AgentSession] the session with the given ID
|
|
55
|
+
#
|
|
56
|
+
# @example
|
|
57
|
+
# client.agent_sessions.retrieve(14)
|
|
58
|
+
#
|
|
59
|
+
# @see https://developers.forem.com/api/v1#/operations/getAgentSessionById
|
|
60
|
+
def retrieve(id, opts = {})
|
|
61
|
+
AgentSession.retrieve(id, opts_with_requestor(opts))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Obtain a pre-signed URL for uploading a file associated with an agent
|
|
65
|
+
# session.
|
|
66
|
+
#
|
|
67
|
+
# @param params [Hash] presign request parameters
|
|
68
|
+
# @option params [String] :filename name of the file to upload
|
|
69
|
+
# @option params [String] :mime_type MIME type of the file
|
|
70
|
+
# @param opts [Hash] per-request options
|
|
71
|
+
# @return [AgentSession] object containing the pre-signed upload URL and
|
|
72
|
+
# related metadata
|
|
73
|
+
#
|
|
74
|
+
# @example
|
|
75
|
+
# presign_data = client.agent_sessions.presign(
|
|
76
|
+
# filename: "image.png",
|
|
77
|
+
# mime_type: "image/png"
|
|
78
|
+
# )
|
|
79
|
+
# puts presign_data.upload_url
|
|
80
|
+
#
|
|
81
|
+
# @see https://developers.forem.com/api/v1
|
|
82
|
+
def presign(params = {}, opts = {})
|
|
83
|
+
AgentSession.presign(params, opts_with_requestor(opts))
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
module Forem
|
|
2
|
+
module Services
|
|
3
|
+
# Service for interacting with the Forem Analytics API.
|
|
4
|
+
#
|
|
5
|
+
# Provides engagement and traffic data for articles and organizations.
|
|
6
|
+
# Access via {Client#analytics}. All methods inject the client's requestor
|
|
7
|
+
# automatically so no additional configuration is required.
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# client = Forem::Client.new("your-api-key")
|
|
11
|
+
# totals = client.analytics.totals(username: "jsmith")
|
|
12
|
+
# daily = client.analytics.historical(username: "jsmith", start: "2024-01-01")
|
|
13
|
+
#
|
|
14
|
+
# @see Analytics
|
|
15
|
+
# @see https://developers.forem.com/api/v1
|
|
16
|
+
class AnalyticsService < BaseService
|
|
17
|
+
# Retrieve total engagement metrics for a user or organization.
|
|
18
|
+
#
|
|
19
|
+
# Returns all-time totals for page views, reactions, comments, and
|
|
20
|
+
# follows.
|
|
21
|
+
#
|
|
22
|
+
# @param params [Hash] query parameters
|
|
23
|
+
# @option params [String] :username filter metrics by author username
|
|
24
|
+
# @option params [String] :organization_id filter metrics by organization
|
|
25
|
+
# ID
|
|
26
|
+
# @param opts [Hash] per-request options
|
|
27
|
+
# @return [Analytics] total engagement metrics
|
|
28
|
+
#
|
|
29
|
+
# @example
|
|
30
|
+
# client.analytics.totals(username: "jsmith")
|
|
31
|
+
#
|
|
32
|
+
# @see https://developers.forem.com/api/v1
|
|
33
|
+
def totals(params = {}, opts = {})
|
|
34
|
+
Analytics.totals(params, opts_with_requestor(opts))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Retrieve historical engagement metrics broken down by day.
|
|
38
|
+
#
|
|
39
|
+
# @param params [Hash] query parameters
|
|
40
|
+
# @option params [String] :username filter by author username
|
|
41
|
+
# @option params [String] :organization_id filter by organization ID
|
|
42
|
+
# @option params [String] :start start date in ISO 8601 format
|
|
43
|
+
# (e.g. "2024-01-01")
|
|
44
|
+
# @option params [String] :end end date in ISO 8601 format
|
|
45
|
+
# @param opts [Hash] per-request options
|
|
46
|
+
# @return [Array<Analytics>] daily breakdown of engagement metrics
|
|
47
|
+
#
|
|
48
|
+
# @example
|
|
49
|
+
# client.analytics.historical(
|
|
50
|
+
# username: "jsmith",
|
|
51
|
+
# start: "2024-01-01",
|
|
52
|
+
# end: "2024-03-31"
|
|
53
|
+
# )
|
|
54
|
+
#
|
|
55
|
+
# @see https://developers.forem.com/api/v1
|
|
56
|
+
def historical(params = {}, opts = {})
|
|
57
|
+
Analytics.historical(params, opts_with_requestor(opts))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Retrieve engagement metrics for the past 24 hours.
|
|
61
|
+
#
|
|
62
|
+
# @param params [Hash] query parameters
|
|
63
|
+
# @option params [String] :username filter by author username
|
|
64
|
+
# @option params [String] :organization_id filter by organization ID
|
|
65
|
+
# @param opts [Hash] per-request options
|
|
66
|
+
# @return [Analytics] metrics for the past day
|
|
67
|
+
#
|
|
68
|
+
# @example
|
|
69
|
+
# client.analytics.past_day(username: "jsmith")
|
|
70
|
+
#
|
|
71
|
+
# @see https://developers.forem.com/api/v1
|
|
72
|
+
def past_day(params = {}, opts = {})
|
|
73
|
+
Analytics.past_day(params, opts_with_requestor(opts))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Retrieve referrer traffic data for a user or organization's content.
|
|
77
|
+
#
|
|
78
|
+
# @param params [Hash] query parameters
|
|
79
|
+
# @option params [String] :username filter by author username
|
|
80
|
+
# @option params [String] :organization_id filter by organization ID
|
|
81
|
+
# @param opts [Hash] per-request options
|
|
82
|
+
# @return [Array<Analytics>] referrer breakdown showing traffic sources
|
|
83
|
+
#
|
|
84
|
+
# @example
|
|
85
|
+
# client.analytics.referrers(username: "jsmith")
|
|
86
|
+
#
|
|
87
|
+
# @see https://developers.forem.com/api/v1
|
|
88
|
+
def referrers(params = {}, opts = {})
|
|
89
|
+
Analytics.referrers(params, opts_with_requestor(opts))
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
module Forem
|
|
2
|
+
module Services
|
|
3
|
+
# Service for interacting with the Forem Articles API.
|
|
4
|
+
#
|
|
5
|
+
# Access via {Client#articles}. All methods inject the client's requestor
|
|
6
|
+
# automatically so no additional configuration is required.
|
|
7
|
+
#
|
|
8
|
+
# @example
|
|
9
|
+
# client = Forem::Client.new("your-api-key")
|
|
10
|
+
# service = client.articles
|
|
11
|
+
# service.list(per_page: 5, tag: "ruby")
|
|
12
|
+
#
|
|
13
|
+
# @see Article
|
|
14
|
+
# @see https://developers.forem.com/api/v1#/operations/getArticles
|
|
15
|
+
class ArticleService < BaseService
|
|
16
|
+
# List published articles.
|
|
17
|
+
#
|
|
18
|
+
# @param params [Hash] query parameters
|
|
19
|
+
# @option params [Integer] :page page number (default: 1)
|
|
20
|
+
# @option params [Integer] :per_page number of results per page (max: 1000)
|
|
21
|
+
# @option params [String] :tag filter by a single tag name
|
|
22
|
+
# @option params [String] :tags comma-separated list of tags to include
|
|
23
|
+
# @option params [String] :tags_exclude comma-separated list of tags to exclude
|
|
24
|
+
# @option params [String] :username filter by author username
|
|
25
|
+
# @option params [String] :state article state ("fresh", "rising", "all")
|
|
26
|
+
# @option params [Integer] :top number of days back to look for top articles
|
|
27
|
+
# @option params [String] :collection_id filter by collection ID
|
|
28
|
+
# @param opts [Hash] per-request options
|
|
29
|
+
# @return [Array<Article>] list of published articles
|
|
30
|
+
#
|
|
31
|
+
# @example
|
|
32
|
+
# client.articles.list(tag: "ruby", per_page: 10)
|
|
33
|
+
#
|
|
34
|
+
# @see https://developers.forem.com/api/v1#/operations/getArticles
|
|
35
|
+
def list(params = {}, opts = {})
|
|
36
|
+
Article.list(params, opts_with_requestor(opts))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Create a new article.
|
|
40
|
+
#
|
|
41
|
+
# @param params [Hash] article attributes
|
|
42
|
+
# @option params [String] :title article title
|
|
43
|
+
# @option params [String] :body_markdown article body in Markdown
|
|
44
|
+
# @option params [Boolean] :published whether to publish immediately
|
|
45
|
+
# @option params [Array<String>] :tags list of tag names
|
|
46
|
+
# @option params [String] :series name of a series to add the article to
|
|
47
|
+
# @option params [String] :canonical_url canonical URL override
|
|
48
|
+
# @option params [String] :description article description / excerpt
|
|
49
|
+
# @param opts [Hash] per-request options
|
|
50
|
+
# @return [Article] the newly created article
|
|
51
|
+
#
|
|
52
|
+
# @example
|
|
53
|
+
# client.articles.create(
|
|
54
|
+
# title: "Hello World",
|
|
55
|
+
# body_markdown: "# Hello\nThis is my first post.",
|
|
56
|
+
# published: true,
|
|
57
|
+
# tags: ["ruby", "beginners"]
|
|
58
|
+
# )
|
|
59
|
+
#
|
|
60
|
+
# @see https://developers.forem.com/api/v1#/operations/createArticle
|
|
61
|
+
def create(params = {}, opts = {})
|
|
62
|
+
Article.create(params, opts_with_requestor(opts))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Retrieve a single article by its numeric ID.
|
|
66
|
+
#
|
|
67
|
+
# @param id [Integer, String] the article ID
|
|
68
|
+
# @param opts [Hash] per-request options
|
|
69
|
+
# @return [Article] the article with the given ID
|
|
70
|
+
#
|
|
71
|
+
# @example
|
|
72
|
+
# client.articles.retrieve(12345)
|
|
73
|
+
#
|
|
74
|
+
# @see https://developers.forem.com/api/v1#/operations/getArticleById
|
|
75
|
+
def retrieve(id, opts = {})
|
|
76
|
+
Article.retrieve(id, opts_with_requestor(opts))
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Update an existing article.
|
|
80
|
+
#
|
|
81
|
+
# @param id [Integer, String] the article ID to update
|
|
82
|
+
# @param params [Hash] article attributes to change
|
|
83
|
+
# @option params [String] :title new title
|
|
84
|
+
# @option params [String] :body_markdown new body in Markdown
|
|
85
|
+
# @option params [Boolean] :published publish or unpublish the article
|
|
86
|
+
# @option params [Array<String>] :tags updated list of tag names
|
|
87
|
+
# @param opts [Hash] per-request options
|
|
88
|
+
# @return [Article] the updated article
|
|
89
|
+
#
|
|
90
|
+
# @example
|
|
91
|
+
# client.articles.update(12345, title: "Updated Title", published: true)
|
|
92
|
+
#
|
|
93
|
+
# @see https://developers.forem.com/api/v1#/operations/updateArticle
|
|
94
|
+
def update(id, params = {}, opts = {})
|
|
95
|
+
Article.update(id, params, opts_with_requestor(opts))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# List articles authored by the authenticated user.
|
|
99
|
+
#
|
|
100
|
+
# @param params [Hash] query parameters
|
|
101
|
+
# @option params [Integer] :page page number (default: 1)
|
|
102
|
+
# @option params [Integer] :per_page number of results per page (max: 1000)
|
|
103
|
+
# @param opts [Hash] per-request options
|
|
104
|
+
# @return [Array<Article>] articles belonging to the current user
|
|
105
|
+
#
|
|
106
|
+
# @example
|
|
107
|
+
# client.articles.me(per_page: 30)
|
|
108
|
+
#
|
|
109
|
+
# @see https://developers.forem.com/api/v1#/operations/getUserArticles
|
|
110
|
+
def me(params = {}, opts = {})
|
|
111
|
+
Article.me(params, opts_with_requestor(opts))
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# List published articles authored by the authenticated user.
|
|
115
|
+
#
|
|
116
|
+
# @param params [Hash] query parameters
|
|
117
|
+
# @option params [Integer] :page page number (default: 1)
|
|
118
|
+
# @option params [Integer] :per_page number of results per page (max: 1000)
|
|
119
|
+
# @param opts [Hash] per-request options
|
|
120
|
+
# @return [Array<Article>] published articles belonging to the current user
|
|
121
|
+
#
|
|
122
|
+
# @example
|
|
123
|
+
# client.articles.me_published
|
|
124
|
+
#
|
|
125
|
+
# @see https://developers.forem.com/api/v1#/operations/getUserArticles
|
|
126
|
+
def me_published(params = {}, opts = {})
|
|
127
|
+
Article.me_published(params, opts_with_requestor(opts))
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# List unpublished articles (drafts) authored by the authenticated user.
|
|
131
|
+
#
|
|
132
|
+
# @param params [Hash] query parameters
|
|
133
|
+
# @option params [Integer] :page page number (default: 1)
|
|
134
|
+
# @option params [Integer] :per_page number of results per page (max: 1000)
|
|
135
|
+
# @param opts [Hash] per-request options
|
|
136
|
+
# @return [Array<Article>] unpublished articles belonging to the current user
|
|
137
|
+
#
|
|
138
|
+
# @example
|
|
139
|
+
# client.articles.me_unpublished
|
|
140
|
+
#
|
|
141
|
+
# @see https://developers.forem.com/api/v1#/operations/getUserArticles
|
|
142
|
+
def me_unpublished(params = {}, opts = {})
|
|
143
|
+
Article.me_unpublished(params, opts_with_requestor(opts))
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# List all articles (published and unpublished) authored by the authenticated user.
|
|
147
|
+
#
|
|
148
|
+
# @param params [Hash] query parameters
|
|
149
|
+
# @option params [Integer] :page page number (default: 1)
|
|
150
|
+
# @option params [Integer] :per_page number of results per page (max: 1000)
|
|
151
|
+
# @param opts [Hash] per-request options
|
|
152
|
+
# @return [Array<Article>] all articles belonging to the current user
|
|
153
|
+
#
|
|
154
|
+
# @example
|
|
155
|
+
# client.articles.me_all
|
|
156
|
+
#
|
|
157
|
+
# @see https://developers.forem.com/api/v1#/operations/getUserArticles
|
|
158
|
+
def me_all(params = {}, opts = {})
|
|
159
|
+
Article.me_all(params, opts_with_requestor(opts))
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# List the most recently published articles.
|
|
163
|
+
#
|
|
164
|
+
# @param params [Hash] query parameters
|
|
165
|
+
# @option params [Integer] :page page number (default: 1)
|
|
166
|
+
# @option params [Integer] :per_page number of results per page (max: 1000)
|
|
167
|
+
# @param opts [Hash] per-request options
|
|
168
|
+
# @return [Array<Article>] latest published articles in chronological order
|
|
169
|
+
#
|
|
170
|
+
# @example
|
|
171
|
+
# client.articles.latest(per_page: 20)
|
|
172
|
+
#
|
|
173
|
+
# @see https://developers.forem.com/api/v1#/operations/getLatestArticles
|
|
174
|
+
def latest(params = {}, opts = {})
|
|
175
|
+
Article.latest(params, opts_with_requestor(opts))
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Search articles by keyword.
|
|
179
|
+
#
|
|
180
|
+
# @param params [Hash] query parameters
|
|
181
|
+
# @option params [String] :q the search term
|
|
182
|
+
# @option params [Integer] :page page number (default: 1)
|
|
183
|
+
# @option params [Integer] :per_page number of results per page
|
|
184
|
+
# @param opts [Hash] per-request options
|
|
185
|
+
# @return [Array<Article>] articles matching the search query
|
|
186
|
+
#
|
|
187
|
+
# @example
|
|
188
|
+
# client.articles.search(q: "ruby on rails")
|
|
189
|
+
#
|
|
190
|
+
# @see https://developers.forem.com/api/v1#/operations/searchArticles
|
|
191
|
+
def search(params = {}, opts = {})
|
|
192
|
+
Article.search(params, opts_with_requestor(opts))
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Semantically search articles using Forem's embeddings-based search.
|
|
196
|
+
#
|
|
197
|
+
# Unlike +search+ (keyword matching), this finds articles whose meaning
|
|
198
|
+
# is close to the query text. Requires authentication.
|
|
199
|
+
#
|
|
200
|
+
# @param params [Hash] query parameters
|
|
201
|
+
# @option params [String] :q the search query text (required)
|
|
202
|
+
# @option params [Integer] :page page number (default: 1)
|
|
203
|
+
# @option params [Integer] :per_page number of results per page (default: 10, max: 50)
|
|
204
|
+
# @option params [Float] :threshold optional cosine distance threshold (0.0-2.0)
|
|
205
|
+
# @param opts [Hash] per-request options
|
|
206
|
+
# @return [Array<Article>] articles matching the query, each exposing
|
|
207
|
+
# +distance+ and +similarity+ attributes
|
|
208
|
+
#
|
|
209
|
+
# @example
|
|
210
|
+
# client.articles.semantic_search(q: "how to deploy rails apps")
|
|
211
|
+
#
|
|
212
|
+
# @see https://developers.forem.com/api/v1#/operations/semanticSearchArticles
|
|
213
|
+
def semantic_search(params = {}, opts = {})
|
|
214
|
+
Article.semantic_search(params, opts_with_requestor(opts))
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
# Retrieve an article by its author username and slug.
|
|
218
|
+
#
|
|
219
|
+
# @param username [String] the author's username
|
|
220
|
+
# @param slug [String] the article slug
|
|
221
|
+
# @param opts [Hash] per-request options
|
|
222
|
+
# @return [Article] the matching article
|
|
223
|
+
#
|
|
224
|
+
# @example
|
|
225
|
+
# client.articles.retrieve_by_path("jsmith", "my-great-post")
|
|
226
|
+
#
|
|
227
|
+
# @see https://developers.forem.com/api/v1#/operations/getArticleByPath
|
|
228
|
+
def retrieve_by_path(username, slug, opts = {})
|
|
229
|
+
Article.retrieve_by_path(username, slug, opts_with_requestor(opts))
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|