mirror of
				https://github.com/iv-org/invidious.git
				synced 2025-11-04 06:08:31 -06:00 
			
		
		
		
	Merge branch 'master' into api-only
This commit is contained in:
		
						commit
						3d76898bb9
					
				@ -10,7 +10,7 @@
 | 
			
		||||
  "newest": "الأجدد",
 | 
			
		||||
  "oldest": "الأقدم",
 | 
			
		||||
  "popular": "الاكثر شعبية",
 | 
			
		||||
  "last": "",
 | 
			
		||||
  "last": "اخر الفيديوهات المعدلة",
 | 
			
		||||
  "Next page": "الصفحة الثانية",
 | 
			
		||||
  "Previous page": "الصفحة السابقة",
 | 
			
		||||
  "Clear watch history?": "مسح السجل ؟",
 | 
			
		||||
@ -50,7 +50,7 @@
 | 
			
		||||
  "Autoplay: ": "تشغيل تلقائى: ",
 | 
			
		||||
  "Autoplay next video: ": "شغل الفيديو التالى تلقائى: ",
 | 
			
		||||
  "Listen by default: ": "تشغيل النسخة السمعية تلقائى: ",
 | 
			
		||||
  "Proxy videos? ": "",
 | 
			
		||||
  "Proxy videos? ": "عرض الفيديوهات عن طريق الوكيل(proxy) ؟",
 | 
			
		||||
  "Default speed: ": "السرعة الإفتراضية: ",
 | 
			
		||||
  "Preferred video quality: ": "الجودة المفضلة للفيديوهات: ",
 | 
			
		||||
  "Player volume: ": "صوت المشغل: ",
 | 
			
		||||
@ -83,14 +83,14 @@
 | 
			
		||||
  "Manage subscriptions": "إدارة المشتركين",
 | 
			
		||||
  "Watch history": "سجل المشاهدة",
 | 
			
		||||
  "Delete account": "حذف الحساب",
 | 
			
		||||
  "Administrator preferences": "",
 | 
			
		||||
  "Default homepage: ": "",
 | 
			
		||||
  "Feed menu: ": "",
 | 
			
		||||
  "Top enabled? ": "",
 | 
			
		||||
  "CAPTCHA enabled? ": "",
 | 
			
		||||
  "Login enabled? ": "",
 | 
			
		||||
  "Registration enabled? ": "",
 | 
			
		||||
  "Report statistics? ": "",
 | 
			
		||||
  "Administrator preferences": "إعدادات المدير",
 | 
			
		||||
  "Default homepage: ": "الصفحة الرئيسية الافتراضية ",
 | 
			
		||||
  "Feed menu: ": "قائمة التغذية",
 | 
			
		||||
  "Top enabled? ": "تفعيل 'الأفضل' ؟ ",
 | 
			
		||||
  "CAPTCHA enabled? ": "تفعيل الكابتشا ؟",
 | 
			
		||||
  "Login enabled? ": "تفعيل تسجيل الدخول ؟",
 | 
			
		||||
  "Registration enabled? ": "تفعيل التسجيل ؟",
 | 
			
		||||
  "Report statistics? ": "إبلاغ الإحصائيات",
 | 
			
		||||
  "Save preferences": "حفظ التفضيلات",
 | 
			
		||||
  "Subscription manager": "مدير الإشتراكات",
 | 
			
		||||
  "`x` subscriptions": "`x` مشتركين",
 | 
			
		||||
@ -103,8 +103,9 @@
 | 
			
		||||
  "Released under the AGPLv3 by Omar Roth.": "تم الإنشاء تحت AGPLv3 بواسطة عمر روث.",
 | 
			
		||||
  "Source available here.": "الأكواد متوفرة هنا.",
 | 
			
		||||
  "View JavaScript license information.": "مشاهدة معلومات حول تراخيص الجافاسكريبت.",
 | 
			
		||||
  "View privacy policy.": "",
 | 
			
		||||
  "View privacy policy.": "عرض سياسة الخصوصية",
 | 
			
		||||
  "Trending": "الشائع",
 | 
			
		||||
  "Unlisted": "غير مصنف",
 | 
			
		||||
  "Watch video on Youtube": "مشاهدة الفيديو على اليوتيوب",
 | 
			
		||||
  "Genre: ": "النوع: ",
 | 
			
		||||
  "License: ": "التراخيص: ",
 | 
			
		||||
@ -114,6 +115,7 @@
 | 
			
		||||
  "Whitelisted regions: ": "الدول المسموح فيها هذا الفيديو: ",
 | 
			
		||||
  "Blacklisted regions: ": "الدول الحظور فيها هذا الفيديو: ",
 | 
			
		||||
  "Shared `x`": "شارك منذ `x`",
 | 
			
		||||
  "Premieres in `x`": "يعرض فى 'x'",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "اهلا! يبدو ان الجافاسكريبت معطلة. اضغط هنا لعرض التعليقات, ضع فى إعتبارك انها ستأخذ وقت اطول للعرض.",
 | 
			
		||||
  "View YouTube comments": "عرض تعليقات اليوتيوب",
 | 
			
		||||
  "View more comments on Reddit": "عرض المزيد من التعليقات على\\من موقع Reddit",
 | 
			
		||||
 | 
			
		||||
@ -105,6 +105,7 @@
 | 
			
		||||
  "View JavaScript license information.": "Javascript Lizenzinformationen anzeigen.",
 | 
			
		||||
  "View privacy policy.": "",
 | 
			
		||||
  "Trending": "Trending",
 | 
			
		||||
  "Unlisted": "",
 | 
			
		||||
  "Watch video on Youtube": "Video auf YouTube ansehen",
 | 
			
		||||
  "Genre: ": "Genre: ",
 | 
			
		||||
  "License: ": "Lizenz: ",
 | 
			
		||||
@ -114,6 +115,7 @@
 | 
			
		||||
  "Whitelisted regions: ": "Erlaubte Regionen: ",
 | 
			
		||||
  "Blacklisted regions: ": "Unerlaubte Regionen: ",
 | 
			
		||||
  "Shared `x`": "Geteilt `x`",
 | 
			
		||||
  "Premieres in `x`": "",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hallo! Anscheinend haben Sie JavaScript deaktiviert. Klicken Sie hier um Kommentare anzuzeigen, beachten sie dass es etwas länger dauern kann um sie zu laden.",
 | 
			
		||||
  "View YouTube comments": "YouTube Kommentare anzeigen",
 | 
			
		||||
  "View more comments on Reddit": "Mehr Kommentare auf Reddit anzeigen",
 | 
			
		||||
 | 
			
		||||
