Initial commit: YouTube Studio Flow (backend, frontend, infrastructure, docs)

This commit is contained in:
2026-08-11 12:27:44 +02:00
commit d5af006443
304 changed files with 74604 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
import { PrismaClient } from '@prisma/client';
import { createDecipheriv, scryptSync } from 'crypto';
import { google } from 'googleapis';
import { writeFileSync } from 'fs';
const prisma = new PrismaClient();
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 channel = await prisma.channel.findFirst({ where: { name: 'My Channel' } });
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,
});
const yt = google.youtube({ version: 'v3', auth: oauth2 });
const pages = [];
let pageToken;
do {
const res = await yt.playlistItems.list({
part: ['contentDetails', 'snippet', 'status'],
playlistId: channel.uploadsPlaylistId,
maxResults: 50,
...(pageToken ? { pageToken } : {}),
});
pages.push(res.data);
pageToken = res.data.nextPageToken;
} while (pageToken);
const outPath = new URL('./playlist-raw.json', import.meta.url).pathname.replace(/^\/([A-Z]:)/, '$1');
writeFileSync(outPath, JSON.stringify(pages, null, 2));
console.log(`Wrote ${pages.length} pages to ${outPath}`);
await prisma.$disconnect();