Coverage Summary for Class: RewardResource (io.github.captnblubber.twitchkt.helix.resource)

Class Method, % Branch, % Line, % Instruction, %
RewardResource 100% (12/12) 91.7% (11/12) 98.5% (64/65) 99.3% (580/584)
RewardResource$create$1
RewardResource$delete$1
RewardResource$getAllRedemptions$$inlined$paginate$default$1 0% (0/1)
RewardResource$getAllRedemptions$1 100% (1/1) 100% (1/1) 100% (35/35)
RewardResource$getRedemptions$1
RewardResource$list$1
RewardResource$update$1
RewardResource$updateRedemptionStatus$1
Total 92.9% (13/14) 91.7% (11/12) 98.5% (65/66) 99.4% (615/619)


 package io.github.captnblubber.twitchkt.helix.resource
 
 import io.github.captnblubber.twitchkt.auth.RequiresScope
 import io.github.captnblubber.twitchkt.auth.TwitchScope
 import io.github.captnblubber.twitchkt.helix.Page
 import io.github.captnblubber.twitchkt.helix.internal.HelixHttpClient
 import io.github.captnblubber.twitchkt.helix.internal.requireFirst
 import io.github.captnblubber.twitchkt.helix.model.CreateRewardRequest
 import io.github.captnblubber.twitchkt.helix.model.CustomReward
 import io.github.captnblubber.twitchkt.helix.model.RedemptionSort
 import io.github.captnblubber.twitchkt.helix.model.RedemptionStatus
 import io.github.captnblubber.twitchkt.helix.model.RewardRedemption
 import io.github.captnblubber.twitchkt.helix.model.UpdateRewardRequest
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.onStart
 import kotlinx.serialization.Serializable
 
 /**
  * Twitch Helix Channel Points API resource.
  *
  * Provides methods for managing custom rewards and redemptions.
  *
  * @see <a href="https://dev.twitch.tv/docs/api/reference/#get-custom-reward">Twitch API Reference - Channel Points</a>
  */
 class RewardResource internal constructor(
     private val http: HelixHttpClient,
 ) {
     /**
      * [Twitch API: Get Custom Reward](https://dev.twitch.tv/docs/api/reference/#get-custom-reward)
      *
      * Gets a list of custom rewards that the specified broadcaster created. A channel may offer
      * a maximum of 50 rewards, which includes both enabled and disabled rewards.
      *
      * @param broadcasterId the ID of the broadcaster whose custom rewards you want to get.
      * This ID must match the user ID found in the OAuth token.
      * @param ids a list of IDs to filter the rewards by. You may specify a maximum of 50 IDs.
      * @param onlyManageableRewards a Boolean value that determines whether the response contains
      * only the custom rewards that the app may manage (the app is identified by the ID in the
      * Client-Id header). Set to `true` to get only the custom rewards that the app may manage.
      * The default is `false`.
      * @return the list of custom rewards, in ascending order by id.
      */
     @RequiresScope(TwitchScope.CHANNEL_READ_REDEMPTIONS, TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
     suspend fun list(
         broadcasterId: String,
         ids: List<String> = emptyList(),
         onlyManageableRewards: Boolean = false,
     ): List<CustomReward> {
         http.validateAnyScope(TwitchScope.CHANNEL_READ_REDEMPTIONS, TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
         val params =
             buildList {
                 add("broadcaster_id" to broadcasterId)
                 ids.forEach { add("id" to it) }
                 if (onlyManageableRewards) add("only_manageable_rewards" to "true")
             }
         return http.get<CustomReward>("channel_points/custom_rewards", params).data
     }
 
     /**
      * [Twitch API: Create Custom Rewards](https://dev.twitch.tv/docs/api/reference/#create-custom-rewards)
      *
      * Creates a Custom Reward in the broadcaster's channel. The maximum number of custom rewards
      * per channel is 50, which includes both enabled and disabled rewards.
      *
      * @param broadcasterId the ID of the broadcaster to add the custom reward to. This ID must
      * match the user ID found in the OAuth token.
      * @param request the reward configuration.
      * @return the created custom reward.
      */
     @RequiresScope(TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
     suspend fun create(
         broadcasterId: String,
         request: CreateRewardRequest,
     ): CustomReward {
         http.validateScopes(TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
         val params = listOf("broadcaster_id" to broadcasterId)
         return http.post<CustomReward>("channel_points/custom_rewards", body = http.encodeBody(request), params = params).requireFirst("channel_points/custom_rewards")
     }
 
     /**
      * [Twitch API: Update Custom Reward](https://dev.twitch.tv/docs/api/reference/#update-custom-reward)
      *
      * Updates a custom reward. The app used to create the reward is the only app that may update
      * the reward.
      *
      * @param broadcasterId the ID of the broadcaster that's updating the reward. This ID must
      * match the user ID found in the OAuth token.
      * @param rewardId the ID of the reward to update.
      * @param request the fields to update. The body should contain only the fields you're updating.
      * @return the updated custom reward.
      */
     @RequiresScope(TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
     suspend fun update(
         broadcasterId: String,
         rewardId: String,
         request: UpdateRewardRequest,
     ): CustomReward {
         http.validateScopes(TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
         val params = listOf("broadcaster_id" to broadcasterId, "id" to rewardId)
         return http.patch<CustomReward>("channel_points/custom_rewards", body = http.encodeBody(request), params = params).requireFirst("channel_points/custom_rewards")
     }
 
     /**
      * [Twitch API: Delete Custom Reward](https://dev.twitch.tv/docs/api/reference/#delete-custom-reward)
      *
      * Deletes a custom reward that the broadcaster created. The app used to create the reward is
      * the only app that may delete it. If the reward's redemption status is UNFULFILLED at the time
      * the reward is deleted, its redemption status is marked as FULFILLED.
      *
      * @param broadcasterId the ID of the broadcaster that created the custom reward. This ID must
      * match the user ID found in the OAuth token.
      * @param id the ID of the custom reward to delete.
      */
     @RequiresScope(TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
     suspend fun delete(
         broadcasterId: String,
         id: String,
     ) {
         http.validateScopes(TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
         val params = listOf("broadcaster_id" to broadcasterId, "id" to id)
         http.deleteNoContent("channel_points/custom_rewards", params)
     }
 
     /**
      * [Twitch API: Get Custom Reward Redemption](https://dev.twitch.tv/docs/api/reference/#get-custom-reward-redemption)
      *
      * Gets all redemptions for the specified reward.
      * Automatically paginates through all results.
      *
      * @param broadcasterId the ID of the broadcaster that owns the custom reward. This ID must match the user ID found in the OAuth token.
      * @param rewardId the ID that identifies the custom reward whose redemptions you want to get.
      * @param status filters the list by redemption status. Possible values: `CANCELED`, `FULFILLED`, `UNFULFILLED`.
      * @param ids a list of IDs to filter the redemptions by (max 50).
      * @param sort the order to sort redemptions by. Possible values: `OLDEST`, `NEWEST`. Default: `OLDEST`.
      * @return a [Flow] of [RewardRedemption] objects.
      */
     @RequiresScope(TwitchScope.CHANNEL_READ_REDEMPTIONS, TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
     fun getAllRedemptions(
         broadcasterId: String,
         rewardId: String,
         status: RedemptionStatus? = null,
         ids: List<String> = emptyList(),
         sort: RedemptionSort? = null,
     ): Flow<RewardRedemption> {
         val params =
             buildList {
                 add("broadcaster_id" to broadcasterId)
                 add("reward_id" to rewardId)
                 status?.let { add("status" to it.name) }
                 ids.forEach { add("id" to it) }
                 sort?.let { add("sort" to it.value) }
             }
         return http
             .paginate<RewardRedemption>("channel_points/custom_rewards/redemptions", params)
             .onStart { http.validateAnyScope(TwitchScope.CHANNEL_READ_REDEMPTIONS, TwitchScope.CHANNEL_MANAGE_REDEMPTIONS) }
     }
 
     /**
      * [Twitch API: Get Custom Reward Redemption](https://dev.twitch.tv/docs/api/reference/#get-custom-reward-redemption)
      *
      * Gets a single page of redemptions for the specified reward.
      *
      * @param broadcasterId the ID of the broadcaster that owns the custom reward. This ID must match the user ID found in the OAuth token.
      * @param rewardId the ID that identifies the custom reward whose redemptions you want to get.
      * @param status filters the list by redemption status. Possible values: `CANCELED`, `FULFILLED`, `UNFULFILLED`.
      * @param ids a list of IDs to filter the redemptions by (max 50).
      * @param sort the order to sort redemptions by. Possible values: `OLDEST`, `NEWEST`. Default: `OLDEST`.
      * @param cursor the cursor used to get the next page of results.
      * @param pageSize the maximum number of redemptions to return per page (1-50, default 20). Null uses the API default.
      * @return a [Page] of [RewardRedemption] objects.
      */
     @RequiresScope(TwitchScope.CHANNEL_READ_REDEMPTIONS, TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
     suspend fun getRedemptions(
         broadcasterId: String,
         rewardId: String,
         status: RedemptionStatus? = null,
         ids: List<String> = emptyList(),
         sort: RedemptionSort? = null,
         cursor: String? = null,
         pageSize: Int? = null,
     ): Page<RewardRedemption> {
         http.validateAnyScope(TwitchScope.CHANNEL_READ_REDEMPTIONS, TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
         val params =
             buildList {
                 add("broadcaster_id" to broadcasterId)
                 add("reward_id" to rewardId)
                 status?.let { add("status" to it.name) }
                 ids.forEach { add("id" to it) }
                 sort?.let { add("sort" to it.value) }
                 cursor?.let { add("after" to it) }
             }
         return http.getPage(endpoint = "channel_points/custom_rewards/redemptions", params = params, pageSize = pageSize)
     }
 
     /**
      * [Twitch API: Update Redemption Status](https://dev.twitch.tv/docs/api/reference/#update-redemption-status)
      *
      * Updates a redemption's status. You may update a redemption only if its status is UNFULFILLED.
      * The app used to create the reward is the only app that may update the redemption.
      *
      * @param broadcasterId the ID of the broadcaster that's updating the redemption. This ID must
      * match the user ID in the user access token.
      * @param rewardId the ID that identifies the reward that's been redeemed.
      * @param redemptionIds a list of IDs that identify the redemptions to update. You may specify
      * a maximum of 50 IDs.
      * @param status the status to set the redemption to. Possible values are: `CANCELED`, `FULFILLED`.
      * Setting the status to CANCELED refunds the user's channel points.
      * @return the list of updated redemptions.
      */
     @RequiresScope(TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
     suspend fun updateRedemptionStatus(
         broadcasterId: String,
         rewardId: String,
         redemptionIds: List<String>,
         status: RedemptionStatus,
     ): List<RewardRedemption> {
         http.validateScopes(TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
         val params =
             buildList {
                 redemptionIds.forEach { add("id" to it) }
                 add("broadcaster_id" to broadcasterId)
                 add("reward_id" to rewardId)
             }
         val body = http.encodeBody(UpdateRedemptionStatusRequest(status = status))
         return http.patch<RewardRedemption>("channel_points/custom_rewards/redemptions", body = body, params = params).data
     }
 
     /**
      * Convenience overload that updates a single redemption's status.
      *
      * @see [updateRedemptionStatus]
      */
     @RequiresScope(TwitchScope.CHANNEL_MANAGE_REDEMPTIONS)
     suspend fun updateRedemptionStatus(
         broadcasterId: String,
         rewardId: String,
         redemptionId: String,
         status: RedemptionStatus,
     ): List<RewardRedemption> =
         updateRedemptionStatus(
             broadcasterId = broadcasterId,
             rewardId = rewardId,
             redemptionIds = listOf(redemptionId),
             status = status,
         )
 }
 
 @Serializable
 internal data class UpdateRedemptionStatusRequest(
     val status: RedemptionStatus,
 )