├── .nycrc ├── .npmignore ├── examples ├── imdb-api-react │ ├── src │ │ ├── react-app-env.d.ts │ │ ├── setupTests.ts │ │ ├── App.test.tsx │ │ ├── index.css │ │ ├── reportWebVitals.ts │ │ ├── index.tsx │ │ ├── App.css │ │ ├── App.tsx │ │ └── logo.svg │ ├── .gitignore │ ├── tsconfig.json │ ├── package.json │ ├── public │ │ └── index.html │ └── README.md └── imdb-api-node │ ├── index.js │ ├── package.json │ └── package-lock.json ├── doc ├── assets │ └── images │ │ ├── icons.png │ │ ├── widgets.png │ │ ├── icons@2x.png │ │ └── widgets@2x.png ├── globals.html ├── interfaces │ ├── _interfaces_.omdbrating.html │ ├── _interfaces_.omdberror.html │ ├── _interfaces_.omdbsearch.html │ ├── _imdb_.searchrequest.html │ ├── _imdb_.movieopts.html │ ├── _interfaces_.omdbsearchresult.html │ ├── _interfaces_.omdbseason.html │ └── _imdb_.movierequest.html ├── classes │ ├── _imdb_.imdberror.html │ └── _imdb_.rating.html └── index.html ├── .travis.yml ├── .editorconfig ├── .gitignore ├── tsconfig.json ├── tsconfig-umd.json ├── .eslintrc.json ├── test ├── data │ ├── james-bond.json │ ├── how-I-met-your-mother.json │ ├── toxic-avenger.json │ ├── mother-ep.json │ ├── toxic-avenger-search.json │ └── how-I-met-your-mother-episodes.json ├── util │ └── server.ts ├── test-search.ts ├── test-client.ts ├── test-movie.ts └── test-getReq.ts ├── TODOs.org ├── .gitlab-ci.yml ├── package.json ├── src └── interfaces.ts ├── CHANGELOG.md └── README.md /.nycrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@istanbuljs/nyc-config-typescript" 3 | } 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | coverage 2 | doc 3 | test 4 | TODOS.org 5 | yarn-error.log 6 | .* 7 | examples 8 | -------------------------------------------------------------------------------- /examples/imdb-api-react/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /doc/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worr/node-imdb-api/HEAD/doc/assets/images/icons.png -------------------------------------------------------------------------------- /doc/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worr/node-imdb-api/HEAD/doc/assets/images/widgets.png -------------------------------------------------------------------------------- /doc/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worr/node-imdb-api/HEAD/doc/assets/images/icons@2x.png -------------------------------------------------------------------------------- /doc/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/worr/node-imdb-api/HEAD/doc/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - '12' 5 | - '14' 6 | - '16' 7 | cache: 8 | directories: 9 | - node_modules 10 | install: 11 | - npm install 12 | script: 13 | - npm run ci 14 | -------------------------------------------------------------------------------- /examples/imdb-api-node/index.js: -------------------------------------------------------------------------------- 1 | const imdb = require("imdb-api"); 2 | 3 | (async function() { 4 | const movie = await imdb.get({name: "Toxic Avenger"}, {apiKey: "your api key here", baseURL: "http://localhost:3000"}); 5 | console.log(movie); 6 | })() 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | node_modules 15 | npm-debug.log 16 | *.swp 17 | lib 18 | typings/ 19 | coverage/ 20 | .nyc_output/ 21 | umd 22 | -------------------------------------------------------------------------------- /examples/imdb-api-react/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /examples/imdb-api-react/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', async () => { 6 | render(); 7 | const linkElement = await screen.findByText(/toxic/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /examples/imdb-api-node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "imdb-api-node", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "imdb-api": "file:../.." 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "target": "es5", 5 | "lib": ["es6"], 6 | "module": "commonjs", 7 | "removeComments": true, 8 | "outDir": "lib", 9 | "sourceMap": true, 10 | "declaration": true, 11 | "strict": true 12 | }, 13 | "include": [ 14 | "src/*" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tsconfig-umd.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "target": "es5", 5 | "lib": ["es6"], 6 | "module": "umd", 7 | "moduleResolution": "node", 8 | "removeComments": true, 9 | "outDir": "umd", 10 | "sourceMap": true, 11 | "declaration": true, 12 | "strict": true 13 | }, 14 | "include": [ 15 | "src/*" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /examples/imdb-api-react/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /examples/imdb-api-react/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": false, 4 | "es2020": true 5 | }, 6 | "extends": [ 7 | "semistandard", 8 | "prettier" 9 | ], 10 | "parser": "@typescript-eslint/parser", 11 | "parserOptions": { 12 | "ecmaVersion": 11, 13 | "sourceType": "module" 14 | }, 15 | "plugins": [ 16 | "@typescript-eslint" 17 | ], 18 | "rules": { 19 | "no-unused-vars": [0], 20 | "no-useless-constructor": [0] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/imdb-api-react/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | } 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /examples/imdb-api-react/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /test/data/james-bond.json: -------------------------------------------------------------------------------- 1 | {"Title":"James Bond","Year":"2015","Rated":"N/A","Released":"24 Jul 2015","Runtime":"142 min","Genre":"Action, Comedy","Director":"Sai Kishore Macha","Writer":"Gopimohan (thanks), Sai Kishore Macha","Actors":"Allari Naresh, Sakshi Choudhary, Banerji, Krishna Bhagavan","Plot":"Nani (Allari Naresh) is a trepid and fearful guy who works as a software engineer. Bullet (Sakshi Chaudhary) is a mafia don in Dubai. Her mother doesn't know about Bullet's profession. ...","Language":"Telugu","Country":"India","Awards":"N/A","Poster":"N/A","Metascore":"N/A","imdbRating":"5.5","imdbVotes":"107","imdbID":"tt4896340","Type":"movie","Response":"True"} -------------------------------------------------------------------------------- /examples/imdb-api-react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /TODOs.org: -------------------------------------------------------------------------------- 1 | * Before 4.x 2 | 3 | * DONE 100% test coverage 4 | CLOSED: [2018-06-23 Sat 20:37] 5 | * DONE test new imdb client obj 6 | CLOSED: [2018-06-07 Thu 23:08] 7 | * DONE add tests for merging ~MovieOpts~ 8 | CLOSED: [2018-06-07 Thu 23:08] 9 | * DONE update documentation for new ~MovieRequest~ structure 10 | CLOSED: [2018-06-23 Sat 18:09] 11 | 12 | * Planned for 5.x 13 | 14 | ** TODO Change class hierarchy, since Movie is no longer top-level 15 | ** TODO Add movie-specific types 16 | 17 | This is apparently filed in #79, but this isn't appearing for me since the 18 | user is too new to file issues that I can see or whatever. 19 | ** TODO Rename all non-camelcase public members to camelcase 20 | ** TODO ~N/A~ -> ~undefined~ translation 21 | -------------------------------------------------------------------------------- /examples/imdb-api-react/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/data/how-I-met-your-mother.json: -------------------------------------------------------------------------------- 1 | { 2 | "Title": "How I Met Your Mother", 3 | "Year": "2005–2014", 4 | "Rated": "TV-14", 5 | "Released": "19 Sep 2005", 6 | "Runtime": "22 min", 7 | "Genre": "Comedy, Romance", 8 | "Director": "N/A", 9 | "Writer": "Carter Bays, Craig Thomas", 10 | "Actors": "Josh Radnor, Jason Segel, Cobie Smulders, Neil Patrick Harris", 11 | "Plot": "A father recounts to his children, through a series of flashbacks, the journey he and his four best friends took leading up to him meeting their mother.", 12 | "Language": "English", 13 | "Country": "USA", 14 | "Awards": "Nominated for 2 Golden Globes. Another 25 wins & 88 nominations.", 15 | "Poster": "http://ia.media-imdb.com/images/M/MV5BMTA5MzAzNTcyNjZeQTJeQWpwZ15BbWU3MDUyMzE1MTk@._V1_SX300.jpg", 16 | "Metascore": "N/A", 17 | "imdbRating": "8.4", 18 | "imdbVotes": "450,097", 19 | "imdbID": "tt0460649", 20 | "Type": "series", 21 | "totalSeasons": "1", 22 | "Response": "True" 23 | } 24 | -------------------------------------------------------------------------------- /test/data/toxic-avenger.json: -------------------------------------------------------------------------------- 1 | {"Title":"The Toxic Avenger","Year":"1984","Rated":"R","Released":"11 Apr 1986","Runtime":"82 min","Genre":"Action, Comedy, Horror, Sci-Fi","Director":"Michael Herz, Lloyd Kaufman","Writer":"Lloyd Kaufman (story), Joe Ritter (screenplay), Lloyd Kaufman (additional material), Gay Partington Terry (additional material), Stuart Strutin (additional material)","Actors":"Andree Maranda, Mitch Cohen, Jennifer Babtist, Cindy Manion","Plot":"Tromaville has a monstrous new hero. The Toxic Avenger is born when meek mop boy Melvin falls into a vat of toxic waste. Now evildoers will have a lot to lose.","Language":"English","Country":"USA","Awards":"1 nomination.","Poster":"https://m.media-amazon.com/images/M/MV5BNzViNmQ5MTYtMmI4Yy00N2Y2LTg4NWUtYWU3MThkMTVjNjk3XkEyXkFqcGdeQXVyMTQxNzMzNDI@._V1_SX300.jpg","Ratings":[{"Source":"Internet Movie Database","Value":"6.2/10"},{"Source":"Rotten Tomatoes","Value":"70%"},{"Source":"Metacritic","Value":"42/100"}],"Metascore":"42","imdbRating":"6.2","imdbVotes":"24,519","imdbID":"tt0090191","Type":"movie","DVD":"10 Nov 1997","BoxOffice":"N/A","Production":"Troma","Website":"N/A","Response":"True"} 2 | -------------------------------------------------------------------------------- /examples/imdb-api-react/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import './App.css'; 3 | import * as imdb from 'imdb-api'; 4 | 5 | type MyProps = {} 6 | 7 | type MyState = { 8 | movie: imdb.Movie|undefined; 9 | error: string; 10 | } 11 | 12 | class App extends Component { 13 | state: MyState = {movie: undefined, error: ""}; 14 | 15 | async componentDidMount() { 16 | try { 17 | const results = await imdb.get({name: 'Toxic Avenger'}, {apiKey: 'use your api key here', baseURL: "http://localhost:3000"}); 18 | this.setState({movie: results, error: ""}); 19 | } catch (e) { 20 | this.setState({movie: undefined, error: e.message}); 21 | } 22 | } 23 | 24 | render() { 25 | return ( 26 |
27 |

Movie

