ani-cli-npm 2.0.0 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- package/.idea/{ani-cli-npm-ts.iml → ani-cli-npm.iml} +1 -1
- package/.idea/inspectionProfiles/Project_Default.xml +10 -0
- package/.idea/jsLibraryMappings.xml +6 -0
- package/.idea/modules.xml +1 -1
- package/README.MD +18 -16
- package/bin/download.js +12 -4
- package/bin/index.js +8 -2
- package/bin/input.js +6 -1
- package/package.json +1 -1
- package/bin/index.js.old +0 -586
@@ -4,7 +4,7 @@
|
|
4
4
|
<content url="file://$MODULE_DIR$">
|
5
5
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
6
6
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
7
|
-
<excludeFolder url="file://$MODULE_DIR$/tmp
|
7
|
+
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
8
8
|
</content>
|
9
9
|
<orderEntry type="inheritedJdk" />
|
10
10
|
<orderEntry type="sourceFolder" forTests="false" />
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<component name="InspectionProjectProfileManager">
|
2
|
+
<profile version="1.0">
|
3
|
+
<option name="myName" value="Project Default" />
|
4
|
+
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
5
|
+
<Languages>
|
6
|
+
<language minSize="76" name="JavaScript" />
|
7
|
+
</Languages>
|
8
|
+
</inspection_tool>
|
9
|
+
</profile>
|
10
|
+
</component>
|
package/.idea/modules.xml
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
<project version="4">
|
3
3
|
<component name="ProjectModuleManager">
|
4
4
|
<modules>
|
5
|
-
<module fileurl="file://$PROJECT_DIR$/.idea/ani-cli-npm
|
5
|
+
<module fileurl="file://$PROJECT_DIR$/.idea/ani-cli-npm.iml" filepath="$PROJECT_DIR$/.idea/ani-cli-npm.iml" />
|
6
6
|
</modules>
|
7
7
|
</component>
|
8
8
|
</project>
|
package/README.MD
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# ANI-CLI-NPM
|
2
2
|
|
3
3
|
### An Anime client, writen in nodeJS, to access any* anime without the need for ad filled websites! Just install, search for the anime of your choice, and watch in the video player of your choice.
|
4
|
-
###
|
4
|
+
### Typescript rewrite of the [ani-cli](https://github.com/pystardust/ani-cli) package for linux.
|
5
5
|
|
6
6
|
|
7
7
|
## Instalation:
|
@@ -31,40 +31,42 @@ npx ani-cli-npm@latest
|
|
31
31
|
```
|
32
32
|
npx ani-cli-npm@latest
|
33
33
|
```
|
34
|
-
|
34
|
+
|
35
|
+
### Build from git:
|
36
|
+
```
|
37
|
+
git clone https://github.com/Bumpkin-Pi/ani-cli-npm.git
|
38
|
+
cd ani-cli-npm
|
39
|
+
npm run build
|
40
|
+
npm run start
|
41
|
+
```
|
35
42
|
|
36
43
|
|
37
44
|
## Usage:
|
38
|
-
|
45
|
+
![image](https://user-images.githubusercontent.com/74017165/204142452-485e31b5-68dc-4eea-9924-bfb040429b02.png)
|
39
46
|
|
40
|
-
#### Input the page you wish to got to then press the enter key to select
|
41
47
|
|
42
|
-
### Search:
|
43
48
|
|
44
|
-
#### Input the
|
49
|
+
#### Input the page you wish to got to then press the enter key to select
|
45
50
|
|
46
|
-
|
51
|
+
### Search: Input the name of the anime you want to watch, the select an anime from the search results. Then select the episode you wish to watch (If there is only one episode, said ep will be played automaticly)
|
47
52
|
|
48
|
-
|
53
|
+
### Download - Download either a single episode, or a range of episodes from an anime of your choice. Download folder can be changed in options.
|
49
54
|
|
50
55
|
##### The download feature is not currently implemented, if you wish to download, open in browser and download there.
|
51
56
|
|
52
57
|
#### Show Link - Will display the link to the video file. This can be opened in a video player or browser.
|
53
58
|
|
54
|
-
###
|
59
|
+
### Options:
|
55
60
|
|
56
61
|
#### For configuring several of options about how the program works.
|
57
62
|
|
58
|
-
#### Player
|
59
|
-
|
60
|
-
#### Proxy - Proxy used for searching. This is not currently implemented and will not work.
|
61
|
-
|
62
|
-
#### User agent - The user agent used to make requests to websites.
|
63
|
+
#### Player - Change which player is used to open the anime (default browser).
|
63
64
|
|
65
|
+
#### Proxy - Proxy used for searching. This is not currently implemented and will not work.
|
64
66
|
|
65
|
-
|
67
|
+
#### User agent - The user agent used to make requests to websites.
|
66
68
|
|
69
|
+
#### Download folder - The folder in which to download episodes.
|
67
70
|
|
68
|
-
### This project is still somewhat under development, as such, there are a few bugs you may run into. Feel free to open an issue on github, though there is a solid chance I am aware of it and just havn't gotten round to fixing it yet.
|
69
71
|
|
70
72
|
## Happy watching :)
|
package/bin/download.js
CHANGED
@@ -15,10 +15,18 @@ async function download(cache_folder, config) {
|
|
15
15
|
let download_id = await (0, search_anime_1.search)();
|
16
16
|
let download = new Anime_1.Anime();
|
17
17
|
await download.init(download_id, cache_folder);
|
18
|
-
|
19
|
-
let
|
20
|
-
|
21
|
-
|
18
|
+
let start_ep_number;
|
19
|
+
let end_ep_number;
|
20
|
+
if (download.episode_list.length <= 1) {
|
21
|
+
start_ep_number = 1;
|
22
|
+
end_ep_number = 0;
|
23
|
+
}
|
24
|
+
else {
|
25
|
+
console.log(`Select start episode [1-${download.episode_list.length}]`);
|
26
|
+
start_ep_number = await (0, input_1.number_input)(download.episode_list.length);
|
27
|
+
console.log(`Select end episode [${start_ep_number}-${download.episode_list.length}]`);
|
28
|
+
end_ep_number = await (0, input_1.number_input)(download.episode_list.length, start_ep_number) - 1;
|
29
|
+
}
|
22
30
|
let to_do = (0, libs_1.range)(start_ep_number, end_ep_number + 1);
|
23
31
|
do {
|
24
32
|
for (let x in to_do) {
|
package/bin/index.js
CHANGED
@@ -36,8 +36,14 @@ async function main() {
|
|
36
36
|
let anime_id = await (0, search_anime_1.search)();
|
37
37
|
let anime = new Anime_1.Anime();
|
38
38
|
await anime.init(anime_id, cache_folder);
|
39
|
-
|
40
|
-
|
39
|
+
let episode_number;
|
40
|
+
if (anime.episode_list.length == 1) {
|
41
|
+
episode_number = 0;
|
42
|
+
}
|
43
|
+
else {
|
44
|
+
console.log(`Select episode [1-${anime.episode_list.length}]`);
|
45
|
+
episode_number = await (0, input_1.number_input)(anime.episode_list.length) - 1;
|
46
|
+
}
|
41
47
|
await anime.play_head(episode_number, config, cache_folder);
|
42
48
|
await anime.player.quit();
|
43
49
|
await main();
|
package/bin/input.js
CHANGED
@@ -42,9 +42,14 @@ async function input() {
|
|
42
42
|
}
|
43
43
|
exports.input = input;
|
44
44
|
async function number_input(max, min = 1) {
|
45
|
+
let selector;
|
45
46
|
let selection;
|
46
47
|
do {
|
47
|
-
|
48
|
+
selector = await _prompt(">");
|
49
|
+
selection = parseInt(selector);
|
50
|
+
if (selector == "") {
|
51
|
+
selection = min;
|
52
|
+
}
|
48
53
|
if (!(min <= selection && selection <= max)) {
|
49
54
|
console.log(chalk_1.default.red("Invalid choice."));
|
50
55
|
}
|
package/package.json
CHANGED
package/bin/index.js.old
DELETED
@@ -1,586 +0,0 @@
|
|
1
|
-
#! /usr/bin/env node
|
2
|
-
|
3
|
-
const {emitWarning} = process;
|
4
|
-
|
5
|
-
process.emitWarning = (warning, ...args) => {
|
6
|
-
if (args[0] === 'ExperimentalWarning') {
|
7
|
-
return;
|
8
|
-
}
|
9
|
-
|
10
|
-
if (args[0] && typeof args[0] === 'object' && args[0].type === 'ExperimentalWarning') {
|
11
|
-
return;
|
12
|
-
}
|
13
|
-
|
14
|
-
return emitWarning(warning, ...args);
|
15
|
-
};
|
16
|
-
const fetch = require('node-fetch');
|
17
|
-
const PlayerController = require("media-player-controller")
|
18
|
-
const open = require("open")
|
19
|
-
const prompt = require("simple-input");
|
20
|
-
const getAppDataPath = require("appdata-path")
|
21
|
-
const fs = require("fs")
|
22
|
-
const dl = require("download-file-with-progressbar");
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
let config = {
|
27
|
-
player: "BROWSER",
|
28
|
-
proxy: "",
|
29
|
-
user_agent: "Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/100.0",
|
30
|
-
most_recent: {
|
31
|
-
episode_number: 0,
|
32
|
-
anime_id: "",
|
33
|
-
episodes: []
|
34
|
-
},
|
35
|
-
download_folder: "./",
|
36
|
-
download_progress_bar: true
|
37
|
-
}
|
38
|
-
|
39
|
-
|
40
|
-
function read_config(){
|
41
|
-
try{
|
42
|
-
try {
|
43
|
-
config = JSON.parse(fs.readFileSync(getAppDataPath() + "/ani-cli-npm.conf")) //getAppDataPath()
|
44
|
-
if (!config.hasOwnProperty("player")) config.player = "BROWSER";
|
45
|
-
if (!config.hasOwnProperty("user_agent")) config.user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/100.0";
|
46
|
-
if (!config.hasOwnProperty("proxy")) config.user_agent = "";
|
47
|
-
if (!config.hasOwnProperty("most_recent")) config.most_recent = null;
|
48
|
-
if (!config.hasOwnProperty("download_folder")) config.download_folder = "./";
|
49
|
-
if (!config.hasOwnProperty("download_progress_bar")) config.download_progress_bar = true;
|
50
|
-
fs.writeFileSync(getAppDataPath() + "/ani-cli-npm.conf", JSON.stringify(config))
|
51
|
-
} catch {
|
52
|
-
fs.writeFileSync(getAppDataPath() + "/ani-cli-npm.conf", JSON.stringify(config))
|
53
|
-
}
|
54
|
-
}catch{
|
55
|
-
console.log(colors.Red, "Failed to read config file")
|
56
|
-
}
|
57
|
-
}
|
58
|
-
|
59
|
-
function write_config(){
|
60
|
-
try{
|
61
|
-
fs.writeFileSync(getAppDataPath() + "/ani-cli-npm.conf", JSON.stringify(config))
|
62
|
-
}catch{
|
63
|
-
console.log(colors.Red, "Failed to write to config file")
|
64
|
-
}
|
65
|
-
}
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
const gogohd_url="https://gogohd.net/"
|
70
|
-
const base_url="https://animixplay.to"
|
71
|
-
const colors = {
|
72
|
-
Black: "\x1b[30m%s\x1b[0m",
|
73
|
-
Red: "\x1b[31m%s\x1b[0m",
|
74
|
-
Green: "\x1b[32m%s\x1b[0m",
|
75
|
-
Yellow: "\x1b[33m%s\x1b[0m",
|
76
|
-
Blue: "\x1b[34m%s\x1b[0m",
|
77
|
-
Magenta: "\x1b[35m%s\x1b[0m",
|
78
|
-
Cyan: "\x1b[36m%s\x1b[0m",
|
79
|
-
White: "\x1b[37m%s\x1b[0m"
|
80
|
-
}
|
81
|
-
|
82
|
-
|
83
|
-
//const HttpsProxyAgent = require('https-proxy-agent');
|
84
|
-
//let proxyAgent = new HttpsProxyAgent(config.proxy);
|
85
|
-
|
86
|
-
|
87
|
-
async function config_(temp){
|
88
|
-
console.clear()
|
89
|
-
console.log(colors.Blue, "ANI-CLI-NPM \n")
|
90
|
-
console.log(colors.Yellow, "Config:\n")
|
91
|
-
console.log(colors.Cyan, `1) Player; ${temp.player}`)
|
92
|
-
console.log(colors.Cyan, `2) Proxy; ${temp.proxy}`)
|
93
|
-
console.log(colors.Cyan, `3) User agent; ${temp.user_agent}`)
|
94
|
-
console.log(colors.Cyan, `4) Download folder; ${config.download_folder}`)
|
95
|
-
console.log(colors.Cyan, "5) Save and exit")
|
96
|
-
console.log(colors.Cyan, "6) Exit without saving changes")
|
97
|
-
let choice = parseInt(await input(""));
|
98
|
-
switch (choice){
|
99
|
-
case 1:
|
100
|
-
console.log(colors.Cyan, `1) VLC (default)`)
|
101
|
-
console.log(colors.Cyan, `2) Browser`)
|
102
|
-
console.log(colors.Cyan, `3) MPV`)
|
103
|
-
let player = parseInt(await input("New Player;"))
|
104
|
-
switch (player){
|
105
|
-
case 1:
|
106
|
-
temp.player = "VLC"
|
107
|
-
break
|
108
|
-
case 2:
|
109
|
-
temp.player = "BROWSER"
|
110
|
-
break
|
111
|
-
case 3:
|
112
|
-
temp.player = "MPV"
|
113
|
-
break
|
114
|
-
}
|
115
|
-
return temp,0
|
116
|
-
case 2:
|
117
|
-
temp.proxy = (await(input("New Proxy;"))).replaceAll(" ", "")
|
118
|
-
return temp, 0
|
119
|
-
case 3:
|
120
|
-
temp.user_agent = await(input("New User agent;"))
|
121
|
-
return temp, 0
|
122
|
-
case 4:
|
123
|
-
temp.download_folder = await(input("New download folder: "))
|
124
|
-
return temp, 0
|
125
|
-
case 5:
|
126
|
-
return temp, 1
|
127
|
-
case 6:
|
128
|
-
return temp, 2
|
129
|
-
}
|
130
|
-
}
|
131
|
-
|
132
|
-
async function input(message){
|
133
|
-
if (message){
|
134
|
-
console.log(colors.Magenta,message)
|
135
|
-
}
|
136
|
-
return await prompt(">")
|
137
|
-
}
|
138
|
-
|
139
|
-
async function curl(url, method="GET", redirect = false){
|
140
|
-
//try{
|
141
|
-
let response = await fetch(url, {
|
142
|
-
//"agent": proxyAgent,
|
143
|
-
"headers": {
|
144
|
-
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:99.0) Gecko/20100101 Firefox/100.0',
|
145
|
-
"X-Requested-With": "XMLHttpRequest"
|
146
|
-
},
|
147
|
-
"referrerPolicy": "origin",
|
148
|
-
"body": null,
|
149
|
-
"method": method,
|
150
|
-
"redirect": 'follow',
|
151
|
-
"follow": 10,
|
152
|
-
}).catch(async function(err) {
|
153
|
-
console.warn(colors.Red, `Something went wrong connecting to ${url}.`);
|
154
|
-
await search();
|
155
|
-
process.exit()
|
156
|
-
})
|
157
|
-
if (redirect){
|
158
|
-
return response.url
|
159
|
-
}else{
|
160
|
-
return await response.text()
|
161
|
-
}
|
162
|
-
/*}catch{
|
163
|
-
console.log(colors.Red, "Something went wrong in curl()")
|
164
|
-
await main()
|
165
|
-
}*/
|
166
|
-
|
167
|
-
}
|
168
|
-
|
169
|
-
async function _continue(){
|
170
|
-
let link = await get_video_link(config.most_recent.episodes[config.most_recent.episode_number])
|
171
|
-
await play(link, config.most_recent)
|
172
|
-
process.exit()
|
173
|
-
}
|
174
|
-
|
175
|
-
|
176
|
-
function RegexParse(str, rule) {
|
177
|
-
let escapeRegex = (str) => str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
|
178
|
-
return new RegExp("^" + rule.split("*").map(escapeRegex).join(".*") + "$").test(str);
|
179
|
-
}
|
180
|
-
|
181
|
-
async function search_anime(search){
|
182
|
-
let filter = "*<ahref=\"/category/*\"title=\"*\">"
|
183
|
-
let html = (await curl("https://gogoanime.dk//search.html?keyword="+search)).split("\n")
|
184
|
-
let lines = []
|
185
|
-
for (x in html){
|
186
|
-
html[x] = html[x].replaceAll(/ /g,'').replaceAll(/\t/g,'')
|
187
|
-
if (RegexParse(html[x], filter)){
|
188
|
-
html[x] = html[x].slice(html[x].indexOf("/category/")+10);
|
189
|
-
html[x] = html[x].slice(0, html[x].indexOf("\"title="));
|
190
|
-
lines.push(html[x])
|
191
|
-
}
|
192
|
-
}
|
193
|
-
if (!lines[0]){
|
194
|
-
lines.pop()
|
195
|
-
}
|
196
|
-
|
197
|
-
|
198
|
-
return lines
|
199
|
-
}
|
200
|
-
|
201
|
-
async function episode_list(anime_id){
|
202
|
-
let html = (await curl(base_url+"/v1/"+anime_id)).split("\n")
|
203
|
-
let lines = ""
|
204
|
-
|
205
|
-
for (let x in html){
|
206
|
-
if(RegexParse(html[x], "*<div id=\"epslistplace\"*")){
|
207
|
-
lines = (html[x])
|
208
|
-
}
|
209
|
-
}
|
210
|
-
|
211
|
-
lines = lines.slice(55, lines.length).replace("}</div>", "")
|
212
|
-
lines = "{" + lines.slice(lines.indexOf(",")+1, lines.length) + "}"
|
213
|
-
lines = JSON.parse(lines)
|
214
|
-
|
215
|
-
let json = []
|
216
|
-
for (x in lines){
|
217
|
-
json.push(lines[x])
|
218
|
-
}
|
219
|
-
return json
|
220
|
-
}
|
221
|
-
|
222
|
-
function download(link, file_name){
|
223
|
-
if (link.includes("m3u8")) console.log(colors.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.");
|
224
|
-
let option = {
|
225
|
-
filename: link.includes("m3u8") ? file_name.replace("mp4", "m3u8") : file_name,
|
226
|
-
dir: config.download_folder,
|
227
|
-
onDone: (info)=>{
|
228
|
-
console.log(colors.Green, `\n -- Download finished -- \nLocation: ${info.path}\nSize: ${Math.round(info.size/100000)*10} Bytes`);
|
229
|
-
return 0;
|
230
|
-
},
|
231
|
-
onError: (err) => {
|
232
|
-
console.log(colors.Red, 'error', err);
|
233
|
-
},
|
234
|
-
onProgress: (curr, total) => {
|
235
|
-
process.stdout.clearLine(0);
|
236
|
-
process.stdout.cursorTo(0);
|
237
|
-
if (config.download_progress_bar){
|
238
|
-
process.stdout.write("\x1b[32m -- "+(curr / total * 100).toFixed(2)+"% "+"#". repeat(Math.ceil((curr / total)*(process.stdout.columns-20)))+"~".repeat(Math.ceil((process.stdout.columns-20) - (curr / total)*(process.stdout.columns-20)))+" -- \x1b[0m")
|
239
|
-
|
240
|
-
}else{
|
241
|
-
process.stdout.write(('\x1b[32m -- progress '+ (curr / total * 100).toFixed(2) + '% -- \x1b[0m'));
|
242
|
-
}
|
243
|
-
},
|
244
|
-
}
|
245
|
-
console.log(colors.White, `${option.dir}/${option.filename}`)
|
246
|
-
|
247
|
-
return dl(link, option);
|
248
|
-
|
249
|
-
}
|
250
|
-
|
251
|
-
async function selection(options, prompt, extra_options = []){
|
252
|
-
let selection = 0
|
253
|
-
while (true){
|
254
|
-
selection = (await input(prompt))
|
255
|
-
if ((selection <= options && selection >= 1) || extra_options.includes(selection)){
|
256
|
-
break
|
257
|
-
}
|
258
|
-
console.log(colors.Red,`Please input a valid option.`)
|
259
|
-
}
|
260
|
-
return selection
|
261
|
-
}
|
262
|
-
|
263
|
-
async function process_search(query) {
|
264
|
-
console.log(colors.Yellow, "Searching: "+query)
|
265
|
-
|
266
|
-
let search_results = await search_anime(query)
|
267
|
-
if (!search_results[0]) {
|
268
|
-
console.log(colors.Red, "No results.")
|
269
|
-
await main()
|
270
|
-
process.exit()
|
271
|
-
} else {
|
272
|
-
for (x in search_results) {
|
273
|
-
console.log(colors.Cyan,`${parseInt(x)+1})${" ".repeat(((search_results.length).toString().length+1)-((parseInt(x)+1).toString().length))}${search_results[x].replaceAll("-", " ")}`)
|
274
|
-
}
|
275
|
-
}
|
276
|
-
|
277
|
-
let anime_id = search_results[await selection(search_results.length, "Please select an anime.")-1]
|
278
|
-
let episodes = await episode_list(anime_id)
|
279
|
-
let episode_number = 0;
|
280
|
-
if (episodes.length > 1){
|
281
|
-
episode_number = (await selection(episodes.length, `Please select an episode (1-${episodes.length}).`))-1
|
282
|
-
}
|
283
|
-
return {
|
284
|
-
anime_id: anime_id,
|
285
|
-
episodes: episodes,
|
286
|
-
episode_number: episode_number
|
287
|
-
}
|
288
|
-
}
|
289
|
-
|
290
|
-
async function get_video_link(episode_dpage){
|
291
|
-
let id = episode_dpage.replace("//gogohd.net/streaming.php?id=","")
|
292
|
-
id = id.slice(0, id.indexOf("="))
|
293
|
-
let link = await generate_link(1,id)
|
294
|
-
if (!link){
|
295
|
-
link = await generate_link(2,id)
|
296
|
-
}
|
297
|
-
return link
|
298
|
-
}
|
299
|
-
|
300
|
-
async function generate_link(provider, id){
|
301
|
-
let html = ""
|
302
|
-
let provider_name = ""
|
303
|
-
switch (provider) {
|
304
|
-
case 1:
|
305
|
-
html = await curl(`${gogohd_url}streaming.php?id=${id}`)
|
306
|
-
provider_name = 'Xstreamcdn'
|
307
|
-
console.log(colors.Yellow, `Fetching ${provider_name} links...`)
|
308
|
-
html = html.split("\n")
|
309
|
-
let fb_id = ""
|
310
|
-
for (x in html){
|
311
|
-
if (RegexParse(html[x], "*<li class=\"linkserver\" data-status=\"1\" data-video=\"https://fembed9hd.com/v/*")){
|
312
|
-
fb_id = html[x].slice(html[x].indexOf("/v/")+3, html[x].indexOf("\">X"))
|
313
|
-
break
|
314
|
-
}
|
315
|
-
}
|
316
|
-
if (!fb_id){
|
317
|
-
console.log("Error, no fb_id found.")
|
318
|
-
return 0
|
319
|
-
}
|
320
|
-
|
321
|
-
//let refr = "https://fembed-hd.com/v/"+fb_id
|
322
|
-
let post = await curl("https://fembed-hd.com/api/source/"+fb_id, "POST")
|
323
|
-
post = post.slice(post.indexOf(",\"data\":[{\"file\":\"")+18, post.length)
|
324
|
-
post = post.slice(0, post.indexOf("\"")).replaceAll("\\/","/")
|
325
|
-
return post
|
326
|
-
case 2:
|
327
|
-
provider_name = 'Animixplay'
|
328
|
-
let buffer = new Buffer(id)
|
329
|
-
let enc_id = buffer.toString("base64")
|
330
|
-
buffer = new Buffer(id+"LTXs3GrU8we9O"+enc_id)
|
331
|
-
let ani_id = buffer.toString("base64")
|
332
|
-
buffer = Buffer.from((await curl(`${base_url}/api/live${ani_id}`, "GET", true)).split("#")[1], "base64")
|
333
|
-
if (config.player === "BROWSER"){
|
334
|
-
return `${base_url}/api/live${ani_id}`
|
335
|
-
}
|
336
|
-
return buffer.toString("utf-8") //TODO m3u8 player
|
337
|
-
|
338
|
-
|
339
|
-
}
|
340
|
-
}
|
341
|
-
|
342
|
-
async function post_play(link, anime, player = null){
|
343
|
-
while (true){
|
344
|
-
config.most_recent = anime
|
345
|
-
write_config()
|
346
|
-
|
347
|
-
console.log(colors.Yellow, `Playing episode ${anime.episode_number+1} of ${anime.anime_id.replaceAll("-", " ")}\n`)
|
348
|
-
console.log(colors.Cyan, "1/l) Show Link")
|
349
|
-
console.log(colors.Cyan, "2/n) Next Episode")
|
350
|
-
console.log(colors.Cyan, "3/p) Prev Episode")
|
351
|
-
console.log(colors.Cyan, "4/d) Download")
|
352
|
-
console.log(colors.Cyan, "5/q) Quit")
|
353
|
-
switch (await selection(5, "select;", ["l", "n", "p", "d", "q"])){
|
354
|
-
case "l":
|
355
|
-
case "1":
|
356
|
-
console.log(colors.Yellow, "Link: "+link)
|
357
|
-
break
|
358
|
-
case "n":
|
359
|
-
case "2":
|
360
|
-
if (anime.episode_number > anime.episodes.length-2){
|
361
|
-
console.log(colors.Red, "Damn, all out of episodes?")
|
362
|
-
break
|
363
|
-
}
|
364
|
-
anime.episode_number += 1
|
365
|
-
link = await get_video_link(anime.episodes[anime.episode_number])
|
366
|
-
await play(link, anime, player)
|
367
|
-
process.exit()
|
368
|
-
break
|
369
|
-
//EVEN MORE NEEDLESS QUIT STATEMENTS!!!!!!
|
370
|
-
case "p":
|
371
|
-
case "3":
|
372
|
-
if (anime.episode_number < 2){
|
373
|
-
console.log(colors.Red, "Error; Episode 0 is only available for premium members")
|
374
|
-
break
|
375
|
-
}
|
376
|
-
anime.episode_number -= 1
|
377
|
-
link = await get_video_link(anime.episodes[anime.episode_number])
|
378
|
-
await play(link, anime, player)
|
379
|
-
process.exit()
|
380
|
-
break
|
381
|
-
case "d":
|
382
|
-
case "4":
|
383
|
-
console.log(colors.Yellow, "Beware of the dysfunctional await clause.")
|
384
|
-
await download(link, anime.anime_id+(anime.episode_number+1)+".mp4")
|
385
|
-
post_play(link, anime, player)
|
386
|
-
break
|
387
|
-
case "q":
|
388
|
-
case "5":
|
389
|
-
console.clear()
|
390
|
-
await main()
|
391
|
-
process.exit()
|
392
|
-
break
|
393
|
-
}
|
394
|
-
}
|
395
|
-
}
|
396
|
-
|
397
|
-
async function play(link, anime, player){
|
398
|
-
console.clear()
|
399
|
-
console.log(colors.Blue, "ANI-CLI-NPM \n")
|
400
|
-
if (config.player === "VLC"){
|
401
|
-
if (!player){
|
402
|
-
console.log(colors.Yellow, "Loading VLC... ")
|
403
|
-
player = new PlayerController({
|
404
|
-
app: 'vlc',
|
405
|
-
args: ['--fullscreen'],
|
406
|
-
media: link
|
407
|
-
});
|
408
|
-
await player.launch(err => {
|
409
|
-
if (err) return console.error(err.message);
|
410
|
-
});
|
411
|
-
}else{
|
412
|
-
player.quit()
|
413
|
-
console.log(colors.Yellow, "Loading VLC... ")
|
414
|
-
player = new PlayerController({
|
415
|
-
app: 'vlc',
|
416
|
-
args: ['--fullscreen'],
|
417
|
-
media: link
|
418
|
-
});
|
419
|
-
await player.launch(err => {
|
420
|
-
if (err) return console.error(err.message);
|
421
|
-
});
|
422
|
-
}
|
423
|
-
|
424
|
-
await post_play(link, anime, player)
|
425
|
-
process.exit()
|
426
|
-
|
427
|
-
|
428
|
-
}else if (config.player === "BROWSER"){
|
429
|
-
console.log(colors.Yellow, "Opening video in browser... ")
|
430
|
-
open(link)
|
431
|
-
await post_play(link, anime)
|
432
|
-
process.exit()
|
433
|
-
}else if (config.player === "MPV"){
|
434
|
-
if (!player){
|
435
|
-
console.log(colors.Yellow, "Loading MPV... ")
|
436
|
-
player = new PlayerController({
|
437
|
-
app: 'mpv',
|
438
|
-
args: ['--fullscreen'],
|
439
|
-
media: link
|
440
|
-
});
|
441
|
-
await player.launch(err => {
|
442
|
-
if (err) return console.error(err.message);
|
443
|
-
});
|
444
|
-
}else{
|
445
|
-
player.load(link)
|
446
|
-
}
|
447
|
-
|
448
|
-
await post_play(link, anime, player)
|
449
|
-
process.exit()
|
450
|
-
}
|
451
|
-
}
|
452
|
-
|
453
|
-
async function search(){
|
454
|
-
console.log(colors.Magenta, "Search...")
|
455
|
-
let choice = await input("")
|
456
|
-
let anime = await process_search(choice)
|
457
|
-
|
458
|
-
console.log("\n")
|
459
|
-
|
460
|
-
console.log(colors.Blue, "Indexing video...")
|
461
|
-
let link = await get_video_link(anime.episodes[anime.episode_number])
|
462
|
-
if (!link){
|
463
|
-
console.log(colors.Red, "Np link for this episode found?")
|
464
|
-
console.log(colors.Yellow, "^ at current this is due to not all of the required video repos being implemented.")
|
465
|
-
console.log(colors.Yellow, "Sorry for any inconvenience, this should soon by implemented. We appreciate your patience.")
|
466
|
-
process.exit()
|
467
|
-
}
|
468
|
-
console.log(colors.Blue, `Episode ${anime.episode_number+1} of ${anime.anime_id.replaceAll("-", " ")} found.\n`)
|
469
|
-
if (link.includes("animixplay.to") && config.player === "VLC"){
|
470
|
-
console.log(colors.Red, "Warning; animix.to uses m3u8 playlists. Without custom plugins, VLC will not be able to play this file format. It is recomended to use another player for this show/film.")
|
471
|
-
}
|
472
|
-
console.log(colors.Cyan, "1/p) Play")
|
473
|
-
console.log(colors.Cyan, "2/d) Download")
|
474
|
-
console.log(colors.Cyan, "3/l) Show Link")
|
475
|
-
console.log(colors.Cyan, "4/q) quit")
|
476
|
-
choice = (await selection(4, "select;", ["p", "d", "l", "q"]))
|
477
|
-
switch (choice){
|
478
|
-
case "p":
|
479
|
-
case "1":
|
480
|
-
await play(link, anime, null)
|
481
|
-
break
|
482
|
-
case "d":
|
483
|
-
case "2":
|
484
|
-
await download(link, anime.anime_id+(anime.episode_number+1)+".mp4")
|
485
|
-
break
|
486
|
-
case "l":
|
487
|
-
case "3":
|
488
|
-
console.log(colors.Yellow, "Link: "+link)
|
489
|
-
console.log(colors.Cyan, "\n1/p) Play")
|
490
|
-
console.log(colors.Cyan, "2/d) Download")
|
491
|
-
console.log(colors.Cyan, "3/q) quit")
|
492
|
-
choice = (await selection(3, "select;", ["p", "d", "q"]))
|
493
|
-
switch (choice){
|
494
|
-
case "p":
|
495
|
-
case "1":
|
496
|
-
await play(link, anime, null)
|
497
|
-
break
|
498
|
-
case "d":
|
499
|
-
case "2":
|
500
|
-
await download(link, anime.anime_id+anime.episode_number+".mp4")
|
501
|
-
break
|
502
|
-
case "q":
|
503
|
-
case "3":
|
504
|
-
await main()
|
505
|
-
process.exit()
|
506
|
-
}
|
507
|
-
break
|
508
|
-
case "q":
|
509
|
-
case "4":
|
510
|
-
await main()
|
511
|
-
process.exit()
|
512
|
-
}
|
513
|
-
}
|
514
|
-
|
515
|
-
|
516
|
-
console.clear()
|
517
|
-
read_config()
|
518
|
-
console.log(colors.Blue, "Welcome to Ani-Cli-npm\n")
|
519
|
-
if (config.most_recent.episode_number !== 0){
|
520
|
-
console.log(colors.White, `Most recently played: ${config.most_recent.anime_id}, ep${config.most_recent.episode_number+1}`)
|
521
|
-
}
|
522
|
-
async function main(){
|
523
|
-
if (config.player === "VLC"){
|
524
|
-
console.log(colors.Red, "Warning; if you do not have mpv video player installed, you will have to change your video player to either vlc or browser in config.\n")
|
525
|
-
}
|
526
|
-
console.log(colors.Cyan, "\n1/s) Search")
|
527
|
-
if (config.most_recent.episode_number !== 0){
|
528
|
-
console.log(colors.Cyan, "2/c) Continue")
|
529
|
-
}else{
|
530
|
-
console.log(colors.White, "2/c) Continue")
|
531
|
-
}
|
532
|
-
console.log(colors.Cyan, "3/C) Config")
|
533
|
-
console.log(colors.Cyan, "4/q) Quit")
|
534
|
-
let choice = await selection(4, "select;", ["s", "c", "C", "q"])
|
535
|
-
switch (choice){
|
536
|
-
case "s":
|
537
|
-
case "1":
|
538
|
-
await search()
|
539
|
-
break
|
540
|
-
case "c":
|
541
|
-
case "2":
|
542
|
-
if (config.most_recent.episode_number !== 0){
|
543
|
-
await _continue()
|
544
|
-
}else{
|
545
|
-
console.log(colors.White, "No episodes watched recently")
|
546
|
-
await main()
|
547
|
-
}
|
548
|
-
|
549
|
-
break
|
550
|
-
case "C":
|
551
|
-
case "3":
|
552
|
-
let temp = structuredClone(config);
|
553
|
-
let exit_code;
|
554
|
-
while (true) {
|
555
|
-
temp, exit_code = await config_(temp)
|
556
|
-
if (exit_code === 1) {
|
557
|
-
config = temp
|
558
|
-
//proxyAgent = new HttpsProxyAgent(config.proxy);
|
559
|
-
console.clear()
|
560
|
-
console.log(colors.Blue, "ANI-CLI-NPM \n")
|
561
|
-
console.log(colors.Yellow, "Config changed.")
|
562
|
-
break
|
563
|
-
} else if (exit_code === 2) {
|
564
|
-
temp = config
|
565
|
-
console.clear()
|
566
|
-
console.log(colors.Blue, "ANI-CLI-NPM \n")
|
567
|
-
console.log(colors.Yellow, "Config changes disregarded.")
|
568
|
-
break
|
569
|
-
}
|
570
|
-
}
|
571
|
-
try{
|
572
|
-
fs.writeFileSync(getAppDataPath()+"/ani-cli-npm.conf", JSON.stringify(config))
|
573
|
-
}catch{
|
574
|
-
console.log(colors.Red, "Error writing to .conf file.")
|
575
|
-
}
|
576
|
-
await main()
|
577
|
-
break
|
578
|
-
case "q":
|
579
|
-
case "4":
|
580
|
-
console.log(colors.Black, "Exiting...")
|
581
|
-
process.exit()
|
582
|
-
}
|
583
|
-
}
|
584
|
-
|
585
|
-
|
586
|
-
main()
|