Skip to content

Commit

Permalink
feat(route): imdb top charts (#15697)
Browse files Browse the repository at this point in the history
* feat(route): imdb top charts

* fix: typo
  • Loading branch information
TonyRL committed May 24, 2024
1 parent fe683a1 commit bc3b3e2
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 0 deletions.
61 changes: 61 additions & 0 deletions lib/routes/imdb/chart.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Route } from '@/types';
import ofetch from '@/utils/ofetch';
import * as cheerio from 'cheerio';
import type { Context } from 'hono';
import { ChartTitleSearchConnection } from './types';
import path from 'path';
import { getCurrentPath } from '@/utils/helpers';
import { art } from '@/utils/render';

const __dirname = getCurrentPath(import.meta.url);
const render = (data) => art(path.join(__dirname, 'templates', 'chart.art'), data);

export const route: Route = {
path: '/chart/:chart?',
categories: ['multimedia'],
parameters: { chart: 'The chart to display, `top` by default' },
example: '/imdb/chart',
radar: [
{
source: ['www.imdb.com/chart/:chart/'],
},
],
name: 'Charts',
maintainers: ['TonyRL'],
handler,
url: 'www.imdb.com/chart/top/',
description: `| Top 250 Movies | Most Popular Movies | Top 250 TV Shows | Most Popular TV Shows |
| -------------- | ------------------- | ---------------- | --------------------- |
| top | moviemeter | toptv | tvmeter |`,
};

async function handler(ctx: Context) {
const { chart = 'top' } = ctx.req.param();
const baseUrl = 'https://www.imdb.com';
const link = `${baseUrl}/chart/${chart}/`;

const response = await ofetch(link);
const $ = cheerio.load(response);
const nextData = JSON.parse($('script#__NEXT_DATA__').text());
const chartTitles = nextData.props.pageProps.pageData.chartTitles as ChartTitleSearchConnection;

const items = chartTitles.edges.map(({ currentRank, node }) => ({
title: `${currentRank}. ${node.titleText.text} (${node.releaseYear.year}${node.releaseYear.endYear ? `-${node.releaseYear.endYear}` : ''})`,
description: render({
primaryImage: node.primaryImage,
originalTitleText: node.originalTitleText,
certificate: node.certificate,
ratingsSummary: node.ratingsSummary,
plot: node.plot,
}),
link: `${baseUrl}/title/${node.id}`,
category: node.titleGenres.genres.map((g) => chartTitles.genres.find((genre) => genre.filterId === g.genre.text)?.text),
}));

return {
title: $('head title').text(),
description: $('head meta[name="description"]').attr('content'),
link,
item: items,
};
}
6 changes: 6 additions & 0 deletions lib/routes/imdb/namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import type { Namespace } from '@/types';

export const namespace: Namespace = {
name: 'IMDb',
url: 'www.imdb.com',
};
15 changes: 15 additions & 0 deletions lib/routes/imdb/templates/chart.art
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{{ if primaryImage.url }}
<figure>
<img src="{{ primaryImage.url }}" alt="{{ primaryImage.caption.plainText }}" />
<figcaption>{{ primaryImage.caption.plainText }}</figcaption>
</figure>
<br>
{{ /if }}

Original title: {{ originalTitleText.text }}<br>

{{ if certificate }}{{ certificate.rating }}{{ /if }}
{{ if ratingsSummary.aggregateRating }}IMDb RATING: {{ ratingsSummary.aggregateRating }}/10 ({{ ratingsSummary.voteCount }}){{ /if }}
<br><br>

{{ plot.plotText.plainText }}
103 changes: 103 additions & 0 deletions lib/routes/imdb/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
interface SearchFacet {
filterId: string;
text: string;
total: number;
__typename: string;
}

interface TitleGenres {
genre: {
text: string;
__typename: string;
};
__typename: string;
}

interface Title {
id: string;
titleText: {
text: string;
__typename: string;
};
titleType: {
id: string;
text: string;
canHaveEpisodes: boolean;
displayableProperty: {
value: {
plainText: string;
__typename: string;
};
__typename: string;
};
__typename: string;
};
originalTitleText: {
text: string;
__typename: string;
};
primaryImage: {
id: string;
width: number;
height: number;
url: string;
caption: {
plainText: string;
__typename: string;
};
__typename: string;
};
releaseYear: {
year: number;
endYear: number | null;
__typename: string;
};
ratingsSummary: {
aggregateRating: number;
voteCount: number;
__typename: string;
};
runtime: {
seconds: number;
__typename: string;
};
certificate: {
rating: string;
__typename: string;
} | null;
canRate: {
isRatable: boolean;
__typename: string;
};
titleGenres: {
genres: TitleGenres[];
__typename: string;
};
canHaveEpisodes: boolean;
plot: {
plotText: {
plainText: string;
__typename: string;
};
__typename: string;
};
latestTrailer: {
id: string;
__typename: string;
} | null;
series: null;
__typename: string;
}

interface ChartTitleEdge {
currentRank: number;
node: Title;
__typename: string;
}

export interface ChartTitleSearchConnection {
edges: ChartTitleEdge[];
genres: SearchFacet[];
keywords: SearchFacet[];
__typename: string;
}

0 comments on commit bc3b3e2

Please sign in to comment.