28 |
29 | {this.state.movie?.title} 30 |
31 |
32 | {this.state.error} 33 |
34 |
35 | ); 36 | } 37 | } 38 | 39 | 40 | export default App; 41 | -------------------------------------------------------------------------------- /examples/imdb-api-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "imdb-api-react", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^16.9.53", 12 | "@types/react-dom": "^16.9.8", 13 | "@ungap/url-search-params": "^0.2.2", 14 | "imdb-api": "file:../../", 15 | "react": "^17.0.1", 16 | "react-dom": "^17.0.1", 17 | "react-scripts": "4.0.0", 18 | "typescript": "^4.0.3", 19 | "web-vitals": "^0.2.4" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | }, 45 | "proxy": "http://localhost:3000/" 46 | } 47 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | .build_default: 2 | stage: build 3 | script: 4 | - npm install 5 | - npm run build 6 | artifacts: 7 | paths: 8 | - node_modules/ 9 | - lib/ 10 | 11 | .test_default: 12 | stage: test 13 | script: 14 | - npm run ci 15 | 16 | stages: 17 | - build 18 | - test 19 | - integration 20 | 21 | cache: 22 | paths: 23 | - node_modules/ 24 | 25 | "node build v12": 26 | image: node:12-alpine 27 | extends: .build_default 28 | 29 | "node test v12": 30 | image: node:12-alpine 31 | extends: .test_default 32 | dependencies: 33 | - node build v12 34 | 35 | "node build v14": 36 | image: node:14-alpine 37 | extends: .build_default 38 | 39 | "node test v14": 40 | image: node:14-alpine 41 | extends: .test_default 42 | dependencies: 43 | - node build v14 44 | 45 | "node build v16": 46 | image: node:16-alpine 47 | extends: .build_default 48 | 49 | "node test v16": 50 | image: node:16-alpine 51 | extends: .test_default 52 | dependencies: 53 | - node build v16 54 | 55 | "example integration testing": 56 | stage: integration 57 | image: node:16-alpine 58 | dependencies: 59 | - node build v16 60 | before_script: 61 | - "npx ts-node test/util/server.ts &" 62 | script: 63 | - "cd examples/imdb-api-react && yarn && yarn test; cd ../.." 64 | - "cd examples/imdb-api-node && npm install && node index.js; cd ../.." 65 | -------------------------------------------------------------------------------- /test/data/mother-ep.json: -------------------------------------------------------------------------------- 1 | {"Title":"The Scorpion and the Toad","Year":"2006","Rated":"TV-14","Released":"25 Sep 2006","Season":"2","Episode":"2","Runtime":"22 min","Genre":"Comedy, Romance","Director":"Rob Greenberg","Writer":"Carter Bays (created by), Carter Bays (creator), Craig Thomas (created by), Craig Thomas (creator), Chris Harris, Gloria Calderon Kellett (executive story editor)","Actors":"Josh Radnor, Jason Segel, Cobie Smulders, Neil Patrick Harris","Plot":"Barney feels that its time for Marshall to get out in the dating scene once again. He likens Marshall being single to a kid in a candy store, with any candy ready for his picking. Barney tells him that he'll be Marshall's wing man in picking up girls. Their nights out don't quite work out that way, but when the opportunity finally arrives for Marshall and a potential date, Marshall doesn't seem to know what to do. Meanwhile, Robin receives a surprise visit: from Lily. Lily implies that she had the best summer in San Francisco, not only with the art fellowship, but with life overall. Robin tells Ted about Lily's return, the two who argue about whether they should tell Marshall. But when Ted finally sees Lily, he has a different point of view.","Language":"English","Country":"USA","Awards":"N/A","Poster":"http://ia.media-imdb.com/images/M/MV5BMTc1NTE0MTE0N15BMl5BanBnXkFtZTgwMzE5MDMyMjE@._V1_SX300.jpg","Metascore":"N/A","imdbRating":"8.3","imdbVotes":"1616","imdbID":"tt0869673","Season": "5","seriesID":"tt0460649","Type":"episode","Response":"True"} 2 | -------------------------------------------------------------------------------- /examples/imdb-api-react/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /examples/imdb-api-react/README.md: -------------------------------------------------------------------------------- 1 | # Getting Started with Create React App 2 | 3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 4 | 5 | ## Available Scripts 6 | 7 | In the project directory, you can run: 8 | 9 | ### `yarn start` 10 | 11 | Runs the app in the development mode.\ 12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 13 | 14 | The page will reload if you make edits.\ 15 | You will also see any lint errors in the console. 16 | 17 | ### `yarn test` 18 | 19 | Launches the test runner in the interactive watch mode.\ 20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 21 | 22 | ### `yarn build` 23 | 24 | Builds the app for production to the `build` folder.\ 25 | It correctly bundles React in production mode and optimizes the build for the best performance. 26 | 27 | The build is minified and the filenames include the hashes.\ 28 | Your app is ready to be deployed! 29 | 30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 31 | 32 | ### `yarn eject` 33 | 34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 35 | 36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 37 | 38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 39 | 40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 41 | 42 | ## Learn More 43 | 44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 45 | 46 | To learn React, check out the [React documentation](https://reactjs.org/). 47 | -------------------------------------------------------------------------------- /test/util/server.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { promises as fs } from "fs"; 3 | import path from "path"; 4 | import cors from "cors"; 5 | 6 | const app = express(); 7 | const port = 3000; 8 | 9 | app.use(express.json()); 10 | app.use(cors()); 11 | 12 | async function readFromFile(filename: string): Promise { 13 | const fullpath = path.join(__dirname, "..", "data", filename); 14 | const rawdata = await fs.readFile(fullpath); 15 | 16 | return JSON.parse(rawdata.toString()); 17 | } 18 | 19 | async function getByTitle(name: string): Promise { 20 | const newname = `${name.replace(" ", "-")}.json`.toLowerCase(); 21 | return readFromFile(newname); 22 | } 23 | 24 | async function search(name: string): Promise { 25 | const search = `${name.replace(" ", "-")}-search.json`.toLowerCase(); 26 | return readFromFile(search); 27 | } 28 | 29 | app.get("/", async (req: express.Request, res: express.Response) => { 30 | if (req.query === undefined) { 31 | res.send({ error: "req.query undefined" }); 32 | return; 33 | } 34 | 35 | const isGet = req.query.t !== undefined || req.query.i !== undefined; 36 | const isSearch = req.query.s !== undefined; 37 | let ret: object = { error: `Invalid query: ${JSON.stringify(req.query)}` }; 38 | 39 | if (isGet) { 40 | if (req.query.t !== undefined && typeof req.query.t === "string") { 41 | const title = req.query.t; 42 | try { 43 | ret = await getByTitle(title); 44 | } catch (e) { 45 | if (e instanceof Error) { 46 | ret = { error: e.message }; 47 | } 48 | } 49 | } else if (req.query.i !== undefined && typeof req.query.i === "string") { 50 | const id = req.query.i; 51 | try { 52 | ret = await getByTitle(id); 53 | } catch (e) { 54 | if (e instanceof Error) { 55 | ret = { error: e.message }; 56 | } 57 | } 58 | } 59 | } else if (isSearch) { 60 | if (typeof req.query.s === "string") { 61 | const searchTerm = req.query.s; 62 | try { 63 | ret = await search(searchTerm); 64 | } catch (e) { 65 | if (e instanceof Error) { 66 | ret = { error: e.message }; 67 | } 68 | } 69 | } 70 | } 71 | 72 | res.send(ret); 73 | }); 74 | 75 | app.listen(port, () => { 76 | console.log(`Test server listening https://localhost:${port}`); 77 | }); 78 | -------------------------------------------------------------------------------- /examples/imdb-api-react/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "William Orr (http://worrbase.com/)", 3 | "name": "imdb-api", 4 | "description": "Queries unofficial imdb APIs to get movie and television information from imdb", 5 | "version": "4.4.1", 6 | "main": "./lib/imdb.js", 7 | "types": "./lib/imdb.d.ts", 8 | "homepage": "https://gitlab.com/worr/node-imdb-api", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://gitlab.com/worr/node-imdb-api" 12 | }, 13 | "license": "MIT", 14 | "scripts": { 15 | "build": "tsc -p .", 16 | "prepare": "npm run build && tsc -p tsconfig-umd.json", 17 | "format": "prettier --write --parser typescript src/*.ts test/*.ts", 18 | "lint": "eslint --ignore-path .gitignore --ignore-pattern examples --ext .ts . && prettier --check --parser typescript src/*.ts test/*.ts", 19 | "test": "nyc mocha", 20 | "check": "npm run lint && npm run test", 21 | "ci": "npm run check", 22 | "docs": "typedoc --out ./doc --ignoreCompilerErrors src/imdb.ts", 23 | "clean": "rm -rf node_modules lib" 24 | }, 25 | "files": [ 26 | "lib/*", 27 | "src/*", 28 | "umd/*" 29 | ], 30 | "devDependencies": { 31 | "@istanbuljs/nyc-config-typescript": "^1.0.1", 32 | "@types/chai": "^4.2.21", 33 | "@types/chai-as-promised": "^7.1.4", 34 | "@types/cors": "^2.8.12", 35 | "@types/express": "^4.17.13", 36 | "@types/mocha": "^9.0.0", 37 | "@types/node": "^16.7.10", 38 | "@typescript-eslint/eslint-plugin": "^4.30.0", 39 | "@typescript-eslint/parser": "^4.30.0", 40 | "chai": "^4.3.4", 41 | "chai-as-promised": "^7.1.1", 42 | "cors": "^2.8.5", 43 | "eslint": "^7.32.0", 44 | "eslint-config-prettier": "^8.3.0", 45 | "eslint-config-semistandard": "^16.0.0", 46 | "eslint-config-standard": "^16.0.3", 47 | "eslint-plugin-import": "^2.24.2", 48 | "eslint-plugin-node": "^11.1.0", 49 | "eslint-plugin-prettier": "^4.0.0", 50 | "eslint-plugin-promise": "^5.1.0", 51 | "express": "^4.17.1", 52 | "js-beautify": "^1.14.0", 53 | "mocha": "^9.1.0", 54 | "nock": "^13.1.3", 55 | "nyc": "^15.1.0", 56 | "prettier": "^2.3.2", 57 | "source-map-support": "^0.5.19", 58 | "ts-node": "^10.2.1", 59 | "typedoc": "^1.0.0-dev.4", 60 | "typescript": "^4.4.2" 61 | }, 62 | "engines": { 63 | "node": ">=12.0" 64 | }, 65 | "keywords": [ 66 | "imdb", 67 | "movies", 68 | "search", 69 | "tv", 70 | "television" 71 | ], 72 | "dependencies": { 73 | "@ungap/url-search-params": "^0.2.2", 74 | "ky": "^0.24.0", 75 | "ky-universal": "^0.8.2" 76 | }, 77 | "mocha": { 78 | "require": [ 79 | "ts-node/register", 80 | "source-map-support/register" 81 | ], 82 | "extension": [ 83 | "ts" 84 | ] 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /test/data/toxic-avenger-search.json: -------------------------------------------------------------------------------- 1 | { 2 | "Search": [ 3 | { 4 | "Title": "The Toxic Avenger", 5 | "Year": "1984", 6 | "imdbID": "tt0090190", 7 | "Type": "movie", 8 | "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BNzViNmQ5MTYtMmI4Yy00N2Y2LTg4NWUtYWU3MThkMTVjNjk3XkEyXkFqcGdeQXVyMTQxNzMzNDI@._V1_SX300.jpg" 9 | }, 10 | { 11 | "Title": "The Toxic Avenger Part II", 12 | "Year": "1989", 13 | "imdbID": "tt0098503", 14 | "Type": "movie", 15 | "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BODhiNTljYTctMmIzZC00ZGVkLTk2NmItN2RjMzY3ZTYyNDczXkEyXkFqcGdeQXVyMTQxNzMzNDI@._V1_SX300.jpg" 16 | }, 17 | { 18 | "Title": "Citizen Toxie: The Toxic Avenger IV", 19 | "Year": "2000", 20 | "imdbID": "tt0212879", 21 | "Type": "movie", 22 | "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BMWI0NWY0ODUtNGY3Yy00ZDU1LTllYjUtMDFkYWEzZGQwY2I1XkEyXkFqcGdeQXVyMTQxNzMzNDI@._V1_SX300.jpg" 23 | }, 24 | { 25 | "Title": "The Toxic Avenger Part III: The Last Temptation of Toxie", 26 | "Year": "1989", 27 | "imdbID": "tt0098502", 28 | "Type": "movie", 29 | "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BNjVlNzFjMGItMTEwYy00OTc0LWFmY2ItM2U0MmQyYWI5Njk3XkEyXkFqcGdeQXVyMTQxNzMzNDI@._V1_SX300.jpg" 30 | }, 31 | { 32 | "Title": "Toxic", 33 | "Year": "2008", 34 | "imdbID": "tt0453560", 35 | "Type": "movie", 36 | "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BMTM4ODI3MzIwN15BMl5BanBnXkFtZTcwOTczMDgzMQ@@._V1_SX300.jpg" 37 | }, 38 | { 39 | "Title": "Toxic Love", 40 | "Year": "1983", 41 | "imdbID": "tt0166476", 42 | "Type": "movie", 43 | "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BNDhhNjFmNDctNzdjOC00MDg1LWE5MjctMmM4OGNiYzE4NjRmXkEyXkFqcGdeQXVyMjYxNzU4MDA@._V1_SX300.jpg" 44 | }, 45 | { 46 | "Title": "Toxic Skies", 47 | "Year": "2008", 48 | "imdbID": "tt1414863", 49 | "Type": "movie", 50 | "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BMjA0Nzg4NjY4OF5BMl5BanBnXkFtZTcwMzY4ODIxMw@@._V1_SX300.jpg" 51 | }, 52 | { 53 | "Title": "Toxic Zombies", 54 | "Year": "1980", 55 | "imdbID": "tt0080448", 56 | "Type": "movie", 57 | "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BMTQzMTc1MjgzN15BMl5BanBnXkFtZTcwNzE2MDc5MQ@@._V1_SX300.jpg" 58 | }, 59 | { 60 | "Title": "Toxic Crusaders", 61 | "Year": "1991–1993", 62 | "imdbID": "tt0173344", 63 | "Type": "series", 64 | "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BMjQ2MTcxNzk3M15BMl5BanBnXkFtZTcwMTQyNjcyMQ@@._V1_SX300.jpg" 65 | }, 66 | { 67 | "Title": "Toxic Affair", 68 | "Year": "1993", 69 | "imdbID": "tt0108372", 70 | "Type": "movie", 71 | "Poster": "https://images-na.ssl-images-amazon.com/images/M/MV5BMTY4OTE3MjAzMF5BMl5BanBnXkFtZTcwOTYxNzY4Mg@@._V1_SX300.jpg" 72 | } 73 | ], 74 | "totalResults": "98", 75 | "Response": "True" 76 | } -------------------------------------------------------------------------------- /examples/imdb-api-node/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "imdb-api-node", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "version": "1.0.0", 9 | "license": "ISC", 10 | "dependencies": { 11 | "imdb-api": "file:../.." 12 | } 13 | }, 14 | "../..": { 15 | "version": "4.3.0", 16 | "license": "MIT", 17 | "dependencies": { 18 | "@ungap/url-search-params": "^0.2.2", 19 | "ky": "^0.24.0", 20 | "ky-universal": "^0.8.2" 21 | }, 22 | "devDependencies": { 23 | "@istanbuljs/nyc-config-typescript": "^1.0.1", 24 | "@types/chai": "^4.2.12", 25 | "@types/chai-as-promised": "^7.1.3", 26 | "@types/mocha": "^8.0.0", 27 | "@types/node": "^14.0.27", 28 | "@typescript-eslint/eslint-plugin": "^4.6.0", 29 | "@typescript-eslint/parser": "^4.6.0", 30 | "chai": "^4.2.0", 31 | "chai-as-promised": "^7.1.1", 32 | "eslint": "^7.6.0", 33 | "eslint-config-prettier": "^6.11.0", 34 | "eslint-config-semistandard": "^15.0.1", 35 | "eslint-config-standard": "^16.0.0", 36 | "eslint-plugin-import": "^2.22.0", 37 | "eslint-plugin-node": "^11.1.0", 38 | "eslint-plugin-prettier": "^3.1.4", 39 | "eslint-plugin-promise": "^4.2.1", 40 | "eslint-plugin-standard": "^4.0.1", 41 | "js-beautify": "^1.11.0", 42 | "mocha": "^8.1.0", 43 | "nock": "^13.0.3", 44 | "nyc": "^15.1.0", 45 | "prettier": "^2.0.5", 46 | "source-map-support": "^0.5.19", 47 | "ts-node": "^9.0.0", 48 | "typedoc": "^0.19.2", 49 | "typescript": "^4.0.5" 50 | }, 51 | "engines": { 52 | "node": ">=6.0" 53 | } 54 | }, 55 | "node_modules/imdb-api": { 56 | "resolved": "../..", 57 | "link": true 58 | } 59 | }, 60 | "dependencies": { 61 | "imdb-api": { 62 | "version": "file:../..", 63 | "requires": { 64 | "@istanbuljs/nyc-config-typescript": "^1.0.1", 65 | "@types/chai": "^4.2.12", 66 | "@types/chai-as-promised": "^7.1.3", 67 | "@types/mocha": "^8.0.0", 68 | "@types/node": "^14.0.27", 69 | "@typescript-eslint/eslint-plugin": "^4.6.0", 70 | "@typescript-eslint/parser": "^4.6.0", 71 | "@ungap/url-search-params": "^0.2.2", 72 | "chai": "^4.2.0", 73 | "chai-as-promised": "^7.1.1", 74 | "eslint": "^7.6.0", 75 | "eslint-config-prettier": "^6.11.0", 76 | "eslint-config-semistandard": "^15.0.1", 77 | "eslint-config-standard": "^16.0.0", 78 | "eslint-plugin-import": "^2.22.0", 79 | "eslint-plugin-node": "^11.1.0", 80 | "eslint-plugin-prettier": "^3.1.4", 81 | "eslint-plugin-promise": "^4.2.1", 82 | "eslint-plugin-standard": "^4.0.1", 83 | "js-beautify": "^1.11.0", 84 | "ky": "^0.24.0", 85 | "ky-universal": "^0.8.2", 86 | "mocha": "^8.1.0", 87 | "nock": "^13.0.3", 88 | "nyc": "^15.1.0", 89 | "prettier": "^2.0.5", 90 | "source-map-support": "^0.5.19", 91 | "ts-node": "^9.0.0", 92 | "typedoc": "^0.19.2", 93 | "typescript": "^4.0.5" 94 | } 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /test/test-search.ts: -------------------------------------------------------------------------------- 1 | import "https"; 2 | import path from "path"; 3 | import nock from "nock"; 4 | import { describe, it } from "mocha"; 5 | import chai from "chai"; 6 | import chaiAsPromised from "chai-as-promised"; 7 | 8 | import * as imdb from "../lib/imdb"; 9 | 10 | chai.use(chaiAsPromised); 11 | const { assert } = chai; 12 | 13 | describe("searching", () => { 14 | it("searches successfully", () => { 15 | nock("https://www.omdbapi.com") 16 | .get("/?apikey=foo&page=1&r=json&s=Toxic%20Avenger") 17 | .replyWithFile( 18 | 200, 19 | path.join(__dirname, "/data/toxic-avenger-search.json") 20 | ); 21 | 22 | return assert.isFulfilled( 23 | imdb 24 | .search( 25 | { 26 | name: "Toxic Avenger", 27 | }, 28 | { 29 | apiKey: "foo", 30 | } 31 | ) 32 | .then((data) => { 33 | assert.isOk(data); 34 | assert.deepEqual( 35 | data.results.length, 36 | 10, 37 | "testing length of results" 38 | ); 39 | assert.deepEqual(data.totalresults, 98, "testing total length"); 40 | for (const result of data.results) { 41 | assert.isOk(result); 42 | } 43 | }) 44 | ); 45 | }); 46 | 47 | it("searches unsuccessfully", () => { 48 | nock("https://www.omdbapi.com") 49 | .get("/?s=Toxic%20Avenger&r=json&apikey=foo&page=1") 50 | .reply(404); 51 | 52 | return assert.isRejected( 53 | imdb.search( 54 | { 55 | name: "Toxic Avenger", 56 | }, 57 | { 58 | apiKey: "foo", 59 | } 60 | ) 61 | ); 62 | }); 63 | 64 | it("times out during a search", () => { 65 | nock("https://www.omdbapi.com") 66 | .get("/?apikey=foo&page=1&r=json&s=Toxic%20Avenger") 67 | .delay(3000) 68 | .replyWithFile( 69 | 200, 70 | path.join(__dirname, "/data/toxic-avenger-search.json") 71 | ); 72 | 73 | return assert.isRejected( 74 | imdb.search( 75 | { 76 | name: "Toxic Avenger", 77 | }, 78 | { 79 | apiKey: "foo", 80 | timeout: 10, 81 | } 82 | ) 83 | ); 84 | }); 85 | 86 | it("gets the next page in a search", () => { 87 | nock("https://www.omdbapi.com") 88 | .get("/?apikey=foo&page=1&r=json&s=Toxic%20Avenger") 89 | .replyWithFile( 90 | 200, 91 | path.join(__dirname, "/data/toxic-avenger-search.json") 92 | ) 93 | .get("/?apikey=foo&page=2&r=json&s=Toxic%20Avenger") 94 | .replyWithFile( 95 | 200, 96 | path.join(__dirname, "/data/toxic-avenger-search.json") 97 | ); 98 | 99 | return assert.isFulfilled( 100 | imdb 101 | .search( 102 | { 103 | name: "Toxic Avenger", 104 | }, 105 | { 106 | apiKey: "foo", 107 | } 108 | ) 109 | .then((data) => { 110 | assert.isOk(data); 111 | return data.next(); 112 | }) 113 | .then((data) => { 114 | assert.isOk(data); 115 | }) 116 | ); 117 | }); 118 | 119 | it("gets an error from searching", () => { 120 | nock("https://www.omdbapi.com") 121 | .get("/?apikey=foo&page=1&r=json&s=Toxic%20Avenger") 122 | .reply(200, { Error: "bad", Response: "False" }); 123 | 124 | return assert.isRejected( 125 | imdb.search( 126 | { 127 | name: "Toxic Avenger", 128 | }, 129 | { 130 | apiKey: "foo", 131 | } 132 | ), 133 | /bad/ 134 | ); 135 | }); 136 | }); 137 | -------------------------------------------------------------------------------- /src/interfaces.ts: -------------------------------------------------------------------------------- 1 | export interface OmdbRating { 2 | Source: string; 3 | Value: string; 4 | } 5 | 6 | export interface OmdbGetResponse { 7 | Title: string; 8 | Year: string; 9 | Rated: string; 10 | Released: string; 11 | Runtime: string; 12 | Genre: string; 13 | Director: string; 14 | Writer: string; 15 | Actors: string; 16 | Plot: string; 17 | Language: string; 18 | Country: string; 19 | Awards: string; 20 | Poster: string; 21 | Metascore: string; 22 | imdbRating: string; 23 | imdbVotes: string; 24 | imdbID: string; 25 | Website?: string; 26 | Ratings?: OmdbRating[]; 27 | DVD?: string; 28 | BoxOffice?: string; 29 | Production?: string; 30 | Type: string; 31 | Response: string; 32 | } 33 | 34 | export interface OmdbTvshow extends OmdbGetResponse { 35 | totalSeasons: string; 36 | } 37 | 38 | export interface OmdbEpisode extends OmdbGetResponse { 39 | Season: string; 40 | Episode: string; 41 | seriesID: string; 42 | } 43 | 44 | export interface OmdbSeason { 45 | Title: string; 46 | Season: string; 47 | totalSeasons: string; 48 | Episodes: OmdbEpisode[]; 49 | Response: string; 50 | } 51 | 52 | export interface OmdbSearchResult { 53 | Title: string; 54 | Year: string; 55 | imdbID: string; 56 | Type: string; 57 | Poster: string; 58 | } 59 | 60 | export interface OmdbSearch { 61 | Search: OmdbSearchResult[]; 62 | totalResults: string; 63 | Response: string; 64 | } 65 | 66 | export interface OmdbError { 67 | Response: string; 68 | Error: string; 69 | } 70 | 71 | export function isError( 72 | response: OmdbSearch | OmdbSeason | OmdbTvshow | OmdbGetResponse | OmdbError 73 | ): response is OmdbError { 74 | return response.Response === "False"; 75 | } 76 | 77 | export function isTvshow(response: OmdbGetResponse): response is OmdbTvshow { 78 | return response.Type === "series"; 79 | } 80 | 81 | export function isMovie(response: OmdbGetResponse): boolean { 82 | return response.Type === "movie"; 83 | } 84 | 85 | export function isEpisode(response: OmdbGetResponse): response is OmdbEpisode { 86 | return response.Type === "episode"; 87 | } 88 | 89 | export function isGame(response: OmdbGetResponse): boolean { 90 | return response.Type === "game"; 91 | } 92 | 93 | export function assertEpisodeSeasonResponse( 94 | response: unknown 95 | ): response is OmdbSeason[] | OmdbError[] { 96 | if (!Array.isArray(response)) { 97 | return false; 98 | } 99 | 100 | for (const res of response) { 101 | if (typeof res !== "object") { 102 | return false; 103 | } 104 | 105 | if ("Response" in res) { 106 | if (res.Response === "False") { 107 | return true; 108 | } 109 | 110 | if ("Season" in res && "totalSeasons" in res) { 111 | return true; 112 | } 113 | } 114 | } 115 | 116 | return false; 117 | } 118 | 119 | export function assertGetResponse( 120 | response: unknown 121 | ): response is OmdbGetResponse | OmdbError { 122 | if (typeof response !== "object") { 123 | return false; 124 | } 125 | 126 | const res: any = response; 127 | if (res === null) { 128 | return false; 129 | } 130 | 131 | if ("Response" in res) { 132 | return true; 133 | } 134 | 135 | return false; 136 | } 137 | 138 | export function assertSearchResponse( 139 | response: unknown 140 | ): response is OmdbSearch | OmdbError { 141 | if (typeof response !== "object") { 142 | return false; 143 | } 144 | 145 | const res: any = response; 146 | if (res === null) { 147 | return false; 148 | } 149 | 150 | if ("Response" in res) { 151 | if (res.Response === "False") { 152 | return true; 153 | } 154 | } 155 | 156 | if ("Search" in res) { 157 | return true; 158 | } 159 | 160 | return false; 161 | } 162 | -------------------------------------------------------------------------------- /test/data/how-I-met-your-mother-episodes.json: -------------------------------------------------------------------------------- 1 | { 2 | "Title": "How I Met Your Mother", 3 | "Season": "1", 4 | "totalSeasons": "9", 5 | "Episodes": [ 6 | { 7 | "Title": "Pilot", 8 | "Released": "19 Sep 2005", 9 | "Episode": "1", 10 | "imdbRating": "8.5", 11 | "imdbID": "tt0606110" 12 | }, 13 | { 14 | "Title": "Purple Giraffe", 15 | "Released": "2005-09-26", 16 | "Episode": "2", 17 | "imdbRating": "8.2", 18 | "imdbID": "tt0606111" 19 | }, 20 | { 21 | "Title": "The Sweet Taste of Liberty", 22 | "Released": "2005-10-03", 23 | "Episode": "3", 24 | "imdbRating": "8.2", 25 | "imdbID": "tt0606117" 26 | }, 27 | { 28 | "Title": "Return of the Shirt", 29 | "Released": "2005-10-10", 30 | "Episode": "4", 31 | "imdbRating": "8.1", 32 | "imdbID": "tt0606112" 33 | }, 34 | { 35 | "Title": "Okay Awesome", 36 | "Released": "2005-10-17", 37 | "Episode": "5", 38 | "imdbRating": "8.4", 39 | "imdbID": "tt0606109" 40 | }, 41 | { 42 | "Title": "The Slutty Pumpkin", 43 | "Released": "2005-10-24", 44 | "Episode": "6", 45 | "imdbRating": "8.2", 46 | "imdbID": "tt0606116" 47 | }, 48 | { 49 | "Title": "Matchmaker", 50 | "Released": "2005-11-07", 51 | "Episode": "7", 52 | "imdbRating": "7.8", 53 | "imdbID": "tt0606108" 54 | }, 55 | { 56 | "Title": "The Duel", 57 | "Released": "2005-11-14", 58 | "Episode": "8", 59 | "imdbRating": "8.2", 60 | "imdbID": "tt0606113" 61 | }, 62 | { 63 | "Title": "Belly Full of Turkey", 64 | "Released": "2005-11-21", 65 | "Episode": "9", 66 | "imdbRating": "8.1", 67 | "imdbID": "tt0606104" 68 | }, 69 | { 70 | "Title": "The Pineapple Incident", 71 | "Released": "2005-11-28", 72 | "Episode": "10", 73 | "imdbRating": "9.2", 74 | "imdbID": "tt0606115" 75 | }, 76 | { 77 | "Title": "The Limo", 78 | "Released": "2005-12-19", 79 | "Episode": "11", 80 | "imdbRating": "8.3", 81 | "imdbID": "tt0606114" 82 | }, 83 | { 84 | "Title": "The Wedding", 85 | "Released": "2006-01-09", 86 | "Episode": "12", 87 | "imdbRating": "8.2", 88 | "imdbID": "tt0606118" 89 | }, 90 | { 91 | "Title": "Drumroll, Please", 92 | "Released": "2006-01-23", 93 | "Episode": "13", 94 | "imdbRating": "8.7", 95 | "imdbID": "tt0606106" 96 | }, 97 | { 98 | "Title": "Zip, Zip, Zip", 99 | "Released": "2006-02-06", 100 | "Episode": "14", 101 | "imdbRating": "8.2", 102 | "imdbID": "tt0606119" 103 | }, 104 | { 105 | "Title": "Game Night", 106 | "Released": "2006-02-27", 107 | "Episode": "15", 108 | "imdbRating": "9.1", 109 | "imdbID": "tt0606107" 110 | }, 111 | { 112 | "Title": "Cupcake", 113 | "Released": "2006-03-06", 114 | "Episode": "16", 115 | "imdbRating": "7.9", 116 | "imdbID": "tt0606105" 117 | }, 118 | { 119 | "Title": "Life Among the Gorillas", 120 | "Released": "2006-03-20", 121 | "Episode": "17", 122 | "imdbRating": "7.8", 123 | "imdbID": "tt0756504" 124 | }, 125 | { 126 | "Title": "Nothing Good Happens After 2 AM", 127 | "Released": "2006-04-10", 128 | "Episode": "18", 129 | "imdbRating": "8.5", 130 | "imdbID": "tt0606103" 131 | }, 132 | { 133 | "Title": "Mary the Paralegal", 134 | "Released": "2006-04-24", 135 | "Episode": "19", 136 | "imdbRating": "8.9", 137 | "imdbID": "tt0788623" 138 | }, 139 | { 140 | "Title": "Best Prom Ever", 141 | "Released": "2006-05-01", 142 | "Episode": "20", 143 | "imdbRating": "7.9", 144 | "imdbID": "tt0760776" 145 | }, 146 | { 147 | "Title": "Milk", 148 | "Released": "2006-05-08", 149 | "Episode": "21", 150 | "imdbRating": "8.2", 151 | "imdbID": "tt0801608" 152 | }, 153 | { 154 | "Title": "Come On", 155 | "Released": "2006-05-15", 156 | "Episode": "22", 157 | "imdbRating": "8.9", 158 | "imdbID": "tt0774239" 159 | } 160 | ], 161 | "Response": "True" 162 | } 163 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Version 4.4.1 2 | 3 | * Added building to umd for unpkg 4 | 5 | # Version 4.4.0 6 | 7 | * Turned on strict typescript checks 8 | * Add `baseURL` option so that folks can use their own omdb implementations, or 9 | the private Patreon instance 10 | * Added examples 11 | * Fix bug where module was unusable in frontend code (Github #84, Gitlab #1) 12 | * Migrated code to gitlab 13 | 14 | # Version 4.3.0 15 | 16 | * Added support for `Game` type from omdb (Fixes #81) 17 | 18 | # Version 4.2.0 19 | 20 | * Added the following fields: 21 | 22 | All types: 23 | * `ratings` (different than `rating`) 24 | * `awards` 25 | 26 | `Movie`: 27 | * `production` 28 | * `boxoffice` 29 | * `dvd` 30 | * `website` 31 | 32 | `Episode`: 33 | * `seriesid` 34 | 35 | * Migration to [ky](https://github.com/sindresorhus/ky) from [requests](https://github.com/request/request) 36 | * Migration to eslint from tslint 37 | * Prettifier 38 | 39 | # Version 4.1.0 40 | 41 | * Fix #73, #74 - where season was in some cases returned as '30' 42 | 43 | # Version 4.0.3 44 | 45 | * Documentation fixes 46 | * Dependency bumps 47 | 48 | # Version 4.0.0 -> 4.0.1/4.0.2 49 | 50 | * Fixes #63, #65 - Be more tolerant of bad data 51 | 52 | # Version 3.1.2 -> 4.0.0 53 | 54 | * Removed callback api 55 | * Created a client object so that applications can re-use options (Fixes #61) 56 | * Added short plot summary (Fixes #55, #37) 57 | * Episode now inherits from Movie, like everything else 58 | * Much more data validation on responses 59 | * Fix broken rating conversion 60 | * Drop support for unsupported node versions 61 | * Convert tests to typescript 62 | * Remove utils module 63 | * Remove `MovieOpts` from `MovieRequest` and have it be a separate arg to `get` 64 | * Changed `SearchRequest.title` to `SearchRequest.name` to unify interface 65 | * Specify types for `TVShow.totalseasons`, `TVShow.start_year` and `TVShow.end_year` 66 | 67 | # Version 3.1.1 -> 3.1.2 68 | 69 | * Fixes #54 70 | * Fixes #51 71 | * lots of modernization and enabling of tslint 72 | 73 | # Version 3.0.0 -> 3.1.0 74 | 75 | This adds searching for movies and items from omdb. 76 | 77 | ```js 78 | imdb.search({title: 'foo'}, {apiKey: 'bar'}).then(console.log); 79 | ``` 80 | 81 | This also adds supports for timeouts 82 | 83 | ```js 84 | imdb.get('The Toxic Avenger', {apiKey: 'foo', timeout: 30}).then(console.log); 85 | ``` 86 | 87 | # Version 2.2.2 -> 3.0.0 88 | 89 | This is a breaking change 90 | 91 | * Added support for passing in options to all `get` functions 92 | * Require an apiKey option for authentication to omdb 93 | 94 | ```js 95 | imdb.get('The Toxic Avenger', {apiKey: 'foo'}).then(function(data) { console.log(data); }); 96 | ``` 97 | 98 | To see more about getting a key, see [here](https://www.patreon.com/posts/api-is-going-10743518) 99 | 100 | # Version 2.2.1 -> 2.2.2 101 | 102 | * Fixed broken date parsing ([PR](https://github.com/worr/node-imdb-api/pull/41)) 103 | 104 | # Version 2.2.0 -> 2.2.1 105 | 106 | * Bug fixes 107 | 108 | # Version 2.1.0 -> 2.2.0 109 | 110 | * Added promise API 111 | 112 | ## Promises 113 | 114 | ```js 115 | imdb.get('The Toxic Avenger').then(function(data) { console.log(data); }); 116 | ``` 117 | 118 | # Version 2.0.0 -> 2.1.0 119 | 120 | * Adds the ability to filter by year 121 | 122 | ## Filtering by year 123 | 124 | ```js 125 | imdb.getReq({name: 'James Bond', year: 2015}, function(err, data) { console.log(data) }); 126 | ``` 127 | 128 | # Version 1.3.3 -> 2.0.0 129 | 130 | Version 2.0 is a breaking change. The APIs that I was using disappeared, and I 131 | switched over to using omdb. Most of the functions and the objects returned 132 | are similar, with some additional properties (and some removed). 133 | 134 | ## Removed properties 135 | 136 | The following properties have been removed from all movie/tv show/episode 137 | objects that are returned to callbacks. 138 | 139 | * `stv` 140 | * `usascreens` 141 | * `ukscreens` 142 | 143 | ## Renamed properties 144 | 145 | The following properties have been renamed in order to not conflict with 146 | builtins or to better describe what the property means 147 | 148 | * `Episode.number` -> `Episode.episode` 149 | 150 | ## Retyped properties 151 | 152 | Some properties have new types for convenience. 153 | 154 | * `Episode.released`: `string` -> `Date` 155 | * `Movie.released`: `string` -> `Date` 156 | * `Movie.series`: `number` -> `boolean` 157 | 158 | ## Changed callback signatures 159 | 160 | * The `episodes` call now just passes a list of episodes to the callback 161 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-imdb-api 2 | 3 | A non-scraping, functional node.js interface to imdb 4 | 5 | # Badges 6 | 7 | [![NPM version](https://badge.fury.io/js/imdb-api.svg)](http://badge.fury.io/js/imdb-api) [![pipeline status](https://gitlab.com/worr/node-imdb-api/badges/master/pipeline.svg)](https://gitlab.com/worr/node-imdb-api/-/commits/master) [![Dependency Freshness](https://david-dm.org/worr/node-imdb-api.svg)](https://david-dm.org/worr/node-imdb-api) [![coverage report](https://gitlab.com/worr/node-imdb-api/badges/master/coverage.svg)](https://gitlab.com/worr/node-imdb-api/-/commits/master) [![Join the chat at https://gitter.im/worr/node-imdb-api](https://badges.gitter.im/worr/node-imdb-api.svg)](https://gitter.im/worr/node-imdb-api?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 8 | 9 | # Github / Gitlab 10 | 11 | [Gitlab](https://gitlab.com/worr/node-imdb-api) is the official upstream, and 12 | commits are mirrored to [Github](https://github.com/worr/node-imdb-api). I look 13 | at issues and PRs/MRs on both. Feel free to contribute on either. 14 | 15 | # API Docs 16 | 17 | [API docs are now here](https://docs.worrbase.com/node/imdb-api/) 18 | 19 | # Use 20 | 21 | Import the library using `require` 22 | 23 | ```js 24 | const imdb = require('imdb-api') 25 | ``` 26 | 27 | or ES6 `import` 28 | 29 | ```js 30 | import imdb from 'imdb-api' 31 | ``` 32 | 33 | Call `get` to get a single movie 34 | ```js 35 | imdb.get({name: 'The Toxic Avenger'}, {apiKey: 'foo', timeout: 30000}).then(console.log).catch(console.log); 36 | 37 | Movie { 38 | title: 'The Toxic Avenger', 39 | ... 40 | } 41 | ``` 42 | Furthermore if you already know the id you can call `get` with different args: 43 | ```js 44 | imdb.get({id: 'tt0090190'}, {apiKey: 'foo'}).then(console.log); 45 | 46 | Movie { 47 | title: 'The Toxic Avenger', 48 | ... 49 | } 50 | ``` 51 | 52 | You can search for movies, and get multiple results by using the `search` function. 53 | 54 | ```js 55 | imdb.search({ 56 | name: 'Toxic Avenger' 57 | }, { 58 | apiKey: 'foo' 59 | }).then(console.log).catch(console.log); 60 | ``` 61 | 62 | TV shows have an `episodes` method that you can use to fetch all of the episodes 63 | from that TV series. 64 | 65 | ```js 66 | imdb.get({name: 'How I Met Your Mother'}, {apiKey: 'foo'}).then((things) => { 67 | return things.episodes() 68 | }).then((eps) => { 69 | console.log(eps); 70 | }); 71 | 72 | Episode { 73 | season: 2, 74 | name: 'The Scorpion and the Toad', 75 | released: '2006-10-25T07:00:00.000Z', 76 | episode: 2, 77 | rating: '8.3', 78 | imdbid: 'tt0869673' }, 79 | ... 80 | ``` 81 | 82 | # Using a `Client` object 83 | 84 | `imdb-api` also exported a `Client` object that you can use to store options for subsequent requests. 85 | 86 | ```js 87 | import imdb = require('imdb'); 88 | const cli = new imdb.Client({apiKey: 'xxxxxx'}); 89 | cli.get({'name': 'The Toxic Avenger'}).then(console.log); 90 | ``` 91 | 92 | `Client` also has a `search` method for searching. 93 | 94 | ```js 95 | import imdb = require('imdb'); 96 | const cli = new imdb.Client({apiKey: 'xxxxxx'}); 97 | cli.search({'name': 'The Toxic Avenger'}).then((search) => { 98 | for (const result of search.results) { 99 | console.log(result.title); 100 | } 101 | }); 102 | ``` 103 | 104 | # FAQ 105 | 106 | ## I see an API key in your examples? Is it required? How do I get one? 107 | 108 | Yes, it is required! omdb made this a requirement as of May 8, 2017. This is unfortunate, 109 | but totally understandable. While I plan on working on finding an alternative to provide 110 | the movie info you crave, I've enabled you to pass in an apikey. 111 | 112 | You can get one by going [here](https://www.patreon.com/posts/api-is-going-10743518). 113 | 114 | ## Why? There are like 3 other interfaces to imdb in npm 115 | 116 | Most of them scrape imdb. imdb explicitly forbids scraping. 117 | 118 | And what happens when the site layout changes? Well then your screen scraping 119 | solution fails in interesting ways. Screen scraping is also pretty slow, 120 | and we can't have that. 121 | 122 | ## WOAH I looked at your code and you're using unofficial APIs! 123 | 124 | There isn't an official API to imdb. As soon as one is released (and I 125 | notice), I'll update the module. 126 | 127 | imdb DOES release all of their data in text files nightly, so unofficial sites 128 | have popped up providing RESTful APIs against that data. 129 | 130 | I have to use a few, since none of them are complete. 131 | 132 | ## What if one of the unofficial APIs disappears? 133 | 134 | File a bug. I'll get creative. 135 | -------------------------------------------------------------------------------- /doc/globals.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 59 |

