@twurple/api
Version:
Interact with Twitch's API.
437 lines (436 loc) • 18 kB
JavaScript
import { __decorate } from "tslib";
import { createBroadcasterQuery } from '@twurple/api-call';
import { extractUserId, rtfm } from '@twurple/common';
import { createChatColorUpdateQuery, createChatSettingsUpdateBody, createSendChatMessageAsAppBody, createSendChatMessageBody, createSendChatMessageQuery, createShoutoutQuery, } from "../../interfaces/endpoints/chat.external.mjs";
import { createModeratorActionQuery, createSingleKeyQuery } from "../../interfaces/endpoints/generic.external.mjs";
import { HelixPaginatedRequest } from "../../utils/pagination/HelixPaginatedRequest.mjs";
import { HelixPaginatedRequestWithTotal } from "../../utils/pagination/HelixPaginatedRequestWithTotal.mjs";
import { createPaginatedResult, createPaginatedResultWithTotal, } from "../../utils/pagination/HelixPaginatedResult.mjs";
import { createPaginationQuery } from "../../utils/pagination/HelixPagination.mjs";
import { BaseApi } from "../BaseApi.mjs";
import { HelixChannelEmote } from "./HelixChannelEmote.mjs";
import { HelixChatBadgeSet } from "./HelixChatBadgeSet.mjs";
import { HelixChatChatter } from "./HelixChatChatter.mjs";
import { HelixChatSettings } from "./HelixChatSettings.mjs";
import { HelixEmote } from "./HelixEmote.mjs";
import { HelixEmoteFromSet } from "./HelixEmoteFromSet.mjs";
import { HelixUserEmote } from "./HelixUserEmote.mjs";
import { HelixPrivilegedChatSettings } from "./HelixPrivilegedChatSettings.mjs";
import { HelixSentChatMessage } from "./HelixSentChatMessage.mjs";
import { createSharedChatSessionQuery, } from "../../interfaces/endpoints/shared-chat-session.external.mjs";
import { HelixSharedChatSession } from "./HelixSharedChatSession.mjs";
/**
* The Helix API methods that deal with chat.
*
* Can be accessed using `client.chat` on an {@link ApiClient} instance.
*
* ## Example
* ```ts
* const api = new ApiClient({ authProvider });
* const rewards = await api.chat.getChannelBadges('125328655');
* ```
*
* @meta category helix
* @meta categorizedTitle Chat
*/
let HelixChatApi = class HelixChatApi extends BaseApi {
/**
* Gets the list of users that are connected to the broadcaster’s chat session.
*
* This uses the token of the broadcaster by default.
* If you want to execute this in the context of another user (who has to be moderator of the channel)
* you can do so using [user context overrides](/docs/auth/concepts/context-switching).
*
* @param broadcaster The broadcaster whose list of chatters you want to get.
* @param pagination
*
* @expandParams
*/
async getChatters(broadcaster, pagination) {
const broadcasterId = extractUserId(broadcaster);
const result = await this._client.callApi({
type: 'helix',
url: 'chat/chatters',
userId: broadcasterId,
canOverrideScopedUserContext: true,
scopes: ['moderator:read:chatters'],
query: {
...this._createModeratorActionQuery(broadcasterId),
...createPaginationQuery(pagination),
},
});
return createPaginatedResultWithTotal(result, HelixChatChatter, this._client);
}
/**
* Creates a paginator for users that are connected to the broadcaster’s chat session.
*
* This uses the token of the broadcaster by default.
* If you want to execute this in the context of another user (who has to be moderator of the channel)
* you can do so using [user context overrides](/docs/auth/concepts/context-switching).
*
* @param broadcaster The broadcaster whose list of chatters you want to get.
*
* @expandParams
*/
getChattersPaginated(broadcaster) {
const broadcasterId = extractUserId(broadcaster);
return new HelixPaginatedRequestWithTotal({
url: 'chat/chatters',
userId: broadcasterId,
canOverrideScopedUserContext: true,
scopes: ['moderator:read:chatters'],
query: this._createModeratorActionQuery(broadcasterId),
}, this._client, data => new HelixChatChatter(data, this._client), 1000);
}
/**
* Gets all global badges.
*/
async getGlobalBadges() {
const result = await this._client.callApi({
type: 'helix',
url: 'chat/badges/global',
});
return result.data.map(data => new HelixChatBadgeSet(data));
}
/**
* Gets all badges specific to the given broadcaster.
*
* @param broadcaster The broadcaster to get badges for.
*/
async getChannelBadges(broadcaster) {
const result = await this._client.callApi({
type: 'helix',
url: 'chat/badges',
userId: extractUserId(broadcaster),
query: createBroadcasterQuery(broadcaster),
});
return result.data.map(data => new HelixChatBadgeSet(data));
}
/**
* Gets all global emotes.
*/
async getGlobalEmotes() {
const result = await this._client.callApi({
type: 'helix',
url: 'chat/emotes/global',
});
return result.data.map(data => new HelixEmote(data));
}
/**
* Gets all emotes specific to the given broadcaster.
*
* @param broadcaster The broadcaster to get emotes for.
*/
async getChannelEmotes(broadcaster) {
const result = await this._client.callApi({
type: 'helix',
url: 'chat/emotes',
userId: extractUserId(broadcaster),
query: createBroadcasterQuery(broadcaster),
});
return result.data.map(data => new HelixChannelEmote(data, this._client));
}
/**
* Gets all emotes from a list of emote sets.
*
* @param setIds The IDs of the emote sets to get emotes from.
*/
async getEmotesFromSets(setIds) {
const result = await this._client.callApi({
type: 'helix',
url: 'chat/emotes/set',
query: createSingleKeyQuery('emote_set_id', setIds),
});
return result.data.map(data => new HelixEmoteFromSet(data, this._client));
}
/**
* Gets emotes available to the user across all channels.
*
* @param user The ID of the user to get available emotes of.
* @param filter Additional query filters.
*/
async getUserEmotes(user, filter) {
const userId = extractUserId(user);
const result = await this._client.callApi({
type: 'helix',
url: 'chat/emotes/user',
userId: extractUserId(user),
scopes: ['user:read:emotes'],
query: {
...createSingleKeyQuery('user_id', userId),
...createSingleKeyQuery('broadcasterId', (filter === null || filter === void 0 ? void 0 : filter.broadcaster) ? extractUserId(filter.broadcaster) : undefined),
...createPaginationQuery(filter),
},
});
return createPaginatedResult(result, HelixUserEmote, this._client);
}
/**
* Creates a paginator for emotes available to the user across all channels.
*
* @param user The ID of the user to get available emotes of.
* @param broadcaster The ID of a broadcaster you wish to get follower emotes of. Using this query parameter will
* guarantee inclusion of the broadcaster’s follower emotes in the response body.
*
* If the user who retrieves their emotes is subscribed to the broadcaster specified, their follower emotes will
* appear in the response body regardless of whether this query parameter is used.
*/
getUserEmotesPaginated(user, broadcaster) {
const userId = extractUserId(user);
return new HelixPaginatedRequest({
url: 'chat/emotes/user',
userId,
scopes: ['user:read:emotes'],
query: {
...createSingleKeyQuery('user_id', userId),
...createSingleKeyQuery('broadcasterId', broadcaster ? extractUserId(broadcaster) : undefined),
},
}, this._client, (data) => new HelixUserEmote(data, this._client));
}
/**
* Gets the settings of a broadcaster's chat.
*
* @param broadcaster The broadcaster the chat belongs to.
*/
async getSettings(broadcaster) {
const result = await this._client.callApi({
type: 'helix',
url: 'chat/settings',
userId: extractUserId(broadcaster),
query: createBroadcasterQuery(broadcaster),
});
return new HelixChatSettings(result.data[0]);
}
/**
* Gets the settings of a broadcaster's chat, including the delay settings.
*
* This uses the token of the broadcaster by default.
* If you want to execute this in the context of another user (who has to be moderator of the channel)
* you can do so using [user context overrides](/docs/auth/concepts/context-switching).
*
* @param broadcaster The broadcaster the chat belongs to.
*/
async getSettingsPrivileged(broadcaster) {
const broadcasterId = extractUserId(broadcaster);
const result = await this._client.callApi({
type: 'helix',
url: 'chat/settings',
userId: broadcasterId,
canOverrideScopedUserContext: true,
scopes: ['moderator:read:chat_settings'],
query: this._createModeratorActionQuery(broadcasterId),
});
return new HelixPrivilegedChatSettings(result.data[0]);
}
/**
* Updates the settings of a broadcaster's chat.
*
* This uses the token of the broadcaster by default.
* If you want to execute this in the context of another user (who has to be moderator of the channel)
* you can do so using [user context overrides](/docs/auth/concepts/context-switching).
*
* @expandParams
*
* @param broadcaster The broadcaster the chat belongs to.
* @param settings The settings to change.
*/
async updateSettings(broadcaster, settings) {
const broadcasterId = extractUserId(broadcaster);
const result = await this._client.callApi({
type: 'helix',
url: 'chat/settings',
method: 'PATCH',
userId: broadcasterId,
canOverrideScopedUserContext: true,
scopes: ['moderator:manage:chat_settings'],
query: this._createModeratorActionQuery(broadcasterId),
jsonBody: createChatSettingsUpdateBody(settings),
});
return new HelixPrivilegedChatSettings(result.data[0]);
}
/**
* Sends a chat message to a broadcaster's chat.
*
* This uses the token of the broadcaster by default.
* If you want to execute this in the context of another user
* you can do so using [user context overrides](/docs/auth/concepts/context-switching).
*
* @expandParams
*
* @param broadcaster The broadcaster the chat belongs to.
* @param message The message to send.
* @param params
*/
async sendChatMessage(broadcaster, message, params) {
const broadcasterId = extractUserId(broadcaster);
const result = await this._client.callApi({
type: 'helix',
url: 'chat/messages',
method: 'POST',
userId: broadcasterId,
canOverrideScopedUserContext: true,
scopes: ['user:write:chat'],
query: createSendChatMessageQuery(broadcasterId, this._getUserContextIdWithDefault(broadcasterId)),
jsonBody: createSendChatMessageBody(message, params),
});
return new HelixSentChatMessage(result.data[0]);
}
/**
* Sends a chat message to a broadcaster's chat, using an app token.
*
* This requires the scopes `user:write:chat` and `user:bot` for the `user` and `channel:bot` for the `broadcaster`.
* `channel:bot` is not required if the `user` has moderator privileges in the `broadcaster`'s channel.
*
* These scope requirements can not be checked by the library, so they are just assumed.
* Make sure to catch authorization errors yourself.
*
* @expandParams
*
* @param user The user to send the chat message from.
* @param broadcaster The broadcaster the chat belongs to.
* @param message The message to send.
* @param params
*/
async sendChatMessageAsApp(user, broadcaster, message, params) {
const userId = extractUserId(user);
const broadcasterId = extractUserId(broadcaster);
const result = await this._client.callApi({
type: 'helix',
url: 'chat/messages',
method: 'POST',
forceType: 'app',
query: createSendChatMessageQuery(broadcasterId, userId),
jsonBody: createSendChatMessageAsAppBody(message, params),
});
return new HelixSentChatMessage(result.data[0]);
}
/**
* Sends an announcement to a broadcaster's chat.
*
* This uses the token of the broadcaster by default.
* If you want to execute this in the context of another user (who has to be moderator of the channel)
* you can do so using [user context overrides](/docs/auth/concepts/context-switching).
*
* @param broadcaster The broadcaster the chat belongs to.
* @param announcement The announcement to send.
*/
async sendAnnouncement(broadcaster, announcement) {
const broadcasterId = extractUserId(broadcaster);
await this._client.callApi({
type: 'helix',
url: 'chat/announcements',
method: 'POST',
userId: broadcasterId,
canOverrideScopedUserContext: true,
scopes: ['moderator:manage:announcements'],
query: this._createModeratorActionQuery(broadcasterId),
jsonBody: {
message: announcement.message,
color: announcement.color,
},
});
}
/**
* Gets the chat colors for a list of users.
*
* Returns a Map with user IDs as keys and their colors as values.
* The value is a color hex code, or `null` if the user did not set a color,
* and unknown users will not be present in the map.
*
* @param users The users to get the chat colors of.
*/
async getColorsForUsers(users) {
const response = await this._client.callApi({
type: 'helix',
url: 'chat/color',
query: createSingleKeyQuery('user_id', users.map(extractUserId)),
});
return new Map(response.data.map(data => [data.user_id, data.color || null]));
}
/**
* Gets the chat color for a user.
*
* Returns the color as hex code, `null` if the user did not set a color, or `undefined` if the user is unknown.
*
* @param user The user to get the chat color of.
*/
async getColorForUser(user) {
const response = await this._client.callApi({
type: 'helix',
url: 'chat/color',
userId: extractUserId(user),
query: createSingleKeyQuery('user_id', extractUserId(user)),
});
if (!response.data.length) {
return undefined;
}
return response.data[0].color || null;
}
/**
* Changes the chat color for a user.
*
* @param user The user to change the color of.
* @param color The color to set.
*
* Note that hex codes can only be used by users that have a Prime or Turbo subscription.
*/
async setColorForUser(user, color) {
await this._client.callApi({
type: 'helix',
url: 'chat/color',
method: 'PUT',
userId: extractUserId(user),
scopes: ['user:manage:chat_color'],
query: createChatColorUpdateQuery(user, color),
});
}
/**
* Sends a shoutout to the specified broadcaster.
* The broadcaster may send a shoutout once every 2 minutes. They may send the same broadcaster a shoutout once every 60 minutes.
*
* This uses the token of the broadcaster by default.
* If you want to execute this in the context of another user (who has to be moderator of the channel)
* you can do so using [user context overrides](/docs/auth/concepts/context-switching).
*
* @param from The ID of the broadcaster that’s sending the shoutout.
* @param to The ID of the broadcaster that’s receiving the shoutout.
*/
async shoutoutUser(from, to) {
const fromId = extractUserId(from);
await this._client.callApi({
type: 'helix',
url: 'chat/shoutouts',
method: 'POST',
userId: fromId,
canOverrideScopedUserContext: true,
scopes: ['moderator:manage:shoutouts'],
query: createShoutoutQuery(from, to, this._getUserContextIdWithDefault(fromId)),
});
}
/**
* Gets the active shared chat session for a channel.
*
* Returns `null` if there is no active shared chat session in the channel.
*
* @param broadcaster The broadcaster to get the active shared chat session for.
*/
async getSharedChatSession(broadcaster) {
const broadcasterId = extractUserId(broadcaster);
const response = await this._client.callApi({
type: 'helix',
url: 'shared_chat/session',
userId: broadcasterId,
query: createSharedChatSessionQuery(broadcasterId),
});
if (response.data.length === 0) {
return null;
}
return new HelixSharedChatSession(response.data[0], this._client);
}
_createModeratorActionQuery(broadcasterId) {
return createModeratorActionQuery(broadcasterId, this._getUserContextIdWithDefault(broadcasterId));
}
};
HelixChatApi = __decorate([
rtfm('api', 'HelixChatApi')
], HelixChatApi);
export { HelixChatApi };