Merge branch 'master' into api-only

This commit is contained in:
Omar Roth 2019-03-29 16:34:19 -05:00
commit 3d76898bb9
21 changed files with 483 additions and 451 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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": "",

View File

@ -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 :",
"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é ?",
"Report statistics? ": "Telemetrie 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 :"
}

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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: ",

View File

@ -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",

View File

@ -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 += "&region=#{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 += "&region=#{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

View File

@ -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,

View File

@ -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">

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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,
)