Skip to content

Commit b20306d

Browse files
committed
Twitch Watch Streak Event Added
1 parent ff77adc commit b20306d

File tree

7 files changed

+175
-36
lines changed

7 files changed

+175
-36
lines changed

chat.html

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/simple-notify.min.css">
1414
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/animate.min.css">
1515

16-
<link rel="stylesheet" href="css/chatrd.css?nocache=13">
16+
<link rel="stylesheet" href="css/chatrd.css?nocache=14">
1717
</head>
1818
<body>
1919

@@ -99,38 +99,38 @@
9999
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/purify.min.js"></script>
100100
<script src="https://cdn.jsdelivr.net/npm/@streamerbot/[email protected]/dist/streamerbot-client.min.js"></script>
101101

102-
<script src="js/speakerbot.js?nocache=13"></script>
103-
<script src="js/sb.js?nocache=13"></script>
104-
<script src="js/chatrd.js?nocache=13"></script>
102+
<script src="js/speakerbot.js?nocache=14"></script>
103+
<script src="js/sb.js?nocache=14"></script>
104+
<script src="js/chatrd.js?nocache=14"></script>
105105

106-
<link href="js/modules/twitch/module.css?nocache=13" rel="stylesheet">
107-
<script src="js/modules/twitch/module.js?nocache=13"></script>
106+
<link href="js/modules/twitch/module.css?nocache=14" rel="stylesheet">
107+
<script src="js/modules/twitch/module.js?nocache=14"></script>
108108

109-
<link href="js/modules/youtube/module.css?nocache=13" rel="stylesheet">
110-
<script src="js/modules/youtube/module.js?nocache=13"></script>
109+
<link href="js/modules/youtube/module.css?nocache=14" rel="stylesheet">
110+
<script src="js/modules/youtube/module.js?nocache=14"></script>
111111

112-
<link href="js/modules/tiktok/module.css?nocache=13" rel="stylesheet">
113-
<script src="js/modules/tiktok/module.js?nocache=13"></script>
112+
<link href="js/modules/tiktok/module.css?nocache=14" rel="stylesheet">
113+
<script src="js/modules/tiktok/module.js?nocache=14"></script>
114114

115-
<link href="js/modules/kick/module.css?nocache=13" rel="stylesheet">
116-
<script src="js/modules/kick/module.js?nocache=13"></script>
115+
<link href="js/modules/kick/module.css?nocache=14" rel="stylesheet">
116+
<script src="js/modules/kick/module.js?nocache=14"></script>
117117

118-
<link href="js/modules/streamelements/module.css?nocache=13" rel="stylesheet">
119-
<script src="js/modules/streamelements/module.js?nocache=13"></script>
118+
<link href="js/modules/streamelements/module.css?nocache=14" rel="stylesheet">
119+
<script src="js/modules/streamelements/module.js?nocache=14"></script>
120120

121-
<link href="js/modules/streamlabs/module.css?nocache=13" rel="stylesheet">
122-
<script src="js/modules/streamlabs/module.js?nocache=13"></script>
121+
<link href="js/modules/streamlabs/module.css?nocache=14" rel="stylesheet">
122+
<script src="js/modules/streamlabs/module.js?nocache=14"></script>
123123

124-
<link href="js/modules/patreon/module.css?nocache=13" rel="stylesheet">
125-
<script src="js/modules/patreon/module.js?nocache=13"></script>
124+
<link href="js/modules/patreon/module.css?nocache=14" rel="stylesheet">
125+
<script src="js/modules/patreon/module.js?nocache=14"></script>
126126

127-
<link href="js/modules/tipeeestream/module.css?nocache=13" rel="stylesheet">
128-
<script src="js/modules/tipeeestream/module.js?nocache=13"></script>
127+
<link href="js/modules/tipeeestream/module.css?nocache=14" rel="stylesheet">
128+
<script src="js/modules/tipeeestream/module.js?nocache=14"></script>
129129

130-
<link href="js/modules/kofi/module.css?nocache=13" rel="stylesheet">
131-
<script src="js/modules/kofi/module.js?nocache=13"></script>
130+
<link href="js/modules/kofi/module.css?nocache=14" rel="stylesheet">
131+
<script src="js/modules/kofi/module.js?nocache=14"></script>
132132

