Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

YouTube Proxy

הורדת סרטונים דרך GitHub Actions במקום דרך שרת. תוסף Chrome שולח לוורקפלואו את הקישור, את האיכות ואת העוגיות של הדפדפן, ה-runner מריץ yt-dlp, והתוסף מושך את התוצאה חזרה למחשב.

תוסף Chrome ──workflow_dispatch──▶ GitHub Actions ──yt-dlp──▶ artifact ──▶ חזרה לתוסף ──▶ תיקיית ההורדות

למה זה מבוסס ID

לכל הורדה נוצר request_id (UUID). הוורקפלואו מגדיר run-name: dl-<request_id> וגם קורא לארטיפקט dl-<request_id>. התוסף מאתר את הריצה ואת הקובץ לפי אותו מזהה בדיוק — כך שכמה הורדות במקביל לא מתערבבות זו בזו.

הגדרה

1. secret בשם COOKIE_KEY

הריפו ציבורי, ולכן עוגיות לא נשלחות בגלוי: התוסף מצפין אותן ב-AES-256-GCM, והוורקפלואו מפענח אותן בתוך הריצה עם ה-secret. שני הצדדים חייבים להחזיק את אותו מפתח (64 תווי hex).

gh secret set COOKIE_KEY --repo <owner>/youtube-proxy

אותו ערך נכנס גם לשדה cookieKey ב-extension/config.js (או דרך מסך ההגדרות של התוסף).

2. טוקן

צריך fine-grained personal access token עם הרשאה אחת בלבד:

הגדרה ערך
Repository access Only select repositories → הריפו הזה בלבד
Permissions → Actions Read and write

זה מספיק כדי להפעיל את הוורקפלואו, לקרוא סטטוס ריצה ולהוריד artifact — ולא נותן שום גישה אחרת. מפיקים אותו כאן: https://github.com/settings/personal-access-tokens/new

להטמעה נוחה:

python tools/embed_token.py

הסקריפט מבקש להדביק את הטוקן (הקלט מוסתר), מוודא מול ה-API שהוא אכן מגיע לוורקפלואו, כותב אותו לתוך config.js לא כמחרוזת גלויה — אלא XOR עם מפתח אקראי, base64, ומפוצל למספר קטעים מעורבבים — ובונה מחדש את ה-ZIP. יש בקובץ פונקציית _assembleToken() שמרכיבה אותו בזמן ריצה. זה טשטוש (obfuscation) ולא הצפנה אמיתית — המפתח יושב באותו קובץ, אז מי שקורא את config.js יכול לשחזר את הטוקן; המטרה היא רק שהוא לא יופיע כמחרוזת קריאה אחת. ההגנה האמיתית היא ההרשאה המצומצמת של הטוקן עצמו (טבלה למעלה) — נבדק בפועל: 403 על כתיבת git blob, 403 על קריאת secrets, ו-204 (הצלחה) רק על הפעלת הוורקפלואו הזה.

אפשר גם להדביק ידנית ב-extension/config.js, או במסך ההגדרות של התוסף (שם הוא נשמר גלוי ב-chrome.storage.local, בלי הטשטוש — כי זה שדה עריכה רגיל).

3. טעינת התוסף

chrome://extensions ← מצב מפתח ← "טעינת פריט לא ארוז" ← בוחרים את התיקייה extension/.

שימוש

לחיצה על האייקון פותחת לשונית קבועה (לא פופאפ) — אפשר לסגור אותה בלי לפגוע בהורדה, ההורדה עצמה רצה ב-background.js ולא תלויה בשום חלון פתוח. פותחים/מרעננים אותה כדי לראות את רשימת ההורדות שוב; כל עבודה פעילה ממשיכה משם שהיא הייתה.

מדביקים קישור (או שהוא נטען לבד מהטאב הפעיל), בוחרים איכות ולוחצים "הורדה". העוגיות של youtube.com ו-google.com נשלחות מוצפנות עם הבקשה, כך שסרטונים שדורשים חשבון מחובר עובדים גם הם.

ערוצים ופלייליסטים שלמים: קישור לערוץ (/channel/…, /c/…, /@handle) או לפלייליסט (?list=… בלי v=) מזוהה אוטומטית ומדליק מתג "הורדת אוסף שלם" (אפשר גם להדליק ידנית). במצב הזה כל הפריטים יורדים ונארזים ל-ZIP אחד בשם הערוץ/הפלייליסט, וזה מה שנשמר בתיקיית ההורדות — לא קובץ בודד לכל סרטון. עד 200 פריטים לערוץ (נבדק בפועל עם ריצה אמיתית של 202 פריטים, ראו מגבלות למטה); ריצה עם if: always() דואגת שה-ZIP ייבנה גם אם חלק מהפריטים נכשלו.