@ -103,6 +103,7 @@
 | 
			
		||||
  "View JavaScript license information.": "View JavaScript license information.",
 | 
			
		||||
  "View privacy policy.": "View privacy policy.",
 | 
			
		||||
  "Trending": "Trending",
 | 
			
		||||
  "Unlisted": "",
 | 
			
		||||
  "Watch video on Youtube": "Watch video on Youtube",
 | 
			
		||||
  "Genre: ": "Genre: ",
 | 
			
		||||
  "License: ": "License: ",
 | 
			
		||||
@ -112,6 +113,7 @@
 | 
			
		||||
  "Whitelisted regions: ": "Whitelisted regions: ",
 | 
			
		||||
  "Blacklisted regions: ": "Blacklisted regions: ",
 | 
			
		||||
  "Shared `x`": "Shared `x`",
 | 
			
		||||
  "Premieres in `x`": "",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.",
 | 
			
		||||
  "View YouTube comments": "View YouTube comments",
 | 
			
		||||
  "View more comments on Reddit": "View more comments on Reddit",
 | 
			
		||||
 | 
			
		||||
@ -102,6 +102,7 @@
 | 
			
		||||
  "Source available here.": "",
 | 
			
		||||
  "View JavaScript license information.": "",
 | 
			
		||||
  "View privacy policy.": "",
 | 
			
		||||
  "Unlisted": "",
 | 
			
		||||
  "Trending": "",
 | 
			
		||||
  "Watch video on Youtube": "",
 | 
			
		||||
  "Genre: ": "",
 | 
			
		||||
@ -112,6 +113,7 @@
 | 
			
		||||
  "Whitelisted regions: ": "",
 | 
			
		||||
  "Blacklisted regions: ": "",
 | 
			
		||||
  "Shared `x`": "",
 | 
			
		||||
  "Premieres in `x`": "",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "",
 | 
			
		||||
  "View YouTube comments": "",
 | 
			
		||||
  "View more comments on Reddit": "",
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
  "`x` subscribers": "`x` abonnés",
 | 
			
		||||
  "`x` videos": "`x` vidéos",
 | 
			
		||||
  "LIVE": "EN DIRECT",
 | 
			
		||||
  "Shared `x` ago": "Partagé il y a `x`",
 | 
			
		||||
  "Shared `x` ago": "Ajoutée il y a `x`",
 | 
			
		||||
  "Unsubscribe": "Se désabonner",
 | 
			
		||||
  "Subscribe": "S'abonner",
 | 
			
		||||
  "Login to subscribe to `x`": "Vous devez vous connecter pour vous abonner à `x`",
 | 
			
		||||
@ -16,7 +16,7 @@
 | 
			
		||||
  "Clear watch history?": "Êtes-vous sûr de vouloir supprimer l'historique des vidéos regardées ?",
 | 
			
		||||
  "Yes": "Oui",
 | 
			
		||||
  "No": "Non",
 | 
			
		||||
  "Import and Export Data": "Importer et Exporter les Données",
 | 
			
		||||
  "Import and Export Data": "Importer et exporter des données",
 | 
			
		||||
  "Import": "Importer",
 | 
			
		||||
  "Import Invidious data": "Importer des données Invidious",
 | 
			
		||||
  "Import YouTube subscriptions": "Importer des abonnements YouTube",
 | 
			
		||||
@ -32,32 +32,32 @@
 | 
			
		||||
  "An alternative front-end to YouTube": "Un front-end alternatif à YouTube",
 | 
			
		||||
  "JavaScript license information": "Informations sur les licences JavaScript",
 | 
			
		||||
  "source": "source",
 | 
			
		||||
  "Login": "Connexion",
 | 
			
		||||
  "Login/Register": "Connexion/S'inscrire",
 | 
			
		||||
  "Login to Google": "Se connecter à Google",
 | 
			
		||||
  "Login": "Se connecter",
 | 
			
		||||
  "Login/Register": "Se connecter/Créer un compte",
 | 
			
		||||
  "Login to Google": "Se connecter avec Google",
 | 
			
		||||
  "User ID:": "Identifiant utilisateur :",
 | 
			
		||||
  "Password:": "Mot de passe :",
 | 
			
		||||
  "Time (h:mm:ss):": "Heure (h:mm:ss) :",
 | 
			
		||||
  "Text CAPTCHA": "CAPTCHA Texte",
 | 
			
		||||
  "Image CAPTCHA": "CAPTCHA Image",
 | 
			
		||||
  "Sign In": "S'identifier",
 | 
			
		||||
  "Sign In": "Se connecter",
 | 
			
		||||
  "Register": "S'inscrire",
 | 
			
		||||
  "Email:": "E-mail :",
 | 
			
		||||
  "Google verification code:": "Code de vérification Google :",
 | 
			
		||||
  "Preferences": "Préférences",
 | 
			
		||||
  "Player preferences": "Préférences du Lecteur",
 | 
			
		||||
  "Player preferences": "Préférences du lecteur",
 | 
			
		||||
  "Always loop: ": "Lire en boucle : ",
 | 
			
		||||
  "Autoplay: ": "Lire Automatiquement : ",
 | 
			
		||||
  "Autoplay: ": "Lire automatiquement : ",
 | 
			
		||||
  "Autoplay next video: ": "Lire automatiquement la vidéo suivante : ",
 | 
			
		||||
  "Listen by default: ": "Audio Uniquement par défaut : ",
 | 
			
		||||
  "Proxy videos? ": "Souhaitez vous charger les vidéos à travers un proxy ?",
 | 
			
		||||
  "Listen by default: ": "Audio uniquement : ",
 | 
			
		||||
  "Proxy videos? ": "Charger les vidéos à travers un proxy ? ",
 | 
			
		||||
  "Default speed: ": "Vitesse par défaut : ",
 | 
			
		||||
  "Preferred video quality: ": "Qualité vidéo souhaitée : ",
 | 
			
		||||
  "Player volume: ": "Volume du lecteur : ",
 | 
			
		||||
  "Default comments: ": "Source des Commentaires : ",
 | 
			
		||||
  "Default captions: ": "Sous-titres principal : ",
 | 
			
		||||
  "Fallback captions: ": "Sous-titres secondaire : ",
 | 
			
		||||
  "Show related videos? ": "Voir les vidéos liées à ce sujet ? ",
 | 
			
		||||
  "Default comments: ": "Source des commentaires : ",
 | 
			
		||||
  "Default captions: ": "Sous-titres par défaut : ",
 | 
			
		||||
  "Fallback captions: ": "Fallback captions: ",
 | 
			
		||||
  "Show related videos? ": "Voir les vidéos liées ? ",
 | 
			
		||||
  "Visual preferences": "Préférences du site",
 | 
			
		||||
  "Dark mode: ": "Mode Sombre : ",
 | 
			
		||||
  "Thin mode: ": "Mode Simplifié : ",
 | 
			
		||||
