add (client-side only) pornhub video streaming (WIP)

This commit is contained in:
La macchina desiderante 2024-05-20 20:52:02 +02:00
parent b1dc47d461
commit f5908b9a5d
6 changed files with 75 additions and 43 deletions

View File

@ -24,9 +24,7 @@ export default async function VideoPage({ params }: { params: { platform: Platfo
const [data, related] = await new VideoAgent(platform).getVideo(decodedId) const [data, related] = await new VideoAgent(platform).getVideo(decodedId)
//const [data, related] = await fetchVideoData(decodedId) if (!data.lowResUrl && (!data.srcSet || data.srcSet.length == 0)) {
if (!data.lowResUrl) {
redirect(`/${locale}/404`) redirect(`/${locale}/404`)
} }

View File

@ -27,7 +27,7 @@ const Player: React.FC<Props> = (props) => {
controls: true, controls: true,
responsive: true, responsive: true,
fluid: true, fluid: true,
sources: [{ sources: data.srcSet ?? [{
src: videoSrc, src: videoSrc,
type: videoType type: videoType
}] }]

View File

@ -12,15 +12,17 @@ export interface GalleryData {
platform: Platforms platform: Platforms
} }
export interface VideoSrcSet { export interface VideoSourceItem {
type: string,
src: string,
label: string
} }
export interface VideoData { export interface VideoData {
lowResUrl?: string, lowResUrl?: string,
hiResUrl?: string, hiResUrl?: string,
hlsUrl?: string hlsUrl?: string
srcSet?: VideoSrcSet srcSet?: VideoSourceItem[]
} }
export interface VideoAgent { export interface VideoAgent {

View File

@ -1,4 +1,12 @@
import { PORNHUB_BASE_URL } from "@/constants/urls" import { PORNHUB_BASE_URL } from "@/constants/urls"
import axios, { AxiosHeaders } from "axios"
import { getHeadersWithCookie } from "../common/headers"
import { VideoSourceItem } from "@/meta/data"
interface PornHubVideoSrcElem {
videoUrl: string
quality: string
}
export const getPornHubQueryUrl = async (query?: string): Promise<string> => { export const getPornHubQueryUrl = async (query?: string): Promise<string> => {
if (query) { if (query) {
@ -6,4 +14,33 @@ export const getPornHubQueryUrl = async (query?: string): Promise<string> => {
} }
return PORNHUB_BASE_URL return PORNHUB_BASE_URL
}
export const getPornHubMediaUrlList = async (url: string, sessionCookie: string): Promise<VideoSourceItem[]> => {
const headersWithCookie = getHeadersWithCookie(PORNHUB_BASE_URL, sessionCookie)
let videos: VideoSourceItem[] = []
await axios.get(url, headersWithCookie)
.then(async response => {
if (response.data) {
videos = await response.data.map((elem: PornHubVideoSrcElem) => ({
src: elem?.videoUrl,
type: 'video/mp4',
label: elem?.quality
})) as VideoSourceItem[]
return videos
} else {
return []
}
})
.catch(error => console.log(error))
return videos
} }

View File

@ -1,5 +1,5 @@
import { PORNHUB_BASE_URL, PORNHUB_BASE_URL_VIDEO } from "@/constants/urls"; import { PORNHUB_BASE_URL, PORNHUB_BASE_URL_VIDEO } from "@/constants/urls";
import { FetchParams, GalleryData, VideoData } from "@/meta/data"; import { FetchParams, GalleryData, VideoData, VideoSourceItem } from "@/meta/data";
import { getHeaders, getHeadersWithCookie } from "../common/headers"; import { getHeaders, getHeadersWithCookie } from "../common/headers";
import { getDataFromRedis, storeDataIntoRedis } from "@/redis/client"; import { getDataFromRedis, storeDataIntoRedis } from "@/redis/client";
import { DEFAULT_PORNHUB_VIDEO_EXPIRY, DEFAULT_RELATED_VIDEO_KEY_PATH } from "@/constants/redis"; import { DEFAULT_PORNHUB_VIDEO_EXPIRY, DEFAULT_RELATED_VIDEO_KEY_PATH } from "@/constants/redis";
@ -8,15 +8,19 @@ import * as cheerio from "cheerio";
import axios, { AxiosError } from "axios"; import axios, { AxiosError } from "axios";
import { createSessionCookie, findGetMediaUrlInTagblock } from "../common/mindgeek"; import { createSessionCookie, findGetMediaUrlInTagblock } from "../common/mindgeek";
import { getPornHubMediaUrlList } from "./url";
export const fetchPornHubVideoData = async (videoId: string, params?: FetchParams): Promise<[VideoData, GalleryData[]]> => { export const fetchPornHubVideoData = async (videoId: string, params?: FetchParams): Promise<[VideoData, GalleryData[]]> => {
let data: VideoData = { let data: VideoData = {
lowResUrl: '' lowResUrl: '',
srcSet: []
} }
let related: GalleryData[] = []; let related: GalleryData[] = [];
let mediaUrl, sessionCookie, convertedData: VideoSourceItem[]
let reqHeaders = getHeaders(PORNHUB_BASE_URL) let reqHeaders = getHeaders(PORNHUB_BASE_URL)
const queryUrl = `${PORNHUB_BASE_URL_VIDEO}${videoId.replace(/\//g, '')}` const queryUrl = `${PORNHUB_BASE_URL_VIDEO}${videoId.replace(/\//g, '')}`
@ -28,11 +32,11 @@ export const fetchPornHubVideoData = async (videoId: string, params?: FetchParam
return [cachedVideoData as VideoData, cachedRelatedData as GalleryData[] ?? []] return [cachedVideoData as VideoData, cachedRelatedData as GalleryData[] ?? []]
} }
await axios.get(queryUrl, reqHeaders) await axios.get(queryUrl, reqHeaders)
.then(async response => { .then(async response => {
const sessionCookie = response?.headers["set-cookie"] ? createSessionCookie(response?.headers["set-cookie"]) : ''; sessionCookie = response?.headers["set-cookie"] ? createSessionCookie(response?.headers["set-cookie"]) : '';
const html = response.data; const html = response.data;
@ -40,45 +44,35 @@ export const fetchPornHubVideoData = async (videoId: string, params?: FetchParam
const scriptTags = $("script"); const scriptTags = $("script");
// populate video data object scriptTags.map((idx, elem) => {
scriptTags.map(async (idx, elem) => { const getMediaUrl = findGetMediaUrlInTagblock($(elem).toString()) ?? null
const getMediaUrl = findGetMediaUrlInTagblock($(elem).toString())
if (getMediaUrl) { if (getMediaUrl) {
mediaUrl = getMediaUrl
const headersWithCookie = getHeadersWithCookie(PORNHUB_BASE_URL, sessionCookie)
await axios.get(getMediaUrl, headersWithCookie)
.then(response => {
console.log(response.data)
// magic goes here
})
.catch(error => console.log(error))
} }
// // populate related gallery
// scriptTags.map((idx, elem) => {
// // magic goes here
// })
// await storeDataIntoRedis(queryUrl + DEFAULT_RELATED_VIDEO_KEY_PATH, related, DEFAULT_PORNHUB_VIDEO_EXPIRY);
}) })
await storeDataIntoRedis(queryUrl, data, DEFAULT_PORNHUB_VIDEO_EXPIRY);
// populate related gallery
scriptTags.map((idx, elem) => {
// magic goes here
})
await storeDataIntoRedis(queryUrl + DEFAULT_RELATED_VIDEO_KEY_PATH, related, DEFAULT_PORNHUB_VIDEO_EXPIRY);
}).catch((error: AxiosError) => { }).catch((error: AxiosError) => {
console.log(queryUrl) // error handling goes here
console.log(error.message)
}); });
return [ { lowResUrl: 'https://www.w3schools.com/html/mov_bbb.mp4' } ,[]] if (sessionCookie && mediaUrl) {
convertedData = await getPornHubMediaUrlList(mediaUrl, sessionCookie)
await storeDataIntoRedis(queryUrl, convertedData, DEFAULT_PORNHUB_VIDEO_EXPIRY);
data.srcSet = convertedData.reverse()
}
return [ data, []]
// return [ { lowResUrl: 'https://www.w3schools.com/html/mov_bbb.mp4' } ,[]]
} }

View File

@ -8,12 +8,13 @@ import { Platforms } from '@/meta/settings';
import { getDataFromRedis, storeDataIntoRedis } from '@/redis/client'; import { getDataFromRedis, storeDataIntoRedis } from '@/redis/client';
import { DEFAULT_XVIDEOS_CONTENT_EXPIRY } from '@/constants/redis'; import { DEFAULT_XVIDEOS_CONTENT_EXPIRY } from '@/constants/redis';
import { XVIDEOS_BASE_URL } from '@/constants/urls';
export const fetchXVideosGalleryData = async (params?: FetchParams): Promise<GalleryData[]> => { export const fetchXVideosGalleryData = async (params?: FetchParams): Promise<GalleryData[]> => {
let data: GalleryData[] = []; let data: GalleryData[] = [];
const reqHeaders = getHeaders() const reqHeaders = getHeaders(XVIDEOS_BASE_URL)
const queryUrl = await getXVideosQueryUrl(params?.query) const queryUrl = await getXVideosQueryUrl(params?.query)