├── .eslintrc.json ├── .gitignore ├── LICENSE ├── README.md ├── img └── tvcli.gif ├── package-lock.json ├── package.json └── src ├── cmd ├── add.js ├── help.js ├── list.js ├── lookup.js ├── remained.js ├── rm.js ├── upcoming.js ├── update.js ├── view.js ├── watch-till.js └── watch.js ├── index.js └── lib ├── episodes_to_watch.js ├── print_ep.js ├── print_series.js ├── storage.js ├── utils.js └── watcher.js /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 2017 4 | }, 5 | "env": { 6 | "es6": true, 7 | "node": true, 8 | "commonjs": true 9 | }, 10 | "extends": "eslint:recommended", 11 | "rules": { 12 | "no-use-before-define": [2, { "functions": false } ], 13 | "semi": [2, "never"], 14 | "no-underscore-dangle": 0, 15 | "no-return-assign": 0, 16 | "camelcase": 0, 17 | "no-console": 0 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Yanis 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 all 13 | 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 THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tvcl 2 | A simple show tracker CLI 3 | 4 | ![](/img/tvcli.gif?raw=true) 5 | 6 | # Intro 7 | This small tool is a CLI for [http://thetvdb.com/](http://thetvdb.com/) API. It allows to track tv shows you follow and the episodes you didn't watch yet. 8 | 9 | # Features 10 | - Lookup for shows 11 | - Viewing episodes titles, air dates, overview, and more 12 | - Marking episodes as wacthed 13 | - Showing episodes you didn't watch yet 14 | 15 | # Install 16 | 17 | ```bash 18 | $ npm install tvcl -g 19 | ``` 20 | 21 | `tvcl` uses the [http://thetvdb.com/](http://thetvdb.com/) API. In order to use it you should [get an API key](http://thetvdb.com/?tab=apiregister) and put it into `THETVDB_API_KEY` environment variable. 22 | 23 | # Usage 24 | 25 | Lookup the series title: 26 | ```bash 27 | $ tv lookup the simpsons 28 | ``` 29 | (you can use `search` alias) 30 | 31 | Add the series to local database by id: 32 | ```bash 33 | $ tv add {id} 34 | ``` 35 | 36 | List added series: 37 | ```bash 38 | $ tv list 39 | ``` 40 | 41 | View the list of episodes for specified series (--wo stands for "with overview"): 42 | ```bash 43 | $ tv view {series_id} --wo 44 | ``` 45 | (you can use `show` alias) 46 | 47 | Mark episode as watched: 48 | ``` 49 | $ tv watch {epid} 50 | ``` 51 | 52 | Mark all episodes till the specified as watched: 53 | ```bash 54 | $ tv watch-till {epid} 55 | ``` 56 | (you can use `wt` alias) 57 | 58 | Show the not-watched-yet episoded: 59 | ``` 60 | $ tv remained 61 | ``` 62 | or just 63 | ``` 64 | $ tv 65 | ``` 66 | -------------------------------------------------------------------------------- /img/tvcli.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiquest/tvcl/30bd25e0510f4820d4adb944c55c4a9ff8b55b8d/img/tvcli.gif -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tvcl", 3 | "version": "1.1.4", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.5.5", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", 10 | "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.0.0" 14 | } 15 | }, 16 | "@babel/highlight": { 17 | "version": "7.5.0", 18 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", 19 | "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", 20 | "dev": true, 21 | "requires": { 22 | "chalk": "^2.0.0", 23 | "esutils": "^2.0.2", 24 | "js-tokens": "^4.0.0" 25 | } 26 | }, 27 | "acorn": { 28 | "version": "7.1.1", 29 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", 30 | "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", 31 | "dev": true 32 | }, 33 | "acorn-jsx": { 34 | "version": "5.0.2", 35 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.2.tgz", 36 | "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==", 37 | "dev": true 38 | }, 39 | "ajv": { 40 | "version": "5.5.2", 41 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", 42 | "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", 43 | "requires": { 44 | "co": "^4.6.0", 45 | "fast-deep-equal": "^1.0.0", 46 | "fast-json-stable-stringify": "^2.0.0", 47 | "json-schema-traverse": "^0.3.0" 48 | } 49 | }, 50 | "ansi-escapes": { 51 | "version": "3.2.0", 52 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", 53 | "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", 54 | "dev": true 55 | }, 56 | "ansi-regex": { 57 | "version": "3.0.1", 58 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", 59 | "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", 60 | "dev": true 61 | }, 62 | "ansi-styles": { 63 | "version": "3.2.1", 64 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 65 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 66 | "requires": { 67 | "color-convert": "^1.9.0" 68 | } 69 | }, 70 | "argparse": { 71 | "version": "1.0.10", 72 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 73 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 74 | "dev": true, 75 | "requires": { 76 | "sprintf-js": "~1.0.2" 77 | } 78 | }, 79 | "asn1": { 80 | "version": "0.2.4", 81 | "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", 82 | "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", 83 | "requires": { 84 | "safer-buffer": "~2.1.0" 85 | } 86 | }, 87 | "assert-plus": { 88 | "version": "1.0.0", 89 | "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", 90 | "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" 91 | }, 92 | "astral-regex": { 93 | "version": "1.0.0", 94 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", 95 | "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", 96 | "dev": true 97 | }, 98 | "async": { 99 | "version": "3.0.1", 100 | "resolved": "https://registry.npmjs.org/async/-/async-3.0.1.tgz", 101 | "integrity": "sha512-ZswD8vwPtmBZzbn9xyi8XBQWXH3AvOQ43Za1KWYq7JeycrZuUYzx01KvHcVbXltjqH4y0MWrQ33008uLTqXuDw==" 102 | }, 103 | "asynckit": { 104 | "version": "0.4.0", 105 | "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", 106 | "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" 107 | }, 108 | "aws-sign2": { 109 | "version": "0.7.0", 110 | "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", 111 | "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" 112 | }, 113 | "aws4": { 114 | "version": "1.8.0", 115 | "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", 116 | "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" 117 | }, 118 | "balanced-match": { 119 | "version": "1.0.0", 120 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 121 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" 122 | }, 123 | "bcrypt-pbkdf": { 124 | "version": "1.0.2", 125 | "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", 126 | "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", 127 | "requires": { 128 | "tweetnacl": "^0.14.3" 129 | } 130 | }, 131 | "big-integer": { 132 | "version": "1.6.43", 133 | "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.43.tgz", 134 | "integrity": "sha512-9dULc9jsKmXl0Aeunug8wbF+58n+hQoFjqClN7WeZwGLh0XJUWyJJ9Ee+Ep+Ql/J9fRsTVaeThp8MhiCCrY0Jg==" 135 | }, 136 | "binary": { 137 | "version": "0.3.0", 138 | "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", 139 | "integrity": "sha1-n2BVO8XOjDOG87VTz/R0Yq3sqnk=", 140 | "requires": { 141 | "buffers": "~0.1.1", 142 | "chainsaw": "~0.1.0" 143 | } 144 | }, 145 | "bluebird": { 146 | "version": "3.4.7", 147 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", 148 | "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=" 149 | }, 150 | "brace-expansion": { 151 | "version": "1.1.11", 152 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 153 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 154 | "requires": { 155 | "balanced-match": "^1.0.0", 156 | "concat-map": "0.0.1" 157 | } 158 | }, 159 | "buffer-indexof-polyfill": { 160 | "version": "1.0.1", 161 | "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.1.tgz", 162 | "integrity": "sha1-qfuAbOgUXVQoUQznLyeLs2OmOL8=" 163 | }, 164 | "buffers": { 165 | "version": "0.1.1", 166 | "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", 167 | "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" 168 | }, 169 | "callsites": { 170 | "version": "3.1.0", 171 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 172 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 173 | "dev": true 174 | }, 175 | "caseless": { 176 | "version": "0.12.0", 177 | "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", 178 | "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" 179 | }, 180 | "chainsaw": { 181 | "version": "0.1.0", 182 | "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", 183 | "integrity": "sha1-XqtQsor+WAdNDVgpE4iCi15fvJg=", 184 | "requires": { 185 | "traverse": ">=0.3.0 <0.4" 186 | } 187 | }, 188 | "chalk": { 189 | "version": "2.4.2", 190 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 191 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 192 | "requires": { 193 | "ansi-styles": "^3.2.1", 194 | "escape-string-regexp": "^1.0.5", 195 | "supports-color": "^5.3.0" 196 | } 197 | }, 198 | "chardet": { 199 | "version": "0.7.0", 200 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 201 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", 202 | "dev": true 203 | }, 204 | "cli-cursor": { 205 | "version": "2.1.0", 206 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 207 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 208 | "dev": true, 209 | "requires": { 210 | "restore-cursor": "^2.0.0" 211 | } 212 | }, 213 | "cli-width": { 214 | "version": "2.2.0", 215 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 216 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", 217 | "dev": true 218 | }, 219 | "co": { 220 | "version": "4.6.0", 221 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 222 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" 223 | }, 224 | "color-convert": { 225 | "version": "1.9.3", 226 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 227 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 228 | "requires": { 229 | "color-name": "1.1.3" 230 | } 231 | }, 232 | "color-name": { 233 | "version": "1.1.3", 234 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 235 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 236 | }, 237 | "combined-stream": { 238 | "version": "1.0.7", 239 | "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", 240 | "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", 241 | "requires": { 242 | "delayed-stream": "~1.0.0" 243 | } 244 | }, 245 | "concat-map": { 246 | "version": "0.0.1", 247 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 248 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 249 | }, 250 | "core-util-is": { 251 | "version": "1.0.2", 252 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 253 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 254 | }, 255 | "cross-spawn": { 256 | "version": "6.0.5", 257 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 258 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 259 | "dev": true, 260 | "requires": { 261 | "nice-try": "^1.0.4", 262 | "path-key": "^2.0.1", 263 | "semver": "^5.5.0", 264 | "shebang-command": "^1.2.0", 265 | "which": "^1.2.9" 266 | }, 267 | "dependencies": { 268 | "semver": { 269 | "version": "5.7.1", 270 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 271 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 272 | "dev": true 273 | } 274 | } 275 | }, 276 | "dashdash": { 277 | "version": "1.14.1", 278 | "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", 279 | "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", 280 | "requires": { 281 | "assert-plus": "^1.0.0" 282 | } 283 | }, 284 | "debug": { 285 | "version": "4.1.1", 286 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 287 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 288 | "dev": true, 289 | "requires": { 290 | "ms": "^2.1.1" 291 | } 292 | }, 293 | "deep-is": { 294 | "version": "0.1.3", 295 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 296 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 297 | "dev": true 298 | }, 299 | "delayed-stream": { 300 | "version": "1.0.0", 301 | "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", 302 | "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" 303 | }, 304 | "doctrine": { 305 | "version": "3.0.0", 306 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 307 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 308 | "dev": true, 309 | "requires": { 310 | "esutils": "^2.0.2" 311 | } 312 | }, 313 | "duplexer2": { 314 | "version": "0.1.4", 315 | "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", 316 | "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", 317 | "requires": { 318 | "readable-stream": "^2.0.2" 319 | } 320 | }, 321 | "ecc-jsbn": { 322 | "version": "0.1.2", 323 | "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", 324 | "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", 325 | "requires": { 326 | "jsbn": "~0.1.0", 327 | "safer-buffer": "^2.1.0" 328 | } 329 | }, 330 | "emoji-regex": { 331 | "version": "7.0.3", 332 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 333 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 334 | "dev": true 335 | }, 336 | "escape-string-regexp": { 337 | "version": "1.0.5", 338 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 339 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 340 | }, 341 | "eslint": { 342 | "version": "6.2.2", 343 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.2.2.tgz", 344 | "integrity": "sha512-mf0elOkxHbdyGX1IJEUsNBzCDdyoUgljF3rRlgfyYh0pwGnreLc0jjD6ZuleOibjmnUWZLY2eXwSooeOgGJ2jw==", 345 | "dev": true, 346 | "requires": { 347 | "@babel/code-frame": "^7.0.0", 348 | "ajv": "^6.10.0", 349 | "chalk": "^2.1.0", 350 | "cross-spawn": "^6.0.5", 351 | "debug": "^4.0.1", 352 | "doctrine": "^3.0.0", 353 | "eslint-scope": "^5.0.0", 354 | "eslint-utils": "^1.4.2", 355 | "eslint-visitor-keys": "^1.1.0", 356 | "espree": "^6.1.1", 357 | "esquery": "^1.0.1", 358 | "esutils": "^2.0.2", 359 | "file-entry-cache": "^5.0.1", 360 | "functional-red-black-tree": "^1.0.1", 361 | "glob-parent": "^5.0.0", 362 | "globals": "^11.7.0", 363 | "ignore": "^4.0.6", 364 | "import-fresh": "^3.0.0", 365 | "imurmurhash": "^0.1.4", 366 | "inquirer": "^6.4.1", 367 | "is-glob": "^4.0.0", 368 | "js-yaml": "^3.13.1", 369 | "json-stable-stringify-without-jsonify": "^1.0.1", 370 | "levn": "^0.3.0", 371 | "lodash": "^4.17.14", 372 | "minimatch": "^3.0.4", 373 | "mkdirp": "^0.5.1", 374 | "natural-compare": "^1.4.0", 375 | "optionator": "^0.8.2", 376 | "progress": "^2.0.0", 377 | "regexpp": "^2.0.1", 378 | "semver": "^6.1.2", 379 | "strip-ansi": "^5.2.0", 380 | "strip-json-comments": "^3.0.1", 381 | "table": "^5.2.3", 382 | "text-table": "^0.2.0", 383 | "v8-compile-cache": "^2.0.3" 384 | }, 385 | "dependencies": { 386 | "ajv": { 387 | "version": "6.10.2", 388 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", 389 | "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", 390 | "dev": true, 391 | "requires": { 392 | "fast-deep-equal": "^2.0.1", 393 | "fast-json-stable-stringify": "^2.0.0", 394 | "json-schema-traverse": "^0.4.1", 395 | "uri-js": "^4.2.2" 396 | } 397 | }, 398 | "eslint-utils": { 399 | "version": "1.4.2", 400 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", 401 | "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", 402 | "dev": true, 403 | "requires": { 404 | "eslint-visitor-keys": "^1.0.0" 405 | } 406 | }, 407 | "fast-deep-equal": { 408 | "version": "2.0.1", 409 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 410 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", 411 | "dev": true 412 | }, 413 | "json-schema-traverse": { 414 | "version": "0.4.1", 415 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 416 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 417 | "dev": true 418 | } 419 | } 420 | }, 421 | "eslint-scope": { 422 | "version": "5.0.0", 423 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", 424 | "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", 425 | "dev": true, 426 | "requires": { 427 | "esrecurse": "^4.1.0", 428 | "estraverse": "^4.1.1" 429 | } 430 | }, 431 | "eslint-visitor-keys": { 432 | "version": "1.1.0", 433 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", 434 | "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", 435 | "dev": true 436 | }, 437 | "espree": { 438 | "version": "6.1.1", 439 | "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.1.tgz", 440 | "integrity": "sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==", 441 | "dev": true, 442 | "requires": { 443 | "acorn": "^7.0.0", 444 | "acorn-jsx": "^5.0.2", 445 | "eslint-visitor-keys": "^1.1.0" 446 | } 447 | }, 448 | "esprima": { 449 | "version": "4.0.1", 450 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 451 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 452 | "dev": true 453 | }, 454 | "esquery": { 455 | "version": "1.0.1", 456 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", 457 | "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", 458 | "dev": true, 459 | "requires": { 460 | "estraverse": "^4.0.0" 461 | } 462 | }, 463 | "esrecurse": { 464 | "version": "4.2.1", 465 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 466 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 467 | "dev": true, 468 | "requires": { 469 | "estraverse": "^4.1.0" 470 | } 471 | }, 472 | "estraverse": { 473 | "version": "4.3.0", 474 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 475 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 476 | "dev": true 477 | }, 478 | "esutils": { 479 | "version": "2.0.3", 480 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 481 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 482 | "dev": true 483 | }, 484 | "extend": { 485 | "version": "3.0.2", 486 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 487 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 488 | }, 489 | "external-editor": { 490 | "version": "3.1.0", 491 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", 492 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", 493 | "dev": true, 494 | "requires": { 495 | "chardet": "^0.7.0", 496 | "iconv-lite": "^0.4.24", 497 | "tmp": "^0.0.33" 498 | } 499 | }, 500 | "extsprintf": { 501 | "version": "1.3.0", 502 | "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", 503 | "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" 504 | }, 505 | "fast-deep-equal": { 506 | "version": "1.1.0", 507 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", 508 | "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" 509 | }, 510 | "fast-json-stable-stringify": { 511 | "version": "2.0.0", 512 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 513 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" 514 | }, 515 | "fast-levenshtein": { 516 | "version": "2.0.6", 517 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 518 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 519 | "dev": true 520 | }, 521 | "figures": { 522 | "version": "2.0.0", 523 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 524 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 525 | "dev": true, 526 | "requires": { 527 | "escape-string-regexp": "^1.0.5" 528 | } 529 | }, 530 | "file-entry-cache": { 531 | "version": "5.0.1", 532 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", 533 | "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", 534 | "dev": true, 535 | "requires": { 536 | "flat-cache": "^2.0.1" 537 | } 538 | }, 539 | "flat-cache": { 540 | "version": "2.0.1", 541 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", 542 | "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", 543 | "dev": true, 544 | "requires": { 545 | "flatted": "^2.0.0", 546 | "rimraf": "2.6.3", 547 | "write": "1.0.3" 548 | } 549 | }, 550 | "flatted": { 551 | "version": "2.0.1", 552 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", 553 | "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", 554 | "dev": true 555 | }, 556 | "forever-agent": { 557 | "version": "0.6.1", 558 | "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", 559 | "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" 560 | }, 561 | "form-data": { 562 | "version": "2.3.3", 563 | "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", 564 | "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", 565 | "requires": { 566 | "asynckit": "^0.4.0", 567 | "combined-stream": "^1.0.6", 568 | "mime-types": "^2.1.12" 569 | } 570 | }, 571 | "fs.realpath": { 572 | "version": "1.0.0", 573 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 574 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 575 | }, 576 | "fstream": { 577 | "version": "1.0.12", 578 | "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", 579 | "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", 580 | "requires": { 581 | "graceful-fs": "^4.1.2", 582 | "inherits": "~2.0.0", 583 | "mkdirp": ">=0.5 0", 584 | "rimraf": "2" 585 | } 586 | }, 587 | "functional-red-black-tree": { 588 | "version": "1.0.1", 589 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 590 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 591 | "dev": true 592 | }, 593 | "getpass": { 594 | "version": "0.1.7", 595 | "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", 596 | "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", 597 | "requires": { 598 | "assert-plus": "^1.0.0" 599 | } 600 | }, 601 | "glob": { 602 | "version": "7.1.4", 603 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", 604 | "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", 605 | "requires": { 606 | "fs.realpath": "^1.0.0", 607 | "inflight": "^1.0.4", 608 | "inherits": "2", 609 | "minimatch": "^3.0.4", 610 | "once": "^1.3.0", 611 | "path-is-absolute": "^1.0.0" 612 | } 613 | }, 614 | "glob-parent": { 615 | "version": "5.0.0", 616 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", 617 | "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", 618 | "dev": true, 619 | "requires": { 620 | "is-glob": "^4.0.1" 621 | } 622 | }, 623 | "globals": { 624 | "version": "11.12.0", 625 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 626 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 627 | "dev": true 628 | }, 629 | "graceful-fs": { 630 | "version": "4.1.15", 631 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", 632 | "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==" 633 | }, 634 | "har-schema": { 635 | "version": "2.0.0", 636 | "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", 637 | "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" 638 | }, 639 | "har-validator": { 640 | "version": "5.1.0", 641 | "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", 642 | "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", 643 | "requires": { 644 | "ajv": "^5.3.0", 645 | "har-schema": "^2.0.0" 646 | } 647 | }, 648 | "has-flag": { 649 | "version": "3.0.0", 650 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 651 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" 652 | }, 653 | "http-signature": { 654 | "version": "1.2.0", 655 | "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", 656 | "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", 657 | "requires": { 658 | "assert-plus": "^1.0.0", 659 | "jsprim": "^1.2.2", 660 | "sshpk": "^1.7.0" 661 | } 662 | }, 663 | "iconv-lite": { 664 | "version": "0.4.24", 665 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 666 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 667 | "dev": true, 668 | "requires": { 669 | "safer-buffer": ">= 2.1.2 < 3" 670 | } 671 | }, 672 | "ignore": { 673 | "version": "4.0.6", 674 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 675 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 676 | "dev": true 677 | }, 678 | "import-fresh": { 679 | "version": "3.1.0", 680 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", 681 | "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", 682 | "dev": true, 683 | "requires": { 684 | "parent-module": "^1.0.0", 685 | "resolve-from": "^4.0.0" 686 | } 687 | }, 688 | "imurmurhash": { 689 | "version": "0.1.4", 690 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 691 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 692 | "dev": true 693 | }, 694 | "inflight": { 695 | "version": "1.0.6", 696 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 697 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 698 | "requires": { 699 | "once": "^1.3.0", 700 | "wrappy": "1" 701 | } 702 | }, 703 | "inherits": { 704 | "version": "2.0.3", 705 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 706 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 707 | }, 708 | "inquirer": { 709 | "version": "6.5.2", 710 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", 711 | "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", 712 | "dev": true, 713 | "requires": { 714 | "ansi-escapes": "^3.2.0", 715 | "chalk": "^2.4.2", 716 | "cli-cursor": "^2.1.0", 717 | "cli-width": "^2.0.0", 718 | "external-editor": "^3.0.3", 719 | "figures": "^2.0.0", 720 | "lodash": "^4.17.12", 721 | "mute-stream": "0.0.7", 722 | "run-async": "^2.2.0", 723 | "rxjs": "^6.4.0", 724 | "string-width": "^2.1.0", 725 | "strip-ansi": "^5.1.0", 726 | "through": "^2.3.6" 727 | } 728 | }, 729 | "is-extglob": { 730 | "version": "2.1.1", 731 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 732 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 733 | "dev": true 734 | }, 735 | "is-fullwidth-code-point": { 736 | "version": "2.0.0", 737 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 738 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 739 | "dev": true 740 | }, 741 | "is-glob": { 742 | "version": "4.0.1", 743 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 744 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 745 | "dev": true, 746 | "requires": { 747 | "is-extglob": "^2.1.1" 748 | } 749 | }, 750 | "is-promise": { 751 | "version": "2.1.0", 752 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 753 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 754 | "dev": true 755 | }, 756 | "is-typedarray": { 757 | "version": "1.0.0", 758 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 759 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" 760 | }, 761 | "isarray": { 762 | "version": "1.0.0", 763 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 764 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 765 | }, 766 | "isexe": { 767 | "version": "2.0.0", 768 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 769 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 770 | "dev": true 771 | }, 772 | "isstream": { 773 | "version": "0.1.2", 774 | "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", 775 | "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" 776 | }, 777 | "js-tokens": { 778 | "version": "4.0.0", 779 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 780 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 781 | "dev": true 782 | }, 783 | "js-yaml": { 784 | "version": "3.13.1", 785 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 786 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 787 | "dev": true, 788 | "requires": { 789 | "argparse": "^1.0.7", 790 | "esprima": "^4.0.0" 791 | } 792 | }, 793 | "jsbn": { 794 | "version": "0.1.1", 795 | "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", 796 | "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" 797 | }, 798 | "json-schema": { 799 | "version": "0.2.3", 800 | "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", 801 | "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" 802 | }, 803 | "json-schema-traverse": { 804 | "version": "0.3.1", 805 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", 806 | "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" 807 | }, 808 | "json-stable-stringify-without-jsonify": { 809 | "version": "1.0.1", 810 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 811 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 812 | "dev": true 813 | }, 814 | "json-stringify-safe": { 815 | "version": "5.0.1", 816 | "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", 817 | "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" 818 | }, 819 | "jsprim": { 820 | "version": "1.4.1", 821 | "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", 822 | "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", 823 | "requires": { 824 | "assert-plus": "1.0.0", 825 | "extsprintf": "1.3.0", 826 | "json-schema": "0.2.3", 827 | "verror": "1.10.0" 828 | } 829 | }, 830 | "levn": { 831 | "version": "0.3.0", 832 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 833 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 834 | "dev": true, 835 | "requires": { 836 | "prelude-ls": "~1.1.2", 837 | "type-check": "~0.3.2" 838 | } 839 | }, 840 | "listenercount": { 841 | "version": "1.0.1", 842 | "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", 843 | "integrity": "sha1-hMinKrWcRyUyFIDJdeZQg0LnCTc=" 844 | }, 845 | "lodash": { 846 | "version": "4.17.15", 847 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 848 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 849 | "dev": true 850 | }, 851 | "mime-db": { 852 | "version": "1.37.0", 853 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", 854 | "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" 855 | }, 856 | "mime-types": { 857 | "version": "2.1.21", 858 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", 859 | "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", 860 | "requires": { 861 | "mime-db": "~1.37.0" 862 | } 863 | }, 864 | "mimic-fn": { 865 | "version": "1.2.0", 866 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 867 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", 868 | "dev": true 869 | }, 870 | "minimatch": { 871 | "version": "3.0.4", 872 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 873 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 874 | "requires": { 875 | "brace-expansion": "^1.1.7" 876 | } 877 | }, 878 | "minimist": { 879 | "version": "0.0.8", 880 | "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 881 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" 882 | }, 883 | "mkdirp": { 884 | "version": "0.5.1", 885 | "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 886 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 887 | "requires": { 888 | "minimist": "0.0.8" 889 | } 890 | }, 891 | "moment": { 892 | "version": "2.29.4", 893 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", 894 | "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" 895 | }, 896 | "ms": { 897 | "version": "2.1.2", 898 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 899 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 900 | "dev": true 901 | }, 902 | "mute-stream": { 903 | "version": "0.0.7", 904 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 905 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", 906 | "dev": true 907 | }, 908 | "natural-compare": { 909 | "version": "1.4.0", 910 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 911 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 912 | "dev": true 913 | }, 914 | "nice-try": { 915 | "version": "1.0.5", 916 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 917 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", 918 | "dev": true 919 | }, 920 | "oauth-sign": { 921 | "version": "0.9.0", 922 | "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", 923 | "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" 924 | }, 925 | "once": { 926 | "version": "1.4.0", 927 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 928 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 929 | "requires": { 930 | "wrappy": "1" 931 | } 932 | }, 933 | "onetime": { 934 | "version": "2.0.1", 935 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 936 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 937 | "dev": true, 938 | "requires": { 939 | "mimic-fn": "^1.0.0" 940 | } 941 | }, 942 | "optionator": { 943 | "version": "0.8.2", 944 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 945 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 946 | "dev": true, 947 | "requires": { 948 | "deep-is": "~0.1.3", 949 | "fast-levenshtein": "~2.0.4", 950 | "levn": "~0.3.0", 951 | "prelude-ls": "~1.1.2", 952 | "type-check": "~0.3.2", 953 | "wordwrap": "~1.0.0" 954 | } 955 | }, 956 | "os-tmpdir": { 957 | "version": "1.0.2", 958 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 959 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 960 | "dev": true 961 | }, 962 | "parent-module": { 963 | "version": "1.0.1", 964 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 965 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 966 | "dev": true, 967 | "requires": { 968 | "callsites": "^3.0.0" 969 | } 970 | }, 971 | "path-is-absolute": { 972 | "version": "1.0.1", 973 | "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 974 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 975 | }, 976 | "path-key": { 977 | "version": "2.0.1", 978 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 979 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 980 | "dev": true 981 | }, 982 | "performance-now": { 983 | "version": "2.1.0", 984 | "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", 985 | "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" 986 | }, 987 | "prelude-ls": { 988 | "version": "1.1.2", 989 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 990 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 991 | "dev": true 992 | }, 993 | "process-nextick-args": { 994 | "version": "2.0.0", 995 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", 996 | "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" 997 | }, 998 | "progress": { 999 | "version": "2.0.3", 1000 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1001 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1002 | "dev": true 1003 | }, 1004 | "psl": { 1005 | "version": "1.1.29", 1006 | "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", 1007 | "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" 1008 | }, 1009 | "punycode": { 1010 | "version": "1.4.1", 1011 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", 1012 | "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" 1013 | }, 1014 | "qs": { 1015 | "version": "6.5.2", 1016 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", 1017 | "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" 1018 | }, 1019 | "readable-stream": { 1020 | "version": "2.3.6", 1021 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", 1022 | "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", 1023 | "requires": { 1024 | "core-util-is": "~1.0.0", 1025 | "inherits": "~2.0.3", 1026 | "isarray": "~1.0.0", 1027 | "process-nextick-args": "~2.0.0", 1028 | "safe-buffer": "~5.1.1", 1029 | "string_decoder": "~1.1.1", 1030 | "util-deprecate": "~1.0.1" 1031 | } 1032 | }, 1033 | "regexpp": { 1034 | "version": "2.0.1", 1035 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", 1036 | "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", 1037 | "dev": true 1038 | }, 1039 | "request": { 1040 | "version": "2.88.0", 1041 | "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", 1042 | "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", 1043 | "requires": { 1044 | "aws-sign2": "~0.7.0", 1045 | "aws4": "^1.8.0", 1046 | "caseless": "~0.12.0", 1047 | "combined-stream": "~1.0.6", 1048 | "extend": "~3.0.2", 1049 | "forever-agent": "~0.6.1", 1050 | "form-data": "~2.3.2", 1051 | "har-validator": "~5.1.0", 1052 | "http-signature": "~1.2.0", 1053 | "is-typedarray": "~1.0.0", 1054 | "isstream": "~0.1.2", 1055 | "json-stringify-safe": "~5.0.1", 1056 | "mime-types": "~2.1.19", 1057 | "oauth-sign": "~0.9.0", 1058 | "performance-now": "^2.1.0", 1059 | "qs": "~6.5.2", 1060 | "safe-buffer": "^5.1.2", 1061 | "tough-cookie": "~2.4.3", 1062 | "tunnel-agent": "^0.6.0", 1063 | "uuid": "^3.3.2" 1064 | } 1065 | }, 1066 | "resolve-from": { 1067 | "version": "4.0.0", 1068 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1069 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1070 | "dev": true 1071 | }, 1072 | "restore-cursor": { 1073 | "version": "2.0.0", 1074 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 1075 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 1076 | "dev": true, 1077 | "requires": { 1078 | "onetime": "^2.0.0", 1079 | "signal-exit": "^3.0.2" 1080 | } 1081 | }, 1082 | "rimraf": { 1083 | "version": "2.6.3", 1084 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 1085 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 1086 | "requires": { 1087 | "glob": "^7.1.3" 1088 | } 1089 | }, 1090 | "run-async": { 1091 | "version": "2.3.0", 1092 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 1093 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 1094 | "dev": true, 1095 | "requires": { 1096 | "is-promise": "^2.1.0" 1097 | } 1098 | }, 1099 | "rxjs": { 1100 | "version": "6.5.2", 1101 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", 1102 | "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", 1103 | "dev": true, 1104 | "requires": { 1105 | "tslib": "^1.9.0" 1106 | } 1107 | }, 1108 | "safe-buffer": { 1109 | "version": "5.1.2", 1110 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1111 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1112 | }, 1113 | "safer-buffer": { 1114 | "version": "2.1.2", 1115 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1116 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1117 | }, 1118 | "sax": { 1119 | "version": "1.2.4", 1120 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 1121 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" 1122 | }, 1123 | "semver": { 1124 | "version": "6.3.0", 1125 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1126 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1127 | "dev": true 1128 | }, 1129 | "setimmediate": { 1130 | "version": "1.0.5", 1131 | "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", 1132 | "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" 1133 | }, 1134 | "shebang-command": { 1135 | "version": "1.2.0", 1136 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1137 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1138 | "dev": true, 1139 | "requires": { 1140 | "shebang-regex": "^1.0.0" 1141 | } 1142 | }, 1143 | "shebang-regex": { 1144 | "version": "1.0.0", 1145 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1146 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1147 | "dev": true 1148 | }, 1149 | "signal-exit": { 1150 | "version": "3.0.2", 1151 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1152 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 1153 | "dev": true 1154 | }, 1155 | "slice-ansi": { 1156 | "version": "2.1.0", 1157 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", 1158 | "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", 1159 | "dev": true, 1160 | "requires": { 1161 | "ansi-styles": "^3.2.0", 1162 | "astral-regex": "^1.0.0", 1163 | "is-fullwidth-code-point": "^2.0.0" 1164 | } 1165 | }, 1166 | "sprintf-js": { 1167 | "version": "1.0.3", 1168 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1169 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1170 | "dev": true 1171 | }, 1172 | "sshpk": { 1173 | "version": "1.15.2", 1174 | "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz", 1175 | "integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==", 1176 | "requires": { 1177 | "asn1": "~0.2.3", 1178 | "assert-plus": "^1.0.0", 1179 | "bcrypt-pbkdf": "^1.0.0", 1180 | "dashdash": "^1.12.0", 1181 | "ecc-jsbn": "~0.1.1", 1182 | "getpass": "^0.1.1", 1183 | "jsbn": "~0.1.0", 1184 | "safer-buffer": "^2.0.2", 1185 | "tweetnacl": "~0.14.0" 1186 | } 1187 | }, 1188 | "string-width": { 1189 | "version": "2.1.1", 1190 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1191 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1192 | "dev": true, 1193 | "requires": { 1194 | "is-fullwidth-code-point": "^2.0.0", 1195 | "strip-ansi": "^4.0.0" 1196 | }, 1197 | "dependencies": { 1198 | "strip-ansi": { 1199 | "version": "4.0.0", 1200 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1201 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1202 | "dev": true, 1203 | "requires": { 1204 | "ansi-regex": "^3.0.0" 1205 | } 1206 | } 1207 | } 1208 | }, 1209 | "string_decoder": { 1210 | "version": "1.1.1", 1211 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1212 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1213 | "requires": { 1214 | "safe-buffer": "~5.1.0" 1215 | } 1216 | }, 1217 | "strip-ansi": { 1218 | "version": "5.2.0", 1219 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1220 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1221 | "dev": true, 1222 | "requires": { 1223 | "ansi-regex": "^4.1.0" 1224 | }, 1225 | "dependencies": { 1226 | "ansi-regex": { 1227 | "version": "4.1.1", 1228 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", 1229 | "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", 1230 | "dev": true 1231 | } 1232 | } 1233 | }, 1234 | "strip-json-comments": { 1235 | "version": "3.0.1", 1236 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", 1237 | "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", 1238 | "dev": true 1239 | }, 1240 | "supports-color": { 1241 | "version": "5.5.0", 1242 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1243 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1244 | "requires": { 1245 | "has-flag": "^3.0.0" 1246 | } 1247 | }, 1248 | "table": { 1249 | "version": "5.4.6", 1250 | "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", 1251 | "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", 1252 | "dev": true, 1253 | "requires": { 1254 | "ajv": "^6.10.2", 1255 | "lodash": "^4.17.14", 1256 | "slice-ansi": "^2.1.0", 1257 | "string-width": "^3.0.0" 1258 | }, 1259 | "dependencies": { 1260 | "ajv": { 1261 | "version": "6.10.2", 1262 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", 1263 | "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", 1264 | "dev": true, 1265 | "requires": { 1266 | "fast-deep-equal": "^2.0.1", 1267 | "fast-json-stable-stringify": "^2.0.0", 1268 | "json-schema-traverse": "^0.4.1", 1269 | "uri-js": "^4.2.2" 1270 | } 1271 | }, 1272 | "fast-deep-equal": { 1273 | "version": "2.0.1", 1274 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", 1275 | "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", 1276 | "dev": true 1277 | }, 1278 | "json-schema-traverse": { 1279 | "version": "0.4.1", 1280 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1281 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1282 | "dev": true 1283 | }, 1284 | "string-width": { 1285 | "version": "3.1.0", 1286 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1287 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1288 | "dev": true, 1289 | "requires": { 1290 | "emoji-regex": "^7.0.1", 1291 | "is-fullwidth-code-point": "^2.0.0", 1292 | "strip-ansi": "^5.1.0" 1293 | } 1294 | } 1295 | } 1296 | }, 1297 | "text-table": { 1298 | "version": "0.2.0", 1299 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1300 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1301 | "dev": true 1302 | }, 1303 | "through": { 1304 | "version": "2.3.8", 1305 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1306 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 1307 | "dev": true 1308 | }, 1309 | "tmp": { 1310 | "version": "0.0.33", 1311 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1312 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1313 | "dev": true, 1314 | "requires": { 1315 | "os-tmpdir": "~1.0.2" 1316 | } 1317 | }, 1318 | "tough-cookie": { 1319 | "version": "2.4.3", 1320 | "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", 1321 | "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", 1322 | "requires": { 1323 | "psl": "^1.1.24", 1324 | "punycode": "^1.4.1" 1325 | } 1326 | }, 1327 | "traverse": { 1328 | "version": "0.3.9", 1329 | "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", 1330 | "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=" 1331 | }, 1332 | "tslib": { 1333 | "version": "1.10.0", 1334 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 1335 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", 1336 | "dev": true 1337 | }, 1338 | "tunnel-agent": { 1339 | "version": "0.6.0", 1340 | "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 1341 | "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", 1342 | "requires": { 1343 | "safe-buffer": "^5.0.1" 1344 | } 1345 | }, 1346 | "tweetnacl": { 1347 | "version": "0.14.5", 1348 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", 1349 | "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" 1350 | }, 1351 | "type-check": { 1352 | "version": "0.3.2", 1353 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1354 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1355 | "dev": true, 1356 | "requires": { 1357 | "prelude-ls": "~1.1.2" 1358 | } 1359 | }, 1360 | "underscore": { 1361 | "version": "1.12.1", 1362 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", 1363 | "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" 1364 | }, 1365 | "unzipper": { 1366 | "version": "0.10.0", 1367 | "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.0.tgz", 1368 | "integrity": "sha512-Vi1fHl+isVKXAiDloz8ykI+DJ9pIzDFhwxbd6ceC8XltYQfoKPhswX3yRsccXnA8tP8LPAxZO1bVWVtGE/VHaQ==", 1369 | "requires": { 1370 | "big-integer": "^1.6.17", 1371 | "binary": "~0.3.0", 1372 | "bluebird": "~3.4.1", 1373 | "buffer-indexof-polyfill": "~1.0.0", 1374 | "duplexer2": "~0.1.4", 1375 | "fstream": "^1.0.12", 1376 | "listenercount": "~1.0.1", 1377 | "readable-stream": "~2.3.6", 1378 | "setimmediate": "~1.0.4" 1379 | } 1380 | }, 1381 | "uri-js": { 1382 | "version": "4.2.2", 1383 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1384 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1385 | "dev": true, 1386 | "requires": { 1387 | "punycode": "^2.1.0" 1388 | }, 1389 | "dependencies": { 1390 | "punycode": { 1391 | "version": "2.1.1", 1392 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1393 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1394 | "dev": true 1395 | } 1396 | } 1397 | }, 1398 | "util-deprecate": { 1399 | "version": "1.0.2", 1400 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1401 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1402 | }, 1403 | "uuid": { 1404 | "version": "3.3.2", 1405 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 1406 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 1407 | }, 1408 | "v8-compile-cache": { 1409 | "version": "2.1.0", 1410 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", 1411 | "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", 1412 | "dev": true 1413 | }, 1414 | "verror": { 1415 | "version": "1.10.0", 1416 | "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", 1417 | "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", 1418 | "requires": { 1419 | "assert-plus": "^1.0.0", 1420 | "core-util-is": "1.0.2", 1421 | "extsprintf": "^1.2.0" 1422 | } 1423 | }, 1424 | "which": { 1425 | "version": "1.3.1", 1426 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1427 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1428 | "dev": true, 1429 | "requires": { 1430 | "isexe": "^2.0.0" 1431 | } 1432 | }, 1433 | "wordwrap": { 1434 | "version": "1.0.0", 1435 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1436 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 1437 | "dev": true 1438 | }, 1439 | "wrappy": { 1440 | "version": "1.0.2", 1441 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1442 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1443 | }, 1444 | "write": { 1445 | "version": "1.0.3", 1446 | "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", 1447 | "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", 1448 | "dev": true, 1449 | "requires": { 1450 | "mkdirp": "^0.5.1" 1451 | } 1452 | }, 1453 | "xml2js": { 1454 | "version": "0.4.19", 1455 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", 1456 | "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", 1457 | "requires": { 1458 | "sax": ">=0.6.0", 1459 | "xmlbuilder": "~9.0.1" 1460 | } 1461 | }, 1462 | "xmlbuilder": { 1463 | "version": "9.0.7", 1464 | "resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", 1465 | "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" 1466 | } 1467 | } 1468 | } 1469 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tvcl", 3 | "version": "1.1.4", 4 | "description": "A simple CLI for show tracking", 5 | "files": [ 6 | "src" 7 | ], 8 | "main": "./src/index.js", 9 | "bin": { 10 | "tv": "./src/index.js" 11 | }, 12 | "scripts": { 13 | "lint": "eslint ./src" 14 | }, 15 | "author": "Yanis", 16 | "license": "MIT", 17 | "dependencies": { 18 | "async": "^3.0.1", 19 | "chalk": "^2.4.2", 20 | "moment": "^2.24.0", 21 | "request": "^2.79.0", 22 | "rimraf": "^2.6.3", 23 | "underscore": "^1.8.3", 24 | "unzipper": "^0.10.0", 25 | "xml2js": "^0.4.9" 26 | }, 27 | "repository": "hiquest/tvcl", 28 | "keywords": [ 29 | "tv", 30 | "series", 31 | "shows", 32 | "tracker", 33 | "thetvdb" 34 | ], 35 | "preferGlobal": "true", 36 | "engines": { 37 | "node": ">=6.0.0" 38 | }, 39 | "devDependencies": { 40 | "eslint": "^6.2.2" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/cmd/add.js: -------------------------------------------------------------------------------- 1 | const {error} = require('../lib/utils') 2 | const storage = require('../lib/storage') 3 | const view = require('./view') 4 | 5 | function add(id) { 6 | if (!id) { 7 | error('Please specify Series id') 8 | } 9 | storage.add(id, () => view(id)) 10 | } 11 | 12 | module.exports = add 13 | -------------------------------------------------------------------------------- /src/cmd/help.js: -------------------------------------------------------------------------------- 1 | const {bold} = require('chalk') 2 | 3 | function help() { 4 | console.log(`\n${bold('tv')} is a simple script that helps keeping track of the shows and episodes (using thetvdb.com API as a source).`) 5 | console.log(`You need to get the API key (which is free at http://thetvdb.com/?tab=apiregister) and set an environment variable ${bold('THETVDB_API_KEY')}.`) 6 | console.log("\n") 7 | console.log(`Usage: ${bold('tv')} {params}`) 8 | console.log("\n") 9 | console.log(`${bold('lookup')} or ${bold('search')} `) 10 | console.log(" look up a show") 11 | console.log(`${bold('add')} <id>`) 12 | console.log(" add a show to your list") 13 | console.log(`${bold('update')}`) 14 | console.log(" update the local episodes data (you should do it from time to time)") 15 | console.log(`${bold('list')}`) 16 | console.log(" list your tv shows") 17 | console.log(`${bold('view')} or ${bold('show')} <id>`) 18 | console.log(" show the list of episodes for a specified show") 19 | console.log(`${bold('rm')} <id>`) 20 | console.log(" remove a tv show from the local database") 21 | console.log(`${bold('watch')} <episode-id>`) 22 | console.log(" mark a specific episode as watched") 23 | console.log(`${bold('watch-till')} or ${bold('wt')} <episode-id>`) 24 | console.log(" mark a specific episode as watched and all of the episodes before it") 25 | console.log(`${bold('remained')} ( or with no command )`) 26 | console.log(" show episodes remained to be watched (but only the ones that are out already)") 27 | console.log(`${bold('help')}`) 28 | console.log(" print what you are now looking at") 29 | console.log("\n") 30 | } 31 | 32 | module.exports = help 33 | -------------------------------------------------------------------------------- /src/cmd/list.js: -------------------------------------------------------------------------------- 1 | const {error, pr} = require('../lib/utils') 2 | const storage = require('../lib/storage') 3 | const printSeries = require('../lib/print_series') 4 | 5 | function list() { 6 | storage.readAll(() => { 7 | const series = storage.all() 8 | if (series.length) { 9 | pr("") 10 | pr("List of tracked shows (use `tv update` to sync)") 11 | pr("") 12 | storage 13 | .all() 14 | .map((s) => s['Data']['Series'][0]) 15 | .forEach((s) => printSeries(s, false, true)) 16 | pr("") 17 | } else { 18 | return error("No Series Added Yet. Try `tv lookup <title>` first. And then `tv add <id>`") 19 | } 20 | }) 21 | } 22 | 23 | module.exports = list 24 | -------------------------------------------------------------------------------- /src/cmd/lookup.js: -------------------------------------------------------------------------------- 1 | const {xmlReq, error, pr} = require('../lib/utils') 2 | const printSeries = require('../lib/print_series') 3 | 4 | const API_HOST = 'http://thetvdb.com' 5 | 6 | // API URL 7 | const api_lookup = (q) => `${API_HOST}/api/GetSeries.php?seriesname=${q}` 8 | 9 | function lookup(...args) { 10 | const q = args.join(' ') 11 | if (!q) { 12 | return error('Please specify title to look for') 13 | } 14 | xmlReq(api_lookup(q), (res) => { 15 | if (!res['Data']['Series']) { 16 | return error('Could not find any show') 17 | } 18 | pr() 19 | res['Data']['Series'].forEach((s) => printSeries(s)) 20 | 21 | pr("To add a show type `tv add <id>`") 22 | pr() 23 | }) 24 | } 25 | 26 | module.exports = lookup 27 | -------------------------------------------------------------------------------- /src/cmd/remained.js: -------------------------------------------------------------------------------- 1 | const { bold } = require('chalk') 2 | 3 | const EpisodesToWatch = require('../lib/episodes_to_watch') 4 | const { pr } = require('../lib/utils') 5 | const printEp = require('../lib/print_ep') 6 | 7 | function rem(param) { 8 | 9 | EpisodesToWatch.all((serieses) => { 10 | 11 | if (!serieses || !serieses.length) return printStub() 12 | 13 | const showOverview = param == '--with-overview' || param == '--wo' 14 | serieses 15 | .filter(s => s.episodes.length > 0) 16 | .forEach((s) => { 17 | printSeries(s, showOverview) 18 | }) 19 | }) 20 | } 21 | 22 | function printStub() { 23 | pr(" ") 24 | pr('✓ All done. Try `tv lookup <title>` to search for shows') 25 | pr(" ") 26 | } 27 | 28 | function printSeries(s, showOverview) { 29 | pr(" ") 30 | pr(bold(s.seriesTitle)) 31 | pr(" ") 32 | s.episodes.forEach(e => printEp(e, showOverview)) 33 | pr(" ") 34 | } 35 | 36 | module.exports = rem 37 | -------------------------------------------------------------------------------- /src/cmd/rm.js: -------------------------------------------------------------------------------- 1 | const storage = require('../lib/storage') 2 | const {pr} = require('../lib/utils') 3 | 4 | function rm(id) { 5 | storage.rm(id, () => { 6 | pr() 7 | pr('✓ Show has been removed') 8 | pr() 9 | }) 10 | } 11 | 12 | module.exports = rm 13 | -------------------------------------------------------------------------------- /src/cmd/upcoming.js: -------------------------------------------------------------------------------- 1 | const { bold } = require('chalk') 2 | 3 | const EpisodesToWatch = require('../lib/episodes_to_watch') 4 | const { pr } = require('../lib/utils') 5 | const printEp = require('../lib/print_ep') 6 | 7 | function rem(param) { 8 | 9 | EpisodesToWatch.upcoming((serieses) => { 10 | 11 | if (!serieses || !serieses.length) return printStub() 12 | 13 | const showOverview = param == '--with-overview' || param == '--wo' 14 | serieses 15 | .filter(s => s.episodes.length > 0) 16 | .forEach((s) => { 17 | printSeries(s, showOverview) 18 | }) 19 | }) 20 | } 21 | 22 | function printStub() { 23 | pr(" ") 24 | pr('✓ No upcoming edpisodes (in 2 months). Try `tv lookup <title>` to search for shows') 25 | pr(" ") 26 | } 27 | 28 | function printSeries(s, showOverview) { 29 | pr(" ") 30 | pr(bold(s.seriesTitle)) 31 | pr(" ") 32 | s.episodes.forEach(e => printEp(e, showOverview)) 33 | pr(" ") 34 | } 35 | 36 | module.exports = rem 37 | -------------------------------------------------------------------------------- /src/cmd/update.js: -------------------------------------------------------------------------------- 1 | const {bold} = require('chalk') 2 | const storage = require('../lib/storage') 3 | const {pr} = require('../lib/utils') 4 | 5 | function update() { 6 | storage.update(() => { 7 | pr() 8 | pr(`Update all shows...${bold('OK')}`) 9 | pr() 10 | }) 11 | } 12 | 13 | module.exports = update 14 | -------------------------------------------------------------------------------- /src/cmd/view.js: -------------------------------------------------------------------------------- 1 | const {error, pr} = require('../lib/utils') 2 | const storage = require('../lib/storage') 3 | const printEp = require('../lib/print_ep') 4 | 5 | function view(id, param) { 6 | if (!id) { 7 | return error('Please specify series id') 8 | } 9 | storage.series(id, (result) => { 10 | const episodes = result['Data']['Episode'] 11 | const showOverview = param == '--with-overview' || param == '--wo' 12 | pr() 13 | episodes.forEach(e => printEp(e, showOverview)) 14 | pr() 15 | }) 16 | } 17 | 18 | module.exports = view 19 | -------------------------------------------------------------------------------- /src/cmd/watch-till.js: -------------------------------------------------------------------------------- 1 | const moment = require('moment') 2 | 3 | const {error} = require('../lib/utils') 4 | const watcher = require('../lib/watcher') 5 | const storage = require('../lib/storage') 6 | 7 | function till(epId) { 8 | if (!epId) { 9 | return error("Please specify episode id") 10 | } 11 | storage.readAll(() => { 12 | const episode = storage.findEp(epId) 13 | const epMomemnt = moment(episode['FirstAired'][0]) 14 | 15 | const series = storage.findSeriesByEp(epId) 16 | const episodes = series['Data']['Episode'] 17 | episodes.forEach((e) => { 18 | const aired = e['FirstAired'][0] 19 | if (!aired) { 20 | return 21 | } 22 | const m = moment(aired) 23 | if (m.isBefore(epMomemnt)) { 24 | watcher.watch(e['id'][0]) 25 | } 26 | }) 27 | watcher.save() 28 | }) 29 | } 30 | 31 | module.exports = till 32 | -------------------------------------------------------------------------------- /src/cmd/watch.js: -------------------------------------------------------------------------------- 1 | const {error} = require('../lib/utils') 2 | const watcher = require('../lib/watcher') 3 | 4 | function watch(...ids) { 5 | if (!ids.length) { 6 | return error("Specify episode id") 7 | } 8 | ids.forEach((id) => watcher.watch(id)) 9 | watcher.save() 10 | } 11 | 12 | module.exports = watch 13 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Available commands (array for aliases) 4 | const CMDS = [ 5 | ["lookup", "search"], 6 | "add", 7 | "list", 8 | ["view", "show"], 9 | "watch", 10 | ["watch-till", "wt"], 11 | ["rm", "remove"], 12 | "update", 13 | "remained", 14 | "upcoming", 15 | "help" 16 | ] 17 | 18 | ensureTvdbKey() 19 | const [cmd, args] = readArgs() 20 | const mod = figureModule(cmd) 21 | require(`./cmd/${mod}`)(...args) 22 | 23 | function ensureTvdbKey() { 24 | if (!process.env.THETVDB_API_KEY) { 25 | throw "Please add 'THETVDB_API_KEY' env variable. You can get it here: http://thetvdb.com/?tab=apiregister" 26 | } 27 | } 28 | 29 | function readArgs() { 30 | const cmd = process.argv[2] || "remained" 31 | const args = process.argv.slice(3) 32 | return [ cmd, args ] 33 | } 34 | 35 | function figureModule() { 36 | const mod = CMDS.find((cmds) => { 37 | return Array.isArray(cmds) && cmds.indexOf(cmd) > -1 || cmds == cmd 38 | }) || "help" 39 | 40 | return Array.isArray(mod) ? mod[0] : mod 41 | } 42 | -------------------------------------------------------------------------------- /src/lib/episodes_to_watch.js: -------------------------------------------------------------------------------- 1 | const moment = require('moment') 2 | 3 | const storage = require('./storage') 4 | const watcher = require('./watcher') 5 | 6 | function all(cb) { 7 | return filterEps((e) => { 8 | return !watcher.isWatched(e) 9 | && moment(e['FirstAired'][0]).isBefore(moment()) 10 | }, cb) 11 | } 12 | 13 | function upcoming(cb) { 14 | return filterEps((e) => { 15 | const aired = moment(e['FirstAired'][0]) 16 | return aired.isBefore(moment().add(2, 'M')) && aired.isAfter(moment()) 17 | }, cb) 18 | } 19 | 20 | function filterEps(filterFn, cb) { 21 | storage.readAll(() => { 22 | const serieses = storage.all() 23 | if (!serieses.length) { 24 | cb(null) 25 | return 26 | } 27 | 28 | const out = serieses 29 | .map((s) => { 30 | const eps = s['Data']['Episode'] 31 | .filter(e => !watcher.isWatched(e)) 32 | .filter(filterFn) 33 | 34 | return { 35 | seriesTitle: s['Data']['Series'][0]['SeriesName'][0], 36 | episodes: eps 37 | } 38 | }) 39 | .filter(s => s.episodes.length > 0) 40 | cb(out) 41 | }) 42 | } 43 | 44 | module.exports = { all, upcoming } 45 | -------------------------------------------------------------------------------- /src/lib/print_ep.js: -------------------------------------------------------------------------------- 1 | const {bold, gray, yellow} = require('chalk') 2 | const watcher = require('./watcher') 3 | const {pr} = require('./utils') 4 | 5 | function printOverview (e) { 6 | let overview = e['Overview'] && e['Overview'][0] 7 | if (overview) { 8 | if (overview.length > 256) { 9 | overview = overview.substring(0, 256) + '...' 10 | } 11 | pr(gray(overview)) 12 | } 13 | } 14 | 15 | function printEp(e, showOverview = false) { 16 | const watched = watcher.isWatched(e) 17 | const id = e['id'][0] 18 | const season = e['SeasonNumber'][0] 19 | const number = e['EpisodeNumber'][0] 20 | let name = e['EpisodeName'][0] 21 | if (!watched) { 22 | name = yellow(name) 23 | } 24 | const aired = e['FirstAired'][0] || 'TBA' 25 | const code = bold(`S${season}E${number}`) 26 | let line = `${id} ${code} ${name}, ${aired}` 27 | if (watched) { 28 | line = `✓ ${line}` 29 | line = gray(line) 30 | } 31 | pr(line) 32 | if (showOverview) { 33 | printOverview(e) 34 | pr("") 35 | } 36 | } 37 | 38 | module.exports = printEp 39 | -------------------------------------------------------------------------------- /src/lib/print_series.js: -------------------------------------------------------------------------------- 1 | const {bold, gray} = require('chalk') 2 | const {pr} = require('./utils') 3 | 4 | function printOverview(s) { 5 | let overview = s['Overview'] && s['Overview'][0] 6 | if (overview) { 7 | if (overview.length > 256) { 8 | overview = overview.substring(0, 256) + '...' 9 | } 10 | pr(gray(overview)) 11 | } 12 | } 13 | 14 | function printSeries(s, overview = true, noSpace = false) { 15 | const id = s['seriesid'] || s['id'][0] 16 | const name = bold(s['SeriesName']) 17 | const aired = s['FirstAired'] || '?' 18 | const resLine = `${id} ${name} (since ${aired})` 19 | pr(resLine) 20 | if (overview) { 21 | printOverview(s) 22 | } 23 | if (!noSpace) { 24 | pr() 25 | } 26 | } 27 | 28 | module.exports = printSeries 29 | -------------------------------------------------------------------------------- /src/lib/storage.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const xml2js = require('xml2js') 3 | const async = require('async') 4 | const path = require('path') 5 | const unzip = require('unzipper') 6 | const _ = require('underscore') 7 | const rimraf = require('rimraf') 8 | 9 | const {error, download} = require('./utils') 10 | 11 | const KEY = process.env.THETVDB_API_KEY 12 | const API_HOST = 'http://thetvdb.com' 13 | const BASE = `${process.env['HOME']}/.tvcl` 14 | const BASE_STORE = `${BASE}/store` 15 | 16 | const storage = {} 17 | 18 | function findEp(epId) { 19 | const series = findSeriesByEp(epId) 20 | if (!series) { 21 | return undefined 22 | } 23 | const episodes = series['Data']['Episode'] 24 | return _.find(episodes, e => e['id'][0] == epId ) 25 | } 26 | 27 | function findSeriesByEp(epId) { 28 | const ids = Object.keys(storage) 29 | const id = _.find(ids, (id) => { 30 | const episodes = storage[id]['Data']['Episode'] 31 | return _.some(episodes, e => e['id'][0] == epId ) 32 | }) 33 | return storage[id] 34 | } 35 | 36 | function readSeries(id, cb) { 37 | const xml_file = `${BASE_STORE}/${id}/en.xml` 38 | if (!fs.existsSync(xml_file)) { error("Could not find the show: maybe `add` it first?") } 39 | const str = fs.readFileSync(xml_file) 40 | const parser = new xml2js.Parser() 41 | parser.parseString(str, function(err, result) { 42 | if (err) { return error(err) } 43 | storage[id] = result 44 | return cb('', result) 45 | }) 46 | } 47 | 48 | function available() { 49 | return fs 50 | .readdirSync(BASE_STORE) 51 | .filter(f => fs.statSync(path.join(BASE_STORE, f)).isDirectory()) 52 | } 53 | 54 | function readAll(cb) { 55 | if (!fs.existsSync(BASE_STORE)) { 56 | return error("No shows added. Try `tv lookup <title>` first. And then `tv add <id>`") 57 | } 58 | return async.map(available(), readSeries, cb) 59 | } 60 | 61 | function series(id, cb) { 62 | if (storage[id]) { 63 | return cb(storage[id]) 64 | } else { 65 | return readSeries(id, () => cb(storage[id])) 66 | } 67 | } 68 | 69 | function add(id, cb) { 70 | const zip_url = id => `${API_HOST}/api/${KEY}/series/${id}/all/en.zip` 71 | if (!fs.existsSync(BASE)) { fs.mkdirSync(BASE) } 72 | if (!fs.existsSync(BASE_STORE)) { fs.mkdirSync(BASE_STORE) } 73 | 74 | const zipFile = `${BASE_STORE}/${id}.zip` 75 | 76 | return download(zip_url(id), zipFile, () => 77 | fs.createReadStream(zipFile) 78 | .pipe(unzip.Extract({path: `${BASE_STORE}/${id}`})) 79 | .on('close', () => cb()) 80 | ) 81 | } 82 | 83 | function rm(id, cb) { 84 | let files = [ 85 | `${BASE_STORE}/${id}.zip`, 86 | `${BASE_STORE}/${id}` 87 | ] 88 | return async.map(files, rimraf, cb) 89 | } 90 | 91 | function updateOne(id, cb) { 92 | rm(id, () => 93 | add(id, () => cb()) 94 | ) 95 | } 96 | 97 | function update(cb) { 98 | return async.map(available(), updateOne, cb) 99 | } 100 | 101 | // Should be used only after readAll! 102 | function all(){ 103 | return Object.keys(storage).map(k => storage[k]) 104 | } 105 | 106 | module.exports = { 107 | series, 108 | readAll, 109 | findSeriesByEp, 110 | findEp, 111 | add, 112 | all, 113 | rm, 114 | update 115 | } 116 | -------------------------------------------------------------------------------- /src/lib/utils.js: -------------------------------------------------------------------------------- 1 | const req = require('request') 2 | const {parseString} = require('xml2js') 3 | const http = require('http') 4 | const fs = require('fs') 5 | 6 | function pr(msg = "") { 7 | console.log(` ${msg}`) 8 | } 9 | 10 | function error(msg) { 11 | pr(" ") 12 | pr(msg) 13 | pr(" ") 14 | } 15 | 16 | function xmlReq(url, cb) { 17 | req(url, (err, resp, body) => { 18 | if (err) { 19 | return error(`Error while req ${url}: ${err}`) 20 | } 21 | if (resp.statusCode != 200) { 22 | return error(`Error while req ${url}: code — ${resp.statusCode}`) 23 | } 24 | parseString(body, (err, res) => { 25 | if (err) { 26 | return error(`Error parsing response from ${url}: ${err}`) 27 | } 28 | cb(res) 29 | }) 30 | }) 31 | } 32 | 33 | function download(url, to, cb) { 34 | const file = fs.createWriteStream(to) 35 | http.get(url, (resp) => { 36 | resp.pipe(file) 37 | file.on('finish', () => file.close(cb) ) 38 | }) 39 | } 40 | 41 | module.exports = {error, xmlReq, download, pr} 42 | -------------------------------------------------------------------------------- /src/lib/watcher.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | 3 | const BASE = `${process.env['HOME']}/.tvcl` 4 | const WATCH_FILE = `${BASE}/watch.json` 5 | 6 | let cache = undefined 7 | 8 | function read() { 9 | if (fs.existsSync(WATCH_FILE)) { 10 | cache = JSON.parse(fs.readFileSync(WATCH_FILE)) 11 | } else { 12 | cache = {} 13 | } 14 | } 15 | 16 | function watch(epId) { 17 | if (!cache) { 18 | read() 19 | } 20 | cache[epId] = true 21 | } 22 | 23 | function save() { 24 | if (!cache) { 25 | read() 26 | } 27 | fs.writeFileSync(WATCH_FILE, JSON.stringify(cache)) 28 | } 29 | 30 | function isWatched(e) { 31 | if (!cache) { 32 | read() 33 | } 34 | const id = e['id'][0] 35 | return !!cache[id] 36 | } 37 | 38 | module.exports = { watch, save, isWatched } 39 | --------------------------------------------------------------------------------