From ec0aa3ba438b10cc9e3a18bd99c8124b605ed951 Mon Sep 17 00:00:00 2001 From: "Reona Oshima(totoraj)" Date: Sat, 4 Jun 2022 00:40:36 +0900 Subject: [PATCH 1/3] add: membership gift --- src/parser.ts | 31 +++++++++++++++++++++++++++++ src/types/data.ts | 4 ++++ src/types/yt-response.ts | 42 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) diff --git a/src/parser.ts b/src/parser.ts index 628a35a..dd094b6 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -5,6 +5,7 @@ import { LiveChatMembershipItemRenderer, LiveChatPaidMessageRenderer, LiveChatPaidStickerRenderer, + LiveChatSponsorshipsHeaderRenderer, LiveChatTextMessageRenderer, MessageRun, Thumbnail, @@ -117,6 +118,13 @@ function parseMessages(runs: MessageRun[]): MessageItem[] { }) } +/** メンバーシップギフトを他のRendererに揃えるためのinterface */ +interface LiveChatMembershipGiftRenderer extends LiveChatSponsorshipsHeaderRenderer { + id: string + timestampUsec: string + authorExternalChannelId: string +} + /** actionの種類を判別してRendererを返す */ function rendererFromAction( action: Action @@ -125,6 +133,7 @@ function rendererFromAction( | LiveChatPaidMessageRenderer | LiveChatPaidStickerRenderer | LiveChatMembershipItemRenderer + | LiveChatMembershipGiftRenderer | null { if (!action.addChatItemAction) { return null @@ -138,6 +147,14 @@ function rendererFromAction( return item.liveChatPaidStickerRenderer } else if (item.liveChatMembershipItemRenderer) { return item.liveChatMembershipItemRenderer + } else if (item.liveChatSponsorshipsGiftPurchaseAnnouncementRenderer) { + const parentRenderer = item.liveChatSponsorshipsGiftPurchaseAnnouncementRenderer; + return { + id: parentRenderer.id, + timestampUsec: parentRenderer.timestampUsec, + authorExternalChannelId: parentRenderer.authorExternalChannelId, + ...parentRenderer.header.liveChatSponsorshipsHeaderRenderer + } } return null } @@ -209,6 +226,20 @@ function parseActionToChatItem(data: Action): ChatItem | null { amount: messageRenderer.purchaseAmountText.simpleText, color: convertColorToHex6(messageRenderer.bodyBackgroundColor), } + } else if ( + data.addChatItemAction?.item.liveChatSponsorshipsGiftPurchaseAnnouncementRenderer + && "primaryText" in messageRenderer + && messageRenderer.primaryText.runs + ) { + ret.membershipGift = { + message: parseMessages(messageRenderer.primaryText.runs), + } + if (messageRenderer.image?.thumbnails?.[0]) { + ret.membershipGift.image = { + ...messageRenderer.image.thumbnails[0], + alt: "" + } + } } return ret diff --git a/src/types/data.ts b/src/types/data.ts index b4c55f0..3dbee17 100644 --- a/src/types/data.ts +++ b/src/types/data.ts @@ -17,6 +17,10 @@ export interface ChatItem { color: string sticker?: ImageItem } + membershipGift?: { + message: MessageItem[] + image?: ImageItem + } isMembership: boolean isVerified: boolean isOwner: boolean diff --git a/src/types/yt-response.ts b/src/types/yt-response.ts index 609a3e9..4fbf2f7 100644 --- a/src/types/yt-response.ts +++ b/src/types/yt-response.ts @@ -157,12 +157,54 @@ export interface LiveChatMembershipItemRenderer extends MessageRendererBase { authorBadges: AuthorBadge[] } +export interface LiveChatSponsorshipsGiftPurchaseAnnouncementRenderer { + id: string + timestampUsec: string + authorExternalChannelId: string + header: { + liveChatSponsorshipsHeaderRenderer: LiveChatSponsorshipsHeaderRenderer + } +} + +export interface LiveChatSponsorshipsHeaderRenderer { + primaryText: { + runs: MessageRun[] + } + image?: { + thumbnails?: { url: string }[] + } + authorName?: { + simpleText: string + } + authorPhoto: { + thumbnails: Thumbnail[] + } + authorBadges?: AuthorBadge[] + contextMenuEndpoint: { + clickTrackingParams: string + commandMetadata: { + webCommandMetadata: { + ignoreNavigation: true + } + } + liveChatItemContextMenuEndpoint: { + params: string + } + } + contextMenuAccessibility: { + accessibilityData: { + label: string + } + } +} + export interface AddChatItemAction { item: { liveChatTextMessageRenderer?: LiveChatTextMessageRenderer liveChatPaidMessageRenderer?: LiveChatPaidMessageRenderer liveChatMembershipItemRenderer?: LiveChatMembershipItemRenderer liveChatPaidStickerRenderer?: LiveChatPaidStickerRenderer + liveChatSponsorshipsGiftPurchaseAnnouncementRenderer?: LiveChatSponsorshipsGiftPurchaseAnnouncementRenderer liveChatViewerEngagementMessageRenderer?: object } clientId: string From 906a2677901776ab7a0da1b3057aea6f6eb7805c Mon Sep 17 00:00:00 2001 From: "Reona Oshima(totoraj)" Date: Sat, 4 Jun 2022 00:40:54 +0900 Subject: [PATCH 2/3] add: membership gift test --- test/parser.test.ts | 36 ++++ .../get_live_chat.membership-gift.json | 168 ++++++++++++++++++ 2 files changed, 204 insertions(+) create mode 100644 test/testdata/get_live_chat.membership-gift.json diff --git a/test/parser.test.ts b/test/parser.test.ts index ded2ad0..c22e125 100644 --- a/test/parser.test.ts +++ b/test/parser.test.ts @@ -230,6 +230,42 @@ describe("Parser", () => { ]) }) + test("Membership Gift", () => { + const res = JSON.parse(readFileSync(__dirname + "/testdata/get_live_chat.membership-gift.json").toString()) + const [chatItems, continuation] = parseChatData(res) + expect(continuation).toBe("test-continuation:01") + expect(chatItems).toMatchObject([ + { + author: { + name: "authorName", + thumbnail: { + url: "https://author.thumbnail.url", + alt: "authorName", + }, + channelId: "channelId", + }, + message: [], + membershipGift: { + message: [ + { text: "10" }, + { text: " 件の " }, + { text: "上級エンジニア" }, + { text: " のメンバーシップ ギフトを贈りました" }, + ], + image: { + url: "https://www.gstatic.com/youtube/img/sponsorships/sponsorships_gift_purchase_announcement_artwork.png", + alt: "", + } + }, + isMembership: false, + isVerified: false, + isOwner: false, + isModerator: false, + timestamp: new Date("2021-01-01"), + } + ]) + }) + test("From Verified User", () => { const res = JSON.parse(readFileSync(__dirname + "/testdata/get_live_chat.from-verified.json").toString()) const [chatItems, continuation] = parseChatData(res) diff --git a/test/testdata/get_live_chat.membership-gift.json b/test/testdata/get_live_chat.membership-gift.json new file mode 100644 index 0000000..36880e8 --- /dev/null +++ b/test/testdata/get_live_chat.membership-gift.json @@ -0,0 +1,168 @@ +{ + "responseContext": { + "serviceTrackingParams": [ + { + "service": "CSI", + "params": [ + { + "key": "c", + "value": "WEB" + }, + { + "key": "cver", + "value": "2.20211119.09.00" + }, + { + "key": "yt_li", + "value": "0" + }, + { + "key": "GetLiveChat_rid", + "value": "0x05d2923065b2295c" + } + ] + }, + { + "service": "GFEEDBACK", + "params": [ + { + "key": "logged_in", + "value": "0" + }, + { + "key": "e", + "value": "24115586,24034168,24137390,24106921,24132435,24129452,24113096,24002025,39321281,24027701,24135287,23983296,24131029,23857950,24118516,24007790,23934970,23744176,24113224,24016904,24080738,24134829,23918597,24049820,24002022,24113538,24028143,24115508,24132376,24084440,24095695,23968386,24131277,24036948,24064555,23986025,24109689,24001373,24077241,24004644,24116916,39321426,24116772,24116735,24007246,24129402,24129776,24136255,23944779,24058380,23998056,24128612,24082661,23882502,23804281,24113699,24130238,23885487,24085811,24077266,23946420,24106407,24110902,24106839,1714247,24116717,24111165,24106628,24114970,24126458,23884386,23966208" + } + ] + }, + { + "service": "GUIDED_HELP", + "params": [ + { + "key": "logged_in", + "value": "0" + } + ] + }, + { + "service": "ECATCHER", + "params": [ + { + "key": "client.version", + "value": "2.20211119" + }, + { + "key": "client.name", + "value": "WEB" + }, + { + "key": "client.fexp", + "value": "24115586,24034168,24137390,24106921,24132435,24129452,24113096,24002025,39321281,24027701,24135287,23983296,24131029,23857950,24118516,24007790,23934970,23744176,24113224,24016904,24080738,24134829,23918597,24049820,24002022,24113538,24028143,24115508,24132376,24084440,24095695,23968386,24131277,24036948,24064555,23986025,24109689,24001373,24077241,24004644,24116916,39321426,24116772,24116735,24007246,24129402,24129776,24136255,23944779,24058380,23998056,24128612,24082661,23882502,23804281,24113699,24130238,23885487,24085811,24077266,23946420,24106407,24110902,24106839,1714247,24116717,24111165,24106628,24114970,24126458,23884386,23966208" + } + ] + } + ], + "mainAppWebResponseContext": { + "loggedOut": true + }, + "webResponseContextExtensionData": { + "hasDecorated": true + } + }, + "continuationContents": { + "liveChatContinuation": { + "continuations": [ + { + "invalidationContinuationData": { + "invalidationId": { + "objectSource": 1056, + "objectId": "objectId", + "topic": "topic", + "subscribeToGcmTopics": true, + "protoCreationTimestampMs": "1637648016661" + }, + "timeoutMs": 10000, + "continuation": "test-continuation:01" + } + } + ], + "actions": [ + { + "addChatItemAction": { + "item": { + "liveChatSponsorshipsGiftPurchaseAnnouncementRenderer": { + "id": "id", + "timestampUsec": "1609459200000000", + "authorExternalChannelId": "channelId", + "header": { + "liveChatSponsorshipsHeaderRenderer": { + "authorName": { + "simpleText": "authorName" + }, + "authorPhoto": { + "thumbnails": [ + { + "url": "https://author.thumbnail.url", + "width": 32, + "height": 32 + }, + { + "url": "https://author.thumbnail.url", + "width": 64, + "height": 64 + } + ] + }, + "primaryText": { + "runs": [ + { + "text": "10", + "bold": true + }, + { + "text": " 件の ", + "bold": true + }, + { + "text": "上級エンジニア", + "bold": true + }, + { + "text": " のメンバーシップ ギフトを贈りました", + "bold": true + } + ] + }, + "contextMenuEndpoint": { + "clickTrackingParams": "CAEQl98BIhMI07io_reR-AIV1LRWAR1kDQ1K", + "commandMetadata": { + "webCommandMetadata": { + "ignoreNavigation": true + } + }, + "liveChatItemContextMenuEndpoint": { + "params": "Q2g0S0hBb2FRMDV4Y1ROMllUTnJabWREUmxKTlQyWlJiMlJMU1hkSmQzY2FLU29uQ2hoVlEyUjVjVUZoV2tSTFNGaG5ORUZvYVRkV1JVNVVhRkVTQzI0NGNWSndhVlpYWDJGRklBRW9CRElhQ2hoVlF6TnJYMjFHZURkRGVsOWhhRXM0Y0RSVWNsbzVTMUU0QWtnQVVDUSUzRA==" + } + }, + "contextMenuAccessibility": { + "accessibilityData": { + "label": "チャットの操作" + } + }, + "image": { + "thumbnails": [ + { + "url": "https://www.gstatic.com/youtube/img/sponsorships/sponsorships_gift_purchase_announcement_artwork.png" + } + ] + } + } + } + } + } + } + } + ] + } + } +} \ No newline at end of file From 5ea6e668bc0b74fdd827429f8f17b5d961e62e90 Mon Sep 17 00:00:00 2001 From: "Reona Oshima(totoraj)" Date: Tue, 20 Jun 2023 18:19:47 +0900 Subject: [PATCH 3/3] format --- src/parser.ts | 12 ++++++------ test/parser.test.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/parser.ts b/src/parser.ts index c07ca62..0069183 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -148,12 +148,12 @@ function rendererFromAction( } else if (item.liveChatMembershipItemRenderer) { return item.liveChatMembershipItemRenderer } else if (item.liveChatSponsorshipsGiftPurchaseAnnouncementRenderer) { - const parentRenderer = item.liveChatSponsorshipsGiftPurchaseAnnouncementRenderer; + const parentRenderer = item.liveChatSponsorshipsGiftPurchaseAnnouncementRenderer return { id: parentRenderer.id, timestampUsec: parentRenderer.timestampUsec, authorExternalChannelId: parentRenderer.authorExternalChannelId, - ...parentRenderer.header.liveChatSponsorshipsHeaderRenderer + ...parentRenderer.header.liveChatSponsorshipsHeaderRenderer, } } return null @@ -228,9 +228,9 @@ function parseActionToChatItem(data: Action): ChatItem | null { color: convertColorToHex6(messageRenderer.bodyBackgroundColor), } } else if ( - data.addChatItemAction?.item.liveChatSponsorshipsGiftPurchaseAnnouncementRenderer - && "primaryText" in messageRenderer - && messageRenderer.primaryText.runs + data.addChatItemAction?.item.liveChatSponsorshipsGiftPurchaseAnnouncementRenderer && + "primaryText" in messageRenderer && + messageRenderer.primaryText.runs ) { ret.membershipGift = { message: parseMessages(messageRenderer.primaryText.runs), @@ -238,7 +238,7 @@ function parseActionToChatItem(data: Action): ChatItem | null { if (messageRenderer.image?.thumbnails?.[0]) { ret.membershipGift.image = { ...messageRenderer.image.thumbnails[0], - alt: "" + alt: "", } } } diff --git a/test/parser.test.ts b/test/parser.test.ts index 3d56d59..778bb95 100644 --- a/test/parser.test.ts +++ b/test/parser.test.ts @@ -294,14 +294,14 @@ describe("Parser", () => { image: { url: "https://www.gstatic.com/youtube/img/sponsorships/sponsorships_gift_purchase_announcement_artwork.png", alt: "", - } + }, }, isMembership: false, isVerified: false, isOwner: false, isModerator: false, timestamp: new Date("2021-01-01"), - } + }, ]) })