Skip to content
This repository was archived by the owner on Apr 13, 2025. It is now read-only.

Commit eaa730f

Browse files
authored
Merge pull request #988 from SteffoSpieler/fix/streamelements-doing-api-changes
StreamElements: Fix API, remove specific Test-Events and add flag for subbomb subscriber event data
2 parents 7e579c8 + 64c73db commit eaa730f

File tree

5 files changed

+32
-320
lines changed

5 files changed

+32
-320
lines changed

samples/streamelements-events/extension/index.ts

Lines changed: 6 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import NodeCG from "@nodecg/types";
22
import { StreamElementsReplicant, StreamElementsServiceClient } from "nodecg-io-streamelements";
3-
import { StreamElementsEvent, StreamElementsTestEvent } from "nodecg-io-streamelements/extension/StreamElementsEvent";
3+
import { StreamElementsEvent } from "nodecg-io-streamelements/extension/StreamElementsEvent";
44
import { requireService } from "nodecg-io-core";
55

66
module.exports = function (nodecg: NodeCG.ServerAPI) {
@@ -16,40 +16,20 @@ module.exports = function (nodecg: NodeCG.ServerAPI) {
1616
nodecg.log.info(`${getName(data)} just cheered ${data.data.amount} bit(s). Message: ${data.data.message}`);
1717
});
1818

19-
client.onTestCheer((data) => {
20-
nodecg.log.info(
21-
`${getName(data)} just cheered ${data.event.amount} bit(s). Message: ${data.event.message}`,
22-
);
23-
});
24-
2519
client.onFollow((data) => {
2620
nodecg.log.info(`${getName(data)} just followed.`);
2721
});
2822

29-
client.onTestFollow((data) => {
30-
nodecg.log.info(`${getName(data)} just followed.`);
31-
});
32-
3323
client.onSubscriber((data) => {
3424
nodecg.log.info(
3525
`${getName(data)} just subscribed for ${data.data.amount} months (${formatSubTier(data.data.tier)}).`,
3626
);
37-
});
38-
39-
client.onTestSubscriber((data) => {
40-
nodecg.log.info(
41-
`${getName(data)} just subscribed for ${data.event.amount} months (${formatSubTier(data.event.tier)}).`,
42-
);
43-
});
27+
}, false);
4428

4529
client.onSubscriberBomb((data) => {
4630
nodecg.log.info(`${data.gifterUsername} just gifted ${data.subscribers.length} subs.`);
4731
});
4832

