Coverage Summary for Class: ChatResource (io.github.captnblubber.twitchkt.helix.resource)
| Class |
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| ChatResource |
100%
(24/24)
|
90%
(9/10)
|
100%
(122/122)
|
99.9%
(1069/1070)
|
| ChatResource$getAllChatters$$inlined$paginate$1 |
0%
(0/1)
|
|
| ChatResource$getAllChatters$1 |
100%
(1/1)
|
|
100%
(1/1)
|
100%
(31/31)
|
| ChatResource$getAllUserEmotes$$inlined$paginate$default$1 |
0%
(0/1)
|
|
| ChatResource$getAllUserEmotes$1 |
100%
(1/1)
|
|
100%
(1/1)
|
100%
(31/31)
|
| ChatResource$getChannelBadges$1 |
|
| ChatResource$getChannelEmotes$1 |
|
| ChatResource$getChatters$1 |
|
| ChatResource$getEmoteSets$1 |
|
| ChatResource$getGlobalBadges$1 |
|
| ChatResource$getGlobalEmotes$1 |
|
| ChatResource$getSettings$1 |
|
| ChatResource$getSharedChatSession$1 |
|
| ChatResource$getUserColor$1 |
|
| ChatResource$getUserEmotes$1 |
|
| ChatResource$sendAnnouncement$1 |
|
| ChatResource$sendMessage$1 |
|
| ChatResource$updateSettings$1 |
|
| ChatResource$updateUserColor$1 |
|
| Total |
92.9%
(26/28)
|
90%
(9/10)
|
100%
(124/124)
|
99.9%
(1131/1132)
|
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.AnnouncementColor
import io.github.captnblubber.twitchkt.helix.model.ChannelEmote
import io.github.captnblubber.twitchkt.helix.model.ChatBadge
import io.github.captnblubber.twitchkt.helix.model.ChatColorEntry
import io.github.captnblubber.twitchkt.helix.model.ChatSettings
import io.github.captnblubber.twitchkt.helix.model.Chatter
import io.github.captnblubber.twitchkt.helix.model.SendChatMessageRequest
import io.github.captnblubber.twitchkt.helix.model.SendMessageResponse
import io.github.captnblubber.twitchkt.helix.model.SharedChatSession
import io.github.captnblubber.twitchkt.helix.model.UserEmote
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onStart
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
/**
* Twitch Helix Chat API resource.
*
* Provides methods for managing chat messages, emotes, badges, settings, colors,
* announcements, shared chat sessions, and user emotes.
*
* @see <a href="https://dev.twitch.tv/docs/api/reference/#chat">Twitch API Reference - Chat</a>
*/
class ChatResource internal constructor(
private val http: HelixHttpClient,
) {
/**
* [Twitch API: Send Chat Message](https://dev.twitch.tv/docs/api/reference/#send-chat-message)
*
* Sends a message to the broadcaster's chat room. To send a chat message, your app may use
* an app access token or user access token.
*
* **Rate Limits**: The user sending the chat message is limited to sending 20 chat messages
* per 30 seconds.
*
* @param request the message payload including broadcaster ID, sender ID, and message text.
* @return the response indicating whether the message was sent successfully.
*/
@RequiresScope(TwitchScope.USER_WRITE_CHAT)
suspend fun sendMessage(request: SendChatMessageRequest): SendMessageResponse {
http.validateScopes(TwitchScope.USER_WRITE_CHAT)
return http.post<SendMessageResponse>("chat/messages", body = http.encodeBody(request)).requireFirst("chat/messages")
}
/**
* [Twitch API: Get Global Chat Badges](https://dev.twitch.tv/docs/api/reference/#get-global-chat-badges)
*
* Gets Twitch's list of chat badges, which users may use in any channel's chat room.
* For a list of custom badges for a specific channel, call [getChannelBadges].
*
* @return the list of chat badges. The list is sorted in ascending order by `set_id`,
* and within a set, the list is sorted in ascending order by the badge version `id`.
*/
suspend fun getGlobalBadges(): List<ChatBadge> = http.get<ChatBadge>("chat/badges/global").data
/**
* [Twitch API: Get Channel Chat Badges](https://dev.twitch.tv/docs/api/reference/#get-channel-chat-badges)
*
* Gets the broadcaster's list of custom chat badges. The list is empty if the broadcaster
* hasn't created custom chat badges. For a list of global badges, call [getGlobalBadges].
*
* @param broadcasterId the ID of the broadcaster whose chat badges you want to get.
* @return the list of chat badges. The list is sorted in ascending order by `set_id`,
* and within a set, the list is sorted in ascending order by the badge version `id`.
*/
suspend fun getChannelBadges(broadcasterId: String): List<ChatBadge> {
val params = listOf("broadcaster_id" to broadcasterId)
return http.get<ChatBadge>("chat/badges", params).data
}
/**
* [Twitch API: Get Chatters](https://dev.twitch.tv/docs/api/reference/#get-chatters)
*
* Fetches a single page of users connected to the broadcaster's chat session.
*
* **NOTE:** There is a delay between when users join and leave a chat and when the list
* is updated accordingly.
*
* @param broadcasterId the ID of the broadcaster whose list of chatters you want to get.
* @param moderatorId the ID of the broadcaster or one of the broadcaster's moderators.
* This ID must match the user ID in the user access token.
* @param cursor the cursor used to get the next page of results. Pass `null` to get the first page.
* @param pageSize the maximum number of items to return (1–1000). `null` uses the API default (100).
* @return a [Page] containing the chatters on this page and the cursor for the next page.
*/
@RequiresScope(TwitchScope.MODERATOR_READ_CHATTERS)
suspend fun getChatters(
broadcasterId: String,
moderatorId: String,
cursor: String? = null,
pageSize: Int? = null,
): Page<Chatter> {
http.validateScopes(TwitchScope.MODERATOR_READ_CHATTERS)
val params =
buildList {
add("broadcaster_id" to broadcasterId)
add("moderator_id" to moderatorId)
cursor?.let { add("after" to it) }
}
return http.getPage(endpoint = "chat/chatters", params = params, pageSize = pageSize)
}
/**
* Returns a paginated [Flow] of all users in the broadcaster's chat room.
* Automatically follows pagination cursors until all chatters have been fetched.
*
* @param broadcasterId the ID of the broadcaster whose chatters to get.
* @param moderatorId the ID of the broadcaster or a moderator. Must match the token user.
* @param pageSize items per page (max 1000).
*/
@RequiresScope(TwitchScope.MODERATOR_READ_CHATTERS)
fun getAllChatters(
broadcasterId: String,
moderatorId: String,
pageSize: Int = 1000,
): Flow<Chatter> =
http
.paginate<Chatter>(
endpoint = "chat/chatters",
params =
listOf(
"broadcaster_id" to broadcasterId,
"moderator_id" to moderatorId,
),
pageSize = pageSize,
).onStart { http.validateScopes(TwitchScope.MODERATOR_READ_CHATTERS) }
/**
* [Twitch API: Get Channel Emotes](https://dev.twitch.tv/docs/api/reference/#get-channel-emotes)
*
* Gets the broadcaster's list of custom emotes. Broadcasters create these custom emotes
* for users who subscribe to or follow the channel or cheer Bits in the channel's chat window.
*
* For information about the custom emotes, see
* [subscriber emotes](https://help.twitch.tv/s/article/subscriber-emote-guide),
* [Bits tier emotes](https://help.twitch.tv/s/article/custom-bit-badges-guide), and
* [follower emotes](https://blog.twitch.tv/en/2021/06/04/kicking-off-10-years-with-our-community/).
*
* **NOTE:** With the exception of custom combos, the emote images are not returned at a 3.0 scale.
*
* @param broadcasterId an ID that identifies the broadcaster whose emotes you want to get.
* @return the list of emotes that the specified broadcaster created. If the broadcaster
* hasn't created custom emotes, the list is empty.
*/
suspend fun getChannelEmotes(broadcasterId: String): List<ChannelEmote> =
http
.get<ChannelEmote>(
"chat/emotes",
listOf("broadcaster_id" to broadcasterId),
).data
/**
* [Twitch API: Get Global Emotes](https://dev.twitch.tv/docs/api/reference/#get-global-emotes)
*
* Gets the list of [global emotes](https://www.twitch.tv/creatorcamp/en/paths/getting-started-on-twitch/emotes/).
* Global emotes are Twitch-created emotes that users can use in any Twitch chat.
*
* @return the list of global emotes.
*/
suspend fun getGlobalEmotes(): List<ChannelEmote> = http.get<ChannelEmote>("chat/emotes/global").data
/**
* [Twitch API: Get Emote Sets](https://dev.twitch.tv/docs/api/reference/#get-emote-sets)
*
* Gets emotes for one or more specified emote sets.
*
* An emote set groups emotes that have a similar context. For example, Twitch places all
* the subscriber emotes that a broadcaster uploads for their channel in the same emote set.
*
* @param emoteSetIds the IDs of the emote sets to get. You may specify a maximum of 25 IDs.
* The response contains only those IDs that are valid.
* @return the list of emotes found in the specified emote sets.
*/
suspend fun getEmoteSets(emoteSetIds: List<String>): List<ChannelEmote> =
http
.get<ChannelEmote>(
"chat/emotes/set",
emoteSetIds.map { "emote_set_id" to it },
).data
/**
* [Twitch API: Get Chat Settings](https://dev.twitch.tv/docs/api/reference/#get-chat-settings)
*
* Gets the broadcaster's chat settings.
*
* To include the `non_moderator_chat_delay` and `non_moderator_chat_delay_duration` settings
* in the response, you must specify a user access token that includes the
* `moderator:read:chat_settings` scope. The [moderatorId] must match the user ID in the access token.
*
* @param broadcasterId the ID of the broadcaster whose chat settings you want to get.
* @param moderatorId the ID of the broadcaster or one of the broadcaster's moderators.
* Required only if you want to include the `non_moderator_chat_delay` and
* `non_moderator_chat_delay_duration` settings in the response.
* @return the chat settings for the specified broadcaster's channel.
*/
suspend fun getSettings(
broadcasterId: String,
moderatorId: String? = null,
): ChatSettings =
http
.get<ChatSettings>(
"chat/settings",
buildList {
add("broadcaster_id" to broadcasterId)
moderatorId?.let { add("moderator_id" to it) }
},
).requireFirst("chat/settings")
/**
* [Twitch API: Update Chat Settings](https://dev.twitch.tv/docs/api/reference/#update-chat-settings)
*
* Updates the broadcaster's chat settings. All fields are optional; specify only those
* fields that you want to update.
*
* @param broadcasterId the ID of the broadcaster whose chat settings you want to update.
* @param moderatorId the ID of a user that has permission to moderate the broadcaster's
* chat room, or the broadcaster's ID if they're making the update. This ID must match
* the user ID in the user access token.
* @param slowMode a Boolean value that determines whether chat messages must wait before
* being sent. Set to `true` to require users to wait; set to `false` to remove the wait time.
* @param slowModeWaitTime the amount of time, in seconds, that users must wait between
* sending messages (3–120). Set only if [slowMode] is `true`.
* @param followerMode a Boolean value that determines whether the broadcaster restricts the
* chat room to followers only. Set to `true` to restrict to followers only; set to `false`
* to remove the restriction.
* @param followerModeDuration the length of time, in minutes, that users must follow the
* broadcaster before being able to participate in the chat room (0–129600). Set only if
* [followerMode] is `true`. 0 means no minimum.
* @param subscriberMode a Boolean value that determines whether only users that subscribe
* to the broadcaster's channel may talk in the chat room.
* @param emoteMode a Boolean value that determines whether chat messages must contain only
* emotes.
* @param uniqueChatMode a Boolean value that determines whether the broadcaster requires
* users to post only unique messages in the chat room (formerly R9K).
* @param nonModeratorChatDelay a Boolean value that determines whether the broadcaster adds
* a short delay before chat messages appear in the chat room. This gives chat moderators
* and bots a chance to remove them before viewers can see the message.
* @param nonModeratorChatDelayDuration the amount of time, in seconds, that messages are
* delayed before appearing in chat. Possible values are: 2, 4, and 6. Set only if
* [nonModeratorChatDelay] is `true`.
* @return the updated chat settings.
*/
@RequiresScope(TwitchScope.MODERATOR_MANAGE_CHAT_SETTINGS)
suspend fun updateSettings(
broadcasterId: String,
moderatorId: String,
slowMode: Boolean? = null,
slowModeWaitTime: Int? = null,
followerMode: Boolean? = null,
followerModeDuration: Int? = null,
subscriberMode: Boolean? = null,
emoteMode: Boolean? = null,
uniqueChatMode: Boolean? = null,
nonModeratorChatDelay: Boolean? = null,
nonModeratorChatDelayDuration: Int? = null,
): ChatSettings {
http.validateScopes(TwitchScope.MODERATOR_MANAGE_CHAT_SETTINGS)
return http
.patch<ChatSettings>(
"chat/settings",
params =
listOf(
"broadcaster_id" to broadcasterId,
"moderator_id" to moderatorId,
),
body =
http.encodeBody(
UpdateChatSettingsRequest(
slowMode = slowMode,
slowModeWaitTime = slowModeWaitTime,
followerMode = followerMode,
followerModeDuration = followerModeDuration,
subscriberMode = subscriberMode,
emoteMode = emoteMode,
uniqueChatMode = uniqueChatMode,
nonModeratorChatDelay = nonModeratorChatDelay,
nonModeratorChatDelayDuration = nonModeratorChatDelayDuration,
),
),
).requireFirst("chat/settings")
}
/**
* [Twitch API: Send Chat Announcement](https://dev.twitch.tv/docs/api/reference/#send-chat-announcement)
*
* Sends an announcement to the broadcaster's chat room.
*
* @param broadcasterId the ID of the broadcaster that owns the chat room to send the
* announcement to.
* @param moderatorId the ID of a user who has permission to moderate the broadcaster's
* chat room, or the broadcaster's ID if they're sending the announcement. This ID must
* match the user ID in the user access token.
* @param message the announcement to make in the broadcaster's chat room. Announcements
* are limited to a maximum of 500 characters; announcements longer than 500 characters
* are truncated.
* @param color the color used to highlight the announcement. Possible case-sensitive values
* are: `blue`, `green`, `orange`, `purple`, `primary` (default). If color is set to
* `primary` or is not set, the channel's accent color is used to highlight the announcement.
* @param sourceOnly determines if the chat announcement is sent only to the source channel
* during a shared chat session. This parameter can only be set when utilizing an App Access
* Token. Defaults to `false`.
*/
@RequiresScope(TwitchScope.MODERATOR_MANAGE_ANNOUNCEMENTS)
suspend fun sendAnnouncement(
broadcasterId: String,
moderatorId: String,
message: String,
color: AnnouncementColor = AnnouncementColor.PRIMARY,
sourceOnly: Boolean? = null,
) {
http.validateScopes(TwitchScope.MODERATOR_MANAGE_ANNOUNCEMENTS)
http.postNoContent(
"chat/announcements",
params =
listOf(
"broadcaster_id" to broadcasterId,
"moderator_id" to moderatorId,
),
body =
http.encodeBody(
AnnouncementRequest(
message = message,
color = color.value,
sourceOnly = sourceOnly,
),
),
)
}
/**
* [Twitch API: Get User Chat Color](https://dev.twitch.tv/docs/api/reference/#get-user-chat-color)
*
* Gets the color used for the user's name in chat.
*
* @param userIds the IDs of the users whose username color you want to get. To specify more
* than one user, include the parameter for each user to get. You may specify a maximum of
* 100 IDs. The API ignores duplicate IDs and IDs that weren't found.
* @return the list of users and the color code that's used for their name.
*/
suspend fun getUserColor(userIds: List<String>): List<ChatColorEntry> =
http
.get<ChatColorEntry>(
"chat/color",
userIds.map { "user_id" to it },
).data
/**
* [Twitch API: Update User Chat Color](https://dev.twitch.tv/docs/api/reference/#update-user-chat-color)
*
* Updates the color used for the user's name in chat.
*
* @param userId the ID of the user whose chat color you want to update. This ID must match
* the user ID in the access token.
* @param color the color to use for the user's name in chat. All users may specify one of
* the following named color values: `blue`, `blue_violet`, `cadet_blue`, `chocolate`,
* `coral`, `dodger_blue`, `firebrick`, `golden_rod`, `green`, `hot_pink`, `orange_red`,
* `red`, `sea_green`, `spring_green`, `yellow_green`. Turbo and Prime users may also
* specify a Hex color code (for example, `#9146FF`). If you use a Hex color code, remember
* to URL-encode the `#` as `%23`.
*/
@RequiresScope(TwitchScope.USER_MANAGE_CHAT_COLOR)
suspend fun updateUserColor(
userId: String,
color: String,
) {
http.validateScopes(TwitchScope.USER_MANAGE_CHAT_COLOR)
http.putNoContent(
"chat/color",
params =
listOf(
"user_id" to userId,
"color" to color,
),
)
}
/**
* [Twitch API: Get Shared Chat Session](https://dev.twitch.tv/docs/api/reference/#get-shared-chat-session)
*
* Retrieves the active shared chat session for a channel.
*
* **NOTE:** This endpoint is only available for channels that are in an active shared chat
* session. If the channel is not in a shared chat session, the response will be a 404 error.
*
* @param broadcasterId the User ID of the channel broadcaster.
* @return the active [SharedChatSession] for the specified channel.
*/
suspend fun getSharedChatSession(broadcasterId: String): SharedChatSession =
http
.get<SharedChatSession>(
"shared_chat/session",
listOf("broadcaster_id" to broadcasterId),
).requireFirst("shared_chat/session")
/**
* [Twitch API: Get User Emotes](https://dev.twitch.tv/docs/api/reference/#get-user-emotes)
*
* Gets all emotes that the specified Twitch user has access to.
* Automatically paginates through all results.
*
* @param userId the ID of the user. This ID must match the user ID in the user access token.
* @param broadcasterId the User ID of a broadcaster you wish to get follower emotes of.
* @return a [Flow] of [UserEmote] objects.
*/
@RequiresScope(TwitchScope.USER_READ_EMOTES)
fun getAllUserEmotes(
userId: String,
broadcasterId: String? = null,
): Flow<UserEmote> {
val params =
buildList {
add("user_id" to userId)
broadcasterId?.let { add("broadcaster_id" to it) }
}
return http
.paginate<UserEmote>("chat/emotes/user", params)
.onStart { http.validateScopes(TwitchScope.USER_READ_EMOTES) }
}
/**
* [Twitch API: Get User Emotes](https://dev.twitch.tv/docs/api/reference/#get-user-emotes)
*
* Gets a single page of emotes that the specified Twitch user has access to.
*
* @param userId the ID of the user. This ID must match the user ID in the user access token.
* @param cursor the cursor used to get the next page of results.
* @param broadcasterId the User ID of a broadcaster you wish to get follower emotes of.
* @return a [Page] of [UserEmote] objects.
*/
@RequiresScope(TwitchScope.USER_READ_EMOTES)
suspend fun getUserEmotes(
userId: String,
cursor: String? = null,
broadcasterId: String? = null,
): Page<UserEmote> {
http.validateScopes(TwitchScope.USER_READ_EMOTES)
val params =
buildList {
add("user_id" to userId)
cursor?.let { add("after" to it) }
broadcasterId?.let { add("broadcaster_id" to it) }
}
return http.getPage(endpoint = "chat/emotes/user", params = params)
}
}
@Serializable
internal data class UpdateChatSettingsRequest(
@SerialName("slow_mode") val slowMode: Boolean? = null,
@SerialName("slow_mode_wait_time") val slowModeWaitTime: Int? = null,
@SerialName("follower_mode") val followerMode: Boolean? = null,
@SerialName("follower_mode_duration") val followerModeDuration: Int? = null,
@SerialName("subscriber_mode") val subscriberMode: Boolean? = null,
@SerialName("emote_mode") val emoteMode: Boolean? = null,
@SerialName("unique_chat_mode") val uniqueChatMode: Boolean? = null,
@SerialName("non_moderator_chat_delay") val nonModeratorChatDelay: Boolean? = null,
@SerialName("non_moderator_chat_delay_duration") val nonModeratorChatDelayDuration: Int? = null,
)
@Serializable
internal data class AnnouncementRequest(
val message: String,
val color: String = "primary",
@SerialName("source_only") val sourceOnly: Boolean? = null,
)