133-
<link href="js/modules/fourthwall/module.css?nocache=13" rel="stylesheet">
134-
<script src="js/modules/fourthwall/module.js?nocache=13"></script>
133+
<link href="js/modules/fourthwall/module.css?nocache=14" rel="stylesheet">
134+
<script src="js/modules/fourthwall/module.js?nocache=14"></script>
135135
</body>
136136
</html>

css/chatrd.css

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ body {
8181
transition: all ease-in-out 300ms;
8282
}
8383

84+
#chat:not(.oneline):not(.horizontal) .item.chat.grouped .message {
85+
padding: 2px 5px 3px 5px;
86+
}
87+
8488
#chat .item .message .actual-message a {
8589
color: #FFF;
8690
font-weight: bold;
@@ -319,6 +323,10 @@ body {
319323
padding: 5px 10px;
320324
}
321325

326+
#chat.horizontal .item.chat.grouped .message {
327+
padding: 0px 5px 7px 5px;
328+
}
329+
322330
#chat.horizontal .item .actual-message img {
323331
height: 22px;
324332
margin: 0 1px;
@@ -480,10 +488,6 @@ body {
480488
margin: 0 0 -5px 0;
481489
}
482490

483-
#chat.oneline .event .info {
484-
display: inline-block;
485-
}
486-
487491
#chat.oneline .event .info .user,
488492
#chat.oneline .event .info .action,
489493
#chat.oneline .event .info .value {

index.html

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,6 @@ <h2><i class="fa-solid fa-wrench"></i> Setup</h2>
195195
</label>
196196
<label class="switch"><input type="checkbox" name="chatOneLine"><span class="slider"></span></label>
197197
</div>
198-
199198

200199
<div class="config">
201200
<label>
@@ -204,6 +203,13 @@ <h2><i class="fa-solid fa-wrench"></i> Setup</h2>
204203
</label>
205204
<label class="switch"><input type="checkbox" name="chatHorizontal"><span class="slider"></span></label>
206205
</div>
206+
207+
<div class="config">
208+
<label>
209+
Group Chat Messages<br><small>Consecutive messages from the same user will be grouped.</small>
210+
</label>
211+
<label class="switch"><input type="checkbox" name="chatMessageGroup"><span class="slider"></span></label>
212+
</div>
207213

208214
<div class="config">
209215
<label>Platforms<br><small>Shows the platforms logos.</small></label>
@@ -308,15 +314,19 @@ <h2><img src="js/modules/twitch/images/logo-twitch.svg">Twitch</h2>
308314
<div class="config">
309315
<label>Bits</label><label class="switch">
310316
<input type="checkbox" name="showTwitchBits" checked><span class="slider"></span></label>
311-
</div>
317+
</div>
312318
<div class="config">
313319
<label>Announcements</label>
314320
<label class="switch"><input type="checkbox" name="showTwitchAnnouncements" checked><span class="slider"></span></label>
315321
</div>
322+
<div class="config">
323+
<label>Watch Streaks<br><small>Shows Watch Streaks in chat.</small></label>
324+
<label class="switch"><input type="checkbox" name="showTwitchWatchStreak"><span class="slider"></span></label>
325+
</div>
316326
<div class="config">
317327
<label>Subscriptions<br><small>Shows Sub events. <u><strong>Disabling this disables all sub events</strong></u>.</small></label>
318328
<label class="switch"><input type="checkbox" name="showTwitchSubs" checked><span class="slider"></span></label>
319-
</div>
329+
</div>
320330
<div class="config">
321331
<label><i class="fa-solid fa-arrow-turn-up"></i> Gifted Subs<br><small>When a user gifts another user a sub.</small></label>
322332
<label class="switch"><input type="checkbox" name="showTwitchGiftedSubs" checked><span class="slider"></span></label>