imdb-api

60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |

Index

68 |
69 |
70 |
71 |

Modules

72 | 76 |
77 |
78 |
79 |
80 |
81 | 106 |
107 |
108 |
109 |
110 |

Legend

111 |
112 |
    113 |
  • Function
  • 114 |
  • Type alias
  • 115 |
116 |
    117 |
  • Interface
  • 118 |
119 |
    120 |
  • Class
  • 121 |
122 |
123 |
124 |
125 |
126 |

Generated using TypeDoc

127 |
128 |
129 | 130 | 131 | -------------------------------------------------------------------------------- /test/test-client.ts: -------------------------------------------------------------------------------- 1 | import "https"; 2 | import path from "path"; 3 | import nock from "nock"; 4 | import { Done, it, describe } from "mocha"; 5 | import chai from "chai"; 6 | import chaiAsPromised from "chai-as-promised"; 7 | 8 | // Node just like, has this. ts-node requires this import 9 | import { URL } from "url"; 10 | 11 | import * as imdb from "../lib/imdb"; 12 | 13 | chai.use(chaiAsPromised); 14 | const { assert } = chai; 15 | 16 | describe("tests client creation and use", () => { 17 | it("creates a new client with one options", (done: Done) => { 18 | const cli = new imdb.Client({ apiKey: "foo" }); 19 | 20 | assert.isOk(cli, "ensure client is created"); 21 | done(); 22 | }); 23 | 24 | it("creates a new client without an apikey", (done: Done) => { 25 | assert.throws(() => { 26 | new imdb.Client({} as imdb.MovieOpts); // eslint-disable-line no-new 27 | }, /Missing api key/); 28 | done(); 29 | }); 30 | 31 | it("makes a get request", () => { 32 | const cli = new imdb.Client({ apiKey: "foo" }); 33 | nock("https://www.omdbapi.com") 34 | .get("/?apikey=foo&plot=full&r=json&t=The%20Toxic%20Avenger") 35 | .replyWithFile(200, path.join(__dirname, "/data/toxic-avenger.json")); 36 | 37 | return assert.eventually.propertyVal( 38 | cli.get({ 39 | name: "The Toxic Avenger", 40 | }), 41 | "title", 42 | "The Toxic Avenger", 43 | "ensuring that we got a movie" 44 | ); 45 | }); 46 | 47 | it("makes a search request", () => { 48 | const cli = new imdb.Client({ apiKey: "foo" }); 49 | nock("https://www.omdbapi.com") 50 | .get("/?apikey=foo&page=1&r=json&s=Toxic%20Avenger") 51 | .replyWithFile( 52 | 200, 53 | path.join(__dirname, "/data/toxic-avenger-search.json") 54 | ); 55 | 56 | return assert.eventually.nestedPropertyVal( 57 | cli.search({ 58 | name: "Toxic Avenger", 59 | }), 60 | "results[0].title", 61 | "The Toxic Avenger", 62 | "ensuring that we got a movie" 63 | ); 64 | }); 65 | 66 | it("merges options from client args", () => { 67 | const cli = new imdb.Client({ apiKey: "foo" }); 68 | nock("https://www.omdbapi.com") 69 | .get("/?apikey=foo&plot=full&r=json&t=The%20Toxic%20Avenger") 70 | .delay(2000) 71 | .replyWithFile(200, path.join(__dirname, "/data/toxic-avenger.json")); 72 | 73 | return assert.isRejected( 74 | cli.get( 75 | { 76 | name: "The Toxic Avenger", 77 | }, 78 | { 79 | timeout: 1000, 80 | } 81 | ), 82 | /Request timed out/ 83 | ); 84 | }); 85 | 86 | it("merges options from client args when performing a search", () => { 87 | const cli = new imdb.Client({ apiKey: "foo" }); 88 | nock("https://www.omdbapi.com") 89 | .get("/?apikey=foo&page=1&r=json&s=Toxic%20Avenger") 90 | .delay(2000) 91 | .replyWithFile( 92 | 200, 93 | path.join(__dirname, "/data/toxic-avenger-search.json") 94 | ); 95 | 96 | return assert.isRejected( 97 | cli.search( 98 | { 99 | name: "Toxic Avenger", 100 | }, 101 | 1, 102 | { 103 | timeout: 1000, 104 | } 105 | ), 106 | /Request timed out/ 107 | ); 108 | }); 109 | 110 | it("uses a new baseURL when configured from a string", () => { 111 | const cli = new imdb.Client({ apiKey: "foo", baseURL: "https://bar.com" }); 112 | nock("https://bar.com") 113 | .get("/?apikey=foo&plot=full&r=json&t=The%20Toxic%20Avenger") 114 | .replyWithFile(200, path.join(__dirname, "/data/toxic-avenger.json")); 115 | 116 | return assert.eventually.propertyVal( 117 | cli.get({ 118 | name: "The Toxic Avenger", 119 | }), 120 | "title", 121 | "The Toxic Avenger", 122 | "ensuring that we got a movie from bar.com" 123 | ); 124 | }); 125 | 126 | it("uses a new baseURL when configured for search from a string", () => { 127 | const cli = new imdb.Client({ apiKey: "foo", baseURL: "https://bar.com" }); 128 | nock("https://bar.com") 129 | .get("/?apikey=foo&page=1&r=json&s=Toxic%20Avenger") 130 | .replyWithFile( 131 | 200, 132 | path.join(__dirname, "/data/toxic-avenger-search.json") 133 | ); 134 | 135 | return assert.eventually.nestedPropertyVal( 136 | cli.search({ 137 | name: "Toxic Avenger", 138 | }), 139 | "results[0].title", 140 | "The Toxic Avenger", 141 | "ensuring that we got a movie from bar.com" 142 | ); 143 | }); 144 | 145 | it("uses a new baseURL when configured from a URL", () => { 146 | const cli = new imdb.Client({ 147 | apiKey: "foo", 148 | baseURL: new URL("https://bar.com"), 149 | }); 150 | nock("https://bar.com") 151 | .get("/?apikey=foo&plot=full&r=json&t=The%20Toxic%20Avenger") 152 | .replyWithFile(200, path.join(__dirname, "/data/toxic-avenger.json")); 153 | 154 | return assert.eventually.propertyVal( 155 | cli.get({ 156 | name: "The Toxic Avenger", 157 | }), 158 | "title", 159 | "The Toxic Avenger", 160 | "ensuring that we got a movie from bar.com" 161 | ); 162 | }); 163 | 164 | it("uses a new baseURL when configured for search", () => { 165 | const cli = new imdb.Client({ 166 | apiKey: "foo", 167 | baseURL: new URL("https://bar.com"), 168 | }); 169 | nock("https://bar.com") 170 | .get("/?apikey=foo&page=1&r=json&s=Toxic%20Avenger") 171 | .replyWithFile( 172 | 200, 173 | path.join(__dirname, "/data/toxic-avenger-search.json") 174 | ); 175 | 176 | return assert.eventually.nestedPropertyVal( 177 | cli.search({ 178 | name: "Toxic Avenger", 179 | }), 180 | "results[0].title", 181 | "The Toxic Avenger", 182 | "ensuring that we got a movie from bar.com" 183 | ); 184 | }); 185 | }); 186 | -------------------------------------------------------------------------------- /test/test-movie.ts: -------------------------------------------------------------------------------- 1 | import { describe, it } from "mocha"; 2 | import chai from "chai"; 3 | import * as imdb from "../lib/imdb"; 4 | 5 | const { assert } = chai; 6 | 7 | const origMovie = { 8 | Title: "Foo", 9 | Year: "1996", 10 | Rated: "R", 11 | Released: "1 May 2001", 12 | Runtime: "5 min", 13 | Genre: "rom com", 14 | Director: "Tilde Swinton", 15 | Writer: "Tilde Swinton", 16 | Actors: "John, Larry, Curly", 17 | Plot: "It good", 18 | Language: "Spanish", 19 | Country: "USA", 20 | Awards: "Lots", 21 | Poster: "www.google.com", 22 | Metascore: "5.6", 23 | imdbRating: "6.7", 24 | imdbVotes: "5", 25 | imdbID: "tt653921", 26 | Type: "movie", 27 | Response: "ok", 28 | }; 29 | 30 | const origTv = { 31 | Title: "Foo", 32 | Year: "1996-1998", 33 | Rated: "R", 34 | Released: "1 May 2001", 35 | Runtime: "5 min", 36 | Genre: "rom com", 37 | Director: "Tilde Swinton", 38 | Writer: "Tilde Swinton", 39 | Actors: "John, Larry, Curly", 40 | Plot: "It good", 41 | Language: "Spanish", 42 | Country: "USA", 43 | Awards: "Lots", 44 | Poster: "www.google.com", 45 | Metascore: "5.6", 46 | imdbRating: "6.7", 47 | imdbVotes: "5", 48 | imdbID: "tt653921", 49 | Type: "series", 50 | totalSeasons: "5", 51 | Response: "ok", 52 | }; 53 | 54 | const origEpisode = { 55 | Title: "ep 1", 56 | Rated: "R", 57 | Released: "6 May 2001", 58 | Runtime: "5 min", 59 | Genre: "rom com", 60 | Director: "Tilde Swinton", 61 | Writer: "Tilde Swinton", 62 | Actors: "John, Larry, Curly", 63 | Plot: "It good", 64 | Language: "Spanish", 65 | Country: "USA", 66 | Awards: "Lots", 67 | Poster: "www.google.com", 68 | Metascore: "5.6", 69 | Episode: "1", 70 | Type: "episode", 71 | imdbRating: "5.6", 72 | imdbID: "tt6539212", 73 | imdbVotes: "17", 74 | Year: "2006", 75 | Season: "5", 76 | Response: "ok", 77 | seriesID: "tt1480055", 78 | }; 79 | 80 | const origGame = { 81 | Title: "The Legend of Heroes: Trails of Cold Steel", 82 | Year: "2015", 83 | Rated: "N/A", 84 | Released: "22 Dec 2015", 85 | Runtime: "N/A", 86 | Genre: "Adventure", 87 | Director: "Valerie Arem", 88 | Writer: "N/A", 89 | Actors: "Edward Bosco, Ben Diskin, Lucien Dodge, D.C. Douglas", 90 | Plot: "N/A", 91 | Language: "English", 92 | Country: "USA", 93 | Awards: "N/A", 94 | Poster: "N/A", 95 | Ratings: [], 96 | Metascore: "N/A", 97 | imdbRating: "N/A", 98 | imdbVotes: "N/A", 99 | imdbID: "tt5591880", 100 | Type: "game", 101 | DVD: "N/A", 102 | BoxOffice: "N/A", 103 | Production: "N/A", 104 | Website: "N/A", 105 | Response: "True", 106 | }; 107 | 108 | describe("Movie", () => { 109 | it("creates a normal movie", () => { 110 | const mov = new imdb.Movie(origMovie); 111 | 112 | assert.isOk(mov, "movie exists"); 113 | assert.deepEqual(mov.title, "Foo", "name is set correctly"); 114 | assert.deepEqual( 115 | mov.released, 116 | new Date(2001, 4, 1), 117 | "Date created correctly" 118 | ); 119 | assert.deepEqual(mov.rating, 6.7); 120 | assert.deepEqual(mov.genres, origMovie.Genre, "Genres set correctly"); 121 | assert.deepEqual( 122 | mov.languages, 123 | origMovie.Language, 124 | "Language set correctly" 125 | ); 126 | assert.deepEqual(mov.votes, "5", "votes set correctly"); 127 | assert.deepEqual(mov.series, false, "not a series"); 128 | assert.deepEqual( 129 | mov.imdburl, 130 | "https://www.imdb.com/title/tt653921", 131 | "url formulated correctly" 132 | ); 133 | }); 134 | it("creates a movie with invalid rating", () => { 135 | const mov = Object.assign(Object.create(origMovie), { 136 | imdbRating: "N/A", 137 | }); 138 | assert.equal(new imdb.Movie(mov).rating, 0); 139 | }); 140 | it("creates a movie with bad release date", () => { 141 | const mov = Object.assign(Object.create(origMovie), { 142 | Released: "N/A", 143 | }); 144 | assert.isUndefined(new imdb.Movie(mov).released); 145 | }); 146 | it("creates a movie with no year", () => { 147 | const mov = Object.assign(Object.create(origMovie), { 148 | Year: undefined, 149 | }); 150 | assert.isNotOk(new imdb.Movie(mov).year); 151 | }); 152 | it("creates a movie with invalid year", () => { 153 | const mov = Object.assign(Object.create(origMovie), { Year: "foo" }); 154 | assert.throws(() => new imdb.Movie(mov), TypeError); 155 | }); 156 | it("creates a movie with matching year", () => { 157 | for (const year of ["2005-2006", "2005-", "2005–2006", "2005–"]) { 158 | const mov = Object.assign(Object.create(origMovie), { 159 | Year: year, 160 | }); 161 | assert.isNotOk(new imdb.Movie(mov).year); 162 | } 163 | }); 164 | }); 165 | 166 | describe("Series", () => { 167 | it("creates a series", () => { 168 | const mov = new imdb.TVShow(origTv, { apiKey: "foo" }); 169 | 170 | assert.isOk(mov, "movie exists"); 171 | assert.deepEqual(mov.title, "Foo", "name is set correctly"); 172 | assert.deepEqual( 173 | mov.released, 174 | new Date(2001, 4, 1), 175 | "Date created correctly" 176 | ); 177 | assert.deepEqual(mov.rating, 6.7); 178 | assert.deepEqual(mov.genres, origTv.Genre, "Genres set correctly"); 179 | assert.deepEqual(mov.languages, origTv.Language, "Language set correctly"); 180 | assert.deepEqual(mov.votes, "5", "votes set correctly"); 181 | assert.deepEqual(mov.series, true, "deffo a series"); 182 | assert.deepEqual( 183 | mov.imdburl, 184 | "https://www.imdb.com/title/tt653921", 185 | "url formulated correctly" 186 | ); 187 | assert.deepEqual(mov.start_year, 1996, "test start year"); 188 | assert.deepEqual(mov.end_year, 1998, "end year set correctly"); 189 | assert.deepEqual(mov.totalseasons, 5, "total seasons set correctly"); 190 | }); 191 | it("creates a series with invalid year", () => { 192 | const mov = Object.assign(Object.create(origTv), { Year: "foo-" }); 193 | assert.throws(() => new imdb.TVShow(mov, { apiKey: "foo" }), TypeError); 194 | }); 195 | }); 196 | 197 | describe("Episode", () => { 198 | it("creates a basic episode", () => { 199 | const ep = new imdb.Episode(origEpisode, 1); 200 | 201 | assert.isOk(ep, "ep exists"); 202 | assert.deepEqual(ep.name, "ep 1", "title is set correctly"); 203 | assert.deepEqual(ep.rating, 5.6, "rating set correctly"); 204 | assert.deepEqual(ep.imdbid, "tt6539212", "imdb id set"); 205 | assert.deepEqual( 206 | ep.released, 207 | new Date(2001, 4, 6), 208 | "Date created correctly" 209 | ); 210 | assert.deepEqual(ep.season, 1, "testing season"); 211 | assert.deepEqual(ep.episode, 1, "testing ep"); 212 | assert.deepEqual(ep.year, 2006, "testing year"); 213 | }); 214 | 215 | it("creates an episode with an invalid release", () => { 216 | const ep = Object.assign(Object.create(origTv), { Released: "foo" }); 217 | assert.isUndefined(new imdb.Episode(ep, 30).released); 218 | }); 219 | 220 | it("creates an episode with an invalid year", () => { 221 | const ep = Object.assign(Object.create(origTv), { Year: "foo" }); 222 | assert.throws(() => new imdb.Episode(ep, 30), TypeError); 223 | }); 224 | 225 | it("creates an episode with an invalid number", () => { 226 | const ep = Object.assign(Object.create(origTv), { Episode: "foo" }); 227 | assert.throws(() => new imdb.Episode(ep, 30), TypeError); 228 | }); 229 | }); 230 | 231 | describe("Game", () => { 232 | it("creates a basic game", () => { 233 | const game = new imdb.Game(origGame); 234 | 235 | assert.isOk(game, "game exists"); 236 | assert.deepEqual(game.name, "The Legend of Heroes: Trails of Cold Steel"); 237 | assert.deepEqual(game.rating, 0); 238 | assert.deepEqual(game.imdbid, "tt5591880"); 239 | assert.deepEqual(game.released, new Date(2015, 11, 22)); 240 | }); 241 | }); 242 | -------------------------------------------------------------------------------- /doc/interfaces/_interfaces_.omdbrating.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | OmdbRating | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 65 |

