feat(routes): Add img=1 option to pornhub handlers to pass through images (#21324)
* Add img=1 option to pornhub handlers to pass through images * Move img=1 to a path parameter, and add clarifications on :lang, etc because each must be set to set the following --------- Co-authored-by: acidicxjrl <acidicxjrl>
This commit is contained in:
parent
1ad606f40f
commit
7c5c66a75b
|
|
@ -8,10 +8,10 @@ import { isValidHost } from '@/utils/valid-host';
|
|||
import { headers, parseItems } from './utils';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/category_url/:url?/:language?',
|
||||
path: '/category_url/:url?/:language?/:img?',
|
||||
categories: ['multimedia'],
|
||||
example: '/pornhub/category_url/video%3Fc%3D15%26o%3Dmv%26t%3Dw%26cc%3Djp',
|
||||
parameters: { language: 'language, see below', url: 'relative path after `pornhub.com/`, need to be URL encoded' },
|
||||
parameters: { language: 'language, see below. defaults to `www` (English)', url: 'relative path after `pornhub.com/`, need to be URL encoded', img: 'show images, set to `img=1` to enable' },
|
||||
features: {
|
||||
requireConfig: false,
|
||||
requirePuppeteer: false,
|
||||
|
|
@ -34,7 +34,7 @@ export const route: Route = {
|
|||
};
|
||||
|
||||
async function handler(ctx) {
|
||||
const { language = 'www', url = 'video' } = ctx.req.param();
|
||||
const { language = 'www', url = 'video', img } = ctx.req.param();
|
||||
const link = `https://${language}.pornhub.com/${url}`;
|
||||
if (!isValidHost(language)) {
|
||||
throw new InvalidParameterError('Invalid language');
|
||||
|
|
@ -42,14 +42,15 @@ async function handler(ctx) {
|
|||
|
||||
const { data: response } = await got(link, { headers });
|
||||
const $ = load(response);
|
||||
const showImages = img === 'img=1';
|
||||
const items = $('#videoCategory .videoBox')
|
||||
.toArray()
|
||||
.map((e) => parseItems($(e)));
|
||||
.map((e) => parseItems($(e), showImages));
|
||||
|
||||
return {
|
||||
title: $('title').first().text(),
|
||||
link,
|
||||
language: $('html').attr('lang'),
|
||||
language: $('html').attr('lang') as any,
|
||||
item: items,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import { defaultDomain, renderDescription } from './utils';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/category/:caty',
|
||||
path: '/category/:caty/:img?',
|
||||
categories: ['multimedia'],
|
||||
view: ViewType.Videos,
|
||||
example: '/pornhub/category/popular-with-women',
|
||||
parameters: { caty: 'category, see [categories](https://www.pornhub.com/webmasters/categories)' },
|
||||
parameters: { caty: 'category, see [categories](https://www.pornhub.com/webmasters/categories)', img: 'show images, set to `img=1` to enable' },
|
||||
features: {
|
||||
requireConfig: false,
|
||||
requirePuppeteer: false,
|
||||
|
|
@ -28,7 +28,7 @@ export const route: Route = {
|
|||
};
|
||||
|
||||
async function handler(ctx) {
|
||||
const category = ctx.req.param('caty');
|
||||
const { caty: category, img } = ctx.req.param();
|
||||
|
||||
const categories = await cache.tryGet('pornhub:categories', async () => {
|
||||
const { data } = await got(`${defaultDomain}/webmasters/categories`);
|
||||
|
|
@ -52,10 +52,12 @@ async function handler(ctx) {
|
|||
throw new Error(response.message);
|
||||
}
|
||||
|
||||
const showImages = img === 'img=1';
|
||||
|
||||
const list = response.videos.map((item) => ({
|
||||
title: item.title,
|
||||
link: item.url,
|
||||
description: renderDescription({ thumbs: item.thumbs }),
|
||||
description: renderDescription({ thumbs: item.thumbs }, showImages),
|
||||
pubDate: parseDate(item.publish_date),
|
||||
category: [...new Set([...item.tags.map((t) => t.tag_name), ...item.categories.map((c) => c.category)])],
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -9,11 +9,16 @@ import { isValidHost } from '@/utils/valid-host';
|
|||
import { getRadarDomin, headers, parseItems } from './utils';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/model/:username/:language?/:sort?',
|
||||
path: '/model/:username/:language?/:sort?/:img?',
|
||||
categories: ['multimedia'],
|
||||
view: ViewType.Videos,
|
||||
example: '/pornhub/model/stacy-starando',
|
||||
parameters: { language: 'language, see below', username: 'username, part of the url e.g. `pornhub.com/model/stacy-starando`', sort: 'sorting method, see below' },
|
||||
parameters: {
|
||||
language: 'language, see below. defaults to www',
|
||||
username: 'username, part of the url e.g. `pornhub.com/model/stacy-starando`',
|
||||
sort: 'sorting method, see below. Defaults to mr (most recent)',
|
||||
img: 'show images, set to `img=1` to enable',
|
||||
},
|
||||
features: {
|
||||
requireConfig: false,
|
||||
requirePuppeteer: false,
|
||||
|
|
@ -30,7 +35,7 @@ export const route: Route = {
|
|||
};
|
||||
|
||||
async function handler(ctx): Promise<Data> {
|
||||
const { language = 'www', username, sort = '' } = ctx.req.param();
|
||||
const { language = 'www', username, sort = '', img } = ctx.req.param();
|
||||
const link = `https://${language}.pornhub.com/model/${username}/videos${sort ? `?o=${sort}` : ''}`;
|
||||
if (!isValidHost(language)) {
|
||||
throw new InvalidParameterError('Invalid language');
|
||||
|
|
@ -38,16 +43,17 @@ async function handler(ctx): Promise<Data> {
|
|||
|
||||
const { data: response } = await got(link, { headers });
|
||||
const $ = load(response);
|
||||
const showImages = img === 'img=1';
|
||||
const items = $('#mostRecentVideosSection .videoBox')
|
||||
.toArray()
|
||||
.map((e) => parseItems($(e)));
|
||||
.map((e) => parseItems($(e), showImages));
|
||||
|
||||
return {
|
||||
title: $('h1').first().text(),
|
||||
description: $('section.aboutMeSection').text().trim(),
|
||||
link,
|
||||
image: $('#getAvatar').attr('src'),
|
||||
language: $('html').attr('lang'),
|
||||
language: $('html').attr('lang') as any,
|
||||
item: items,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { isValidHost } from '@/utils/valid-host';
|
|||
import { getRadarDomin, headers, parseItems } from './utils';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/pornstar/:username/:language?/:sort?',
|
||||
path: '/pornstar/:username/:language?/:sort?/:img?',
|
||||
categories: ['multimedia'],
|
||||
view: ViewType.Videos,
|
||||
example: '/pornhub/pornstar/june-liu/www/mr',
|
||||
|
|
@ -18,7 +18,7 @@ export const route: Route = {
|
|||
description: 'username, part of the url e.g. `pornhub.com/pornstar/june-liu`',
|
||||
},
|
||||
language: {
|
||||
description: 'language',
|
||||
description: 'language, defaults to `www` (English)',
|
||||
options: [
|
||||
{ value: 'www', label: 'English' },
|
||||
{ value: 'de', label: 'Deutsch' },
|
||||
|
|
@ -36,7 +36,7 @@ export const route: Route = {
|
|||
default: 'www',
|
||||
},
|
||||
sort: {
|
||||
description: 'sorting method, leave empty for `Best`',
|
||||
description: 'sorting method, defaults to `mr` (Most Recent)',
|
||||
options: [
|
||||
{
|
||||
label: 'Most Recent',
|
||||
|
|
@ -56,6 +56,7 @@ export const route: Route = {
|
|||
},
|
||||
],
|
||||
},
|
||||
img: 'show images, set to `img=1` to enable',
|
||||
},
|
||||
features: {
|
||||
requireConfig: false,
|
||||
|
|
@ -73,7 +74,7 @@ export const route: Route = {
|
|||
};
|
||||
|
||||
async function handler(ctx): Promise<Data> {
|
||||
const { language = 'www', username, sort = 'mr' } = ctx.req.param();
|
||||
const { language = 'www', username, sort = 'mr', img } = ctx.req.param();
|
||||
let link = `https://${language}.pornhub.com/pornstar/${username}?o=${sort}`;
|
||||
if (!isValidHost(language)) {
|
||||
throw new InvalidParameterError('Invalid language');
|
||||
|
|
@ -83,17 +84,19 @@ async function handler(ctx): Promise<Data> {
|
|||
let $ = load(response);
|
||||
let items;
|
||||
|
||||
const showImages = img === 'img=1';
|
||||
|
||||
if ($('.withBio').length === 0) {
|
||||
link = `https://${language}.pornhub.com/pornstar/${username}/videos?o=${sort}`;
|
||||
const { data: response } = await got(link, { headers });
|
||||
$ = load(response);
|
||||
items = $('#mostRecentVideosSection .videoBox')
|
||||
.toArray()
|
||||
.map((e) => parseItems($(e)));
|
||||
.map((e) => parseItems($(e), showImages));
|
||||
} else {
|
||||
items = $('#pornstarsVideoSection .videoBox')
|
||||
.toArray()
|
||||
.map((e) => parseItems($(e)));
|
||||
.map((e) => parseItems($(e), showImages));
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
@ -101,7 +104,7 @@ async function handler(ctx): Promise<Data> {
|
|||
description: $('section.aboutMeSection').text().trim(),
|
||||
link,
|
||||
image: $('#getAvatar').attr('src'),
|
||||
language: $('html').attr('lang'),
|
||||
language: $('html').attr('lang') as any,
|
||||
item: items,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ import { parseDate } from '@/utils/parse-date';
|
|||
import { defaultDomain, renderDescription } from './utils';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/search/:keyword',
|
||||
path: '/search/:keyword/:img?',
|
||||
categories: ['multimedia'],
|
||||
view: ViewType.Videos,
|
||||
example: '/pornhub/search/stepsister',
|
||||
parameters: { keyword: 'keyword' },
|
||||
parameters: { keyword: 'keyword', img: 'show images, set to `img=1` to enable' },
|
||||
features: {
|
||||
requireConfig: false,
|
||||
requirePuppeteer: false,
|
||||
|
|
@ -26,14 +26,16 @@ export const route: Route = {
|
|||
};
|
||||
|
||||
async function handler(ctx) {
|
||||
const keyword = ctx.req.param('keyword');
|
||||
const { keyword, img } = ctx.req.param();
|
||||
const currentUrl = `${defaultDomain}/webmasters/search?search=${keyword}`;
|
||||
const response = await got(currentUrl);
|
||||
|
||||
const showImages = img === 'img=1';
|
||||
|
||||
const list = response.data.videos.map((item) => ({
|
||||
title: item.title,
|
||||
link: item.url,
|
||||
description: renderDescription({ thumbs: item.thumbs }),
|
||||
description: renderDescription({ thumbs: item.thumbs }, showImages),
|
||||
pubDate: parseDate(item.publish_date),
|
||||
category: [...new Set([...item.tags.map((t) => t.tag_name), ...item.categories.map((c) => c.category)])],
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ import { isValidHost } from '@/utils/valid-host';
|
|||
import { getRadarDomin, headers, parseItems } from './utils';
|
||||
|
||||
export const route: Route = {
|
||||
path: '/users/:username/:language?',
|
||||
path: '/users/:username/:language?/:img?',
|
||||
categories: ['multimedia'],
|
||||
example: '/pornhub/users/pornhubmodels',
|
||||
parameters: { language: 'language, see below', username: 'username, part of the url e.g. `pornhub.com/users/pornhubmodels`' },
|
||||
parameters: { language: 'language, see below. defaults to `www` (English)', username: 'username, part of the url e.g. `pornhub.com/users/pornhubmodels`', img: 'show images, set to `img=1` to enable' },
|
||||
features: {
|
||||
requireConfig: false,
|
||||
requirePuppeteer: false,
|
||||
|
|
@ -28,7 +28,7 @@ export const route: Route = {
|
|||
};
|
||||
|
||||
async function handler(ctx): Promise<Data> {
|
||||
const { language = 'www', username } = ctx.req.param();
|
||||
const { language = 'www', username, img } = ctx.req.param();
|
||||
const link = `https://${language}.pornhub.com/users/${username}/videos`;
|
||||
if (!isValidHost(language)) {
|
||||
throw new InvalidParameterError('Invalid language');
|
||||
|
|
@ -36,16 +36,17 @@ async function handler(ctx): Promise<Data> {
|
|||
|
||||
const { data: response } = await got(link, { headers });
|
||||
const $ = load(response);
|
||||
const showImages = img === 'img=1';
|
||||
const items = $('.videoUList .videoBox')
|
||||
.toArray()
|
||||
.map((e) => parseItems($(e)));
|
||||
.map((e) => parseItems($(e), showImages));
|
||||
|
||||
return {
|
||||
title: $('.profileUserName a').text(),
|
||||
description: $('.aboutMeText').text().trim(),
|
||||
link,
|
||||
image: $('#getAvatar').attr('src'),
|
||||
language: $('html').attr('lang'),
|
||||
language: $('html').attr('lang') as any,
|
||||
allowEmpty: true,
|
||||
item: items,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ const headers = {
|
|||
hasVisited: 1,
|
||||
};
|
||||
|
||||
const renderDescription = (data): string =>
|
||||
const renderDescription = (data, showImages = false): string =>
|
||||
renderToString(
|
||||
<>
|
||||
{data.previewVideo ? (
|
||||
|
|
@ -18,9 +18,12 @@ const renderDescription = (data): string =>
|
|||
<source src={data.previewVideo} type="video/webm" />
|
||||
</video>
|
||||
) : null}
|
||||
{data.thumbs?.map((thumb, index) => (
|
||||
<img key={`${thumb.src}-${index}`} src={thumb.src} />
|
||||
))}
|
||||
{showImages &&
|
||||
(data.thumbs ? (
|
||||
data.thumbs.map((thumb, index) => <img key={`${thumb.src}-${index}`} src={thumb.src} />)
|
||||
) : (
|
||||
<img src={data.poster} />
|
||||
))}
|
||||
</>
|
||||
);
|
||||
const extractDateFromImageUrl = (imageUrl) => {
|
||||
|
|
@ -28,13 +31,16 @@ const extractDateFromImageUrl = (imageUrl) => {
|
|||
return matchResult ? matchResult.slice(1, 3).join('') : null;
|
||||
};
|
||||
|
||||
const parseItems = (e) => ({
|
||||
const parseItems = (e, showImages = false) => ({
|
||||
title: e.find('span.title a').text().trim(),
|
||||
link: defaultDomain + e.find('span.title a').attr('href'),
|
||||
description: renderDescription({
|
||||
poster: e.find('img').data('mediumthumb'),
|
||||
previewVideo: e.find('img').data('mediabook'),
|
||||
}),
|
||||
description: renderDescription(
|
||||
{
|
||||
poster: e.find('img').data('mediumthumb'),
|
||||
previewVideo: e.find('img').data('mediabook'),
|
||||
},
|
||||
showImages
|
||||
),
|
||||
author: e.find('.usernameWrap a').text(),
|
||||
pubDate: dayjs(extractDateFromImageUrl(e.find('img').data('mediumthumb'))).toDate() || parseRelativeDate(e.find('.added').text()),
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue