forem-ruby 0.1.0.beta3 → 0.1.0.beta5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e948a4e3001066a9344c0609f3493a6c582b31fab01ff88dcc418e0dcc67c1c
4
- data.tar.gz: ae8872806a2a55f49d4879561cf9bf5b993da167ec665a43c48390f3ced505cd
3
+ metadata.gz: 83797be860d88f26465e8497d17232bc764baa5c297fde6ff208e50f37fd5a94
4
+ data.tar.gz: 2997d86bd809479c4085c2d2308202a2b1938415d74d0350ca5b84da87f9101f
5
5
  SHA512:
6
- metadata.gz: 3e2846154e8d12dbb1b78b3b7c46f44fc7b210c064429630af165164a59a45c5a336160d63c65cfa64fd9c3300e75a2ddb14eda607b7b660ba11fde557ae6628
7
- data.tar.gz: 970dcc16e46767419612226f5ad6bd085e340e1617e99a5bf034685cebde22acbe5ac1b0abda6621160aeeed1b81b221f94c647626b1073e23538621937a1f46
6
+ metadata.gz: '095016c6e947721f81f23fbb63e82afb6c5f7b45a2253d83b6151d2f97977d097d1759e5a0fd9f13800f5607914e2a633a01485a8300502e090ee7be7a9760b1'
7
+ data.tar.gz: a7c39b213002376f16d5d06563759ee3cd03ac6ec54889f4bdf1ed9545d57a89334ecd93c2a00afe12549d1b54cd8ba64e0c9d1a87c4baabcf8359ad12c95fd6
data/lib/forem/client.rb CHANGED
@@ -61,6 +61,26 @@ module Forem
61
61
  # client.users.retrieve(42)
62
62
  def users; @users ||= Services::UserService.new(@requestor); end
63
63
 
64
+ # Access the Badges API.
65
+ #
66
+ # @return [Services::BadgeService] the badges service
67
+ # @see https://developers.forem.com/api/v1
68
+ #
69
+ # @example
70
+ # client.badges.list(page: 1)
71
+ # client.badges.retrieve(45)
72
+ def badges; @badges ||= Services::BadgeService.new(@requestor); end
73
+
74
+ # Access the Badge Achievements API.
75
+ #
76
+ # @return [Services::BadgeAchievementService] the badge achievements service
77
+ # @see https://developers.forem.com/api/v1
78
+ #
79
+ # @example
80
+ # client.badge_achievements.create(user_id: 123, badge_id: 45)
81
+ # client.badge_achievements.delete(9876)
82
+ def badge_achievements; @badge_achievements ||= Services::BadgeAchievementService.new(@requestor); end
83
+
64
84
  # Access the Comments API.
65
85
  #
66
86
  # @return [Services::CommentService] the comments service
data/lib/forem/errors.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require "json"
2
+
1
3
  module Forem
2
4
  # Base error class for all errors raised by the forem-ruby library.
3
5
  #
@@ -45,6 +47,28 @@ module Forem
45
47
  @code = code
46
48
  super(message)
47
49
  end
50
+
51
+ # The response body parsed as JSON.
52
+ #
53
+ # Useful when the API returns structured detail alongside an error. An empty
54
+ # or unparseable body yields +nil+.
55
+ #
56
+ # @return [Hash, Array, nil] the parsed body, or +nil+ when there is
57
+ # nothing parseable to return.
58
+ #
59
+ # @example Reading a field the API returned with the error
60
+ # begin
61
+ # client.badge_achievements.create(user_id: 123, badge_id: 45)
62
+ # rescue Forem::ConflictError => e
63
+ # e.parsed_body&.dig("achievement_id")
64
+ # end
65
+ def parsed_body
66
+ return @parsed_body if defined?(@parsed_body)
67
+
68
+ @parsed_body = (JSON.parse(http_body) if http_body && !http_body.empty?)
69
+ rescue JSON::ParserError
70
+ @parsed_body = nil
71
+ end
48
72
  end
49
73
 
50
74
  # Raised when the server responds with HTTP 401 Unauthorized.