Interface OmdbRating

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |

Hierarchy

74 |
    75 |
  • 76 | OmdbRating 77 |
  • 78 |
79 |
80 |
81 |

Index

82 |
83 |
84 |
85 |

Properties

86 | 90 |
91 |
92 |
93 |
94 |
95 |

Properties

96 |
97 | 98 |

Source

99 |
Source: string
100 | 105 |
106 |
107 | 108 |

Value

109 |
Value: string
110 | 115 |
116 |
117 |
118 | 203 |
204 |
205 |
206 |
207 |

Legend

208 |
209 |
    210 |
  • Function
  • 211 |
  • Type alias
  • 212 |
213 |
    214 |
  • Interface
  • 215 |
216 |
    217 |
  • Class
  • 218 |
219 |
220 |
221 |
222 |
223 |

Generated using TypeDoc

224 |
225 |
226 | 227 | 228 | -------------------------------------------------------------------------------- /doc/interfaces/_interfaces_.omdberror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | OmdbError | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 65 |

Interface OmdbError

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |

Hierarchy

74 |
    75 |
  • 76 | OmdbError 77 |
  • 78 |
79 |
80 |
81 |

Index

82 |
83 |
84 |
85 |

Properties

86 | 90 |
91 |
92 |
93 |
94 |
95 |