@ -82,13 +82,13 @@
 | 
			
		||||
  "Watch history": "Historique de visionnage",
 | 
			
		||||
  "Delete account": "Supprimer votre compte",
 | 
			
		||||
  "Administrator preferences": "Préferences d'Administrateur",
 | 
			
		||||
  "Default homepage: ": "Page d'accueil par defaut :",
 | 
			
		||||
  "Feed menu: ": "Menu des Flux :",
 | 
			
		||||
  "Top enabled? ": "Top activé ?",
 | 
			
		||||
  "CAPTCHA enabled? ": "CAPTCHA activé ?",
 | 
			
		||||
  "Login enabled? ": "Connexion activé ?",
 | 
			
		||||
  "Registration enabled? ": "Inscription activé ?",
 | 
			
		||||
  "Report statistics? ": "Telemetrie activé ?",
 | 
			
		||||
  "Default homepage: ": "Page d'accueil par défaut : ",
 | 
			
		||||
  "Feed menu: ": "Menu des Flux : ",
 | 
			
		||||
  "Top enabled? ": "Top activé ? ",
 | 
			
		||||
  "CAPTCHA enabled? ": "CAPTCHA activé ? ",
 | 
			
		||||
  "Login enabled? ": "Connexion activé ? ",
 | 
			
		||||
  "Registration enabled? ": "Inscription activée ? ",
 | 
			
		||||
  "Report statistics? ": "Télémétrie activé ? ",
 | 
			
		||||
  "Save preferences": "Enregistrer les préférences",
 | 
			
		||||
  "Subscription manager": "Gestionnaire d'abonnement",
 | 
			
		||||
  "`x` subscriptions": "`x` abonnements",
 | 
			
		||||
@ -103,16 +103,18 @@
 | 
			
		||||
  "View JavaScript license information.": "Voir les informations des licences JavaScript.",
 | 
			
		||||
  "View privacy policy.": "Politique de confidentialité",
 | 
			
		||||
  "Trending": "Tendances",
 | 
			
		||||
  "Unlisted": "Non répertoriée",
 | 
			
		||||
  "Watch video on Youtube": "Voir la vidéo sur Youtube",
 | 
			
		||||
  "Genre: ": "Genre : ",
 | 
			
		||||
  "License: ": "Licence : ",
 | 
			
		||||
  "Family friendly? ": "Tout Public ? ",
 | 
			
		||||
  "Wilson score: ": "Score de Wilson : ",
 | 
			
		||||
  "Engagement: ": "Poucentage de spectateur aillant aimé Liker ou Disliker la vidéo : ",
 | 
			
		||||
  "Engagement: ": "Poucentage de spectateur aillant aimé Like ou Dislike la vidéo : ",
 | 
			
		||||
  "Whitelisted regions: ": "Régions en liste blanche : ",
 | 
			
		||||
  "Blacklisted regions: ": "Régions sur liste noire : ",
 | 
			
		||||
  "Shared `x`": "Partagée `x`",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Il semblerait que JavaScript sois désactivé. Cliquez ici pour voir les commentaires. Gardez à l'esprit que le chargement peut prendre plus de temps.",
 | 
			
		||||
  "Shared `x`": "Ajoutée le `x`",
 | 
			
		||||
  "Premieres in `x`": "Première dans `x`",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Il semblerait que JavaScript soit désactivé. Cliquez ici pour voir les commentaires sans. Gardez à l'esprit que le chargement peut prendre plus de temps.",
 | 
			
		||||
  "View YouTube comments": "Voir les commentaires YouTube",
 | 
			
		||||
  "View more comments on Reddit": "Voir plus de commentaires sur Reddit",
 | 
			
		||||
  "View `x` comments": "Voir `x` commentaires",
 | 
			
		||||
@ -124,13 +126,13 @@
 | 
			
		||||
  "Unable to login, make sure two-factor authentication (Authenticator or SMS) is enabled.": "Si vous ne parvenez pas à vous connecter, assurez-vous que l'authentification à deux facteurs (Authenticator ou SMS) est activée.",
 | 
			
		||||
  "Invalid TFA code": "Code d'authentification à deux facteurs invalide",
 | 
			
		||||
  "Login failed. This may be because two-factor authentication is not enabled on your account.": "La connexion a échoué. Cela peut être dû au fait que l'authentification à deux facteurs n'est pas activée sur votre compte.",
 | 
			
		||||
  "Invalid answer": "Réponse non valide",
 | 
			
		||||
  "Invalid answer": "Réponse invalide",
 | 
			
		||||
  "Invalid CAPTCHA": "CAPTCHA invalide",
 | 
			
		||||
  "CAPTCHA is a required field": "Veuillez rentrez un CAPTCHA",
 | 
			
		||||
  "User ID is a required field": "Veuillez rentrez un Identifiant Utilisateur",
 | 
			
		||||
  "Password is a required field": "Veuillez rentrez un Mot de passe",
 | 
			
		||||
  "CAPTCHA is a required field": "Veuillez entrer un CAPTCHA",
 | 
			
		||||
  "User ID is a required field": "Veuillez entrer un Identifiant Utilisateur",
 | 
			
		||||
  "Password is a required field": "Veuillez entrer un Mot de passe",
 | 
			
		||||
  "Invalid username or password": "Nom d'utilisateur ou mot de passe invalide",
 | 
			
		||||
  "Please sign in using 'Sign in with Google'": "Veuillez vous connecter en utilisant \"S'identifier avec Google\"",
 | 
			
		||||
  "Please sign in using 'Sign in with Google'": "Veuillez vous connecter en utilisant \"Se connecter avec Google\"",
 | 
			
		||||
  "Password cannot be empty": "Le mot de passe ne peut pas être vide",
 | 
			
		||||
  "Password cannot be longer than 55 characters": "Le mot de passe ne doit pas comporter plus de 55 caractères",
 | 
			
		||||
  "Please sign in": "Veuillez vous connecter",
 | 
			
		||||
@ -268,7 +270,7 @@
 | 
			
		||||
  "`x` hours": "`x` heures",
 | 
			
		||||
  "`x` minutes": "`x` minutes",
 | 
			
		||||
  "`x` seconds": "`x` secondes",
 | 
			
		||||
  "Fallback comments: ": "Commentaires secondaires : ",
 | 
			
		||||
  "Fallback comments: ": "Fallback comments: ",
 | 
			
		||||
  "Popular": "Populaire",
 | 
			
		||||
  "Top": "Top",
 | 
			
		||||
  "About": "A Propos",
 | 
			
		||||