סרגל ההתקדמות משקף מה שגיטהאב באמת מדווח, בכל שלב אחרת:

  • בהורדת סרטון בודד — אחוז השלמת השלבים בריצה (10–55%, מתוך Jobs API). לגיטהאב אין API להתקדמות בתוך שלב בודד — נבדק בפועל: קריאת הלוגים החיים של ריצה שעדיין רצה מחזירה 404 (BlobNotFound) — אז השלב "Download" (שיכול לקחת בין שנייה לכמה דקות) מוצג עם "זחילה" הדרגתית לכיוון האחוז הבא במקום קפיאה על מספר קבוע.
  • בהורדת ערוץ/פלייליסט — אחוזים אמיתיים לפי כמה פריטים כבר ירדו מתוך הסך הכול (5 מתוך 20 פריטים ירדו), כי כל פריט הוא Job נפרד בגיטהאב וה-API מדווח על סטטוס כל Job בנפרד. זו הסיבה שהורדת אוסף בנויה על כמה Jobs (enumerate → download-item במטריצה → package) ולא לולאה אחת בתוך ריצה בודדת — בלי הפיצול הזה אין דרך לדעת כמה פריטים כבר ירדו לפני שהריצה כולה מסתיימת.

התחברות מחדש אחרי טעינה/ריסטארט

ה-jobs נשמרים ב-chrome.storage.session, שלא שורד ריסטארט של הדפדפן (וטעינה מחדש של התוסף בזמן פיתוח יכולה גם היא לנקות אותו) — אבל הריצה עצמה ממשיכה בגיטהאב בכל מקרה. בכל פתיחה של הלשונית (וגם כל דקה ברקע) התוסף בודק אם יש ריצות workflow_dispatch שעדיין רצות בגיטהאב ולא מוכרות לו מקומית, ומתחבר אליהן מחדש. בכוונה זה חל רק על ריצות שעדיין בעיצומן — ריצה שכבר הסתיימה לא "מתאוששת" אוטומטית, כדי לא לשמור מחדש בלי שקט קובץ שכבר נשמר. מכיוון שגיטהאב לא חושף את הפרמטרים המקוריים של workflow_dispatch אחרי השליחה, ריצה משוחזרת לא יודעת את הכתובת/כותרת/איכות המקוריים (ולכן גם אין לה כפתור "נסה שוב") — אבל היא כן ממשיכה לעקוב אחרי הריצה, מושכת את הקובץ בסיום, ומציגה את השם האמיתי מ-yt-dlp כמו כל הורדה אחרת.

מה יושב איפה

קובץ תפקיד
.github/workflows/download.yml הוורקפלואו: resolve-video (וידאו בודד) או enumerate→download-item (מטריצה)→package (אוסף שלם)
extension/background.js שולח dispatch, עוקב אחרי הריצה (כולל התקדמות אמיתית לפי Jobs), שומר את הקובץ, מתחבר מחדש לריצות קיימות
extension/offscreen.js מוריד את ה-ZIP בזרימה (עם דיווח התקדמות) ופורק אותו
extension/panel.html / panel.js הממשק: קישור, איכות, זיהוי אוסף, רשימת הורדות עם התקדמות
extension/options.js ריפו, טוקן, מפתח הצפנה
tools/make_icons.py מייצר את האייקונים מחדש
tools/embed_token.py מטמיע טוקן חדש בצורה מטושטשת ובונה מחדש את ה-ZIP

מגבלות שכדאי להכיר

  • הריפו ציבורי, ולכן גם ה-artifacts ציבוריים. כל מי שיש לו קישור לריצה יכול להוריד את הקובץ במשך יום (retention-days: 1). העוגיות עצמן מוצפנות, אבל הסרטון שהורדתם — לא. אם זה מפריע, gh repo edit --visibility private פותר את זה (במחיר של מכסת דקות חודשית).
  • יוטיוב חוסם כתובות IP של דאטה-סנטר. בלי עוגיות של חשבון מחובר, כל ריצה מיוטיוב נופלת על Sign in to confirm you're not a bot — נבדק, זה מה שקורה. בדיוק בשביל זה התוסף שולח את העוגיות שלכם. שווה לדעת שיוטיוב עלול לפסול עוגיות שנעשה בהן שימוש מכתובת אחרת, ולכן עדיף חשבון נפרד ולא החשבון הראשי. אתרים אחרים וקישורים ישירים עובדים גם בלי עוגיות בכלל.
  • קובץ (או ZIP אחד) לכל ריצה, עד 45 דקות לכל Job בנפרד — ערוץ גדול מאוד עלול לא להספיק בזמן הזה.
  • מצב אוסף מוגבל ל-200 פריטים (--playlist-end 200); ערוץ גדול יותר יוריד רק את ה-200 הראשונים, עם ::notice:: בלוג הריצה. פריט בודד שנכשל לא מפיל את כל ההורדה (continue-on-error ברמת ה-Job) — הוא פשוט לא נכנס ל-ZIP, וזה מוצג בפרטי ההתקדמות ("X נכשלו").
  • עד 8 פריטים במקביל בהורדת אוסף (max-parallel: 8) — כדי לא להציף את הריפו בעשרות Jobs בו-זמנית.

About

Download videos through GitHub Actions

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages