Skip to content

Commit

Permalink
support channel.chat.message, channel.chat.notification and add suppo…
Browse files Browse the repository at this point in the history
…rt for user context in other chat topics

fixes #535
  • Loading branch information
d-fischer committed Feb 8, 2024
1 parent 42410bc commit 5cf14b5
Show file tree
Hide file tree
Showing 27 changed files with 1,590 additions and 21 deletions.
52 changes: 49 additions & 3 deletions packages/api/src/endpoints/eventSub/HelixEventSubApi.ts
Expand Up @@ -6,6 +6,7 @@ import {
createEventSubDropEntitlementGrantCondition,
createEventSubModeratorCondition,
createEventSubRewardCondition,
createEventSubUserCondition,
type HelixEventSubSubscriptionData,
type HelixEventSubSubscriptionStatus,
type HelixPaginatedEventSubSubscriptionsResponse,
Expand Down Expand Up @@ -1219,10 +1220,11 @@ export class HelixEventSubApi extends BaseApi {
broadcaster: UserIdResolvable,
transport: HelixEventSubTransportOptions,
): Promise<HelixEventSubSubscription> {
const broadcasterId = extractUserId(broadcaster);
return await this.createSubscription(
'channel.chat.clear',
'1',
createEventSubBroadcasterCondition(broadcaster),
createEventSubUserCondition(broadcasterId, this._getUserContextIdWithDefault(broadcasterId)),
transport,
broadcaster,
['user:read:chat'],
Expand All @@ -1239,10 +1241,11 @@ export class HelixEventSubApi extends BaseApi {
broadcaster: UserIdResolvable,
transport: HelixEventSubTransportOptions,
): Promise<HelixEventSubSubscription> {
const broadcasterId = extractUserId(broadcaster);
return await this.createSubscription(
'channel.chat.clear_user_messages',
'1',
createEventSubBroadcasterCondition(broadcaster),
createEventSubUserCondition(broadcasterId, this._getUserContextIdWithDefault(broadcasterId)),
transport,
broadcaster,
['user:read:chat'],
Expand All @@ -1259,10 +1262,53 @@ export class HelixEventSubApi extends BaseApi {
broadcaster: UserIdResolvable,
transport: HelixEventSubTransportOptions,
): Promise<HelixEventSubSubscription> {
const broadcasterId = extractUserId(broadcaster);
return await this.createSubscription(
'channel.chat.message_delete',
'1',
createEventSubBroadcasterCondition(broadcaster),
createEventSubUserCondition(broadcasterId, this._getUserContextIdWithDefault(broadcasterId)),
transport,
broadcaster,
['user:read:chat'],
);
}

/**
* Subscribe to events that represent a chat notification in a channel.
*
* @param broadcaster The broadcaster for which you want to listen to chat notification events.
* @param transport The transport options.
*/
async subscribeToChannelChatNotificationEvents(
broadcaster: UserIdResolvable,
transport: HelixEventSubTransportOptions,
): Promise<HelixEventSubSubscription> {
const broadcasterId = extractUserId(broadcaster);
return await this.createSubscription(
'channel.chat.notification',
'1',
createEventSubUserCondition(broadcasterId, this._getUserContextIdWithDefault(broadcasterId)),
transport,
broadcaster,
['user:read:chat'],
);
}

/**
* Subscribe to events that represent a chat message in a channel.
*
* @param broadcaster The broadcaster for which you want to listen to chat message events.
* @param transport The transport options.
*/
async subscribeToChannelChatMessageEvents(
broadcaster: UserIdResolvable,
transport: HelixEventSubTransportOptions,
): Promise<HelixEventSubSubscription> {
const broadcasterId = extractUserId(broadcaster);
return await this.createSubscription(
'channel.chat.message',
'1',
createEventSubUserCondition(broadcasterId, this._getUserContextIdWithDefault(broadcasterId)),
transport,
broadcaster,
['user:read:chat'],
Expand Down
8 changes: 8 additions & 0 deletions packages/api/src/interfaces/endpoints/eventSub.external.ts
Expand Up @@ -84,6 +84,14 @@ export function createEventSubModeratorCondition(broadcasterId: string, moderato
};
}

/** @internal */
export function createEventSubUserCondition(broadcasterId: string, userId: string) {
return {
broadcaster_user_id: broadcasterId,
user_id: userId,
};
}

/** @internal */
export function createEventSubDropEntitlementGrantCondition(
filter: HelixEventSubDropEntitlementGrantFilter,
Expand Down
68 changes: 62 additions & 6 deletions packages/eventsub-base/src/EventSubBase.ts
Expand Up @@ -10,6 +10,7 @@ import {
type UserIdResolvable,
} from '@twurple/api';
import { rtfm } from '@twurple/common';
import { type EventSubChannelChatNotificationEvent } from './events/chatNotifications/EventSubChannelChatNotificationEvent';
import type { EventSubChannelAdBreakBeginEvent } from './events/EventSubChannelAdBreakBeginEvent';
import type { EventSubChannelBanEvent } from './events/EventSubChannelBanEvent';
import type { EventSubChannelCharityCampaignProgressEvent } from './events/EventSubChannelCharityCampaignProgressEvent';
Expand Down Expand Up @@ -65,6 +66,7 @@ import { EventSubChannelCharityDonationSubscription } from './subscriptions/Even
import { EventSubChannelChatClearSubscription } from './subscriptions/EventSubChannelChatClearSubscription';
import { EventSubChannelChatClearUserMessagesSubscription } from './subscriptions/EventSubChannelChatClearUserMessagesSubscription';
import { EventSubChannelChatMessageDeleteSubscription } from './subscriptions/EventSubChannelChatMessageDeleteSubscription';
import { EventSubChannelChatNotificationSubscription } from './subscriptions/EventSubChannelChatNotificationSubscription';
import { EventSubChannelCheerSubscription } from './subscriptions/EventSubChannelCheerSubscription';
import { EventSubChannelFollowSubscription } from './subscriptions/EventSubChannelFollowSubscription';
import { EventSubChannelGoalBeginSubscription } from './subscriptions/EventSubChannelGoalBeginSubscription';
Expand Down Expand Up @@ -968,46 +970,100 @@ export abstract class EventSubBase extends EventEmitter {
/**
* Subscribes to events that represent an channel's chat being cleared.
*
* @param user The user for which to get notifications about chat being cleared in their channel.
* @param broadcaster The user for which to get notifications about chat being cleared in their channel.
* @param user The user to use for reading the channel's chat.
* @param handler The function that will be called for any new notifications.
*/
onChannelChatClear(
broadcaster: UserIdResolvable,
user: UserIdResolvable,
handler: (data: EventSubChannelChatClearEvent) => void,
): EventSubSubscription {
const broadcasterId = this._extractUserIdWithNumericWarning(broadcaster, 'subscribeToChannelChatClearEvents');
const userId = this._extractUserIdWithNumericWarning(user, 'subscribeToChannelChatClearEvents');

return this._genericSubscribe(EventSubChannelChatClearSubscription, handler, this, userId);
return this._genericSubscribe(EventSubChannelChatClearSubscription, handler, this, broadcasterId, userId);
}

/**
* Subscribes to events that represent a user's chat messages being cleared in a channel.
*
* @param user The user for which to get notifications about a user's chat messages being cleared in their channel.
* @param broadcaster The user for which to get notifications about a user's chat messages being cleared in their channel.
* @param user The user to use for reading the channel's chat.
* @param handler The function that will be called for any new notifications.
*/
onChannelChatClearUserMessages(
broadcaster: UserIdResolvable,
user: UserIdResolvable,
handler: (data: EventSubChannelChatClearUserMessagesEvent) => void,
): EventSubSubscription {
const broadcasterId = this._extractUserIdWithNumericWarning(
broadcaster,
'subscribeToChannelChatClearUserMessagesEvents',
);
const userId = this._extractUserIdWithNumericWarning(user, 'subscribeToChannelChatClearUserMessagesEvents');

return this._genericSubscribe(EventSubChannelChatClearUserMessagesSubscription, handler, this, userId);
return this._genericSubscribe(
EventSubChannelChatClearUserMessagesSubscription,
handler,
this,
broadcasterId,
userId,
);
}

/**
* Subscribes to events that represent a chat message being deleted in a channel.
*
* @param user The user for which to get notifications about a chat message being deleted in their channel.
* @param broadcaster The user for which to get notifications about a chat message being deleted in their channel.
* @param user The user to use for reading the channel's chat.
* @param handler The function that will be called for any new notifications.
*/
onChannelChatMessageDelete(
broadcaster: UserIdResolvable,
user: UserIdResolvable,
handler: (data: EventSubChannelChatMessageDeleteEvent) => void,
): EventSubSubscription {
const broadcasterId = this._extractUserIdWithNumericWarning(
broadcaster,
'subscribeToChannelChatMessageDeleteEvents',
);
const userId = this._extractUserIdWithNumericWarning(user, 'subscribeToChannelChatMessageDeleteEvents');

return this._genericSubscribe(
EventSubChannelChatMessageDeleteSubscription,
handler,
this,
broadcasterId,
userId,
);
}

/**
* Subscribes to events that represent a chat notification being sent to a channel.
*
* @param broadcaster The user for which to get chat notifications in their channel.
* @param user The user to use for reading the channel's chat.
* @param handler The function that will be called for any new notifications.
*/
onChannelChatNotification(
broadcaster: UserIdResolvable,
user: UserIdResolvable,
handler: (data: EventSubChannelChatNotificationEvent) => void,
): EventSubSubscription {
const broadcasterId = this._extractUserIdWithNumericWarning(
broadcaster,
'subscribeToChannelChatMessageDeleteEvents',
);
const userId = this._extractUserIdWithNumericWarning(user, 'subscribeToChannelChatMessageDeleteEvents');

return this._genericSubscribe(EventSubChannelChatMessageDeleteSubscription, handler, this, userId);
return this._genericSubscribe(
EventSubChannelChatNotificationSubscription,
handler,
this,
broadcasterId,
userId,
);
}

/**
Expand Down
26 changes: 23 additions & 3 deletions packages/eventsub-base/src/EventSubListener.ts
@@ -1,5 +1,6 @@
import { type HelixEventSubDropEntitlementGrantFilter } from '@twurple/api';
import type { UserIdResolvable } from '@twurple/common';
import { type EventSubChannelChatNotificationEvent } from './events/chatNotifications/EventSubChannelChatNotificationEvent';
import type { EventSubChannelAdBreakBeginEvent } from './events/EventSubChannelAdBreakBeginEvent';
import type { EventSubChannelBanEvent } from './events/EventSubChannelBanEvent';
import type { EventSubChannelCharityCampaignProgressEvent } from './events/EventSubChannelCharityCampaignProgressEvent';
Expand Down Expand Up @@ -586,36 +587,55 @@ export interface EventSubListener {
/**
* Subscribes to events that represent a channel's chat being cleared.
*
* @param user The user for which to get notifications about chat being cleared in their channel.
* @param broadcaster The user for which to get notifications about chat being cleared in their channel.
* @param user The user to use for reading the channel's chat.
* @param handler The function that will be called for any new notifications.
*/
onChannelChatClear: (
broadcaster: UserIdResolvable,
user: UserIdResolvable,
handler: (data: EventSubChannelChatClearEvent) => void,
) => EventSubSubscription;

/**
* Subscribes to events that represent a user's chat messages being cleared in a channel.
*
* @param user The user for which to get notifications about a user's chat messages being cleared in their channel.
* @param broadcaster The user for which to get notifications about a user's chat messages being cleared in their channel.
* @param user The user to use for reading the channel's chat.
* @param handler The function that will be called for any new notifications.
*/
onChannelChatClearUserMessages: (
broadcaster: UserIdResolvable,
user: UserIdResolvable,
handler: (data: EventSubChannelChatClearUserMessagesEvent) => void,
) => EventSubSubscription;

/**
* Subscribes to events that represent a chat message being deleted in a channel.
*
* @param user The user for which to get notifications about a chat message being deleted in their channel.
* @param broadcaster The user for which to get notifications about a chat message being deleted in their channel.
* @param user The user to use for reading the channel's chat.
* @param handler The function that will be called for any new notifications.
*/
onChannelChatMessageDelete: (
broadcaster: UserIdResolvable,
user: UserIdResolvable,
handler: (data: EventSubChannelChatMessageDeleteEvent) => void,
) => EventSubSubscription;

/**
* Subscribes to events that represent a chat notification being sent to a channel.
*
* @param broadcaster The user for which to get chat notifications in their channel.
* @param user The user to use for reading the channel's chat.
* @param handler The function that will be called for any new notifications.
*/
onChannelChatNotification: (
broadcaster: UserIdResolvable,
user: UserIdResolvable,
handler: (data: EventSubChannelChatNotificationEvent) => void,
) => EventSubSubscription;

/**
* Subscribes to events that represent a drop entitlement being granted.
*
Expand Down
@@ -0,0 +1,42 @@
import { type EventSubChatBadge, type EventSubChatMessageData } from './common/EventSubChatMessage.external';

/**
* The type of message that was sent.
*/
export type EventSubChatMessageType = 'text' | 'channel_points_highlighted' | 'channel_points_sub_only' | 'user_intro';

/** @private */
export interface EventSubChatMessageCheerData {
bits: number;
}

/** @private */
export interface EventSubChatMessageReplyData {
parent_message_id: string;
parent_message_body: string;
parent_user_id: string;
parent_user_name: string;
parent_user_login: string;
thread_message_id: string;
thread_user_id: string;
thread_user_name: string;
thread_user_login: string;
}

/** @private */
export interface EventSubChannelChatMessageEventData {
broadcaster_user_id: string;
broadcaster_user_login: string;
broadcaster_user_name: string;
chatter_user_id: string;
chatter_user_login: string;
chatter_user_name: string;
message_id: string;
message: EventSubChatMessageData;
message_type: EventSubChatMessageType;
badges: EventSubChatBadge[];
cheer: EventSubChatMessageCheerData | null;
color: string;
reply: EventSubChatMessageReplyData | null;
channel_points_custom_reward_id: string | null;
}

0 comments on commit 5cf14b5

Please sign in to comment.