Skip to content

Commit

Permalink
add helix custom reward redemptions API methods
Browse files Browse the repository at this point in the history
fixes #135
  • Loading branch information
d-fischer committed Nov 19, 2020
1 parent c88c2c5 commit 9dc2818
Show file tree
Hide file tree
Showing 3 changed files with 335 additions and 1 deletion.
165 changes: 164 additions & 1 deletion packages/twitch/src/API/Helix/ChannelPoints/HelixChannelPointsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@ import { TwitchApiCallType } from 'twitch-api-call';
import type { UserIdResolvable } from '../../../Toolkit/UserTools';
import { extractUserId } from '../../../Toolkit/UserTools';
import { BaseApi } from '../../BaseApi';
import type { HelixResponse } from '../HelixResponse';
import { HelixPaginatedRequest } from '../HelixPaginatedRequest';
import type { HelixPaginatedResult } from '../HelixPaginatedResult';
import { createPaginatedResult } from '../HelixPaginatedResult';
import { makePaginationQuery } from '../HelixPagination';
import type { HelixForwardPagination } from '../HelixPagination';
import type { HelixPaginatedResponse, HelixResponse } from '../HelixResponse';
import type { HelixCustomRewardData } from './HelixCustomReward';
import { HelixCustomReward } from './HelixCustomReward';
import type {
HelixCustomRewardRedemptionData,
HelixCustomRewardRedemptionStatus,
HelixCustomRewardRedemptionTargetStatus
} from './HelixCustomRewardRedemption';
import { HelixCustomRewardRedemption } from './HelixCustomRewardRedemption';

/**
* Data to create a new custom reward.
Expand Down Expand Up @@ -73,6 +84,25 @@ interface HelixUpdateCustomRewardData extends Partial<HelixCreateCustomRewardDat
isPaused?: boolean;
}

/**
* Filters for the custom reward redemptions request.
*/
export interface HelixCustomRewardRedemptionFilter {
/**
* Whether to put the newest redemptions first.
*
* Oldest redemptions are shown first by default.
*/
newestFirst?: boolean;
}

/**
* @inheritDoc
*/
export interface HelixPaginatedCustomRewardRedemptionFilter
extends HelixCustomRewardRedemptionFilter,
HelixForwardPagination {}

export class HelixChannelPointsApi extends BaseApi {
/**
* Retrieves all custom rewards for the given broadcaster.
Expand Down Expand Up @@ -197,6 +227,139 @@ export class HelixChannelPointsApi extends BaseApi {
});
}

/**
* Retrieves custom reward redemptions by IDs.
*
* @param broadcaster The broadcaster to retrieve the redemptions for.
* @param rewardId The ID of the reward.
* @param redemptionIds The IDs of the redemptions.
*/
async getRedemptionsByIds(
broadcaster: UserIdResolvable,
rewardId: string,
redemptionIds: string[]
): Promise<HelixCustomRewardRedemption[]> {
const result = await this._client.callApi<HelixResponse<HelixCustomRewardRedemptionData>>({
type: TwitchApiCallType.Helix,
url: 'channel_points/custom_rewards/redemptions',
scope: 'channel:read:redemptions',
query: {
broadcaster_id: extractUserId(broadcaster),
reward_id: rewardId,
id: redemptionIds
}
});

return result.data.map(data => new HelixCustomRewardRedemption(data, this._client));
}

/**
* Retrieves a custom reward redemption by ID.
*
* @param broadcaster The broadcaster to retrieve the redemption for.
* @param rewardId The ID of the reward.
* @param redemptionId The ID of the redemption.
*/
async getRedemptionById(
broadcaster: UserIdResolvable,
rewardId: string,
redemptionId: string
): Promise<HelixCustomRewardRedemption | null> {
const redemptions = await this.getRedemptionsByIds(broadcaster, rewardId, [redemptionId]);
return redemptions.length ? redemptions[0] : null;
}

/**
* Retrieves custom reward redemptions for the given broadcaster.
*
* @param broadcaster The broadcaster to retrieve the redemptions for.
* @param rewardId The ID of the reward.
* @param status The status of the redemptions to retrieve.
* @param filter
*
* @expandParams
*/
async getRedemptionsForBroadcaster(
broadcaster: UserIdResolvable,
rewardId: string,
status: HelixCustomRewardRedemptionStatus,
filter: HelixPaginatedCustomRewardRedemptionFilter
): Promise<HelixPaginatedResult<HelixCustomRewardRedemption>> {
const result = await this._client.callApi<HelixPaginatedResponse<HelixCustomRewardRedemptionData>>({
type: TwitchApiCallType.Helix,
url: 'channel_points/custom_rewards/redemptions',
scope: 'channel:read:redemptions',
query: {
broadcaster_id: extractUserId(broadcaster),
reward_id: rewardId,
sort: filter.newestFirst ? 'NEWEST' : 'OLDEST',
...makePaginationQuery(filter)
}
});

return createPaginatedResult(result, HelixCustomRewardRedemption, this._client);
}

/**
* Creates a paginator for custom reward redemptions for the given broadcaster.
*
* @param broadcaster The broadcaster to retrieve the redemptions for.
* @param rewardId The ID of the reward.
* @param status The status of the redemptions to retrieve.
* @param filter
*
* @expandParams
*/
getRedemptionsForBroadcasterPaginated(
broadcaster: UserIdResolvable,
rewardId: string,
status: HelixCustomRewardRedemptionStatus,
filter: HelixCustomRewardRedemptionFilter
): HelixPaginatedRequest<HelixCustomRewardRedemptionData, HelixCustomRewardRedemption> {
return new HelixPaginatedRequest<HelixCustomRewardRedemptionData, HelixCustomRewardRedemption>(
{
url: 'channel_points/custom_rewards/redemptions',
scope: 'channel:read:redemptions',
query: {
broadcaster_id: extractUserId(broadcaster),
reward_id: rewardId,
sort: filter.newestFirst ? 'NEWEST' : 'OLDEST'
}
},
this._client,
data => new HelixCustomRewardRedemption(data, this._client)
);
}

/**
* Updates the status of the given redemptions by IDs.
*
* @param broadcaster The broadcaster to retrieve the redemptions for.
* @param rewardId The ID of the reward.
* @param redemptionIds The IDs of the redemptions to update.
* @param status The status to set for the redemptions.
*/
async updateRedemptionStatusByIds(
broadcaster: UserIdResolvable,
rewardId: string,
redemptionIds: string[],
status: HelixCustomRewardRedemptionTargetStatus
): Promise<HelixCustomRewardRedemption[]> {
const result = await this._client.callApi<HelixResponse<HelixCustomRewardRedemptionData>>({
type: TwitchApiCallType.Helix,
url: 'channel_points/custom_rewards/redemptions',
method: 'PATCH',
scope: 'channel:manage:redemptions',
query: {
broadcaster_id: extractUserId(broadcaster),
reward_id: rewardId,
id: redemptionIds
}
});

return result.data.map(data => new HelixCustomRewardRedemption(data, this._client));
}

private static _transformRewardData(data: HelixCreateCustomRewardData | HelixUpdateCustomRewardData) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const result: any = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Enumerable } from '@d-fischer/shared-utils';
import type { HelixUser } from '../User/HelixUser';
import type { ApiClient } from '../../../ApiClient';

