@ -1,16 +0,0 @@ | |||
{ | |||
"name": "@autoplex/themoviedb", | |||
"version": "0.0.0", | |||
"main": "dist/lib/index.js", | |||
"types": "dist/typings/index.d.ts", | |||
"license": "MIT", | |||
"scripts": { | |||
"build": "yarn run clean && tsc", | |||
"clean": "rimraf ./dist" | |||
}, | |||
"devDependencies": { | |||
"@types/node": "^15.0.1", | |||
"rimraf": "^3.0.2", | |||
"typescript": "^4.2.4" | |||
} | |||
} |
@ -1,38 +0,0 @@ | |||
import ApiRequestManager from "./request" | |||
import * as Schema from "./schema"; | |||
export enum ExternalSource { | |||
Facebook = "facebook_id", | |||
Freebase = "freebase_id", | |||
FreebaseM = "freebase_mid", | |||
Imdb = "imdb_id", | |||
Instagram = "instagram_id", | |||
Tvdb = "tvdb_id", | |||
TvRage = "tvrage_id", | |||
Twitter = "twitter_id" | |||
} | |||
export default class TheMovieDb | |||
{ | |||
protected requestManager!: ApiRequestManager; | |||
public constructor(apiKey: string) { | |||
this.requestManager = new ApiRequestManager(apiKey); | |||
} | |||
public async configuration() { | |||
return await this.requestManager.get("/configuration"); | |||
} | |||
public async searchMovie(query: string, year?: number, page?: number) { | |||
return await this.requestManager.get<Schema.IPaginatedResponse<Schema.IMovieSearchResult>>("/search/movie", { query, year }); | |||
} | |||
public async movie(id: number) { | |||
return await this.requestManager.get<Schema.IMovieDetails>(`/movie/${id}`); | |||
} | |||
public async findMovie(id: string, externalSource: ExternalSource) { | |||
return await this.requestManager.get<Schema.IFindResult>(`/find/${id}`, { external_source: externalSource }); | |||
} | |||
} |
@ -1,126 +0,0 @@ | |||
import https, { RequestOptions } from "https"; | |||
/** | |||
* The API URL | |||
*/ | |||
const API_URL = "https://api.themoviedb.org/3"; | |||
/** | |||
* A status error is used to indicate responses with non-200 status codes | |||
*/ | |||
export class StatusError<T = any> extends Error | |||
{ | |||
/** | |||
* The resulting body of a response | |||
*/ | |||
public readonly response: T; | |||
/** | |||
* The resulting status code of a response | |||
*/ | |||
public readonly statusCode?: number; | |||
/** | |||
* Create a new error indicating non-200 status | |||
*/ | |||
public constructor(response: T, statusCode: number) { | |||
super(); | |||
Object.setPrototypeOf(this, StatusError.prototype); | |||
this.response = response; | |||
this.statusCode = statusCode; | |||
} | |||
} | |||
/** | |||
* A request manager with atomic/persistent request options | |||
*/ | |||
export default class ApiRequestManager | |||
{ | |||
private __api_key: string; | |||
/** | |||
* Store additional request options | |||
*/ | |||
protected options: RequestOptions; | |||
/** | |||
* Create a new API request manager | |||
* | |||
* @param options Additional request options | |||
*/ | |||
public constructor(apiKey: string, options: RequestOptions = {}) { | |||
this.__api_key = apiKey; | |||
this.options = options; | |||
} | |||
/** | |||
* Perform a generic HTTPS request | |||
* | |||
* @param method The HTTP method | |||
* @param url The URL to request | |||
* @param apiKey An optional bearer token | |||
* @param params Optional parameters | |||
* @param body Optional body | |||
*/ | |||
protected request<T>(method: string, url: string, params?: any, body?: string) | |||
{ | |||
return new Promise<T>((resolve, reject) => { | |||
// Create request options | |||
let options = Object.assign({ method, headers: {} }, this.options); | |||
if (body) { | |||
options.headers["Content-Type"] = "application/json"; | |||
options.headers["Content-Length"] = body.length; | |||
} | |||
// Add search parameters if necessary | |||
let requestUrl = new URL(url); | |||
requestUrl.searchParams.set("api_key", this.__api_key); | |||
if (params) { | |||
Object.keys(params).forEach((key) => { | |||
if (params[key] !== undefined) { | |||
requestUrl.searchParams.set(key, params[key]); | |||
} | |||
}); | |||
} | |||
// Create the request | |||
let request = https.request(<any>requestUrl, options, (res) => { | |||
let rawData: string = ""; | |||
res.setEncoding("utf8"); | |||
res.on("data", chunk => {rawData += chunk}); | |||
res.on("error", reject); | |||
res.on("end", () => { | |||
let response: T = JSON.parse(rawData); | |||
if (res.statusCode == 200) { | |||
resolve(response) | |||
} else { | |||
reject(new StatusError(response, <number>res.statusCode)); | |||
} | |||
}); | |||
}) | |||
.on("error", reject) | |||
.on("timeout", () => reject("timeout")); | |||
if (body) { | |||
request.write(body); | |||
} | |||
request.end(); | |||
}); | |||
} | |||
/** | |||
* Perform a generic GET request | |||
*/ | |||
public async get<T = any>(path: string, params?: any) { | |||
return await this.request<T>("GET", `${API_URL}${path}`, params); | |||
} | |||
/** | |||
* Perform a generic POST request | |||
*/ | |||
public async post<T = any>(path: string, params?: any, body?: any) { | |||
if (body !== undefined) { | |||
body = JSON.stringify(body); | |||
} | |||
return await this.request<T>("POST", `${API_URL}${path}`, params, body); | |||
} | |||
} |
@ -1,89 +0,0 @@ | |||
export enum Status { | |||
Rumored = "Rumored", | |||
Planned = "Planned", | |||
InProduction = "InProduction", | |||
PostProduction = "PostProduction", | |||
Released = "Released", | |||
Canceled = "Canceled" | |||
} | |||
export interface IGenre { | |||
id : number, | |||
name: string | |||
} | |||
export interface ILanguage { | |||
iso_639_1: string, | |||
name : string | |||
} | |||
export interface IFindResult { | |||
movie_results : IMovieSearchResult[], | |||
person_results : unknown, | |||
tv_results : unknown, | |||
tv_episode_results: unknown, | |||
tv_season_results : unknown | |||
} | |||
export interface IMovieSearchResult { | |||
adult : boolean, | |||
backdrop_path : string | null, | |||
genre_ids : number[], | |||
id : number, | |||
original_string: string, | |||
original_title : string, | |||
overview : string, | |||
popularity : number, | |||
poster_path : string | null, | |||
release_date : string, | |||
title : string, | |||
video : boolean, | |||
vote_average : number | |||
vote_count : number, | |||
} | |||
export interface IMovieDetails { | |||
adult : boolean, | |||
backdrop_path : string | null, | |||
belongs_to_collection: any, | |||
budget : number, | |||
genres : IGenre[] | |||
imdb_id : string | null, | |||
original_language : string, | |||
original_title : string, | |||
overview : string | null, | |||
popularity : number, | |||
poster_path : string | null, | |||
production_companies : IProductionCompany[], | |||
production_countries : IProductionCountry[], | |||
release_date : string, | |||
revenue : number, | |||
runtime : number | null, | |||
spoken_languages : ILanguage[], | |||
status : Status, | |||
tagline : string | null, | |||
title : string, | |||
video : boolean, | |||
vote_average : number, | |||
vote_count : number | |||
} | |||
export interface IProductionCompany { | |||
name : string, | |||
id : number, | |||
logo_path : string | null, | |||
origin_country: string | |||
} | |||
export interface IProductionCountry { | |||
release_date: string, | |||
revenue : number, | |||
runtime : number | null | |||
} | |||
export interface IPaginatedResponse<T> { | |||
page : number, | |||
results : T[], | |||
total_results: number, | |||
total_pages : number | |||
} |
@ -1,7 +0,0 @@ | |||
{ | |||
"extends": "../../tsconfig.package.json", | |||
"compilerOptions": { | |||
"outDir": "./dist/lib", | |||
"declarationDir": "./dist/typings" | |||
} | |||
} |
@ -1,92 +0,0 @@ | |||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | |||
# yarn lockfile v1 | |||
"@types/node@^15.0.1": | |||
version "15.0.1" | |||
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.0.1.tgz#ef34dea0881028d11398be5bf4e856743e3dc35a" | |||
integrity sha512-TMkXt0Ck1y0KKsGr9gJtWGjttxlZnnvDtphxUOSd0bfaR6Q1jle+sPvrzNR1urqYTWMinoKvjKfXUGsumaO1PA== | |||
balanced-match@^1.0.0: | |||
version "1.0.2" | |||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" | |||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== | |||
brace-expansion@^1.1.7: | |||
version "1.1.11" | |||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" | |||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== | |||
dependencies: | |||
balanced-match "^1.0.0" | |||
concat-map "0.0.1" | |||
concat-map@0.0.1: | |||
version "0.0.1" | |||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" | |||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= | |||
fs.realpath@^1.0.0: | |||
version "1.0.0" | |||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" | |||
integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= | |||
glob@^7.1.3: | |||
version "7.1.6" | |||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" | |||
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== | |||
dependencies: | |||
fs.realpath "^1.0.0" | |||
inflight "^1.0.4" | |||
inherits "2" | |||
minimatch "^3.0.4" | |||
once "^1.3.0" | |||
path-is-absolute "^1.0.0" | |||
inflight@^1.0.4: | |||
version "1.0.6" | |||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" | |||
integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= | |||
dependencies: | |||
once "^1.3.0" | |||
wrappy "1" | |||
inherits@2: | |||
version "2.0.4" | |||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" | |||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== | |||
minimatch@^3.0.4: | |||
version "3.0.4" | |||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" | |||
integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== | |||
dependencies: | |||
brace-expansion "^1.1.7" | |||
once@^1.3.0: | |||
version "1.4.0" | |||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" | |||
integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= | |||
dependencies: | |||
wrappy "1" | |||
path-is-absolute@^1.0.0: | |||
version "1.0.1" | |||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" | |||
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= | |||
rimraf@^3.0.2: | |||
version "3.0.2" | |||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" | |||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== | |||
dependencies: | |||
glob "^7.1.3" | |||
typescript@^4.2.4: | |||
version "4.2.4" | |||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" | |||
integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== | |||
wrappy@1: | |||
version "1.0.2" | |||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" | |||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= |