Skip to content

Commit 43c7406

Browse files
committed
fix issues with info init
1 parent f3ced76 commit 43c7406

File tree

6 files changed

+116
-107
lines changed

6 files changed

+116
-107
lines changed

src/components/Hyperchat.svelte

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
UNDONE_MSG
2828
} from '../ts/chat-constants';
2929
import '../ts/resize-tracker';
30-
import { isAllEmoji, isChatMessage, isPrivileged, responseIsAction, createPopup, getRandomString, getFrameInfoAsync } from '../ts/chat-utils';
30+
import { isAllEmoji, isChatMessage, isPrivileged, responseIsAction, createPopup, getRandomString } from '../ts/chat-utils';
3131
import Button from 'smelte/src/components/Button';
3232
import {
3333
theme,
@@ -155,20 +155,20 @@
155155
chatFilterPresets.ready(),
156156
defaultFilterPresetId.ready(),
157157
new Promise(resolve => {
158-
const unsub = initialized.subscribe((v) => {
159-
if (v) {
160-
unsub();
158+
const interval = setInterval(() => {
159+
if ($initialized) {
160+
clearInterval(interval);
161161
resolve(null);
162162
}
163-
});
163+
}, 10);
164164
}),
165165
new Promise(resolve => {
166-
const unsub = videoInfo.subscribe((v) => {
167-
if (v !== undefined) {
168-
unsub();
166+
const interval = setInterval(() => {
167+
if ($videoInfo !== undefined) {
168+
clearInterval(interval);
169169
resolve(null);
170170
}
171-
});
171+
}, 10);
172172
})
173173
]);
174174
await tick();

src/scripts/chat-injector.ts

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,10 @@ const chatLoaded = async (): Promise<void> => {
5050
window.addEventListener('messageSent', (d) => {
5151
processSentMessage((d as CustomEvent).detail);
5252
});
53-
let videoInfoResolver = (_info: string): void => {};
54-
const videoInfoPromise = new Promise<string>((resolve) => {
55-
videoInfoResolver = resolve;
56-
});
57-
window.addEventListener('videoInfo', d => {
58-
videoInfoResolver((d as CustomEvent).detail);
53+
let json = '{}';
54+
window.addEventListener('videoInfoYtcFilter', d => {
55+
console.log('calling setInitialData', json, JSON.parse((d as CustomEvent).detail));
56+
setInitialData(json, JSON.parse((d as CustomEvent).detail));
5957
});
6058
const script = document.createElement('script');
6159
script.src = chrome.runtime.getURL('scripts/chat-interceptor.js');
@@ -73,11 +71,7 @@ const chatLoaded = async (): Promise<void> => {
7371
if (!text || !text.startsWith(start)) {
7472
continue;
7573
}
76-
const json = text.replace(start, '').slice(0, -1);
77-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
78-
videoInfoPromise.then((info) => {
79-
setInitialData(json, JSON.parse(info));
80-
});
74+
json = text.replace(start, '').slice(0, -1);
8175
break;
8276
}
8377

src/scripts/chat-interceptor.ts

Lines changed: 71 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -2,76 +2,78 @@ import { stringifyRuns } from '../ts/ytcf-utils';
22
import { fixLeaks } from '../ts/ytc-fix-memleaks';
33
import { parseMessageRuns } from '../ts/chat-parser';
44

5-
for (const eventName of ['visibilitychange', 'webkitvisibilitychange', 'blur']) {
6-
window.addEventListener(eventName, event => {
7-
event.stopImmediatePropagation();
8-
}, true);
9-
}
10-
const fetchFallback = window.fetch;
11-
(window as any).fetchFallback = fetchFallback;
12-
window.fetch = async (...args) => {
13-
const request = args[0] as Request;
14-
const url = request.url;
15-
const result = await fetchFallback(...args);
16-
17-
const currentDomain = (location.protocol + '//' + location.host);
18-
const ytApi = (end: string): string => `${currentDomain}/youtubei/v1/live_chat${end}`;
19-
const isReceiving = url.startsWith(ytApi('/get_live_chat'));
20-
const isSending = url.startsWith(ytApi('/send_message'));
21-
const action = isReceiving ? 'messageReceive' : 'messageSent';
22-
if (isReceiving || isSending) {
23-
const response = JSON.stringify(await (result.clone()).json());
24-
window.dispatchEvent(new CustomEvent(action, { detail: response }));
5+
if (!window.location.href.includes('v=Lq9eqHDKJPE&ytcfilter=1')) {
6+
for (const eventName of ['visibilitychange', 'webkitvisibilitychange', 'blur']) {
7+
window.addEventListener(eventName, event => {
8+
event.stopImmediatePropagation();
9+
}, true);
2510
}
26-
return result;
27-
};
28-
// window.dispatchEvent(new CustomEvent('chatLoaded', {
29-
// detail: JSON.stringify(window.ytcfg)
30-
// }));
31-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
32-
window.addEventListener('proxyFetchRequest', async (event) => {
33-
const args = JSON.parse((event as any).detail as string) as [string, any];
34-
const request = await fetchFallback(...args);
35-
const response = await request.json();
36-
window.dispatchEvent(new CustomEvent('proxyFetchResponse', {
37-
detail: JSON.stringify(response)
38-
}));
39-
});
11+
const fetchFallback = window.fetch;
12+
(window as any).fetchFallback = fetchFallback;
13+
window.fetch = async (...args) => {
14+
const request = args[0] as Request;
15+
const url = request.url;
16+
const result = await fetchFallback(...args);
17+
18+
const currentDomain = (location.protocol + '//' + location.host);
19+
const ytApi = (end: string): string => `${currentDomain}/youtubei/v1/live_chat${end}`;
20+
const isReceiving = url.startsWith(ytApi('/get_live_chat'));
21+
const isSending = url.startsWith(ytApi('/send_message'));
22+
const action = isReceiving ? 'messageReceive' : 'messageSent';
23+
if (isReceiving || isSending) {
24+
const response = JSON.stringify(await (result.clone()).json());
25+
window.dispatchEvent(new CustomEvent(action, { detail: response }));
26+
}
27+
return result;
28+
};
29+
// window.dispatchEvent(new CustomEvent('chatLoaded', {
30+
// detail: JSON.stringify(window.ytcfg)
31+
// }));
32+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
33+
window.addEventListener('proxyFetchRequest', async (event) => {
34+
const args = JSON.parse((event as any).detail as string) as [string, any];
35+
const request = await fetchFallback(...args);
36+
const response = await request.json();
37+
window.dispatchEvent(new CustomEvent('proxyFetchResponse', {
38+
detail: JSON.stringify(response)
39+
}));
40+
});
4041

41-
try {
42-
const video = (window as any)
43-
.parent.yt.config_.SBOX_SETTINGS.SEARCHBOX_COMPONENT.__dataHost.parentComponent
44-
.__data.data.response.contents.twoColumnWatchNextResults.results.results.contents[0]
45-
.videoPrimaryInfoRenderer;
46-
const channel = (window as any).parent.yt.config_.SBOX_SETTINGS.SEARCHBOX_COMPONENT.__dataHost
47-
.parentComponent.__data.data.response.contents.twoColumnWatchNextResults.results.results
48-
.contents[1].videoSecondaryInfoRenderer.owner.videoOwnerRenderer;
49-
const params = new URLSearchParams(window.parent.location.search);
50-
window.dispatchEvent(new CustomEvent('videoInfo', {
51-
detail: JSON.stringify({
52-
video: {
53-
title: stringifyRuns(parseMessageRuns(video.title.runs)),
54-
videoId: video.updatedMetadataEndpoint?.updatedMetadataEndpoint?.videoId || params.get('v')
55-
},
56-
channel: {
57-
channelId: channel.navigationEndpoint.browseEndpoint.browseId,
58-
handle: channel.navigationEndpoint.browseEndpoint.canonicalBaseUrl.split('/@')[1],
59-
name: stringifyRuns(parseMessageRuns(channel.title.runs))
60-
}
61-
})
62-
}));
63-
} catch (e) {
64-
const videoId = new URLSearchParams(window.location.search).get('v');
65-
window.dispatchEvent(new CustomEvent('videoInfo', {
66-
detail: JSON.stringify(
67-
videoId !== null
68-
? {
69-
video: {
70-
videoId
42+
try {
43+
const video = (window as any)
44+
.parent.yt.config_.SBOX_SETTINGS.SEARCHBOX_COMPONENT.__dataHost.parentComponent
45+
.__data.data.response.contents.twoColumnWatchNextResults.results.results.contents[0]
46+
.videoPrimaryInfoRenderer;
47+
const channel = (window as any).parent.yt.config_.SBOX_SETTINGS.SEARCHBOX_COMPONENT.__dataHost
48+
.parentComponent.__data.data.response.contents.twoColumnWatchNextResults.results.results
49+
.contents[1].videoSecondaryInfoRenderer.owner.videoOwnerRenderer;
50+
const params = new URLSearchParams(window.parent.location.search);
51+
window.dispatchEvent(new CustomEvent('videoInfoYtcFilter', {
52+
detail: JSON.stringify({
53+
video: {
54+
title: stringifyRuns(parseMessageRuns(video.title.runs)),
55+
videoId: video.updatedMetadataEndpoint?.updatedMetadataEndpoint?.videoId || params.get('v')
56+
},
57+
channel: {
58+
channelId: channel.navigationEndpoint.browseEndpoint.browseId,
59+
handle: channel.navigationEndpoint.browseEndpoint.canonicalBaseUrl.split('/@')[1],
60+
name: stringifyRuns(parseMessageRuns(channel.title.runs))
61+
}
62+
})
63+
}));
64+
} catch (e) {
65+
const videoId = new URLSearchParams(window.location.search).get('v');
66+
window.dispatchEvent(new CustomEvent('videoInfoYtcFilter', {
67+
detail: JSON.stringify(
68+
videoId !== null
69+
? {
70+
video: {
71+
videoId
72+
}
7173
}
72-
}
73-
: null)
74-
}));
75-
}
74+
: null)
75+
}));
76+
}
7677

77-
fixLeaks();
78+
fixLeaks();
79+
}

src/ts/messaging.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,30 @@ const registerClient = (
6666
}
6767
);
6868

69-
if (getInitialData && isYtcInterceptor(interceptor)) {
70-
const selfChannel = interceptor.queue.selfChannel.get();
71-
const videoInfo = interceptor.queue.videoInfo.get();
72-
const payload: Chat.InitialData = {
73-
type: 'initialData',
74-
initialData: interceptor.queue.getInitialData(),
75-
selfChannel: selfChannel != null
76-
? {
77-
name: selfChannel.authorName?.simpleText ?? '',
78-
channelId: selfChannel.authorExternalChannelId ?? ''
79-
}
80-
: null,
81-
videoInfo
69+
if (getInitialData) {
70+
const callback = (): void => {
71+
if (isYtcInterceptor(interceptor) && interceptor.queue.initialDataReady.get()) {
72+
const selfChannel = interceptor.queue.selfChannel.get();
73+
const videoInfo = interceptor.queue.videoInfo.get();
74+
if (!videoInfo) console.debug('Video info not ready', { port, interceptor });
75+
const payload: Chat.InitialData = {
76+
type: 'initialData',
77+
initialData: interceptor.queue.getInitialData(),
78+
selfChannel: selfChannel != null
79+
? {
80+
name: selfChannel.authorName?.simpleText ?? '',
81+
channelId: selfChannel.authorExternalChannelId ?? ''
82+
}
83+
: null,
84+
videoInfo
85+
};
86+
port.postMessage(payload);
87+
console.debug('Sent initial data', { port, interceptor, payload });
88+
unsubber();
89+
}
8290
};
83-
port.postMessage(payload);
84-
console.debug('Sent initial data', { port, interceptor, payload });
91+
const unsubber = (interceptor as Chat.YtcInterceptor).queue.initialDataReady.subscribe(() => setTimeout(callback, 0));
92+
callback();
8593
}
8694
};
8795

@@ -140,12 +148,14 @@ export const setInitialData = (json: string, info: SimpleVideoInfo | null): void
140148
?.addLiveChatTextMessageFromTemplateAction?.template
141149
?.liveChatTextMessageRenderer ?? {
142150
authorName: {
143-
simpleText: parsedJson.continuationContents.liveChatContinuation.viewerName
151+
simpleText: parsedJson?.continuationContents?.liveChatContinuation?.viewerName
144152
}
145153
};
146154

147155
interceptor.queue.selfChannel.set(user);
148156
interceptor.queue.videoInfo.set(info);
157+
interceptor.queue.initialDataReady.set(true);
158+
console.log('initialDataReady', interceptor.queue.initialDataReady.get());
149159
};
150160

151161
/** Updates the player progress of the queue of the interceptor. */

src/ts/queue.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export interface YtcQueue {
9797
cleanUp: () => void;
9898
selfChannel: Subscribable<Ytc.TextMessageRenderer | null | undefined>;
9999
videoInfo: Subscribable<SimpleVideoInfo | null>;
100+
initialDataReady: Subscribable<boolean>;
100101
}
101102

102103
export function ytcQueue(isReplay = false): YtcQueue {
@@ -108,6 +109,8 @@ export function ytcQueue(isReplay = false): YtcQueue {
108109
let initialData: Chat.Actions[] = [];
109110
const selfChannel = subscribable<Ytc.TextMessageRenderer | null | undefined>();
110111
const videoInfo = subscribable<SimpleVideoInfo | null>();
112+
const initialDataReady = subscribable<boolean>();
113+
initialDataReady.set(false);
111114

112115
/**
113116
* Continuously pushes queue messages to store until queue is empty or until
@@ -302,6 +305,7 @@ export function ytcQueue(isReplay = false): YtcQueue {
302305
updatePlayerProgress,
303306
cleanUp,
304307
selfChannel,
305-
videoInfo
308+
videoInfo,
309+
initialDataReady
306310
};
307311
}

src/ts/ytcf-logic.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,6 @@ export const saveMessageActions = async (
534534
nickname: lastObj.nickname || '',
535535
size: actions.length
536536
};
537-
console.log(obj);
538537
await saveMessageDumpInfo(key, obj);
539538
// const actionsStore = stores.addSyncStore(keyGen(key, 'actions'), actions, false);
540539
// await actionsStore.ready();

0 commit comments

Comments
 (0)