@@ -0,0 +1,61 @@
1
+ module Forem
2
+ # Represents a badge that can be awarded to users on a Forem instance.
3
+ #
4
+ # Badges are awards that can be given to users. Badges support full CRUD
5
+ # operations.
6
+ #
7
+ # Available operations (via mixins):
8
+ # - +List+ — GET /api/badges
9
+ # - +Create+ — POST /api/badges
10
+ # - +Retrieve+ — GET /api/badges/:id
11
+ # - +Update+ — PUT /api/badges/:id
12
+ # - +Delete+ — class- and instance-level delete (DELETE /api/badges/:id)
13
+ # - +Save+ — instance-level save (create or update)
14
+ #
15
+ # == Badge Fields
16
+ #
17
+ # - +id+ (Integer) — Assigned by the API; not writable
18
+ # - +title+ (String) — Badge title; unique across the instance
19
+ # - +slug+ (String) — Generated from +title+ by the API; not writable
20
+ # - +description+ (String) — Badge description
21
+ # - +badge_image+ (String) — Badge image URL; set on write with
22
+ # +remote_badge_image_url+
23
+ # - +credits_awarded+ (Integer) — Credits granted alongside the badge
24
+ # - +allow_multiple_awards+ (Boolean) — Whether the badge can be awarded to the same user more than once
25
+ # - +created_at+ / +updated_at+ (String) — ISO 8601 timestamps; not writable
26
+ #
27
+ # == Authentication
28
+ #
29
+ # All badge endpoints require an admin API key, reads included.
30
+ #
31
+ # == Pagination
32
+ #
33
+ # +list+ returns a fixed 50 records per page.
34
+ #
35
+ # @example List every badge
36
+ # page = 1
37
+ # loop do
38
+ # badges = client.badges.list(page: page)
39
+ # break if badges.data.empty?
40
+ # badges.data.each { |b| puts "#{b.id}: #{b.title}" }
41
+ # page += 1
42
+ # end
43
+ #
44
+ # @example Retrieve a badge by ID
45
+ # badge = client.badges.retrieve(45)
46
+ # puts badge.title
47
+ #
48
+ # @see BadgeAchievement
49
+ # @see https://developers.forem.com/api/v1
50
+ class Badge < APIResource
51
+ extend APIOperations::Create
52
+ extend APIOperations::List
53
+ extend APIOperations::Retrieve
54
+ extend APIOperations::Update
55
+ include APIOperations::Delete
56
+ include APIOperations::Save
57
+
58
+ OBJECT_NAME = "badge"
59
+ RESOURCE_PATH = "/api/badges"
60
+ end
61
+ end
@@ -0,0 +1,63 @@
1
+ module Forem
2
+ # Represents a badge awarded to a specific user.
3
+ #
4
+ # Creating a badge achievement awards a badge; deleting one revokes it. There
5
+ # is no update endpoint.
6
+ #
7
+ # Available operations (via mixins):
8
+ # - +List+ — GET /api/badge_achievements
9
+ # - +Create+ — POST /api/badge_achievements
10
+ # - +Retrieve+ — GET /api/badge_achievements/:id
11
+ # - +Delete+ — class- and instance-level delete (DELETE /api/badge_achievements/:id)
12
+ #
13
+ # == BadgeAchievement Fields
14
+ #
15
+ # - +id+ (Integer) — Assigned by the API; not writable
16
+ # - +user_id+ (Integer) — The user the badge was awarded to
17
+ # - +badge_id+ (Integer) — The badge that was awarded
18
+ # - +rewarder_id+ (Integer) — The awarding user; not writable, so always
19
+ # +null+ on achievements created through the API
20
+ # - +rewarding_context_message_markdown+ (String) — Message shown with the award, in markdown
21
+ # - +rewarding_context_message+ (String) — Rendered from
22
+ # +rewarding_context_message_markdown+ by the API; not writable
23
+ # - +include_default_description+ (Boolean) — Whether the badge description accompanies the message
24
+ # - +metadata+ (ForemObject) — Arbitrary key/value data supplied for context. Defaults to +{}+.
25
+ # - +created_at+ / +updated_at+ (String) — ISO 8601 timestamps; not writable
26
+ #
27
+ # == Authentication
28
+ #
29
+ # All badge achievement endpoints require an admin API key, reads included.
30
+ #
31
+ # == Pagination
32
+ #
33
+ # +list+ returns a fixed 50 records per page.
34
+ #
35
+ # @example Award a badge
36
+ # achievement = client.badge_achievements.create(
37
+ # user_id: 123,
38
+ # badge_id: 45
39
+ # )
40
+ # puts achievement.id
41
+ #
42
+ # @example Award a badge with caller-supplied metadata
43
+ # client.badge_achievements.create(
44
+ # user_id: 123,
45
+ # badge_id: 45,
46
+ # metadata: { entitlement_id: "01a0…", source: "core" }
47
+ # )
48
+ #
49
+ # @example Revoke a badge
50
+ # client.badge_achievements.delete(9876)
51
+ #
52
+ # @see Badge
53
+ # @see https://developers.forem.com/api/v1
54
+ class BadgeAchievement < APIResource
55
+ extend APIOperations::Create
56
+ extend APIOperations::List
57
+ extend APIOperations::Retrieve
58
+ include APIOperations::Delete
59
+
60
+ OBJECT_NAME = "badge_achievement"
61
+ RESOURCE_PATH = "/api/badge_achievements"
62
+ end
63
+ end
@@ -0,0 +1,110 @@
1
+ module Forem
2
+ module Services
3
+ # Service for interacting with the Forem Badge Achievements API.
4
+ #
5
+ # A badge achievement is a badge awarded to a user; creating one awards the
6
+ # badge and deleting one revokes it. These endpoints require an API key with
7
+ # admin-level privileges.
8
+ #
9
+ # Access via {Client#badge_achievements}. All methods inject the client's
10
+ # requestor automatically so no additional configuration is required.
11
+ #
12
+ # @example
13
+ # client = Forem::Client.new("your-admin-api-key")
14
+ # client.badge_achievements.create(user_id: 123, badge_id: 45)
15
+ #
16
+ # @see BadgeAchievement
17
+ # @see BadgeService
18
+ # @see https://developers.forem.com/api/v1
19
+ class BadgeAchievementService < BaseService
20
+ # List badge achievements, most recently created first.
21
+ #
22
+ # Returns a fixed 50 records per page.
23
+ #
24
+ # @param params [Hash] query parameters
25
+ # @option params [Integer] :page page number (default: 1)
26
+ # @param opts [Hash] per-request options
27
+ # @return [ListObject<BadgeAchievement>] a page of achievements
28
+ #
29
+ # @example
30
+ # client.badge_achievements.list(page: 2)
31
+ #
32
+ # @see https://developers.forem.com/api/v1
33
+ def list(params = {}, opts = {})
34
+ BadgeAchievement.list(params, opts_with_requestor(opts))
35
+ end
36
+
37
+ # Retrieve a single badge achievement by its numeric ID.
38
+ #
39
+ # @param id [Integer, String] the achievement ID
40
+ # @param opts [Hash] per-request options
41
+ # @return [BadgeAchievement] the achievement with the given ID
42
+ # @raise [NotFoundError] on HTTP 404
43
+ #
44
+ # @example
45
+ # client.badge_achievements.retrieve(9876)
46
+ #
47
+ # @see https://developers.forem.com/api/v1
48
+ def retrieve(id, opts = {})
49
+ BadgeAchievement.retrieve(id, opts_with_requestor(opts))
50
+ end
51
+
52
+ # Award a badge to a user.
53
+ #
54
+ # If the badge cannot be awarded more than once and the user already holds
55
+ # it, this raises {ConflictError} (HTTP 409). The response carries
56
+ # +achievement_id+, the id of the award that blocked the request.
57
+ #
58
+ # begin
59
+ # client.badge_achievements.create(user_id: 123, badge_id: 45)
60
+ # rescue Forem::ConflictError => e
61
+ # existing_id = e.parsed_body&.dig("achievement_id")
62
+ # end
63
+ #
64
+ # @param params [Hash] achievement attributes
65
+ # @option params [Integer] :user_id the user ID (required)
66
+ # @option params [Integer] :badge_id the badge ID (required)
67
+ # @option params [String] :rewarding_context_message_markdown a message
68
+ # shown with the award
69
+ # @option params [Boolean] :include_default_description whether to show
70
+ # the badge's own description alongside the message (default true)
71
+ # @option params [Hash] :metadata arbitrary key/value data stored with the
72
+ # achievement for context
73
+ # @param opts [Hash] per-request options
74
+ # @return [BadgeAchievement] the newly created achievement
75
+ # @raise [ConflictError] on HTTP 409 when the user already holds a badge
76
+ # that cannot be awarded more than once
77
+ # @raise [InvalidRequestError] on HTTP 422
78
+ #
79
+ # @example
80
+ # client.badge_achievements.create(
81
+ # user_id: 123,
82
+ # badge_id: 45,
83
+ # metadata: { entitlement_id: "01a0…" }
84
+ # )
85
+ #
86
+ # @see https://developers.forem.com/api/v1
87
+ def create(params = {}, opts = {})
88
+ BadgeAchievement.create(
89
+ enveloped(:badge_achievement, params),
90
+ opts_with_requestor(opts),
91
+ )
92
+ end
93
+
94
+ # Revoke a badge by deleting the achievement.
95
+ #
96
+ # @param id [Integer, String] the achievement ID to delete
97
+ # @param opts [Hash] per-request options
98
+ # @return [nil] returns nil on success
99
+ # @raise [NotFoundError] on HTTP 404
100
+ #
101
+ # @example
102
+ # client.badge_achievements.delete(9876)
103
+ #
104
+ # @see https://developers.forem.com/api/v1
105
+ def delete(id, opts = {})
106
+ BadgeAchievement.delete(id, opts_with_requestor(opts))
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,117 @@
1
+ module Forem
2
+ module Services
3
+ # Service for interacting with the Forem Badges API.
4
+ #
5
+ # Badges are awards that can be given to users. These endpoints require
6
+ # an API key with admin-level privileges.
7
+ #
8
+ # Access via {Client#badges}. All methods inject the client's requestor
9
+ # automatically so no additional configuration is required.
10
+ #
11
+ # @example
12
+ # client = Forem::Client.new("your-admin-api-key")
13
+ # badges = client.badges.list
14
+ # badge = client.badges.retrieve(45)
15
+ #
16
+ # @see Badge
17
+ # @see BadgeAchievementService for awarding a badge to a user
18
+ # @see https://developers.forem.com/api/v1
19
+ class BadgeService < BaseService
20
+ # List badges, most recently created first.
21
+ #
22
+ # Returns a fixed 50 records per page.
23
+ #
24
+ # @param params [Hash] query parameters
25
+ # @option params [Integer] :page page number (default: 1)
26
+ # @param opts [Hash] per-request options
27
+ # @return [ListObject<Badge>] a page of badges
28
+ #
29
+ # @example
30
+ # client.badges.list(page: 2)
31
+ #
32
+ # @see https://developers.forem.com/api/v1
33
+ def list(params = {}, opts = {})
34
+ Badge.list(params, opts_with_requestor(opts))
35
+ end
36
+
37
+ # Retrieve a single badge by its numeric ID.
38
+ #
39
+ # @param id [Integer, String] the badge ID
40
+ # @param opts [Hash] per-request options
41
+ # @return [Badge] the badge with the given ID
42
+ # @raise [NotFoundError] on HTTP 404
43
+ #
44
+ # @example
45
+ # client.badges.retrieve(45)
46
+ #
47
+ # @see https://developers.forem.com/api/v1
48
+ def retrieve(id, opts = {})
49
+ Badge.retrieve(id, opts_with_requestor(opts))
50
+ end
51
+
52
+ # Create a new badge.
53
+ #
54
+ # @param params [Hash] badge attributes
55
+ # @option params [String] :title badge title (must be unique)
56
+ # @option params [String] :description badge description
57
+ # @option params [String] :remote_badge_image_url URL to fetch the badge
58
+ # image from
59
+ # @option params [Integer] :credits_awarded credits granted alongside the
60
+ # badge (default 0)
61
+ # @option params [Boolean] :allow_multiple_awards whether the badge can
62
+ # be awarded to the same user more than once (default false)
63
+ # @param opts [Hash] per-request options
64
+ # @return [Badge] the newly created badge
65
+ # @raise [InvalidRequestError] on HTTP 422 (validation errors)
66
+ #
67
+ # @example
68
+ # client.badges.create(
69
+ # title: "Forem Contributor",
70
+ # description: "Contributed an article",
71
+ # remote_badge_image_url: "https://example.com/badge.png"
72
+ # )
73
+ #
74
+ # @see https://developers.forem.com/api/v1
75
+ def create(params = {}, opts = {})
76
+ Badge.create(enveloped(:badge, params), opts_with_requestor(opts))
77
+ end
78
+
79
+ # Update an existing badge.
80
+ #
81
+ # @param id [Integer, String] the badge ID to update
82
+ # @param params [Hash] badge attributes to change
83
+ # @option params [String] :title new title
84
+ # @option params [String] :description new description
85
+ # @option params [Integer] :credits_awarded new credit amount
86
+ # @option params [Boolean] :allow_multiple_awards new multiple-award
87
+ # setting
88
+ # @param opts [Hash] per-request options
89
+ # @return [Badge] the updated badge
90
+ # @raise [NotFoundError] on HTTP 404
91
+ # @raise [InvalidRequestError] on HTTP 422 (validation errors)
92
+ #
93
+ # @example
94
+ # client.badges.update(45, description: "Updated description")
95
+ #
96
+ # @see https://developers.forem.com/api/v1
97
+ def update(id, params = {}, opts = {})
98
+ Badge.update(id, enveloped(:badge, params), opts_with_requestor(opts))
99
+ end
100
+
101
+ # Delete a badge.
102
+ #
103
+ # @param id [Integer, String] the badge ID to delete
104
+ # @param opts [Hash] per-request options
105
+ # @return [nil] returns nil on success
106
+ # @raise [NotFoundError] on HTTP 404
107
+ #
108
+ # @example
109
+ # client.badges.delete(45)
110
+ #
111
+ # @see https://developers.forem.com/api/v1
112
+ def delete(id, opts = {})
113
+ Badge.delete(id, opts_with_requestor(opts))
114
+ end
115
+ end
116
+ end
117
+ end
@@ -40,6 +40,26 @@ module Forem
40
40
  def opts_with_requestor(opts)
