Skip to content

Commit 011ed7e

Browse files
authored
Merge pull request #128 from destinygg/live-update
Update `!live` command to take Kick and Rumble streams into account
2 parents 8372346 + 09811f8 commit 011ed7e

File tree

6 files changed

+166
-44
lines changed

6 files changed

+166
-44
lines changed

lib/commands/implementations/live.js

+28-38
Original file line numberDiff line numberDiff line change
@@ -6,54 +6,44 @@ const CommandOutput = require('../command-output');
66
function live(input, services) {
77
return services.dggApi.getStreamInfo().then((data) => {
88
const now = moment();
9-
let totalViewers = 0;
10-
let twitchViewers = 0;
11-
let youtubeViewers = 0;
12-
let startedAt = 0;
13-
14-
const twitch = data.twitch;
15-
const youtube = data.youtube;
16-
17-
if (!twitch && !youtube) return new CommandOutput(null, 'Could not retrieve live status.');
18-
19-
if ((!twitch || !twitch.live) && (!youtube || !youtube.live)) {
20-
const endedAt = youtube.ended_at ? youtube.ended_at : twitch.ended_at;
21-
const duration = youtube.duration ? youtube.duration : twitch.duration;
22-
if (endedAt) {
23-
const lastOnlineDuration = formatDuration(moment.duration(now.diff(endedAt)));
24-
const timeStreamedDuration = formatDuration(moment.duration(duration, 'seconds'));
9+
10+
const isLive = () => {
11+
return data.some((s) => s?.live);
12+
};
13+
14+
const oldestStartedLiveStream = () => {
15+
return data.filter((s) => s?.live).sort((a, b) => (a.started_at < b.started_at ? -1 : 1))[0];
16+
};
17+
18+
const newestEndedStream = () => {
19+
return data
20+
.filter((s) => s?.live === false)
21+
.sort((a, b) => (a?.ended_at > b?.ended_at ? -1 : 1))[0];
22+
};
23+
24+
const totalViewers = () => {
25+
return data.filter((s) => s?.live).reduce((acc, s) => acc + s.viewers, 0);
26+
};
27+
28+
if (!isLive()) {
29+
const { duration, ended_at } = newestEndedStream() ?? {};
30+
if (duration && ended_at) {
31+
const endedAgo = formatDuration(moment.duration(now.diff(ended_at)));
32+
const friendlyDuration = formatDuration(moment.duration(duration, 'seconds'));
2533
return new CommandOutput(
2634
null,
27-
`Stream was last online ${lastOnlineDuration} ago. Time Streamed: ${timeStreamedDuration}`,
35+
`Stream was last online ${endedAgo} ago. Time Streamed: ${friendlyDuration}.`,
2836
);
2937
} else {
3038
return new CommandOutput(null, 'Stream is offline.');
3139
}
3240
}
3341

34-
if (twitch && twitch.live) {
35-
twitchViewers = parseInt(twitch.viewers, 10);
36-
totalViewers += twitchViewers;
37-
startedAt = twitch.started_at;
38-
}
39-
40-
if (youtube && youtube.live) {
41-
youtubeViewers = parseInt(youtube.viewers, 10);
42-
totalViewers += youtubeViewers;
43-
startedAt = youtube.started_at;
44-
}
45-
46-
const formattedDuration = formatDuration(moment.duration(now.diff(startedAt)));
47-
if (twitchViewers && youtubeViewers) {
48-
return new CommandOutput(
49-
null,
50-
`Viewers: ${totalViewers}, TTV: ${twitchViewers}, YT: ${youtubeViewers}. Stream live as of ${formattedDuration} ago`,
51-
);
52-
}
53-
42+
const { viewers, started_at } = oldestStartedLiveStream();
43+
const startedAgo = formatDuration(moment.duration(now.diff(started_at)));
5444
return new CommandOutput(
5545
null,
56-
`Viewers: ${totalViewers}. Stream live as of ${formattedDuration} ago`,
46+
`Viewers: ${totalViewers()}. Stream live as of ${startedAgo} ago.`,
5747
);
5848
});
5949
}

lib/services/dgg-api.js

+2-6
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,8 @@ class DggApi {
1515
},
1616
})
1717
.then((res) => {
18-
const twitch = _.get(res, 'data.data.streams.twitch');
19-
const youtube = _.get(res, 'data.data.streams.youtube');
20-
return {
21-
twitch,
22-
youtube,
23-
};
18+
const streams = _.get(res, 'data.data.streams');
19+
return _.values(streams);
2420
})
2521
.catch((err) => this.log.error('Error retrieving data from dgg api.', err));
2622
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const _ = require('lodash');
2+
const live = require('../../../../lib/commands/implementations/live');
3+
const CommandOutput = require('../../../../lib/commands/command-output');
4+
const assert = require('assert');
5+
const streamInfoOffline = require('./mocks/stream-info-offline.json');
6+
const streamInfoOfflineNull = require('./mocks/stream-info-offline-null.json');
7+
const streamInfoOnline = require('./mocks/stream-info-online.json');
8+
9+
describe('!live Test', () => {
10+
const buildMockServices = (dggApiResponse) => {
11+
return {
12+
dggApi: {
13+
getStreamInfo: () => {
14+
return Promise.resolve(_.values(dggApiResponse.data.streams));
15+
},
16+
},
17+
};
18+
};
19+
20+
it('responds with end time of newest stream when all streams are offline', function () {
21+
const expected = new CommandOutput(
22+
null,
23+
`Stream was last online 2 days 11h ago. Time Streamed: 4h 35m.`,
24+
);
25+
return live.work(null, buildMockServices(streamInfoOffline)).then((response) => {
26+
assert.deepStrictEqual(response, expected);
27+
});
28+
});
29+
30+
it('responds correctly when all streams are null', function () {
31+
const expected = new CommandOutput(null, 'Stream is offline.');
32+
return live.work(null, buildMockServices(streamInfoOfflineNull)).then((response) => {
33+
assert.deepStrictEqual(response, expected);
34+
});
35+
});
36+
37+
it('responds with start time of oldest stream and cumulative viewers', function () {
38+
const expected = new CommandOutput(null, `Viewers: 17018. Stream live as of 2 days 16h ago.`);
39+
return live.work(null, buildMockServices(streamInfoOnline)).then((response) => {
40+
assert.deepStrictEqual(response, expected);
41+
});
42+
});
43+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"data": {
3+
"streams": {
4+
"twitch": null,
5+
"youtube": null,
6+
"facebook": null,
7+
"rumble": null,
8+
"kick": null
9+
}
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"data": {
3+
"streams": {
4+
"twitch": {
5+
"live": false,
6+
"game": "Just Chatting",
7+
"preview": null,
8+
"status_text": "Okay I lied, second short stream today, leaving @ 6 PM | Random videos/articles/memes",
9+
"started_at": "2023-04-13T16:23:41+0000",
10+
"ended_at": "2023-04-13T20:59:13+0000",
11+
"duration": 16532,
12+
"viewers": null,
13+
"id": null,
14+
"platform": "twitch",
15+
"type": null
16+
},
17+
"youtube": {
18+
"live": false,
19+
"game": null,
20+
"preview": "https://i.ytimg.com/vi/HmCHsE9LYUI/mqdefault.jpg",
21+
"status_text": "Okay I lied, second short stream today, leaving @ 6 PM | Random videos/articles/memes",
22+
"started_at": "2023-04-13T16:23:41+0000",
23+
"ended_at": "2023-04-13T20:58:13+0000",
24+
"duration": 16472,
25+
"viewers": null,
26+
"id": null,
27+
"platform": "youtube",
28+
"type": "livestream"
29+
},
30+
"facebook": null,
31+
"rumble": null,
32+
"kick": null
33+
}
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"data": {
3+
"streams": {
4+
"twitch": null,
5+
"youtube": {
6+
"live": true,
7+
"game": null,
8+
"preview": "https://i.ytimg.com/vi/HmCHsE9LYUI/mqdefault.jpg",
9+
"status_text": "Okay I lied, second short stream today, leaving @ 6 PM | Random videos/articles/memes",
10+
"started_at": "2023-04-13T16:23:41+0000",
11+
"ended_at": null,
12+
"duration": 16472,
13+
"viewers": 5183,
14+
"id": "zOhOMLCuCW0",
15+
"platform": "youtube",
16+
"type": "livestream"
17+
},
18+
"facebook": null,
19+
"rumble": {
20+
"live": false,
21+
"game": null,
22+
"preview": null,
23+
"status_text": "Obamna",
24+
"started_at": "2023-04-10T13:21:40+0000",
25+
"ended_at": "2023-04-10T16:23:48+0000",
26+
"duration": 10928,
27+
"viewers": null,
28+
"id": null,
29+
"platform": "rumble",
30+
"type": null
31+
},
32+
"kick": {
33+
"live": true,
34+
"game": null,
35+
"preview": null,
36+
"status_text": "Okay I lied, second short stream today, leaving @ 6 PM | Random videos/articles/memes",
37+
"started_at": "2023-04-13T16:20:41+0000",
38+
"ended_at": null,
39+
"duration": 16652,
40+
"viewers": 11835,
41+
"id": "https://fa723fc1b171.us-west-2.playback.live-video.net/api/video/v1/us-west-2.196233775518.channel.0PMYoN0I2p4i.m3u8",
42+
"platform": "kick",
43+
"type": null
44+
}
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)