Properties

96 |
97 | 98 |

Error

99 |
Error: string
100 | 105 |
106 |
107 | 108 |

Response

109 |
Response: string
110 | 115 |
116 |
117 |
118 | 203 |
204 |
205 |
206 |
207 |

Legend

208 |
209 |
    210 |
  • Function
  • 211 |
  • Type alias
  • 212 |
213 |
    214 |
  • Interface
  • 215 |
216 |
    217 |
  • Class
  • 218 |
219 |
220 |
221 |
222 |
223 |

Generated using TypeDoc

224 |
225 |
226 | 227 | 228 | -------------------------------------------------------------------------------- /doc/interfaces/_interfaces_.omdbsearch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | OmdbSearch | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 65 |

Interface OmdbSearch

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |

Hierarchy

74 |
    75 |
  • 76 | OmdbSearch 77 |
  • 78 |
79 |
80 |
81 |

Index

82 |
83 |
84 |
85 |

Properties

86 | 91 |
92 |
93 |
94 |
95 |
96 |

Properties

97 |
98 | 99 |

Response

100 |
Response: string
101 | 106 |
107 |
108 | 109 |

Search

110 | 111 | 116 |
117 |
118 | 119 |

totalResults

120 |
totalResults: string
121 | 126 |
127 |
128 |
129 | 217 |
218 |
219 |
220 |
221 |