/** @private */
Expand Down Expand Up @@ -85,6 +86,13 @@ export class HelixCustomReward {
return this._data.broadcaster_name;
}

/**
* Retrieves more information about the reward's broadcaster.
*/
async getBroadcaster(): Promise<HelixUser | null> {
return this._client.helix.users.getUserById(this._data.broadcaster_id);
}

/**
* Gets the URL of the image of the reward in the given scale.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import { Enumerable } from '@d-fischer/shared-utils';
import type { HelixUser } from '../User/HelixUser';
import type { ApiClient } from '../../../ApiClient';
import type { HelixCustomReward } from './HelixCustomReward';

/**
* The possible statuses of a custom Channel Points reward redemption you can set.
*/
export type HelixCustomRewardRedemptionTargetStatus = 'FULFILLED' | 'CANCELED';

/**
* The possible statuses of a custom Channel Points reward redemption.
*/
export type HelixCustomRewardRedemptionStatus = 'UNFULFILLED' | HelixCustomRewardRedemptionTargetStatus;

/** @private */
export interface HelixCustomRewardRedemptionRewardData {
id: string;
title: string;
prompt: string;
cost: number;
}

/** @private */
export interface HelixCustomRewardRedemptionData {
broadcaster_name: string;
broadcaster_id: string;
id: string;
user_id: string;
user_name: string;
user_input: string;
status: HelixCustomRewardRedemptionStatus;
redeemed_at: string;
reward: HelixCustomRewardRedemptionRewardData;
}

/**
* A redemption of a custom Channel Points reward.
*/
export class HelixCustomRewardRedemption {
/** @private */
@Enumerable(false) protected readonly _client: ApiClient;

/** @private */
constructor(private readonly _data: HelixCustomRewardRedemptionData, client: ApiClient) {
this._client = client;
}

/**
* The ID of the redemption.
*/
get id(): string {
return this._data.id;
}

/**
* The ID of the broadcaster where the reward was redeemed.
*/
get broadcasterId(): string {
return this._data.broadcaster_id;
}

/**
* The display name of the broadcaster where the reward was redeemed.
*/
get broadcasterDisplayName(): string {
return this._data.broadcaster_name;
}

/**
* Retrieves more information about the broadcaster where the reward was redeemed.
*/
async getBroadcaster(): Promise<HelixUser | null> {
return this._client.helix.users.getUserById(this._data.broadcaster_id);
}

/**
* The ID of the user that redeemed the reward.
*/
get userId(): string {
return this._data.user_id;
}

/**
* The display name of the user that redeemed the reward.
*/
get userDisplayName(): string {
return this._data.user_name;
}

/**
* Retrieves more information about the user that redeemed the reward.
*/
async getUser(): Promise<HelixUser | null> {
return this._client.helix.users.getUserById(this._data.user_id);
}

/**
* The text the user wrote when redeeming the reward.
*/
get userInput(): string {
return this._data.user_input;
}

/**
* Whether the redemption was fulfilled.
*/
get isFulfilled(): boolean {
return this._data.status === 'FULFILLED';
}

/**
* Whether the redemption was canceled.
*/
get isCanceled(): boolean {
return this._data.status === 'CANCELED';
}

/**
* The date and time when the reward was redeemed.
*/
get redemptionDate(): Date {
return new Date(this._data.redeemed_at);
}

/**
* The ID of the reward that was redeemed.
*/
get rewardId(): string {
return this._data.reward.id;
}

/**
* Retrieves more info about the reward that was redeemed.
*/
async getReward(): Promise<HelixCustomReward> {
return (await this._client.helix.channelPoints.getCustomRewardById(
this._data.broadcaster_id,
this._data.reward.id
))!;
}

/**
* The title of the reward that was redeemed.
*/
get rewardTitle(): string {
return this._data.reward.title;
}

/**
* The prompt of the reward that was redeemed.
*/
get rewardPrompt(): string {
return this._data.reward.prompt;
}

/**
* The cost of the reward that was redeemed.
*/
get rewardCost(): number {
return this._data.reward.cost;
}
}

0 comments on commit 9dc2818

Please sign in to comment.