Skip to content

Commit 948c469

Browse files
committed
fix(sanity): add visitorData token to transcript sync functions and target incomplete transcripts
1 parent d5f5a61 commit 948c469

2 files changed

Lines changed: 60 additions & 25 deletions

File tree

  • apps/sanity/functions

‎apps/sanity/functions/sync-missing-youtube-transcripts/index.ts‎

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,42 @@ async function fetchYouTubeCaptions(videoId: string): Promise<{
7474
const INNERTUBE_CLIENT_VERSION = "20.10.38";
7575

7676
try {
77+
// Acquire fresh visitorData token to bypass LOGIN_REQUIRED in datacenter environments
78+
let visitorData: string | undefined;
79+
try {
80+
const pageResp = await fetch(`https://www.youtube.com/watch?v=${videoId}`, {
81+
headers: {
82+
"User-Agent":
83+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
84+
"Accept-Language": "en-US,en;q=0.9",
85+
},
86+
});
87+
if (pageResp.ok) {
88+
const html = await pageResp.text();
89+
const match = html.match(/"visitorData":"([^"]+)"/);
90+
if (match) {
91+
visitorData = match[1];
92+
}
93+
}
94+
} catch {}
95+
96+
const requestHeaders: Record<string, string> = {
97+
"Content-Type": "application/json",
98+
"User-Agent": `com.google.android.youtube/${INNERTUBE_CLIENT_VERSION} (Linux; U; Android 14)`,
99+
};
100+
if (visitorData) {
101+
requestHeaders["X-Goog-Visitor-Id"] = visitorData;
102+
}
103+
77104
const response = await fetch(INNERTUBE_API_URL, {
78105
method: "POST",
79-
headers: {
80-
"Content-Type": "application/json",
81-
"User-Agent": `com.google.android.youtube/${INNERTUBE_CLIENT_VERSION} (Linux; U; Android 14)`,
82-
},
106+
headers: requestHeaders,
83107
body: JSON.stringify({
84108
context: {
85109
client: {
86110
clientName: "ANDROID",
87111
clientVersion: INNERTUBE_CLIENT_VERSION,
112+
...(visitorData ? { visitorData } : {}),
88113
},
89114
},
90115
videoId,
@@ -262,24 +287,9 @@ export const handler = scheduledEventHandler(async ({ context }) => {
262287
const batchSize = parseInt(process.env.SYNC_BATCH_SIZE || "50", 10);
263288

264289
console.log(
265-
`[Sync Missing YouTube Transcripts] Querying documents with YouTube URLs missing transcripts in project ${projectId}, dataset ${dataset}...`,
290+
`[Sync Missing YouTube Transcripts] Querying documents with YouTube URLs missing transcripts or full captions in project ${projectId}, dataset ${dataset}...`,
266291
);
267292

268-
const totalMissing = await client.fetch<number>(
269-
`count(*[_type in ["post", "podcast", "course", "lesson", "short"] && (defined(youtube) || defined(listenLinks.youtube)) && !defined(transcript) && !(_id in path("drafts.**"))])`,
270-
);
271-
272-
console.log(
273-
`[Sync Missing YouTube Transcripts] Total documents currently missing transcripts in ${dataset}: ${totalMissing}`,
274-
);
275-
276-
if (totalMissing === 0) {
277-
console.log(
278-
"[Sync Missing YouTube Transcripts] All videos currently have linked transcripts. Done.",
279-
);
280-
return;
281-
}
282-
283293
const missingDocs = await client.fetch<
284294
Array<{
285295
_id: string;
@@ -288,7 +298,7 @@ export const handler = scheduledEventHandler(async ({ context }) => {
288298
youtube: string;
289299
}>
290300
>(
291-
`*[_type in ["post", "podcast", "course", "lesson", "short"] && (defined(youtube) || defined(listenLinks.youtube)) && !defined(transcript) && !(_id in path("drafts.**"))][0...$batchSize]{
301+
`*[_type in ["post", "podcast", "course", "lesson", "short"] && (defined(youtube) || defined(listenLinks.youtube)) && (!defined(transcript) || !defined(transcript->fullText) || length(transcript->fullText) < 50) && !(_id in path("drafts.**"))][0...$batchSize]{
292302
_id,
293303
_type,
294304
title,

‎apps/sanity/functions/sync-youtube-transcript/index.ts‎

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,17 +85,42 @@ async function fetchYouTubeCaptions(videoId: string): Promise<{
8585
const INNERTUBE_CLIENT_VERSION = "20.10.38";
8686

8787
try {
88+
// Acquire fresh visitorData token to bypass LOGIN_REQUIRED in datacenter environments
89+
let visitorData: string | undefined;
90+
try {
91+
const pageResp = await fetch(`https://www.youtube.com/watch?v=${videoId}`, {
92+
headers: {
93+
"User-Agent":
94+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
95+
"Accept-Language": "en-US,en;q=0.9",
96+
},
97+
});
98+
if (pageResp.ok) {
99+
const html = await pageResp.text();
100+
const match = html.match(/"visitorData":"([^"]+)"/);
101+
if (match) {
102+
visitorData = match[1];
103+
}
104+
}
105+
} catch {}
106+
107+
const requestHeaders: Record<string, string> = {
108+
"Content-Type": "application/json",
109+
"User-Agent": `com.google.android.youtube/${INNERTUBE_CLIENT_VERSION} (Linux; U; Android 14)`,
110+
};
111+
if (visitorData) {
112+
requestHeaders["X-Goog-Visitor-Id"] = visitorData;
113+
}
114+
88115
const response = await fetch(INNERTUBE_API_URL, {
89116
method: "POST",
90-
headers: {
91-
"Content-Type": "application/json",
92-
"User-Agent": `com.google.android.youtube/${INNERTUBE_CLIENT_VERSION} (Linux; U; Android 14)`,
93-
},
117+
headers: requestHeaders,
94118
body: JSON.stringify({
95119
context: {
96120
client: {
97121
clientName: "ANDROID",
98122
clientVersion: INNERTUBE_CLIENT_VERSION,
123+
...(visitorData ? { visitorData } : {}),
99124
},
100125
},
101126
videoId,

0 commit comments

Comments
 (0)