├── .eslintignore ├── .eslintrc ├── .github └── workflows │ └── node.js.yml ├── .gitignore ├── .jsdoc.json ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── docs ├── Client.html ├── index.html ├── scripts │ └── prism.min.js └── styles │ ├── jsdoc-default.css │ └── prism.css ├── index.d.ts ├── index.js ├── package-lock.json ├── package.json └── test ├── Client.js ├── episodeByAirDate.js ├── getActorsForSeries.js ├── getEpisodesBySeriesId.js ├── getEpisodesSummaryBySeriesId.js ├── getLanguages.js ├── getSeasonPosters.js ├── getSeriesAllById.js ├── getSeriesBanner.js ├── getSeriesById.js ├── getSeriesByImdbId.js ├── getSeriesByName.js ├── getSeriesByZap2ItId.js ├── getSeriesImages.js ├── getSeriesPosters.js ├── getUpdates.js ├── language.js └── mocha.opts /.eslintignore: -------------------------------------------------------------------------------- 1 | docs 2 | node_modules 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "node": true, 4 | "es6": true, 5 | "mocha": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "plugins": [ 9 | "mocha" 10 | ], 11 | "rules": { 12 | "array-bracket-spacing": ["error", "never"], 13 | "brace-style": "error", 14 | "callback-return": "error", 15 | "comma-spacing": "error", 16 | "comma-style": "error", 17 | "consistent-return": "error", 18 | "curly": "error", 19 | "eol-last": "error", 20 | "eqeqeq": ["error", "smart"], 21 | "func-style": ["error", "declaration"], 22 | "global-require": "error", 23 | "guard-for-in": "error", 24 | "indent": ["error", 4, { "MemberExpression": "off" }], 25 | "new-cap": "error", 26 | "new-parens": "error", 27 | "no-else-return": "error", 28 | "no-eval": "error", 29 | "no-extend-native": "error", 30 | "no-floating-decimal": "error", 31 | "no-global-assign": "error", 32 | "no-implicit-coercion": ["error", {"boolean": false}], 33 | "no-implicit-globals": "error", 34 | "no-implied-eval": "error", 35 | "no-invalid-this": "error", 36 | "no-loop-func": "error", 37 | "no-nested-ternary": "error", 38 | "no-self-compare": "error", 39 | "no-sequences": "error", 40 | "no-trailing-spaces": "error", 41 | "no-var": "error", 42 | "no-with": "error", 43 | "radix": "error", 44 | "semi": "error", 45 | "strict": ["error", "global"], 46 | 47 | "mocha/handle-done-callback": "error", 48 | "mocha/no-exclusive-tests": "error", 49 | "mocha/no-global-tests": "error", 50 | "mocha/no-pending-tests": "error", 51 | "mocha/no-skipped-tests": "warn", 52 | "mocha/no-synchronous-tests": "error" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | jobs: 13 | test: 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | matrix: 18 | node-version: [14.x, 15.x, 16.x] 19 | 20 | steps: 21 | - uses: actions/checkout@v2 22 | 23 | - name: Use Node.js ${{ matrix.node-version }} 24 | uses: actions/setup-node@v2 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | cache: 'npm' 28 | 29 | - run: npm ci 30 | - run: npm run build --if-present 31 | 32 | - run: npm test 33 | env: 34 | TVDB_KEY: ${{ secrets.TVDB_KEY }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | logs 4 | *.log 5 | pids 6 | *.pid 7 | *.seed 8 | lib-cov 9 | coverage 10 | .grunt 11 | .idea 12 | _builds 13 | _projects 14 | _steps 15 | -------------------------------------------------------------------------------- /.jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "include": [ 4 | "index.js", 5 | "README.md" 6 | ] 7 | }, 8 | "templates": { 9 | "default": { 10 | "outputSourceFiles": false, 11 | "useLongnameInNav": true 12 | } 13 | }, 14 | "plugins": [ 15 | "plugins/markdown" 16 | ], 17 | "markdown": { 18 | "tags": [ "description" ] 19 | }, 20 | "opts": { 21 | "destination": "./docs", 22 | "encoding": "utf8", 23 | "template": "./node_modules/@edwellbrook/minami" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at edwellbrook@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2017 Edward Wellbrook 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-tvdb 2 | 3 | [![Build Status](https://travis-ci.org/edwellbrook/node-tvdb.svg?branch=master)](https://travis-ci.org/edwellbrook/node-tvdb) 4 | [![npm Downloads](https://img.shields.io/npm/dm/node-tvdb.svg?style=flat)](https://www.npmjs.com/package/node-tvdb) 5 | 6 | Node.js library for accessing [TheTVDB JSON API](https://api.thetvdb.com/swagger). Originally based on [joaocampinhos/thetvdb-api](https://github.com/joaocampinhos/thetvdb-api) to give nicer output and additional features. 7 | 8 | Pull requests are always very welcome. 9 | 10 | ## Features 11 | 12 | - Handle errors from API as JavaScript errors 13 | - Only returns relevant data (no need to call response.Data.Series etc.) 14 | - Set language at initialisation or on each function call 15 | - Return values through promises (dropped callback support) 16 | - Uses the new JSON API from TheTVDB 17 | - [Tests with Mocha and Travis CI](https://travis-ci.org/edwellbrook/node-tvdb) 18 | 19 | ## Installation 20 | 21 | Install with [npm](https://npmjs.org/): 22 | 23 | ``` shell 24 | npm install --save node-tvdb 25 | ``` 26 | 27 | And run tests with [Mocha](https://mochajs.org): 28 | 29 | ``` shell 30 | TVDB_KEY=[YOUR API KEY HERE] npm test 31 | ``` 32 | 33 | > _Mocha is installed as a development dependency; you do not need to install it globally to run the tests._ 34 | 35 | ## Example Usage 36 | 37 | To start using this library you first need an API key. You can request one [here](http://thetvdb.com/?tab=apiregister). Then just follow this simple example that fetches all the shows containing "The Simpsons" in the name. 38 | 39 | ``` javascript 40 | const TVDB = require('node-tvdb'); 41 | const tvdb = new TVDB('ABC123'); 42 | 43 | tvdb.getSeriesByName('The Simpsons') 44 | .then(response => { /* process data */ }) 45 | .catch(error => { /* handle error */ }); 46 | ``` 47 | 48 | ## Full API Docs 49 | 50 | Generated API docs with code examples can be found at: [edwellbrook.github.io/node-tvdb](https://edwellbrook.github.io/node-tvdb/). 51 | 52 | For details on response data, please see [TheTVDB API docs](https://api.thetvdb.com/swagger). 53 | 54 | ## License 55 | 56 | The MIT License (MIT) 57 | -------------------------------------------------------------------------------- /docs/Client.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Client - Documentation 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 103 | 104 |
105 | 106 |

Client

107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |
115 | 116 |
117 | 118 |

119 | Client 120 |

121 | 122 | 123 |
124 | 125 |
126 |
127 | 128 | 129 | 130 | 131 | 132 |

new Client(apiKey, [language])

133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 |
Parameters:
147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 184 | 185 | 186 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 215 | 216 | 217 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 |
NameTypeAttributesDescription
apiKey 177 | 178 | 179 | String 180 | 181 | 182 | 183 | 187 | 188 | 189 | 190 | 191 | 192 |
language 208 | 209 | 210 | String 211 | 212 | 213 | 214 | 218 | 219 | <optional>
220 | 221 | 222 | 223 | 224 | 225 |
236 | 237 | 238 | 239 | 240 | 241 | 242 |
243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 |
276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 |
294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 |

Methods

309 | 310 |
311 | 312 |
313 | 314 | 315 | 316 | 317 |

getActors(seriesId, [opts]) → {Promise}

318 | 319 | 320 | 321 | 322 | 323 |
324 |

Get series actors by series id.

325 |
tvdb.getActors(73255)
 326 |     .then(response => { handle response })
 327 |     .catch(error => { handle error });
 328 | 
329 |
330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 |
Parameters:
340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 380 | 381 | 382 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 411 | 412 | 413 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 |
NameTypeAttributesDescription
seriesId 370 | 371 | 372 | Number 373 | | 374 | 375 | String 376 | 377 | 378 | 379 | 383 | 384 | 385 | 386 | 387 | 388 |
opts 404 | 405 | 406 | Object 407 | 408 | 409 | 410 | 414 | 415 | <optional>
416 | 417 | 418 | 419 | 420 | 421 |

additional options for request

432 | 433 | 434 | 435 | 436 | 437 | 438 |
439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 |
See:
470 |
471 | 474 |
475 | 476 | 477 | 478 |
479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 |
496 | 497 |
498 | 499 | 500 | 501 | 502 |

getEpisodeById(episodeId, [opts]) → {Promise}

503 | 504 | 505 | 506 | 507 | 508 |
509 |

Get episode by episode id.

510 |
tvdb.getEpisodeById(4768125)
 511 |     .then(response => { handle response })
 512 |     .catch(error => { handle error });
 513 | 
514 |
515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 |
Parameters:
525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 565 | 566 | 567 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 596 | 597 | 598 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 |
NameTypeAttributesDescription
episodeId 555 | 556 | 557 | Number 558 | | 559 | 560 | String 561 | 562 | 563 | 564 | 568 | 569 | 570 | 571 | 572 | 573 |
opts 589 | 590 | 591 | Object 592 | 593 | 594 | 595 | 599 | 600 | <optional>
601 | 602 | 603 | 604 | 605 | 606 |

additional options for request

617 | 618 | 619 | 620 | 621 | 622 | 623 |
624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 |
See:
655 |
656 | 659 |
660 | 661 | 662 | 663 |
664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 |
681 | 682 |
683 | 684 | 685 | 686 | 687 |

getEpisodesByAirDate(seriesId, airDate, [opts]) → {Promise}

688 | 689 | 690 | 691 | 692 | 693 |
694 |

Get series episode by air date.

695 |
tvdb.getEpisodeByAirDate(153021, '2011-10-03')
 696 |     .then(response => { handle response })
 697 |     .catch(error => { handle error });
 698 | 
699 |
700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 |
Parameters:
710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 750 | 751 | 752 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 781 | 782 | 783 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 812 | 813 | 814 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 |
NameTypeAttributesDescription
seriesId 740 | 741 | 742 | Number 743 | | 744 | 745 | String 746 | 747 | 748 | 749 | 753 | 754 | 755 | 756 | 757 | 758 |
airDate 774 | 775 | 776 | String 777 | 778 | 779 | 780 | 784 | 785 | 786 | 787 | 788 | 789 |
opts 805 | 806 | 807 | Object 808 | 809 | 810 | 811 | 815 | 816 | <optional>
817 | 818 | 819 | 820 | 821 | 822 |

additional options for request

833 | 834 | 835 | 836 | 837 | 838 | 839 |
840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 |
See:
871 |
872 | 875 |
876 | 877 | 878 | 879 |
880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 |
897 | 898 |
899 | 900 | 901 | 902 | 903 |

getEpisodesBySeriesId(seriesId, [opts]) → {Promise}

904 | 905 | 906 | 907 | 908 | 909 |
910 |

Get all episodes by series id.

911 |

The opts may include the object query with any of the parameters from the query endpoint

912 |
tvdb.getEpisodesBySeriesId(153021)
 913 |     .then(response => { handle response })
 914 |     .catch(error => { handle error });
 915 | 
916 |
917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 |
Parameters:
927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 967 | 968 | 969 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 998 | 999 | 1000 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 |
NameTypeAttributesDescription
seriesId 957 | 958 | 959 | Number 960 | | 961 | 962 | String 963 | 964 | 965 | 966 | 970 | 971 | 972 | 973 | 974 | 975 |
opts 991 | 992 | 993 | Object 994 | 995 | 996 | 997 | 1001 | 1002 | <optional>
1003 | 1004 | 1005 | 1006 | 1007 | 1008 |

additional options for request

1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 |
1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 |
See:
1057 |
1058 | 1063 |
1064 | 1065 | 1066 | 1067 |
1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 |
1085 | 1086 |
1087 | 1088 | 1089 | 1090 | 1091 |

getEpisodesSummaryBySeriesId(seriesId) → {Promise}

1092 | 1093 | 1094 | 1095 | 1096 | 1097 |
1098 |

Get episodes summary by series id.

1099 |
tvdb.getEpisodesSummaryBySeriesId(153021)
1100 |     .then(response => { handle response })
1101 |     .catch(error => { handle error });
1102 | 
1103 |
1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 |
Parameters:
1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 |
NameTypeDescription
seriesId 1142 | 1143 | 1144 | Number 1145 | | 1146 | 1147 | String 1148 | 1149 | 1150 | 1151 |
1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 |
1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 |
See:
1201 |
1202 | 1205 |
1206 | 1207 | 1208 | 1209 |
1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 |
1227 | 1228 |
1229 | 1230 | 1231 | 1232 | 1233 |

getLanguages([opts]) → {Promise}

1234 | 1235 | 1236 | 1237 | 1238 | 1239 |
1240 |

Get available languages useable by TheTVDB API.

1241 |
tvdb.getLanguages()
1242 |     .then(response => { handle response })
1243 |     .catch(error => { handle error });
1244 | 
1245 |
1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 |
Parameters:
1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | 1273 | 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1285 | 1293 | 1294 | 1295 | 1304 | 1305 | 1306 | 1307 | 1308 | 1309 | 1310 | 1311 | 1312 | 1313 |
NameTypeAttributesDescription
opts 1286 | 1287 | 1288 | Object 1289 | 1290 | 1291 | 1292 | 1296 | 1297 | <optional>
1298 | 1299 | 1300 | 1301 | 1302 | 1303 |

additional options for request

1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 |
1321 | 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | 1347 | 1348 | 1349 | 1350 | 1351 |
See:
1352 |
1353 | 1356 |
1357 | 1358 | 1359 | 1360 |
1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1372 | 1373 | 1374 | 1375 | 1376 | 1377 |
1378 | 1379 |
1380 | 1381 | 1382 | 1383 | 1384 |

getSeasonPosters(seriesId, season, [opts]) → {Promise}

1385 | 1386 | 1387 | 1388 | 1389 | 1390 |
1391 |

Convenience wrapper around getSeriesImages to only return season poster images for a series.

1392 |
tvdb.getSeasonPosters(73255, 1)
1393 |     .then(response => { handle response })
1394 |     .catch(error => { handle error });
1395 | 
1396 |
1397 | 1398 | 1399 | 1400 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 |
Parameters:
1407 | 1408 | 1409 | 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1419 | 1420 | 1421 | 1422 | 1423 | 1424 | 1425 | 1426 | 1427 | 1428 | 1429 | 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | 1436 | 1447 | 1448 | 1449 | 1456 | 1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1481 | 1482 | 1483 | 1490 | 1491 | 1492 | 1493 | 1494 | 1495 | 1496 | 1497 | 1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 1504 | 1512 | 1513 | 1514 | 1523 | 1524 | 1525 | 1526 | 1527 | 1528 | 1529 | 1530 | 1531 | 1532 |
NameTypeAttributesDescription
seriesId 1437 | 1438 | 1439 | Number 1440 | | 1441 | 1442 | String 1443 | 1444 | 1445 | 1446 | 1450 | 1451 | 1452 | 1453 | 1454 | 1455 |
season 1471 | 1472 | 1473 | Number 1474 | | 1475 | 1476 | String 1477 | 1478 | 1479 | 1480 | 1484 | 1485 | 1486 | 1487 | 1488 | 1489 |
opts 1505 | 1506 | 1507 | Object 1508 | 1509 | 1510 | 1511 | 1515 | 1516 | <optional>
1517 | 1518 | 1519 | 1520 | 1521 | 1522 |

additional options for request

1533 | 1534 | 1535 | 1536 | 1537 | 1538 | 1539 |
1540 | 1541 | 1542 | 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | 1550 | 1551 | 1552 | 1553 | 1554 | 1555 | 1556 | 1557 | 1558 | 1559 | 1560 | 1561 | 1562 | 1563 | 1564 | 1565 | 1566 | 1567 | 1568 | 1569 | 1570 |
See:
1571 |
1572 | 1575 |
1576 | 1577 | 1578 | 1579 |
1580 | 1581 | 1582 | 1583 | 1584 | 1585 | 1586 | 1587 | 1588 | 1589 | 1590 | 1591 | 1592 | 1593 | 1594 | 1595 | 1596 |
1597 | 1598 |
1599 | 1600 | 1601 | 1602 | 1603 |

getSeriesAllById(seriesId, [opts]) → {Promise}

1604 | 1605 | 1606 | 1607 | 1608 | 1609 |
1610 |

Get series and episode information by series id. Helper for calling 1611 | getSeriesById and getEpisodesBySeriesId at the same time.

1612 |
tvdb.getSeriesAllById(73255)
1613 |     .then(response => {
1614 |         response; // contains series data (i.e. `id`, `seriesName`)
1615 |         response.episodes; // contains an array of episodes
1616 |     })
1617 |     .catch(error => { handle error });
1618 | 
1619 |
1620 | 1621 | 1622 | 1623 | 1624 | 1625 | 1626 | 1627 | 1628 | 1629 |
Parameters:
1630 | 1631 | 1632 | 1633 | 1634 | 1635 | 1636 | 1637 | 1638 | 1639 | 1640 | 1641 | 1642 | 1643 | 1644 | 1645 | 1646 | 1647 | 1648 | 1649 | 1650 | 1651 | 1652 | 1653 | 1654 | 1655 | 1656 | 1657 | 1658 | 1659 | 1670 | 1671 | 1672 | 1679 | 1680 | 1681 | 1682 | 1683 | 1684 | 1685 | 1686 | 1687 | 1688 | 1689 | 1690 | 1691 | 1692 | 1693 | 1701 | 1702 | 1703 | 1712 | 1713 | 1714 | 1715 | 1716 | 1717 | 1718 | 1719 | 1720 | 1721 |
NameTypeAttributesDescription
seriesId 1660 | 1661 | 1662 | Number 1663 | | 1664 | 1665 | String 1666 | 1667 | 1668 | 1669 | 1673 | 1674 | 1675 | 1676 | 1677 | 1678 |
opts 1694 | 1695 | 1696 | Object 1697 | 1698 | 1699 | 1700 | 1704 | 1705 | <optional>
1706 | 1707 | 1708 | 1709 | 1710 | 1711 |

additional options for request

1722 | 1723 | 1724 | 1725 | 1726 | 1727 | 1728 |
1729 | 1730 | 1731 | 1732 | 1733 | 1734 | 1735 | 1736 | 1737 | 1738 | 1739 | 1740 | 1741 | 1742 | 1743 | 1744 | 1745 | 1746 | 1747 | 1748 | 1749 | 1750 | 1751 | 1752 | 1753 | 1754 | 1755 | 1756 | 1757 | 1758 | 1759 | 1760 | 1761 |
1762 | 1763 | 1764 | 1765 | 1766 | 1767 | 1768 | 1769 | 1770 | 1771 | 1772 | 1773 | 1774 | 1775 | 1776 | 1777 | 1778 |
1779 | 1780 |
1781 | 1782 | 1783 | 1784 | 1785 |

getSeriesBanner(seriesId, [opts]) → {Promise}

1786 | 1787 | 1788 | 1789 | 1790 | 1791 |
1792 |

Get series banner by series id.

1793 |
tvdb.getSeriesBanner(73255)
1794 |     .then(response => { handle response })
1795 |     .catch(error => { handle error });
1796 | 
1797 |
1798 | 1799 | 1800 | 1801 | 1802 | 1803 | 1804 | 1805 | 1806 | 1807 |
Parameters:
1808 | 1809 | 1810 | 1811 | 1812 | 1813 | 1814 | 1815 | 1816 | 1817 | 1818 | 1819 | 1820 | 1821 | 1822 | 1823 | 1824 | 1825 | 1826 | 1827 | 1828 | 1829 | 1830 | 1831 | 1832 | 1833 | 1834 | 1835 | 1836 | 1837 | 1848 | 1849 | 1850 | 1857 | 1858 | 1859 | 1860 | 1861 | 1862 | 1863 | 1864 | 1865 | 1866 | 1867 | 1868 | 1869 | 1870 | 1871 | 1879 | 1880 | 1881 | 1890 | 1891 | 1892 | 1893 | 1894 | 1895 | 1896 | 1897 | 1898 | 1899 |
NameTypeAttributesDescription
seriesId 1838 | 1839 | 1840 | Number 1841 | | 1842 | 1843 | String 1844 | 1845 | 1846 | 1847 | 1851 | 1852 | 1853 | 1854 | 1855 | 1856 |
opts 1872 | 1873 | 1874 | Object 1875 | 1876 | 1877 | 1878 | 1882 | 1883 | <optional>
1884 | 1885 | 1886 | 1887 | 1888 | 1889 |

additional options for request

1900 | 1901 | 1902 | 1903 | 1904 | 1905 | 1906 |
1907 | 1908 | 1909 | 1910 | 1911 | 1912 | 1913 | 1914 | 1915 | 1916 | 1917 | 1918 | 1919 | 1920 | 1921 | 1922 | 1923 | 1924 | 1925 | 1926 | 1927 | 1928 | 1929 | 1930 | 1931 | 1932 | 1933 | 1934 | 1935 | 1936 | 1937 |
See:
1938 |
1939 | 1942 |
1943 | 1944 | 1945 | 1946 |
1947 | 1948 | 1949 | 1950 | 1951 | 1952 | 1953 | 1954 | 1955 | 1956 | 1957 | 1958 | 1959 | 1960 | 1961 | 1962 | 1963 |
1964 | 1965 |
1966 | 1967 | 1968 | 1969 | 1970 |

getSeriesById(seriesId, [opts]) → {Promise}

1971 | 1972 | 1973 | 1974 | 1975 | 1976 |
1977 |

Get basic series information by id.

1978 |
tvdb.getSeriesById(73255)
1979 |     .then(response => { handle response })
1980 |     .catch(error => { handle error });
1981 | 
1982 |
1983 | 1984 | 1985 | 1986 | 1987 | 1988 | 1989 | 1990 | 1991 | 1992 |
Parameters:
1993 | 1994 | 1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 | 2014 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2033 | 2034 | 2035 | 2042 | 2043 | 2044 | 2045 | 2046 | 2047 | 2048 | 2049 | 2050 | 2051 | 2052 | 2053 | 2054 | 2055 | 2056 | 2064 | 2065 | 2066 | 2075 | 2076 | 2077 | 2078 | 2079 | 2080 | 2081 | 2082 | 2083 | 2084 |
NameTypeAttributesDescription
seriesId 2023 | 2024 | 2025 | Number 2026 | | 2027 | 2028 | String 2029 | 2030 | 2031 | 2032 | 2036 | 2037 | 2038 | 2039 | 2040 | 2041 |
opts 2057 | 2058 | 2059 | Object 2060 | 2061 | 2062 | 2063 | 2067 | 2068 | <optional>
2069 | 2070 | 2071 | 2072 | 2073 | 2074 |

additional options for request

2085 | 2086 | 2087 | 2088 | 2089 | 2090 | 2091 |
2092 | 2093 | 2094 | 2095 | 2096 | 2097 | 2098 | 2099 | 2100 | 2101 | 2102 | 2103 | 2104 | 2105 | 2106 | 2107 | 2108 | 2109 | 2110 | 2111 | 2112 | 2113 | 2114 | 2115 | 2116 | 2117 | 2118 | 2119 | 2120 | 2121 | 2122 |
See:
2123 |
2124 | 2127 |
2128 | 2129 | 2130 | 2131 |
2132 | 2133 | 2134 | 2135 | 2136 | 2137 | 2138 | 2139 | 2140 | 2141 | 2142 | 2143 | 2144 | 2145 | 2146 | 2147 | 2148 |
2149 | 2150 |
2151 | 2152 | 2153 | 2154 | 2155 |

getSeriesByImdbId(imdbId, [opts]) → {Promise}

2156 | 2157 | 2158 | 2159 | 2160 | 2161 |
2162 |

Get basic series information by imdb id.

2163 |
tvdb.getSeriesByImdbId('tt0903747')
2164 |     .then(response => { handle response })
2165 |     .catch(error => { handle error });
2166 | 
2167 |
2168 | 2169 | 2170 | 2171 | 2172 | 2173 | 2174 | 2175 | 2176 | 2177 |
Parameters:
2178 | 2179 | 2180 | 2181 | 2182 | 2183 | 2184 | 2185 | 2186 | 2187 | 2188 | 2189 | 2190 | 2191 | 2192 | 2193 | 2194 | 2195 | 2196 | 2197 | 2198 | 2199 | 2200 | 2201 | 2202 | 2203 | 2204 | 2205 | 2206 | 2207 | 2215 | 2216 | 2217 | 2224 | 2225 | 2226 | 2227 | 2228 | 2229 | 2230 | 2231 | 2232 | 2233 | 2234 | 2235 | 2236 | 2237 | 2238 | 2246 | 2247 | 2248 | 2257 | 2258 | 2259 | 2260 | 2261 | 2262 | 2263 | 2264 | 2265 | 2266 |
NameTypeAttributesDescription
imdbId 2208 | 2209 | 2210 | String 2211 | 2212 | 2213 | 2214 | 2218 | 2219 | 2220 | 2221 | 2222 | 2223 |
opts 2239 | 2240 | 2241 | Object 2242 | 2243 | 2244 | 2245 | 2249 | 2250 | <optional>
2251 | 2252 | 2253 | 2254 | 2255 | 2256 |

additional options for request

2267 | 2268 | 2269 | 2270 | 2271 | 2272 | 2273 |
2274 | 2275 | 2276 | 2277 | 2278 | 2279 | 2280 | 2281 | 2282 | 2283 | 2284 | 2285 | 2286 | 2287 | 2288 | 2289 | 2290 | 2291 | 2292 | 2293 | 2294 | 2295 | 2296 | 2297 | 2298 | 2299 | 2300 | 2301 | 2302 | 2303 | 2304 |
See:
2305 |
2306 | 2309 |
2310 | 2311 | 2312 | 2313 |
2314 | 2315 | 2316 | 2317 | 2318 | 2319 | 2320 | 2321 | 2322 | 2323 | 2324 | 2325 | 2326 | 2327 | 2328 | 2329 | 2330 |
2331 | 2332 |
2333 | 2334 | 2335 | 2336 | 2337 |

getSeriesByName(name, [opts]) → {Promise}

2338 | 2339 | 2340 | 2341 | 2342 | 2343 |
2344 |

Get basic series information by name.

2345 |
tvdb.getSeriesByName('Breaking Bad')
2346 |     .then(response => { handle response })
2347 |     .catch(error => { handle error });
2348 | 
2349 |
2350 | 2351 | 2352 | 2353 | 2354 | 2355 | 2356 | 2357 | 2358 | 2359 |
Parameters:
2360 | 2361 | 2362 | 2363 | 2364 | 2365 | 2366 | 2367 | 2368 | 2369 | 2370 | 2371 | 2372 | 2373 | 2374 | 2375 | 2376 | 2377 | 2378 | 2379 | 2380 | 2381 | 2382 | 2383 | 2384 | 2385 | 2386 | 2387 | 2388 | 2389 | 2397 | 2398 | 2399 | 2406 | 2407 | 2408 | 2409 | 2410 | 2411 | 2412 | 2413 | 2414 | 2415 | 2416 | 2417 | 2418 | 2419 | 2420 | 2428 | 2429 | 2430 | 2439 | 2440 | 2441 | 2442 | 2443 | 2444 | 2445 | 2446 | 2447 | 2448 |
NameTypeAttributesDescription
name 2390 | 2391 | 2392 | String 2393 | 2394 | 2395 | 2396 | 2400 | 2401 | 2402 | 2403 | 2404 | 2405 |
opts 2421 | 2422 | 2423 | Object 2424 | 2425 | 2426 | 2427 | 2431 | 2432 | <optional>
2433 | 2434 | 2435 | 2436 | 2437 | 2438 |

additional options for request

2449 | 2450 | 2451 | 2452 | 2453 | 2454 | 2455 |
2456 | 2457 | 2458 | 2459 | 2460 | 2461 | 2462 | 2463 | 2464 | 2465 | 2466 | 2467 | 2468 | 2469 | 2470 | 2471 | 2472 | 2473 | 2474 | 2475 | 2476 | 2477 | 2478 | 2479 | 2480 | 2481 | 2482 | 2483 | 2484 | 2485 | 2486 |
See:
2487 |
2488 | 2491 |
2492 | 2493 | 2494 | 2495 |
2496 | 2497 | 2498 | 2499 | 2500 | 2501 | 2502 | 2503 | 2504 | 2505 | 2506 | 2507 | 2508 | 2509 | 2510 | 2511 | 2512 |
2513 | 2514 |
2515 | 2516 | 2517 | 2518 | 2519 |

getSeriesByZap2ItId(zap2ItId, [opts]) → {Promise}

2520 | 2521 | 2522 | 2523 | 2524 | 2525 |
2526 |

Get basic series information by zap2it id.

2527 |
tvdb.getSeriesByZap2ItId('EP00018693')
2528 |     .then(response => { handle response })
2529 |     .catch(error => { handle error });
2530 | 
2531 |
2532 | 2533 | 2534 | 2535 | 2536 | 2537 | 2538 | 2539 | 2540 | 2541 |
Parameters:
2542 | 2543 | 2544 | 2545 | 2546 | 2547 | 2548 | 2549 | 2550 | 2551 | 2552 | 2553 | 2554 | 2555 | 2556 | 2557 | 2558 | 2559 | 2560 | 2561 | 2562 | 2563 | 2564 | 2565 | 2566 | 2567 | 2568 | 2569 | 2570 | 2571 | 2579 | 2580 | 2581 | 2588 | 2589 | 2590 | 2591 | 2592 | 2593 | 2594 | 2595 | 2596 | 2597 | 2598 | 2599 | 2600 | 2601 | 2602 | 2610 | 2611 | 2612 | 2621 | 2622 | 2623 | 2624 | 2625 | 2626 | 2627 | 2628 | 2629 | 2630 |
NameTypeAttributesDescription
zap2ItId 2572 | 2573 | 2574 | String 2575 | 2576 | 2577 | 2578 | 2582 | 2583 | 2584 | 2585 | 2586 | 2587 |
opts 2603 | 2604 | 2605 | Object 2606 | 2607 | 2608 | 2609 | 2613 | 2614 | <optional>
2615 | 2616 | 2617 | 2618 | 2619 | 2620 |

additional options for request

2631 | 2632 | 2633 | 2634 | 2635 | 2636 | 2637 |
2638 | 2639 | 2640 | 2641 | 2642 | 2643 | 2644 | 2645 | 2646 | 2647 | 2648 | 2649 | 2650 | 2651 | 2652 | 2653 | 2654 | 2655 | 2656 | 2657 | 2658 | 2659 | 2660 | 2661 | 2662 | 2663 | 2664 | 2665 | 2666 | 2667 | 2668 |
See:
2669 |
2670 | 2673 |
2674 | 2675 | 2676 | 2677 |
2678 | 2679 | 2680 | 2681 | 2682 | 2683 | 2684 | 2685 | 2686 | 2687 | 2688 | 2689 | 2690 | 2691 | 2692 | 2693 | 2694 |
2695 | 2696 |
2697 | 2698 | 2699 | 2700 | 2701 |

getSeriesImages(seriesId, keyType, [opts]) → {Promise}

2702 | 2703 | 2704 | 2705 | 2706 | 2707 |
2708 |

Get series images for a given key type.

2709 |
// request only return fan art images:
2710 | tvdb.getSeriesImages(73255, 'fanart', { query: queryOptions })
2711 |     .then(response => { handle response })
2712 |     .catch(error => { handle error });
2713 | 
2714 |
2715 | 2716 | 2717 | 2718 | 2719 | 2720 | 2721 | 2722 | 2723 | 2724 |
Parameters:
2725 | 2726 | 2727 | 2728 | 2729 | 2730 | 2731 | 2732 | 2733 | 2734 | 2735 | 2736 | 2737 | 2738 | 2739 | 2740 | 2741 | 2742 | 2743 | 2744 | 2745 | 2746 | 2747 | 2748 | 2749 | 2750 | 2751 | 2752 | 2753 | 2754 | 2765 | 2766 | 2767 | 2774 | 2775 | 2776 | 2777 | 2778 | 2779 | 2780 | 2781 | 2782 | 2783 | 2784 | 2785 | 2786 | 2787 | 2788 | 2796 | 2797 | 2798 | 2805 | 2806 | 2807 | 2808 | 2809 | 2810 | 2811 | 2812 | 2813 | 2814 | 2815 | 2816 | 2817 | 2818 | 2819 | 2827 | 2828 | 2829 | 2838 | 2839 | 2840 | 2841 | 2842 | 2843 | 2844 | 2845 | 2846 | 2847 |
NameTypeAttributesDescription
seriesId 2755 | 2756 | 2757 | Number 2758 | | 2759 | 2760 | String 2761 | 2762 | 2763 | 2764 | 2768 | 2769 | 2770 | 2771 | 2772 | 2773 |
keyType 2789 | 2790 | 2791 | String 2792 | 2793 | 2794 | 2795 | 2799 | 2800 | 2801 | 2802 | 2803 | 2804 |

the key type to query by

opts 2820 | 2821 | 2822 | Object 2823 | 2824 | 2825 | 2826 | 2830 | 2831 | <optional>
2832 | 2833 | 2834 | 2835 | 2836 | 2837 |

additional options for request

2848 | 2849 | 2850 | 2851 | 2852 | 2853 | 2854 |
2855 | 2856 | 2857 | 2858 | 2859 | 2860 | 2861 | 2862 | 2863 | 2864 | 2865 | 2866 | 2867 | 2868 | 2869 | 2870 | 2871 | 2872 | 2873 | 2874 | 2875 | 2876 | 2877 | 2878 | 2879 | 2880 | 2881 | 2882 | 2883 | 2884 | 2885 |
See:
2886 |
2887 | 2892 |
2893 | 2894 | 2895 | 2896 |
2897 | 2898 | 2899 | 2900 | 2901 | 2902 | 2903 | 2904 | 2905 | 2906 | 2907 | 2908 | 2909 | 2910 | 2911 | 2912 | 2913 |
2914 | 2915 |
2916 | 2917 | 2918 | 2919 | 2920 |

getSeriesPosters(seriesId, [opts]) → {Promise}

2921 | 2922 | 2923 | 2924 | 2925 | 2926 |
2927 |

Convenience wrapper around getSeriesImages to only return poster images for a series.

2928 |
tvdb.getSeriesPosters(73255)
2929 |     .then(response => { handle response })
2930 |     .catch(error => { handle error });
2931 | 
2932 |
2933 | 2934 | 2935 | 2936 | 2937 | 2938 | 2939 | 2940 | 2941 | 2942 |
Parameters:
2943 | 2944 | 2945 | 2946 | 2947 | 2948 | 2949 | 2950 | 2951 | 2952 | 2953 | 2954 | 2955 | 2956 | 2957 | 2958 | 2959 | 2960 | 2961 | 2962 | 2963 | 2964 | 2965 | 2966 | 2967 | 2968 | 2969 | 2970 | 2971 | 2972 | 2983 | 2984 | 2985 | 2992 | 2993 | 2994 | 2995 | 2996 | 2997 | 2998 | 2999 | 3000 | 3001 | 3002 | 3003 | 3004 | 3005 | 3006 | 3014 | 3015 | 3016 | 3025 | 3026 | 3027 | 3028 | 3029 | 3030 | 3031 | 3032 | 3033 | 3034 |
NameTypeAttributesDescription
seriesId 2973 | 2974 | 2975 | Number 2976 | | 2977 | 2978 | String 2979 | 2980 | 2981 | 2982 | 2986 | 2987 | 2988 | 2989 | 2990 | 2991 |
opts 3007 | 3008 | 3009 | Object 3010 | 3011 | 3012 | 3013 | 3017 | 3018 | <optional>
3019 | 3020 | 3021 | 3022 | 3023 | 3024 |

additional options for request

3035 | 3036 | 3037 | 3038 | 3039 | 3040 | 3041 |
3042 | 3043 | 3044 | 3045 | 3046 | 3047 | 3048 | 3049 | 3050 | 3051 | 3052 | 3053 | 3054 | 3055 | 3056 | 3057 | 3058 | 3059 | 3060 | 3061 | 3062 | 3063 | 3064 | 3065 | 3066 | 3067 | 3068 | 3069 | 3070 | 3071 | 3072 |
See:
3073 |
3074 | 3077 |
3078 | 3079 | 3080 | 3081 |
3082 | 3083 | 3084 | 3085 | 3086 | 3087 | 3088 | 3089 | 3090 | 3091 | 3092 | 3093 | 3094 | 3095 | 3096 | 3097 | 3098 |
3099 | 3100 |
3101 | 3102 | 3103 | 3104 | 3105 |

getUpdates(fromTime, [toTime], [opts]) → {Promise}

3106 | 3107 | 3108 | 3109 | 3110 | 3111 |
3112 |

Get a list of series updated since a given unix timestamp (and, if given, 3113 | between a second timestamp).

3114 |
tvdb.getUpdates(1400611370, 1400621370)
3115 |     .then(response => { handle response })
3116 |     .catch(error => { handle error });
3117 | 
3118 |
3119 | 3120 | 3121 | 3122 | 3123 | 3124 | 3125 | 3126 | 3127 | 3128 |
Parameters:
3129 | 3130 | 3131 | 3132 | 3133 | 3134 | 3135 | 3136 | 3137 | 3138 | 3139 | 3140 | 3141 | 3142 | 3143 | 3144 | 3145 | 3146 | 3147 | 3148 | 3149 | 3150 | 3151 | 3152 | 3153 | 3154 | 3155 | 3156 | 3157 | 3158 | 3166 | 3167 | 3168 | 3175 | 3176 | 3177 | 3178 | 3179 | 3180 | 3181 | 3182 | 3183 | 3184 | 3185 | 3186 | 3187 | 3188 | 3189 | 3197 | 3198 | 3199 | 3208 | 3209 | 3210 | 3211 | 3212 | 3213 | 3214 | 3215 | 3216 | 3217 | 3218 | 3219 | 3220 | 3221 | 3222 | 3230 | 3231 | 3232 | 3241 | 3242 | 3243 | 3244 | 3245 | 3246 | 3247 | 3248 | 3249 | 3250 |
NameTypeAttributesDescription
fromTime 3159 | 3160 | 3161 | Number 3162 | 3163 | 3164 | 3165 | 3169 | 3170 | 3171 | 3172 | 3173 | 3174 |

timestamp to get series updates from

toTime 3190 | 3191 | 3192 | Number 3193 | 3194 | 3195 | 3196 | 3200 | 3201 | <optional>
3202 | 3203 | 3204 | 3205 | 3206 | 3207 |

timestamp to get series updates to

opts 3223 | 3224 | 3225 | Object 3226 | 3227 | 3228 | 3229 | 3233 | 3234 | <optional>
3235 | 3236 | 3237 | 3238 | 3239 | 3240 |

additional options for request

3251 | 3252 | 3253 | 3254 | 3255 | 3256 | 3257 |
3258 | 3259 | 3260 | 3261 | 3262 | 3263 | 3264 | 3265 | 3266 | 3267 | 3268 | 3269 | 3270 | 3271 | 3272 | 3273 | 3274 | 3275 | 3276 | 3277 | 3278 | 3279 | 3280 | 3281 | 3282 | 3283 | 3284 | 3285 | 3286 | 3287 | 3288 |
See:
3289 |
3290 | 3293 |
3294 | 3295 | 3296 | 3297 |
3298 | 3299 | 3300 | 3301 | 3302 | 3303 | 3304 | 3305 | 3306 | 3307 | 3308 | 3309 | 3310 | 3311 | 3312 | 3313 | 3314 |
3315 | 3316 |
3317 | 3318 | 3319 | 3320 | 3321 |

sendRequest(path, [opts]) → {Promise}

3322 | 3323 | 3324 | 3325 | 3326 | 3327 |
3328 |

Runs a get request with the given options, useful for running custom 3329 | requests.

3330 |
tvdb.sendRequest('custom/endpoint', { custom: 'options' })
3331 |     .then(response => { handle response })
3332 |     .catch(error => { handle error });
3333 | 
3334 |
3335 | 3336 | 3337 | 3338 | 3339 | 3340 | 3341 | 3342 | 3343 | 3344 |
Parameters:
3345 | 3346 | 3347 | 3348 | 3349 | 3350 | 3351 | 3352 | 3353 | 3354 | 3355 | 3356 | 3357 | 3358 | 3359 | 3360 | 3361 | 3362 | 3363 | 3364 | 3365 | 3366 | 3367 | 3368 | 3369 | 3370 | 3371 | 3372 | 3373 | 3374 | 3382 | 3383 | 3384 | 3391 | 3392 | 3393 | 3394 | 3395 | 3396 | 3397 | 3398 | 3399 | 3400 | 3401 | 3402 | 3403 | 3404 | 3405 | 3413 | 3414 | 3415 | 3424 | 3425 | 3426 | 3427 | 3428 | 3429 | 3430 | 3431 | 3432 | 3433 |
NameTypeAttributesDescription
path 3375 | 3376 | 3377 | String 3378 | 3379 | 3380 | 3381 | 3385 | 3386 | 3387 | 3388 | 3389 | 3390 |

path for http resource

opts 3406 | 3407 | 3408 | Object 3409 | 3410 | 3411 | 3412 | 3416 | 3417 | <optional>
3418 | 3419 | 3420 | 3421 | 3422 | 3423 |

additional options for request

3434 | 3435 | 3436 | 3437 | 3438 | 3439 | 3440 |
3441 | 3442 | 3443 | 3444 | 3445 | 3446 | 3447 | 3448 | 3449 | 3450 | 3451 | 3452 | 3453 | 3454 | 3455 | 3456 | 3457 | 3458 | 3459 | 3460 | 3461 | 3462 | 3463 | 3464 | 3465 | 3466 | 3467 | 3468 | 3469 | 3470 | 3471 | 3472 | 3473 |
3474 | 3475 | 3476 | 3477 | 3478 | 3479 | 3480 | 3481 | 3482 | 3483 | 3484 | 3485 | 3486 | 3487 | 3488 | 3489 | 3490 |
3491 | 3492 |
3493 | 3494 | 3495 | 3496 | 3497 | 3498 |
3499 | 3500 |
3501 | 3502 | 3503 | 3504 | 3505 |
3506 | 3507 | 3508 | 3509 | 3514 | 3515 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Home - Documentation 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 103 | 104 |
105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 |
125 |

node-tvdb

126 |

Build Status 127 | npm Downloads

128 |

Node.js library for accessing TheTVDB JSON API. Originally based on joaocampinhos/thetvdb-api to give nicer output and additional features.

129 |

Pull requests are always very welcome.

130 |

Features

131 |
    132 |
  • Handle errors from API as JavaScript errors
  • 133 |
  • Only returns relevant data (no need to call response.Data.Series etc.)
  • 134 |
  • Set language at initialisation or on each function call
  • 135 |
  • Return values through promises (dropped callback support)
  • 136 |
  • Uses the new JSON API from TheTVDB
  • 137 |
  • Tests with Mocha and Travis CI
  • 138 |
139 |

Installation

140 |

Install with npm:

141 |
npm install --save node-tvdb
142 | 
143 |

And run tests with Mocha:

144 |
TVDB_KEY=[YOUR API KEY HERE] npm test
145 | 
146 |
147 |

Mocha is installed as a development dependency; you do not need to install it globally to run the tests.

148 |
149 |

Example Usage

150 |

To start using this library you first need an API key. You can request one here. Then just follow this simple example that fetches all the shows containing "The Simpsons" in the name.

151 |
const TVDB = require('node-tvdb');
152 | const tvdb = new TVDB('ABC123');
153 | 
154 | tvdb.getSeriesByName('The Simpsons')
155 |     .then(response => { /* process data */ })
156 |     .catch(error => { /* handle error */ });
157 | 
158 |

Full API Docs

159 |

Generated API docs with code examples can be found at: edwellbrook.github.io/node-tvdb.

160 |

For details on response data, please see TheTVDB API docs.

161 |

License

162 |

The MIT License (MIT)

163 |
164 | 165 | 166 | 167 | 168 | 169 | 170 |
171 | 172 | 173 | 174 | 179 | 180 | -------------------------------------------------------------------------------- /docs/scripts/prism.min.js: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism-solarizedlight&languages=clike+javascript */ 2 | var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={util:{encode:function(e){return e instanceof a?new a(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(v instanceof a)){u.lastIndex=0;var b=u.exec(v),k=1;if(!b&&h&&m!=r.length-1){if(u.lastIndex=y,b=u.exec(e),!b)break;for(var w=b.index+(c?b[1].length:0),_=b.index+b[0].length,A=m,P=y,j=r.length;j>A&&_>P;++A)P+=r[A].length,w>=P&&(++m,y=P);if(r[m]instanceof a||r[A-1].greedy)continue;k=A-m,v=e.slice(y,P),b.index-=y}if(b){c&&(f=b[1].length);var w=b.index+f,b=b[0].slice(f),_=w+b.length,x=v.slice(0,w),O=v.slice(_),S=[m,k];x&&S.push(x);var N=new a(l,g?n.tokenize(b,g):b,d,b,h);S.push(N),O&&S.push(O),Array.prototype.splice.apply(r,S)}}}}}return r},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(t)}}},a=n.Token=function(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!r};if(a.stringify=function(e,t,r){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return a.stringify(n,t,e)}).join("");var i={type:e.type,content:a.stringify(e.content,t,r),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}n.hooks.run("wrap",i);var o=Object.keys(i.attributes).map(function(e){return e+'="'+(i.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+(o?" "+o:"")+">"+i.content+""},!_self.document)return _self.addEventListener?(_self.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,r=t.code,i=t.immediateClose;_self.postMessage(n.highlight(r,n.languages[a],a)),i&&_self.close()},!1),_self.Prism):_self.Prism;var r=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return r&&(n.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); 3 | Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/}; 4 | Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*\*?|\/|~|\^|%|\.{3}/}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[.+?]|\\.|[^\/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\\\|\\?[^\\])*?`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/()[\w\W]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript"}}),Prism.languages.js=Prism.languages.javascript; 5 | -------------------------------------------------------------------------------- /docs/styles/jsdoc-default.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box 3 | } 4 | 5 | html, body { 6 | height: 100%; 7 | width: 100%; 8 | } 9 | 10 | body { 11 | color: #4d4e53; 12 | background-color: white; 13 | margin: 0 auto; 14 | padding: 0 20px; 15 | max-width: 960px; 16 | 17 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 18 | font-size: 16px; 19 | line-height: 160%; 20 | } 21 | 22 | a, 23 | a:active { 24 | color: #0095dd; 25 | text-decoration: none; 26 | } 27 | 28 | a:hover { 29 | text-decoration: underline 30 | } 31 | 32 | p, ul, ol, blockquote { 33 | margin-bottom: 1em; 34 | } 35 | 36 | blockquote { 37 | margin-left: 0; 38 | padding-left: 1em; 39 | border-left: 3px solid rgba(0,0,0,.1); 40 | } 41 | 42 | h1, h2, h3, h4, h5, h6 { 43 | color: #000; 44 | font-weight: 400; 45 | } 46 | 47 | h1 { 48 | font-weight: 300; 49 | font-size: 48px; 50 | } 51 | 52 | h1.page-title { 53 | font-size: 48px; 54 | } 55 | 56 | h2 { 57 | font-size: 22px; 58 | padding: 0.6em 0; 59 | } 60 | 61 | h3 { 62 | font-size: 24px; 63 | } 64 | 65 | h4 { 66 | font-size: 18px; 67 | color: #4d4e53; 68 | margin: 1em 0; 69 | } 70 | 71 | h5, 72 | .container-overview .subsection-title { 73 | font-size: 1.1em; 74 | margin: 1.4em 0 1em; 75 | } 76 | 77 | h6 { 78 | font-size: 100%; 79 | margin: 6px 0 3px 0; 80 | font-style: italic; 81 | } 82 | 83 | 84 | article h2 { 85 | border-bottom: 1px solid rgba(0,0,0,.1); 86 | } 87 | 88 | pre { 89 | padding: 5px 10px; 90 | border-radius: 5px; 91 | background: #f4f4f4; 92 | } 93 | 94 | tt, code, kbd, samp { 95 | font-family: Consolas, Monaco, "Andale Mono", monospace; 96 | } 97 | 98 | .class-description { 99 | font-size: 130%; 100 | line-height: 140%; 101 | margin-bottom: 1em; 102 | margin-top: 1em; 103 | } 104 | 105 | .class-description:empty { 106 | margin: 0 107 | } 108 | 109 | #main, 110 | footer { 111 | float: right; 112 | width: calc(100% - 240px); 113 | position: relative; 114 | z-index: 3; 115 | } 116 | 117 | footer { 118 | text-align: center; 119 | padding: 20px 0; 120 | } 121 | 122 | header { 123 | display: block 124 | } 125 | 126 | .variation { 127 | display: none 128 | } 129 | 130 | .signature .optional-param { 131 | color: #aaa; 132 | } 133 | 134 | .signature-attributes { 135 | font-size: 60%; 136 | color: #aaa; 137 | font-style: italic; 138 | font-weight: lighter; 139 | } 140 | 141 | nav { 142 | float: left; 143 | display: block; 144 | width: 240px; 145 | background: #fff; 146 | overflow: auto; 147 | position: fixed; 148 | height: 100%; 149 | } 150 | 151 | nav h3 { 152 | margin-top: 12px; 153 | font-size: 13px; 154 | text-transform: uppercase; 155 | letter-spacing: 1px; 156 | font-weight: 700; 157 | line-height: 24px; 158 | margin: 15px 0 10px; 159 | padding: 0; 160 | color: #000; 161 | } 162 | 163 | nav ul { 164 | font-size: 100%; 165 | line-height: 17px; 166 | padding: 0; 167 | margin: 0; 168 | list-style-type: none; 169 | } 170 | 171 | nav ul a, 172 | nav ul a:active { 173 | line-height: 18px; 174 | padding: 0; 175 | display: block; 176 | font-size: 12px; 177 | } 178 | 179 | nav ul a:hover, 180 | nav ul a:active { 181 | color: hsl(200, 100%, 43%); 182 | text-decoration: none; 183 | } 184 | 185 | nav > ul { 186 | padding: 0 10px; 187 | } 188 | 189 | nav > ul > li > a { 190 | color: #000; 191 | } 192 | 193 | nav ul ul { 194 | margin-bottom: 10px 195 | } 196 | 197 | nav ul ul a { 198 | color: hsl(207, 1%, 60%); 199 | border-left: 1px solid hsl(207, 10%, 86%); 200 | } 201 | 202 | nav ul ul a, 203 | nav ul ul a:active { 204 | padding-left: 20px 205 | } 206 | 207 | nav h2 { 208 | font-size: 12px; 209 | margin: 0; 210 | padding: 0; 211 | } 212 | 213 | nav > h2 > a { 214 | display: block; 215 | margin: 10px 0 -10px; 216 | color: hsl(202, 71%, 50%) !important; 217 | } 218 | 219 | footer { 220 | color: hsl(0, 0%, 28%); 221 | display: block; 222 | font-style: italic; 223 | font-size: 90%; 224 | } 225 | 226 | .subsection-methods .method { 227 | padding: 30px 0; 228 | border-bottom: 1px solid rgba(0,0,0,.1); 229 | } 230 | 231 | .subsection-methods .method:first-child { 232 | padding-top: 0; 233 | } 234 | 235 | .ancestors { 236 | color: #999 237 | } 238 | 239 | .ancestors a { 240 | color: #999 !important; 241 | text-decoration: none; 242 | } 243 | 244 | .clear { 245 | display: block; 246 | clear: both 247 | } 248 | 249 | .important { 250 | font-weight: bold; 251 | color: #950B02; 252 | } 253 | 254 | .yes-def { 255 | text-indent: -1000px 256 | } 257 | 258 | .type-signature { 259 | color: #aaa 260 | } 261 | 262 | .name, .signature { 263 | font-family: Consolas, Monaco, "Andale Mono", monospace 264 | } 265 | 266 | .details { 267 | margin-top: 14px; 268 | border-left: 2px solid #DDD; 269 | line-height: 30px; 270 | width: 100%; 271 | overflow: scroll; 272 | } 273 | 274 | .details dt { 275 | width: 120px; 276 | float: left; 277 | padding-left: 10px; 278 | } 279 | 280 | .details dd { 281 | margin-left: 70px 282 | } 283 | 284 | .details ul { 285 | margin: 0 286 | } 287 | 288 | .details ul { 289 | list-style-type: none 290 | } 291 | 292 | .details li { 293 | margin-left: 30px 294 | } 295 | 296 | .details pre.prettyprint { 297 | margin: 0 298 | } 299 | 300 | .details .object-value { 301 | padding-top: 0 302 | } 303 | 304 | .description { 305 | margin-bottom: 1em; 306 | margin-top: 1em; 307 | } 308 | 309 | .code-caption { 310 | font-style: italic; 311 | font-size: 107%; 312 | margin: 0; 313 | } 314 | 315 | .params, 316 | .props { 317 | border-spacing: 0; 318 | border-radius: 3px; 319 | box-shadow: 0 0 0 1px rgba(0,0,0,0.1), 0 1px 3px rgba(0,0,0,0.1); 320 | width: 100%; 321 | font-size: 14px; 322 | } 323 | 324 | .params td, 325 | .params th, 326 | .props td, 327 | .props th { 328 | margin: 0px; 329 | text-align: left; 330 | vertical-align: top; 331 | padding: 10px; 332 | display: table-cell; 333 | } 334 | 335 | .params td { 336 | border-top: 1px solid #eee 337 | } 338 | 339 | .params thead tr, 340 | .props thead tr { 341 | background-color: rgba(0,0,0,0.02); 342 | font-weight: bold; 343 | } 344 | 345 | .params .params thead tr, 346 | .props .props thead tr { 347 | background-color: #fff; 348 | font-weight: bold; 349 | } 350 | 351 | .params td.description > p:first-child, .props td.description > p:first-child { 352 | margin-top: 0; 353 | padding-top: 0; 354 | } 355 | 356 | .params td.description > p:last-child, .props td.description > p:last-child { 357 | margin-bottom: 0; 358 | padding-bottom: 0; 359 | } 360 | 361 | .param-type dt, .param-type dd { 362 | display: inline-block 363 | } 364 | 365 | .param-type dd { 366 | font-family: Consolas, Monaco, "Andale Mono", monospace 367 | } 368 | 369 | .disabled { 370 | color: #454545 371 | } 372 | 373 | /* navicon button */ 374 | .navicon-button { 375 | display: none; 376 | position: relative; 377 | padding: 2.0625rem 1.5rem; 378 | transition: 0.25s; 379 | cursor: pointer; 380 | user-select: none; 381 | opacity: .8; 382 | } 383 | .navicon-button .navicon:before, .navicon-button .navicon:after { 384 | transition: 0.25s; 385 | } 386 | .navicon-button:hover { 387 | transition: 0.5s; 388 | opacity: 1; 389 | } 390 | .navicon-button:hover .navicon:before, .navicon-button:hover .navicon:after { 391 | transition: 0.25s; 392 | } 393 | .navicon-button:hover .navicon:before { 394 | top: .825rem; 395 | } 396 | .navicon-button:hover .navicon:after { 397 | top: -.825rem; 398 | } 399 | 400 | /* navicon */ 401 | .navicon { 402 | position: relative; 403 | width: 2.5em; 404 | height: .3125rem; 405 | background: #000; 406 | transition: 0.3s; 407 | border-radius: 2.5rem; 408 | } 409 | .navicon:before, .navicon:after { 410 | display: block; 411 | content: ""; 412 | height: .3125rem; 413 | width: 2.5rem; 414 | background: #000; 415 | position: absolute; 416 | z-index: -1; 417 | transition: 0.3s 0.25s; 418 | border-radius: 1rem; 419 | } 420 | .navicon:before { 421 | top: .625rem; 422 | } 423 | .navicon:after { 424 | top: -.625rem; 425 | } 426 | 427 | /* open */ 428 | .nav-trigger:checked + label:not(.steps) .navicon:before, 429 | .nav-trigger:checked + label:not(.steps) .navicon:after { 430 | top: 0 !important; 431 | } 432 | 433 | .nav-trigger:checked + label .navicon:before, 434 | .nav-trigger:checked + label .navicon:after { 435 | transition: 0.5s; 436 | } 437 | 438 | /* Minus */ 439 | .nav-trigger:checked + label { 440 | transform: scale(0.75); 441 | } 442 | 443 | /* × and + */ 444 | .nav-trigger:checked + label.plus .navicon, 445 | .nav-trigger:checked + label.x .navicon { 446 | background: transparent; 447 | } 448 | 449 | .nav-trigger:checked + label.plus .navicon:before, 450 | .nav-trigger:checked + label.x .navicon:before { 451 | transform: rotate(-45deg); 452 | background: #FFF; 453 | } 454 | 455 | .nav-trigger:checked + label.plus .navicon:after, 456 | .nav-trigger:checked + label.x .navicon:after { 457 | transform: rotate(45deg); 458 | background: #FFF; 459 | } 460 | 461 | .nav-trigger:checked + label.plus { 462 | transform: scale(0.75) rotate(45deg); 463 | } 464 | 465 | .nav-trigger:checked ~ nav { 466 | left: 0 !important; 467 | } 468 | 469 | .nav-trigger:checked ~ .overlay { 470 | display: block; 471 | } 472 | 473 | .nav-trigger { 474 | position: fixed; 475 | top: 0; 476 | clip: rect(0, 0, 0, 0); 477 | } 478 | 479 | .overlay { 480 | display: none; 481 | position: fixed; 482 | top: 0; 483 | bottom: 0; 484 | left: 0; 485 | right: 0; 486 | width: 100%; 487 | height: 100%; 488 | background: hsla(0, 0%, 0%, 0.5); 489 | z-index: 4; 490 | } 491 | 492 | @media only screen and (min-width: 320px) and (max-width: 680px) { 493 | body { 494 | overflow-x: hidden; 495 | } 496 | 497 | nav { 498 | background: #FFF; 499 | width: 250px; 500 | height: 100%; 501 | position: fixed; 502 | top: 0; 503 | right: 0; 504 | bottom: 0; 505 | left: -250px; 506 | z-index: 4; 507 | padding: 0 10px; 508 | transition: left 0.2s; 509 | } 510 | 511 | .navicon-button { 512 | display: inline-block; 513 | position: fixed; 514 | top: 1.5em; 515 | right: 0; 516 | z-index: 5; 517 | } 518 | 519 | #main { 520 | width: 100%; 521 | } 522 | 523 | #main h1.page-title { 524 | margin: 1em 0; 525 | } 526 | 527 | #main section { 528 | padding: 0; 529 | } 530 | 531 | footer { 532 | margin-left: 0; 533 | } 534 | } 535 | 536 | @media only print { 537 | nav { 538 | display: none; 539 | } 540 | 541 | #main { 542 | float: none; 543 | width: 100%; 544 | } 545 | } 546 | -------------------------------------------------------------------------------- /docs/styles/prism.css: -------------------------------------------------------------------------------- 1 | /* 2 | Name: Base16 Atelier Sulphurpool Light 3 | Author: Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool) 4 | Prism template by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/prism/) 5 | Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) 6 | */ 7 | code[class*="language-"], 8 | pre[class*="language-"] { 9 | font-family: Consolas, Menlo, Monaco, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, monospace; 10 | font-size: 14px; 11 | line-height: 1.375; 12 | direction: ltr; 13 | text-align: left; 14 | white-space: pre; 15 | word-spacing: normal; 16 | word-break: normal; 17 | -moz-tab-size: 4; 18 | -o-tab-size: 4; 19 | tab-size: 4; 20 | -webkit-hyphens: none; 21 | -moz-hyphens: none; 22 | -ms-hyphens: none; 23 | hyphens: none; 24 | background: #f5f7ff; 25 | color: #5e6687; 26 | } 27 | 28 | pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection, 29 | code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection { 30 | text-shadow: none; 31 | background: #dfe2f1; 32 | } 33 | 34 | pre[class*="language-"]::selection, pre[class*="language-"] ::selection, 35 | code[class*="language-"]::selection, code[class*="language-"] ::selection { 36 | text-shadow: none; 37 | background: #dfe2f1; 38 | } 39 | 40 | /* Code blocks */ 41 | pre[class*="language-"] { 42 | padding: 1em; 43 | margin: .5em 0; 44 | overflow: auto; 45 | } 46 | 47 | /* Inline code */ 48 | :not(pre) > code[class*="language-"] { 49 | padding: .1em; 50 | border-radius: .3em; 51 | } 52 | 53 | .token.comment, 54 | .token.prolog, 55 | .token.doctype, 56 | .token.cdata { 57 | color: #898ea4; 58 | } 59 | 60 | .token.punctuation { 61 | color: #5e6687; 62 | } 63 | 64 | .token.namespace { 65 | opacity: .7; 66 | } 67 | 68 | .token.operator, 69 | .token.boolean, 70 | .token.number { 71 | color: #c76b29; 72 | } 73 | 74 | .token.property { 75 | color: #c08b30; 76 | } 77 | 78 | .token.tag { 79 | color: #3d8fd1; 80 | } 81 | 82 | .token.string { 83 | color: #22a2c9; 84 | } 85 | 86 | .token.selector { 87 | color: #6679cc; 88 | } 89 | 90 | .token.attr-name { 91 | color: #c76b29; 92 | } 93 | 94 | .token.entity, 95 | .token.url, 96 | .language-css .token.string, 97 | .style .token.string { 98 | color: #22a2c9; 99 | } 100 | 101 | .token.attr-value, 102 | .token.keyword, 103 | .token.control, 104 | .token.directive, 105 | .token.unit { 106 | color: #ac9739; 107 | } 108 | 109 | .token.statement, 110 | .token.regex, 111 | .token.atrule { 112 | color: #22a2c9; 113 | } 114 | 115 | .token.placeholder, 116 | .token.variable { 117 | color: #3d8fd1; 118 | } 119 | 120 | .token.deleted { 121 | text-decoration: line-through; 122 | } 123 | 124 | .token.inserted { 125 | border-bottom: 1px dotted #202746; 126 | text-decoration: none; 127 | } 128 | 129 | .token.italic { 130 | font-style: italic; 131 | } 132 | 133 | .token.important, 134 | .token.bold { 135 | font-weight: bold; 136 | } 137 | 138 | .token.important { 139 | color: #c94922; 140 | } 141 | 142 | .token.entity { 143 | cursor: help; 144 | } 145 | 146 | pre > code.highlight { 147 | outline: 0.4em solid #c94922; 148 | outline-offset: .4em; 149 | } 150 | 151 | /* overrides color-values for the Line Numbers plugin 152 | * http://prismjs.com/plugins/line-numbers/ 153 | */ 154 | .line-numbers .line-numbers-rows { 155 | border-right-color: #dfe2f1; 156 | } 157 | 158 | .line-numbers-rows > span:before { 159 | color: #979db4; 160 | } 161 | 162 | /* overrides color-values for the Line Highlight plugin 163 | * http://prismjs.com/plugins/line-highlight/ 164 | */ 165 | .line-highlight { 166 | background: rgba(107, 115, 148, 0.2); 167 | background: -webkit-linear-gradient(left, rgba(107, 115, 148, 0.2) 70%, rgba(107, 115, 148, 0)); 168 | background: linear-gradient(to right, rgba(107, 115, 148, 0.2) 70%, rgba(107, 115, 148, 0)); 169 | } 170 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for node-tvdb 2 | // Definitions by: Jeffrey Barrus http://github.com/jbarrus 3 | 4 | export = Client; 5 | 6 | declare class Client { 7 | constructor(apiKey: string, language?: string) 8 | 9 | /** 10 | * Get available languages useable by TheTVDB API. 11 | * 12 | * ``` javascript 13 | * tvdb.getLanguages() 14 | * .then(response => { handle response }) 15 | * .catch(error => { handle error }); 16 | * ``` 17 | */ 18 | getLanguages(opts?: any): Promise 19 | 20 | /** 21 | * Get episode by episode id. 22 | * 23 | * ``` javascript 24 | * tvdb.getEpisodeById(4768125) 25 | * .then(response => { handle response }) 26 | * .catch(error => { handle error }); 27 | * ``` 28 | * @see https://api.thetvdb.com/swagger#!/Episodes/get_episodes_id 29 | */ 30 | 31 | getEpisodeById(episodeId: number | string, opts?: any): Promise 32 | 33 | /** 34 | * Get all episodes by series id. 35 | * 36 | * The opts may include the object `query` with any of the parameters from the query endpoint 37 | * 38 | * ``` javascript 39 | * tvdb.getEpisodesBySeriesId(153021) 40 | * .then(response => { handle response }) 41 | * .catch(error => { handle error }); 42 | * ``` 43 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_episodes 44 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_episodes_query 45 | */ 46 | 47 | getEpisodesBySeriesId(seriesId: number | string, opts?: any): Promise 48 | 49 | /** 50 | * Get episodes summary by series id. 51 | * 52 | * ``` javascript 53 | * tvdb.getEpisodesSummaryBySeriesId(153021) 54 | * .then(response => { handle response }) 55 | * .catch(error => { handle error }); 56 | * ``` 57 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_episodes_summary 58 | */ 59 | 60 | getEpisodesSummaryBySeriesId(seriesId: number | string): Promise 61 | 62 | /** 63 | * Get basic series information by id. 64 | * 65 | * ``` javascript 66 | * tvdb.getSeriesById(73255) 67 | * .then(response => { handle response }) 68 | * .catch(error => { handle error }); 69 | * ``` 70 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id 71 | */ 72 | 73 | getSeriesById(seriesId: number | string, opts?: any): Promise 74 | 75 | /** 76 | * Get series episode by air date. 77 | * 78 | * ``` javascript 79 | * tvdb.getEpisodeByAirDate(153021, '2011-10-03') 80 | * .then(response => { handle response }) 81 | * .catch(error => { handle error }); 82 | * ``` 83 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_episodes_query 84 | */ 85 | 86 | getEpisodesByAirDate(seriesId: number | string, airDate: string, opts?: any): Promise 87 | 88 | /** 89 | * Get basic series information by name. 90 | * 91 | * ``` javascript 92 | * tvdb.getSeriesByName('Breaking Bad') 93 | * .then(response => { handle response }) 94 | * .catch(error => { handle error }); 95 | * ``` 96 | * @see https://api.thetvdb.com/swagger#!/Search/get_search_series 97 | */ 98 | 99 | getSeriesByName(name: string, opts?: any) : Promise 100 | 101 | /** 102 | * Get series actors by series id. 103 | * 104 | * ``` javascript 105 | * tvdb.getActors(73255) 106 | * .then(response => { handle response }) 107 | * .catch(error => { handle error }); 108 | * ``` 109 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_actors 110 | */ 111 | 112 | getActors(seriesId: number | string, opts?: any): Promise 113 | 114 | /** 115 | * Get basic series information by imdb id. 116 | * 117 | * ``` javascript 118 | * tvdb.getSeriesByImdbId('tt0903747') 119 | * .then(response => { handle response }) 120 | * .catch(error => { handle error }); 121 | * ``` 122 | * @see https://api.thetvdb.com/swagger#!/Search/get_search_series 123 | */ 124 | 125 | getSeriesByImdbId(imdbId: string, opts?: any): Promise 126 | 127 | /** 128 | * Get basic series information by zap2it id. 129 | * 130 | * ``` javascript 131 | * tvdb.getSeriesByZap2ItId('EP00018693') 132 | * .then(response => { handle response }) 133 | * .catch(error => { handle error }); 134 | * ``` 135 | * @see https://api.thetvdb.com/swagger#!/Search/get_search_series 136 | */ 137 | 138 | getSeriesByZap2ItId(zap2ItId: string, opts?: any): Promise 139 | 140 | /** 141 | * Get series banner by series id. 142 | * 143 | * ``` javascript 144 | * tvdb.getSeriesBanner(73255) 145 | * .then(response => { handle response }) 146 | * .catch(error => { handle error }); 147 | * ``` 148 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_filter 149 | */ 150 | 151 | getSeriesBanner(seriesId: number | string, opts?: any): Promise 152 | 153 | /** 154 | * Get series images for a given key type. 155 | * 156 | * ``` javascript 157 | * // request only return fan art images: 158 | * tvdb.getSeriesImages(73255, 'fanart', { query: queryOptions }) 159 | * .then(response => { handle response }) 160 | * .catch(error => { handle error }); 161 | * ``` 162 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_images 163 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_images_query 164 | */ 165 | 166 | getSeriesImages(seriesId: number | string, keyType: string, opts?: any): Promise 167 | 168 | /** 169 | * Convenience wrapper around `getSeriesImages` to only return poster images for a series. 170 | * 171 | * ``` javascript 172 | * tvdb.getSeriesPosters(73255) 173 | * .then(response => { handle response }) 174 | * .catch(error => { handle error }); 175 | * ``` 176 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_images_query 177 | */ 178 | getSeriesPosters(seriesId: number | string, opts?: any): Promise 179 | 180 | /** 181 | * Convenience wrapper around `getSeriesImages` to only return season poster images for a series. 182 | * 183 | * ``` javascript 184 | * tvdb.getSeasonPosters(73255, 1) 185 | * .then(response => { handle response }) 186 | * .catch(error => { handle error }); 187 | * ``` 188 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_images_query 189 | */ 190 | getSeasonPosters(seriesId: number | string, season: number | string, opts?: any): Promise 191 | 192 | /** 193 | * Get a list of series updated since a given unix timestamp (and, if given, 194 | * between a second timestamp). 195 | * 196 | * ``` javascript 197 | * tvdb.getUpdates(1400611370, 1400621370) 198 | * .then(response => { handle response }) 199 | * .catch(error => { handle error }); 200 | * ``` 201 | * @see https://api.thetvdb.com/swagger#!/Updates/get_updated_query 202 | */ 203 | 204 | getUpdates(fromTime: number, toTime: number, opts?: any): Promise 205 | 206 | /** 207 | * Get series and episode information by series id. Helper for calling 208 | * `getSeriesById` and `getEpisodesBySeriesId` at the same time. 209 | * 210 | * ``` javascript 211 | * tvdb.getSeriesAllById(73255) 212 | * .then(response => { 213 | * response; // contains series data (i.e. `id`, `seriesName`) 214 | * response.episodes; // contains an array of episodes 215 | * }) 216 | * .catch(error => { handle error }); 217 | * ``` 218 | */ 219 | getSeriesAllById(seriesId: number | string, opts?: any): Promise 220 | 221 | /** 222 | * Runs a get request with the given options, useful for running custom 223 | * requests. 224 | * 225 | * ``` javascript 226 | * tvdb.sendRequest('custom/endpoint', { custom: 'options' }) 227 | * .then(response => { handle response }) 228 | * .catch(error => { handle error }); 229 | * ``` 230 | */ 231 | sendRequest(path: string, opts?: any): Promise 232 | } 233 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * node-tvdb 3 | * 4 | * Node.js library for accessing TheTVDB API at 5 | * 6 | * Copyright (c) 2014-2017 Edward Wellbrook 7 | * MIT Licensed 8 | */ 9 | 10 | 'use strict'; 11 | 12 | const url = require('url'); 13 | const request = require('node-fetch'); 14 | const flatten = require('lodash/flatten'); 15 | 16 | const BASE_URL = 'https://api.thetvdb.com'; 17 | const LIB_VERSION = require('./package.json').version; 18 | const API_VERSION = 'v2.1.1'; 19 | const AV_HEADER = `application/vnd.thetvdb.${API_VERSION}`; 20 | 21 | const DEFAULT_OPTS = { 22 | getAllPages: true, 23 | headers: { 24 | 'User-Agent': `node-tvdb/${LIB_VERSION} (+https://github.com/edwellbrook/node-tvdb)` 25 | } 26 | }; 27 | 28 | 29 | // 30 | // API Client 31 | // 32 | 33 | class Client { 34 | 35 | /** 36 | * @param {String} apiKey 37 | * @param {String} [language] 38 | */ 39 | 40 | constructor(apiKey, language) { 41 | if (!apiKey) { 42 | throw new Error('API key is required'); 43 | } 44 | 45 | this.apiKey = apiKey; 46 | this.language = language || 'en'; 47 | 48 | // store and manage auth token 49 | let tokenPromise = null; 50 | 51 | this.getToken = function() { 52 | if (tokenPromise === null) { 53 | tokenPromise = logIn(this.apiKey); 54 | } 55 | 56 | return tokenPromise; 57 | }; 58 | } 59 | 60 | /** 61 | * Get available languages useable by TheTVDB API. 62 | * 63 | * ``` javascript 64 | * tvdb.getLanguages() 65 | * .then(response => { handle response }) 66 | * .catch(error => { handle error }); 67 | * ``` 68 | * 69 | * @param {Object} [opts] - additional options for request 70 | * @returns {Promise} 71 | * 72 | * @see https://api.thetvdb.com/swagger#!/Languages/get_languages 73 | * @public 74 | */ 75 | 76 | getLanguages(opts) { 77 | return this.sendRequest('languages', opts); 78 | } 79 | 80 | /** 81 | * Get episode by episode id. 82 | * 83 | * ``` javascript 84 | * tvdb.getEpisodeById(4768125) 85 | * .then(response => { handle response }) 86 | * .catch(error => { handle error }); 87 | * ``` 88 | * 89 | * @param {Number|String} episodeId 90 | * @param {Object} [opts] - additional options for request 91 | * @returns {Promise} 92 | * 93 | * @see https://api.thetvdb.com/swagger#!/Episodes/get_episodes_id 94 | * @public 95 | */ 96 | 97 | getEpisodeById(episodeId, opts) { 98 | return this.sendRequest(`episodes/${episodeId}`, opts); 99 | } 100 | 101 | /** 102 | * Get all episodes by series id. 103 | * 104 | * The opts may include the object `query` with any of the parameters from the query endpoint 105 | * 106 | * ``` javascript 107 | * tvdb.getEpisodesBySeriesId(153021) 108 | * .then(response => { handle response }) 109 | * .catch(error => { handle error }); 110 | * ``` 111 | * 112 | * @param {Number|String} seriesId 113 | * @param {Object} [opts] - additional options for request 114 | * @returns {Promise} 115 | * 116 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_episodes 117 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_episodes_query 118 | * @public 119 | */ 120 | 121 | getEpisodesBySeriesId(seriesId, opts) { 122 | if (opts && opts.query) { 123 | return this.sendRequest(`series/${seriesId}/episodes/query`, opts); 124 | } 125 | return this.sendRequest(`series/${seriesId}/episodes`, opts); 126 | } 127 | 128 | /** 129 | * Get episodes summary by series id. 130 | * 131 | * ``` javascript 132 | * tvdb.getEpisodesSummaryBySeriesId(153021) 133 | * .then(response => { handle response }) 134 | * .catch(error => { handle error }); 135 | * ``` 136 | * 137 | * @param {Number|String} seriesId 138 | * @returns {Promise} 139 | * 140 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_episodes_summary 141 | * @public 142 | */ 143 | 144 | getEpisodesSummaryBySeriesId(seriesId) { 145 | return this.sendRequest(`series/${seriesId}/episodes/summary`); 146 | } 147 | 148 | /** 149 | * Get basic series information by id. 150 | * 151 | * ``` javascript 152 | * tvdb.getSeriesById(73255) 153 | * .then(response => { handle response }) 154 | * .catch(error => { handle error }); 155 | * ``` 156 | * 157 | * @param {Number|String} seriesId 158 | * @param {Object} [opts] - additional options for request 159 | * @returns {Promise} 160 | * 161 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id 162 | * @public 163 | */ 164 | 165 | getSeriesById(seriesId, opts) { 166 | return this.sendRequest(`series/${seriesId}`, opts); 167 | } 168 | 169 | /** 170 | * Get series episode by air date. 171 | * 172 | * ``` javascript 173 | * tvdb.getEpisodeByAirDate(153021, '2011-10-03') 174 | * .then(response => { handle response }) 175 | * .catch(error => { handle error }); 176 | * ``` 177 | * 178 | * @param {Number|String} seriesId 179 | * @param {String} airDate 180 | * @param {Object} [opts] - additional options for request 181 | * @returns {Promise} 182 | * 183 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_episodes_query 184 | * @public 185 | */ 186 | 187 | getEpisodesByAirDate(seriesId, airDate, opts) { 188 | const query = { firstAired: airDate }; 189 | const reqOpts = Object.assign({}, opts, { query: query }); 190 | 191 | return this.getEpisodesBySeriesId(seriesId, reqOpts); 192 | } 193 | 194 | /** 195 | * Get basic series information by name. 196 | * 197 | * ``` javascript 198 | * tvdb.getSeriesByName('Breaking Bad') 199 | * .then(response => { handle response }) 200 | * .catch(error => { handle error }); 201 | * ``` 202 | * 203 | * @param {String} name 204 | * @param {Object} [opts] - additional options for request 205 | * @returns {Promise} 206 | * 207 | * @see https://api.thetvdb.com/swagger#!/Search/get_search_series 208 | * @public 209 | */ 210 | 211 | getSeriesByName(name, opts) { 212 | const query = { name: name }; 213 | const reqOpts = Object.assign({}, opts, { query: query }); 214 | return this.sendRequest(`search/series`, reqOpts); 215 | } 216 | 217 | /** 218 | * Get series actors by series id. 219 | * 220 | * ``` javascript 221 | * tvdb.getActors(73255) 222 | * .then(response => { handle response }) 223 | * .catch(error => { handle error }); 224 | * ``` 225 | * 226 | * @param {Number|String} seriesId 227 | * @param {Object} [opts] - additional options for request 228 | * @returns {Promise} 229 | * 230 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_actors 231 | * @public 232 | */ 233 | 234 | getActors(seriesId, opts) { 235 | return this.sendRequest(`series/${seriesId}/actors`, opts); 236 | } 237 | 238 | /** 239 | * Get basic series information by imdb id. 240 | * 241 | * ``` javascript 242 | * tvdb.getSeriesByImdbId('tt0903747') 243 | * .then(response => { handle response }) 244 | * .catch(error => { handle error }); 245 | * ``` 246 | * 247 | * @param {String} imdbId 248 | * @param {Object} [opts] - additional options for request 249 | * @returns {Promise} 250 | * 251 | * @see https://api.thetvdb.com/swagger#!/Search/get_search_series 252 | * @public 253 | */ 254 | 255 | getSeriesByImdbId(imdbId, opts) { 256 | const query = { imdbId: imdbId }; 257 | const reqOpts = Object.assign({}, opts, { query: query }); 258 | return this.sendRequest(`search/series`, reqOpts); 259 | } 260 | 261 | /** 262 | * Get basic series information by zap2it id. 263 | * 264 | * ``` javascript 265 | * tvdb.getSeriesByZap2ItId('EP00018693') 266 | * .then(response => { handle response }) 267 | * .catch(error => { handle error }); 268 | * ``` 269 | * 270 | * @param {String} zap2ItId 271 | * @param {Object} [opts] - additional options for request 272 | * @returns {Promise} 273 | * 274 | * @see https://api.thetvdb.com/swagger#!/Search/get_search_series 275 | * @public 276 | */ 277 | 278 | getSeriesByZap2ItId(zap2ItId, opts) { 279 | const query = { zap2itId: zap2ItId }; 280 | const reqOpts = Object.assign({}, opts, { query: query }); 281 | return this.sendRequest(`search/series`, reqOpts); 282 | } 283 | 284 | /** 285 | * Get series banner by series id. 286 | * 287 | * ``` javascript 288 | * tvdb.getSeriesBanner(73255) 289 | * .then(response => { handle response }) 290 | * .catch(error => { handle error }); 291 | * ``` 292 | * 293 | * @param {Number|String} seriesId 294 | * @param {Object} [opts] - additional options for request 295 | * @returns {Promise} 296 | * 297 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_filter 298 | * @public 299 | */ 300 | 301 | getSeriesBanner(seriesId, opts) { 302 | const query = { keys: 'banner' }; 303 | const reqOpts = Object.assign({}, opts, { query: query }); 304 | 305 | return this.sendRequest(`series/${seriesId}/filter`, reqOpts).then(response => { 306 | return response.banner; 307 | }); 308 | } 309 | 310 | /** 311 | * Get series images for a given key type. 312 | * 313 | * ``` javascript 314 | * // request only return fan art images: 315 | * tvdb.getSeriesImages(73255, 'fanart', { query: queryOptions }) 316 | * .then(response => { handle response }) 317 | * .catch(error => { handle error }); 318 | * ``` 319 | * 320 | * @param {Number|String} seriesId 321 | * @param {String} keyType - the key type to query by 322 | * @param {Object} [opts] - additional options for request 323 | * @returns {Promise} 324 | * 325 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_images 326 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_images_query 327 | * @public 328 | */ 329 | 330 | getSeriesImages(seriesId, keyType, opts) { 331 | let query = {}; 332 | if (keyType !== null) { 333 | query = { query: { 334 | keyType: keyType } 335 | }; 336 | } 337 | const reqOpts = Object.assign({}, opts, query); 338 | 339 | return this.sendRequest(`series/${seriesId}/images/query`, reqOpts); 340 | } 341 | 342 | /** 343 | * Convenience wrapper around `getSeriesImages` to only return poster images for a series. 344 | * 345 | * ``` javascript 346 | * tvdb.getSeriesPosters(73255) 347 | * .then(response => { handle response }) 348 | * .catch(error => { handle error }); 349 | * ``` 350 | * 351 | * @param {Number|String} seriesId 352 | * @param {Object} [opts] - additional options for request 353 | * @returns {Promise} 354 | * 355 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_images_query 356 | * @public 357 | */ 358 | getSeriesPosters(seriesId, opts) { 359 | return this.getSeriesImages(seriesId, 'poster', opts); 360 | } 361 | 362 | /** 363 | * Convenience wrapper around `getSeriesImages` to only return season poster images for a series. 364 | * 365 | * ``` javascript 366 | * tvdb.getSeasonPosters(73255, 1) 367 | * .then(response => { handle response }) 368 | * .catch(error => { handle error }); 369 | * ``` 370 | * 371 | * @param {Number|String} seriesId 372 | * @param {Number|String} season 373 | * @param {Object} [opts] - additional options for request 374 | * @returns {Promise} 375 | * 376 | * @see https://api.thetvdb.com/swagger#!/Series/get_series_id_images_query 377 | * @public 378 | */ 379 | getSeasonPosters(seriesId, season, opts) { 380 | const query = { keyType: 'season', subKey: season }; 381 | const reqOpts = Object.assign({}, opts, { query: query }); 382 | 383 | return this.getSeriesImages(seriesId, null, reqOpts); 384 | } 385 | 386 | /** 387 | * Get a list of series updated since a given unix timestamp (and, if given, 388 | * between a second timestamp). 389 | * 390 | * ``` javascript 391 | * tvdb.getUpdates(1400611370, 1400621370) 392 | * .then(response => { handle response }) 393 | * .catch(error => { handle error }); 394 | * ``` 395 | * 396 | * @param {Number} fromTime - timestamp to get series updates from 397 | * @param {Number} [toTime] - timestamp to get series updates to 398 | * @param {Object} [opts] - additional options for request 399 | * @returns {Promise} 400 | * 401 | * @see https://api.thetvdb.com/swagger#!/Updates/get_updated_query 402 | * @public 403 | */ 404 | 405 | getUpdates(fromTime, toTime, opts) { 406 | const query = { fromTime: fromTime }; 407 | if (toTime) { 408 | query.toTime = toTime; 409 | } else { 410 | opts = toTime; 411 | } 412 | 413 | const reqOpts = Object.assign({}, opts, { query: query }); 414 | return this.sendRequest('updated/query', reqOpts); 415 | } 416 | 417 | /** 418 | * Get series and episode information by series id. Helper for calling 419 | * `getSeriesById` and `getEpisodesBySeriesId` at the same time. 420 | * 421 | * ``` javascript 422 | * tvdb.getSeriesAllById(73255) 423 | * .then(response => { 424 | * response; // contains series data (i.e. `id`, `seriesName`) 425 | * response.episodes; // contains an array of episodes 426 | * }) 427 | * .catch(error => { handle error }); 428 | * ``` 429 | * 430 | * @param {Number|String} seriesId 431 | * @param {Object} [opts] - additional options for request 432 | * @returns {Promise} 433 | * 434 | * @public 435 | */ 436 | 437 | getSeriesAllById(seriesId, opts) { 438 | return Promise.all([ 439 | this.getSeriesById(seriesId, opts), 440 | this.getEpisodesBySeriesId(seriesId, opts) 441 | ]) 442 | .then(results => { 443 | let series = results[0]; 444 | series.episodes = results[1]; 445 | return series; 446 | }); 447 | } 448 | 449 | /** 450 | * Runs a get request with the given options, useful for running custom 451 | * requests. 452 | * 453 | * ``` javascript 454 | * tvdb.sendRequest('custom/endpoint', { custom: 'options' }) 455 | * .then(response => { handle response }) 456 | * .catch(error => { handle error }); 457 | * ``` 458 | * 459 | * @param {String} path - path for http resource 460 | * @param {Object} [opts] - additional options for request 461 | * @returns {Promise} 462 | * 463 | * @public 464 | */ 465 | 466 | sendRequest(path, opts) { 467 | const options = Object.assign({}, DEFAULT_OPTS, opts); 468 | const query = Object.assign({}, options.query); 469 | const headers = Object.assign({ 470 | 'Accept': AV_HEADER, 471 | 'Accept-language': options.lang || this.language 472 | }, options.headers); 473 | 474 | const requestURL = BASE_URL + '/' + url.format({ 475 | pathname: path, 476 | query: query 477 | }); 478 | 479 | return this.getToken() 480 | .then(token => { 481 | headers['Authorization'] = `Bearer ${token}`; 482 | return request(requestURL, { headers: headers }); 483 | }) 484 | .then(res => checkHttpError(res)) 485 | .then(res => checkJsonError(res)) 486 | .then(json => getNextPages(this, json, path, options)) 487 | .then(json => json.data); 488 | } 489 | 490 | } 491 | 492 | /** 493 | * Returns the next page of a paged response. 494 | * 495 | * @param {TVDB} client TVDB client to run next request with 496 | * @param {Object} res response from previous request 497 | * @param {String} path path from previous request 498 | * @param {Object} opts additional options from previous request 499 | * @returns {Promise} 500 | * @private 501 | */ 502 | 503 | function getNextPages(client, res, path, opts) { 504 | if (!hasNextPage(res) || !opts.getAllPages) { 505 | return Promise.resolve(res); 506 | } 507 | 508 | const query = Object.assign({}, opts.query, { page: res.links.next }); 509 | const reqOpts = Object.assign({}, opts, { query: query }); 510 | 511 | return client.sendRequest(path, reqOpts) 512 | .then(nextRes => [res.data, nextRes]) 513 | .then(dataArr => { 514 | return { data: flatten(dataArr) }; 515 | }); 516 | } 517 | 518 | /** 519 | * Check response for HTTP error. Return a rejected promise if there's an error 520 | * otherwise resolve the full response object. 521 | * 522 | * @param {Object} res node-fetch response object 523 | * @returns {Promise} 524 | * @private 525 | */ 526 | 527 | function checkHttpError(res) { 528 | const contentType = res.headers.get('content-type') || ''; 529 | 530 | if (res.status && res.status >= 400 && !contentType.includes('application/json')) { 531 | let err = new Error(res.statusText); 532 | err.response = { 533 | url: res.url, 534 | status: res.status, 535 | statusText: res.statusText 536 | }; 537 | return Promise.reject(err); 538 | } 539 | return Promise.resolve(res); 540 | } 541 | 542 | /** 543 | * Check response for JSON error. Return a rejected promise if there's an error 544 | * otherwise resolve the response body as a JSON object. 545 | * 546 | * @param {Object} res node-fetch response object 547 | * @returns {Promise} 548 | * @private 549 | */ 550 | 551 | function checkJsonError(res) { 552 | return res.json().then((json) => { 553 | if (json.Error) { 554 | let err = new Error(json.Error); 555 | err.response = { 556 | url: res.url, 557 | status: res.status, 558 | statusText: res.statusText 559 | }; 560 | return Promise.reject(err); 561 | } 562 | return Promise.resolve(json); 563 | }); 564 | } 565 | 566 | /** 567 | * Perform login flow with given API Key. 568 | * 569 | * @param {String} apiKey 570 | * @returns {Promise} 571 | * @private 572 | */ 573 | 574 | function logIn(apiKey) { 575 | const opts = { 576 | method: 'POST', 577 | body: JSON.stringify({ apikey: apiKey }), 578 | headers: { 579 | 'Accept': AV_HEADER, 580 | 'Content-Type': 'application/json' 581 | } 582 | }; 583 | 584 | return request(`${BASE_URL}/login`, opts) 585 | .then(res => checkHttpError(res)) 586 | .then(res => checkJsonError(res)) 587 | .then(json => json.token); 588 | } 589 | 590 | /** 591 | * Returns true if the response has additional pages, otherwise returns false. 592 | * 593 | * @param {Object} response 594 | * @returns {Boolean} 595 | * @private 596 | */ 597 | 598 | function hasNextPage(response) { 599 | return response && response.links && response.links.next; 600 | } 601 | 602 | // 603 | // Exports 604 | // 605 | 606 | module.exports = Client; 607 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-tvdb", 3 | "description": "Node.js library for accessing TheTVDB's API", 4 | "version": "5.0.0", 5 | "author": "Edward Wellbrook ", 6 | "keywords": [ 7 | "tv", 8 | "tvdb", 9 | "thetvdb", 10 | "api", 11 | "wrapper" 12 | ], 13 | "homepage": "https://github.com/edwellbrook/node-tvdb", 14 | "main": "index.js", 15 | "files": [ 16 | "index.js", 17 | "index.d.ts" 18 | ], 19 | "engines": { 20 | "node": ">= 14.*" 21 | }, 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/edwellbrook/node-tvdb.git" 25 | }, 26 | "dependencies": { 27 | "lodash": "^4.17.11", 28 | "node-fetch": "^2.4.1" 29 | }, 30 | "devDependencies": { 31 | "@edwellbrook/minami": "^1.3.1", 32 | "chai": "^4.0.2", 33 | "chai-as-promised": "^7.0.0", 34 | "eslint": "^6.0.0", 35 | "eslint-plugin-mocha": "^6.0.0", 36 | "jsdoc": "^3.5.5", 37 | "mocha": "^6.1.4", 38 | "nock": "^11.1.0", 39 | "sinon": "^7.4.1", 40 | "sinon-chai": "^3.0.0" 41 | }, 42 | "scripts": { 43 | "test": "mocha test && eslint .", 44 | "eslint": "eslint .", 45 | "generate-docs": "rm -rf ./docs && jsdoc -c .jsdoc.json" 46 | }, 47 | "license": "MIT" 48 | } 49 | -------------------------------------------------------------------------------- /test/Client.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const chai = require('chai'); 5 | const expect = chai.expect; 6 | const nock = require('nock'); 7 | const sinon = require('sinon'); 8 | 9 | chai.use(require('chai-as-promised')); 10 | chai.use(require('sinon-chai')); 11 | 12 | const API_KEY = 'fake-api-key'; 13 | const JWT_TOKEN = 'fake-jwt-token'; 14 | const BASE_URL = 'https://api.thetvdb.com'; 15 | const LIB_VERSION = require('../package.json').version; 16 | const API_VERSION = 'v2.1.1'; 17 | const AV_HEADER = `application/vnd.thetvdb.${API_VERSION}`; 18 | const AGENT_STRING = `node-tvdb/${LIB_VERSION} (+https://github.com/edwellbrook/node-tvdb)`; 19 | 20 | const HTML_RESPONSE_HEADERS = { 'content-type': 'text/html; charset=utf-8' }; 21 | const JSON_RESPONSE_HEADERS = { 'content-type': 'application/json; charset=utf-8' }; 22 | 23 | describe('Client', () => { 24 | 25 | before((done) => { 26 | nock.disableNetConnect(); 27 | done(); 28 | }); 29 | 30 | after((done) => { 31 | nock.cleanAll(); 32 | nock.enableNetConnect(); 33 | done(); 34 | }); 35 | 36 | describe('#constructor', () => { 37 | 38 | describe('when called with no arguments', () => { 39 | 40 | it('should throw', () => { 41 | return expect(() => new TVDB()).to.throw(Error, 'API key is required'); 42 | }); 43 | 44 | }); 45 | 46 | describe('when called with api key', () => { 47 | 48 | let client; 49 | 50 | before((done) => { 51 | client = new TVDB(API_KEY); 52 | 53 | done(); 54 | }); 55 | 56 | it('should store the api key', () => { 57 | return expect(client.apiKey).to.equal(API_KEY); 58 | }); 59 | 60 | it('should set the default language (en)', () => { 61 | return expect(client.language).to.equal('en'); 62 | }); 63 | 64 | }); 65 | 66 | describe('when called with api key and language', () => { 67 | 68 | let client; 69 | 70 | before((done) => { 71 | client = new TVDB(API_KEY, 'ja'); 72 | 73 | done(); 74 | }); 75 | 76 | it('should store the api key', () => { 77 | return expect(client.apiKey).to.equal(API_KEY); 78 | }); 79 | 80 | it('should set the given language', () => { 81 | return expect(client.language).to.equal('ja'); 82 | }); 83 | 84 | }); 85 | 86 | }); 87 | 88 | describe('#getToken', () => { 89 | 90 | describe('when api key is valid', () => { 91 | 92 | let api; 93 | let client; 94 | 95 | before((done) => { 96 | api = nock(BASE_URL, { 97 | reqheaders: { 98 | 'accept': AV_HEADER, 99 | 'content-type': 'application/json' 100 | } 101 | }) 102 | .post('/login', { 103 | apikey: API_KEY 104 | }) 105 | .reply(200, { 106 | token: JWT_TOKEN 107 | }, JSON_RESPONSE_HEADERS); 108 | 109 | client = new TVDB(API_KEY); 110 | 111 | done(); 112 | }); 113 | 114 | it('should call the /login endpoint', () => { 115 | return expect(client.getToken()).to.be.fulfilled.then(() => { 116 | expect(api.isDone()).to.be.true; 117 | }); 118 | }); 119 | 120 | it('should yield the token from the api response', () => { 121 | return expect(client.getToken()).to.eventually.equal(JWT_TOKEN); 122 | }); 123 | 124 | }); 125 | 126 | describe('when api key is not valid', () => { 127 | 128 | let api; 129 | let client; 130 | 131 | before((done) => { 132 | api = nock(BASE_URL, { 133 | reqheaders: { 134 | 'accept': AV_HEADER, 135 | 'content-type': 'application/json' 136 | } 137 | }) 138 | .post('/login', { 139 | apikey: API_KEY 140 | }) 141 | .reply(401, { 142 | Error: 'API Key Required' 143 | }, JSON_RESPONSE_HEADERS); 144 | 145 | client = new TVDB(API_KEY); 146 | 147 | done(); 148 | }); 149 | 150 | it('should call the /login endpoint', () => { 151 | return expect(client.getToken()).to.be.rejected.then(() => { 152 | expect(api.isDone()).to.be.true; 153 | }); 154 | }); 155 | 156 | it('should throw the error from the api response', () => { 157 | return expect(client.getToken()).to.be.rejectedWith(Error, 'API Key Required'); 158 | }); 159 | 160 | it('should put the response on the error', () => { 161 | return client.getToken().catch((e) => { 162 | expect(e.response).to.be.instanceOf(Object); 163 | expect(e.response.url).to.equal('https://api.thetvdb.com/login'); 164 | expect(e.response.status).to.equal(401); 165 | }); 166 | }); 167 | 168 | }); 169 | 170 | describe('when the api is down', () => { 171 | 172 | let api; 173 | let client; 174 | 175 | before((done) => { 176 | api = nock(BASE_URL, { 177 | reqheaders: { 178 | 'accept': AV_HEADER, 179 | 'content-type': 'application/json' 180 | } 181 | }) 182 | .post('/login', { 183 | apikey: API_KEY 184 | }) 185 | .reply(522, '', HTML_RESPONSE_HEADERS); 186 | 187 | client = new TVDB(API_KEY); 188 | 189 | done(); 190 | }); 191 | 192 | it('should call the /login endpoint', () => { 193 | return expect(client.getToken()).to.be.rejected.then(() => { 194 | expect(api.isDone()).to.be.true; 195 | }); 196 | }); 197 | 198 | it('should throw', () => { 199 | return expect(client.getToken()).to.be.rejectedWith(Error); 200 | }); 201 | 202 | it('should put the response on the error', () => { 203 | return client.getToken().catch((e) => { 204 | expect(e.response).to.be.instanceOf(Object); 205 | expect(e.response.url).to.equal('https://api.thetvdb.com/login'); 206 | expect(e.response.status).to.equal(522); 207 | }); 208 | }); 209 | 210 | }); 211 | 212 | }); 213 | 214 | describe('#sendRequest', () => { 215 | 216 | let client; 217 | let getTokenStub; 218 | 219 | before((done) => { 220 | client = new TVDB(API_KEY); 221 | getTokenStub = sinon.stub(client, 'getToken').callsFake(() => Promise.resolve(JWT_TOKEN)); 222 | 223 | done(); 224 | }); 225 | 226 | describe('single page result', () => { 227 | 228 | let data = [ 229 | {id: 0}, 230 | {id: 1}, 231 | {id: 2} 232 | ]; 233 | 234 | let api; 235 | 236 | beforeEach((done) => { 237 | getTokenStub.resetHistory(); 238 | 239 | api = nock(BASE_URL, { 240 | reqheaders: { 241 | 'accept': AV_HEADER, 242 | 'accept-language': 'en', 243 | 'authorization': `Bearer ${JWT_TOKEN}`, 244 | 'user-agent': AGENT_STRING 245 | } 246 | }) 247 | .get('/some/path') 248 | .reply(200, { 249 | data: data 250 | }, JSON_RESPONSE_HEADERS); 251 | 252 | done(); 253 | }); 254 | 255 | afterEach((done) => { 256 | nock.cleanAll(); 257 | done(); 258 | }); 259 | 260 | it('should call getToken', () => { 261 | const promise = client.sendRequest('some/path'); 262 | return expect(promise).to.be.fulfilled.then(() => { 263 | expect(getTokenStub).to.have.been.calledOnce; 264 | }); 265 | }); 266 | 267 | it('should call the specified endpoint', () => { 268 | const promise = client.sendRequest('some/path'); 269 | return expect(promise).to.be.fulfilled.then(() => { 270 | expect(api.isDone()).to.be.true; 271 | }); 272 | }); 273 | 274 | it('should resolve to the data returned by the api', () => { 275 | const promise = client.sendRequest('some/path'); 276 | return expect(promise).to.eventually.deep.equal(data); 277 | }); 278 | 279 | }); 280 | 281 | describe('multi page result', () => { 282 | 283 | let api; 284 | let reverseApi; 285 | 286 | let data = [ 287 | {id: 0}, 288 | {id: 1}, 289 | {id: 2}, 290 | {id: 3}, 291 | {id: 4}, 292 | {id: 5} 293 | ]; 294 | 295 | beforeEach((done) => { 296 | getTokenStub.resetHistory(); 297 | 298 | api = nock(BASE_URL, { 299 | reqheaders: { 300 | 'accept': AV_HEADER, 301 | 'accept-language': 'en', 302 | 'authorization': `Bearer ${JWT_TOKEN}`, 303 | 'user-agent': AGENT_STRING 304 | } 305 | }) 306 | .get('/some/path') 307 | .reply(200, { 308 | data: data.slice(0, 3), 309 | links: { 310 | next: 2 311 | } 312 | }, JSON_RESPONSE_HEADERS) 313 | .get('/some/path?page=2') 314 | .reply(200, { 315 | data: data.slice(3, 6) 316 | }, JSON_RESPONSE_HEADERS); 317 | 318 | // data in reverse to check custom query paramters are 319 | // maintained across pages 320 | reverseApi = nock(BASE_URL, { 321 | reqheaders: { 322 | 'accept': AV_HEADER, 323 | 'accept-language': 'en', 324 | 'authorization': `Bearer ${JWT_TOKEN}`, 325 | 'user-agent': AGENT_STRING 326 | } 327 | }) 328 | .get('/another/path?params=custom') 329 | .reply(200, { 330 | data: data.slice(3, 6).reverse(), 331 | links: { 332 | next: 2 333 | } 334 | }, JSON_RESPONSE_HEADERS) 335 | .get('/another/path?params=custom&page=2') 336 | .reply(200, { 337 | data: data.slice(0, 3).reverse() 338 | }, JSON_RESPONSE_HEADERS); 339 | 340 | done(); 341 | }); 342 | 343 | afterEach((done) => { 344 | nock.cleanAll(); 345 | done(); 346 | }); 347 | 348 | it('should call getToken twice', () => { 349 | const promise = client.sendRequest('some/path'); 350 | return expect(promise).to.be.fulfilled.then(() => { 351 | expect(getTokenStub).to.have.been.calledTwice; 352 | }); 353 | }); 354 | 355 | it('should call the specified endpoint twice', () => { 356 | const promise = client.sendRequest('some/path'); 357 | return expect(promise).to.be.fulfilled.then(() => { 358 | expect(api.isDone()).to.be.true; 359 | }); 360 | }); 361 | 362 | it('should resolve to the combined data returned by the api', () => { 363 | const promise = client.sendRequest('some/path'); 364 | return expect(promise).to.eventually.deep.equal(data); 365 | }); 366 | 367 | it('should preserve any custom query parameters', () => { 368 | const promise = client.sendRequest('another/path', { 369 | query: { 370 | params: 'custom' 371 | } 372 | }); 373 | return expect(promise).to.eventually.deep.equal(data.reverse()).then(() => { 374 | expect(reverseApi.isDone()).to.be.true; 375 | }); 376 | }); 377 | 378 | }); 379 | 380 | describe('when the api returns an error', () => { 381 | 382 | let api; 383 | 384 | beforeEach((done) => { 385 | getTokenStub.resetHistory(); 386 | 387 | api = nock(BASE_URL, { 388 | reqheaders: { 389 | 'accept': AV_HEADER, 390 | 'accept-language': 'en', 391 | 'authorization': `Bearer ${JWT_TOKEN}`, 392 | 'user-agent': AGENT_STRING 393 | } 394 | }) 395 | .get('/some/path') 396 | .reply(404, { 397 | Error: 'ID Not Found' 398 | }, JSON_RESPONSE_HEADERS); 399 | 400 | done(); 401 | }); 402 | 403 | afterEach((done) => { 404 | nock.cleanAll(); 405 | done(); 406 | }); 407 | 408 | it('should call getToken', () => { 409 | const promise = client.sendRequest('some/path'); 410 | return expect(promise).to.be.rejected.then(() => { 411 | expect(getTokenStub).to.have.been.calledOnce; 412 | }); 413 | }); 414 | 415 | it('should call the specified endpoint', () => { 416 | const promise = client.sendRequest('some/path'); 417 | return expect(promise).to.be.rejected.then(() => { 418 | expect(api.isDone()).to.be.true; 419 | }); 420 | }); 421 | 422 | it('should throw the error returned by the api', () => { 423 | const promise = client.sendRequest('some/path'); 424 | return expect(promise).to.be.rejectedWith(Error, 'ID Not Found'); 425 | }); 426 | 427 | it('should put the response on the error', () => { 428 | const promise = client.sendRequest('some/path'); 429 | return promise.catch((e) => { 430 | expect(e.response).to.be.instanceOf(Object); 431 | expect(e.response.url).to.equal('https://api.thetvdb.com/some/path'); 432 | expect(e.response.status).to.equal(404); 433 | }); 434 | }); 435 | 436 | }); 437 | 438 | describe('when the api is down', () => { 439 | 440 | let api; 441 | 442 | beforeEach((done) => { 443 | getTokenStub.resetHistory(); 444 | 445 | api = nock(BASE_URL, { 446 | reqheaders: { 447 | 'accept': AV_HEADER, 448 | 'accept-language': 'en', 449 | 'authorization': `Bearer ${JWT_TOKEN}`, 450 | 'user-agent': AGENT_STRING 451 | } 452 | }) 453 | .get('/some/path') 454 | .reply(522, '', HTML_RESPONSE_HEADERS); 455 | 456 | done(); 457 | }); 458 | 459 | afterEach((done) => { 460 | nock.cleanAll(); 461 | done(); 462 | }); 463 | 464 | it('should call getToken', () => { 465 | const promise = client.sendRequest('some/path'); 466 | return expect(promise).to.be.rejected.then(() => { 467 | expect(getTokenStub).to.have.been.calledOnce; 468 | }); 469 | }); 470 | 471 | it('should call the specified endpoint', () => { 472 | const promise = client.sendRequest('some/path'); 473 | return expect(promise).to.be.rejected.then(() => { 474 | expect(api.isDone()).to.be.true; 475 | }); 476 | }); 477 | 478 | it('should throw', () => { 479 | const promise = client.sendRequest('some/path'); 480 | return expect(promise).to.be.rejectedWith(Error); 481 | }); 482 | 483 | it('should put the response on the error', () => { 484 | const promise = client.sendRequest('some/path'); 485 | return promise.catch((e) => { 486 | expect(e.response).to.be.instanceOf(Object); 487 | expect(e.response.url).to.equal('https://api.thetvdb.com/some/path'); 488 | expect(e.response.status).to.equal(522); 489 | }); 490 | }); 491 | 492 | }); 493 | 494 | }); 495 | 496 | }); 497 | -------------------------------------------------------------------------------- /test/episodeByAirDate.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#episodeByAirDate', () => { 13 | 14 | it('should return all episodes aired on "2011-10-03" from the show with id "153021"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getEpisodesByAirDate(153021, '2011-10-03').then(response => { 18 | expect(response.length).to.equal(6); 19 | 20 | [4185563, 4185564, 4185565, 4185566, 4185567, 4185568].forEach(episodeId => { 21 | return expect(response.find(episode => episode.id === episodeId)).to.exist; 22 | }); 23 | }); 24 | }); 25 | 26 | it('should return an empty array if no episodes did air on the requested date', () => { 27 | const tvdb = new TVDB(API_KEY); 28 | 29 | return expect(tvdb.getEpisodesByAirDate(153021, '2000-01-01')).to.be.rejected; 30 | }); 31 | 32 | it('should return an error if given an invalid series', () => { 33 | const tvdb = new TVDB(API_KEY); 34 | 35 | return expect(tvdb.getEpisodesByAirDate('', '2016-01-01')).to.be.rejected; 36 | }); 37 | 38 | }); 39 | -------------------------------------------------------------------------------- /test/getActorsForSeries.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe("#getActorsForSeries", () => { 13 | 14 | it('should return an array of the actors for the series with id "153021"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getActors(246151).then(response => { 18 | expect(response).to.have.length.of.at.least(5); 19 | }); 20 | }); 21 | 22 | }); 23 | -------------------------------------------------------------------------------- /test/getEpisodesBySeriesId.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getEpisodesBySeriesId', () => { 13 | 14 | it('should return the episodes of the series with id "71470"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getEpisodesBySeriesId(71470).then(response => { 18 | expect(response).to.have.length.above(0); 19 | 20 | let someEpisode = response.find(ep => ep.airedSeason === 3 && ep.airedEpisodeNumber === 22); 21 | 22 | expect(someEpisode.episodeName).to.equal('The Most Toys'); 23 | }); 24 | }); 25 | 26 | it('should allow filtering request to season and episode', () => { 27 | const tvdb = new TVDB(API_KEY); 28 | const opts = { 29 | query: { 30 | airedSeason: 3, 31 | airedEpisode: 22 32 | } 33 | }; 34 | 35 | return tvdb.getEpisodesBySeriesId(71470, opts).then(response => { 36 | expect(response).to.have.length(1); 37 | expect(response[0].episodeName).to.equal('The Most Toys'); 38 | }); 39 | }); 40 | 41 | describe('returns correct record for other languages', () => { 42 | 43 | it('if given in constructor', () => { 44 | const tvdb = new TVDB(API_KEY, 'de'); 45 | 46 | return tvdb.getEpisodesBySeriesId(71470).then(response => { 47 | expect(response).to.have.length.above(0); 48 | 49 | let someEpisode = response.find(ep => ep.airedSeason === 3 && ep.airedEpisodeNumber === 22); 50 | 51 | expect(someEpisode.episodeName).to.equal('Der Sammler'); 52 | }); 53 | }); 54 | 55 | it('if given in function call', () => { 56 | const tvdb = new TVDB(API_KEY, 'en'); 57 | 58 | return tvdb.getEpisodesBySeriesId(71470, { lang: 'de' }).then(response => { 59 | expect(response).to.have.length.above(0); 60 | 61 | let someEpisode = response.find(ep => ep.airedSeason === 3 && ep.airedEpisodeNumber === 22); 62 | 63 | expect(someEpisode.episodeName).to.equal('Der Sammler'); 64 | }); 65 | }); 66 | 67 | }); 68 | 69 | it('returns data from several pages', () => { 70 | const tvdb = new TVDB(API_KEY); 71 | 72 | return tvdb.getEpisodesBySeriesId(71663).then(response => { 73 | expect(response).to.have.length.above(600); 74 | }); 75 | }); 76 | 77 | }); 78 | -------------------------------------------------------------------------------- /test/getEpisodesSummaryBySeriesId.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getEpisodesSummaryBySeriesId', () => { 13 | 14 | it('should return an object for the series with id "176941"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getEpisodesSummaryBySeriesId(176941).then(response => { 18 | expect(response).to.be.an('object'); 19 | 20 | expect(response).to.contain.all.keys('airedEpisodes', 'airedSeasons', 'dvdEpisodes', 'dvdSeasons'); 21 | expect(response.airedEpisodes).to.be.a('String'); 22 | expect(response.airedSeasons).to.be.a('Array'); 23 | expect(response.dvdEpisodes).to.be.a('String'); 24 | expect(response.dvdSeasons).to.be.a('Array'); 25 | }); 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /test/getLanguages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getLanguages', () => { 13 | 14 | it('result should contain english and german language objects', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getLanguages().then(langs => { 18 | const enLang = langs.find(entry => entry.abbreviation === 'en'); 19 | const deLang = langs.find(entry => entry.abbreviation === 'de'); 20 | 21 | expect(enLang.abbreviation).to.equal('en'); 22 | expect(enLang.id).to.equal(7); 23 | expect(enLang.name).to.equal('English'); 24 | 25 | expect(deLang.abbreviation).to.equal('de'); 26 | expect(deLang.id).to.equal(14); 27 | expect(deLang.name).to.equal('Deutsch'); 28 | }); 29 | }); 30 | 31 | }); 32 | -------------------------------------------------------------------------------- /test/getSeasonPosters.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getSeasonPosters', () => { 13 | 14 | it('should return an array of season posters for the series with id "80379", season 10', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getSeasonPosters(80379, 10).then(response => { 18 | expect(response).to.be.an('array'); 19 | expect(response).to.not.be.empty; 20 | 21 | response.forEach(poster => { 22 | expect(poster).to.contain.all.keys('id', 'keyType', 'subKey', 'fileName', 'resolution', 'ratingsInfo', 'thumbnail'); 23 | expect(poster.keyType).to.equal('season'); 24 | expect(poster.subKey).to.equal('10'); 25 | }); 26 | }); 27 | }); 28 | 29 | }); 30 | -------------------------------------------------------------------------------- /test/getSeriesAllById.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getSeriesAllById', () => { 13 | 14 | it('should return an object of the series and its episodes with id "246151"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getSeriesAllById('71470').then(response => { 18 | expect(response.id).to.equal(71470); 19 | expect(response.seriesName).to.equal('Star Trek: The Next Generation'); 20 | expect(response.episodes).to.have.length.above(0); 21 | 22 | const firstEpisode = response.episodes.find(ep => ep.airedSeason === 1 && ep.airedEpisodeNumber === 1); 23 | expect(firstEpisode.episodeName).to.equal('Encounter at Farpoint (1)'); 24 | }); 25 | }); 26 | 27 | describe('returns the correct data for other languages', () => { 28 | 29 | it('if given in constructor', () => { 30 | const tvdb = new TVDB(API_KEY, 'de'); 31 | 32 | return tvdb.getSeriesAllById(71470).then(response => { 33 | expect(response.id).to.equal(71470); 34 | expect(response.seriesName).to.equal('Raumschiff Enterprise - Das nächste Jahrhundert'); 35 | expect(response.episodes).to.have.length.above(0); 36 | 37 | const firstEpisode = response.episodes.find(ep => ep.airedSeason === 1 && ep.airedEpisodeNumber === 1); 38 | expect(firstEpisode.episodeName).to.equal('Der Mächtige'); 39 | }); 40 | }); 41 | 42 | it('if given in function call', () => { 43 | const tvdb = new TVDB(API_KEY, 'en'); 44 | 45 | return tvdb.getSeriesAllById(71470, { lang: 'de' }).then(response => { 46 | expect(response.id).to.equal(71470); 47 | expect(response.seriesName).to.equal('Raumschiff Enterprise - Das nächste Jahrhundert'); 48 | expect(response.episodes).to.have.length.above(0); 49 | 50 | const firstEpisode = response.episodes.find(ep => ep.airedSeason === 1 && ep.airedEpisodeNumber === 1); 51 | expect(firstEpisode.episodeName).to.equal('Der Mächtige'); 52 | }); 53 | }); 54 | 55 | }); 56 | 57 | it('should return an error for a series search with an invalid id', () => { 58 | const tvdb = new TVDB(API_KEY); 59 | 60 | return expect(tvdb.getSeriesAllById('')).to.be.rejected; 61 | }); 62 | 63 | }); 64 | -------------------------------------------------------------------------------- /test/getSeriesBanner.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getSeriesBanner', () => { 13 | 14 | it('should return an array of the banners for the series with id "246151"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getSeriesBanner(71663).then(response => { 18 | expect(response).to.contain('graphical/71663'); 19 | }); 20 | }); 21 | 22 | }); 23 | -------------------------------------------------------------------------------- /test/getSeriesById.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getSeriesById', () => { 13 | 14 | it('should return an object of the series with id "246151"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getSeriesById('71663').then(response => { 18 | expect(response.id).to.equal(71663); 19 | expect(response.seriesName).to.equal('The Simpsons'); 20 | }); 21 | }); 22 | 23 | describe('returns the correct data for other languages', () => { 24 | 25 | it('if given in constructor', () => { 26 | const tvdb = new TVDB(API_KEY, 'de'); 27 | 28 | return tvdb.getSeriesById('71663') 29 | .then(response => { 30 | expect(response.id).to.equal(71663); 31 | expect(response.seriesName).to.equal('Die Simpsons'); 32 | }); 33 | }); 34 | 35 | it('if given in function call', () => { 36 | const tvdb = new TVDB(API_KEY, 'en'); 37 | 38 | return tvdb.getSeriesById('71663', { lang: 'de' }).then(response => { 39 | expect(response.id).to.equal(71663); 40 | expect(response.seriesName).to.equal('Die Simpsons'); 41 | }); 42 | }); 43 | 44 | }); 45 | 46 | }); 47 | -------------------------------------------------------------------------------- /test/getSeriesByImdbId.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getSeriesByImdbId', function () { 13 | 14 | it('should return a series with IMDB id "tt0096697"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getSeriesByImdbId('tt0096697') 18 | .then(function (response) { 19 | expect(response).to.have.length(1); 20 | expect(response[0]).to.have.property('id', 71663); 21 | expect(response[0]).to.have.property('seriesName', 'The Simpsons'); 22 | }); 23 | }); 24 | 25 | describe('returns the correct record for other languages', () => { 26 | 27 | it('if given in constructor', () => { 28 | const tvdb = new TVDB(API_KEY, 'de'); 29 | 30 | return tvdb.getSeriesByImdbId('tt0096697') 31 | .then(response => { 32 | expect(response).to.have.length(1); 33 | expect(response[0]).to.have.property('id', 71663); 34 | expect(response[0]).to.have.property('seriesName', 'Die Simpsons'); 35 | }); 36 | }); 37 | 38 | it('if given in function call', () => { 39 | const tvdb = new TVDB(API_KEY, 'en'); 40 | 41 | return tvdb.getSeriesByImdbId('tt0096697', { lang: 'de' }).then(response => { 42 | expect(response).to.have.length(1); 43 | expect(response[0]).to.have.property('id', 71663); 44 | expect(response[0]).to.have.property('seriesName', 'Die Simpsons'); 45 | }); 46 | }); 47 | 48 | }); 49 | 50 | it('should return an error for a series search with an invalid id', () => { 51 | const tvdb = new TVDB(API_KEY); 52 | 53 | return expect(tvdb.getSeriesByImdbId('')).to.be.rejected; 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /test/getSeriesByName.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getSeriesByName', () => { 13 | 14 | it('should return an array of available matches', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getSeriesByName('The Walking Dead').then(response => { 18 | expect(response).to.have.length.of.at.least(2); 19 | 20 | let theWalkingDeadShow = response.find(show => show.id === 153021); 21 | expect(theWalkingDeadShow).to.exist; 22 | expect(theWalkingDeadShow.id).to.equal(153021); 23 | expect(theWalkingDeadShow.seriesName).to.equal('The Walking Dead'); 24 | 25 | let fearTheWalkingDeadShow = response.find(show => show.id === 290853); 26 | expect(fearTheWalkingDeadShow).to.exist; 27 | expect(fearTheWalkingDeadShow.id).to.equal(290853); 28 | expect(fearTheWalkingDeadShow.seriesName).to.equal('Fear the Walking Dead'); 29 | }); 30 | }); 31 | 32 | it('should return result for unescaped series name', () => { 33 | const tvdb = new TVDB(API_KEY); 34 | 35 | return tvdb.getSeriesByName('Eastbound & Down').then(response => { 36 | expect(response).to.have.length.of.at.least(1); 37 | 38 | let show = response.find(s => s.id === 82467); 39 | expect(show).to.exist; 40 | }); 41 | }); 42 | 43 | describe('returns the correct data for other languages', () => { 44 | 45 | it('if given in constructor', () => { 46 | const tvdb = new TVDB(API_KEY, 'de'); 47 | 48 | return tvdb.getSeriesByName('Simpsons').then(response => { 49 | expect(response).to.have.length.of.at.least(1); 50 | 51 | let show = response.find(s => s.id === 71663); 52 | expect(show).to.exist; 53 | expect(show.id).to.equal(71663); 54 | expect(show.seriesName).to.equal('Die Simpsons'); 55 | }); 56 | }); 57 | 58 | it('if given in function call', () => { 59 | const tvdb = new TVDB(API_KEY); 60 | 61 | return tvdb.getSeriesByName('Simpsons', { lang: 'de' }).then(response => { 62 | expect(response).to.have.length.of.at.least(1); 63 | 64 | const show = response.find(s => s.id === 71663); 65 | expect(show).to.exist; 66 | expect(show.id).to.equal(71663); 67 | expect(show.seriesName).to.equal('Die Simpsons'); 68 | }); 69 | }); 70 | 71 | }); 72 | 73 | describe('returns 404 error when no matches are found', () => { 74 | 75 | it(`when search term is 'asdasqwerty'`, () => { 76 | const tvdb = new TVDB(API_KEY); 77 | 78 | return expect(tvdb.getSeriesByName('asdasqwerty')).to.be.rejected; 79 | }); 80 | 81 | it(`when search term is blank`, () => { 82 | const tvdb = new TVDB(API_KEY); 83 | 84 | return expect(tvdb.getSeriesByName('')).to.be.rejected; 85 | }); 86 | 87 | }); 88 | 89 | }); 90 | -------------------------------------------------------------------------------- /test/getSeriesByZap2ItId.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getSeriesByZap2ItId', function () { 13 | 14 | it('should return a series with zap2it id "EP00018693"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getSeriesByZap2ItId('EP00018693').then(function(response) { 18 | expect(response).to.have.length(1); 19 | expect(response[0]).to.have.property('id', 71663); 20 | expect(response[0]).to.have.property('seriesName', 'The Simpsons'); 21 | }); 22 | }); 23 | 24 | describe('returns the correct record for other languages', () => { 25 | 26 | it('if given in constructor', () => { 27 | const tvdb = new TVDB(API_KEY, 'de'); 28 | 29 | return tvdb.getSeriesByZap2ItId('EP00018693').then(response => { 30 | expect(response).to.have.length(1); 31 | expect(response[0]).to.have.property('id', 71663); 32 | expect(response[0]).to.have.property('seriesName', 'Die Simpsons'); 33 | }); 34 | }); 35 | 36 | it('if given in function call', () => { 37 | const tvdb = new TVDB(API_KEY, 'en'); 38 | 39 | return tvdb.getSeriesByZap2ItId('EP00018693', { lang: 'de' }).then(response => { 40 | expect(response).to.have.length(1); 41 | expect(response[0]).to.have.property('id', 71663); 42 | expect(response[0]).to.have.property('seriesName', 'Die Simpsons'); 43 | }); 44 | }); 45 | 46 | }); 47 | 48 | it('should return an error for a series search with an invalid id', () => { 49 | const tvdb = new TVDB(API_KEY); 50 | 51 | return expect(tvdb.getSeriesByZap2ItId('')).to.be.rejected; 52 | }); 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /test/getSeriesImages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getSeriesImages', () => { 13 | 14 | it('should return an array of the fanart images for the series with id "73255"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getSeriesImages(71663, 'fanart').then(response => { 18 | expect(response).to.be.an('array'); 19 | expect(response).to.not.be.empty; 20 | 21 | response.forEach(poster => { 22 | expect(poster).to.contain.all.keys('id', 'keyType', 'subKey', 'fileName', 'resolution', 'ratingsInfo', 'thumbnail'); 23 | expect(poster.keyType).to.equal('fanart'); 24 | }); 25 | }); 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /test/getSeriesPosters.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('#getSeriesPosters', () => { 13 | 14 | it('should return an array of the posters for the series with id "176941"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return tvdb.getSeriesPosters(176941).then(response => { 18 | expect(response).to.be.an('array'); 19 | expect(response).to.not.be.empty; 20 | 21 | const poster = response[0]; 22 | expect(poster).to.contain.all.keys('id', 'keyType', 'subKey', 'fileName', 'resolution', 'ratingsInfo', 'thumbnail'); 23 | expect(poster.keyType).to.equal('poster'); 24 | expect(poster.fileName).to.contain('posters/176941'); 25 | }); 26 | }); 27 | 28 | }); 29 | -------------------------------------------------------------------------------- /test/getUpdates.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe("#getUpdates", function() { 13 | 14 | it('must be called with a from Time', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | const now = Math.floor((new Date()).getTime() / 1000); 18 | const fromTime = now - (60 * 60 * 24 * 6); 19 | 20 | return tvdb.getUpdates(fromTime).then(response => { 21 | expect(response).to.have.length.above(1); 22 | expect(response[0]).to.have.deep.property('id'); 23 | expect(response[0]).to.have.deep.property('lastUpdated'); 24 | }); 25 | }); 26 | 27 | it('can be called with a toTime', () => { 28 | const tvdb = new TVDB(API_KEY); 29 | 30 | const now = Math.floor((new Date()).getTime() / 1000); 31 | const fromTime = now - (60 * 60 * 24 * 6); 32 | 33 | const toTime = fromTime + 10000; 34 | 35 | return tvdb.getUpdates(fromTime, toTime).then(response => { 36 | expect(response).to.have.length.above(1); 37 | expect(response[0]).to.have.deep.property('id'); 38 | expect(response[0]).to.have.deep.property('lastUpdated'); 39 | }); 40 | }); 41 | 42 | it('cannot be called with an invalid fromTime', () => { 43 | const tvdb = new TVDB(API_KEY); 44 | 45 | return expect(tvdb.getUpdates()).to.be.rejected; 46 | }); 47 | 48 | it('cannot be called without a fromTime', () => { 49 | const tvdb = new TVDB(API_KEY); 50 | 51 | return expect(tvdb.getUpdates('')).to.be.rejected; 52 | }); 53 | }); 54 | -------------------------------------------------------------------------------- /test/language.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const TVDB = require('..'); 4 | const API_KEY = process.env.TVDB_KEY; 5 | 6 | const chai = require('chai'); 7 | const chaiAsPromised = require('chai-as-promised'); 8 | const expect = chai.expect; 9 | 10 | chai.use(chaiAsPromised); 11 | 12 | describe('Language', () => { 13 | 14 | it('should return the default language as "en"', () => { 15 | const tvdb = new TVDB(API_KEY); 16 | 17 | return expect(tvdb.language).to.equal('en'); 18 | }); 19 | 20 | it('should return the language as "pt" if initialised with the language "pt"', () => { 21 | const tvdb = new TVDB(API_KEY, 'pt'); 22 | 23 | return expect(tvdb.language).to.equal('pt'); 24 | }); 25 | 26 | it('should return the lanaguage as "pt" if changed to "pt"', () => { 27 | const tvdb = new TVDB(API_KEY); 28 | expect(tvdb.language).to.equal('en'); 29 | 30 | tvdb.language = 'pt'; 31 | return expect(tvdb.language).to.equal('pt'); 32 | }); 33 | 34 | }); 35 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --reporter spec 2 | --slow infinity 3 | --timeout 0 4 | --------------------------------------------------------------------------------