feat: 쿠키 파일 기반 설정(YOUTUBE_COOKIE_PATH)+리졸버 URL 설정화, 다음곡 프리페치로 재생지연 단축, ytresolver 리포 포함, 쿠키 재발급 스크립트, README 상세화
This commit is contained in:
91
scripts/refresh-cookies.mjs
Normal file
91
scripts/refresh-cookies.mjs
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* refresh-cookies.mjs — 성인인증 계정 쿠키(ytcookie.txt) 재발급 스크립트
|
||||
*
|
||||
* 쿠키가 만료되면(19금 재생만 막히고 일반 재생은 계속 됨) 이 스크립트로 새 쿠키를 뽑는다.
|
||||
* Chromium을 띄워 구글 로그인 → youtube.com 쿠키를 Netscape 형식으로 저장한다.
|
||||
*
|
||||
* 사용 전: npm i -D playwright (그리고 최초 1회) npx playwright install chromium
|
||||
*
|
||||
* 실행 예:
|
||||
* GOOGLE_EMAIL=tmdgks040466@gmail.com GOOGLE_PASSWORD='...' \
|
||||
* OUT=/root/bot/db/ytcookie.txt node scripts/refresh-cookies.mjs
|
||||
*
|
||||
* 환경변수:
|
||||
* GOOGLE_EMAIL / GOOGLE_PASSWORD : 자동 로그인 시도용(생략 가능 — 그러면 수동 로그인)
|
||||
* OUT : 저장 경로 (기본 ./ytcookie.txt). 운영은 /root/bot/db/ytcookie.txt
|
||||
* HEADLESS : "1"이면 창 없이(자동 로그인 성공 시에만 권장). 기본은 창 표시(수동 로그인 가능)
|
||||
*
|
||||
* 구글이 자동 로그인을 막으면(2차인증/캡차/"안전하지 않은 브라우저") 뜬 창에서 직접 로그인하면 된다.
|
||||
* 스크립트는 로그인 세션 쿠키(SID)가 잡힐 때까지 최대 5분 기다린 뒤 저장한다.
|
||||
*/
|
||||
import { chromium } from "playwright";
|
||||
import { writeFileSync } from "node:fs";
|
||||
|
||||
const EMAIL = process.env.GOOGLE_EMAIL;
|
||||
const PASSWORD = process.env.GOOGLE_PASSWORD;
|
||||
const OUT = process.env.OUT || "./ytcookie.txt";
|
||||
const HEADLESS = process.env.HEADLESS === "1";
|
||||
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
|
||||
// Playwright 쿠키 배열 -> Netscape cookies.txt (yt-dlp/youtubei.js 호환)
|
||||
function toNetscape(cookies) {
|
||||
const lines = ["# Netscape HTTP Cookie File", "# music_bot_v2 refresh-cookies.mjs"];
|
||||
for (const c of cookies) {
|
||||
if (!/(^|\.)youtube\.com$|(^|\.)google\.com$/.test(c.domain)) continue;
|
||||
const domain = c.domain.startsWith(".") ? c.domain : "." + c.domain;
|
||||
const expires = c.expires && c.expires > 0 ? Math.floor(c.expires) : 2000000000;
|
||||
lines.push([
|
||||
domain, "TRUE", c.path || "/", c.secure ? "TRUE" : "FALSE",
|
||||
expires, c.name, c.value,
|
||||
].join("\t"));
|
||||
}
|
||||
return lines.join("\n") + "\n";
|
||||
}
|
||||
|
||||
async function tryAutoLogin(page) {
|
||||
if (!EMAIL || !PASSWORD) return;
|
||||
try {
|
||||
await page.goto("https://accounts.google.com/ServiceLogin?continue=https://www.youtube.com/", { waitUntil: "domcontentloaded" });
|
||||
await page.fill('input[type="email"]', EMAIL, { timeout: 15000 });
|
||||
await page.click('#identifierNext, button:has-text("다음"), button:has-text("Next")');
|
||||
await page.waitForTimeout(2500);
|
||||
await page.fill('input[type="password"]', PASSWORD, { timeout: 15000 });
|
||||
await page.click('#passwordNext, button:has-text("다음"), button:has-text("Next")');
|
||||
await page.waitForTimeout(3000);
|
||||
} catch (e) {
|
||||
console.log("[auto-login] 자동 로그인 중단(수동 로그인으로 진행):", String(e).slice(0, 100));
|
||||
}
|
||||
}
|
||||
|
||||
async function waitForLogin(context, page, maxMs = 5 * 60 * 1000) {
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < maxMs) {
|
||||
const cookies = await context.cookies("https://www.youtube.com");
|
||||
if (cookies.some((c) => c.name === "SID") && cookies.some((c) => c.name === "LOGIN_INFO")) {
|
||||
return cookies;
|
||||
}
|
||||
await sleep(3000);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
(async () => {
|
||||
const browser = await chromium.launch({ headless: HEADLESS });
|
||||
const context = await browser.newContext();
|
||||
const page = await context.newPage();
|
||||
await tryAutoLogin(page);
|
||||
// youtube를 한번 열어 로그인 세션 쿠키를 확실히 발급
|
||||
try { await page.goto("https://www.youtube.com/", { waitUntil: "domcontentloaded" }); } catch {}
|
||||
console.log("로그인 완료를 기다리는 중... (자동 로그인이 막혔으면 뜬 창에서 직접 로그인하세요)");
|
||||
const cookies = await waitForLogin(context, page);
|
||||
if (!cookies) {
|
||||
console.error("❌ 로그인 세션 쿠키(SID/LOGIN_INFO)를 못 잡았습니다. 다시 시도하세요.");
|
||||
await browser.close();
|
||||
process.exit(1);
|
||||
}
|
||||
const all = await context.cookies();
|
||||
writeFileSync(OUT, toNetscape(all));
|
||||
console.log(`✅ 쿠키 저장 완료: ${OUT} (youtube/google 쿠키 ${all.length}개 중 관련 항목)`);
|
||||
await browser.close();
|
||||
process.exit(0);
|
||||
})();
|
||||
Reference in New Issue
Block a user