UNPKG

tiktok-live-connector

Version:

Node.js library to receive live stream chat events like comments and gifts from TikTok LIVE.

224 lines 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getPreferredPictureFormat = exports.mapBadges = exports.getTopViewerAttributes = exports.getEventAttributes = exports.simplifyObject = void 0; /** * This ugly function brings the nested protobuf objects to a flat level * In addition, attributes in "Long" format are converted to strings (e.g. UserIds) * This makes it easier to handle the data later, since some libraries have problems to serialize this protobuf specific data. */ function simplifyObject(type, originalObject) { // Utility function for modifying types easily const simplify = (fn) => fn(originalObject); if (originalObject.user) { originalObject = simplify((webcastObject) => { Object.assign(webcastObject, getUserAttributes(webcastObject.user)); delete webcastObject.user; return webcastObject; }); } if (originalObject.common) { originalObject = simplify((webcastObject) => { Object.assign(webcastObject, webcastObject.common.displayText); delete webcastObject.common.displayText; Object.assign(webcastObject, webcastObject.common); delete webcastObject.common; return webcastObject; }); } switch (type) { case 'WebcastQuestionNewMessage': { originalObject = simplify((webcastObject) => { Object.assign(webcastObject, webcastObject.details); delete webcastObject.details; return webcastObject; }); break; } case 'WebcastRoomUserSeqMessage': { originalObject = simplify((webcastObject) => { webcastObject.topViewers = getTopViewerAttributes(webcastObject.ranksList); delete webcastObject.ranksList; return webcastObject; }); break; } case 'WebcastLinkMicBattle': { originalObject = simplify((webcastObject) => { const battleUsers = []; Object.values(webcastObject.anchorInfo).forEach((anchor) => { if (anchor.user) { battleUsers.push(getUserAttributes(anchor.user)); } }); webcastObject.battleUsers = battleUsers; return webcastObject; }); break; } case 'WebcastGiftMessage': { originalObject = simplify((webcastObject) => { webcastObject.repeatEnd = !!webcastObject.repeatEnd; // Add previously used JSON structure (for compatibility reasons) // Can be removed soon <-- Will it ever be? webcastObject.gift = { gift_id: webcastObject.giftId, repeat_count: webcastObject.repeatCount, repeat_end: webcastObject.repeatEnd ? 1 : 0, gift_type: webcastObject.giftDetails?.giftType }; if (webcastObject.giftDetails) { Object.assign(webcastObject, webcastObject.giftDetails); delete webcastObject.giftDetails; } if (webcastObject.giftDetails.giftImage) { Object.assign(webcastObject, webcastObject.giftDetails.giftImage); delete webcastObject.giftDetails.giftImage; } if (webcastObject.giftExtra) { if (webcastObject.giftExtra.toUserId) { webcastObject.receiverUserId = webcastObject.giftExtra.toUserId; delete webcastObject.giftExtra.toUserId; } if (webcastObject.giftExtra.sendGiftSendMessageSuccessMs) { webcastObject.timestamp = parseInt(webcastObject.giftExtra.sendGiftSendMessageSuccessMs); delete webcastObject.giftExtra.sendGiftSendMessageSuccessMs; } Object.assign(webcastObject, webcastObject.giftExtra); delete webcastObject.giftExtra; } if (webcastObject.monitorExtra?.indexOf('{') === 0) { try { webcastObject.monitorExtra = JSON.parse(webcastObject.monitorExtra); } catch (err) { } } return webcastObject; }); break; } case 'WebcastChatMessage': { originalObject = simplify((webcastObject) => { webcastObject.emotes = webcastObject.emotes.map((emote) => ({ emoteId: emote.emote.emoteId, emoteImageUrl: emote.emote.image.imageUrl, placeInComment: emote.placeInComment })); return webcastObject; }); break; } case 'WebcastEmoteChatMessage': { originalObject = simplify((webcastObject) => { webcastObject.emotes = webcastObject.emoteList.map((emote) => ({ emoteId: emote.emoteId, emoteImageUrl: emote.image.url[0] })); return webcastObject; }); break; } } return originalObject; } exports.simplifyObject = simplifyObject; function getUserAttributes(webcastUser) { webcastUser ||= {}; const userAttributes = { userId: webcastUser.userId?.toString(), secUid: webcastUser.secUid?.toString(), uniqueId: webcastUser.uniqueId !== '' ? webcastUser.uniqueId : undefined, nickname: webcastUser.nickname !== '' ? webcastUser.nickname : undefined, profilePictureUrl: getPreferredPictureFormat(webcastUser.profilePicture?.url), followRole: webcastUser.followInfo?.followStatus, userBadges: mapBadges(webcastUser.badges), userSceneTypes: webcastUser.badges?.map((x) => x?.badgeScene || 0), userDetails: { createTime: webcastUser.createTime?.toString(), bioDescription: webcastUser.bioDescription, profilePictureUrls: webcastUser.profilePicture?.url } }; if (webcastUser.followInfo) { userAttributes.followInfo = { followingCount: webcastUser.followInfo.followingCount, followerCount: webcastUser.followInfo.followerCount, followStatus: webcastUser.followInfo.followStatus, pushStatus: webcastUser.followInfo.pushStatus }; } userAttributes.isModerator = userAttributes.userBadges.some((x) => (x.type && x.type.toLowerCase().includes('moderator')) || x.badgeSceneType === 1); userAttributes.isNewGifter = userAttributes.userBadges.some((x) => x.type && x.type.toLowerCase().includes('live_ng_')); userAttributes.isSubscriber = userAttributes.userBadges.some((x) => (x.url && x.url.toLowerCase().includes('/sub_')) || x.badgeSceneType === 4 || x.badgeSceneType === 7); userAttributes.topGifterRank = userAttributes.userBadges .find((x) => x.url && x.url.includes('/ranklist_top_gifter_')) ?.url.match(/(?<=ranklist_top_gifter_)(\d+)(?=.png)/g) ?.map(Number)[0] ?? null; userAttributes.gifterLevel = userAttributes.userBadges.find((x) => x.badgeSceneType === 8)?.level || 0; // BadgeSceneType_UserGrade userAttributes.teamMemberLevel = userAttributes.userBadges.find((x) => x.badgeSceneType === 10)?.level || 0; // BadgeSceneType_Fans return userAttributes; } function getEventAttributes(event) { if (event.msgId) event.msgId = event.msgId.toString(); if (event.createTime) event.createTime = event.createTime.toString(); return event; } exports.getEventAttributes = getEventAttributes; function getTopViewerAttributes(topViewers) { return topViewers.map((viewer) => { return { user: viewer.user ? getUserAttributes(viewer.user) : null, coinCount: viewer.coinCount ? parseInt(viewer.coinCount) : 0 }; }); } exports.getTopViewerAttributes = getTopViewerAttributes; function mapBadges(badges) { let simplifiedBadges = []; if (Array.isArray(badges)) { badges.forEach((innerBadges) => { let badgeSceneType = innerBadges.badgeSceneType; if (Array.isArray(innerBadges.badges)) { innerBadges.badges.forEach((badge) => { simplifiedBadges.push(Object.assign({ badgeSceneType }, badge)); }); } if (Array.isArray(innerBadges.imageBadges)) { innerBadges.imageBadges.forEach((badge) => { if (badge && badge.image && badge.image.url) { simplifiedBadges.push({ type: 'image', badgeSceneType, displayType: badge.displayType, url: badge.image.url }); } }); } if (innerBadges.privilegeLogExtra?.level && innerBadges.privilegeLogExtra?.level !== '0') { simplifiedBadges.push({ type: 'privilege', privilegeId: innerBadges.privilegeLogExtra.privilegeId, level: parseInt(innerBadges.privilegeLogExtra.level), badgeSceneType: innerBadges.badgeSceneType }); } }); } return simplifiedBadges; } exports.mapBadges = mapBadges; function getPreferredPictureFormat(pictureUrls) { if (!pictureUrls || !Array.isArray(pictureUrls) || !pictureUrls.length) { return null; } return (pictureUrls.find((x) => x.includes('100x100') && x.includes('.webp')) || pictureUrls.find((x) => x.includes('100x100') && x.includes('.jpeg')) || pictureUrls.find((x) => !x.includes('shrink')) || pictureUrls[0]); } exports.getPreferredPictureFormat = getPreferredPictureFormat; //# sourceMappingURL=data-converter.js.map