js/chatrd.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const showPlatformStatistics = getURLParam("showPlatformStatistics", true
1313
const chatThreshold = 50;
1414
const chatOneLine = getURLParam("chatOneLine", false);
1515
const chatHorizontal = getURLParam("chatHorizontal", false);
16+
const chatMessageGroup = getURLParam("chatMessageGroup", false);
1617
const chatFontSize = getURLParam("chatFontSize", 1);
1718
const chatFontFamily = getURLParam("chatFontFamily", "DM Sans");
1819
const chatBackground = getURLParam("chatBackground", "#121212");
@@ -87,6 +88,7 @@ function addMessageItem(platform, clone, classes, userid, messageid) {
8788
root.style.opacity = '0';
8889

8990
const messageEl = clone.querySelector('.actual-message');
91+
const infoEl = clone.querySelector('.info');
9092
getAndReplaceLinks(messageEl);
9193

9294
const platformElement = clone.querySelector('.platform');
@@ -137,6 +139,14 @@ function addMessageItem(platform, clone, classes, userid, messageid) {
137139
}
138140
}
139141

142+
if (chatMessageGroup == true && chatContainer.children.length > 0) {
143+
let lastUserId = chatContainer.firstElementChild.dataset.user;
144+
if (lastUserId == userid) {
145+
infoEl.remove();
146+
root.classList.add('grouped');
147+
}
148+
}
149+
140150
chatContainer.prepend(clone);
141151

142152
const item = document.getElementById(messageid);

js/modules/tiktok/module.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@
2121
}
2222

2323

24+
25+
#chat.oneline .event.tiktok.gift .info {
26+
display: inline-flex !important;
27+
}
28+
2429
#chat .event.tiktok.gift .value img { vertical-align: sub; }
2530

2631
#chat.horizontal .item.tiktok .info .badges {
@@ -54,6 +59,16 @@
5459
border-radius: 3px;
5560
}
5661

62+
#chat .item.tiktok span.badge.sceneTen.inactive-fan {
63+
filter: saturate(0%);
64+
}
65+
66+
#chat.oneline .item.tiktok span.badge.top-gifter,
67+
#chat.oneline .item.tiktok span.badge.sceneEight,
68+
#chat.oneline .item.tiktok span.badge.sceneTen {
69+
transform: translateY(-3px);
70+
}
71+
5772
#chat .item.tiktok span.badge.top-gifter img,
5873
#chat .item.tiktok span.badge.sceneEight img,
5974
#chat .item.tiktok span.badge.sceneTen img {

js/modules/tiktok/module.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,7 @@ async function tiktokShareMessage(data) {
299299

300300

301301
async function tiktokJoinMessage(data) {
302+
302303
if (showTikTokJoins == false) return;
303304

304305
function onIdle() {
@@ -637,10 +638,15 @@ async function getTikTokBadges(data) {
637638

638639
// Scene Ten - Fan Badges
639640
if (badge.badgeSceneType === 10) {
641+
642+
let badgeClasses = ['badge', 'sceneTen'];
643+
//if (badge.privilegeId == "7196929090442513157") { badgeClasses.push('inactive-fan'); }
644+
badgeClasses = badgeClasses.join(" ");
645+
640646
const match = badgesLevelTen.find(lv => badge.level >= lv.min && badge.level <= lv.max);
641647
if (match) {
642648
badgesHTML.push(
643-
`<span class="badge sceneTen">
649+
`<span class="${badgeClasses}">
644650
<img src="${match.url}" alt="Level ${badge.level}">
645651
</span>`
646652
);
@@ -669,7 +675,4 @@ async function tiktokUpdateStatistics(data, type) {
669675
document.querySelector('#statistics #tiktok .likes span').textContent = likes;
670676
}
671677

672-
}
673-
674-
675-
678+
}

js/modules/twitch/module.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const showTwitch = getURLParam("showTwitch", false);
66

77
const showTwitchMessages = getURLParam("showTwitchMessages", true);
88
const showTwitchFollows = getURLParam("showTwitchFollows", true);
9+
const showTwitchWatchStreak = getURLParam("showTwitchWatchStreak", false);
910
const showTwitchBits = getURLParam("showTwitchBits", true);
1011
const showTwitchAnnouncements = getURLParam("showTwitchAnnouncements", true);
1112
const showTwitchSubs = getURLParam("showTwitchSubs", true);
@@ -47,6 +48,9 @@ const twitchMessageHandlers = {
4748
'Twitch.ChatMessage': (response) => {
4849
twitchChatMessage(response.data);
4950
},
51+
'Twitch.WatchStreak': (response) => {
52+
twitchWatchStreakMessage(response.data);
53+
},
5054
'Twitch.Follow': (response) => {
5155
twitchFollowMessage(response.data);
5256
},
@@ -256,6 +260,44 @@ async function twitchChatMessage(data) {
256260

257261

258262

263+
264+
async function twitchWatchStreakMessage(data) {
265+
266+
if (showTwitchWatchStreak == false) return;
267+
268+
const template = eventTemplate;
269+
const clone = template.content.cloneNode(true);
270+
const messageId = data.msgId;
271+
const userId = data.userName.toLowerCase();
272+
273+
const {
274+
header,
275+
platform,
276+
user,
277+
action,
278+
value,
279+
'actual-message': message
280+
} = Object.fromEntries(
281+
[...clone.querySelectorAll('[class]')]
282+
.map(el => [el.className, el])
283+
);
284+
285+
const classes = ['twitch', 'watch-streak'];
286+
287+
header.remove();
288+
289+
user.textContent = data.displayName;
290+
291+
action.innerHTML = ` watched `;
292+
value.innerHTML = `<strong>${data.watchStreak} consecutive streams</strong> this month`;
293+
message.textContent = data.message;
294+
await getTwitchEmotesForWatchedStreakMessage(data, message);
295+
296+
addEventItem('twitch', clone, classes, userId, messageId);
297+
}
298+
299+
300+
259301
async function twitchChatMessageGiantEmote(data) {
260302

261303
if (showTwitchMessages == false) return;
@@ -899,6 +941,61 @@ async function getTwitchEmotes(data, messageElement) {
899941

900942

901943

944+
async function getTwitchEmotesForWatchedStreakMessage(data, messageElement) {
945+
const message = data.message;
946+
const emotes = (data.emotes || []).sort((a, b) => a.startIndex - b.startIndex);
947+
948+
// Limpa o conteúdo (vamos recriar com nodes)
949+
messageElement.innerHTML = "";
950+
951+
let lastIndex = 0;
952+
953+
for (const emote of emotes) {
954+
// texto antes do emote
955+
if (lastIndex < emote.startIndex) {
956+
const text = message.slice(lastIndex, emote.startIndex);
957+
messageElement.appendChild(document.createTextNode(text));
958+
}
959+
960+
let emoteUrl = emote.imageUrl;
961+
962+
// Detecta Twemoji
963+
const isTwemoji =
964+
String(emote.type || "").toLowerCase() === "twemoji" ||
965+
/(twemoji|jdecked)/i.test(emote.imageUrl || "");
966+
967+
if (isTwemoji) {
968+
const codePoints = Array.from(emote.name).map(c => c.codePointAt(0).toString(16));
969+
let fileName = codePoints.join("-");
970+
fileName = fileName.replace(/-fe0f/g, ""); // remove FE0F
971+
emoteUrl = `https://cdn.jsdelivr.net/gh/twitter/[email protected]/assets/72x72/${fileName}.png`;
972+
}
973+
974+
if (!emoteUrl || emoteUrl.trim() === "") {
975+
messageElement.appendChild(document.createTextNode(emote.name));
976+
}
977+
else {
978+
const img = document.createElement("img");
979+
img.src = emoteUrl;
980+
img.alt = emote.name;
981+
img.className = "emote";
982+
img.dataset.emoteId = emote.id || "";
983+
img.onerror = () => (img.outerHTML = emote.name);
984+
messageElement.appendChild(img);
985+
}
986+
987+
lastIndex = emote.endIndex + 1;
988+
}
989+
990+
// texto final depois do último emote
991+
if (lastIndex < message.length) {
992+
const text = message.slice(lastIndex);
993+
messageElement.appendChild(document.createTextNode(text));
994+
}
995+
}
996+
997+
998+
902999

9031000

9041001
async function getTwitchEmotesOnParts(data, messageElement) {

0 commit comments

Comments
 (0)