From d6f13e20ac6806e7a97dc8c3bd6bb947be6fd76c Mon Sep 17 00:00:00 2001 From: ChunkyProgrammer <78101139+ChunkyProgrammer@users.noreply.github.com> Date: Tue, 17 Jun 2025 16:26:50 +0000 Subject: [PATCH] feat(CommentsView): parse `voice_reply_transcript` (#981) * Parse the VoiceReplyContainer instead of just parsing the text --- src/parser/classes/comments/CommentView.ts | 12 +++++++++++- .../comments/VoiceReplyContainerView.ts | 18 ++++++++++++++++++ src/parser/nodes.ts | 1 + src/parser/parser.ts | 6 +++++- 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/parser/classes/comments/VoiceReplyContainerView.ts diff --git a/src/parser/classes/comments/CommentView.ts b/src/parser/classes/comments/CommentView.ts index d70bc639..ff4da93e 100644 --- a/src/parser/classes/comments/CommentView.ts +++ b/src/parser/classes/comments/CommentView.ts @@ -1,8 +1,10 @@ +import { Parser } from '../../index.js'; import { YTNode } from '../../helpers.js'; import NavigationEndpoint from '../NavigationEndpoint.js'; import Author from '../misc/Author.js'; import Text from '../misc/Text.js'; import CommentReplyDialog from './CommentReplyDialog.js'; +import VoiceReplyContainerView from './VoiceReplyContainerView.js'; import { InnertubeError } from '../../../utils/Utils.js'; import * as ProtoUtils from '../../../utils/ProtoUtils.js'; @@ -63,6 +65,8 @@ export default class CommentView extends YTNode { public is_disliked?: boolean; public is_hearted?: boolean; + public voice_reply_container?: VoiceReplyContainerView | null; + constructor(data: RawNode) { super(); @@ -78,7 +82,7 @@ export default class CommentView extends YTNode { }; } - applyMutations(comment?: RawNode, toolbar_state?: RawNode, toolbar_surface?: RawNode) { + applyMutations(comment?: RawNode, toolbar_state?: RawNode, toolbar_surface?: RawNode, comment_surface?: RawNode) { if (comment) { this.content = Text.fromAttributed(comment.properties.content); this.published_time = comment.properties.publishedTime; @@ -129,6 +133,12 @@ export default class CommentView extends YTNode { this.reply_command = new NavigationEndpoint(toolbar_surface.replyCommand); } } + + if (comment_surface) { + if ('voiceReplyContainerViewModel' in comment_surface) { + this.voice_reply_container = Parser.parseItem(comment_surface.voiceReplyContainerViewModel, VoiceReplyContainerView); + } + } } /** diff --git a/src/parser/classes/comments/VoiceReplyContainerView.ts b/src/parser/classes/comments/VoiceReplyContainerView.ts new file mode 100644 index 00000000..2a7c86ac --- /dev/null +++ b/src/parser/classes/comments/VoiceReplyContainerView.ts @@ -0,0 +1,18 @@ +import { YTNode } from '../../helpers.js'; +import Text from '../misc/Text.js'; + +import type { RawNode } from '../../index.js'; + +export default class VoiceReplyContainerView extends YTNode { + static type = 'VoiceReplyContainerView'; + + voice_reply_unavailable_text : Text; + transcript_text : Text; + + constructor(data: RawNode) { + super(); + + this.voice_reply_unavailable_text = Text.fromAttributed(data.voiceReplyUnavailableText); + this.transcript_text = Text.fromAttributed(data.transcriptText); + } +} \ No newline at end of file diff --git a/src/parser/nodes.ts b/src/parser/nodes.ts index cb94e821..a20da1f2 100644 --- a/src/parser/nodes.ts +++ b/src/parser/nodes.ts @@ -101,6 +101,7 @@ export { default as CreatorHeart } from './classes/comments/CreatorHeart.js'; export { default as EmojiPicker } from './classes/comments/EmojiPicker.js'; export { default as PdgCommentChip } from './classes/comments/PdgCommentChip.js'; export { default as SponsorCommentBadge } from './classes/comments/SponsorCommentBadge.js'; +export { default as VoiceReplyContainerView } from './classes/comments/VoiceReplyContainerView.js'; export { default as CompactChannel } from './classes/CompactChannel.js'; export { default as CompactLink } from './classes/CompactLink.js'; export { default as CompactMix } from './classes/CompactMix.js'; diff --git a/src/parser/parser.ts b/src/parser/parser.ts index 4c9f52da..e513217a 100644 --- a/src/parser/parser.ts +++ b/src/parser/parser.ts @@ -844,7 +844,11 @@ export function applyCommentsMutations(memo: Memo, mutations: RawNode[]) { const engagement_toolbar = mutations.find((mutation) => mutation.entityKey === comment_view.keys.toolbar_surface) ?.payload?.engagementToolbarSurfaceEntityPayload; - comment_view.applyMutations(comment_mutation, toolbar_state_mutation, engagement_toolbar); + const comment_surface_mutation = mutations + .find((mutation) => mutation.payload?.commentSurfaceEntityPayload?.key === comment_view.keys.comment_surface) + ?.payload?.commentSurfaceEntityPayload; + + comment_view.applyMutations(comment_mutation, toolbar_state_mutation, engagement_toolbar, comment_surface_mutation); } } }