Merge pull request #571 from movie-web/dev

Version v4.1.1
This commit is contained in:
William Oldham 2023-12-21 20:33:23 +00:00 committed by GitHub
commit 040a054b13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 167 additions and 25 deletions

View File

@ -1,6 +1,6 @@
{
"name": "movie-web",
"version": "4.1.0",
"version": "4.1.1",
"private": true,
"homepage": "https://movie-web.app",
"scripts": {

View File

@ -86,7 +86,7 @@
"dmca": "DMCA",
"github": "غيت هاب"
},
"tagline": "شاهد عروضك وأفلامك المفضلة باستخدام البث تطبيق مفتوح المصدر هذا."
"tagline": "شاهد عروضك وأفلامك المفضلة باستخدام تطبيق البث مفتوح المصدر هذا."
},
"global": {
"name": "movie-web",
@ -157,7 +157,7 @@
},
"notFound": {
"badge": "صفحة غير موجودة",
"goHome": "العودة للصفحة الرئيسية",
"goHome": "عودة",
"message": "بحثنا في كل مكان: في الخزانة وحتى تحت الصناديق، ومع ذلك لم نعثر عن الصفحة التي طلبتَها.",
"title": "تعذر العثور على هته الصفحة"
},
@ -166,7 +166,7 @@
},
"player": {
"back": {
"default": ُدْ للصفحة الرئيسية",
"default": ودة",
"short": "عُدْ"
},
"casting": {
@ -305,7 +305,7 @@
},
"screens": {
"dmca": {
"text": "مرحبًا بكم في صفحة اتصال بقانون الألفية للملكية الرقمية (DMCA) الخاصة بـ movie-web! نحن نحترم حقوق الملكية الفكرية ونرغب في التعامل بسرعة مع أي قلق يتعلق بحقوق الطبع والنشر. إذا كنت تعتقد أن عملك المحمي بحقوق الطبع والنشر قد تم استخدامه بشكل غير لائق على منصتنا، يرجى إرسال إشعار DMCA مفصل إلى البريد الإلكتروني أدناه. يرجى تضمين وصف للمواد المحمية بحقوق الطبع والنشر، وتفاصيل الاتصال الخاصة بك، وبيان من النية الصادقة. نحن ملتزمون بحل هذه القضايا بسرعة ونقدر تعاونكم في الحفاظ على movie-web كمكان يحترم الإبداع وحقوق الطبع والنشر.",
"text": "مرحبًا بكم في صفحة movie-web الخاصة بالتواصل حول قانون الألفية للملكية الرقمية (DMCA) ! نحن نحترم حقوق الملكية الفكرية ونرغب في التعامل بسرعة مع أي مسألة تخص حقوق الطبع والنشر. إن كنت تعتقد أن أيا من أعمالك المحميو بحقوق الطبع والنشر قد تم استخدامها بشكل غير لائق على منصتنا، رجاءً أرسل إشعارا مفصلا إلى البريد الإلكتروني أدناه. يرجى تضمين وصف للمواد المحمية بحقوق الطبع والنشر، وكذا طريقةً للتواصل معك، إضافة إلى تصريح بمصداقية طلبك. نحن ملتزمون بحل هذه القضايا بسرعة ونقدر تعاونكم في الحفاظ على movie-web كمكان يحترم الإبداع وحقوق الطبع والنشر.",
"title": "DMCA"
},
"loadingApp": "جار تحميل التطبيق",

View File

@ -25,6 +25,7 @@
},
"generate": {
"title": "Your passphrase",
"passphraseFrameLabel": "Passphrase",
"next": "I have saved my passphrase",
"description": "Your passphrase acts as your username and password. Make sure to keep it safe as you will need to enter it to login to your account"
},

View File

@ -7,11 +7,11 @@
"title": "D'où vient le contenu ?"
},
"q2": {
"body": "Il n'est pas possible de demander une émission ou un film, movie-web ne gère aucun contenu. Tous les contenus sont consultés par l'intermédiaire de sources sur Internet.",
"title": "Où puis-je demander un show ou un film ?"
"body": "Il est impossible de solliciter une émission ou un film car movie-web ne gère aucun contenu. Les sources sur Internet sont utilisées pour consulter tous les contenus.",
"title": "Où puis-je demander une série ou un film ?"
},
"q3": {
"body": "Nos résultats de recherche sont fournis par The Movie Database (TMDB) et s'affichent indépendamment du fait que nos sources possèdent ou non le contenu.",
"body": "Nos résultats de recherche sont disponibles dans The Movie Database (TMDB), indépendamment du fait que nos sources possèdent ou non le contenu.",
"title": "Les résultats de la recherche affichent l'émission ou le film, pourquoi ne puis-je pas le lire ?"
},
"title": "A propos de movie-web"
@ -21,7 +21,7 @@
"copy": "Copier"
},
"auth": {
"createAccount": "Vous n'avez pas encore de compte ? <0>Créer un compte.</0>",
"createAccount": "N'avez-vous pas encore de compte? <0>Créer un compte.</0>",
"deviceNameLabel": "Nom de l'appareil",
"deviceNamePlaceholder": "Téléphone personnel",
"generate": {
@ -29,7 +29,7 @@
"next": "J'ai sauvegardé ma passphrase",
"title": "Votre passphrase"
},
"hasAccount": "Vous avez déjà un compte ? <0>Connectez-vous ici.</0>",
"hasAccount": "Avez-vous déjà un compte? <0>Connectez-vous ici.</0>",
"login": {
"description": "Veuillez entrer votre passphrase pour vous connecter à votre compte",
"deviceLengthError": "Veuillez saisir un nom d'appareil",
@ -79,14 +79,14 @@
"footer": {
"legal": {
"disclaimer": "Avertissement",
"disclaimerText": "movie-web n'héberge aucun fichier, il se contente de proposer des liens vers des services tiers. Les questions juridiques doivent être réglées avec les hébergeurs et les fournisseurs de fichiers. movie-web n'est pas responsable des fichiers multimédias diffusés par les fournisseurs de vidéos."
"disclaimerText": "Le site movie-web ne stocke pas de fichiers, mais propose des liens vers des services externes. Les problèmes juridiques doivent être traités avec les fournisseurs et les hébergeurs de fichiers. Les fichiers multimédias diffusés par les fournisseurs de vidéos ne sont pas couverts par movie-web."
},
"links": {
"discord": "Discord",
"dmca": "DMCA",
"github": "GitHub"
},
"tagline": "Regardez vos émissions et films préférés avec cette application de streaming open source."
"tagline": "Cette application de streaming open source vous permet de regarder vos émissions et films préférés."
},
"global": {
"name": "movie-web",

View File

@ -1,4 +1,21 @@
{
"about": {
"description": "movie-web एउटा वेब एप हो जसले स्ट्रिमहरूको लागि इन्टरनेटमा खोज्छ। हाम्रा टोलीले सामग्री उपभोग गर्नको लागि प्रायः न्यूनतम दृष्टिकोणको लागि लक्ष्य राख्छ।",
"faqTitle": "सामान्य प्रश्नहरू",
"q1": {
"body": "movie-web ले कुनै पनि सामग्री होस्ट गर्दैन। जब तपाइँ हेर्नको लागि केहि क्लिक गर्नुहुन्छ, इन्टरनेटमा चयन गरिएको मिडियाको लागि खोजी गरिन्छ (लोडिङ स्क्रिनमा र 'भिडियो स्रोत' ट्याबमा तपाइँ कुन स्रोत प्रयोग गरिरहनु भएको छ भनेर देख्न सक्नुहुन्छ)। मिडिया कहिले पनि चलचित्र-वेब द्वारा अपलोड हुँदैन, सबै कुरा यो खोजी संयन्त्र मार्फत हुन्छ।",
"title": "सामग्री कहाँबाट आउँछ?"
},
"q2": {
"body": "कार्यक्रम वा चलचित्र अनुरोध गर्न सम्भव छैन, movie-webले कुनै पनि सामग्री व्यवस्थापन गर्दैन। सबै सामग्री इन्टरनेटमा स्रोतहरू मार्फत हेरिन्छ।",
"title": "म कहाँ कार्यक्रम वा चलचित्र अनुरोध गर्न सक्छु?"
},
"q3": {
"body": "हाम्रा खोज परिणामहरू चलचित्र डाटाबेस (TMDB) द्वारा संचालित हुन्छन् र हाम्रा स्रोतहरूमा साँच्चै सामग्री छ कि छैन भनी प्रदर्शन गरिन्छ।",
"title": "खोज परिणामहरूले कार्यक्रम वा चलचित्र प्रदर्शन गर्दछ, म यसलाई किन प्ले गर्न सक्दिन?"
},
"title": "movie-web बारेमा"
},
"actions": {
"copied": "कपी भयो",
"copy": "कपी"
@ -59,6 +76,18 @@
"showError": "त्रुटि विवरण देखाउनुहोस्",
"title": "हामीले एउटा त्रुटिको सामना गर्यौं!"
},
"footer": {
"legal": {
"disclaimer": "Disclaimer",
"disclaimerText": "movie-webले कुनै पनि फाइलहरू होस्ट गर्दैन, यसले केवल तेस्रो पक्ष सेवाहरूमा लिङ्क गर्दछ। कानुनी मुद्दाहरू फाइल होस्ट र प्रदायकहरूसँग लिनु पर्छ। चलचित्र-वेब भिडियो प्रदायकहरू द्वारा देखाइएका कुनै पनि मिडिया फाइलहरूको लागि जिम्मेवार छैन।"
},
"links": {
"discord": "Discord",
"dmca": "DMCA",
"github": "GitHub"
},
"tagline": "यो खुला स्रोत स्ट्रिमिङ एपको साथ आफ्नो मनपर्ने शो र चलचित्रहरू हेर्नुहोस्।"
},
"global": {
"name": "movie-web",
"pages": {
@ -293,8 +322,99 @@
}
},
"settings": {
"account": {
"accountDetails": {
"deviceNameLabel": "उपकरणको नाम",
"deviceNamePlaceholder": "व्यक्तिगत फोन",
"editProfile": "सम्पादन गर्नुहोस्",
"logoutButton": "बाहिर निस्कनु"
},
"actions": {
"delete": {
"button": "खाता डिलीट गर्नुहोस्",
"confirmButton": "खाता डिलीट गर्नुहोस्",
"confirmDescription": "के तपाइँ आफ्नो खाता डिलीट गर्न नश्चित हुनुहुन्छ? तपाईंको सबै डाटा हराउनेछ!",
"confirmTitle": "के तपाईँ निश्चित हुनुहुन्छ?",
"text": "यो कार्य अपरिवर्तनीय छ। सबै डाटा मेटाइनेछ र केहि पनि पुन: प्राप्त गर्न सकिँदैन।",
"title": "खाता डिलीट गर्नुहोस्"
},
"title": "कार्यहरू"
},
"devices": {
"deviceNameLabel": "उपकरणको नाम",
"failed": "सत्रहरू लोड गर्न असफल भयो",
"removeDevice": "हटाउनुहोस्",
"title": "उपकरणहरु"
},
"profile": {
"finish": "सम्पादन समाप्त गर्नुहोस्",
"firstColor": "प्रोफाइल रङ एक",
"secondColor": "प्रोफाइल रङ दुई",
"title": "प्रोफाइल तस्वीर सम्पादन गर्नुहोस्",
"userIcon": "प्रयोगकर्ता आइकन"
},
"register": {
"cta": "सुरु गर्नु",
"text": "उपकरणहरू बीच आफ्नो cप्रगति साझेदारी गर्नुहोस् र तिनीहरूलाई सिंक राख्नुहोस्।",
"title": "क्लाउडमा सिंक गर्नुहोस्"
},
"title": "खाता"
},
"appearance": {
"activeTheme": "सक्रिय",
"themes": {
"blue": "निलो",
"default": "साधारण",
"gray": "खैरो",
"red": "रातो",
"teal": "हरियो-नीलो"
},
"title": "रूप-रंग"
},
"captions": {
"backgroundLabel": "पृष्ठभूमि अस्पष्टता",
"colorLabel": "रङ",
"previewQuote": "म डराउनु हुँदैन। डर मनको हत्यारा हो।",
"textSizeLabel": "शब्दको आकार",
"title": "क्याप्शन"
},
"connections": {
"server": {
"description": "यदि तपाईं आफ्नो डेटा भण्डारण गर्न अनुकूलन ब्याकइन्डमा जडान गर्न चाहनुहुन्छ भने, यसलाई सक्षम गर्नुहोस् र URL प्रदान गर्नुहोस्।",
"label": "अनुकूलन सर्भर",
"urlLabel": "अनुकूलन सर्भर URL"
},
"title": "संबन्धहरु",
"workers": {
"addButton": "नया worker हरु हाल्नुहोस",
"description": "एप्लिकेसन प्रकार्य बनाउनको लागि, सबै ट्राफिक प्रोक्सीहरू मार्फत रूट गरिएको छ। यदि तपाईं आफ्नो कामदारहरू ल्याउन चाहनुहुन्छ भने यसलाई सक्षम गर्नुहोस्।",
"emptyState": "अहिलेसम्म worker हरु छैनन्, तल एउटा थप्नुहोस्",
"label": "आफ्नै proxy workers हरु चलाउनुहोस्",
"urlLabel": "Worker URL हरु",
"urlPlaceholder": "https://"
}
},
"locale": {
"language": "एपको भाषा",
"languageDescription": "सम्पूर्ण अनुप्रयोगमा भाषा लागू गरियो।",
"title": "भाषा"
},
"reset": "रिसेट गर्नुहोस्",
"save": "सेभ गर्नुहोस्",
"sidebar": {
"info": {
"appVersion": "एप संस्करण",
"backendUrl": "ब्याकइन्ड URL",
"backendVersion": "ब्याकएन्ड संस्करण",
"hostname": "होस्टको नाम",
"insecure": "असुरक्षित",
"notLoggedIn": "तपाईं लग्द इन हुनुहुन्न",
"secure": "सुरक्षित",
"title": "एप बारे जानकारी",
"unknownVersion": "अज्ञात",
"userId": "प्रयोगकर्ता ID"
}
},
"unsaved": "तपाईंसँग सुरक्षित नगरिएका परिवर्तनहरू छन्"
}
}

View File

@ -396,7 +396,7 @@
},
"locale": {
"language": "应用程序语言",
"languageDescription": "语言已应用到整个应用程序。",
"languageDescription": "当前已应用到整个应用程序的语言。",
"title": "本地化"
},
"reset": "重设",

View File

@ -9,6 +9,7 @@ import { PlayerMeta } from "@/stores/player/slices/source";
// for anybody who cares - these are anonymous metrics.
// They are just used for figuring out if providers are broken or not
const metricsEndpoint = "https://backend.movie-web.app/metrics/providers";
const captchaMetricsEndpoint = "https://backend.movie-web.app/metrics/captcha";
const batchId = () => nanoid(32);
export type ProviderMetric = {
@ -136,8 +137,17 @@ export function scrapePartsToProviderMetric(
export function useReportProviders() {
const report = useCallback((items: ProviderMetric[]) => {
if (items.length === 0) return;
reportProviders(items);
reportProviders(items).catch(() => {});
}, []);
return { report };
}
export function reportCaptchaSolve(success: boolean) {
ofetch(captchaMetricsEndpoint, {
method: "POST",
body: {
success,
},
}).catch(() => {});
}

View File

@ -25,7 +25,9 @@ export function PassphraseDisplay(props: { mnemonic: string }) {
return (
<div className="rounded-lg border border-authentication-border/50 ">
<div className="px-4 py-2 flex justify-between border-b border-authentication-border/50">
<p className="font-bold text-sm text-white">Passphrase</p>
<p className="font-bold text-sm text-white">
{t("auth.generate.passphraseFrameLabel")}
</p>
<button
type="button"
className="text-authentication-copyText hover:text-authentication-copyTextHover transition-colors flex gap-2 items-center cursor-pointer"

View File

@ -160,7 +160,7 @@ function ParticlesCanvas() {
}
// Fish easter egg
const shouldShowFishie = Math.floor(Math.random() * 600) === 1;
const shouldShowFishie = Math.floor(Math.random() * 600) === 69;
if (shouldShowFishie) {
imageOverride = [
{

View File

@ -24,7 +24,9 @@ export function useAuthData() {
const clearProgress = useProgressStore((s) => s.clear);
const setTheme = useThemeStore((s) => s.setTheme);
const setAppLanguage = useLanguageStore((s) => s.setLanguage);
const setCaptionLanguage = useSubtitleStore((s) => s.setLanguage);
const importSubtitleLanguage = useSubtitleStore(
(s) => s.importSubtitleLanguage
);
const replaceBookmarks = useBookmarkStore((s) => s.replaceBookmarks);
const replaceItems = useProgressStore((s) => s.replaceItems);
@ -72,7 +74,7 @@ export function useAuthData() {
}
if (settings.defaultSubtitleLanguage) {
setCaptionLanguage(settings.defaultSubtitleLanguage);
importSubtitleLanguage(settings.defaultSubtitleLanguage);
}
if (settings.applicationTheme) {
@ -83,7 +85,7 @@ export function useAuthData() {
replaceBookmarks,
replaceItems,
setAppLanguage,
setCaptionLanguage,
importSubtitleLanguage,
setTheme,
]
);

View File

@ -24,7 +24,7 @@ export function useDerived<T>(
const setter = useCallback<Dispatch<SetStateAction<T>>>(
(inp) => {
if (!(inp instanceof Function)) setOverwrite(inp);
else setOverwrite((s) => inp(s ?? initial));
else setOverwrite((s) => inp(s !== undefined ? s : initial));
},
[initial, setOverwrite]
);

View File

@ -10,7 +10,6 @@ import ReactDOM from "react-dom";
import { HelmetProvider } from "react-helmet-async";
import { useTranslation } from "react-i18next";
import { BrowserRouter, HashRouter } from "react-router-dom";
import Turnstile from "react-turnstile";
import { useAsync } from "react-use";
import { Button } from "@/components/buttons/Button";

View File

@ -196,7 +196,7 @@ export function SettingsPage() {
<SettingsLayout>
<div id="settings-account">
<Heading1 border className="!mb-0">
Account
{t("settings.account.title")}
</Heading1>
{user.account && state.profile.state ? (
<AccountSettings

View File

@ -122,7 +122,7 @@ export function SidebarPart() {
boundaryElement=".sidebar-boundary"
>
<div className="hidden lg:block">
<SidebarSection title="Settings">
<SidebarSection title={t("global.pages.settings")}>
{settingLinks.map((v) => (
<SidebarLink
icon={v.icon}

View File

@ -2,6 +2,7 @@ import Turnstile, { BoundTurnstileObject } from "react-turnstile";
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
import { reportCaptchaSolve } from "@/backend/helpers/report";
import { conf } from "@/setup/config";
export interface TurnstileStore {
@ -52,11 +53,18 @@ export function isTurnstileInitialized() {
return !!getTurnstile();
}
export function getTurnstileToken() {
export async function getTurnstileToken() {
const turnstile = getTurnstile();
turnstile?.reset();
turnstile?.execute();
return useTurnstileStore.getState().getToken();
try {
const token = await useTurnstileStore.getState().getToken();
reportCaptchaSolve(true);
return token;
} catch (err) {
reportCaptchaSolve(false);
throw err;
}
}
export function TurnstileProvider() {