Merge pull request 'v0.1/code-improvements' (#53) from v0.1/code-improvements into main
Reviewed-on: #53
This commit is contained in:
commit
1e79619808
|
@ -8,6 +8,13 @@ services:
|
||||||
|
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
|
healthcheck:
|
||||||
|
test: wget --no-verbose --tries=1 --spider http://localhost:3000/api/status || exit 1
|
||||||
|
interval: 60s
|
||||||
|
retries: 5
|
||||||
|
start_period: 20s
|
||||||
|
timeout: 10s
|
||||||
|
|
||||||
build: .
|
build: .
|
||||||
|
|
||||||
ports:
|
ports:
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
"disclaimer_5": "No banners or annoying popups. You can jerk off with no hassle!",
|
"disclaimer_5": "No banners or annoying popups. You can jerk off with no hassle!",
|
||||||
"disclaimer_6": "You're choosing image over imagination. What if they're not in antithesis?"
|
"disclaimer_6": "You're choosing image over imagination. What if they're not in antithesis?"
|
||||||
},
|
},
|
||||||
|
"NotFound": {
|
||||||
|
"uh_oh": "Uh Oh...",
|
||||||
|
"something_wrong": "Something went wrong :|",
|
||||||
|
"back_to_home": "Back to homepage"
|
||||||
|
},
|
||||||
"Search": {
|
"Search": {
|
||||||
"placeholder": "categories, pornostars, etc...",
|
"placeholder": "categories, pornostars, etc...",
|
||||||
"submit": "Search"
|
"submit": "Search"
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
"disclaimer_5": "Niente banner o popup fastidiosi. Puoi masturbarti in santa pace.",
|
"disclaimer_5": "Niente banner o popup fastidiosi. Puoi masturbarti in santa pace.",
|
||||||
"disclaimer_6": "Stai preferendo l'immagine all'immaginazione. E se immagine e immaginazione non fossero in antitesi?"
|
"disclaimer_6": "Stai preferendo l'immagine all'immaginazione. E se immagine e immaginazione non fossero in antitesi?"
|
||||||
},
|
},
|
||||||
|
"NotFound": {
|
||||||
|
"uh_oh": "Uh Oh...",
|
||||||
|
"something_wrong": "Qualcosa è andato storto :|",
|
||||||
|
"back_to_home": "Torna alla home"
|
||||||
|
},
|
||||||
"Search": {
|
"Search": {
|
||||||
"placeholder": "categorie, pornostar, ecc...",
|
"placeholder": "categorie, pornostar, ecc...",
|
||||||
"submit": "Cerca"
|
"submit": "Cerca"
|
||||||
|
|
|
@ -1,11 +1,25 @@
|
||||||
const createNextIntlPlugin = require('next-intl/plugin');
|
const createNextIntlPlugin = require('next-intl/plugin');
|
||||||
|
|
||||||
const withNextIntl = createNextIntlPlugin();
|
const withNextIntl = createNextIntlPlugin();
|
||||||
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
module.exports = withNextIntl({
|
module.exports = withNextIntl({
|
||||||
sassOptions: {
|
sassOptions: {
|
||||||
includePaths: [path.join(__dirname, 'src/styles')],
|
includePaths: [path.join(__dirname, 'src/styles')],
|
||||||
},
|
},
|
||||||
|
async headers() {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
// matching all API routes
|
||||||
|
source: "/api/:path*",
|
||||||
|
headers: [
|
||||||
|
{ key: "Access-Control-Allow-Credentials", value: "true" },
|
||||||
|
{ key: "Access-Control-Allow-Origin", value: "*" },
|
||||||
|
{ key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT" },
|
||||||
|
{ key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
})
|
})
|
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
Binary file not shown.
After Width: | Height: | Size: 8.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 578 B |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
|
@ -0,0 +1 @@
|
||||||
|
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import Layout from "@/components/Layout";
|
||||||
|
import NotFound from "@/components/Pages/NotFound";
|
||||||
|
|
||||||
|
export default function NotFoundPage() {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<NotFound />
|
||||||
|
</Layout>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,12 +1,8 @@
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
import * as cheerio from "cheerio";
|
|
||||||
|
|
||||||
import Layout from "@/components/Layout";
|
import Layout from "@/components/Layout";
|
||||||
|
|
||||||
import Home from "@/components/Pages/Home";
|
import Home from "@/components/Pages/Home";
|
||||||
|
|
||||||
import { fetchGalleryData } from '@/utils/scrape/gallery';
|
import { fetchGalleryData } from '@/utils/scrape/xvideos/gallery';
|
||||||
|
|
||||||
export default async function HomePage() {
|
export default async function HomePage() {
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import Layout from "@/components/Layout";
|
||||||
|
|
||||||
import Search from "@/components/Pages/Search";
|
import Search from "@/components/Pages/Search";
|
||||||
|
|
||||||
import { fetchGalleryData } from "@/utils/scrape/gallery";
|
import { fetchGalleryData } from "@/utils/scrape/xvideos/gallery";
|
||||||
|
|
||||||
export default async function SearchPage({ params }: { params: { query: string } }) {
|
export default async function SearchPage({ params }: { params: { query: string } }) {
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,9 @@ import Layout from "@/components/Layout";
|
||||||
|
|
||||||
import Video from "@/components/Pages/Video";
|
import Video from "@/components/Pages/Video";
|
||||||
|
|
||||||
import { fetchVideoData } from "@/utils/scrape/video";
|
import { decodeVideoUrlPath } from '@/utils/string';
|
||||||
|
|
||||||
|
import { fetchVideoData } from '@/utils/scrape/xvideos/video';
|
||||||
|
|
||||||
import { useLocale } from 'next-intl';
|
import { useLocale } from 'next-intl';
|
||||||
|
|
||||||
|
@ -12,7 +14,7 @@ export default async function VideoPage({ params }: { params: { id: string } })
|
||||||
|
|
||||||
const locale = useLocale()
|
const locale = useLocale()
|
||||||
|
|
||||||
const decodedId = decodeURIComponent(params.id)
|
const decodedId = decodeVideoUrlPath(params.id)
|
||||||
|
|
||||||
const [data, related] = await fetchVideoData(decodedId)
|
const [data, related] = await fetchVideoData(decodedId)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
import { getAppVersion } from '@/utils/info/version'
|
||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
|
||||||
|
export async function GET() {
|
||||||
|
const version = await getAppVersion()
|
||||||
|
return NextResponse.json({ version })
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
import { NextResponse } from 'next/server'
|
||||||
|
|
||||||
|
export async function GET(request: Request) {
|
||||||
|
return NextResponse.json({ msg: 'OK' })
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import classNames from 'classnames';
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
|
|
||||||
import style from './Thumbnail.module.scss'
|
import style from './Thumbnail.module.scss'
|
||||||
|
import { encodeVideoUrlPath } from '@/utils/string';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
locale: string
|
locale: string
|
||||||
|
@ -22,7 +23,7 @@ const Thumbnail: React.FC<Props> = (props) => {
|
||||||
|
|
||||||
const { locale, videoUrl, imgUrl, text, show } = props
|
const { locale, videoUrl, imgUrl, text, show } = props
|
||||||
|
|
||||||
const encodedUri = encodeURIComponent(videoUrl)
|
const encodedUri = encodeVideoUrlPath(videoUrl)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classNames(style.thumbnailContainer, { [style.show]: show } )}>
|
<div className={classNames(style.thumbnailContainer, { [style.show]: show } )}>
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
.query{
|
.query{
|
||||||
flex: 6;
|
flex: 6;
|
||||||
margin-right: $spacing_16;
|
margin-right: $spacing_16;
|
||||||
|
transition: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.query:hover {
|
.query:hover {
|
||||||
|
@ -24,6 +25,7 @@
|
||||||
background-color: var(--primary);
|
background-color: var(--primary);
|
||||||
border-color: var(--primary);
|
border-color: var(--primary);
|
||||||
color: var(--primary-inverse);
|
color: var(--primary-inverse);
|
||||||
|
transition: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.submitBtn:hover {
|
.submitBtn:hover {
|
||||||
|
|
|
@ -21,7 +21,7 @@ const Layout: React.FC<React.PropsWithChildren> = (props) => {
|
||||||
<Head>
|
<Head>
|
||||||
<meta charSet="utf-8" />
|
<meta charSet="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>Proxy Raye: un proxy per XVideos basato su PornInvidious</title>
|
<title>Proxy Raye: watch porn videos without tracking or annoying ads!</title>
|
||||||
</Head>
|
</Head>
|
||||||
<body>
|
<body>
|
||||||
<main className="container">{children}</main>
|
<main className="container">{children}</main>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
@import 'fontsize';
|
||||||
|
|
||||||
|
.header {
|
||||||
|
font-size: $font-size-xlarge;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg {
|
||||||
|
font-size: $font-size-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import React, { } from 'react';
|
||||||
|
|
||||||
|
import style from './Msg.module.scss';
|
||||||
|
|
||||||
|
import { useTranslations } from 'next-intl';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
|
const Msg: React.FC = () => {
|
||||||
|
|
||||||
|
const t = useTranslations('NotFound');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={style.container}>
|
||||||
|
<div className={style.header}>{t('uh_oh')}</div>
|
||||||
|
<p className={style.msg}>{t('something_wrong')}</p>
|
||||||
|
<Link className={style.link} href="/">{t('back_to_home')}</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Msg;
|
|
@ -0,0 +1,18 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import Header from '@/components/Layout/Header';
|
||||||
|
import SearchBar from '@/components/Layout/SearchBar';
|
||||||
|
import Msg from './Msg';
|
||||||
|
|
||||||
|
const NotFound: React.FC = (props) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header />
|
||||||
|
<SearchBar />
|
||||||
|
<Msg />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NotFound;
|
|
@ -0,0 +1,23 @@
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
export const getAppVersion = async (): Promise<string> => {
|
||||||
|
|
||||||
|
let version = ''
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
const packageJsonPath = path.resolve(process.cwd(), 'package.json');
|
||||||
|
|
||||||
|
const data = await fs.readFile(packageJsonPath, 'utf8');
|
||||||
|
|
||||||
|
const packageJson = JSON.parse(data);
|
||||||
|
|
||||||
|
version = packageJson.version
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
// handle error
|
||||||
|
}
|
||||||
|
|
||||||
|
return version
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { XVIDEOS_BASE_URL } from "@/constants/urls";
|
||||||
|
import { removeHttpS } from "../string";
|
||||||
|
|
||||||
|
const getRandomUserAgent = (): string => {
|
||||||
|
|
||||||
|
const userAgents: string[] = [
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5397.215 Safari/537.36',
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0',
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.2420.81',
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 OPR/109.0.0.0',
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 14.4; rv:124.0) Gecko/20100101 Firefox/124.0',
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Safari/605.1.15',
|
||||||
|
'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 OPR/109.0.0.0',
|
||||||
|
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
|
||||||
|
'Mozilla/5.0 (X11; Linux i686; rv:124.0) Gecko/20100101 Firefox/124.0'
|
||||||
|
];
|
||||||
|
|
||||||
|
const rand = Math.floor(Math.random() * userAgents.length);
|
||||||
|
|
||||||
|
return userAgents[rand]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getHeaders = (host:string = XVIDEOS_BASE_URL) => {
|
||||||
|
return {
|
||||||
|
headers: {
|
||||||
|
"User-Agent": getRandomUserAgent(),
|
||||||
|
"Accept-Language": "en-gb, en, en-US, it",
|
||||||
|
"Accept-Encoding": "gzip, deflate, br",
|
||||||
|
"Connection": "keep-alive",
|
||||||
|
"Sec-Fetch-Dest": "document",
|
||||||
|
"Sec-Fetch-Mode": "navigate",
|
||||||
|
"Sec-Fetch-Site": "none",
|
||||||
|
"Host": removeHttpS(host)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
|
@ -1,8 +1,9 @@
|
||||||
import { XVIDEOS_BASE_URL } from '@/constants/urls';
|
import { XVIDEOS_BASE_URL } from '@/constants/urls';
|
||||||
import { GalleryData, VideoData } from '@/meta/data';
|
import { GalleryData } from '@/meta/data';
|
||||||
import axios, { AxiosError } from 'axios';
|
import axios, { AxiosError } from 'axios';
|
||||||
|
|
||||||
import * as cheerio from "cheerio";
|
import * as cheerio from "cheerio";
|
||||||
|
import { getHeaders } from '../headers';
|
||||||
|
|
||||||
interface FetchParams {
|
interface FetchParams {
|
||||||
baseUrl?: string
|
baseUrl?: string
|
||||||
|
@ -13,11 +14,7 @@ export const fetchGalleryData = async (params?: FetchParams): Promise<GalleryDat
|
||||||
|
|
||||||
let data: GalleryData[] = [];
|
let data: GalleryData[] = [];
|
||||||
|
|
||||||
const reqHeaders = {
|
const reqHeaders = getHeaders()
|
||||||
headers: {
|
|
||||||
"User-Agent": 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5397.215 Safari/537.36'
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const queryUrl = `${(params && params.baseUrl) ?? XVIDEOS_BASE_URL}${params && params.query ? '/?k=' + params.query : ''}`
|
const queryUrl = `${(params && params.baseUrl) ?? XVIDEOS_BASE_URL}${params && params.query ? '/?k=' + params.query : ''}`
|
||||||
|
|
|
@ -4,7 +4,8 @@ import { GalleryData, VideoData } from '@/meta/data';
|
||||||
import axios, { AxiosError } from 'axios';
|
import axios, { AxiosError } from 'axios';
|
||||||
|
|
||||||
import * as cheerio from "cheerio";
|
import * as cheerio from "cheerio";
|
||||||
import { findRelatedVideos, findVideoUrlInsideTagStringByFunctionNameAndExtension } from '../string';
|
import { findRelatedVideos, findVideoUrlInsideTagStringByFunctionNameAndExtension } from '../../string';
|
||||||
|
import { getHeaders } from '../headers';
|
||||||
|
|
||||||
interface FetchParams {
|
interface FetchParams {
|
||||||
baseUrl?: string
|
baseUrl?: string
|
||||||
|
@ -19,11 +20,7 @@ export const fetchVideoData = async (videoId: string, params?: FetchParams): Pro
|
||||||
|
|
||||||
let related: GalleryData[] = [];
|
let related: GalleryData[] = [];
|
||||||
|
|
||||||
const reqHeaders = {
|
const reqHeaders = getHeaders()
|
||||||
headers: {
|
|
||||||
"User-Agent": 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.5397.215 Safari/537.36'
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const queryUrl = `${(params && params.baseUrl) ?? XVIDEOS_BASE_URL}${videoId}`
|
const queryUrl = `${(params && params.baseUrl) ?? XVIDEOS_BASE_URL}${videoId}`
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import { GalleryData } from "@/meta/data";
|
import { GalleryData } from "@/meta/data";
|
||||||
|
|
||||||
export const findVideoUrlInsideTagStringByFunctionNameAndExtension = (
|
export const findVideoUrlInsideTagStringByFunctionNameAndExtension = (
|
||||||
tagBlock: string, functionName: string, extension: string): string|null => {
|
tagBlock: string, functionName: string, extension: string): string | null => {
|
||||||
const start = tagBlock.indexOf(`html5player.${functionName}('`) + `html5player.${functionName}('`.length;
|
const start = tagBlock.indexOf(`html5player.${functionName}('`) + `html5player.${functionName}('`.length;
|
||||||
const end = tagBlock.toString().indexOf("'", start);
|
const end = tagBlock.toString().indexOf("'", start);
|
||||||
|
|
||||||
const substr = tagBlock.substring(start, end);
|
const substr = tagBlock.substring(start, end);
|
||||||
|
|
||||||
if (substr.includes(extension)) {
|
if (substr.includes(extension)) {
|
||||||
return substr
|
return substr
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const findRelatedVideos = (tagBlock: string): GalleryData[]|null => {
|
export const findRelatedVideos = (tagBlock: string): GalleryData[] | null => {
|
||||||
if (!(tagBlock.includes('video_related=['))) {
|
if (!(tagBlock.includes('video_related=['))) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,13 @@ export const findRelatedVideos = (tagBlock: string): GalleryData[]|null => {
|
||||||
// Trova l'inizio e la fine dell'array di oggetti nell'input
|
// Trova l'inizio e la fine dell'array di oggetti nell'input
|
||||||
const start = tagBlock.indexOf('[{');
|
const start = tagBlock.indexOf('[{');
|
||||||
const end = tagBlock.lastIndexOf('}]') + 2;
|
const end = tagBlock.lastIndexOf('}]') + 2;
|
||||||
|
|
||||||
// Estrai la sottostringa contenente l'array di oggetti
|
// Estrai la sottostringa contenente l'array di oggetti
|
||||||
const jsonString = tagBlock.substring(start, end);
|
const jsonString = tagBlock.substring(start, end);
|
||||||
|
|
||||||
// Parsea la stringa JSON in un array di oggetti
|
// Parsea la stringa JSON in un array di oggetti
|
||||||
const videoRelatedArray = JSON.parse(jsonString);
|
const videoRelatedArray = JSON.parse(jsonString);
|
||||||
|
|
||||||
// Mappa ogni oggetto nell'array per rinominare le chiavi
|
// Mappa ogni oggetto nell'array per rinominare le chiavi
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const parsedArray = videoRelatedArray.map(obj => ({
|
const parsedArray = videoRelatedArray.map(obj => ({
|
||||||
|
@ -37,6 +37,23 @@ export const findRelatedVideos = (tagBlock: string): GalleryData[]|null => {
|
||||||
imgUrl: obj.i,
|
imgUrl: obj.i,
|
||||||
text: obj.tf
|
text: obj.tf
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return parsedArray;
|
return parsedArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const removeHttpS = (url: string): string => {
|
||||||
|
if (url.startsWith("http://")) {
|
||||||
|
return url.slice(7);
|
||||||
|
} else if (url.startsWith("https://")) {
|
||||||
|
return url.slice(8);
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const encodeVideoUrlPath = (input: string): string => {
|
||||||
|
return encodeURIComponent(input.replace(/^\/+/, ''))
|
||||||
|
};
|
||||||
|
|
||||||
|
export const decodeVideoUrlPath = (input: string): string => {
|
||||||
|
return `/${decodeURIComponent(input)}`;
|
||||||
|
};
|
Loading…
Reference in New Issue