41
41
  opts.merge(requestor: @requestor)
42
42
  end
43
+
44
+ # Wrap flat attributes in the envelope key an endpoint expects.
45
+ #
46
+ # Some write endpoints expect a nested body
47
+ # (<tt>{ badge: { title: "..." } }</tt>). This lets service methods take
48
+ # flat attributes and nest them on the caller's behalf. Params that are
49
+ # already enveloped are passed through untouched, so both call styles
50
+ # work.
51
+ #
52
+ # @param key [Symbol] the envelope key (e.g. +:badge+)
53
+ # @param params [Hash] attributes, flat or already enveloped
54
+ # @return [Hash] the enveloped params
55
+ #
56
+ # @example
57
+ # enveloped(:badge, title: "Top 7") #=> { badge: { title: "Top 7" } }
58
+ def enveloped(key, params)
59
+ return params if params.key?(key) || params.key?(key.to_s)
60
+
61
+ { key => params }
62
+ end
43
63
  end
44
64
  end
45
65
  end
data/lib/forem/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Forem
2
2
  # The current version of the forem-ruby gem.
3
- VERSION = "0.1.0.beta3"
3
+ VERSION = "0.1.0.beta5"
4
4
  end
data/lib/forem.rb CHANGED
@@ -16,6 +16,8 @@ require "forem/api_operations/save"
16
16
  require "forem/api_resource"