@ -289,5 +291,5 @@
 | 
			
		||||
  "Video mode": "Mode Vidéo",
 | 
			
		||||
  "Videos": "Vidéos",
 | 
			
		||||
  "Playlists": "Liste de lecture",
 | 
			
		||||
  "Current version: ": "Version actuelle :"
 | 
			
		||||
  "Current version: ": "Version :"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -103,6 +103,7 @@
 | 
			
		||||
  "View JavaScript license information.": "Guarda le informazioni di licenza del codice JavaScript.",
 | 
			
		||||
  "View privacy policy.": "",
 | 
			
		||||
  "Trending": "Tendenze",
 | 
			
		||||
  "Unlisted": "",
 | 
			
		||||
  "Watch video on Youtube": "Guarda il video su YouTube",
 | 
			
		||||
  "Genre: ": "Genere: ",
 | 
			
		||||
  "License: ": "Licenza: ",
 | 
			
		||||
@ -112,6 +113,7 @@
 | 
			
		||||
  "Whitelisted regions: ": "Regioni nella lista bianca: ",
 | 
			
		||||
  "Blacklisted regions: ": "Regioni nella lista nera: ",
 | 
			
		||||
  "Shared `x`": "Condiviso `x`",
 | 
			
		||||
  "Premieres in `x`": "",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Ciao! Sembra che tu abbia disattivato JavaScript. Clicca qui per visualizzare i commenti. Considera che potrebbe volerci più tempo.",
 | 
			
		||||
  "View YouTube comments": "Visualizza i commenti da YouTube",
 | 
			
		||||
  "View more comments on Reddit": "Visualizza più commenti su Reddit",
 | 
			
		||||
 | 
			
		||||
@ -103,6 +103,7 @@
 | 
			
		||||
  "View JavaScript license information.": "Vis JavaScript-lisensinfo.",
 | 
			
		||||
  "View privacy policy.": "",
 | 
			
		||||
  "Trending": "Trendsettende",
 | 
			
		||||
  "Unlisted": "",
 | 
			
		||||
  "Watch video on Youtube": "Vis video på YouTube",
 | 
			
		||||
  "Genre: ": "Sjanger: ",
 | 
			
		||||
  "License: ": "Lisens: ",
 | 
			
		||||
@ -112,6 +113,7 @@
 | 
			
		||||
  "Whitelisted regions: ": "Hvitlistede regioner: ",
 | 
			
		||||
  "Blacklisted regions: ": "Svartelistede regioner: ",
 | 
			
		||||
  "Shared `x`": "Delt `x`",
 | 
			
		||||
  "Premieres in `x`": "",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hei. Det ser ut til at du har JavaScript avslått. Klikk her for å vise kommentarer, ha i minnet at innlasting tar lengre tid.",
 | 
			
		||||
  "View YouTube comments": "Vis YouTube-kommentarer",
 | 
			
		||||
  "View more comments on Reddit": "Vis flere kommenterer på Reddit",
 | 
			
		||||
 | 
			
		||||
@ -103,6 +103,7 @@
 | 
			
		||||
  "View JavaScript license information.": "Bekijk JavaScript licentie informatie.",
 | 
			
		||||
  "View privacy policy.": "",
 | 
			
		||||
  "Trending": "Trending",
 | 
			
		||||
  "Unlisted": "",
 | 
			
		||||
  "Watch video on Youtube": "Bekijk video op Youtube",
 | 
			
		||||
  "Genre: ": "Genre: ",
 | 
			
		||||
  "License: ": "Licentie: ",
 | 
			
		||||
@ -112,6 +113,7 @@
 | 
			
		||||
  "Whitelisted regions: ": "Toegestane regio's: ",
 | 
			
		||||
  "Blacklisted regions: ": "Geblokkeerde regio's: ",
 | 
			
		||||
  "Shared `x`": "`x` gedeeld",
 | 
			
		||||
  "Premieres in `x`": "",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Hoi! Het lijkt erop dat je JavaScript uit hebt staan. Klik hier om de reacties te bekijken, hou er rekening mee dat het wat langer duurt om te laden.",
 | 
			
		||||
  "View YouTube comments": "Bekijk YouTube reacties",
 | 
			
		||||
  "View more comments on Reddit": "Bekijk meer reacties op Reddit",
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@
 | 
			
		||||
  "newest": "najnowsze",
 | 
			
		||||
  "oldest": "najstarsze",
 | 
			
		||||
  "popular": "popularne",
 | 
			
		||||
  "last": "",
 | 
			
		||||
  "last": "ostatnie",
 | 
			
		||||
  "Next page": "Następna strona",
 | 
			
		||||
  "Previous page": "Poprzednia strona",
 | 
			
		||||
  "Clear watch history?": "Wyczyścić historię?",
 | 
			
		||||
@ -50,7 +50,7 @@
 | 
			
		||||
  "Autoplay: ": "Autoodtwarzanie: ",
 | 
			
		||||
  "Autoplay next video: ": "Odtwórz następny film: ",
 | 
			
		||||
  "Listen by default: ": "Tryb dźwiękowy: ",
 | 
			
		||||
  "Proxy videos? ": "",
 | 
			
		||||
  "Proxy videos? ": "Filmy przez proxy? ",
 | 
			
		||||
  "Default speed: ": "Domyślna prędkość: ",
 | 
			
		||||
  "Preferred video quality: ": "Preferowana jakość filmów: ",
 | 
			
		||||
  "Player volume: ": "Głośność odtwarzacza: ",
 | 
			
		||||
@ -101,8 +101,9 @@
 | 
			
		||||
  "Released under the AGPLv3 by Omar Roth.": "Wydano na licencji AGPLv3 przez Omar Roth.",
 | 
			
		||||
  "Source available here.": "Kod źródłowy dostępny tutaj.",
 | 
			
		||||
  "View JavaScript license information.": "Wyświetl informację o licencji JavaScript.",
 | 
			
		||||
  "View privacy policy.": "",
 | 
			
		||||
  "View privacy policy.": "Polityka prywatności.",
 | 
			
		||||
  "Trending": "Na czasie",
 | 
			
		||||
  "Unlisted": "",
 | 
			
		||||
  "Watch video on Youtube": "Zobacz film na YouTube",
 | 
			
		||||
  "Genre: ": "Gatunek: ",
 | 
			
		||||
  "License: ": "Licencja: ",
 | 
			
		||||
