Skip to content

Commit 29afd38

Browse files
authored
Merge pull request #853 from steveseguin/beta
Beta
2 parents 5f141f8 + 58e5ec3 commit 29afd38

4 files changed

Lines changed: 83 additions & 10 deletions

File tree

docs/event-reference.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1096,7 +1096,7 @@ <h3>VPZone - WebSocket</h3>
10961096
<tr>
10971097
<td><code>message</code></td>
10981098
<td>VPZone <code>msg</code>, <code>message</code>, <code>new_message</code>, or <code>chat_message</code> websocket frame.</td>
1099-
<td><code>chatname</code> comes from <code>username</code>; <code>chatmessage</code> comes from <code>body</code>; subscriber/owner flags are copied into <code>chatbadges</code> and <code>meta</code>.</td>
1099+
<td><code>chatname</code> comes from <code>username</code>; <code>chatmessage</code> comes from <code>body</code>; subscriber/owner/mod/VIP flags are copied into <code>chatbadges</code>, top-level role flags, and <code>meta</code>. Native IDs populate <code>data.id</code> and <code>meta.messageId</code>.</td>
11001100
</tr>
11011101
<tr>
11021102
<td class="status-event"><code>viewer_update</code></td>
@@ -1108,6 +1108,11 @@ <h3>VPZone - WebSocket</h3>
11081108
<td>VPZone <code>subscribe</code> / <code>subscription</code> frame.</td>
11091109
<td><code>membership</code> is set to Subscriber when subscription flags are present.</td>
11101110
</tr>
1111+
<tr>
1112+
<td class="membership-event"><code>subscription_gift</code></td>
1113+
<td>VPZone <code>gift</code> / <code>gift_subscription</code> frame.</td>
1114+
<td>Uses the same gifted-sub event name as Twitch, Kick, Rumble, and Velora.</td>
1115+
</tr>
11111116
<tr>
11121117
<td class="status-event"><code>new_follower</code></td>
11131118
<td>VPZone <code>follow</code> frame.</td>

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "Social Stream Ninja",
33
"description": "Capture live chat from 100+ supported sites and consolidate it into a single dashboard for live production workflows",
44
"manifest_version": 3,
5-
"version": "3.49.6",
5+
"version": "3.50.0",
66
"homepage_url": "http://socialstream.ninja/",
77
"browser_specific_settings": {
88
"gecko": {

sources/websocket/vpzone.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,6 @@ <h2>Diagnostics</h2>
469469
</section>
470470
</section>
471471
</div>
472-
<script src="vpzone.js?v=20260615g"></script>
472+
<script src="vpzone.js?v=20260615h"></script>
473473
</body>
474474
</html>

sources/websocket/vpzone.js

Lines changed: 75 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
(function () {
22
const HOST = "https://vpzone.tv";
33
const SOURCE_NAME = "VPZone";
4-
const SOURCE_IMG = HOST + "/favicon.ico";
4+
const SOURCE_IMG = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iMTQiIGZpbGw9IiMxMTE4MjciLz48cGF0aCBkPSJNMTQgMThoMTBsOCAyNCA4LTI0aDEwTDM3IDUwSDI3TDE0IDE4eiIgZmlsbD0iIzEyYzdjMiIvPjxjaXJjbGUgY3g9IjQ4IiBjeT0iMTYiIHI9IjYiIGZpbGw9IiM3YzVjZmYiLz48L3N2Zz4=";
55
const CONFIG_KEY = "vpzoneWsConfig";
66
const TOKEN_KEY = "vpzoneWsTokens";
77
const OAUTH_KEY = "vpzoneOAuthState";
@@ -975,14 +975,58 @@
975975
return ev && (ev.createdAt || ev.timestamp || ev.sentAt || ev.ts) ? (ev.createdAt || ev.timestamp || ev.sentAt || ev.ts) : "";
976976
}
977977

978+
function flagValue(value) {
979+
var text;
980+
if (value === true || value === 1) return true;
981+
if (value === false || value === 0 || value == null) return false;
982+
text = String(value).toLowerCase();
983+
return text === "true" || text === "1" || text === "yes";
984+
}
985+
986+
function eventValue(ev, keys) {
987+
var meta = ev && ev.metadata && typeof ev.metadata === "object" ? ev.metadata : {};
988+
var i;
989+
if (!ev) return "";
990+
for (i = 0; i < keys.length; i += 1) {
991+
if (ev[keys[i]] != null && ev[keys[i]] !== "") return ev[keys[i]];
992+
if (meta[keys[i]] != null && meta[keys[i]] !== "") return meta[keys[i]];
993+
}
994+
return "";
995+
}
996+
997+
function eventFlag(ev, keys) {
998+
var meta = ev && ev.metadata && typeof ev.metadata === "object" ? ev.metadata : {};
999+
var roles = [];
1000+
var i;
1001+
var j;
1002+
for (i = 0; i < keys.length; i += 1) {
1003+
if (flagValue(ev && ev[keys[i]])) return true;
1004+
if (flagValue(meta && meta[keys[i]])) return true;
1005+
}
1006+
if (Array.isArray(ev && ev.roles)) roles = roles.concat(ev.roles);
1007+
if (Array.isArray(meta.roles)) roles = roles.concat(meta.roles);
1008+
for (j = 0; j < roles.length; j += 1) {
1009+
var role = String(roles[j] || "").toLowerCase();
1010+
for (i = 0; i < keys.length; i += 1) {
1011+
if (role === String(keys[i]).toLowerCase().replace(/^is_?/, "")) return true;
1012+
}
1013+
}
1014+
return false;
1015+
}
1016+
1017+
function eventMessageId(ev) {
1018+
var value = eventValue(ev, ["messageId", "message_id", "chatMessageId", "chat_message_id", "id"]);
1019+
return value != null && value !== "" ? String(value) : "";
1020+
}
1021+
9781022
function mapEventName(value) {
9791023
value = String(value || "").toLowerCase();
9801024
if (value === "msg" || value === "message" || value === "new_message" || value === "chat") return "chat_message";
9811025
if (value === "viewer_join") return "joined";
9821026
if (value === "viewer_quit") return "left";
9831027
if (value === "follow") return "new_follower";
9841028
if (value === "subscribe" || value === "subscription") return "new_subscriber";
985-
if (value === "gift") return "gift_subscription";
1029+
if (value === "gift" || value === "gift_subscription" || value === "gifted_subscription" || value === "subscription_gift" || value === "subgift") return "subscription_gift";
9861030
if (value === "raid") return "raid";
9871031
if (value === "clip") return "clip";
9881032
if (value === "level_up") return "level_up";
@@ -1001,47 +1045,71 @@
10011045
if (Array.isArray(ev.chatbadges)) badges = badges.concat(ev.chatbadges);
10021046
if (Array.isArray(ev.badges)) badges = badges.concat(ev.badges);
10031047
if (ev.is_owner || ev.isOwner) badges.push(svgBadge("OP", "#c071f5", 20));
1004-
if (ev.is_subscriber || ev.isSubscriber) badges.push(svgBadge(subLabel, ev.tier === "tier3" ? "#00E9E2" : (ev.tier === "tier2" ? "#FF6DE4" : "#f9376b")));
1048+
if (eventFlag(ev, ["is_moderator", "isModerator", "moderator", "mod"])) badges.push(svgBadge("MOD", "#00a7ff", 28));
1049+
if (eventFlag(ev, ["is_vip", "isVip", "vip"])) badges.push(svgBadge("VIP", "#ff68b3", 24));
1050+
if (eventFlag(ev, ["is_subscriber", "isSubscriber", "subscriber", "member"])) badges.push(svgBadge(subLabel, ev.tier === "tier3" ? "#00E9E2" : (ev.tier === "tier2" ? "#FF6DE4" : "#f9376b")));
10051051
if (ev.metadata && ev.metadata.source === "twitch") badges.push(svgBadge("TW", "#9146FF", 20));
10061052
return badges;
10071053
}
10081054

10091055
function buildChat(ev) {
10101056
var rawName = ev.actorDisplayName || ev.displayName || ev.actorUsername || ev.username || "";
1057+
var messageId = eventMessageId(ev);
1058+
var isSubscriber = eventFlag(ev, ["is_subscriber", "isSubscriber", "subscriber", "member"]);
1059+
var isModerator = eventFlag(ev, ["is_moderator", "isModerator", "moderator", "mod"]);
1060+
var isVip = eventFlag(ev, ["is_vip", "isVip", "vip"]);
1061+
var isOwner = eventFlag(ev, ["is_owner", "isOwner", "owner", "broadcaster"]);
10111062
if (!rawName || String(rawName).toLowerCase() === "system") return null;
10121063
var data = basePayload();
1064+
if (messageId) data.id = messageId;
10131065
data.chatname = esc(rawName);
1066+
data.username = ev.actorUsername || ev.username || "";
10141067
data.chatmessage = renderMessage(ev.message || ev.text || ev.body || ev.content || "");
10151068
data.chatimg = absUrl(ev.actorAvatarUrl || ev.avatarUrl || ev.actorAvatar || ev.avatar_url || ev.profileImage || "");
10161069
data.contentimg = absUrl(ev.contentimg || ev.contentImage || ev.imageUrl || "");
10171070
data.chatbadges = buildBadges(ev);
1018-
data.membership = ev.metadata && ev.metadata.actorRank ? nice(ev.metadata.actorRank) : ((ev.is_subscriber || ev.isSubscriber) ? "Subscriber" : "");
1071+
data.membership = ev.metadata && ev.metadata.actorRank ? nice(ev.metadata.actorRank) : (isSubscriber ? "Subscriber" : "");
10191072
data.nameColor = ev.actorNameColor || ev.nameColor || ev.color || "#c084fc";
10201073
data.userid = ev.actorUserId != null ? String(ev.actorUserId) : (ev.userId != null ? String(ev.userId) : (ev.actorUsername || ev.username || ""));
1074+
if (isModerator) data.mod = true;
1075+
if (isVip) data.vip = true;
1076+
if (isSubscriber) data.member = true;
10211077
data.timestamp = eventTime(ev);
1022-
data.meta = { id: ev.id != null ? ev.id : null, streamUsername: ev.streamUsername || state.currentChannel || state.cfg.channel, createdAt: eventTime(ev), actorUsername: ev.actorUsername || ev.username || "", actorRank: ev.metadata && ev.metadata.actorRank ? ev.metadata.actorRank : "", rawEventType: ev.eventType || ev.type || "chat_message", transport: "websocket", isSubscriber: !!(ev.is_subscriber || ev.isSubscriber), subMonths: Number(ev.sub_months || ev.subMonths || 0), isOwner: !!(ev.is_owner || ev.isOwner) };
1078+
data.meta = { streamUsername: ev.streamUsername || state.currentChannel || state.cfg.channel, createdAt: eventTime(ev), actorUsername: ev.actorUsername || ev.username || "", actorRank: ev.metadata && ev.metadata.actorRank ? ev.metadata.actorRank : "", rawEventType: ev.eventType || ev.type || "chat_message", transport: "websocket", isSubscriber: isSubscriber, subMonths: Number(ev.sub_months || ev.subMonths || 0), isOwner: isOwner, isModerator: isModerator, isVip: isVip };
1079+
if (messageId) data.meta.messageId = messageId;
10231080
return data.chatname && data.chatmessage ? data : null;
10241081
}
10251082

10261083
function buildEvent(ev) {
10271084
var mapped = mapEventName(ev.eventType || ev.type || "");
10281085
var data;
1086+
var messageId = eventMessageId(ev);
1087+
var isSubscriber = eventFlag(ev, ["is_subscriber", "isSubscriber", "subscriber", "member"]);
1088+
var isModerator = eventFlag(ev, ["is_moderator", "isModerator", "moderator", "mod"]);
1089+
var isVip = eventFlag(ev, ["is_vip", "isVip", "vip"]);
1090+
var isOwner = eventFlag(ev, ["is_owner", "isOwner", "owner", "broadcaster"]);
10291091
if (!mapped || mapped === "presence" || mapped === "chat_message") return null;
10301092
if (state.settings.hideevents) return null;
10311093
if (mapped === "joined" && state.settings.capturejoinedevent === false) return null;
10321094
var rawName = ev.actorDisplayName || ev.displayName || ev.actorUsername || ev.username || "";
10331095
if (!rawName || String(rawName).toLowerCase() === "system") return null;
10341096
data = basePayload();
1097+
if (messageId) data.id = messageId;
10351098
data.event = mapped;
10361099
data.chatname = esc(rawName);
1100+
data.username = ev.actorUsername || ev.username || "";
10371101
data.chatmessage = renderMessage(ev.body || ev.message || ev.text || mapped);
10381102
data.chatimg = absUrl(ev.actorAvatarUrl || ev.avatarUrl || ev.actorAvatar || ev.avatar_url || ev.profileImage || "");
10391103
data.chatbadges = buildBadges(ev);
1040-
data.membership = ev.metadata && ev.metadata.actorRank ? nice(ev.metadata.actorRank) : ((ev.is_subscriber || ev.isSubscriber) ? "Subscriber" : "");
1104+
data.membership = ev.metadata && ev.metadata.actorRank ? nice(ev.metadata.actorRank) : (isSubscriber ? "Subscriber" : "");
10411105
data.nameColor = ev.actorNameColor || ev.nameColor || ev.color || "#c084fc";
10421106
data.userid = ev.actorUserId != null ? String(ev.actorUserId) : (ev.userId != null ? String(ev.userId) : (ev.actorUsername || ev.username || ""));
1107+
if (isModerator) data.mod = true;
1108+
if (isVip) data.vip = true;
1109+
if (isSubscriber) data.member = true;
10431110
data.timestamp = eventTime(ev);
1044-
data.meta = { id: ev.id != null ? ev.id : null, streamUsername: ev.streamUsername || state.currentChannel || state.cfg.channel, createdAt: eventTime(ev), actorUsername: ev.actorUsername || ev.username || "", actorRank: ev.metadata && ev.metadata.actorRank ? ev.metadata.actorRank : "", rawEventType: ev.eventType || ev.type || "", transport: "websocket" };
1111+
data.meta = { streamUsername: ev.streamUsername || state.currentChannel || state.cfg.channel, createdAt: eventTime(ev), actorUsername: ev.actorUsername || ev.username || "", actorRank: ev.metadata && ev.metadata.actorRank ? ev.metadata.actorRank : "", rawEventType: ev.eventType || ev.type || "", transport: "websocket", isSubscriber: isSubscriber, isOwner: isOwner, isModerator: isModerator, isVip: isVip };
1112+
if (messageId) data.meta.messageId = messageId;
10451113
if (mapped === "new_follower") data.meta.followedOn = eventTime(ev);
10461114
if (mapped === "new_subscriber") data.meta.subscribedOn = eventTime(ev);
10471115
return data.chatname ? data : null;

0 commit comments

Comments
 (0)