Legend

222 |
223 |
    224 |
  • Function
  • 225 |
  • Type alias
  • 226 |
227 |
    228 |
  • Interface
  • 229 |
230 |
    231 |
  • Class
  • 232 |
233 |
234 |
235 |
236 |
237 |

Generated using TypeDoc

238 |
239 |
240 | 241 | 242 | -------------------------------------------------------------------------------- /doc/classes/_imdb_.imdberror.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ImdbError | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 65 |

Class ImdbError

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |

Hierarchy

74 |
    75 |
  • 76 | ImdbError 77 |
  • 78 |
79 |
80 |
81 |

Index

82 |
83 |
84 |
85 |

Constructors

86 | 89 |
90 |
91 |

Properties

92 | 96 |
97 |
98 |
99 |
100 |
101 |

Constructors

102 |
103 | 104 |

constructor

105 |
    106 |
  • new ImdbError(message: string): ImdbError
  • 107 |
108 |
    109 |
  • 110 | 115 |

    Parameters

    116 |
      117 |
    • 118 |
      message: string
      119 |
    • 120 |
    121 |

    Returns ImdbError

    122 |
  • 123 |
124 |
125 |
126 |
127 |

Properties

128 |
129 | 130 |

message

131 |
message: string
132 | 137 |
138 |
139 | 140 |

name

141 |
name: string = "imdb api error"
142 | 147 |
148 |
149 |
150 | 238 |
239 |
240 |
241 |
242 |

Legend

243 |
244 |
    245 |
  • Class
  • 246 |
  • Constructor
  • 247 |
  • Property
  • 248 |
249 |
    250 |
  • Function
  • 251 |
  • Type alias
  • 252 |
253 |
    254 |
  • Interface
  • 255 |
256 |
257 |
258 |
259 |
260 |

Generated using TypeDoc

261 |
262 |
263 | 264 | 265 | -------------------------------------------------------------------------------- /doc/interfaces/_imdb_.searchrequest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | SearchRequest | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 65 |

Interface SearchRequest

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |

A search for a movie. This will fetch multiple results based on fuzzy matches 76 | for a particular piece of media.

77 |
78 |
79 |
80 |
81 |

Hierarchy

82 |
    83 |
  • 84 | SearchRequest 85 |
  • 86 |
87 |
88 |
89 |

Index

90 |
91 |
92 |
93 |

Properties

94 | 99 |
100 |
101 |
102 |
103 |
104 |

Properties

105 |
106 | 107 |

name

108 |
name: string
109 | 114 |
115 |
116 |

Title of the media that we're looking for. Unfortunately, only English 117 | names are supported by omdb at the moment.

118 |
119 |
120 |
121 |
122 | 123 |

Optional reqtype

124 |
reqtype: RequestType
125 | 130 |
131 |
132 |

Type of media we're looking for

133 |
134 |
135 |
136 |
137 | 138 |

Optional year

139 |
year: undefined | number
140 | 145 |
146 |
147 |

Year that the media was released

148 |
149 |
150 |
151 |
152 |
153 | 241 |
242 |
243 |
244 |
245 |

Legend

246 |
247 |
    248 |
  • Function
  • 249 |
  • Type alias
  • 250 |
251 |
    252 |
  • Interface
  • 253 |
  • Property
  • 254 |
255 |
    256 |
  • Class
  • 257 |
258 |
259 |
260 |
261 |
262 |

Generated using TypeDoc

263 |
264 |
265 | 266 | 267 | -------------------------------------------------------------------------------- /doc/interfaces/_imdb_.movieopts.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | MovieOpts | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 65 |

Interface MovieOpts

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |

Options to manipulate movie fetching. These can be passed to get, search 76 | or the constructor for Client.

77 |
78 |
79 |
80 |
81 |

Hierarchy

82 |
    83 |
  • 84 | MovieOpts 85 |
  • 86 |
87 |
88 |
89 |

Index

90 |
91 |
92 |
93 |

Properties

94 | 99 |
100 |
101 |
102 |
103 |
104 |

Properties

105 |
106 | 107 |

Optional apiKey

108 |
apiKey: undefined | string
109 | 114 |
115 |
116 |

API key for omdbapi. Needed to make any API calls.

117 |
118 |

Get one here

119 |
120 |
121 |
122 | 123 |

Optional baseURL

124 |
baseURL: string | URL
125 | 130 |
131 |
132 |