@ -112,6 +113,7 @@
 | 
			
		||||
  "Whitelisted regions: ": "Dostępny na obszarach: ",
 | 
			
		||||
  "Blacklisted regions: ": "Niedostępny na obszarach: ",
 | 
			
		||||
  "Shared `x`": "Udostępniono `x`",
 | 
			
		||||
  "Premieres in `x`": "",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Cześć! Wygląda na to, że masz wyłączoną obsługę JavaScriptu. Kliknij tutaj, żeby zobaczyć komentarze. Pamiętaj, że wczytywanie może potrwać dłużej.",
 | 
			
		||||
  "View YouTube comments": "Wyświetl komentarze z YouTube",
 | 
			
		||||
  "View more comments on Reddit": "Wyświetl więcej komentarzy na Reddicie",
 | 
			
		||||
@ -270,7 +272,7 @@
 | 
			
		||||
  "`x` seconds": "`x` sekund",
 | 
			
		||||
  "Fallback comments: ": "Zastępcze komentarze: ",
 | 
			
		||||
  "Popular": "Popularne",
 | 
			
		||||
  "Top": "Na czasie",
 | 
			
		||||
  "Top": "Najczęściej oglądane",
 | 
			
		||||
  "About": "Informacje",
 | 
			
		||||
  "Rating: ": "Ocena: ",
 | 
			
		||||
  "Language: ": "Język: ",
 | 
			
		||||
 | 
			
		||||
@ -105,6 +105,7 @@
 | 
			
		||||
  "View JavaScript license information.": "Посмотреть лицензии JavaScript кода.",
 | 
			
		||||
  "View privacy policy.": "См. политику конфиденциальности.",
 | 
			
		||||
  "Trending": "В тренде",
 | 
			
		||||
  "Unlisted": "",
 | 
			
		||||
  "Watch video on Youtube": "Смотреть на YouTube",
 | 
			
		||||
  "Genre: ": "Жанр: ",
 | 
			
		||||
  "License: ": "Лицензия: ",
 | 
			
		||||
@ -114,6 +115,7 @@
 | 
			
		||||
  "Whitelisted regions: ": "Доступно для: ",
 | 
			
		||||
  "Blacklisted regions: ": "Недоступно для: ",
 | 
			
		||||
  "Shared `x`": "Опубликовано `x`",
 | 
			
		||||
  "Premieres in `x`": "",
 | 
			
		||||
  "Hi! Looks like you have JavaScript disabled. Click here to view comments, keep in mind it may take a bit longer to load.": "Похоже, что у Вас отключен JavaScript. Нажмите сюда, чтобы увидеть комментарии (учтите, что они могут загружаться дольше).",
 | 
			
		||||
  "View YouTube comments": "Смотреть комментарии с YouTube",
 | 
			
		||||
  "View more comments on Reddit": "Больше комментариев на Reddit",
 | 
			
		||||
 | 
			
		||||
@ -242,6 +242,9 @@ get "/api/v1/comments/:id" do |env|
 | 
			
		||||
  source = env.params.query["source"]?
 | 
			
		||||
  source ||= "youtube"
 | 
			
		||||
 | 
			
		||||
  thin_mode = env.params.query["thin_mode"]?
 | 
			
		||||
  thin_mode = thin_mode == "true"
 | 
			
		||||
 | 
			
		||||
  format = env.params.query["format"]?
 | 
			
		||||
  format ||= "json"
 | 
			
		||||
 | 
			
		||||
@ -249,7 +252,7 @@ get "/api/v1/comments/:id" do |env|
 | 
			
		||||
 | 
			
		||||
  if source == "youtube"
 | 
			
		||||
    begin
 | 
			
		||||
      comments = fetch_youtube_comments(id, continuation, proxies, format, locale, region)
 | 
			
		||||
      comments = fetch_youtube_comments(id, continuation, proxies, format, locale, thin_mode, region)
 | 
			
		||||
    rescue ex
 | 
			
		||||
      error_message = {"error" => ex.message}.to_json
 | 
			
		||||
      env.response.status_code = 500
 | 
			
		||||
@ -1688,6 +1691,11 @@ get "/videoplayback" do |env|
 | 
			
		||||
  fvip = query_params["fvip"]? || "3"
 | 
			
		||||
  mns = query_params["mn"].split(",")
 | 
			
		||||
 | 
			
		||||
  if query_params["region"]?
 | 
			
		||||
    region = query_params["region"]
 | 
			
		||||
    query_params.delete("region")
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  if query_params["host"]? && !query_params["host"].empty?
 | 
			
		||||
    host = "https://#{query_params["host"]}"
 | 
			
		||||
    query_params.delete("host")
 | 
			
		||||
@ -1704,8 +1712,6 @@ get "/videoplayback" do |env|
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  region = query_params["region"]?
 | 
			
		||||
 | 
			
		||||
  response = HTTP::Client::Response.new(403)
 | 
			
		||||
  5.times do
 | 
			
		||||
    begin
 | 
			
		||||
@ -1725,9 +1731,12 @@ get "/videoplayback" do |env|
 | 
			
		||||
 | 
			
		||||
  if response.headers["Location"]?
 | 
			
		||||
    url = URI.parse(response.headers["Location"])
 | 
			
		||||
    host = url.host
 | 
			
		||||
    env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
			
		||||
 | 
			
		||||
    url = url.full_path
 | 
			
		||||
    url += "&host=#{host}"
 | 
			
		||||
 | 
			
		||||
    if region
 | 
			
		||||
      url += "®ion=#{region}"
 | 
			
		||||
    end
 | 
			
		||||
@ -1744,15 +1753,30 @@ get "/videoplayback" do |env|
 | 
			
		||||
  client.get(url, headers) do |response|
 | 
			
		||||
    env.response.status_code = response.status_code
 | 
			
		||||
 | 
			
		||||
    if title = env.params.query["title"]?
 | 
			
		||||
      # https://blog.fastmail.com/2011/06/24/download-non-english-filenames/
 | 
			
		||||
      env.response.headers["Content-Disposition"] = "attachment; filename=\"#{URI.escape(title)}\"; filename*=UTF-8''#{URI.escape(title)}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    response.headers.each do |key, value|
 | 
			
		||||
      env.response.headers[key] = value
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if response.headers["Location"]?
 | 
			
		||||
      url = URI.parse(response.headers["Location"])
 | 
			
		||||
      host = url.host
 | 
			
		||||
      env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
			
		||||
 | 
			
		||||
      url = url.full_path
 | 
			
		||||
      url += "&host=#{host}"
 | 
			
		||||
 | 
			
		||||
      if region
 | 
			
		||||
        url += "®ion=#{region}"
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      next env.redirect url
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if title = query_params["title"]?
 | 
			
		||||
      # https://blog.fastmail.com/2011/06/24/download-non-english-filenames/
 | 
			
		||||
      env.response.headers["Content-Disposition"] = "attachment; filename=\"#{URI.escape(title)}\"; filename*=UTF-8''#{URI.escape(title)}"
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    env.response.headers["Access-Control-Allow-Origin"] = "*"
 | 
			
		||||
 | 
			
		||||
    begin
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
class InvidiousChannel
 | 
			
		||||
