ani-cli-npm 2.1.3 → 2.1.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/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
+