Base URL to connect to (default: https://www.omdbapi.com)

133 |
134 |
135 |
136 |
137 | 138 |

Optional timeout

139 |
timeout: undefined | number
140 | 145 |
146 |
147 |

Timeout in milliseconds to wait before giving up on a request

148 |
149 |
150 |
151 |
152 |
153 | 241 |
242 |
243 |
244 |
245 |

Legend

246 |
247 |
    248 |
  • Function
  • 249 |
  • Type alias
  • 250 |
251 |
    252 |
  • Interface
  • 253 |
  • Property
  • 254 |
255 |
    256 |
  • Class
  • 257 |
258 |
259 |
260 |
261 |
262 |

Generated using TypeDoc

263 |
264 |
265 | 266 | 267 | -------------------------------------------------------------------------------- /doc/classes/_imdb_.rating.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Rating | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 65 |

Class Rating

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |

Rating for a piece of media.

76 |
77 |
78 |
79 |
80 |

Hierarchy

81 |
    82 |
  • 83 | Rating 84 |
  • 85 |
86 |
87 |
88 |

Index

89 |
90 |
91 |
92 |

Constructors

93 | 96 |
97 |
98 |

Properties

99 | 103 |
104 |
105 |
106 |
107 |
108 |

Constructors

109 |
110 | 111 |

constructor

112 |
    113 |
  • new Rating(source: string, value: string): Rating
  • 114 |
115 |
    116 |
  • 117 | 122 |

    Parameters

    123 |
      124 |
    • 125 |
      source: string
      126 |
    • 127 |
    • 128 |
      value: string
      129 |
    • 130 |
    131 |

    Returns Rating

    132 |
  • 133 |
134 |
135 |
136 |
137 |

Properties

138 |
139 | 140 |

source

141 |
source: string
142 | 147 |
148 |
149 |

Site where the rating came from

150 |
151 |
152 |
153 |
154 | 155 |

value

156 |
value: string
157 | 162 |
163 |
164 |

Rating that the media got from the @{link Rating.source}

165 |
166 |
167 |
168 |
169 |
170 | 258 |
259 |
260 |
261 |
262 |

Legend

263 |
264 |
    265 |
  • Class
  • 266 |
  • Constructor
  • 267 |
  • Property
  • 268 |
269 |
    270 |
  • Function
  • 271 |
  • Type alias
  • 272 |
273 |
    274 |
  • Interface
  • 275 |
276 |
277 |
278 |
279 |
280 |

Generated using TypeDoc

281 |
282 |
283 | 284 | 285 | -------------------------------------------------------------------------------- /doc/interfaces/_interfaces_.omdbsearchresult.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | OmdbSearchResult | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 65 |

Interface OmdbSearchResult

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |

Hierarchy

74 |
    75 |
  • 76 | OmdbSearchResult 77 |
  • 78 |
79 |
80 |
81 |

Index

82 |
83 |
84 |
85 |

Properties

86 | 93 |
94 |
95 |
96 |
97 |
98 |

Properties

99 |
100 | 101 |

Poster

102 |
Poster: string
103 | 108 |
109 |
110 | 111 |

Title

112 |
Title: string
113 | 118 |
119 |
120 | 121 |

Type

122 |
Type: string
123 | 128 |
129 |
130 | 131 |

Year

132 |
Year: string
133 | 138 |
139 |
140 | 141 |

imdbID

142 |
imdbID: string
143 | 148 |
149 |
150 |
151 | 245 |
246 |
247 |
248 |
249 |

Legend

250 |
251 |
    252 |
  • Function
  • 253 |
  • Type alias
  • 254 |
255 |
    256 |
  • Interface
  • 257 |
258 |
    259 |
  • Class
  • 260 |
261 |
262 |
263 |
264 |
265 |

Generated using TypeDoc

266 |
267 |
268 | 269 | 270 | -------------------------------------------------------------------------------- /doc/interfaces/_interfaces_.omdbseason.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | OmdbSeason | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 65 |

Interface OmdbSeason

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |

Hierarchy

74 |
    75 |
  • 76 | OmdbSeason 77 |
  • 78 |
79 |
80 |
81 |

Index

82 |
83 |
84 |
85 |

Properties

86 | 93 |
94 |
95 |
96 |
97 |
98 |

Properties

99 |
100 | 101 |

Episodes

102 |
Episodes: OmdbEpisode[]
103 | 108 |
109 |
110 | 111 |

Response

112 |
Response: string
113 | 118 |
119 |
120 | 121 |

Season

122 |
Season: string
123 | 128 |
129 |
130 | 131 |

Title

132 |
Title: string
133 | 138 |
139 |
140 | 141 |

totalSeasons

142 |
totalSeasons: string
143 | 148 |
149 |
150 |
151 | 245 |
246 |
247 |
248 |
249 |

Legend

250 |
251 |
    252 |
  • Function
  • 253 |
  • Type alias
  • 254 |
255 |
    256 |
  • Interface
  • 257 |
258 |
    259 |
  • Class
  • 260 |
261 |
262 |
263 |
264 |
265 |

Generated using TypeDoc

266 |
267 |
268 | 269 | 270 | -------------------------------------------------------------------------------- /test/test-getReq.ts: -------------------------------------------------------------------------------- 1 | import "https"; 2 | import path from "path"; 3 | import nock from "nock"; 4 | import { describe, it } from "mocha"; 5 | import chai from "chai"; 6 | import chaiAsPromised from "chai-as-promised"; 7 | import { URL } from "url"; 8 | 9 | import * as imdb from "../lib/imdb"; 10 | 11 | chai.use(chaiAsPromised); 12 | const { assert } = chai; 13 | 14 | describe("get", () => { 15 | it("makes a successful request by name", () => { 16 | nock("https://www.omdbapi.com") 17 | .get("/?apikey=foo&plot=full&r=json&t=The%20Toxic%20Avenger") 18 | .replyWithFile(200, path.join(__dirname, "/data/toxic-avenger.json")); 19 | 20 | return assert.isFulfilled( 21 | imdb 22 | .get( 23 | { 24 | name: "The Toxic Avenger", 25 | }, 26 | { 27 | apiKey: "foo", 28 | } 29 | ) 30 | .then((data) => { 31 | assert.isOk(data); 32 | assert.deepEqual(data.imdbid, "tt0090191", "testing returned data"); 33 | assert.deepEqual(data.series, false, "testing series bool"); 34 | assert.deepEqual( 35 | Object.prototype.hasOwnProperty.call(data, "episodes"), 36 | false, 37 | "should not have episodes" 38 | ); 39 | assert.deepEqual(data.rating, 6.2, "testing rating conversion"); 40 | assert.deepEqual(data.website, "N/A", "testing fetching website"); 41 | assert.deepEqual(data.ratings[0].value, "6.2/10"); 42 | assert.deepEqual(data.ratings[1].value, "70%"); 43 | assert.deepEqual(data.boxoffice, "N/A"); 44 | assert.deepEqual(data.dvd, new Date(1997, 10, 10)); 45 | assert.deepEqual(data.production, "Troma"); 46 | }) 47 | ); 48 | }); 49 | 50 | it("makes a successful request by id", () => { 51 | nock("https://www.omdbapi.com") 52 | .get("/?apikey=foo&i=tt0090191&plot=full&r=json") 53 | .replyWithFile(200, path.join(__dirname, "/data/toxic-avenger.json")); 54 | 55 | return assert.isFulfilled( 56 | imdb 57 | .get( 58 | { 59 | id: "tt0090191", 60 | }, 61 | { 62 | apiKey: "foo", 63 | } 64 | ) 65 | .then((data) => { 66 | assert.isOk(data); 67 | assert.deepEqual( 68 | data.title, 69 | "The Toxic Avenger", 70 | "testing returned data" 71 | ); 72 | assert.deepEqual(data.series, false, "testing series bool"); 73 | assert.deepEqual( 74 | Object.prototype.hasOwnProperty.call(data, "episodes"), 75 | false, 76 | "should not have episodes" 77 | ); 78 | assert.deepEqual(data.rating, 6.2, "testing rating conversion"); 79 | }) 80 | ); 81 | }); 82 | 83 | it("makes a successful request with a year", () => { 84 | nock("https://www.omdbapi.com") 85 | .get("/?apikey=foo&plot=full&r=json&t=James%20Bond&y=2015") 86 | .replyWithFile(200, path.join(__dirname, "/data/james-bond.json")); 87 | 88 | return assert.isFulfilled( 89 | imdb 90 | .get( 91 | { 92 | name: "James Bond", 93 | year: 2015, 94 | }, 95 | { 96 | apiKey: "foo", 97 | } 98 | ) 99 | .then((data) => { 100 | assert.isOk(data); 101 | assert.deepEqual(data.title, "James Bond", "testing returned data"); 102 | assert.deepEqual(data.year, 2015, "testing correct year"); 103 | }) 104 | ); 105 | }); 106 | 107 | it("makes a successful request for an episode", () => { 108 | nock("https://www.omdbapi.com") 109 | .get("/?apikey=foo&i=tt0869673&plot=full&r=json") 110 | .replyWithFile(200, path.join(__dirname, "/data/mother-ep.json")); 111 | 112 | return assert.isFulfilled( 113 | imdb 114 | .get( 115 | { 116 | id: "tt0869673", 117 | }, 118 | { 119 | apiKey: "foo", 120 | } 121 | ) 122 | .then((data) => { 123 | assert.isOk(data); 124 | assert.deepEqual( 125 | data.name, 126 | "The Scorpion and the Toad", 127 | "testing returned title" 128 | ); 129 | if (!(data instanceof imdb.Episode)) { 130 | assert.fail("not an episode"); 131 | } else { 132 | assert.equal(data.seriesid, "tt0460649", "testing seriesid"); 133 | assert.deepEqual(data.year, 2006, "testing correct year"); 134 | assert.deepEqual(data.website, undefined); 135 | } 136 | }) 137 | ); 138 | }); 139 | 140 | it("makes a successful request with a short plot", () => { 141 | nock("https://www.omdbapi.com") 142 | .get("/?apikey=foo&plot=short&r=json&t=The%20Toxic%20Avenger") 143 | .replyWithFile(200, path.join(__dirname, "/data/toxic-avenger.json")); 144 | 145 | return assert.isFulfilled( 146 | imdb 147 | .get( 148 | { 149 | name: "The Toxic Avenger", 150 | short_plot: true, 151 | }, 152 | { 153 | apiKey: "foo", 154 | } 155 | ) 156 | .then((data) => { 157 | assert.isOk(data); 158 | assert.deepEqual(data.imdbid, "tt0090191", "testing returned data"); 159 | assert.deepEqual(data.series, false, "testing series bool"); 160 | assert.deepEqual( 161 | Object.prototype.hasOwnProperty.call(data, "episodes"), 162 | false, 163 | "should not have episodes" 164 | ); 165 | }) 166 | ); 167 | }); 168 | 169 | it("times out making a request", () => { 170 | nock("https://www.omdbapi.com") 171 | .get("/?apikey=foo&plot=full&r=json&t=The%20Toxic%20Avenger") 172 | .delay(2000) 173 | .replyWithFile(200, path.join(__dirname, "/data/toxic-avenger.json")); 174 | 175 | return assert.isRejected( 176 | imdb.get( 177 | { 178 | name: "The Toxic Avenger", 179 | }, 180 | { 181 | apiKey: "foo", 182 | timeout: 1000, 183 | } 184 | ), 185 | /Request timed out/ 186 | ); 187 | }); 188 | 189 | it("times out fetching episodes", () => { 190 | nock("https://www.omdbapi.com") 191 | .get("/?apikey=foo&plot=full&r=json&t=How%20I%20Met%20Your%20Mother") 192 | .replyWithFile( 193 | 200, 194 | path.join(__dirname, "/data/how-I-met-your-mother.json") 195 | ) 196 | .get("/?Season=1&apikey=foo&i=tt0460649&r=json") 197 | .delay(2000) 198 | .replyWithFile( 199 | 200, 200 | path.join(__dirname, "/data/how-I-met-your-mother-episodes.json") 201 | ); 202 | 203 | return assert.isRejected( 204 | imdb 205 | .get( 206 | { 207 | name: "How I Met Your Mother", 208 | }, 209 | { 210 | apiKey: "foo", 211 | timeout: 1000, 212 | } 213 | ) 214 | .then((data) => { 215 | if (data instanceof imdb.TVShow) { 216 | return data.episodes(); 217 | } 218 | throw new Error("failure"); 219 | }), 220 | /Request timed out/ 221 | ); 222 | }); 223 | 224 | it("fails to make a request without an api key", () => 225 | assert.isRejected( 226 | imdb.get({ name: "foo" }, {} as imdb.MovieOpts), 227 | /Missing api key/ 228 | )); 229 | 230 | it("makes two calls to episodes", () => { 231 | nock("https://www.omdbapi.com") 232 | .get("/?apikey=foo&plot=full&r=json&t=How%20I%20Met%20Your%20Mother") 233 | .replyWithFile( 234 | 200, 235 | path.join(__dirname, "/data/how-I-met-your-mother.json") 236 | ) 237 | .get("/?Season=1&apikey=foo&i=tt0460649&r=json") 238 | .replyWithFile( 239 | 200, 240 | path.join(__dirname, "/data/how-I-met-your-mother-episodes.json") 241 | ); 242 | 243 | return assert.isFulfilled( 244 | imdb 245 | .get( 246 | { 247 | name: "How I Met Your Mother", 248 | }, 249 | { 250 | apiKey: "foo", 251 | timeout: 1000, 252 | } 253 | ) 254 | .then((data) => { 255 | if (data instanceof imdb.TVShow) { 256 | return data.episodes().then((eps) => data.episodes()); 257 | } 258 | 259 | throw new Error("failure"); 260 | }) 261 | .then((data) => { 262 | assert.isOk(data, "ensure data is defined"); 263 | }) 264 | ); 265 | }); 266 | 267 | it("gets a movie with no reqs", () => 268 | assert.isRejected( 269 | imdb.get({} as imdb.MovieRequest, { 270 | apiKey: "foo", 271 | }), 272 | /Missing one of req.id or req.name/ 273 | )); 274 | 275 | it("gets an unknown type of data", () => { 276 | nock("https://www.omdbapi.com") 277 | .get("/?apikey=foo&plot=full&r=json&t=asdfasdfasdf") 278 | .reply(200, {}); 279 | 280 | return assert.isRejected( 281 | imdb.get( 282 | { 283 | name: "asdfasdfasdf", 284 | }, 285 | { 286 | apiKey: "foo", 287 | } 288 | ), 289 | /Invalid response from server/ 290 | ); 291 | }); 292 | 293 | it("gets an error fetching an episode", () => { 294 | nock("https://www.omdbapi.com") 295 | .get("/?apikey=foo&plot=full&r=json&t=How%20I%20Met%20Your%20Mother") 296 | .replyWithFile( 297 | 200, 298 | path.join(__dirname, "/data/how-I-met-your-mother.json") 299 | ) 300 | .get("/?Season=1&apikey=foo&i=tt0460649&r=json") 301 | .reply(200, { Error: "bad", Response: "False" }); 302 | 303 | return assert.isRejected( 304 | imdb 305 | .get( 306 | { 307 | name: "How I Met Your Mother", 308 | }, 309 | { 310 | apiKey: "foo", 311 | } 312 | ) 313 | .then((data) => { 314 | assert.isOk(data); 315 | assert.instanceOf(data, imdb.TVShow); 316 | 317 | if (data instanceof imdb.TVShow) { 318 | return data.episodes(); 319 | } 320 | throw new Error("failure"); 321 | }), 322 | /bad/ 323 | ); 324 | }); 325 | 326 | it("gets an error from omdb by name", () => { 327 | nock("https://www.omdbapi.com") 328 | .get("/?apikey=foo&plot=full&r=json&t=blah") 329 | .reply(200, { Error: "bad", Response: "False" }); 330 | 331 | return assert.isRejected( 332 | imdb 333 | .get( 334 | { 335 | name: "blah", 336 | }, 337 | { 338 | apiKey: "foo", 339 | } 340 | ) 341 | .then((data) => { 342 | assert.notExists(data, "unreachable"); 343 | }), 344 | /bad/ 345 | ); 346 | }); 347 | 348 | it("gets an error from omdb by id", () => { 349 | nock("https://www.omdbapi.com") 350 | .get("/?apikey=foo&plot=full&r=json&i=tt01") 351 | .reply(200, { Error: "bad", Response: "False" }); 352 | 353 | return assert.isRejected( 354 | imdb.get( 355 | { 356 | id: "tt01", 357 | }, 358 | { 359 | apiKey: "foo", 360 | } 361 | ), 362 | /bad/ 363 | ); 364 | }); 365 | 366 | it("gets an episode when we use a string baseURL", () => { 367 | nock("https://bar.com") 368 | .get("/?apikey=foo&plot=full&r=json&t=How%20I%20Met%20Your%20Mother") 369 | .replyWithFile( 370 | 200, 371 | path.join(__dirname, "/data/how-I-met-your-mother.json") 372 | ) 373 | .get("/?Season=1&apikey=foo&i=tt0460649&r=json") 374 | .replyWithFile( 375 | 200, 376 | path.join(__dirname, "/data/how-I-met-your-mother-episodes.json") 377 | ); 378 | 379 | return assert.eventually.nestedPropertyVal( 380 | imdb 381 | .get( 382 | { 383 | name: "How I Met Your Mother", 384 | }, 385 | { 386 | apiKey: "foo", 387 | baseURL: "https://bar.com/", 388 | } 389 | ) 390 | .then((data) => { 391 | if (data instanceof imdb.TVShow) { 392 | return data.episodes(); 393 | } 394 | throw new Error("failure"); 395 | }), 396 | "[0].title", 397 | "Pilot" 398 | ); 399 | }); 400 | 401 | it("gets an episode when we use a URL baseURL", () => { 402 | nock("https://bar.com") 403 | .get("/?apikey=foo&plot=full&r=json&t=How%20I%20Met%20Your%20Mother") 404 | .replyWithFile( 405 | 200, 406 | path.join(__dirname, "/data/how-I-met-your-mother.json") 407 | ) 408 | .get("/?Season=1&apikey=foo&i=tt0460649&r=json") 409 | .replyWithFile( 410 | 200, 411 | path.join(__dirname, "/data/how-I-met-your-mother-episodes.json") 412 | ); 413 | 414 | return assert.eventually.nestedPropertyVal( 415 | imdb 416 | .get( 417 | { 418 | name: "How I Met Your Mother", 419 | }, 420 | { 421 | apiKey: "foo", 422 | baseURL: new URL("https://bar.com/"), 423 | } 424 | ) 425 | .then((data) => { 426 | if (data instanceof imdb.TVShow) { 427 | return data.episodes(); 428 | } 429 | throw new Error("failure"); 430 | }), 431 | "[0].title", 432 | "Pilot" 433 | ); 434 | }); 435 | }); 436 | -------------------------------------------------------------------------------- /doc/interfaces/_imdb_.movierequest.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | MovieRequest | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 65 |

Interface MovieRequest

66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |

An explicit request for a movie. Does not do searching, this is meant 76 | to specify one movie.

77 |
78 |

One of name or id MUST be requested. year can be used to ensure 79 | that the movie you're looking for is selected in the case that there exists 80 | more than one movie with the same name.

81 |

short_plot can be used to specify whether or not a short or a long plot 82 | description is returned with your movie. Default is to return a full plot.

83 |
84 |
85 |
86 |

Hierarchy

87 |
    88 |
  • 89 | MovieRequest 90 |
  • 91 |
92 |
93 |
94 |

Index

95 |
96 |
97 |
98 |

Properties

99 | 105 |
106 |
107 |
108 |
109 |
110 |

Properties

111 |
112 | 113 |

Optional id

114 |
id: undefined | string
115 | 120 |
121 |
122 |

imdb id of the movie

123 |
124 |
125 |
126 |
127 | 128 |

Optional name

129 |
name: undefined | string
130 | 135 |
136 |
137 |

Name of the movie

138 |
139 |

Unfortunately, only English names are supported 140 | by omdb at the moment.

141 |
142 |
143 |
144 | 145 |

Optional short_plot

146 |
short_plot: undefined | false | true
147 | 152 |
153 |
154 |

Whether or not to request a short plot. Default is full plot.

155 |
156 |
157 |
158 |
159 | 160 |

Optional year

161 |
year: undefined | number
162 | 167 |
168 |
169 |

Year that the movie was released

170 |
171 |
172 |
173 |
174 |
175 | 266 |
267 |
268 |
269 |
270 |

Legend

271 |
272 |
    273 |
  • Function
  • 274 |
  • Type alias
  • 275 |
276 |
    277 |
  • Interface
  • 278 |
  • Property
  • 279 |
280 |
    281 |
  • Class
  • 282 |
283 |
284 |
285 |
286 |
287 |

Generated using TypeDoc

288 |
289 |
290 | 291 | 292 | -------------------------------------------------------------------------------- /doc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | imdb-api 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 27 |
28 |
29 | Options 30 |
31 |
32 | All 33 |
    34 |
  • Public
  • 35 |
  • Public/Protected
  • 36 |
  • All
  • 37 |
38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 |
46 |
47 | Menu 48 |
49 |
50 |
51 |
52 |
53 |
54 | 59 |

imdb-api

60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | 68 |

node-imdb-api

69 |
70 |

A non-scraping, functional node.js interface to imdb

71 | 72 |

Badges

73 |
74 |

NPM version pipeline status Dependency Freshness coverage report Join the chat at https://gitter.im/worr/node-imdb-api

75 |

NOTE ON GITTER: I am online! I use the matrix bridge to talk on Gitter, so you'll see me talking through MatrixBot. Feel free to ask questions!

76 | 77 |

Github / Gitlab

78 |
79 |

Gitlab is the official upstream, and 80 | commits are mirrored to Github. I look 81 | at issues and PRs/MRs on both. Feel free to contribute on either.

82 | 83 |

API Docs

84 |
85 |

API docs are now here

86 | 87 |

Use

88 |
89 |

Import the library using require

90 |
const imdb = require('imdb-api')
91 |

or ES6 import

92 |
import imdb from 'imdb-api'
93 |

Call get to get a single movie

94 |
imdb.get({name: 'The Toxic Avenger'}, {apiKey: 'foo', timeout: 30000}).then(console.log).catch(console.log);
 95 | 
 96 | Movie {
 97 |   title: 'The Toxic Avenger',
 98 |   ...
 99 | }
100 |

Furthermore if you already know the id you can call get with different args:

101 |
imdb.get({id: 'tt0090190'}, {apiKey: 'foo'}).then(console.log);
102 | 
103 | Movie {
104 |   title: 'The Toxic Avenger',
105 |   ...
106 | }
107 |

You can search for movies, and get multiple results by using the search function.

108 |
imdb.search({
109 |   name: 'Toxic Avenger'
110 | }, {
111 |   apiKey: 'foo'
112 | }).then(console.log).catch(console.log);
113 |

TV shows have an episodes method that you can use to fetch all of the episodes 114 | from that TV series.

115 |
imdb.get({name: 'How I Met Your Mother'}, {apiKey: 'foo'}).then((things) => {
116 |     return things.episodes()
117 | }).then((eps) => {
118 |     console.log(eps);
119 | });
120 | 
121 | Episode {
122 |   season: 2,
123 |   name: 'The Scorpion and the Toad',
124 |   released: '2006-10-25T07:00:00.000Z',
125 |   episode: 2,
126 |   rating: '8.3',
127 |   imdbid: 'tt0869673' },
128 | ...
129 | 130 |

Using a Client object

131 |
132 |

imdb-api also exported a Client object that you can use to store options for subsequent requests.

133 |
import imdb = require('imdb');
134 | const cli = new imdb.Client({apiKey: 'xxxxxx'});
135 | cli.get({'name': 'The Toxic Avenger'}).then(console.log);
136 |

Client also has a search method for searching.

137 |
import imdb = require('imdb');
138 | const cli = new imdb.Client({apiKey: 'xxxxxx'});
139 | cli.search({'name': 'The Toxic Avenger'}).then((search) => {
140 |   for (const result of search.results) {
141 |     console.log(result.title);
142 |   }
143 | });
144 | 145 |

FAQ

146 |
147 | 148 |

I see an API key in your examples? Is it required? How do I get one?

149 |
150 |

Yes, it is required! omdb made this a requirement as of May 8, 2017. This is unfortunate, 151 | but totally understandable. While I plan on working on finding an alternative to provide 152 | the movie info you crave, I've enabled you to pass in an apikey.

153 |

You can get one by going here.

154 | 155 |

Why? There are like 3 other interfaces to imdb in npm

156 |
157 |

Most of them scrape imdb. imdb explicitly forbids scraping.

158 |

And what happens when the site layout changes? Well then your screen scraping 159 | solution fails in interesting ways. Screen scraping is also pretty slow, 160 | and we can't have that.

161 | 162 |

WOAH I looked at your code and you're using unofficial APIs!

163 |
164 |

There isn't an official API to imdb. As soon as one is released (and I 165 | notice), I'll update the module.

166 |

imdb DOES release all of their data in text files nightly, so unofficial sites 167 | have popped up providing RESTful APIs against that data.

168 |

I have to use a few, since none of them are complete.

169 | 170 |

What if one of the unofficial APIs disappears?

171 |
172 |

File a bug. I'll get creative.

173 |
174 |
175 | 200 |
201 |
202 |
203 |
204 |

Legend

205 |
206 |
    207 |
  • Function
  • 208 |
  • Type alias
  • 209 |
210 |
    211 |
  • Interface
  • 212 |
213 |
    214 |
  • Class
  • 215 |
216 |
217 |
218 |
219 |
220 |

Generated using TypeDoc

221 |
222 |
223 | 224 | 225 | --------------------------------------------------------------------------------