ani-cli-npm 2.1.3 → 2.1.5

Sign up to get free protection for your applications and to get access to all the features.
package/src/Anime.ts ADDED
@@ -0,0 +1,427 @@
1
+ import {curl} from "./core_utils/curl";
2
+ import {RegexParse} from "./core_utils/regex";
3
+ import {generate_link} from "./url_genoration/generate_link";
4
+ import {config_interface, player} from "./core_utils/interfaces";
5
+ import {search_cache, new_cache} from "./file_managment/cache";
6
+ import {number_input, selection} from "./IO/input";
7
+ import {write_config} from "./file_managment/load_config";
8
+ const W2GClient = require("w2g-client")
9
+ const open = require("open")
10
+ const PlayerController = require("media-player-controller")
11
+ const dl = require("download-file-with-progressbar");
12
+ const chalk = require("chalk")
13
+ const m3u8ToMp4 = require("m3u8-to-mp4");
14
+ const converter = new m3u8ToMp4();
15
+
16
+
17
+ class Anime{
18
+ /*
19
+ Class for handling a show/film
20
+
21
+ Stores anime dpage links assigned with anime_id.
22
+
23
+ Initialised with Anime.init()
24
+
25
+ */
26
+
27
+ id: string = "";
28
+ episode_list: string[] = [];
29
+ most_recent:number = 0;
30
+ player:player = new class implements player {
31
+ play(episode_link: string): {} {
32
+ return {};
33
+ }
34
+ player: any;
35
+ };
36
+ current_pos:number = 0;
37
+ current_episode:number = 0;
38
+
39
+ async init(anime_id: string, cache_folder:string){ // init mate
40
+ /*
41
+ Initiate Anime object
42
+
43
+ Will first search cache folder for cache file (this will contain id and dpage links)
44
+
45
+ If no cache is found, it will use get_ep_bases(anime_id) to get links. (Webscrapes from animixplay.to), then creates cache
46
+
47
+ anime_id:
48
+ */
49
+ let cache_object = search_cache(cache_folder, anime_id)
50
+ this.id = anime_id
51
+ if (cache_object == 0){
52
+ await this.get_ep_bases(this.id)
53
+ new_cache(cache_folder,{
54
+ id: this.id,
55
+ episode_list: this.episode_list,
56
+ most_recent: this.most_recent
57
+ })
58
+ }else{
59
+ try{
60
+ this.episode_list = cache_object.episode_list
61
+ if (cache_object.most_recent != undefined){
62
+ this.most_recent = cache_object.most_recent
63
+ }
64
+ if (cache_object.position != undefined){
65
+ this.current_pos = cache_object.position
66
+ }
67
+ }catch{
68
+ await this.get_ep_bases(this.id)
69
+ }
70
+ }
71
+ new_cache(cache_folder,{
72
+ id: this.id,
73
+ episode_list: this.episode_list,
74
+ most_recent: this.most_recent
75
+ })
76
+ return 0;
77
+ }
78
+
79
+ async get_episode_link(episode:number, player:string = "VLC"){
80
+ let episode_dpage = this.episode_list[episode]
81
+ let id = episode_dpage.replace("//gogohd.pro/streaming.php?id=","")
82
+ id = id.slice(0, id.indexOf("="))
83
+ let link:string = await generate_link(1,id, player)
84
+ if (!link){
85
+ link = await generate_link(2,id, player)
86
+ }
87
+ if (!link){
88
+ console.log(chalk.red("Failed to generate links"))
89
+ }
90
+ if (player == "VLC" && link.includes("m3u8")){
91
+ console.log(chalk.red("Warning; VLC is not compatible with m3u8 playlist files without custom plugins."))
92
+ }
93
+ return link
94
+ }
95
+
96
+ async get_ep_bases(anime_id:string){
97
+ /*
98
+ Scrapes animixplay.to for dpage links.
99
+ returns array with all dpage links
100
+ */
101
+ let html = (await(curl("https://animixplay.to/v1/"+anime_id))).split("\n") //POTENTIAL BREAK POINT. animixplay.to may change domain address
102
+ let lines = ""
103
+ for (let x in html){
104
+ if(RegexParse(html[x], "*<div id=\"epslistplace\"*")){
105
+ lines = (html[x])
106
+ }
107
+ }
108
+ lines = lines.slice(55, lines.length).replace("}</div>", "")
109
+ lines = "{" + lines.slice(lines.indexOf(",")+1, lines.length) + "}"
110
+ let json = JSON.parse(lines)
111
+ for (const value of Object.entries(json) as unknown as string[]) {
112
+ if (typeof value[1] == "string"){
113
+ this.episode_list.push(value[1].replace("//gogohd.pro/streaming.php?id=",""))
114
+ }
115
+ }
116
+ }
117
+
118
+ async play_head(episode:number, config:config_interface, config_dir:string){
119
+ /*
120
+ # Starts play cascade.
121
+
122
+ ## Takes in:
123
+ ### Episode number, counting from 0
124
+ ### Config object
125
+ ### Config save directory
126
+
127
+ - If config.player is set to MPV or VLC, it will use the media-player-controller package.
128
+
129
+ - If set to Browser, it will use the "open" packer.
130
+
131
+ - If set to Link, it will simply print the media stream link to console, primarily for debuting peruses.
132
+ */
133
+ console.clear()
134
+ console.log(`Playing ${this.id} episode ${episode+1}`)// from ${new Date(this.current_pos * 1000).toISOString().slice(11, 19)}`)
135
+ if (this.current_pos != 0){
136
+ console.log(`Most recent position: ${new Date(this.current_pos * 1000).toISOString().slice(11, 19)}`)
137
+ }
138
+ switch (config.player){
139
+ case "MPV":
140
+ console.log(("Opening MPV.."))
141
+ this.player.player = await new PlayerController({
142
+ app: 'mpv',
143
+ args: ['--fullscreen', '--keep-open=yes'],// `--start=+${this.current_pos}`],
144
+ media: await this.get_episode_link(episode, config.player),
145
+ ipcPath: config.mpv_socket_path
146
+ });
147
+ this.player.play = (async (episode_link:string) => {
148
+ this.player.player.load(episode_link)
149
+ })
150
+ this.player.player.on('playback', (data: any) =>{
151
+ if (data.name == "time-pos" && data.value >= 0){
152
+ this.current_pos = data.value;
153
+ }
154
+ //console.log(data)
155
+ })
156
+ this.player.player.on('app-exit', (code: any) => {
157
+ config.most_recent.anime_id = this.id
158
+ config.most_recent.episode_number = episode
159
+ config.most_recent.episode_second = this.current_pos
160
+ write_config(config_dir, config)
161
+ this.most_recent = episode;
162
+ new_cache(config_dir,{
163
+ id: this.id,
164
+ episode_list: this.episode_list,
165
+ most_recent: this.most_recent,
166
+ position: this.current_pos
167
+ })
168
+ })
169
+ // @ts-ignore
170
+ await this.player.player.launch(err => {
171
+ if (err) return console.error(err.message);
172
+ });
173
+
174
+ break
175
+ case "VLC":
176
+ console.log(("Opening VLC.."))
177
+ this.player.player = await new PlayerController({
178
+ app: 'vlc',
179
+ args: ['--fullscreen'],//, `--start-time ${this.current_pos}`],
180
+ media: await this.get_episode_link(episode, config.player),
181
+ //httpPort: (config.vlc_socket !== 0)? config.vlc_socket : null,
182
+ //httpPass: (config.vlc_pass !== "")? config.vlc_socket : null,
183
+ });
184
+ // @ts-ignore
185
+ await this.player.player.launch(err => {
186
+ if (err) return console.error(err.message);
187
+ });
188
+
189
+ this.player.play = (async (episode_link:string) => {
190
+ this.player.player.quit()
191
+ this.player.player = await new PlayerController({
192
+ app: 'vlc',
193
+ args: ['--fullscreen'],// "--start-time 0"],
194
+ media: episode_link
195
+ //httpPort: (config.vlc_socket !== 0)? config.vlc_socket : null,
196
+ //httpPass: (config.vlc_pass !== "")? config.vlc_socket : null,
197
+ });
198
+ this.player.player.on('playback', (data: any) =>{
199
+ if (data.name == "time-pos" && data.value >= 0){
200
+ this.current_pos = data.value;
201
+ }
202
+ //console.log(data)
203
+ })
204
+
205
+ this.player.player.on('app-exit', (code: any) => {
206
+ config.most_recent.anime_id = this.id
207
+ config.most_recent.episode_number = episode
208
+ config.most_recent.episode_second = this.current_pos
209
+ write_config(config_dir, config)
210
+ this.most_recent = episode;
211
+ new_cache(config_dir,{
212
+ id: this.id,
213
+ episode_list: this.episode_list,
214
+ most_recent: this.most_recent,
215
+ position: this.current_pos
216
+ })
217
+ })
218
+ // @ts-ignore
219
+ await this.player.player.launch(err => {
220
+ if (err) return console.error(err.message);
221
+ });
222
+
223
+
224
+ })
225
+ break
226
+ case "BROWSER":
227
+ this.player.play = (async (episode_link:string) => {
228
+ console.log(("Opening browser..."))
229
+ await open(episode_link)
230
+ })
231
+ console.log(("Opening browser..."))
232
+ await open(await this.get_episode_link(episode, config.player))
233
+ break
234
+ case "W2G":
235
+ try{
236
+ this.player.player = new W2GClient.W2GClient(config.w2g_api_key);
237
+ await this.player.player.create(await this.get_episode_link(episode, config.player))
238
+ console.log(chalk.green("Room link: " + await this.player.player.getLink()));
239
+ }catch{
240
+ console.log(chalk.red("Failed to create w2g.tv room. \nthis can often be because your API token is invalid. You can change it in options."))
241
+ process.exit()
242
+ }
243
+ this.player.play = (async (episode_link:string) => {
244
+ console.log(("Updating W2G room..."))
245
+ console.log(chalk.green("Room link: " + await this.player.player.getLink()));
246
+ try{
247
+ await this.player.player.update(episode_link)
248
+ }catch{
249
+ console.log(chalk.red("Error updating W2G room. Very sorry, w2g functionality is a bit broken at present. Worst case you should be able to just restart with a new room for each episode."))
250
+ }
251
+ })
252
+ console.log("Opening W2G.tv...")
253
+ await open(await this.player.player.getLink())
254
+
255
+ break
256
+ case "LINK":
257
+ this.player.play = (async (episode_link:string) => {
258
+ console.log(chalk.green(episode_link))
259
+ });
260
+ this.player.play(await this.get_episode_link(episode))
261
+ break
262
+ }
263
+ await this.play_controller(episode, config, config_dir, true)
264
+ }
265
+
266
+ async next(player:string){
267
+ this.current_episode += 1
268
+ this.current_pos = 0
269
+ this.player.play(await this.get_episode_link(this.current_episode, player))
270
+ }
271
+ async previous(player:string){
272
+ this.current_episode -= 1
273
+ this.current_pos = 0
274
+ this.player.play(await this.get_episode_link(this.current_episode, player))
275
+ }
276
+
277
+ private async play_controller(episode:number, config:config_interface, config_dir:string, first:boolean=false){
278
+ if (config.show_cover){
279
+
280
+ }
281
+ console.clear()
282
+ console.log(`Playing ${this.id} episode ${episode+1}`)// from ${new Date(this.current_pos * 1000).toISOString().slice(11, 19)}`)
283
+ // if (!first){
284
+ // console.clear()
285
+ // console.log(chalk.blue(`Playing ${this.id} episode ${episode+1}`))
286
+ // if (this.player == 0){
287
+ // await open(await this.get_episode_link(episode, "BROWSER"))
288
+ // }else if(this.player == 1){
289
+ // console.log(await this.get_episode_link(episode))
290
+ // } else if (this.player.roomID != undefined){
291
+ // console.log(chalk.green("Room link: "+ await this.player.getLink()));
292
+ // this.player.update(await this.get_episode_link(episode))
293
+ // } else if (this.player.opts.app == "mpv"){
294
+ // await this.player.load(await this.get_episode_link(episode))
295
+ // }else{
296
+ // this.player.quit()
297
+ // this.player = await new PlayerController({
298
+ // app: 'vlc',
299
+ // args: ['--fullscreen'],
300
+ // media: await this.get_episode_link(episode, config.player)
301
+ // });
302
+ // // @ts-ignore
303
+ // await this.player.launch(err => {
304
+ // if (err) return console.error(err.message);
305
+ // });
306
+ // }
307
+ // }
308
+ this.current_episode = episode
309
+ config.most_recent.anime_id = this.id
310
+ config.most_recent.episode_number = episode
311
+ config.most_recent.episode_second = this.current_pos
312
+ write_config(config_dir, config)
313
+ this.most_recent = episode;
314
+ new_cache(config_dir,{
315
+ id: this.id,
316
+ episode_list: this.episode_list,
317
+ most_recent: this.most_recent,
318
+ position: this.current_pos
319
+ })
320
+
321
+
322
+ let selected:number; // Look, I'm sorry, but there is no way I can possibly document this in a sane way. It's a dumb patch.
323
+ do{
324
+ console.clear()
325
+ selected = await selection(
326
+ (episode <= 0)? [chalk.yellow("1/n) Next"), chalk.grey("2/p) Previous"), chalk.yellow("3/s) Select"), chalk.green("4/q) Quit")]:
327
+ (episode >= this.episode_list.length-1)? [chalk.grey("1/n) Next"), chalk.green("2/p) Previous"), chalk.yellow("3/s) Select"), chalk.green("4/q) Quit")] :
328
+ [chalk.yellow("1/n) Next"), chalk.green("2/p) Previous"), chalk.yellow("3/s) Select"), chalk.green("4/q) Quit")],
329
+
330
+ ["n", "p", "s", "q"],
331
+ ((thing:string) => {return (thing)}),
332
+ ((thing:string) => {return (thing)}),
333
+ true
334
+ )
335
+ if (!(selected != ((episode <= 0)? 1 : (episode >= this.episode_list.length-1)? 0 : -1))){
336
+ console.log(chalk.red("Invalid choice."))
337
+ }
338
+ }while (!(selected != ((episode <= 0)? 1 : (episode >= this.episode_list.length-1)? 0 : -1)))
339
+
340
+ switch(selected){
341
+ case 0:
342
+ if (episode >= this.episode_list.length-1){
343
+ await this.next(config.player)
344
+ await this.play_controller(episode-1, config, config_dir)
345
+ }else{
346
+ await this.next(config.player)
347
+ await this.play_controller(episode+1, config, config_dir)
348
+ }
349
+ break
350
+ case 1:
351
+ if ((episode >= this.episode_list.length-1) || (episode <= 0)){
352
+ break
353
+ }
354
+ await this.previous(config.player)
355
+ await this.play_controller(episode-1, config, config_dir)
356
+ break
357
+ case 2:
358
+ if (this.episode_list.length == 1){
359
+ this.player.play(await this.get_episode_link(0, config.player))
360
+ await this.play_controller(0, config, config_dir)
361
+ }else{
362
+ console.log(`Select episode [1-${this.episode_list.length}]`)
363
+ let episode = await number_input(this.episode_list.length, 1)-1
364
+ this.player.play(await this.get_episode_link(episode, config.player))
365
+ await this.play_controller(episode, config, config_dir)
366
+ }
367
+ break
368
+ case 3:
369
+ break
370
+ }
371
+ }
372
+
373
+ async download(episode:number, download_folder:string, final_ep:number){
374
+ /*
375
+ ## Downloads an episode (counting from 0) to download_folder, with progress bar.
376
+ */
377
+ while (episode <= final_ep){
378
+
379
+ }
380
+ try {
381
+ let ep_link: string = await this.get_episode_link(episode)
382
+ let file_name = `${this.id}-${episode + 1}.mp4`
383
+ if (ep_link.includes(".m3u8")){
384
+ console.log(chalk.green(`Downloading episode ${episode+1} of ${this.id.replace("-", "")} to ${download_folder+"/"+file_name}...`))
385
+ console.log("Progress bar unavailable for m3u8 files.")
386
+ await converter
387
+ .setInputFile(ep_link)
388
+ .setOutputFile((download_folder+"/"+file_name))
389
+ .start();
390
+ console.log(chalk.green("Download finished."))
391
+ }else{
392
+ // @ts-ignore
393
+ let option = {
394
+ filename: (ep_link.includes("m3u8") ? file_name.replace("mp4", "m3u8") : file_name),
395
+ dir: download_folder,
396
+ onDone: (final_ep > episode) ? ((info: any) => {
397
+ // @ts-ignore
398
+ console.log(chalk.green(`\n -- 1Download finished -- \nLocation: ${info.path}. Size: ${Math.round(info.size / 100000) * 10} Bytes\n`));
399
+ this.download(episode + 1, download_folder, final_ep)
400
+ }) : ((info: any) => {
401
+ // @ts-ignore
402
+ console.log(chalk.green(`\n -- 2Download finished -- \n${info.path}. Size: ${Math.round(info.size / 100000) * 10} Bytes\n`));
403
+ }),
404
+ // @ts-ignore
405
+ onError: (err) => {
406
+ console.log(chalk.red('error', err));
407
+ this.download(episode, download_folder, final_ep)
408
+ },
409
+ // @ts-ignore
410
+ onProgress: (curr, total) => {
411
+ process.stdout.clearLine(0);
412
+ process.stdout.cursorTo(0);
413
+ 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")
414
+ }
415
+ }
416
+ //console.log((`${option.dir}/${option.filename}`))
417
+
418
+ return await dl(ep_link, option);
419
+ }
420
+ }catch{
421
+ await this.download(episode, download_folder, final_ep)
422
+ }
423
+ }
424
+
425
+ }
426
+
427
+ export {Anime}
package/src/IO/help.ts ADDED
@@ -0,0 +1,64 @@
1
+ import {selection} from "./input";
2
+
3
+ const chalk = require("chalk")
4
+
5
+
6
+ const helps = [
7
+ (async () => { // Playing anime
8
+ console.log(chalk.cyan("Playing anime: \n" +
9
+ " Search: \n" +
10
+ " Search for a show/movie. This will search on gogoanime.dk.\n" +
11
+ " Episode selection: \n" +
12
+ " Once an anime is selected, select an episode. If there is only 1 episode " +
13
+ "(in the case of a movie), the episode will be played automatically.\n" +
14
+ " The episode selected will be played in the video player selected in options. Info on video players can be found in options help."))
15
+ await help()
16
+ return
17
+ }),
18
+ (async () => { // Downloading anime
19
+ console.log(chalk.cyan("Downloading anime: \n" +
20
+ " Search: \n" +
21
+ " Search for a show/movie. This will search on gogoanime.dk.\n" +
22
+ " Episode selection: \n" +
23
+ " Once an anime is selected, select a start episode and an end episode. If there is only 1 episode " +
24
+ "(in the case of a movie), the episode will be downloaded automatically. Download folder can be changed in options. Default to run location.\n" +
25
+ " The selected episodes will be downloaded. It is common for episode links to fail to be fetched, when this happens the episode will be passed, then reattempted in another pass.\n" +
26
+ " Episodes sourced from Animixplay links will download m3u8 file, which you will have difficulty playing, if you are able to at all."))
27
+ await help()
28
+ return
29
+ }),
30
+ (async () => {
31
+ console.log(chalk.cyan("Options: \n" +
32
+ " Player: \n" +
33
+ " Player used to play anime.\n" +
34
+ " Proxy: \n" +
35
+ " https proxy address and port in form ip:port. This is not currently implemented.\n" +
36
+ " User agent:\n" +
37
+ " node-fetch user agent.\n" +
38
+ " Downloads folder:\n" +
39
+ " Folder to place downloaded episodes.\n" +
40
+ " MPV socket connection file:\n" +
41
+ " File for mpv socket, used to control mpv instance with outside tools.\n" +
42
+ " VLC socket:\n" +
43
+ " VLC http control socket\n" +
44
+ " VLC pass:\n" +
45
+ " VLC http control password\n" +
46
+ " W2G api token:\n" +
47
+ " Your user access token for w2g.tv. Can be found at https://w2g.tv/en/account/edit_user under Tools/API\n"
48
+ ))
49
+ await help()
50
+ return
51
+ }),
52
+ (async () => {
53
+ return
54
+ })
55
+
56
+ ]
57
+
58
+
59
+ async function help(){
60
+ console.log(chalk.cyan("Help page select: \n"))
61
+ return helps[await selection(["Playing", "Downloading", "Options", "Quit"], ["p", "d", "o", "q"])]()
62
+ }
63
+
64
+ export {help}
@@ -0,0 +1,92 @@
1
+ import chalk from "chalk";
2
+ const _prompt = require("simple-input");
3
+
4
+
5
+ async function selection(options:string[], extra_options:string[] = [], color1 = ((thing:string) => {return chalk.yellow(thing)}), color2 = ((thing:string) => {return chalk.green(thing)}), overwrite:boolean=false){
6
+ /*
7
+ selection(options, extra_options, color1, color2)
8
+
9
+ 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.
10
+
11
+
12
+ - options: array of options; e.g. ["play", "download", "continue", "quit"] REQUIRED
13
+
14
+
15
+ - extra_options: array of characters as alternatives to numbers (both will be displayed). e.g. ["p", "d", "c", "q"].
16
+
17
+ default: []
18
+
19
+ - color1 and color2: functions that will dictate what 2 colors the options with alternate between (option1 will be color1, option2;color2, option3;color1, etc).
20
+ recommended for this function to return a chalk.____() parsed string.
21
+
22
+ default: ((thing:string) => {return chalk.yellow(thing)}) and ((thing:string) => {return chalk.green(thing)})
23
+
24
+ - Overwrite: boolean. Please dont use this. I should not be using it. It prints out the raw string instead of adding numbers to them to allow for bogus.
25
+ */
26
+
27
+
28
+ let color:boolean = true;
29
+ for (let x in options){
30
+ if (!overwrite){
31
+ if (color){
32
+ console.log(
33
+ color1((parseInt(x)+1).toString()+
34
+ ((extra_options[x] == undefined)? "" : "/"+extra_options[x])+
35
+ ") "+options[x].replaceAll("-", " "))
36
+ )
37
+ }else{
38
+ console.log(
39
+ color2((parseInt(x)+1).toString()+
40
+ ((extra_options[x] == undefined)? "" : "/"+extra_options[x])+
41
+ ") "+options[x].replaceAll("-", " "))
42
+ )
43
+ }
44
+ }else{
45
+ console.log(options[x])
46
+ }
47
+ color = !color
48
+ }
49
+ let input:string = ""
50
+ do{
51
+ // @ts-ignore
52
+ input = (await _prompt(">")).toLowerCase()
53
+ for (let x in extra_options){
54
+ if (extra_options[x].toLowerCase() == input){
55
+ input = (parseInt(x)+1).toString()
56
+ }
57
+ }
58
+ if (!(1 <= parseInt(input) && parseInt(input) <= options.length)){
59
+ console.log(chalk.red("Invalid choice."))
60
+ }
61
+ }while(!(1 <= parseInt(input) && parseInt(input) <= options.length))
62
+ return parseInt(input)-1
63
+ }
64
+
65
+ async function input(){
66
+ return await _prompt(">")
67
+ }
68
+
69
+ async function number_input(max:number, min:number=1, extra_options:string[] =[], extra_option_values:number[]=[]){
70
+ let selector:string;
71
+ let selection:number;
72
+ do{
73
+ selector = await _prompt(">")
74
+ if (extra_options.includes(selector.toLowerCase())){
75
+ selection = extra_option_values[extra_options.indexOf(selector)]
76
+ }else{
77
+ selection = parseInt(selector)
78
+ }
79
+ if (selector == ""){
80
+ selection = min
81
+ }
82
+ if (!(min <= selection && selection <= max)){
83
+ console.log(chalk.red("Invalid choice."))
84
+ }
85
+ }while (!(min <= selection && selection <= max))
86
+
87
+ return selection
88
+ }
89
+
90
+
91
+
92
+ export {selection, input, number_input}
@@ -0,0 +1,32 @@
1
+ const fetch = require("node-fetch")
2
+ const chalk = require("chalk")
3
+ async function curl(url: string, method="GET", redirect = false){
4
+ try{
5
+ let response = await fetch(url, {
6
+ //"agent": proxyAgent,
7
+ "headers": {
8
+ 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/100.0',
9
+ "X-Requested-With": "XMLHttpRequest"
10
+ },
11
+ "referrerPolicy": "origin",
12
+ "body": null,
13
+ "method": method,
14
+ "redirect": 'follow',
15
+ // "follow": 10,
16
+ }).catch(async function(err:string) {
17
+ console.warn(chalk.red(`Something went wrong connecting to ${url}. ${err}`));
18
+ process.exit()
19
+ })
20
+ if (redirect){
21
+ return response.url
22
+ }else{
23
+ return await response.text()
24
+ }
25
+ }catch{
26
+ console.log(chalk.red("Something went wrong in curl()"))
27
+ process.exit()
28
+ }
29
+
30
+ }
31
+
32
+ export {curl}
@@ -0,0 +1,25 @@
1
+ interface config_interface{
2
+ player: string,
3
+ proxy: string,
4
+ user_agent: string,
5
+ most_recent: {
6
+ episode_number: number,
7
+ episode_second: number,
8
+ anime_id: string,
9
+ }
10
+ download_folder:string,
11
+ debug_mode: boolean,
12
+ mpv_socket_path: string,
13
+ vlc_socket:number,
14
+ vlc_pass:string,
15
+ w2g_api_key:string,
16
+ show_cover: boolean
17
+ }
18
+
19
+ interface player{
20
+ player: any,
21
+ play: ((episode_link:string) => {}),
22
+ }
23
+
24
+
25
+ export {config_interface, player}
@@ -0,0 +1,13 @@
1
+ // Random functions
2
+
3
+ function range(start:number, end:number) {
4
+ let ans = [];
5
+ for (let i = start; i <= end; i++) {
6
+ ans.push(i);
7
+ }
8
+ return ans;
9
+ }
10
+
11
+
12
+
13
+ export {range}
@@ -0,0 +1,5 @@
1
+ function RegexParse(str: string, rule: string) {
2
+ let escapeRegex = (str: string) => str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
3
+ return new RegExp("^" + rule.split("*").map(escapeRegex).join(".*") + "$").test(str);
4
+ }
5
+ export { RegexParse }
@@ -0,0 +1,9 @@
1
+ // let base:string = "https://gogocdn.net/cover/yuri-on-ice-dub.png"
2
+
3
+
4
+
5
+
6
+
7
+
8
+ // export {display_cover}
9
+