49-
client.onTestSubscriberBomb((data) => {
50-
nodecg.log.info(`${data.gifterUsername} just gifted ${data.subscribers.length} subs.`);
51-
});
52-
5333
client.onGift((data) => {
5434
nodecg.log.info(
5535
`${getName(data)} just got a tier ${formatSubTier(data.data.tier)} subscription from ${
@@ -58,30 +38,14 @@ module.exports = function (nodecg: NodeCG.ServerAPI) {
5838
);
5939
});
6040

61-
client.onTestGift((data) => {
62-
nodecg.log.info(
63-
`${getName(data)} just got a tier ${formatSubTier(data.event.tier)} subscription from ${
64-
data.event.sender ?? "anonymous"
65-
}! It's ${data.event.displayName}'s ${data.event.amount} month.`,
66-
);
67-
});
68-
6941
client.onHost((data) => {
7042
nodecg.log.info(`${getName(data)} just hosted the stream for ${data.data.amount} viewer(s).`);
7143
});
7244

73-
client.onTestHost((data) => {
74-
nodecg.log.info(`${getName(data)} just hosted the stream for ${data.event.amount} viewer(s).`);
75-
});
76-
7745
client.onRaid((data) => {
7846
nodecg.log.info(`${getName(data)} just raided the stream with ${data.data.amount} viewers.`);
7947
});
8048

81-
client.onTestRaid((data) => {
82-
nodecg.log.info(`${getName(data)} just raided the stream with ${data.event.amount} viewers.`);
83-
});
84-
8549
client.onTip((data) => {
8650
if (data.data.currency) {
8751
nodecg.log.info(
@@ -92,46 +56,18 @@ module.exports = function (nodecg: NodeCG.ServerAPI) {
9256
}
9357
});
9458

95-
client.onTestTip((data) => {
96-
nodecg.log.info(
97-
`${getName(data)} just donated ${data.event.amount} ${data.event.currency}. Message. ${
98-
data.event.message
99-
}`,
100-
);
101-
});
102-
103-
client.onTest((data) => {
104-
nodecg.log.info(JSON.stringify(data));
105-
});
106-
10759
client.setupReplicant(streamElementsReplicant);
10860
});
10961

11062
streamElements?.onUnavailable(() => nodecg.log.info("SE client has been unset."));
11163
};
11264

113-
/**
114-
* Gets the name of the user from the event.
115-
* Defaults to use the displayName that is sent by StreamElements.
116-
* The displayName contains capitalization and special characters.
117-
* If the displayName is not available, the normal username of the relevant platform is used.
118-
* Supports real and test events.
119-
*/
120-
function getName(event: StreamElementsEvent | StreamElementsTestEvent): string {
121-
const eventData = "data" in event ? event.data : event.event;
122-
123-
if ("displayName" in eventData && typeof eventData.displayName === "string") {
124-
return eventData.displayName;
125-
} else if ("name" in eventData && typeof eventData.name === "string") {
126-
return eventData.name;
127-
} else if ("username" in eventData && typeof eventData.username === "string") {
128-
return eventData.username;
129-
} else {
130-
return "unknown";
131-
}
65+
function getName(event: StreamElementsEvent): string {
66+
return event.data.displayName ?? event.data.username;
13267
}
13368

134-
function formatSubTier(tier: "1000" | "2000" | "3000" | "prime"): string {
69+
function formatSubTier(tier?: "1000" | "2000" | "3000" | "prime"): string {
70+
if (!tier) return "unknown";
13571
if (tier === "prime") return "Twitch Prime";
13672

13773
// We want to display the tier as 1, 2, 3

services/nodecg-io-streamelements/extension/StreamElements.ts

Lines changed: 10 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,16 @@ import {
66
StreamElementsFollowEvent,
77
StreamElementsHostEvent,
88
StreamElementsRaidEvent,
9-
StreamElementsReplayEvent,
109
StreamElementsSubBombEvent,
1110
StreamElementsSubscriberEvent,
12-
StreamElementsTestCheerEvent,
13-
StreamElementsTestEvent,
14-
StreamElementsTestFollowEvent,
15-
StreamElementsTestHostEvent,
16-
StreamElementsTestRaidEvent,
17-
StreamElementsTestSubscriberEvent,
18-
StreamElementsTestTipEvent,
1911
StreamElementsTipEvent,
2012
} from "./StreamElementsEvent";
2113
import { EventEmitter } from "events";
2214
import NodeCG from "@nodecg/types";
2315

2416
export interface StreamElementsReplicant {
2517
lastSubscriber?: StreamElementsSubscriberEvent;
26-
lastSubBomb?: StreamElementsSubBombEvent<StreamElementsSubscriberEvent>;
18+
lastSubBomb?: StreamElementsSubBombEvent;
2719
lastTip?: StreamElementsTipEvent;
2820
lastCheer?: StreamElementsCheerEvent;
2921
lastGift?: StreamElementsSubscriberEvent;
@@ -37,14 +29,14 @@ export interface StreamElementsReplicant {
3729
*/
3830
interface SubBomb {
3931
timeout: NodeJS.Timeout;
40-
subs: Array<StreamElementsSubscriberEvent | StreamElementsTestSubscriberEvent>;
32+
subs: Array<StreamElementsSubscriberEvent>;
4133
}
4234

4335
export class StreamElementsServiceClient extends EventEmitter {
4436
private socket: SocketIOClient.Socket;
4537
private subBombDetectionMap: Map<string, SubBomb> = new Map();
4638

47-
constructor(private jwtToken: string, private handleTestEvents: boolean) {
39+
constructor(private jwtToken: string) {
4840
super();
4941
}
5042

@@ -73,32 +65,12 @@ export class StreamElementsServiceClient extends EventEmitter {
7365
}
7466
this.emit(data.type, data);
7567
});
76-
77-
if (this.handleTestEvents) {
78-
this.onTestEvent((data: StreamElementsTestEvent) => {
79-
if (data.listener) {
80-
this.emit("test", data);
81-
this.emit("test:" + data.listener, data);
82-
}
83-
});
84-
85-
this.onTestSubscriber((data) => {
86-
if (data.event.gifted) {
87-
this.handleSubGift(
88-
data.event.sender,
89-
data,
90-
(subBomb) => this.emit("test:subbomb", subBomb),
91-
(gift) => this.emit("test:gift", gift),
92-
);
93-
}
94-
});
95-
}
9668
}
9769

98-
private handleSubGift<T extends StreamElementsSubscriberEvent | StreamElementsTestSubscriberEvent>(
70+
private handleSubGift<T extends StreamElementsSubscriberEvent>(
9971
subGifter: string | undefined,
10072
gift: T,
101-
handlerSubBomb: (data: StreamElementsSubBombEvent<T>) => void,
73+
handlerSubBomb: (data: StreamElementsSubBombEvent) => void,
10274
handlerGift: (data: T) => void,
10375
) {
10476
const gifter = subGifter ?? "anonymous";
@@ -116,6 +88,10 @@ export class StreamElementsServiceClient extends EventEmitter {
11688
subscribers: subBomb.subs as T[],
11789
};
11890
handlerSubBomb(subBombEvent);
91+
92+
subBomb.subs.forEach(sub => {
93+
sub.data.isFromSubBomb = true;
94+
});
11995
}
12096

12197
subBomb.subs.forEach(handlerGift);
@@ -183,36 +159,14 @@ export class StreamElementsServiceClient extends EventEmitter {
183159
});
184160
}
185161

186-
private onTestEvent(handler: (data: StreamElementsTestEvent) => void): void {
187-
this.socket.on("event:test", (data: StreamElementsTestEvent) => {
188-
if (data) {
189-
handler(data);
190-
}
191-
});
192-
193-
this.socket.on("event:update", (data: StreamElementsReplayEvent) => {
194-
// event:update is all replays of previous real events.
195-
// Because the structure is similar to the test events and just the keys in the root element
196-
// are named differently we rename those to align with the naming in the test events
197-
// and handle it as a test event from here on.
198-
if (data) {
199-
handler({
200-
event: data.data,
201-
listener: data.name,
202-
provider: data.provider,
203-
} as unknown as StreamElementsTestEvent);
204-
}
205-
});
206-
}
207-
208162
public onSubscriber(handler: (data: StreamElementsSubscriberEvent) => void, includeSubGifts = true): void {
209163
this.on("subscriber", (data) => {
210164
if (data.data.gifted && !includeSubGifts) return;
211165
handler(data);
212166
});
213167
}
214168

215-
public onSubscriberBomb(handler: (data: StreamElementsSubBombEvent<StreamElementsSubscriberEvent>) => void): void {
169+
public onSubscriberBomb(handler: (data: StreamElementsSubBombEvent) => void): void {
216170
this.on("subbomb", handler);
217171
}
218172

@@ -240,47 +194,6 @@ export class StreamElementsServiceClient extends EventEmitter {
240194
this.on("host", handler);
241195
}
242196

243-
public onTest(handler: (data: StreamElementsEvent) => void): void {
244-
this.on("test", handler);
245-
}
246-
247-
public onTestSubscriber(handler: (data: StreamElementsTestSubscriberEvent) => void, includeSubGifts = true): void {
248-
this.on("test:subscriber-latest", (data) => {
249-
if (data.event.gifted && !includeSubGifts) return;
250-
handler(data);
251-
});
252-
}
253-
254-
public onTestSubscriberBomb(
255-
handler: (data: StreamElementsSubBombEvent<StreamElementsTestSubscriberEvent>) => void,
256-
): void {
257-
this.on("test:subbomb", handler);
258-
}
259-
260-
public onTestGift(handler: (data: StreamElementsTestSubscriberEvent) => void): void {
261-
this.on("test:gift", handler);
262-
}
263-
264-
public onTestCheer(handler: (data: StreamElementsTestCheerEvent) => void): void {
265-
this.on("test:cheer-latest", handler);
266-
}
267-
268-
public onTestFollow(handler: (data: StreamElementsTestFollowEvent) => void): void {
269-
this.on("test:follower-latest", handler);
270-
}
271-
272-
public onTestRaid(handler: (data: StreamElementsTestRaidEvent) => void): void {
273-
this.on("test:raid-latest", handler);
274-
}
275-
276-
public onTestHost(handler: (data: StreamElementsTestHostEvent) => void): void {
277-
this.on("test:host-latest", handler);
278-
}
279-
280-
public onTestTip(handler: (data: StreamElementsTestTipEvent) => void): void {
281-
this.on("test:tip-latest", handler);
282-
}
283-
284197
public setupReplicant(rep: NodeCG.ServerReplicant<StreamElementsReplicant>): void {
285198
if (rep.value === undefined) {
286199
rep.value = {};

0 commit comments

Comments
 (0)