113 lines
3.8 KiB
JavaScript
113 lines
3.8 KiB
JavaScript
import { PrismaClient } from '@prisma/client';
|
|
import { createDecipheriv, scryptSync } from 'crypto';
|
|
import { google } from 'googleapis';
|
|
|
|
const MISSING_IDS = [
|
|
'4dcg46RQqnM',
|
|
'9xsmLBY20wA',
|
|
'DmmQ7HPxBRg',
|
|
'G58lGGaMOOY',
|
|
'I5u-8xk6BHM',
|
|
'OdHheItBlyQ',
|
|
'VtfmpQXPheA',
|
|
'hIgaxCUX9ts',
|
|
'nHWtSlE-kgE',
|
|
'ye3b5J7zX0M',
|
|
'zW7yrpUs34Q',
|
|
];
|
|
|
|
const CHANNEL_ID = 'cmpfdm4el008nn3uoemascs0z';
|
|
|
|
const PRIVACY_MAP = { public: 'PUBLIC', private: 'PRIVATE', unlisted: 'UNLISTED' };
|
|
|
|
function decrypt(text) {
|
|
const key = scryptSync('7017a681f5b32c3799d1bbf58ce58064', 'studioflow-salt', 32);
|
|
const [ivHex, encHex] = text.split(':');
|
|
const decipher = createDecipheriv('aes-256-cbc', key, Buffer.from(ivHex, 'hex'));
|
|
return Buffer.concat([decipher.update(Buffer.from(encHex, 'hex')), decipher.final()]).toString('utf8');
|
|
}
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
const channel = await prisma.channel.findUniqueOrThrow({ where: { id: CHANNEL_ID } });
|
|
|
|
// Persist supplemental IDs on the channel
|
|
const existing = new Set(channel.supplementalVideoIds ?? []);
|
|
for (const id of MISSING_IDS) existing.add(id);
|
|
await prisma.channel.update({
|
|
where: { id: CHANNEL_ID },
|
|
data: { supplementalVideoIds: [...existing] },
|
|
});
|
|
console.log(`Saved ${existing.size} supplemental video IDs on channel`);
|
|
|
|
// Set up YouTube client and refresh access token
|
|
const oauth2 = new google.auth.OAuth2(
|
|
'496320251583-rpbr13i0rh1112cdvv9ui5s373735qqj.apps.googleusercontent.com',
|
|
'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',
|
|
);
|
|
oauth2.setCredentials({
|
|
access_token: decrypt(channel.youtubeAccessToken),
|
|
refresh_token: channel.youtubeRefreshToken ? decrypt(channel.youtubeRefreshToken) : undefined,
|
|
});
|
|
|
|
// Force token refresh so we always have a valid access token
|
|
const { credentials } = await oauth2.refreshAccessToken();
|
|
oauth2.setCredentials(credentials);
|
|
console.log('Access token refreshed');
|
|
|
|
const yt = google.youtube({ version: 'v3', auth: oauth2 });
|
|
|
|
// Fetch metadata for all missing IDs
|
|
const res = await yt.videos.list({
|
|
part: ['snippet', 'status'],
|
|
id: MISSING_IDS,
|
|
maxResults: 50,
|
|
});
|
|
const items = res.data.items ?? [];
|
|
console.log(`YouTube returned ${items.length} of ${MISSING_IDS.length} requested IDs`);
|
|
|
|
const notFound = MISSING_IDS.filter((id) => !items.find((i) => i.id === id));
|
|
if (notFound.length > 0) console.warn(`Not returned by YouTube API: ${notFound.join(', ')}`);
|
|
|
|
let created = 0;
|
|
let updated = 0;
|
|
|
|
for (const item of items) {
|
|
const ytId = item.id;
|
|
if (!ytId) continue;
|
|
|
|
const snippet = item.snippet;
|
|
const status = item.status;
|
|
|
|
const ytFields = {
|
|
title: snippet?.title ?? '(Untitled)',
|
|
youtubeDescription: snippet?.description ?? undefined,
|
|
tags: snippet?.tags ?? [],
|
|
categoryId: snippet?.categoryId ?? undefined,
|
|
publishedAt: snippet?.publishedAt ? new Date(snippet.publishedAt) : undefined,
|
|
privacyStatus: PRIVACY_MAP[status?.privacyStatus ?? ''] ?? 'PRIVATE',
|
|
defaultLanguage: snippet?.defaultLanguage ?? undefined,
|
|
defaultAudioLanguage: snippet?.defaultAudioLanguage ?? undefined,
|
|
selfDeclaredMadeForKids: status?.selfDeclaredMadeForKids ?? undefined,
|
|
embeddable: status?.embeddable ?? undefined,
|
|
license: status?.license ?? undefined,
|
|
};
|
|
|
|
const existing = await prisma.video.findUnique({ where: { youtubeVideoId: ytId } });
|
|
if (!existing) {
|
|
await prisma.video.create({ data: { youtubeVideoId: ytId, channelId: CHANNEL_ID, ...ytFields } });
|
|
console.log(` CREATED: ${ytId} — ${ytFields.title}`);
|
|
created++;
|
|
} else {
|
|
await prisma.video.update({
|
|
where: { youtubeVideoId: ytId },
|
|
data: { channelId: CHANNEL_ID, ...ytFields },
|
|
});
|
|
console.log(` UPDATED: ${ytId} — ${ytFields.title}`);
|
|
updated++;
|
|
}
|
|
}
|
|
|
|
console.log(`\nDone: ${created} created, ${updated} updated, ${notFound.length} not found on YouTube`);
|
|
await prisma.$disconnect();
|