ani-cli-npm 2.0.3 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.MD CHANGED
@@ -36,6 +36,7 @@ npx ani-cli-npm@latest
36
36
  ```
37
37
  git clone https://github.com/Bumpkin-Pi/ani-cli-npm.git
38
38
  cd ani-cli-npm
39
+ npm i
39
40
  npm run build
40
41
  npm run start
41
42
  ```
@@ -69,4 +70,5 @@ npm run start
69
70
  #### Download folder - The folder in which to download episodes.
70
71
 
71
72
 
72
- ## Happy watching :)
73
+
74
+ <a href="https://www.buymeacoffee.com/bumpkinpi" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
package/bin/Anime.js CHANGED
@@ -11,24 +11,40 @@ const open = require("open");
11
11
  const PlayerController = require("media-player-controller");
12
12
  const dl = require("download-file-with-progressbar");
13
13
  const chalk = require("chalk");
14
- // const gogohd_url="https://gogohd.net/"
15
- const base_url = "https://animixplay.to";
16
14
  class Anime {
15
+ /*
16
+ Class for handling a show/film
17
+
18
+ Stores anime dpage links assigned with anime_id.
19
+
20
+ Initialised with Anime.init()
21
+
22
+ */
17
23
  id = "";
18
24
  episode_list = [];
19
25
  player = 0;
20
26
  async init(anime_id, cache_folder) {
27
+ /*
28
+ Initiate Anime object
29
+
30
+ Will first search cache folder for cache file (this will contain id and dpage links)
31
+
32
+ If no cache is found, it will use get_ep_bases(anime_id) to get links. (Webscrapes from animixplay.to), then creates cache
33
+
34
+ anime_id:
35
+ */
21
36
  let cache_object = (0, cache_1.search_cache)(cache_folder, anime_id);
22
37
  this.id = anime_id;
23
38
  if (cache_object == 0) {
24
- await this.get_ap_bases(anime_id);
39
+ await this.get_ep_bases(this.id);
40
+ (0, cache_1.new_cache)(cache_folder, this);
25
41
  }
26
42
  else {
27
43
  try {
28
44
  this.episode_list = cache_object.episode_list;
29
45
  }
30
46
  catch {
31
- await this.get_ap_bases(anime_id);
47
+ await this.get_ep_bases(this.id);
32
48
  }
33
49
  }
34
50
  return 0;
@@ -49,8 +65,12 @@ class Anime {
49
65
  }
50
66
  return link;
51
67
  }
52
- async get_ap_bases(anime_id) {
53
- let html = (await ((0, curl_1.curl)(base_url + "/v1/" + anime_id))).split("\n");
68
+ async get_ep_bases(anime_id) {
69
+ /*
70
+ Scrapes animixplay.to for dpage links.
71
+ returns array with all dpage links
72
+ */
73
+ let html = (await ((0, curl_1.curl)("https://animixplay.to/v1/" + anime_id))).split("\n"); //POTENTIAL BREAK POINT. animixplay.to may change domain address
54
74
  let lines = "";
55
75
  for (let x in html) {
56
76
  if ((0, regex_1.RegexParse)(html[x], "*<div id=\"epslistplace\"*")) {
@@ -65,6 +85,20 @@ class Anime {
65
85
  }
66
86
  }
67
87
  async play_head(episode, config, config_dir) {
88
+ /*
89
+ # Starts play cascade.
90
+
91
+ ## Takes in:
92
+ ### Episode number, counding from 0
93
+ ### Config object
94
+ ### Config save directory
95
+
96
+ - If config.player is set to MPV or VLC, it will use the media-player-controller package.
97
+
98
+ - If set to Browser, it will use the "open" packer.
99
+
100
+ - If set to Link, it will simply print the media stream link to console, primarily for debuting peruses.
101
+ */
68
102
  console.clear();
69
103
  console.log(`Playing ${this.id} episode ${episode + 1}`);
70
104
  switch (config.player) {
@@ -148,6 +182,10 @@ class Anime {
148
182
  }
149
183
  }
150
184
  async play(episode, config, config_dir) {
185
+ /*
186
+ # Continues play cascade
187
+ ## Continues on from play_head()
188
+ */
151
189
  console.clear();
152
190
  console.log(`Playing ${this.id} episode ${episode + 1}`);
153
191
  if (this.player == 0) {
@@ -216,42 +254,46 @@ class Anime {
216
254
  }
217
255
  }
218
256
  }
219
- async download(episode, download_folder) {
220
- // @ts-ignore
221
- let ep_link = await this.get_episode_link(episode);
222
- let file_name = `${this.id}-${episode + 1}.mp4`;
223
- if (ep_link.includes(".m3u8"))
224
- console.log(chalk.red("Warning: Animixplay will download an m3u8 file. This will require some extra steps to play. It is advised to use a 3rd party website or tool to download these from the link."));
225
- // @ts-ignore
226
- let option = {
227
- filename: ep_link.includes("m3u8") ? file_name.replace("mp4", "m3u8") : file_name,
228
- dir: download_folder,
257
+ async download(episode, download_folder, final_ep) {
258
+ /*
259
+ ## Downloads an episode (counting from 0) to download_folder, with progress bar.
260
+ */
261
+ try {
229
262
  // @ts-ignore
230
- onDone: (info) => {
231
- // @ts-ignore
232
- console.log(chalk.green(`\n -- Download finished -- \nLocation: ${info.path}. Size: ${Math.round(info.size / 100000) * 10} Bytes\n`) + ">");
233
- return 0;
234
- },
235
- // @ts-ignore
236
- onError: (err) => {
237
- console.log(chalk.red('error', err));
238
- },
263
+ let ep_link = await this.get_episode_link(episode);
264
+ let file_name = `${this.id}-${episode + 1}.mp4`;
265
+ if (ep_link.includes(".m3u8"))
266
+ console.log(chalk.red("Warning: Animixplay will download an m3u8 file. This will require some extra steps to play. It is advised to use a 3rd party website or tool to download these from the link."));
239
267
  // @ts-ignore
240
- onProgress: (curr, total) => {
241
- process.stdout.clearLine(0);
242
- process.stdout.cursorTo(0);
243
- process.stdout.write("\x1b[32m -- " + (curr / total * 100).toFixed(2) + "% " + "#".repeat(Math.ceil((curr / total) * ((process.stdout.columns - 20) / 1.5))) + "~".repeat(Math.ceil(((process.stdout.columns - 20) / 1.5) - (curr / total) * ((process.stdout.columns - 20) / 1.5))) + " -- \x1b[0m");
244
- }
245
- };
246
- //console.log((`${option.dir}/${option.filename}`))
247
- return await dl(ep_link, option);
248
- }
249
- async bulk_download(start_episode, end_episode, download_folder) {
250
- let downloaders = [];
251
- for (let episode = start_episode; episode <= end_episode; episode++) {
252
- downloaders.push(await this.download(episode, download_folder));
268
+ let option = {
269
+ filename: (ep_link.includes("m3u8") ? file_name.replace("mp4", "m3u8") : file_name),
270
+ dir: download_folder,
271
+ onDone: (final_ep > episode) ? ((info) => {
272
+ // @ts-ignore
273
+ console.log(chalk.green(`\n -- 1Download finished -- \nLocation: ${info.path}. Size: ${Math.round(info.size / 100000) * 10} Bytes\n`));
274
+ this.download(episode + 1, download_folder, final_ep);
275
+ }) : ((info) => {
276
+ // @ts-ignore
277
+ console.log(chalk.green(`\n -- 2Download finished -- \n${info.path}. Size: ${Math.round(info.size / 100000) * 10} Bytes\n`));
278
+ }),
279
+ // @ts-ignore
280
+ onError: (err) => {
281
+ console.log(chalk.red('error', err));
282
+ this.download(episode, download_folder, final_ep);
283
+ },
284
+ // @ts-ignore
285
+ onProgress: (curr, total) => {
286
+ process.stdout.clearLine(0);
287
+ process.stdout.cursorTo(0);
288
+ process.stdout.write("\x1b[32m -- " + (curr / total * 100).toFixed(2) + "% " + "#".repeat(Math.ceil((curr / total) * ((process.stdout.columns - 20) / 1.5))) + "~".repeat(Math.ceil(((process.stdout.columns - 20) / 1.5) - (curr / total) * ((process.stdout.columns - 20) / 1.5))) + " -- \x1b[0m");
289
+ }
290
+ };
291
+ //console.log((`${option.dir}/${option.filename}`))
292
+ return await dl(ep_link, option);
293
+ }
294
+ catch {
295
+ this.download(episode, download_folder, final_ep);
253
296
  }
254
- return await Promise.all(downloaders);
255
297
  }
256
298
  }
257
299
  exports.Anime = Anime;
package/bin/cache.js CHANGED
@@ -39,24 +39,33 @@ function clear_cache(location, show) {
39
39
  }
40
40
  }
41
41
  exports.clear_cache = clear_cache;
42
- function new_cache(location, anime, show) {
42
+ function new_cache(location, anime) {
43
+ /*
44
+ Creates cache of Anime object, in cache file.
45
+ */
43
46
  try {
44
47
  fs.writeFileSync(location + "/" + anime.id + ".cache", JSON.stringify(anime));
45
48
  }
46
49
  catch {
47
- if (show) {
48
- console.log("Failed to write to cache");
49
- }
50
+ console.log("Failed to write to cache");
50
51
  }
51
52
  }
52
53
  exports.new_cache = new_cache;
53
54
  function get_cache(location, anime_id) {
55
+ /*
56
+ ## Get cache by anime_id. Does not check if the cache exists.
57
+ */
54
58
  return JSON.parse(fs.readFileSync(location + "/" + anime_id + ".cache").toString());
55
59
  }
56
- function search_cache(location, anime_id) {
60
+ function search_cache(cache_folder, anime_id) {
61
+ /*
62
+ ## Searches cache folder for cache file with name of anime_id, at the location of cache_folder
63
+
64
+ ### returns boolean for weather it is found.
65
+ */
57
66
  try {
58
- if (check_cache(location, anime_id)) {
59
- return get_cache(location, anime_id);
67
+ if (check_cache(cache_folder, anime_id)) {
68
+ return get_cache(cache_folder, anime_id);
60
69
  }
61
70
  return false;
62
71
  }
@@ -4,6 +4,9 @@ exports.config_ = void 0;
4
4
  const chalk = require("chalk");
5
5
  const input_1 = require("./input");
6
6
  async function config_(temp) {
7
+ /*
8
+ ## Lets user change a single attribute of config. Returns new config object, and an exit code
9
+ */
7
10
  console.clear();
8
11
  console.log(chalk.blue("ANI-CLI-NPM \n"));
9
12
  console.log(chalk.yellow("Config:\n"));
package/bin/curl.js CHANGED
@@ -2,33 +2,34 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.curl = void 0;
4
4
  const fetch = require("node-fetch");
5
+ const chalk = require("chalk");
5
6
  async function curl(url, method = "GET", redirect = false) {
6
- //try{
7
- let response = await fetch(url, {
8
- //"agent": proxyAgent,
9
- "headers": {
10
- 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/100.0',
11
- "X-Requested-With": "XMLHttpRequest"
12
- },
13
- "referrerPolicy": "origin",
14
- "body": null,
15
- "method": method,
16
- "redirect": 'follow',
17
- // "follow": 10,
18
- }); /*.catch(async function(err) {
19
- console.warn(colors.Red, `Something went wrong connecting to ${url}.`);
20
- await search();
21
- process.exit()
22
- })*/
23
- if (redirect) {
24
- return response.url;
7
+ try {
8
+ let response = await fetch(url, {
9
+ //"agent": proxyAgent,
10
+ "headers": {
11
+ 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/100.0',
12
+ "X-Requested-With": "XMLHttpRequest"
13
+ },
14
+ "referrerPolicy": "origin",
15
+ "body": null,
16
+ "method": method,
17
+ "redirect": 'follow',
18
+ // "follow": 10,
19
+ }).catch(async function (err) {
20
+ console.warn(chalk.red(`Something went wrong connecting to ${url}. ${err}`));
21
+ process.exit();
22
+ });
23
+ if (redirect) {
24
+ return response.url;
25
+ }
26
+ else {
27
+ return await response.text();
28
+ }
25
29
  }
26
- else {
27
- return await response.text();
30
+ catch {
31
+ console.log(chalk.red("Something went wrong in curl()"));
32
+ process.exit();
28
33
  }
29
- /*}catch{
30
- console.log(colors.Red, "Something went wrong in curl()")
31
- await main()
32
- }*/
33
34
  }
34
35
  exports.curl = curl;
package/bin/download.js CHANGED
@@ -1,18 +1,17 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.download = void 0;
7
4
  const search_anime_1 = require("./search_anime");
8
5
  const Anime_1 = require("./Anime");
9
6
  const input_1 = require("./input");
10
- const libs_1 = require("./libs");
11
- const chalk_1 = __importDefault(require("chalk"));
12
7
  async function download(cache_folder, config) {
13
8
  try {
14
9
  console.clear();
15
- let download_id = await (0, search_anime_1.search)();
10
+ let temp_ = await (0, search_anime_1.search)();
11
+ if (temp_ == 1) {
12
+ return 2;
13
+ }
14
+ let download_id = temp_;
16
15
  let download = new Anime_1.Anime();
17
16
  await download.init(download_id, cache_folder);
18
17
  let start_ep_number;
@@ -27,21 +26,7 @@ async function download(cache_folder, config) {
27
26
  console.log(`Select end episode [${start_ep_number}-${download.episode_list.length}]`);
28
27
  end_ep_number = await (0, input_1.number_input)(download.episode_list.length, start_ep_number) - 1;
29
28
  }
30
- let to_do = (0, libs_1.range)(start_ep_number, end_ep_number + 1);
31
- do {
32
- for (let x in to_do) {
33
- try {
34
- await download.download(to_do[x] - 1, config.download_folder);
35
- to_do.splice(Number(x), 1);
36
- }
37
- catch {
38
- console.log(chalk_1.default.red("Failed to download episode " + to_do[x]));
39
- }
40
- }
41
- if (to_do[0] !== undefined) { //TODO fix buggy downloads
42
- console.log(chalk_1.default.red("Failed to download episodes: " + to_do) + "\nRetrying...");
43
- }
44
- } while (to_do[0] !== undefined);
29
+ await download.download(start_ep_number - 1, config.download_folder, end_ep_number);
45
30
  }
46
31
  catch {
47
32
  return 1;
package/bin/index.js CHANGED
@@ -18,9 +18,10 @@ const download_1 = require("./download");
18
18
  const fs_1 = __importDefault(require("fs"));
19
19
  const app_data_folder = (0, appdata_path_1.default)();
20
20
  const cache_folder = app_data_folder + "/ani-cli-npm";
21
+ (0, load_config_1.make_config_dir)(cache_folder, true);
21
22
  console.clear();
22
23
  async function main() {
23
- let config = (0, load_config_1.load_config)(app_data_folder);
24
+ let config = (0, load_config_1.load_config)(cache_folder);
24
25
  console.log(chalk.magenta("Ani-cli-npm!\n"));
25
26
  if (config.most_recent.anime_id !== "") {
26
27
  console.log(chalk.grey(`Most recently played: ${config.most_recent.anime_id} episode ${config.most_recent.episode_number + 1}\n`));
@@ -34,7 +35,12 @@ async function main() {
34
35
  ], ["s", "c", "d", "o", "q"], ((thing) => { return chalk.magenta(thing); }), ((thing) => { return chalk.magenta(thing); }));
35
36
  switch (choice) {
36
37
  case 0: // Search
37
- let anime_id = await (0, search_anime_1.search)();
38
+ let temp_ = await (0, search_anime_1.search)();
39
+ if (temp_ == 1) {
40
+ await main();
41
+ process.exit();
42
+ }
43
+ let anime_id = temp_;
38
44
  let anime = new Anime_1.Anime();
39
45
  await anime.init(anime_id, cache_folder);
40
46
  let episode_number;
@@ -59,7 +65,9 @@ async function main() {
59
65
  let continue_anime = new Anime_1.Anime();
60
66
  await continue_anime.init(config.most_recent.anime_id, cache_folder);
61
67
  await continue_anime.play_head(config.most_recent.episode_number, config, cache_folder);
62
- await continue_anime.player.quit();
68
+ if (continue_anime.player != 0 && continue_anime.player != 1) {
69
+ await continue_anime.player.quit();
70
+ }
63
71
  await main();
64
72
  break;
65
73
  case 2: // Download
@@ -67,7 +75,6 @@ async function main() {
67
75
  if (code == 1) {
68
76
  console.log(chalk.red("Error downloading episodes"));
69
77
  }
70
- await main();
71
78
  break;
72
79
  case 3: // Options
73
80
  let temp = structuredClone(config);
@@ -100,6 +107,7 @@ async function main() {
100
107
  case 4: // Quit
101
108
  console.log("Exit");
102
109
  }
110
+ return 0;
103
111
  // await search()
104
112
  }
105
113
  main();
package/bin/input.js CHANGED
@@ -7,6 +7,24 @@ exports.number_input = exports.input = exports.selection = void 0;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const _prompt = require("simple-input");
9
9
  async function selection(options, extra_options = [], color1 = ((thing) => { return chalk_1.default.yellow(thing); }), color2 = ((thing) => { return chalk_1.default.green(thing); })) {
10
+ /*
11
+ selection(options, extra_options, color1, color2)
12
+
13
+ Gives use prompt to choose from a list of options. Either by inputting a number ranging from 1, to the length of the list. Or by inputting a letter (non-caps-sensitive) relating to the option.
14
+
15
+
16
+ - options: array of options; e.g. ["play", "download", "continue", "quit"] REQUIRED
17
+
18
+
19
+ - extra_options: array of characters as alternatives to numbers (both will be displayed). e.g. ["p", "d", "c", "q"].
20
+
21
+ default: []
22
+
23
+ - color1 and color2: functions that will dictate what 2 colors the options with alternate between (option1 will be color1, option2;color2, option3;color1, etc).
24
+ recommended for this function to return a chalk.____() parsed string.
25
+
26
+ default: ((thing:string) => {return chalk.yellow(thing)}) and ((thing:string) => {return chalk.green(thing)})
27
+ */
10
28
  let color = true;
11
29
  for (let x in options) {
12
30
  if (color) {
@@ -57,12 +75,3 @@ async function number_input(max, min = 1) {
57
75
  return selection;
58
76
  }
59
77
  exports.number_input = number_input;
60
- async function number_input_range(max, min = 1) {
61
- let selection;
62
- do {
63
- selection = await _prompt(">");
64
- if (!(min <= parseInt(selection[0]) && parseInt(selection[0]) <= max)) {
65
- console.log(chalk_1.default.red("Invalid choice."));
66
- }
67
- } while (!(min <= parseInt(selection[0]) && parseInt(selection[0]) <= max));
68
- }
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.write_config = exports.load_config = void 0;
26
+ exports.make_config_dir = exports.write_config = exports.load_config = void 0;
27
27
  const fs = __importStar(require("fs"));
28
28
  function make_config_dir(cache_dir, debug) {
29
29
  try {
@@ -36,9 +36,10 @@ function make_config_dir(cache_dir, debug) {
36
36
  }
37
37
  }
38
38
  }
39
+ exports.make_config_dir = make_config_dir;
39
40
  function write_config(cache_dir, config) {
40
41
  try {
41
- make_config_dir(cache_dir, config.debug_mode);
42
+ //make_config_dir(cache_dir, config.debug_mode)
42
43
  fs.writeFileSync(cache_dir + "/config.conf", JSON.stringify(config));
43
44
  }
44
45
  catch {
@@ -30,6 +30,10 @@ async function search() {
30
30
  console.log(chalk_1.default.magenta("Search..."));
31
31
  let _selection = await (0, input_1.input)();
32
32
  let results = await search_anime(_selection);
33
+ if (results[0] === undefined) {
34
+ console.log(chalk_1.default.red("No results found."));
35
+ return 1;
36
+ }
33
37
  return results[await (0, input_1.selection)(results)];
34
38
  }
35
39
  exports.search = search;
@@ -0,0 +1,9 @@
1
+ #EXTM3U
2
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=120532,RESOLUTION=640x360,NAME="360p"
3
+ ep.1.1657688701.360.m3u8
4
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=195379,RESOLUTION=854x480,NAME="480p"
5
+ ep.1.1657688701.480.m3u8
6
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=418741,RESOLUTION=1280x720,NAME="720p"
7
+ ep.1.1657688701.720.m3u8
8
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=903363,RESOLUTION=1920x1080,NAME="1080p"
9
+ ep.1.1657688701.1080.m3u8
@@ -0,0 +1,9 @@
1
+ #EXTM3U
2
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=112046,RESOLUTION=640x360,NAME="360p"
3
+ ep.2.1657689264.360.m3u8
4
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=180246,RESOLUTION=854x480,NAME="480p"
5
+ ep.2.1657689264.480.m3u8
6
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=382280,RESOLUTION=1280x720,NAME="720p"
7
+ ep.2.1657689264.720.m3u8
8
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=829748,RESOLUTION=1920x1080,NAME="1080p"
9
+ ep.2.1657689264.1080.m3u8
@@ -0,0 +1,9 @@
1
+ #EXTM3U
2
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=113161,RESOLUTION=640x360,NAME="360p"
3
+ ep.3.1657689714.360.m3u8
4
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=177223,RESOLUTION=854x480,NAME="480p"
5
+ ep.3.1657689714.480.m3u8
6
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=372889,RESOLUTION=1280x720,NAME="720p"
7
+ ep.3.1657689714.720.m3u8
8
+ #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=798185,RESOLUTION=1920x1080,NAME="1080p"
9
+ ep.3.1657689714.1080.m3u8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ani-cli-npm",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "description": "ani-cli tool rewritten as npm package",
5
5
  "main": "bin/index.js",
6
6
  "scripts": {
@@ -35,7 +35,6 @@
35
35
  "media-player-controller": "^1.5.3",
36
36
  "node-fetch": "^2.6.6",
37
37
  "open": "^8.4.0",
38
- "persistent-cache": "^0.1.0",
39
38
  "simple-input": "^1.0.1",
40
39
  "typescript": "^4.9.3"
41
40
  },