struct InvidiousChannel
 | 
			
		||||
  add_mapping({
 | 
			
		||||
    id:         String,
 | 
			
		||||
    author:     String,
 | 
			
		||||
@ -8,7 +8,7 @@ class InvidiousChannel
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class ChannelVideo
 | 
			
		||||
struct ChannelVideo
 | 
			
		||||
  add_mapping({
 | 
			
		||||
    id:                 String,
 | 
			
		||||
    title:              String,
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@ class RedditComment
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class RedditLink
 | 
			
		||||
struct RedditLink
 | 
			
		||||
  JSON.mapping({
 | 
			
		||||
    author:       String,
 | 
			
		||||
    score:        Int32,
 | 
			
		||||
@ -41,7 +41,7 @@ class RedditLink
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class RedditMore
 | 
			
		||||
struct RedditMore
 | 
			
		||||
  JSON.mapping({
 | 
			
		||||
    children: Array(String),
 | 
			
		||||
    count:    Int32,
 | 
			
		||||
@ -56,7 +56,7 @@ class RedditListing
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def fetch_youtube_comments(id, continuation, proxies, format, locale, region)
 | 
			
		||||
def fetch_youtube_comments(id, continuation, proxies, format, locale, thin_mode, region)
 | 
			
		||||
  video = fetch_video(id, proxies, region: region)
 | 
			
		||||
 | 
			
		||||
  session_token = video.info["session_token"]?
 | 
			
		||||
@ -232,7 +232,7 @@ def fetch_youtube_comments(id, continuation, proxies, format, locale, region)
 | 
			
		||||
 | 
			
		||||
  if format == "html"
 | 
			
		||||
    comments = JSON.parse(comments)
 | 
			
		||||
    content_html = template_youtube_comments(comments, locale)
 | 
			
		||||
    content_html = template_youtube_comments(comments, locale, thin_mode)
 | 
			
		||||
 | 
			
		||||
    comments = JSON.build do |json|
 | 
			
		||||
      json.object do
 | 
			
		||||
@ -278,7 +278,7 @@ def fetch_reddit_comments(id)
 | 
			
		||||
  return comments, thread
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
def template_youtube_comments(comments, locale)
 | 
			
		||||
def template_youtube_comments(comments, locale, thin_mode)
 | 
			
		||||
  html = ""
 | 
			
		||||
 | 
			
		||||
  root = comments["comments"].as_a
 | 
			
		||||
@ -297,7 +297,11 @@ def template_youtube_comments(comments, locale)
 | 
			
		||||
      END_HTML
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if !thin_mode
 | 
			
		||||
      author_thumbnail = "/ggpht#{URI.parse(child["authorThumbnails"][-1]["url"].as_s).full_path}"
 | 
			
		||||
    else
 | 
			
		||||
      author_thumbnail = ""
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    html += <<-END_HTML
 | 
			
		||||
    <div class="pure-g">
 | 
			
		||||
@ -318,7 +322,12 @@ def template_youtube_comments(comments, locale)
 | 
			
		||||
    END_HTML
 | 
			
		||||
 | 
			
		||||
    if child["creatorHeart"]?
 | 
			
		||||
      if !thin_mode
 | 
			
		||||
        creator_thumbnail = "/ggpht#{URI.parse(child["creatorHeart"]["creatorThumbnail"].as_s).full_path}"
 | 
			
		||||
      else
 | 
			
		||||
        creator_thumbnail = ""
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      html += <<-END_HTML
 | 
			
		||||
          <span class="creator-heart-container" title="#{translate(locale, "`x` marked it with a ❤", child["creatorHeart"]["creatorName"].as_s)}">
 | 
			
		||||
              <div class="creator-heart">
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
class Config
 | 
			
		||||
struct Config
 | 
			
		||||
  YAML.mapping({
 | 
			
		||||
    channel_threads: Int32,      # Number of threads to use for crawling videos from channels (for updating subscriptions)
 | 
			
		||||
    feed_threads:    Int32,      # Number of threads to use for updating feeds
 | 
			
		||||
 | 
			
		||||
@ -9,6 +9,17 @@ macro add_mapping(mapping)
 | 
			
		||||
    DB.mapping({{mapping}})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
macro json_mapping(mapping)
 | 
			
		||||
    def initialize({{*mapping.keys.map { |id| "@#{id}".id }}})
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def to_a
 | 
			
		||||
        return [{{*mapping.keys.map { |id| "@#{id}".id }}}]
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    JSON.mapping({{mapping}})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
macro templated(filename, template = "template")
 | 
			
		||||
    render "src/invidious/views/#{{{filename}}}.ecr", "src/invidious/views/#{{{template}}}.ecr"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
@ -106,7 +106,7 @@ def subscribe_to_feeds(db, logger, key, config)
 | 
			
		||||
  if config.use_pubsub_feeds
 | 
			
		||||
    spawn do
 | 
			
		||||
      loop do
 | 
			
		||||
        db.query_all("SELECT id FROM channels WHERE CURRENT_TIMESTAMP - subscribed > '4 days'") do |rs|
 | 
			
		||||
        db.query_all("SELECT id FROM channels WHERE CURRENT_TIMESTAMP - subscribed > '4 days' OR subscribed IS NULL") do |rs|
 | 
			
		||||
          rs.each do
 | 
			
		||||
            ucid = rs.read(String)
 | 
			
		||||
            response = subscribe_pubsub(ucid, key, config)
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
class MixVideo
 | 
			
		||||
struct MixVideo
 | 
			
		||||
  add_mapping({
 | 
			
		||||
    title:          String,
 | 
			
		||||
    id:             String,
 | 
			
		||||
@ -10,7 +10,7 @@ class MixVideo
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Mix
 | 
			
		||||
struct Mix
 | 
			
		||||
  add_mapping({
 | 
			
		||||
    title:  String,
 | 
			
		||||
    id:     String,
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
class PlaylistVideo
 | 
			
		||||
struct PlaylistVideo
 | 
			
		||||
  add_mapping({
 | 
			
		||||
    title:          String,
 | 
			
		||||
    id:             String,
 | 
			
		||||
@ -12,7 +12,7 @@ class PlaylistVideo
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Playlist
 | 
			
		||||
struct Playlist
 | 
			
		||||
  add_mapping({
 | 
			
		||||
    title:            String,
 | 
			
		||||
    id:               String,
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
class SearchVideo
 | 
			
		||||
struct SearchVideo
 | 
			
		||||
  add_mapping({
 | 
			
		||||
    title:              String,
 | 
			
		||||
    id:                 String,
 | 
			
		||||
@ -16,7 +16,7 @@ class SearchVideo
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class SearchPlaylistVideo
 | 
			
		||||
struct SearchPlaylistVideo
 | 
			
		||||
  add_mapping({
 | 
			
		||||
    title:          String,
 | 
			
		||||
    id:             String,
 | 
			
		||||
@ -24,7 +24,7 @@ class SearchPlaylistVideo
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class SearchPlaylist
 | 
			
		||||
struct SearchPlaylist
 | 
			
		||||
  add_mapping({
 | 
			
		||||
    title:        String,
 | 
			
		||||
    id:           String,
 | 
			
		||||
@ -36,7 +36,7 @@ class SearchPlaylist
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class SearchChannel
 | 
			
		||||
struct SearchChannel
 | 
			
		||||
  add_mapping({
 | 
			
		||||
    author:           String,
 | 
			
		||||
    ucid:             String,
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,12 @@
 | 
			
		||||
require "crypto/bcrypt/password"
 | 
			
		||||
 | 
			
		||||
class User
 | 
			
		||||
struct User
 | 
			
		||||
  module PreferencesConverter
 | 
			
		||||
    def self.from_rs(rs)
 | 
			
		||||
      begin
 | 
			
		||||
        Preferences.from_json(rs.read(String))
 | 
			
		||||
      rescue ex
 | 
			
		||||
        DEFAULT_USER_PREFERENCES
 | 
			
		||||
        Preferences.from_json("{}")
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
@ -18,7 +18,6 @@ class User
 | 
			
		||||
    email:         String,
 | 
			
		||||
    preferences:   {
 | 
			
		||||
      type:      Preferences,
 | 
			
		||||
      default:   DEFAULT_USER_PREFERENCES,
 | 
			
		||||
      converter: PreferencesConverter,
 | 
			
		||||
    },
 | 
			
		||||
    password: String?,
 | 
			
		||||
@ -27,30 +26,30 @@ class User
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
DEFAULT_USER_PREFERENCES = Preferences.from_json({
 | 
			
		||||
  "video_loop"         => false,
 | 
			
		||||
  "autoplay"           => false,
 | 
			
		||||
  "continue"           => false,
 | 
			
		||||
  "local"              => false,
 | 
			
		||||
  "listen"             => false,
 | 
			
		||||
  "speed"              => 1.0,
 | 
			
		||||
  "quality"            => "hd720",
 | 
			
		||||
  "volume"             => 100,
 | 
			
		||||
  "comments"           => ["youtube", ""],
 | 
			
		||||
  "captions"           => ["", "", ""],
 | 
			
		||||
  "related_videos"     => true,
 | 
			
		||||
  "redirect_feed"      => false,
 | 
			
		||||
  "locale"             => "en-US",
 | 
			
		||||
  "dark_mode"          => false,
 | 
			
		||||
  "thin_mode"          => false,
 | 
			
		||||
  "max_results"        => 40,
 | 
			
		||||
  "sort"               => "published",
 | 
			
		||||
  "latest_only"        => false,
 | 
			
		||||
  "unseen_only"        => false,
 | 
			
		||||
  "notifications_only" => false,
 | 
			
		||||
}.to_json)
 | 
			
		||||
DEFAULT_USER_PREFERENCES = Preferences.new(
 | 
			
		||||
  video_loop: false,
 | 
			
		||||
  autoplay: false,
 | 
			
		||||
  continue: false,
 | 
			
		||||
  local: false,
 | 
			
		||||
  listen: false,
 | 
			
		||||
  speed: 1.0_f32,
 | 
			
		||||
  quality: "hd720",
 | 
			
		||||
  volume: 100,
 | 
			
		||||
  comments: ["youtube", ""],
 | 
			
		||||
  captions: ["", "", ""],
 | 
			
		||||
  related_videos: true,
 | 
			
		||||
  redirect_feed: false,
 | 
			
		||||
  locale: "en-US",
 | 
			
		||||
  dark_mode: false,
 | 
			
		||||
  thin_mode: false,
 | 
			
		||||
  max_results: 40,
 | 
			
		||||
  sort: "published",
 | 
			
		||||
  latest_only: false,
 | 
			
		||||
  unseen_only: false,
 | 
			
		||||
  notifications_only: false,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
class Preferences
 | 
			
		||||
struct Preferences
 | 
			
		||||
  module StringToArray
 | 
			
		||||
    def self.to_json(value : Array(String), json : JSON::Builder)
 | 
			
		||||
      json.array do
 | 
			
		||||
@ -74,58 +73,27 @@ class Preferences
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  JSON.mapping({
 | 
			
		||||
    video_loop: Bool,
 | 
			
		||||
    autoplay:   Bool,
 | 
			
		||||
    continue:   {
 | 
			
		||||
      type:    Bool,
 | 
			
		||||
      default: DEFAULT_USER_PREFERENCES.continue,
 | 
			
		||||
    },
 | 
			
		||||
    local: {
 | 
			
		||||
      type:    Bool,
 | 
			
		||||
      default: DEFAULT_USER_PREFERENCES.local,
 | 
			
		||||
    },
 | 
			
		||||
    listen: {
 | 
			
		||||
      type:    Bool,
 | 
			
		||||
      default: DEFAULT_USER_PREFERENCES.listen,
 | 
			
		||||
    },
 | 
			
		||||
    speed:    Float32,
 | 
			
		||||
    quality:  String,
 | 
			
		||||
    volume:   Int32,
 | 
			
		||||
    comments: {
 | 
			
		||||
      type:      Array(String),
 | 
			
		||||
      default:   DEFAULT_USER_PREFERENCES.comments,
 | 
			
		||||
      converter: StringToArray,
 | 
			
		||||
    },
 | 
			
		||||
    captions: {
 | 
			
		||||
      type:    Array(String),
 | 
			
		||||
      default: DEFAULT_USER_PREFERENCES.captions,
 | 
			
		||||
    },
 | 
			
		||||
    redirect_feed: {
 | 
			
		||||
      type:    Bool,
 | 
			
		||||
      default: DEFAULT_USER_PREFERENCES.redirect_feed,
 | 
			
		||||
    },
 | 
			
		||||
    related_videos: {
 | 
			
		||||
      type:    Bool,
 | 
			
		||||
      default: DEFAULT_USER_PREFERENCES.related_videos,
 | 
			
		||||
    },
 | 
			
		||||
    dark_mode: Bool,
 | 
			
		||||
    thin_mode: {
 | 
			
		||||
      type:    Bool,
 | 
			
		||||
      default: DEFAULT_USER_PREFERENCES.thin_mode,
 | 
			
		||||
    },
 | 
			
		||||
    max_results:        Int32,
 | 
			
		||||
    sort:               String,
 | 
			
		||||
    latest_only:        Bool,
 | 
			
		||||
    unseen_only:        Bool,
 | 
			
		||||
    notifications_only: {
 | 
			
		||||
      type:    Bool,
 | 
			
		||||
      default: DEFAULT_USER_PREFERENCES.notifications_only,
 | 
			
		||||
    },
 | 
			
		||||
    locale: {
 | 
			
		||||
      type:    String,
 | 
			
		||||
      default: DEFAULT_USER_PREFERENCES.locale,
 | 
			
		||||
    },
 | 
			
		||||
  json_mapping({
 | 
			
		||||
    video_loop:         {type: Bool, default: DEFAULT_USER_PREFERENCES.video_loop},
 | 
			
		||||
    autoplay:           {type: Bool, default: DEFAULT_USER_PREFERENCES.autoplay},
 | 
			
		||||
    continue:           {type: Bool, default: DEFAULT_USER_PREFERENCES.continue},
 | 
			
		||||
    local:              {type: Bool, default: DEFAULT_USER_PREFERENCES.local},
 | 
			
		||||
    listen:             {type: Bool, default: DEFAULT_USER_PREFERENCES.listen},
 | 
			
		||||
    speed:              {type: Float32, default: DEFAULT_USER_PREFERENCES.speed},
 | 
			
		||||
    quality:            {type: String, default: DEFAULT_USER_PREFERENCES.quality},
 | 
			
		||||
    volume:             {type: Int32, default: DEFAULT_USER_PREFERENCES.volume},
 | 
			
		||||
    comments:           {type: Array(String), default: DEFAULT_USER_PREFERENCES.comments, converter: StringToArray},
 | 
			
		||||
    captions:           {type: Array(String), default: DEFAULT_USER_PREFERENCES.captions, converter: StringToArray},
 | 
			
		||||
    redirect_feed:      {type: Bool, default: DEFAULT_USER_PREFERENCES.redirect_feed},
 | 
			
		||||
    related_videos:     {type: Bool, default: DEFAULT_USER_PREFERENCES.related_videos},
 | 
			
		||||
    dark_mode:          {type: Bool, default: DEFAULT_USER_PREFERENCES.dark_mode},
 | 
			
		||||
    thin_mode:          {type: Bool, default: DEFAULT_USER_PREFERENCES.thin_mode},
 | 
			
		||||
    max_results:        {type: Int32, default: DEFAULT_USER_PREFERENCES.max_results},
 | 
			
		||||
    sort:               {type: String, default: DEFAULT_USER_PREFERENCES.sort},
 | 
			
		||||
    latest_only:        {type: Bool, default: DEFAULT_USER_PREFERENCES.latest_only},
 | 
			
		||||
    unseen_only:        {type: Bool, default: DEFAULT_USER_PREFERENCES.unseen_only},
 | 
			
		||||
    notifications_only: {type: Bool, default: DEFAULT_USER_PREFERENCES.notifications_only},
 | 
			
		||||
    locale:             {type: String, default: DEFAULT_USER_PREFERENCES.locale},
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -241,7 +241,7 @@ VIDEO_FORMATS = {
 | 
			
		||||
  "251" => {"ext" => "webm", "format" => "DASH audio", "acodec" => "opus", "abr" => 160},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Video
 | 
			
		||||
struct Video
 | 
			
		||||
  property player_json : JSON::Any?
 | 
			
		||||
 | 
			
		||||
  module HTTPParamConverter
 | 
			
		||||
@ -251,7 +251,7 @@ class Video
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def allow_ratings
 | 
			
		||||
    allow_ratings = player_response["videoDetails"].try &.["allowRatings"]?.try &.as_bool
 | 
			
		||||
    allow_ratings = player_response["videoDetails"]?.try &.["allowRatings"]?.try &.as_bool
 | 
			
		||||
 | 
			
		||||
    if allow_ratings.nil?
 | 
			
		||||
      return true
 | 
			
		||||
@ -271,7 +271,7 @@ class Video
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def is_listed
 | 
			
		||||
    is_listed = player_response["videoDetails"].try &.["isCrawlable"]?.try &.as_bool
 | 
			
		||||
    is_listed = player_response["videoDetails"]?.try &.["isCrawlable"]?.try &.as_bool
 | 
			
		||||
 | 
			
		||||
    if is_listed.nil?
 | 
			
		||||
      return true
 | 
			
		||||
@ -281,7 +281,7 @@ class Video
 | 
			
		||||
  end
 | 
			
		||||
 | 
			
		||||
  def is_upcoming
 | 
			
		||||
    is_upcoming = player_response["videoDetails"].try &.["isUpcoming"]?.try &.as_bool
 | 
			
		||||
    is_upcoming = player_response["videoDetails"]?.try &.["isUpcoming"]?.try &.as_bool
 | 
			
		||||
 | 
			
		||||
    if is_upcoming.nil?
 | 
			
		||||
      return false
 | 
			
		||||
@ -297,7 +297,7 @@ class Video
 | 
			
		||||
          .try &.["liveStreamabilityRenderer"]?
 | 
			
		||||
            .try &.["offlineSlate"]?
 | 
			
		||||
              .try &.["liveStreamOfflineSlateRenderer"]?
 | 
			
		||||
                .try &.["scheduledStartTime"].as_s.to_i64
 | 
			
		||||
                .try &.["scheduledStartTime"]?.try &.as_s.to_i64
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if premiere_timestamp
 | 
			
		||||
@ -549,7 +549,7 @@ class Video
 | 
			
		||||
  })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class Caption
 | 
			
		||||
struct Caption
 | 
			
		||||
  JSON.mapping(
 | 
			
		||||
    name: CaptionName,
 | 
			
		||||
    baseUrl: String,
 | 
			
		||||
@ -557,7 +557,7 @@ class Caption
 | 
			
		||||
  )
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
class CaptionName
 | 
			
		||||
struct CaptionName
 | 
			
		||||
  JSON.mapping(
 | 
			
		||||
    simpleText: String,
 | 
			
		||||
  )
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user