mirror of
https://github.com/movie-web/providers.git
synced 2025-09-13 14:33:26 +00:00
move script into src
This commit is contained in:
@@ -36,7 +36,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:dev": "ts-node ./run-source.ts",
|
"test:dev": "npx ts-node ./src/dev-cli.ts",
|
||||||
"test:watch": "vitest",
|
"test:watch": "vitest",
|
||||||
"test:coverage": "vitest run --coverage",
|
"test:coverage": "vitest run --coverage",
|
||||||
"lint": "eslint --ext .ts,.js src/",
|
"lint": "eslint --ext .ts,.js src/",
|
||||||
|
@@ -1,9 +1,14 @@
|
|||||||
import nodeFetch from 'node-fetch';
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
import { prompt } from 'enquirer';
|
|
||||||
import Spinnies from 'spinnies';
|
|
||||||
import { program } from 'commander';
|
import { program } from 'commander';
|
||||||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
import { makeProviders, targets, makeStandardFetcher, MovieMedia, ShowMedia, ProviderControls, MetaOutput } from '.';
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
|
import { prompt } from 'enquirer';
|
||||||
|
import nodeFetch from 'node-fetch';
|
||||||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
|
import Spinnies from 'spinnies';
|
||||||
|
|
||||||
|
import { MetaOutput, MovieMedia, ProviderControls, ShowMedia, makeProviders, makeStandardFetcher, targets } from '..';
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
|
||||||
@@ -49,8 +54,8 @@ function getAllSources() {
|
|||||||
// * create all these things. Maybe this should change
|
// * create all these things. Maybe this should change
|
||||||
const providers = makeProviders({
|
const providers = makeProviders({
|
||||||
fetcher: makeStandardFetcher(nodeFetch),
|
fetcher: makeStandardFetcher(nodeFetch),
|
||||||
target: targets.NATIVE
|
target: targets.NATIVE,
|
||||||
})
|
});
|
||||||
|
|
||||||
const sources = providers.listSources();
|
const sources = providers.listSources();
|
||||||
const embeds = providers.listEmbeds();
|
const embeds = providers.listEmbeds();
|
||||||
@@ -58,9 +63,9 @@ function getAllSources() {
|
|||||||
const combined = [...sources, ...embeds];
|
const combined = [...sources, ...embeds];
|
||||||
|
|
||||||
// * Remove dupes
|
// * Remove dupes
|
||||||
const map = new Map(combined.map(source => [source.id, source]));
|
const map = new Map(combined.map((source) => [source.id, source]));
|
||||||
|
|
||||||
return [...map.values()]
|
return [...map.values()];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function makeTMDBRequest(url: string): Promise<Response> {
|
async function makeTMDBRequest(url: string): Promise<Response> {
|
||||||
@@ -68,7 +73,7 @@ async function makeTMDBRequest(url: string): Promise<Response> {
|
|||||||
accept: 'application/json';
|
accept: 'application/json';
|
||||||
authorization?: string;
|
authorization?: string;
|
||||||
} = {
|
} = {
|
||||||
accept: 'application/json'
|
accept: 'application/json',
|
||||||
};
|
};
|
||||||
|
|
||||||
// * JWT keys always start with ey and are ONLY valid as a header.
|
// * JWT keys always start with ey and are ONLY valid as a header.
|
||||||
@@ -82,7 +87,7 @@ async function makeTMDBRequest(url: string): Promise<Response> {
|
|||||||
|
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: headers
|
headers,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +107,7 @@ async function getMovieMediaDetails(id: string): Promise<MovieMedia> {
|
|||||||
type: 'movie',
|
type: 'movie',
|
||||||
title: movie.title,
|
title: movie.title,
|
||||||
releaseYear: Number(movie.release_date.split('-')[0]),
|
releaseYear: Number(movie.release_date.split('-')[0]),
|
||||||
tmdbId: id
|
tmdbId: id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +132,9 @@ async function getShowMediaDetails(id: string, seasonNumber: string, episodeNumb
|
|||||||
throw new Error(season.status_message);
|
throw new Error(season.status_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
response = await makeTMDBRequest(`https://api.themoviedb.org/3/tv/${id}/season/${seasonNumber}/episode/${episodeNumber}`);
|
response = await makeTMDBRequest(
|
||||||
|
`https://api.themoviedb.org/3/tv/${id}/season/${seasonNumber}/episode/${episodeNumber}`,
|
||||||
|
);
|
||||||
const episode = await response.json();
|
const episode = await response.json();
|
||||||
|
|
||||||
if (episode.success === false) {
|
if (episode.success === false) {
|
||||||
@@ -141,26 +148,27 @@ async function getShowMediaDetails(id: string, seasonNumber: string, episodeNumb
|
|||||||
tmdbId: id,
|
tmdbId: id,
|
||||||
episode: {
|
episode: {
|
||||||
number: episode.episode_number,
|
number: episode.episode_number,
|
||||||
tmdbId: episode.id
|
tmdbId: episode.id,
|
||||||
},
|
},
|
||||||
season: {
|
season: {
|
||||||
number: season.season_number,
|
number: season.season_number,
|
||||||
tmdbId: season.id
|
tmdbId: season.id,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function joinMediaTypes(mediaTypes: string[] | undefined) {
|
function joinMediaTypes(mediaTypes: string[] | undefined) {
|
||||||
if (mediaTypes) {
|
if (mediaTypes) {
|
||||||
const formatted = mediaTypes.map((type: string) => {
|
const formatted = mediaTypes
|
||||||
type = type[0].toUpperCase() + type.substring(1).toLowerCase();
|
.map((type: string) => {
|
||||||
return `${type}s`;
|
type = type[0].toUpperCase() + type.substring(1).toLowerCase();
|
||||||
}).join(' / ');
|
return `${type}s`;
|
||||||
|
})
|
||||||
|
.join(' / ');
|
||||||
|
|
||||||
return `(${formatted})`;
|
return `(${formatted})`;
|
||||||
} else {
|
|
||||||
return ''; // * Embed sources pass through here too
|
|
||||||
}
|
}
|
||||||
|
return ''; // * Embed sources pass through here too
|
||||||
}
|
}
|
||||||
|
|
||||||
async function runQuestions() {
|
async function runQuestions() {
|
||||||
@@ -171,7 +179,7 @@ async function runQuestions() {
|
|||||||
type: 'movie',
|
type: 'movie',
|
||||||
season: '0',
|
season: '0',
|
||||||
episode: '0',
|
episode: '0',
|
||||||
url: ''
|
url: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
const answers = await prompt<CommonAnswers>([
|
const answers = await prompt<CommonAnswers>([
|
||||||
@@ -181,39 +189,38 @@ async function runQuestions() {
|
|||||||
message: 'Select a fetcher',
|
message: 'Select a fetcher',
|
||||||
choices: [
|
choices: [
|
||||||
{
|
{
|
||||||
|
|
||||||
message: 'Native',
|
message: 'Native',
|
||||||
name: 'native'
|
name: 'native',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message: 'Node fetch',
|
message: 'Node fetch',
|
||||||
name: 'node-fetch'
|
name: 'node-fetch',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
name: 'source',
|
name: 'source',
|
||||||
message: 'Select a source',
|
message: 'Select a source',
|
||||||
choices: sources.map(source => ({
|
choices: sources.map((source) => ({
|
||||||
message: `[${source.type.toLocaleUpperCase()}] ${source.name} ${joinMediaTypes(source.mediaTypes)}`.trim(),
|
message: `[${source.type.toLocaleUpperCase()}] ${source.name} ${joinMediaTypes(source.mediaTypes)}`.trim(),
|
||||||
name: source.id
|
name: source.id,
|
||||||
}))
|
})),
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
options.fetcher = answers.fetcher;
|
options.fetcher = answers.fetcher;
|
||||||
options.sourceId = answers.source;
|
options.sourceId = answers.source;
|
||||||
|
|
||||||
const source = sources.find(source => source.id === answers.source)!;
|
const source = sources.find((source) => source.id === answers.source)!;
|
||||||
|
|
||||||
if (source.type === 'embed') {
|
if (source.type === 'embed') {
|
||||||
const sourceAnswers = await prompt<EmbedSourceAnswers>([
|
const sourceAnswers = await prompt<EmbedSourceAnswers>([
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'url',
|
name: 'url',
|
||||||
message: 'Embed URL'
|
message: 'Embed URL',
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
options.url = sourceAnswers.url;
|
options.url = sourceAnswers.url;
|
||||||
@@ -222,7 +229,7 @@ async function runQuestions() {
|
|||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'id',
|
name: 'id',
|
||||||
message: 'TMDB ID'
|
message: 'TMDB ID',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'select',
|
type: 'select',
|
||||||
@@ -231,14 +238,14 @@ async function runQuestions() {
|
|||||||
choices: [
|
choices: [
|
||||||
{
|
{
|
||||||
message: 'Movie',
|
message: 'Movie',
|
||||||
name: 'movie'
|
name: 'movie',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
message: 'TV Show',
|
message: 'TV Show',
|
||||||
name: 'show'
|
name: 'show',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
options.tmdbId = sourceAnswers.id;
|
options.tmdbId = sourceAnswers.id;
|
||||||
@@ -249,13 +256,13 @@ async function runQuestions() {
|
|||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'season',
|
name: 'season',
|
||||||
message: 'Season'
|
message: 'Season',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'episode',
|
name: 'episode',
|
||||||
message: 'Episode'
|
message: 'Episode',
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
options.season = seriesAnswers.season;
|
options.season = seriesAnswers.season;
|
||||||
@@ -268,13 +275,13 @@ async function runQuestions() {
|
|||||||
|
|
||||||
async function runCommandLine() {
|
async function runCommandLine() {
|
||||||
program
|
program
|
||||||
.option('-f, --fetcher <fetcher>', 'Fetcher to use. Either \'native\' or \'node-fetch\'', 'node-fetch')
|
.option('-f, --fetcher <fetcher>', "Fetcher to use. Either 'native' or 'node-fetch'", 'node-fetch')
|
||||||
.option('-sid, --source-id <id>', 'ID for the source to use. Either an embed or provider', '')
|
.option('-sid, --source-id <id>', 'ID for the source to use. Either an embed or provider', '')
|
||||||
.option('-tid, --tmdb-id <id>', 'TMDB ID for the media to scrape. Only used if source is a provider', '')
|
.option('-tid, --tmdb-id <id>', 'TMDB ID for the media to scrape. Only used if source is a provider', '')
|
||||||
.option('-t, --type <type>', 'Media type. Either \'movie\' or \'show\'. Only used if source is a provider', 'movie')
|
.option('-t, --type <type>', "Media type. Either 'movie' or 'show'. Only used if source is a provider", 'movie')
|
||||||
.option('-s, --season <number>', 'Season number. Only used if type is \'show\'', '0')
|
.option('-s, --season <number>', "Season number. Only used if type is 'show'", '0')
|
||||||
.option('-e, --episode <number>', 'Episode number. Only used if type is \'show\'', '0')
|
.option('-e, --episode <number>', "Episode number. Only used if type is 'show'", '0')
|
||||||
.option('-u, --url <embed URL>', 'URL to a video embed. Only used if source is an embed', '')
|
.option('-u, --url <embed URL>', 'URL to a video embed. Only used if source is an embed', '');
|
||||||
|
|
||||||
program.parse();
|
program.parse();
|
||||||
|
|
||||||
@@ -283,14 +290,14 @@ async function runCommandLine() {
|
|||||||
|
|
||||||
async function processOptions(options: CommandLineArguments) {
|
async function processOptions(options: CommandLineArguments) {
|
||||||
if (options.fetcher !== 'node-fetch' && options.fetcher !== 'native') {
|
if (options.fetcher !== 'node-fetch' && options.fetcher !== 'native') {
|
||||||
throw new Error('Fetcher must be either \'native\' or \'node-fetch\'');
|
throw new Error("Fetcher must be either 'native' or 'node-fetch'");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.sourceId.trim()) {
|
if (!options.sourceId.trim()) {
|
||||||
throw new Error('Source ID must be provided');
|
throw new Error('Source ID must be provided');
|
||||||
}
|
}
|
||||||
|
|
||||||
const source = sources.find(source => source.id === options.sourceId);
|
const source = sources.find((source) => source.id === options.sourceId);
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
throw new Error('Invalid source ID. No source found');
|
throw new Error('Invalid source ID. No source found');
|
||||||
@@ -314,7 +321,7 @@ async function processOptions(options: CommandLineArguments) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.type !== 'movie' && options.type !== 'show') {
|
if (options.type !== 'movie' && options.type !== 'show') {
|
||||||
throw new Error('Invalid media type. Must be either \'movie\' or \'show\'');
|
throw new Error("Invalid media type. Must be either 'movie' or 'show'");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.type === 'show') {
|
if (options.type === 'show') {
|
||||||
@@ -345,8 +352,8 @@ async function processOptions(options: CommandLineArguments) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const providers = makeProviders({
|
const providers = makeProviders({
|
||||||
fetcher: fetcher,
|
fetcher,
|
||||||
target: targets.NATIVE
|
target: targets.NATIVE,
|
||||||
});
|
});
|
||||||
|
|
||||||
await runScraper(providers, source, options);
|
await runScraper(providers, source, options);
|
||||||
@@ -360,7 +367,7 @@ async function runScraper(providers: ProviderControls, source: MetaOutput, optio
|
|||||||
try {
|
try {
|
||||||
const result = await providers.runEmbedScraper({
|
const result = await providers.runEmbedScraper({
|
||||||
url: options.url,
|
url: options.url,
|
||||||
id: source.id
|
id: source.id,
|
||||||
});
|
});
|
||||||
spinnies.succeed('scrape', { text: 'Done!' });
|
spinnies.succeed('scrape', { text: 'Done!' });
|
||||||
console.log(result);
|
console.log(result);
|
||||||
@@ -384,8 +391,8 @@ async function runScraper(providers: ProviderControls, source: MetaOutput, optio
|
|||||||
spinnies.add('scrape', { text: `Running ${source.name} scraper on ${media.title}` });
|
spinnies.add('scrape', { text: `Running ${source.name} scraper on ${media.title}` });
|
||||||
try {
|
try {
|
||||||
const result = await providers.runSourceScraper({
|
const result = await providers.runSourceScraper({
|
||||||
media: media,
|
media,
|
||||||
id: source.id
|
id: source.id,
|
||||||
});
|
});
|
||||||
spinnies.succeed('scrape', { text: 'Done!' });
|
spinnies.succeed('scrape', { text: 'Done!' });
|
||||||
console.log(result);
|
console.log(result);
|
Reference in New Issue
Block a user