Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions lib/routes/gettyimages/description.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { renderToString } from 'hono/jsx/dom/server';

export const renderSearchItemDescription = (imageSrc: string): string =>
renderToString(
<figure>
<img src={imageSrc} />
</figure>
);
7 changes: 7 additions & 0 deletions lib/routes/gettyimages/namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Namespace } from '@/types';

export const namespace: Namespace = {
name: 'Getty Images Australia',
url: 'www.gettyimages.com.au',
lang: 'en',
};
100 changes: 100 additions & 0 deletions lib/routes/gettyimages/search.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import type { Cheerio, CheerioAPI } from 'cheerio';
import { load } from 'cheerio';
import type { Element } from 'domhandler';
import type { Context } from 'hono';

import { config } from '@/config';
import type { DataItem, Route } from '@/types';
import { ViewType } from '@/types';
import ofetch from '@/utils/ofetch';

import { renderSearchItemDescription } from './description';

const getTitleFromElement = ($element: Cheerio<Element>): string | undefined => $element.attr('aria-label') || $element.find('img').attr('alt') || $element.text() || undefined;

const getImageFromElement = ($element: Cheerio<Element>): string | undefined =>
$element.find('img').attr('src') || $element.find('img').attr('data-src') || $element.find('img').attr('data-lazy-src') || $element.find('img').attr('data-image-src');

export const route: Route = {
path: '/search/:keyword',
categories: ['picture'],
view: ViewType.Pictures,
description:
'Image search results on the first page only. Radar cannot extract the `phrase` query string; subscribe with `/gettyimages/search/:keyword` manually (e.g. `/gettyimages/search/kangaroo`). The listing does not provide reliable publish dates.',
url: 'www.gettyimages.com.au',
example: '/gettyimages/search/kangaroo',
parameters: {
keyword: 'Search keyword',
},
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportRadar: true,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
radar: [
{
source: ['www.gettyimages.com.au/search/2/image'],
target: '/search/:keyword',
},
],
name: 'Search',
maintainers: ['QwQ-OvO'],
handler,
};

async function handler(ctx: Context) {
const keyword = ctx.req.param('keyword');
if (!keyword) {
throw new Error('Missing required parameter: keyword');
}
Comment on lines +51 to +53
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreachable condition.

path: '/search/:keyword',
defines keyword as compulsory path parameter. If one visits the route without it, the request will be rejected by hono with a 404 error.


const baseUrl = 'https://www.gettyimages.com.au';
const searchUrl = `${baseUrl}/search/2/image?phrase=${encodeURIComponent(keyword)}`;

const response = await ofetch<string>(searchUrl, {
headers: {
'User-Agent': config.trueUA,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the site only work when using this exact UA instead of RSSHub's random generated UA?

},
});
const $: CheerioAPI = load(response);

const seen = new Set<string>();
const list: DataItem[] = [];
for (const element of $('a[href^="/detail/"]').toArray()) {
const $element: Cheerio<Element> = $(element);
const href = $element.attr('href');
if (!href) {
continue;
}

const link = new URL(href, baseUrl);
link.search = '';
link.hash = '';
const normalizedLink = link.toString();

if (seen.has(normalizedLink)) {
continue;
}
seen.add(normalizedLink);

const title = getTitleFromElement($element) || normalizedLink;
const image = getImageFromElement($element);

list.push({
title,
link: normalizedLink,
guid: normalizedLink,
description: image ? renderSearchItemDescription(image) : undefined,
});
}
Comment on lines +65 to +93
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the number 1 anti-pattern listed in Script Standard.

Comment on lines +65 to +93
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the embeded JSON in data-component="Search" instead.


return {
title: `Getty Images Australia - ${keyword}`,
link: searchUrl,
item: list,
};
}
Loading