Merge pull request #938 from qtchaos/remove-domain

Remove references to official domain
This commit is contained in:
William Oldham 2024-02-25 22:19:14 +00:00 committed by GitHub
commit 9e4241e464
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 107 additions and 61 deletions

View file

@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
codeofconduct@movie-web.app.
our [Discord](https://discord.gg/gQYB6fGArX).
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View file

@ -1,6 +1,6 @@
# Contributing Guidelines for movie-web
Thank you for investing your time in contributing to our project! Your contribution will be reflected on [movie-web.app](https://movie-web.app).
Thank you for investing your time in contributing to our project! Your contribution will be reflected on all of the community hosted instances that are on the latest version.
Please read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.
@ -33,7 +33,7 @@ There are two places where to request features or report bugs:
### Discord Server
If you do not have a GitHub account or want to discuss a feature or bug with us before making an issue, you can join our Discord server.
<a href="https://discord.movie-web.app"><img src="https://discord.com/api/guilds/871713465100816424/widget.png?style=banner2" alt="Discord Server"></a>
<a href="https://discord.gg/gQYB6fGArX"><img src="https://discord.com/api/guilds/871713465100816424/widget.png?style=banner2" alt="Discord Server"></a>
### GitHub Issues
To make a GitHub issue for movie-web, please visit the [new issue page](https://github.com/movie-web/movie-web/issues/new/choose) where you can pick either the "Bug Report" or "Feature Request" template.
@ -85,7 +85,7 @@ Here are some tips to make sure that your pull requests are :pinched_fingers: fi
### Language Contributions
Language contributions help movie-web massively, allowing people worldwide to use our app!
We use weblate for crowdsourcing our translations. [Click here to go to our translation tool.](https://weblate.movie-web.app/projects/movie-web/website/)
We use weblate for crowdsourcing our translations.
1. First make sure you make an account. (click the link above)
2. Click the language you want to help translate, if it's not listed you can click the plus top left to add a new language.

9
.github/SECURITY.md vendored
View file

@ -2,12 +2,9 @@
## Supported Versions
The movie-web maintainers only support the latest version of movie-web published at https://movie-web.app.
Support is not provided for any forks or mirrors of movie-web.
The latest version of movie-web is the only version that is supported, as it is the only version that is being actively developed.
## Reporting a Vulnerability
There are two ways you can contact the movie-web maintainers to report a vulnerability:
- Email [security@movie-web.app](mailto:security@movie-web.app)
- Report the vulnerability in the [movie-web Discord server](https://discord.movie-web.app)
You can contact the movie-web maintainers to report a vulnerability:
- Report the vulnerability in the [movie-web Discord server](https://discord.gg/gQYB6fGArX)

View file

@ -4,13 +4,13 @@
<p align="center">
<img src="https://skillicons.dev/icons?i=react,vite,ts" />
<br/>
<a href="https://discord.movie-web.app"><kbd>🔵 discord</kbd></a> <a href="https://movie-web.app"><kbd>🟢 website</kbd></a>
<a href="https://discord.gg/gQYB6fGArX"><kbd>🔵 discord</kbd></a> <a href="https://movie-web.github.io/docs"><kbd>🟢 docs</kbd></a>
</p>
<br/><br/>
# ⚡What is movie-web?
movie-web is a web app for watching movies easily. Check it out at <a href="https://movie-web.app"><kbd>movie-web.app</kbd></a>.
movie-web is a web app for watching movies easily.
This service works by displaying video files from third-party providers inside an intuitive and aesthetic user interface.
@ -57,7 +57,7 @@ pnpm build
A simple guide has been written to assist in hosting your own instance of movie-web. Check it out below
|[Selfhosting guide](https://docs.movie-web.app)|
|[Selfhosting guide](https://movie-web.github.io/docs)|
|---|
## 🤝 Thanks to all Contributors

View file

@ -2,7 +2,7 @@
"name": "movie-web",
"version": "4.4.2",
"private": true,
"homepage": "https://movie-web.app",
"homepage": "https://github.com/movie-web/movie-web",
"scripts": {
"dev": "vite",
"build": "vite build",

View file

@ -11,7 +11,7 @@ window.__CONFIG__ = {
// Whether to disable hash-based routing, leave this as false if you don't know what this is
VITE_NORMAL_ROUTER: false,
// The backend URL to communicate with, defaults to the movie-web hosted one at backend.movie-web.app
// The backend URL to communicate with
VITE_BACKEND_URL: null,
// A comma separated list of disallowed IDs in the case of a DMCA claim - in the format "series-<id>" and "movie-<id>"

View file

@ -55,6 +55,8 @@
"text": "Did you configure it correctly?",
"title": "Failed to reach server"
},
"noHostTitle": "Server not configured!",
"noHost": "The server has not been configured, therefore you cannot create an account",
"host": "You are connecting to <0>{{hostname}}</0> - please confirm you trust it before making an account",
"no": "Go back",
"title": "Do you trust this server?",

View file

@ -5,13 +5,14 @@ import { useCallback } from "react";
import { isExtensionActiveCached } from "@/backend/extension/messaging";
import { ScrapingItems, ScrapingSegment } from "@/hooks/useProviderScrape";
import { BACKEND_URL } from "@/setup/constants";
import { useAuthStore } from "@/stores/auth";
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 metricsEndpoint = `${BACKEND_URL}/metrics/providers`;
const captchaMetricsEndpoint = `${BACKEND_URL}/metrics/captcha`;
const batchId = () => nanoid(32);
export type ProviderMetric = {
@ -44,6 +45,7 @@ function getStackTrace(error: Error, lines: number) {
}
export async function reportProviders(items: ProviderMetric[]): Promise<void> {
if (!BACKEND_URL) return;
return ofetch(metricsEndpoint, {
method: "POST",
body: {
@ -156,6 +158,7 @@ export function useReportProviders() {
}
export function reportCaptchaSolve(success: boolean) {
if (!BACKEND_URL) return;
ofetch(captchaMetricsEndpoint, {
method: "POST",
body: {

View file

@ -63,6 +63,7 @@ export function useAuth() {
const login = useCallback(
async (loginData: LoginData) => {
if (!backendUrl) return;
const keys = await keysFromMnemonic(loginData.mnemonic);
const publicKeyBase64Url = bytesToBase64Url(keys.publicKey);
const { challenge } = await getLoginChallengeToken(
@ -87,7 +88,7 @@ export function useAuth() {
);
const logout = useCallback(async () => {
if (!currentAccount) return;
if (!currentAccount || !backendUrl) return;
try {
await removeSession(
backendUrl,
@ -102,6 +103,7 @@ export function useAuth() {
const register = useCallback(
async (registerData: RegistrationData) => {
if (!backendUrl) return;
const { challenge } = await getRegisterChallengeToken(
backendUrl,
registerData.recaptchaToken,
@ -134,6 +136,7 @@ export function useAuth() {
progressItems: Record<string, ProgressMediaItem>,
bookmarks: Record<string, BookmarkMediaItem>,
) => {
if (!backendUrl) return;
if (
Object.keys(progressItems).length === 0 &&
Object.keys(bookmarks).length === 0
@ -159,6 +162,7 @@ export function useAuth() {
const restore = useCallback(
async (account: AccountWithToken) => {
if (!backendUrl) return;
let user: { user: UserResponse; session: SessionResponse };
try {
user = await getUser(backendUrl, account.token);

View file

@ -1,7 +1,7 @@
import { conf } from "@/setup/config";
import { useAuthStore } from "@/stores/auth";
export function useBackendUrl() {
export function useBackendUrl(): string | undefined {
const backendUrl = useAuthStore((s) => s.backendUrl);
return backendUrl ?? conf().BACKEND_URL;
}

View file

@ -70,6 +70,7 @@ export function AccountSettings(props: {
const url = useBackendUrl();
const { account } = props;
const [sessionsResult, execSessions] = useAsyncFn(() => {
if (!url) return Promise.resolve([]);
return getSessions(url, account);
}, [account, url]);
useEffect(() => {
@ -144,7 +145,7 @@ export function SettingsPage() {
);
const saveChanges = useCallback(async () => {
if (account) {
if (account && backendUrl) {
if (
state.appLanguage.changed ||
state.theme.changed ||

View file

@ -43,7 +43,7 @@ export function OnboardingProxyPage() {
throw new Error("onboarding.proxy.input.errorNotProxy");
setProxySet([url]);
if (account) {
if (account && backendUrl) {
await updateSettings(backendUrl, account, {
proxyUrls: [url],
});

View file

@ -32,13 +32,21 @@ export function BackendTestPart() {
value: null,
});
if (!backendUrl) {
return setStatus({
hasTested: true,
success: false,
errorText: "Backend URL is not set",
value: null,
});
}
try {
const backendData = await getBackendMeta(backendUrl);
return setStatus({
hasTested: true,
success: true,
errorText:
"Failed to call backend, double check the URL key and your internet connection",
errorText: "",
value: backendData,
});
} catch (err) {
@ -46,7 +54,7 @@ export function BackendTestPart() {
hasTested: true,
success: false,
errorText:
"Failed to call backend, double check the URL key and your internet connection",
"Failed to call backend, double check the URL, your internet connection, and ensure CORS is properly configured on your backend.",
value: null,
});
}

View file

@ -52,6 +52,9 @@ export function LoginFormPart(props: LoginFormPartProps) {
throw err;
}
if (!account)
throw new Error(t("auth.login.validationError") ?? undefined);
await importData(account, progressItems, bookmarkItems);
await restore(account);

View file

@ -22,8 +22,12 @@ interface TrustBackendPartProps {
export function TrustBackendPart(props: TrustBackendPartProps) {
const navigate = useNavigate();
const backendUrl = useBackendUrl();
const hostname = useMemo(() => new URL(backendUrl).hostname, [backendUrl]);
const hostname = useMemo(
() => (backendUrl ? new URL(backendUrl).hostname : undefined),
[backendUrl],
);
const result = useAsync(() => {
if (!backendUrl) return Promise.resolve(null);
return getBackendMeta(backendUrl);
}, [backendUrl]);
const { t } = useTranslation();
@ -50,38 +54,52 @@ export function TrustBackendPart(props: TrustBackendPartProps) {
return (
<LargeCard>
<LargeCardText
title={t("auth.trust.title")}
title={hostname ? t("auth.trust.title") : t("auth.trust.noHostTitle")}
icon={<Icon icon={Icons.CIRCLE_EXCLAMATION} />}
>
<Trans
i18nKey="auth.trust.host"
values={{
hostname,
}}
>
<span className="text-white" />
</Trans>
{hostname ? (
<Trans
i18nKey="auth.trust.host"
values={{
hostname,
}}
>
<span className="text-white" />
</Trans>
) : (
<p>{t("auth.trust.noHost")}</p>
)}
</LargeCardText>
<div className="border border-authentication-border rounded-xl px-4 py-8 flex flex-col items-center space-y-2 my-8">
{cardContent}
</div>
<LargeCardButtons>
<Button theme="secondary" onClick={() => navigate("/")}>
{t("auth.trust.no")}
</Button>
<Button
theme="purple"
onClick={() => result.value && props.onNext?.(result.value)}
>
{t("auth.trust.yes")}
</Button>
</LargeCardButtons>
<p className="text-center mt-6">
<Trans i18nKey="auth.hasAccount">
<MwLink to="/login">.</MwLink>
</Trans>
</p>
{hostname ? (
<>
<div className="border border-authentication-border rounded-xl px-4 py-8 flex flex-col items-center space-y-2 my-8">
{cardContent}
</div>
<LargeCardButtons>
<Button theme="secondary" onClick={() => navigate("/")}>
{t("auth.trust.no")}
</Button>
<Button
theme="purple"
onClick={() => result.value && props.onNext?.(result.value)}
>
{t("auth.trust.yes")}
</Button>
</LargeCardButtons>
<p className="text-center mt-6">
<Trans i18nKey="auth.hasAccount">
<MwLink to="/login">.</MwLink>
</Trans>
</p>
</>
) : (
<LargeCardButtons>
<Button theme="purple" onClick={() => navigate("/")}>
{t("auth.trust.no")}
</Button>
</LargeCardButtons>
)}
</LargeCard>
);
}

View file

@ -47,6 +47,8 @@ export function VerifyPassphrase(props: VerifyPassphraseProps) {
const [result, execute] = useAsyncFn(
async (inputMnemonic: string) => {
if (!backendUrl)
throw new Error(t("auth.verify.noBackendUrl") ?? undefined);
if (!props.mnemonic || !props.userData)
throw new Error(t("auth.verify.invalidData") ?? undefined);
@ -68,6 +70,9 @@ export function VerifyPassphrase(props: VerifyPassphraseProps) {
recaptchaToken,
});
if (!account)
throw new Error(t("auth.verify.registrationFailed") ?? undefined);
await importData(account, progressItems, bookmarkItems);
await updateSettings(backendUrl, account, {

View file

@ -18,7 +18,7 @@ export function AccountActionsPart() {
const deleteModal = useModal("account-delete");
const [deleteResult, deleteExec] = useAsyncFn(async () => {
if (!account) return;
if (!account || !url) return;
await deleteUser(url, account);
await logout();
deleteModal.hide();

View file

@ -55,7 +55,7 @@ function ProxyEdit({ proxyUrls, setProxyUrls }: ProxyEditProps) {
</p>
<p className="max-w-[20rem] font-medium">
<Trans i18nKey="settings.connections.workers.description">
<MwLink to="https://docs.movie-web.app/proxy/deploy">
<MwLink to="https://movie-web.github.io/docs/proxy/deploy">
Proxy documentation
</MwLink>
</Trans>
@ -125,7 +125,7 @@ function BackendEdit({ backendUrl, setBackendUrl }: BackendEditProps) {
</p>
<p className="max-w-[20rem] font-medium">
<Trans i18nKey="settings.connections.server.description">
<MwLink to="https://docs.movie-web.app/backend/deploy">
<MwLink to="https://movie-web.github.io/docs/backend/deploy">
Backend documentation
</MwLink>
</Trans>

View file

@ -24,6 +24,7 @@ export function Device(props: {
const token = useAuthStore((s) => s.account?.token);
const [result, exec] = useAsyncFn(async () => {
if (!token) throw new Error("No token present");
if (!url) throw new Error("No backend set");
await removeSession(url, token, props.id);
props.onRemove?.();
}, [url, token, props.id]);

View file

@ -14,9 +14,9 @@ import { useAuthStore } from "@/stores/auth";
const rem = 16;
function SecureBadge(props: { url: string }) {
function SecureBadge(props: { url: string | undefined }) {
const { t } = useTranslation();
const secure = props.url.startsWith("https://");
const secure = props.url ? props.url.startsWith("https://") : false;
return (
<div className="flex items-center gap-1 -mx-1 ml-3 px-1 rounded bg-largeCard-background font-bold">
<Icon icon={secure ? Icons.LOCK : Icons.UNLOCK} />
@ -68,6 +68,7 @@ export function SidebarPart() {
const backendUrl = useBackendUrl();
const backendMeta = useAsync(async () => {
if (!backendUrl) return;
return getBackendMeta(backendUrl);
}, [backendUrl]);
@ -159,7 +160,7 @@ export function SidebarPart() {
<SecureBadge url={backendUrl} />
</div>
<p className="text-white">
{backendUrl.replace(/https?:\/\//, "")}
{backendUrl?.replace(/https?:\/\//, "") ?? "—"}
</p>
</div>

View file

@ -1,6 +1,6 @@
export const APP_VERSION = import.meta.env.PACKAGE_VERSION;
export const DISCORD_LINK = "https://discord.movie-web.app";
export const DISCORD_LINK = "https://discord.gg/gQYB6fGArX";
export const GITHUB_LINK = "https://github.com/movie-web/movie-web";
export const DONATION_LINK = "https://ko-fi.com/movieweb";
export const GA_ID = "G-44YVXRL61C";
export const BACKEND_URL = "https://backend.movie-web.app";
export const BACKEND_URL = import.meta.env.VITE_BACKEND_URL;

View file

@ -60,6 +60,7 @@ export function BookmarkSyncer() {
useEffect(() => {
const interval = setInterval(() => {
(async () => {
if (!url) return;
const state = useBookmarkStore.getState();
const user = useAuthStore.getState();
await syncBookmarks(

View file

@ -62,6 +62,7 @@ export function ProgressSyncer() {
useEffect(() => {
const interval = setInterval(() => {
(async () => {
if (!url) return;
const state = useProgressStore.getState();
const user = useAuthStore.getState();
await syncProgress(

View file

@ -16,6 +16,7 @@ export function SettingsSyncer() {
useEffect(() => {
const interval = setInterval(() => {
(async () => {
if (!url) return;
const state = useSubtitleStore.getState();
const user = useAuthStore.getState();
if (state.lastSync.lastSelectedLanguage === state.lastSelectedLanguage)