diff --git a/client/public/rabbit.svg b/client/public/rabbit.svg index 15e0ab7..b77663f 100644 --- a/client/public/rabbit.svg +++ b/client/public/rabbit.svg @@ -1,11 +1,24 @@ - - - - - - - - - - + + + + + + + + + diff --git a/client/public/rabbit_.svg b/client/public/rabbit_.svg new file mode 100644 index 0000000..15e0ab7 --- /dev/null +++ b/client/public/rabbit_.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/client/src/components/Sidebar.svelte b/client/src/components/Sidebar.svelte index 28d7019..8caabdf 100644 --- a/client/src/components/Sidebar.svelte +++ b/client/src/components/Sidebar.svelte @@ -338,8 +338,8 @@ const unsubscribeRabbit = rabbitCount.subscribe((count) => { } .rabbit-icon { - width: 18px; - height: 18px; + width: 31px; + height: 31px; object-fit: contain; } diff --git a/client/src/routes/Settings.svelte b/client/src/routes/Settings.svelte index 080b5b5..528e97b 100644 --- a/client/src/routes/Settings.svelte +++ b/client/src/routes/Settings.svelte @@ -5,6 +5,7 @@ const tabs = [ { id: "general", label: "General", icon: "fa-solid fa-sliders" }, { id: "youtube", label: "YouTube", icon: "fa-brands fa-youtube" }, + { id: "pornhub", label: "Pornhub", icon: "fa-solid fa-lock" }, { id: "advanced", label: "Advanced", icon: "fa-solid fa-gear" } ]; @@ -13,6 +14,10 @@ let cookiesUpdatedAt = null; let loadingCookies = false; let savingCookies = false; + let pornhubCookies = ""; + let phCookiesUpdatedAt = null; + let loadingPhCookies = false; + let savingPhCookies = false; let loadingYtSettings = false; let savingYtSettings = false; let selectedResolution = "1080p"; @@ -69,6 +74,54 @@ } } + async function loadPornhubCookies() { + loadingPhCookies = true; + error = null; + success = null; + try { + const resp = await apiFetch("/api/pornhub/cookies"); + if (!resp.ok) throw new Error(`HTTP ${resp.status}`); + const data = await resp.json(); + pornhubCookies = data?.cookies || ""; + phCookiesUpdatedAt = data?.updatedAt || null; + } catch (err) { + error = err?.message || "Cookies alınamadı."; + } finally { + loadingPhCookies = false; + } + } + + async function savePornhubCookies() { + if (savingPhCookies) return; + error = null; + success = null; + savingPhCookies = true; + try { + const payload = { + cookies: pornhubCookies + .split("\n") + .map((line) => line.trim()) + .filter(Boolean) + .join("\n") + }; + const resp = await apiFetch("/api/pornhub/cookies", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload) + }); + const data = await resp.json().catch(() => ({})); + if (!resp.ok || !data?.ok) { + throw new Error(data?.error || `HTTP ${resp.status}`); + } + phCookiesUpdatedAt = data.updatedAt || Date.now(); + success = "Cookies kaydedildi."; + } catch (err) { + error = err?.message || "Cookies kaydedilemedi."; + } finally { + savingPhCookies = false; + } + } + async function loadYoutubeSettings() { loadingYtSettings = true; error = null; @@ -114,6 +167,7 @@ onMount(() => { loadCookies(); loadYoutubeSettings(); + loadPornhubCookies(); }); function formatDate(ts) { @@ -221,6 +275,54 @@ + {#if error} +
+ + {error} +
+ {/if} + {#if success} +
+ + {success} +
+ {/if} + + {:else if activeTab === "pornhub"} +
+
+
+ + Pornhub Cookies +
+ {#if phCookiesUpdatedAt} +
Son güncelleme: {formatDate(phCookiesUpdatedAt)}
+ {/if} +
+ +
+ + + + Zararlı komut çalıştırılamaz; yalnızca düz metin cookie satırları yazılır. + Maksimum 20KB. Engellenen karakterler otomatik reddedilir. + +
+ +
+ + +
+ {#if error}
diff --git a/docker-compose.yml b/docker-compose.yml index d0a7aa6..833c48f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: build: . container_name: app ports: - - "3001:3001" + - "3005:3001" volumes: - ./downloads:/app/server/downloads - ./cache:/app/server/cache diff --git a/server/server.js b/server/server.js index fd41447..cf94a9f 100644 --- a/server/server.js +++ b/server/server.js @@ -78,6 +78,11 @@ const YT_COOKIES_PATH = process.env.YT_DLP_COOKIES || process.env.YT_DLP_COOKIE_FILE || path.join(CACHE_DIR, "yt_cookies.txt"); +const PH_COOKIES_PATH = + process.env.PH_DLP_COOKIES || + process.env.PH_DLP_COOKIE_FILE || + process.env.PORNHUB_COOKIES || + path.join(CACHE_DIR, "ph_cookies.txt"); const YT_SETTINGS_PATH = path.join(CACHE_DIR, "yt_settings.json"); const YT_DEFAULT_RESOLUTION = "1080p"; const YT_ALLOWED_RESOLUTIONS = new Set([ @@ -963,6 +968,9 @@ function launchYoutubeJob(job) { function launchPornhubJob(job) { const binary = getYtDlpBinary(); + const cookieFile = + (PH_COOKIES_PATH && fs.existsSync(PH_COOKIES_PATH) && PH_COOKIES_PATH) || + null; const args = [ "-f", "bestvideo+bestaudio/best", @@ -972,6 +980,7 @@ function launchPornhubJob(job) { "--write-info-json", "--concurrent-fragments", "10", + ...(cookieFile ? ["--cookies", cookieFile] : []), job.url ]; @@ -980,7 +989,7 @@ function launchPornhubJob(job) { args, logs: [], jsRuntime: null, - cookies: null, + cookies: cookieFile, extractorArgs: null, resolution: null, onlyAudio: false, @@ -6372,6 +6381,50 @@ app.post("/api/youtube/cookies", requireAuth, (req, res) => { } }); +// --- 🎫 Pornhub cookies yönetimi --- +app.get("/api/pornhub/cookies", requireAuth, (req, res) => { + try { + if (!PH_COOKIES_PATH || !fs.existsSync(PH_COOKIES_PATH)) { + return res.json({ hasCookies: false, cookies: null, updatedAt: null }); + } + const stat = fs.statSync(PH_COOKIES_PATH); + const size = stat.size; + if (size > 20000) { + return res.json({ hasCookies: true, cookies: "", updatedAt: stat.mtimeMs }); + } + const content = fs.readFileSync(PH_COOKIES_PATH, "utf-8"); + res.json({ hasCookies: true, cookies: content, updatedAt: stat.mtimeMs }); + } catch (err) { + console.warn("⚠️ Pornhub cookies okunamadı:", err.message); + res.status(500).json({ error: "Cookies okunamadı" }); + } +}); + +app.post("/api/pornhub/cookies", requireAuth, (req, res) => { + try { + let cookies = req.body?.cookies; + if (typeof cookies !== "string") { + return res.status(400).json({ error: "cookies alanı metin olmalı" }); + } + cookies = cookies.replace(/\r\n/g, "\n"); + if (cookies.length > 20000) { + return res.status(400).json({ error: "Cookie içeriği çok büyük (20KB sınırı)." }); + } + if (/[^\x09\x0a\x0d\x20-\x7e]/.test(cookies)) { + return res.status(400).json({ error: "Cookie içeriğinde desteklenmeyen karakterler var." }); + } + if (!PH_COOKIES_PATH) { + return res.status(500).json({ error: "Cookie yolu tanımlı değil." }); + } + ensureDirForFile(PH_COOKIES_PATH); + fs.writeFileSync(PH_COOKIES_PATH, cookies, "utf-8"); + res.json({ ok: true, updatedAt: Date.now() }); + } catch (err) { + console.error("❌ Pornhub cookies yazılamadı:", err.message); + res.status(500).json({ error: "Cookies kaydedilemedi" }); + } +}); + // --- 🎚️ YouTube kalite ayarları --- app.get("/api/youtube/settings", requireAuth, (req, res) => { try {