Skip to content

Commit

Permalink
add EventSub channel.subscription.message
Browse files Browse the repository at this point in the history
  • Loading branch information
d-fischer committed Jun 20, 2021
1 parent 73188cc commit c95cd01
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .eslintrc.js
Expand Up @@ -63,7 +63,7 @@ const memberNames = [
'^tag_(ids|list)$',
'^cooldown_end_time$',
'^(last|top)_contributions?$',
'^(streak|cumulative)_months',
'^(streak|cumulative|duration)_months',
'^live_only$',
'^localization_(names|descriptions)',
'^allow_notifications$',
Expand Down
22 changes: 22 additions & 0 deletions packages/twitch-eventsub/src/EventSubBase.ts
Expand Up @@ -32,6 +32,7 @@ import type { EventSubChannelRewardEvent } from './Events/EventSubChannelRewardE
import type { EventSubChannelSubscriptionEndEvent } from './Events/EventSubChannelSubscriptionEndEvent';
import type { EventSubChannelSubscriptionEvent } from './Events/EventSubChannelSubscriptionEvent';
import type { EventSubChannelSubscriptionGiftEvent } from './Events/EventSubChannelSubscriptionGiftEvent';
import type { EventSubChannelSubscriptionMessageEvent } from './Events/EventSubChannelSubscriptionMessageEvent';
import type { EventSubChannelUnbanEvent } from './Events/EventSubChannelUnbanEvent';
import type { EventSubChannelUpdateEvent } from './Events/EventSubChannelUpdateEvent';
import type { EventSubExtensionBitsTransactionCreateEvent } from './Events/EventSubExtensionBitsTransactionCreateEvent';
Expand Down Expand Up @@ -63,6 +64,7 @@ import { EventSubChannelRewardRemoveSubscription } from './Subscriptions/EventSu
import { EventSubChannelRewardUpdateSubscription } from './Subscriptions/EventSubChannelRewardUpdateSubscription';
import { EventSubChannelSubscriptionEndSubscription } from './Subscriptions/EventSubChannelSubscriptionEndSubscription';
import { EventSubChannelSubscriptionGiftSubscription } from './Subscriptions/EventSubChannelSubscriptionGiftSubscription';
import { EventSubChannelSubscriptionMessageSubscription } from './Subscriptions/EventSubChannelSubscriptionMessageSubscription';
import { EventSubChannelSubscriptionSubscription } from './Subscriptions/EventSubChannelSubscriptionSubscription';
import { EventSubChannelUnbanSubscription } from './Subscriptions/EventSubChannelUnbanSubscription';
import { EventSubChannelUpdateSubscription } from './Subscriptions/EventSubChannelUpdateSubscription';
Expand Down Expand Up @@ -253,6 +255,26 @@ export abstract class EventSubBase {
return this._genericSubscribe(EventSubChannelSubscriptionGiftSubscription, handler, this, userId);
}

/**
* Subscribes to events that represent a user's subscription to a channel being announced.
*
* @param user The user for which to get notifications for about announced subscriptions.
* @param handler The function that will be called for any new notifications.
*/
async subscribeToChannelSubscriptionMessageEvents(
user: UserIdResolvable,
handler: (event: EventSubChannelSubscriptionMessageEvent) => void
): Promise<EventSubSubscription> {
const userId = extractUserId(user);

if (!numberRegex.test(userId)) {
this._logger.warn(
'EventSubListener#subscribeToChannelSubscriptionMessageEvents: The given user is a non-numeric string. You might be sending a user name instead of a user ID.'
);
}
return this._genericSubscribe(EventSubChannelSubscriptionMessageSubscription, handler, this, userId);
}

/**
* Subscribes to events that represent a user's subscription to a channel ending.
*
Expand Down
@@ -0,0 +1,141 @@
import { Enumerable } from '@d-fischer/shared-utils';
import type { ApiClient, HelixUser } from 'twitch';
import { rtfm } from 'twitch-common';

/**
* The tier of a subscription. 1000 means tier 1, and so on.
*/
export type EventSubChannelSubscriptionMessageEventTier = '1000' | '2000' | '3000';

/** @private */
export interface EventSubChannelSubscriptionMessageEmoteData {
begin: number;
end: number;
id: string;
}

/** @private */
export interface EventSubChannelSubscriptionMessageData {
text: string;
emotes: EventSubChannelSubscriptionMessageEmoteData[];
}

/** @private */
export interface EventSubChannelSubscriptionMessageEventData {
user_id: string;
user_login: string;
user_name: string;
broadcaster_user_id: string;
broadcaster_user_login: string;
broadcaster_user_name: string;
tier: EventSubChannelSubscriptionMessageEventTier;
message: EventSubChannelSubscriptionMessageData;
cumulative_months: number;
streak_months: number | null;
duration_months: number;
}

/**
* An EventSub event representing the public announcement of a channel subscription by the subscriber.
*/
@rtfm<EventSubChannelSubscriptionMessageEvent>('twitch-eventsub', 'EventSubChannelSubscriptionMessageEvent', 'userId')
export class EventSubChannelSubscriptionMessageEvent {
/** @private */
@Enumerable(false) protected readonly _client: ApiClient;

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

/**
* The ID of the user whose subscription is being announced.
*/
get userId(): string {
return this._data.user_id;
}

/**
* The name of the user whose subscription is being announced.
*/
get userName(): string {
return this._data.user_login;
}

/**
* The display name of the user whose subscription is being announced.
*/
get userDisplayName(): string {
return this._data.user_name;
}

/**
* Retrieves more information about the user whose subscription is being announced.
*/
async getUser(): Promise<HelixUser> {
return (await this._client.helix.users.getUserById(this._data.user_id))!;
}

/**
* The ID of the broadcaster.
*/
get broadcasterId(): string {
return this._data.broadcaster_user_id;
}

/**
* The name of the broadcaster.
*/
get broadcasterName(): string {
return this._data.broadcaster_user_login;
}

/**
* The display name of the broadcaster.
*/
get broadcasterDisplayName(): string {
return this._data.broadcaster_user_name;
}

/**
* Retrieves more information about the broadcaster.
*/
async getBroadcaster(): Promise<HelixUser> {
return (await this._client.helix.users.getUserById(this._data.broadcaster_user_id))!;
}

/**
* The tier of the subscription, either 1000, 2000 or 3000.
*/
get tier(): EventSubChannelSubscriptionMessageEventTier {
return this._data.tier;
}

/**
* The total number of months the user has been subscribed.
*/
get cumulativeMonths(): number {
return this._data.cumulative_months;
}

/**
* The number of months the user has been subscribed in a row, or null if they don't want to share it.
*/
get streakMonths(): number | null {
return this._data.streak_months;
}

/**
* The number of months the user has now subscribed.
*/
get durationMonths(): number {
return this._data.duration_months;
}

/**
* The text of the message.
*/
get messageText(): string {
return this._data.message.text;
}
}
@@ -0,0 +1,37 @@
import type { HelixEventSubSubscription } from 'twitch';
import { rtfm } from 'twitch-common';
import type { EventSubChannelSubscriptionMessageEventData } from '../Events/EventSubChannelSubscriptionMessageEvent';
import { EventSubChannelSubscriptionMessageEvent } from '../Events/EventSubChannelSubscriptionMessageEvent';
import type { EventSubBase } from '../EventSubBase';
import { EventSubSubscription } from './EventSubSubscription';

/**
* @private
*/
@rtfm('twitch-eventsub', 'EventSubSubscription')
export class EventSubChannelSubscriptionMessageSubscription extends EventSubSubscription<EventSubChannelSubscriptionMessageEvent> {
constructor(
handler: (data: EventSubChannelSubscriptionMessageEvent) => void,
client: EventSubBase,
private readonly _userId: string
) {
super(handler, client);
}

get id(): string {
return `channel.subscription.end.${this._userId}`;
}

protected transformData(
data: EventSubChannelSubscriptionMessageEventData
): EventSubChannelSubscriptionMessageEvent {
return new EventSubChannelSubscriptionMessageEvent(data, this._client._apiClient);
}

protected async _subscribe(): Promise<HelixEventSubSubscription> {
return this._client._apiClient.helix.eventSub.subscribeToChannelSubscriptionMessageEvents(
this._userId,
await this._getTransportOptions()
);
}
}
18 changes: 18 additions & 0 deletions packages/twitch/src/API/Helix/EventSub/HelixEventSubApi.ts
Expand Up @@ -348,6 +348,24 @@ export class HelixEventSubApi extends BaseApi {
);
}

/**
* Subscribe to events that represent a user's subscription to a channel being announced.
*
* @param broadcaster The broadcaster you want to listen to subscription message events for.
* @param transport The transport options
*/
async subscribeToChannelSubscriptionMessageEvents(
broadcaster: UserIdResolvable,
transport: HelixEventSubTransportOptions
): Promise<HelixEventSubSubscription> {
return this.createSubscription(
'channel.subscription.message',
'1',
{ broadcaster_user_id: extractUserId(broadcaster) },
transport
);
}

/**
* Subscribe to events that represent a user's subscription to a channel ending.
*
Expand Down

0 comments on commit c95cd01

Please sign in to comment.