17
17
  require "forem/api_requestor"
18
18
  require "forem/resources/article"
19
+ require "forem/resources/badge"
20
+ require "forem/resources/badge_achievement"
19
21
  require "forem/resources/user"
20
22
  require "forem/resources/comment"
21
23
  require "forem/resources/organization"
@@ -42,6 +44,8 @@ require "forem/resources/admin_concept"
42
44
  require "forem/resources/request_redirect"
43
45
  require "forem/services/base_service"
44
46
  require "forem/services/article_service"
47
+ require "forem/services/badge_service"
48
+ require "forem/services/badge_achievement_service"
45
49
  require "forem/services/user_service"
46
50
  require "forem/services/comment_service"
47
51
  require "forem/services/organization_service"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forem-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.beta3
4
+ version: 0.1.0.beta5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Forem
@@ -38,6 +38,8 @@ files:
38
38
  - lib/forem/resources/agent_session.rb
39
39
  - lib/forem/resources/analytics.rb
40
40
  - lib/forem/resources/article.rb
41
+ - lib/forem/resources/badge.rb
42
+ - lib/forem/resources/badge_achievement.rb
41
43
  - lib/forem/resources/billboard.rb
42
44
  - lib/forem/resources/comment.rb
43
45
  - lib/forem/resources/concept.rb
@@ -63,6 +65,8 @@ files:
63
65
  - lib/forem/services/agent_session_service.rb
64
66
  - lib/forem/services/analytics_service.rb
65
67
  - lib/forem/services/article_service.rb
68
+ - lib/forem/services/badge_achievement_service.rb
69
+ - lib/forem/services/badge_service.rb
66
70
  - lib/forem/services/base_service.rb
67
71
  - lib/forem/services/billboard_service.rb
68
72
  - lib/forem/services/comment_service.rb