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
|
||||
|
||||
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: .
|
||||
|
||||
ports:
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
"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?"
|
||||
},
|
||||
"NotFound": {
|
||||
"uh_oh": "Uh Oh...",
|
||||
"something_wrong": "Something went wrong :|",
|
||||
"back_to_home": "Back to homepage"
|
||||
},
|
||||
"Search": {
|
||||
"placeholder": "categories, pornostars, etc...",
|
||||
"submit": "Search"
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
"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?"
|
||||
},
|
||||
"NotFound": {
|
||||
"uh_oh": "Uh Oh...",
|
||||
"something_wrong": "Qualcosa è andato storto :|",
|
||||
"back_to_home": "Torna alla home"
|
||||
},
|
||||
"Search": {
|
||||
"placeholder": "categorie, pornostar, ecc...",
|
||||
"submit": "Cerca"
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
const createNextIntlPlugin = require('next-intl/plugin');
|
||||
|
||||
|
||||
const withNextIntl = createNextIntlPlugin();
|
||||
|
||||
const path = require('path')
|
||||
|
||||
|
||||
module.exports = withNextIntl({
|
||||
sassOptions: {
|
||||
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 Home from "@/components/Pages/Home";
|
||||
|
||||
import { fetchGalleryData } from '@/utils/scrape/gallery';
|
||||
import { fetchGalleryData } from '@/utils/scrape/xvideos/gallery';
|
||||
|
||||
export default async function HomePage() {
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import Layout from "@/components/Layout";
|
|||
|
||||
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 } }) {
|
||||
|
||||
|
|
|
@ -4,7 +4,9 @@ import Layout from "@/components/Layout";
|
|||
|
||||
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';
|
||||
|
||||
|
@ -12,7 +14,7 @@ export default async function VideoPage({ params }: { params: { id: string } })
|
|||
|
||||
const locale = useLocale()
|
||||
|
||||
const decodedId = decodeURIComponent(params.id)
|
||||
const decodedId = decodeVideoUrlPath(params.id)
|
||||
|
||||
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 style from './Thumbnail.module.scss'
|
||||
import { encodeVideoUrlPath } from '@/utils/string';
|
||||
|
||||
interface Props {
|
||||
locale: string
|
||||
|
@ -22,7 +23,7 @@ const Thumbnail: React.FC<Props> = (props) => {
|
|||
|
||||
const { locale, videoUrl, imgUrl, text, show } = props
|
||||
|
||||
const encodedUri = encodeURIComponent(videoUrl)
|
||||
const encodedUri = encodeVideoUrlPath(videoUrl)
|
||||
|
||||
return (
|
||||
<div className={classNames(style.thumbnailContainer, { [style.show]: show } )}>
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
.query{
|
||||
flex: 6;
|
||||
margin-right: $spacing_16;
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.query:hover {
|
||||
|
@ -24,6 +25,7 @@
|
|||
background-color: var(--primary);
|
||||
border-color: var(--primary);
|
||||
color: var(--primary-inverse);
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.submitBtn:hover {
|
||||
|
|
|
@ -21,7 +21,7 @@ const Layout: React.FC<React.PropsWithChildren> = (props) => {
|
|||
<Head>
|
||||
<meta charSet="utf-8" />
|
||||
<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>
|
||||
<body>
|
||||
<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 { GalleryData, VideoData } from '@/meta/data';
|
||||
import { GalleryData } from '@/meta/data';
|
||||
import axios, { AxiosError } from 'axios';
|
||||
|
||||
import * as cheerio from "cheerio";
|
||||
import { getHeaders } from '../headers';
|
||||
|
||||
interface FetchParams {
|
||||
baseUrl?: string
|
||||
|
@ -13,11 +14,7 @@ export const fetchGalleryData = async (params?: FetchParams): Promise<GalleryDat
|
|||
|
||||
let data: GalleryData[] = [];
|
||||
|
||||
const reqHeaders = {
|
||||
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 reqHeaders = getHeaders()
|
||||
|
||||
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 * as cheerio from "cheerio";
|
||||
import { findRelatedVideos, findVideoUrlInsideTagStringByFunctionNameAndExtension } from '../string';
|
||||
import { findRelatedVideos, findVideoUrlInsideTagStringByFunctionNameAndExtension } from '../../string';
|
||||
import { getHeaders } from '../headers';
|
||||
|
||||
interface FetchParams {
|
||||
baseUrl?: string
|
||||
|
@ -19,11 +20,7 @@ export const fetchVideoData = async (videoId: string, params?: FetchParams): Pro
|
|||
|
||||
let related: GalleryData[] = [];
|
||||
|
||||
const reqHeaders = {
|
||||
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 reqHeaders = getHeaders()
|
||||
|
||||
const queryUrl = `${(params && params.baseUrl) ?? XVIDEOS_BASE_URL}${videoId}`
|
||||
|
|
@ -1,20 +1,20 @@
|
|||
import { GalleryData } from "@/meta/data";
|
||||
|
||||
export const findVideoUrlInsideTagStringByFunctionNameAndExtension = (
|
||||
tagBlock: string, functionName: string, extension: string): string|null => {
|
||||
const start = tagBlock.indexOf(`html5player.${functionName}('`) + `html5player.${functionName}('`.length;
|
||||
const end = tagBlock.toString().indexOf("'", start);
|
||||
tagBlock: string, functionName: string, extension: string): string | null => {
|
||||
const start = tagBlock.indexOf(`html5player.${functionName}('`) + `html5player.${functionName}('`.length;
|
||||
const end = tagBlock.toString().indexOf("'", start);
|
||||
|
||||
const substr = tagBlock.substring(start, end);
|
||||
const substr = tagBlock.substring(start, end);
|
||||
|
||||
if (substr.includes(extension)) {
|
||||
return substr
|
||||
}
|
||||
if (substr.includes(extension)) {
|
||||
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=['))) {
|
||||
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
|
||||
const start = tagBlock.indexOf('[{');
|
||||
const end = tagBlock.lastIndexOf('}]') + 2;
|
||||
|
||||
|
||||
// Estrai la sottostringa contenente l'array di oggetti
|
||||
const jsonString = tagBlock.substring(start, end);
|
||||
|
||||
|
||||
// Parsea la stringa JSON in un array di oggetti
|
||||
const videoRelatedArray = JSON.parse(jsonString);
|
||||
|
||||
|
||||
// Mappa ogni oggetto nell'array per rinominare le chiavi
|
||||
//@ts-ignore
|
||||
const parsedArray = videoRelatedArray.map(obj => ({
|
||||
|
@ -37,6 +37,23 @@ export const findRelatedVideos = (tagBlock: string): GalleryData[]|null => {
|
|||
imgUrl: obj.i,
|
||||
text: obj.tf
|
||||
}));
|
||||
|
||||
|
||||
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