aw-cli 2.1__tar.gz → 2.1.2__tar.gz
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.
- {aw_cli-2.1 → aw_cli-2.1.2}/PKG-INFO +5 -4
- {aw_cli-2.1 → aw_cli-2.1.2}/README.md +1 -1
- {aw_cli-2.1 → aw_cli-2.1.2}/aw_cli.egg-info/PKG-INFO +5 -4
- {aw_cli-2.1 → aw_cli-2.1.2}/aw_cli.egg-info/requires.txt +1 -1
- {aw_cli-2.1 → aw_cli-2.1.2}/awcli/anilist.py +8 -15
- {aw_cli-2.1 → aw_cli-2.1.2}/awcli/run.py +103 -118
- {aw_cli-2.1 → aw_cli-2.1.2}/awcli/utilities.py +31 -39
- aw_cli-2.1.2/awcli/version.py +1 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/setup.py +3 -3
- aw_cli-2.1/awcli/version.py +0 -1
- {aw_cli-2.1 → aw_cli-2.1.2}/LICENSE +0 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/aw_cli.egg-info/SOURCES.txt +0 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/aw_cli.egg-info/dependency_links.txt +0 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/aw_cli.egg-info/entry_points.txt +0 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/aw_cli.egg-info/top_level.txt +0 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/awcli/__init__.py +0 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/awcli/anime.py +0 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/awcli/arg_parser.py +0 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/setup.cfg +0 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/tests/test_anime.py +0 -0
- {aw_cli-2.1 → aw_cli-2.1.2}/tests/test_utilities.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: aw-cli
|
|
3
|
-
Version: 2.1
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: guarda anime dal terminale e molto altro!
|
|
5
5
|
Home-page: https://github.com/fexh10/aw-cli
|
|
6
6
|
Author: fexh10
|
|
@@ -9,15 +9,16 @@ Requires-Python: >3.10
|
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Dist: requests
|
|
12
|
-
Requires-Dist: lxml
|
|
13
12
|
Requires-Dist: pySmartDL
|
|
14
13
|
Requires-Dist: wheel
|
|
15
14
|
Requires-Dist: regex
|
|
15
|
+
Requires-Dist: toml
|
|
16
16
|
Dynamic: author
|
|
17
17
|
Dynamic: description
|
|
18
18
|
Dynamic: description-content-type
|
|
19
19
|
Dynamic: home-page
|
|
20
20
|
Dynamic: license
|
|
21
|
+
Dynamic: license-file
|
|
21
22
|
Dynamic: requires-dist
|
|
22
23
|
Dynamic: requires-python
|
|
23
24
|
Dynamic: summary
|
|
@@ -93,7 +94,7 @@ Android richiede l'installazione di <a href="https://github.com/termux/termux-ap
|
|
|
93
94
|
|
|
94
95
|
```
|
|
95
96
|
pkg update && pkg upgrade
|
|
96
|
-
pkg install python python-pip
|
|
97
|
+
pkg install python python-pip fzf
|
|
97
98
|
python3 -m pip install aw-cli
|
|
98
99
|
```
|
|
99
100
|
</details>
|
|
@@ -69,7 +69,7 @@ Android richiede l'installazione di <a href="https://github.com/termux/termux-ap
|
|
|
69
69
|
|
|
70
70
|
```
|
|
71
71
|
pkg update && pkg upgrade
|
|
72
|
-
pkg install python python-pip
|
|
72
|
+
pkg install python python-pip fzf
|
|
73
73
|
python3 -m pip install aw-cli
|
|
74
74
|
```
|
|
75
75
|
</details>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: aw-cli
|
|
3
|
-
Version: 2.1
|
|
3
|
+
Version: 2.1.2
|
|
4
4
|
Summary: guarda anime dal terminale e molto altro!
|
|
5
5
|
Home-page: https://github.com/fexh10/aw-cli
|
|
6
6
|
Author: fexh10
|
|
@@ -9,15 +9,16 @@ Requires-Python: >3.10
|
|
|
9
9
|
Description-Content-Type: text/markdown
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Requires-Dist: requests
|
|
12
|
-
Requires-Dist: lxml
|
|
13
12
|
Requires-Dist: pySmartDL
|
|
14
13
|
Requires-Dist: wheel
|
|
15
14
|
Requires-Dist: regex
|
|
15
|
+
Requires-Dist: toml
|
|
16
16
|
Dynamic: author
|
|
17
17
|
Dynamic: description
|
|
18
18
|
Dynamic: description-content-type
|
|
19
19
|
Dynamic: home-page
|
|
20
20
|
Dynamic: license
|
|
21
|
+
Dynamic: license-file
|
|
21
22
|
Dynamic: requires-dist
|
|
22
23
|
Dynamic: requires-python
|
|
23
24
|
Dynamic: summary
|
|
@@ -93,7 +94,7 @@ Android richiede l'installazione di <a href="https://github.com/termux/termux-ap
|
|
|
93
94
|
|
|
94
95
|
```
|
|
95
96
|
pkg update && pkg upgrade
|
|
96
|
-
pkg install python python-pip
|
|
97
|
+
pkg install python python-pip fzf
|
|
97
98
|
python3 -m pip install aw-cli
|
|
98
99
|
```
|
|
99
100
|
</details>
|
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
import requests
|
|
2
2
|
|
|
3
|
-
tokenAnilist = "tokenAnilist: False"
|
|
4
|
-
user_id = 0
|
|
5
|
-
ratingAnilist = False
|
|
6
|
-
preferitoAnilist = False
|
|
7
|
-
dropAnilist = False
|
|
8
|
-
|
|
9
3
|
class TokenError(Exception):
|
|
10
4
|
pass
|
|
11
5
|
|
|
12
|
-
|
|
13
|
-
def updateAnilist(id_anilist: int, ep: int, status_list: str, score: float, favourite: bool = False) -> None:
|
|
6
|
+
def updateAnilist(token, id_anilist: int, ep: int, status_list: str, score: float, favourite: bool = False) -> None:
|
|
14
7
|
"""
|
|
15
8
|
Collegamento alle API di AniList per aggiornare lo stato dell'anime
|
|
16
9
|
|
|
@@ -47,10 +40,10 @@ def updateAnilist(id_anilist: int, ep: int, status_list: str, score: float, favo
|
|
|
47
40
|
if score != 0:
|
|
48
41
|
var["score"] = score
|
|
49
42
|
|
|
50
|
-
requestModifyAnilist(query, var)
|
|
43
|
+
requestModifyAnilist(token, query, var)
|
|
51
44
|
|
|
52
45
|
|
|
53
|
-
def getAnilistUserId() -> int:
|
|
46
|
+
def getAnilistUserId(token) -> int:
|
|
54
47
|
"""
|
|
55
48
|
Collegamento alle API di AniList per trovare
|
|
56
49
|
l'id dell'utente in base al token AniList dell'utente.
|
|
@@ -67,7 +60,7 @@ def getAnilistUserId() -> int:
|
|
|
67
60
|
}
|
|
68
61
|
"""
|
|
69
62
|
|
|
70
|
-
header_anilist = {'Authorization': 'Bearer ' +
|
|
63
|
+
header_anilist = {'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json', 'Accept': 'application/json'}
|
|
71
64
|
risposta = requests.post('https://graphql.anilist.co',headers=header_anilist,json={'query' : query})
|
|
72
65
|
if risposta.status_code != 200:
|
|
73
66
|
raise TokenError("Errore: Token AniList sbagliato")
|
|
@@ -77,7 +70,7 @@ def getAnilistUserId() -> int:
|
|
|
77
70
|
return user_id
|
|
78
71
|
|
|
79
72
|
|
|
80
|
-
def getAnimePrivateRating(id_anime: int) -> (float | None):
|
|
73
|
+
def getAnimePrivateRating(token, user_id, id_anime: int) -> (float | None):
|
|
81
74
|
"""
|
|
82
75
|
Collegamento alle API di AniList per trovare
|
|
83
76
|
il voto dato all'anime dall'utente.
|
|
@@ -102,7 +95,7 @@ def getAnimePrivateRating(id_anime: int) -> (float | None):
|
|
|
102
95
|
}
|
|
103
96
|
|
|
104
97
|
header_anilist = {
|
|
105
|
-
'Authorization': 'Bearer '
|
|
98
|
+
'Authorization': f'Bearer {token}',
|
|
106
99
|
'Content-Type': 'application/json', 'Accept': 'application/json'
|
|
107
100
|
}
|
|
108
101
|
|
|
@@ -113,7 +106,7 @@ def getAnimePrivateRating(id_anime: int) -> (float | None):
|
|
|
113
106
|
return float(risposta.json()["data"]["MediaList"]["score"])
|
|
114
107
|
|
|
115
108
|
|
|
116
|
-
def requestModifyAnilist(query: str, var: dict):
|
|
109
|
+
def requestModifyAnilist(token, query: str, var: dict):
|
|
117
110
|
"""
|
|
118
111
|
Request alle API di Anilist.
|
|
119
112
|
Se la richiesta non va a buon fine, viene stampato un errore.
|
|
@@ -123,7 +116,7 @@ def requestModifyAnilist(query: str, var: dict):
|
|
|
123
116
|
var (dict): dizionario che contiene le variabili da passare alla query.
|
|
124
117
|
"""
|
|
125
118
|
|
|
126
|
-
header_anilist = {'Authorization': 'Bearer ' +
|
|
119
|
+
header_anilist = {'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json', 'Accept': 'application/json'}
|
|
127
120
|
risposta = requests.post('https://graphql.anilist.co',headers=header_anilist,json={'query' : query, 'variables' : var})
|
|
128
121
|
|
|
129
122
|
if risposta.status_code != 200:
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import re
|
|
2
3
|
import csv
|
|
3
4
|
from signal import signal, SIGINT
|
|
4
5
|
from concurrent.futures import ThreadPoolExecutor
|
|
5
6
|
from pySmartDL import SmartDL
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from threading import Thread
|
|
8
|
-
from awcli
|
|
9
|
+
from awcli import anilist, utilities as ut
|
|
10
|
+
from awcli.anime import Anime
|
|
9
11
|
from awcli.arg_parser import *
|
|
10
|
-
import awcli.anilist as anilist
|
|
11
12
|
|
|
12
13
|
def safeExit():
|
|
13
14
|
with open(f"{os.path.dirname(__file__)}/aw-cronologia.csv", 'w', newline='', encoding='utf-8') as file:
|
|
14
15
|
csv.writer(file).writerows(log)
|
|
15
16
|
exit()
|
|
16
17
|
|
|
17
|
-
signal(SIGINT, safeExit)
|
|
18
|
+
signal(SIGINT, lambda signum, frame: safeExit())
|
|
18
19
|
|
|
19
20
|
def fzf(elementi: list[str], prompt: str = "> ", multi: bool = False, cls: bool = False, esci: bool = True) -> str:
|
|
20
21
|
"""
|
|
@@ -33,7 +34,7 @@ def fzf(elementi: list[str], prompt: str = "> ", multi: bool = False, cls: bool
|
|
|
33
34
|
"""
|
|
34
35
|
|
|
35
36
|
if cls:
|
|
36
|
-
my_print("",end="", cls=True)
|
|
37
|
+
ut.my_print("", end="", cls=True)
|
|
37
38
|
string = "\n".join(elementi)
|
|
38
39
|
comando = f"""fzf --tac --height={len(elementi) + 2} --cycle --ansi --tiebreak=begin --prompt="{prompt}" """
|
|
39
40
|
if multi:
|
|
@@ -58,12 +59,12 @@ def RicercaAnime() -> list[Anime]:
|
|
|
58
59
|
def check_search(s: str):
|
|
59
60
|
if s == "exit":
|
|
60
61
|
safeExit()
|
|
61
|
-
result = search(s)
|
|
62
|
+
result = ut.search(s)
|
|
62
63
|
if len(result) != 0:
|
|
63
64
|
return result
|
|
64
65
|
|
|
65
|
-
my_print("", end="", cls=True)
|
|
66
|
-
return my_input("Cerca un anime", check_search,"La ricerca non ha prodotto risultati", cls = True)
|
|
66
|
+
ut.my_print("", end="", cls=True)
|
|
67
|
+
return ut.my_input("Cerca un anime", check_search,"La ricerca non ha prodotto risultati", cls = True)
|
|
67
68
|
|
|
68
69
|
|
|
69
70
|
def animeScaricati(path: str) -> list[Anime]:
|
|
@@ -79,7 +80,7 @@ def animeScaricati(path: str) -> list[Anime]:
|
|
|
79
80
|
nomi = os.listdir(path)
|
|
80
81
|
|
|
81
82
|
if len(nomi) == 0:
|
|
82
|
-
my_print("Nessun anime scaricato", color='rosso')
|
|
83
|
+
ut.my_print("Nessun anime scaricato", color='rosso')
|
|
83
84
|
safeExit()
|
|
84
85
|
|
|
85
86
|
animes = list[Anime]()
|
|
@@ -100,10 +101,10 @@ def scegliEpisodi() -> list[int]:
|
|
|
100
101
|
"""
|
|
101
102
|
|
|
102
103
|
|
|
103
|
-
my_print(anime.name, cls=True)
|
|
104
|
+
ut.my_print(anime.name, cls=True)
|
|
104
105
|
#se contiene solo 1 ep sarà riprodotto automaticamente
|
|
105
106
|
if anime.ep == 1:
|
|
106
|
-
return 1
|
|
107
|
+
return [1]
|
|
107
108
|
|
|
108
109
|
ep = [str(i) for i in range(anime.ep, anime.ep_ini - 1, -1)]
|
|
109
110
|
return sorted([int(ep) for ep in fzf(ep, "Scegli un episodio: ", multi=downl).split("\n")])
|
|
@@ -121,7 +122,7 @@ def downloadPath(create: bool = True) -> str:
|
|
|
121
122
|
str: il percorso di download dell'anime.
|
|
122
123
|
"""
|
|
123
124
|
|
|
124
|
-
if (nome_os == "Android"):
|
|
125
|
+
if (ut.nome_os == "Android"):
|
|
125
126
|
path = f"/sdcard/Movies/Anime"
|
|
126
127
|
else:
|
|
127
128
|
path = f"{Path.home()}/Videos/Anime"
|
|
@@ -144,12 +145,12 @@ def scaricaEpisodio(ep: int, path: str):
|
|
|
144
145
|
nome_video = anime.ep_name(ep)
|
|
145
146
|
|
|
146
147
|
# se l'episodio non è ancora stato scaricato lo scarico, altrimenti skippo
|
|
147
|
-
my_print(nome_video, color="blu", end=":\n")
|
|
148
|
+
ut.my_print(nome_video, color="blu", end=":\n")
|
|
148
149
|
if not os.path.exists(f"{path}/{nome_video}.mp4"):
|
|
149
150
|
SDL = SmartDL(url_ep, f"{path}/{nome_video}.mp4")
|
|
150
151
|
SDL.start()
|
|
151
152
|
else:
|
|
152
|
-
my_print("già scaricato, skippo...", color="giallo")
|
|
153
|
+
ut.my_print("già scaricato, skippo...", color="giallo")
|
|
153
154
|
|
|
154
155
|
def openSyncplay(url_ep: str, nome_video: str, progress: int) -> tuple[bool, int]:
|
|
155
156
|
"""
|
|
@@ -165,24 +166,24 @@ def openSyncplay(url_ep: str, nome_video: str, progress: int) -> tuple[bool, int
|
|
|
165
166
|
int: il progresso dell'episodio.
|
|
166
167
|
"""
|
|
167
168
|
|
|
168
|
-
if
|
|
169
|
-
my_print("Aggiornare il path di syncplay nella configurazione tramite: aw-cli -a", color="rosso")
|
|
169
|
+
if "syncplay" not in ut.configData:
|
|
170
|
+
ut.my_print("Aggiornare il path di syncplay nella configurazione tramite: aw-cli -a", color="rosso")
|
|
170
171
|
safeExit()
|
|
171
172
|
|
|
172
173
|
|
|
173
174
|
args = f'''--force-media-title="{nome_video}" --start="{progress}" --fullscreen --keep-open'''
|
|
174
|
-
if
|
|
175
|
+
if ut.configData["player"]["type"] == "vlc":
|
|
175
176
|
args = f'''--meta-title "{nome_video}" --start-time="{progress}" --fullscreen'''
|
|
176
177
|
|
|
177
178
|
try :
|
|
178
|
-
out = os.popen(f'''{
|
|
179
|
+
out = os.popen(f'''{ut.configData["syncplay"]["path"]} -d --language it "{url_ep}" -- {args} 2>&1''').read()
|
|
179
180
|
except UnicodeDecodeError:
|
|
180
181
|
out = ""
|
|
181
182
|
|
|
182
183
|
duration_match = re.findall(r'duration(?:-change)?"?: (\d+)\.?[\d]*', out)
|
|
183
184
|
progress_match = re.findall(r'pos(?:ition"?)?:? (\d+).?\d+', out)
|
|
184
185
|
if not duration_match:
|
|
185
|
-
my_print("Errore, impossibile leggere l'output di Syncplay!", color="rosso")
|
|
186
|
+
ut.my_print("Errore, impossibile leggere l'output di Syncplay!", color="rosso")
|
|
186
187
|
return False, 0
|
|
187
188
|
|
|
188
189
|
duration = max(map(int, duration_match))
|
|
@@ -207,11 +208,11 @@ def openMPV(url_ep: str, nome_video: str, progress: int) -> tuple[bool, int]:
|
|
|
207
208
|
"""
|
|
208
209
|
|
|
209
210
|
|
|
210
|
-
if (nome_os == "Android"):
|
|
211
|
+
if (ut.nome_os == "Android"):
|
|
211
212
|
os.system(f'''am start --user 0 -a android.intent.action.VIEW -d "{url_ep}" -n is.xyz.mpv/.MPVActivity > /dev/null 2>&1''')
|
|
212
213
|
return True, 0
|
|
213
214
|
|
|
214
|
-
out = os.popen(f'''{
|
|
215
|
+
out = os.popen(f'''{ut.configData["player"]["path"]} "{url_ep}" --force-media-title="{nome_video}" --start="{progress}" --fullscreen --keep-open 2>&1''')
|
|
215
216
|
|
|
216
217
|
res = re.findall(r'(\d+):(\d+):(\d+) / [\d:]+ \((\d+)%\)', out.read())[-1]
|
|
217
218
|
progress = (int(res[0]) * 3600) + (int(res[1]) * 60) + int(res[2])
|
|
@@ -233,11 +234,11 @@ def openVLC(url_ep: str, nome_video: str, progress: int) -> tuple[bool, int]:
|
|
|
233
234
|
int: il progresso dell'episodio.
|
|
234
235
|
"""
|
|
235
236
|
|
|
236
|
-
if nome_os == "Android":
|
|
237
|
+
if ut.nome_os == "Android":
|
|
237
238
|
os.system(f'''am start --user 0 -a android.intent.action.VIEW -d "{url_ep}" -n org.videolan.vlc/.StartActivity -e "title" "{nome_video}" > /dev/null 2>&1''')
|
|
238
239
|
return True, 0
|
|
239
240
|
|
|
240
|
-
os.system(f'''{
|
|
241
|
+
os.system(f'''{ut.configData["player"]["path"]} "{url_ep}" --meta-title "{nome_video}" --start-time="{progress}" --fullscreen > /dev/null 2>&1''')
|
|
241
242
|
|
|
242
243
|
# se il file di configurazione di VLC esiste, prendo la posizione dell'ultimo episodio riprodotto
|
|
243
244
|
progress = 0
|
|
@@ -318,7 +319,7 @@ def updateAnilist(ep: int, voto_anilist: float, drop: bool = False):
|
|
|
318
319
|
"""
|
|
319
320
|
|
|
320
321
|
if anime.id_anilist == 0:
|
|
321
|
-
my_print("Impossibile aggiornare AniList: id anime non trovato!", color="rosso")
|
|
322
|
+
ut.my_print("Impossibile aggiornare AniList: id anime non trovato!", color="rosso")
|
|
322
323
|
return
|
|
323
324
|
|
|
324
325
|
voto = 0
|
|
@@ -331,16 +332,16 @@ def updateAnilist(ep: int, voto_anilist: float, drop: bool = False):
|
|
|
331
332
|
status_list = 'COMPLETED'
|
|
332
333
|
|
|
333
334
|
#chiedo di votare
|
|
334
|
-
if anilist
|
|
335
|
+
if ut.configData["anilist"]["rating"]:
|
|
335
336
|
is_number = lambda n: float(n) if n.replace('.', '', 1).isdigit() else None
|
|
336
|
-
voto = my_input("Inserisci un voto per l'anime" + (f" (voto corrente: {voto_anilist})" if voto_anilist else ""), is_number)
|
|
337
|
+
voto = ut.my_input("Inserisci un voto per l'anime" + (f" (voto corrente: {voto_anilist})" if voto_anilist else ""), is_number)
|
|
337
338
|
|
|
338
339
|
#chiedo di mettere tra i preferiti
|
|
339
|
-
if anilist
|
|
340
|
-
my_print(f"Riproduco {anime.name} Ep. {anime.ep}", color="giallo", cls=True)
|
|
340
|
+
if ut.configData["anilist"]["favorite"] and status_list == 'COMPLETED':
|
|
341
|
+
ut.my_print(f"Riproduco {anime.name} Ep. {anime.ep}", color="giallo", cls=True)
|
|
341
342
|
preferiti = fzf(["sì","no"], "Mettere l'anime tra i preferiti? ") == "sì"
|
|
342
343
|
|
|
343
|
-
Thread(target=anilist.updateAnilist, args=(anime.id_anilist, ep, status_list, voto, preferiti)).start()
|
|
344
|
+
Thread(target=anilist.updateAnilist, args=(ut.configData["anilist"]["token"],anime.id_anilist, ep, status_list, voto, preferiti)).start()
|
|
344
345
|
|
|
345
346
|
|
|
346
347
|
def openVideos(ep: int):
|
|
@@ -358,18 +359,18 @@ def openVideos(ep: int):
|
|
|
358
359
|
path = f"{downloadPath(create=False)}/{anime.name}/{nome_video}.mp4"
|
|
359
360
|
|
|
360
361
|
if os.path.exists(path):
|
|
361
|
-
url_ep = "file://" + path if nome_os == "Android" else path
|
|
362
|
+
url_ep = "file://" + path if ut.nome_os == "Android" else path
|
|
362
363
|
elif offline:
|
|
363
|
-
my_print(f"Episodio {nome_video} non scaricato, skippo...", color='giallo')
|
|
364
|
+
ut.my_print(f"Episodio {nome_video} non scaricato, skippo...", color='giallo')
|
|
364
365
|
return
|
|
365
366
|
else:
|
|
366
367
|
url_ep = anime.get_episodio(ep)
|
|
367
368
|
|
|
368
|
-
if not (offline or privato) and anilist
|
|
369
|
+
if not (offline or privato) and "anilist" in ut.configData:
|
|
369
370
|
executor = ThreadPoolExecutor(max_workers=1)
|
|
370
|
-
voto_anilist = executor.submit(anilist.getAnimePrivateRating, anime.id_anilist)
|
|
371
|
+
voto_anilist = executor.submit(anilist.getAnimePrivateRating, ut.configData["anilist"]["token"], ut.configData["anilist"]["user_id"], anime.id_anilist)
|
|
371
372
|
|
|
372
|
-
my_print(f"Riproduco {nome_video}...", color="giallo", cls=True)
|
|
373
|
+
ut.my_print(f"Riproduco {nome_video}...", color="giallo", cls=True)
|
|
373
374
|
progress = anime.progress[ep]
|
|
374
375
|
completed, progress = openPlayer(url_ep, nome_video, progress)
|
|
375
376
|
|
|
@@ -379,7 +380,7 @@ def openVideos(ep: int):
|
|
|
379
380
|
progress = 0
|
|
380
381
|
anime.ep_corrente = ep
|
|
381
382
|
#update watchlist anilist se ho fatto l'accesso
|
|
382
|
-
if not offline and anilist
|
|
383
|
+
if not offline and "anilist" in ut.configData:
|
|
383
384
|
updateAnilist(ep, voto_anilist.result())
|
|
384
385
|
else:
|
|
385
386
|
anime.ep_corrente = ep - 1
|
|
@@ -418,79 +419,79 @@ def getCronologia() -> list[Anime]:
|
|
|
418
419
|
|
|
419
420
|
#se il file esiste ma non contiene dati stampo un messaggio di errore
|
|
420
421
|
if len(animes) == 0:
|
|
421
|
-
my_print("Cronologia inesistente!", color='rosso')
|
|
422
|
+
ut.my_print("Cronologia inesistente!", color='rosso')
|
|
422
423
|
safeExit()
|
|
423
424
|
return animes
|
|
424
425
|
|
|
425
426
|
|
|
426
427
|
def setupConfig() -> None:
|
|
427
428
|
"""
|
|
428
|
-
Crea un file di configurazione chiamato "
|
|
429
|
+
Crea un file di configurazione chiamato "config.toml"
|
|
429
430
|
nella stessa directory dello script.
|
|
430
431
|
Le informazioni riportate saranno scelte dall'utente.
|
|
431
432
|
Sarà possibile scegliere il Player predefinito,
|
|
432
433
|
se collegare il proprio profilo AniList e
|
|
433
434
|
se inserire il path di syncplay.
|
|
434
435
|
"""
|
|
436
|
+
ut.configData.clear()
|
|
437
|
+
|
|
435
438
|
#player predefinito
|
|
436
|
-
my_print("", end="", cls=True)
|
|
437
|
-
my_print("AW-CLI - CONFIGURAZIONE", color="giallo")
|
|
439
|
+
ut.my_print("", end="", cls=True)
|
|
440
|
+
ut.my_print("AW-CLI - CONFIGURAZIONE", color="giallo")
|
|
438
441
|
|
|
439
|
-
player
|
|
440
|
-
if nome_os != "Android":
|
|
441
|
-
res = os.popen(f"whereis -b {player} 2>&1").read().removeprefix(f"{player}:").strip().split()
|
|
442
|
+
ut.configData["player"]["type"] = fzf(["vlc","mpv"], "Scegli il player predefinito: ")
|
|
443
|
+
if ut.nome_os != "Android":
|
|
444
|
+
res = os.popen(f"whereis -b {ut.configData["player"]["type"]} 2>&1").read().removeprefix(f"{ut.configData["player"]["type"]}:").strip().split()
|
|
442
445
|
if len(res) == 0:
|
|
443
|
-
my_print(f"Player {player} non trovato!", color="rosso")
|
|
444
|
-
player = my_input(f"Inserisci il path di {player} manualmente se è installato")
|
|
446
|
+
ut.my_print(f"Player {ut.configData["player"]["type"]} non trovato!", color="rosso")
|
|
447
|
+
ut.configData["player"]["path"] = ut.my_input(f"Inserisci il path di {ut.configData["player"]["type"]} manualmente se è installato")
|
|
445
448
|
else:
|
|
446
|
-
player = res[0]
|
|
447
|
-
my_print("AW-CLI - CONFIGURAZIONE", color="giallo", cls=True)
|
|
449
|
+
ut.configData["player"]["path"] = res[0]
|
|
450
|
+
ut.my_print("AW-CLI - CONFIGURAZIONE", color="giallo", cls=True)
|
|
448
451
|
|
|
449
|
-
#
|
|
450
|
-
ratingAnilist = "ratingAnilist: False"
|
|
451
|
-
preferitoAnilist = "preferitoAnilist: False"
|
|
452
|
-
dropAnilist = "dropAnilist: False"
|
|
453
|
-
|
|
452
|
+
#anilist
|
|
454
453
|
if fzf(["sì","no"], "Aggiornare automaticamente la watchlist con AniList? ") == "sì":
|
|
455
454
|
link = "https://anilist.co/api/v2/oauth/authorize?client_id=11388&response_type=token"
|
|
456
|
-
if nome_os == "
|
|
457
|
-
os.system(f"xdg-open '{link}' > /dev/null 2>&1")
|
|
458
|
-
else:
|
|
455
|
+
if ut.nome_os == "Darwin":
|
|
459
456
|
os.system(f"open '{link}' > /dev/null 2>&1")
|
|
457
|
+
else:
|
|
458
|
+
os.system(f"xdg-open '{link}' > /dev/null 2>&1")
|
|
459
|
+
|
|
460
460
|
|
|
461
461
|
#inserimento token
|
|
462
|
-
anilist
|
|
463
|
-
|
|
462
|
+
ut.configData["anilist"]["token"] = ut.my_input(f"Inserire il token di AniList ({link})", cls=True)
|
|
463
|
+
|
|
464
464
|
#prendo l'id dell'utente tramite query
|
|
465
465
|
with ThreadPoolExecutor() as executor:
|
|
466
|
-
|
|
467
|
-
|
|
466
|
+
ut.configData["anilist"]["rating"], ut.configData["anilist"]["favorite"], ut.configData["anilist"]["drop"] = False, False, False
|
|
467
|
+
future = executor.submit(anilist.getAnilistUserId, ut.configData["anilist"]["token"])
|
|
468
|
+
ut.my_print("AW-CLI - CONFIGURAZIONE", color="giallo", cls=True)
|
|
468
469
|
if fzf(["sì","no"], "Votare l'anime una volta completato? ") == "sì":
|
|
469
|
-
|
|
470
|
+
ut.configData["anilist"]["rating"] = True
|
|
470
471
|
|
|
471
472
|
if fzf(["sì","no"], "Chiedere se mettere l'anime tra i preferiti una volta completato? ") == "sì":
|
|
472
|
-
|
|
473
|
+
ut.configData["anilist"]["favorite"] = True
|
|
473
474
|
|
|
474
475
|
if fzf(["sì","no"], "Chiedere se droppare l'anime una volta rimosso dalla cronologia? ") == "sì":
|
|
475
|
-
|
|
476
|
+
ut.configData["anilist"]["drop"] = True
|
|
476
477
|
|
|
477
|
-
anilist
|
|
478
|
+
ut.configData["anilist"]["user_id"] = future.result()
|
|
478
479
|
|
|
479
|
-
|
|
480
|
+
#syncplay
|
|
481
|
+
if ut.nome_os != "Android":
|
|
480
482
|
res = os.popen(f"whereis -b syncplay 2>&1").read().removeprefix(f"syncplay:").strip().split()
|
|
481
483
|
if len(res) == 0:
|
|
482
|
-
my_print("Syncplay non trovato!", color="rosso")
|
|
483
|
-
syncplay = my_input(f"Inserisci il path di Syncplay (premere INVIO se non lo si desidera utilizzare)").replace("Program Files (x86)", "Progra~2")
|
|
484
|
+
ut.my_print("Syncplay non trovato!", color="rosso")
|
|
485
|
+
syncplay = ut.my_input(f"Inserisci il path di Syncplay (premere INVIO se non lo si desidera utilizzare)").replace("Program Files (x86)", "Progra~2")
|
|
486
|
+
if syncplay != "": ut.configData["syncplay"]["path"] = syncplay
|
|
484
487
|
else:
|
|
485
|
-
syncplay = res[0]
|
|
486
|
-
if syncplay == "":
|
|
487
|
-
syncplay = "Syncplay: None"
|
|
488
|
-
|
|
489
|
-
#creo il file
|
|
490
|
-
config = f"{os.path.dirname(__file__)}/aw.config"
|
|
491
|
-
with open(config, 'w') as config_file:
|
|
492
|
-
config_file.write(f"{player}\n{anilist.tokenAnilist}\n{ratingAnilist}\n{preferitoAnilist}\n{dropAnilist}\n{anilist.user_id}\n{syncplay}")
|
|
488
|
+
ut.configData["syncplay"]["path"] = res[0]
|
|
493
489
|
|
|
490
|
+
#creo il file
|
|
491
|
+
config = f"{os.path.dirname(__file__)}/config.toml"
|
|
492
|
+
with open(config, 'w') as f:
|
|
493
|
+
ut.toml.dump(ut.configData, f)
|
|
494
|
+
|
|
494
495
|
|
|
495
496
|
def reloadCrono(cronologia: list[Anime]):
|
|
496
497
|
"""
|
|
@@ -509,9 +510,9 @@ def reloadCrono(cronologia: list[Anime]):
|
|
|
509
510
|
if 0 not in [anime.status for anime in cronologia]:
|
|
510
511
|
return
|
|
511
512
|
|
|
512
|
-
my_print("Ricerco le nuove uscite...", color="giallo")
|
|
513
|
-
ultime_uscite = latest()
|
|
514
|
-
my_print(end="", cls=True)
|
|
513
|
+
ut.my_print("Ricerco le nuove uscite...", color="giallo")
|
|
514
|
+
ultime_uscite = ut.latest()
|
|
515
|
+
ut.my_print(end="", cls=True)
|
|
515
516
|
testo = []
|
|
516
517
|
|
|
517
518
|
for i, a in reversed(list(enumerate(cronologia))):
|
|
@@ -580,25 +581,20 @@ def removeFromCrono(number: int):
|
|
|
580
581
|
|
|
581
582
|
global log
|
|
582
583
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
if delete == "sì":
|
|
586
|
-
if anilist.dropAnilist:
|
|
587
|
-
drop = fzf(["sì","no"], f"Droppare {anime.name} su AniList? ")
|
|
588
|
-
|
|
589
|
-
if drop == "sì":
|
|
590
|
-
if anime.id_anilist == 0:
|
|
591
|
-
my_print("Impossibile droppare su AniList: id anime non trovato!", color="rosso")
|
|
592
|
-
sleep(1)
|
|
593
|
-
else:
|
|
594
|
-
updateAnilist(anime.ep_corrente, drop=True)
|
|
584
|
+
if fzf(["sì","no"], f"Si è sicuri di voler rimuovere {anime.name} dalla cronologia? ") == "no":
|
|
585
|
+
return
|
|
595
586
|
|
|
596
|
-
|
|
587
|
+
if "anilist" in ut.configData and ut.configData["anilist"]["drop"] and fzf(["sì","no"], f"Droppare {anime.name} su AniList? ") == "sì":
|
|
588
|
+
if anime.id_anilist == 0:
|
|
589
|
+
ut.my_print("Impossibile droppare su AniList: id anime non trovato!", color="rosso")
|
|
590
|
+
ut.sleep(1)
|
|
591
|
+
else:
|
|
592
|
+
updateAnilist(anime.ep_corrente, drop=True)
|
|
597
593
|
|
|
598
|
-
|
|
594
|
+
log.pop(number)
|
|
599
595
|
|
|
600
|
-
|
|
601
|
-
|
|
596
|
+
if fzf(["esci","continua"], cls=True) == "esci":
|
|
597
|
+
safeExit()
|
|
602
598
|
|
|
603
599
|
|
|
604
600
|
def updateScript():
|
|
@@ -606,7 +602,9 @@ def updateScript():
|
|
|
606
602
|
Aggiorna di default il programma in base
|
|
607
603
|
all'ultima versione stabile.
|
|
608
604
|
Se viene specificato il branch,
|
|
609
|
-
verrà installato
|
|
605
|
+
verrà installato que#se il file di configurazione non esiste viene chiesto all'utente di fare il setup
|
|
606
|
+
if args.avvia_config or not os.path.exists(f"{os.path.dirname(__file__)}/config.toml"):
|
|
607
|
+
setupConfig()st'ultimo.
|
|
610
608
|
"""
|
|
611
609
|
|
|
612
610
|
if args.update == None:
|
|
@@ -616,19 +614,16 @@ def updateScript():
|
|
|
616
614
|
|
|
617
615
|
os.system(comando)
|
|
618
616
|
|
|
619
|
-
my_print("aw-cli aggiornato con successo!", color="bianco")
|
|
617
|
+
ut.my_print("aw-cli aggiornato con successo!", color="bianco")
|
|
620
618
|
exit()
|
|
621
619
|
|
|
622
620
|
|
|
623
621
|
def main():
|
|
624
622
|
global log
|
|
625
623
|
global anime
|
|
626
|
-
global player_path
|
|
627
|
-
global syncplay_path
|
|
628
624
|
global openPlayer
|
|
629
625
|
global scelta_anime
|
|
630
626
|
global notSelected
|
|
631
|
-
global mpv
|
|
632
627
|
|
|
633
628
|
if update:
|
|
634
629
|
updateScript()
|
|
@@ -640,21 +635,14 @@ def main():
|
|
|
640
635
|
pass
|
|
641
636
|
|
|
642
637
|
#se il file di configurazione non esiste viene chiesto all'utente di fare il setup
|
|
643
|
-
if args.avvia_config or not os.path.exists(f"{os.path.dirname(__file__)}/
|
|
638
|
+
if args.avvia_config or not os.path.exists(f"{os.path.dirname(__file__)}/config.toml"):
|
|
644
639
|
setupConfig()
|
|
645
640
|
|
|
646
|
-
|
|
647
|
-
#se la prima riga del config corrisponde a una versione vecchia, faccio rifare il config
|
|
648
|
-
if player_path.startswith("Player") or mpv == None:
|
|
649
|
-
my_print("Ci sono stati dei cambiamenti nella configurazione...", color="giallo")
|
|
650
|
-
sleep(1)
|
|
651
|
-
setupConfig()
|
|
652
|
-
mpv, player_path, syncplay_path = getConfig()
|
|
641
|
+
ut.getConfig()
|
|
653
642
|
|
|
654
|
-
|
|
655
|
-
openPlayer = openMPV if mpv else openVLC
|
|
643
|
+
openPlayer = openMPV if ut.configData["player"]["type"] == "mpv" else openVLC
|
|
656
644
|
|
|
657
|
-
if nome_os != "Android" and args.syncpl:
|
|
645
|
+
if ut.nome_os != "Android" and args.syncpl:
|
|
658
646
|
openPlayer = openSyncplay
|
|
659
647
|
|
|
660
648
|
reload = True
|
|
@@ -663,13 +651,13 @@ def main():
|
|
|
663
651
|
if cronologia:
|
|
664
652
|
animelist = getCronologia()
|
|
665
653
|
elif lista:
|
|
666
|
-
animelist = latest(args.lista)
|
|
654
|
+
animelist = ut.latest(args.lista)
|
|
667
655
|
else:
|
|
668
656
|
animelist = RicercaAnime()
|
|
669
657
|
if offline:
|
|
670
658
|
animelist = [anime for anime in animelist if anime.name in [a.name for a in animeScaricati(downloadPath())]]
|
|
671
659
|
|
|
672
|
-
my_print("", end="", cls=True)
|
|
660
|
+
ut.my_print("", end="", cls=True)
|
|
673
661
|
esci = True
|
|
674
662
|
if cronologia and args.cronologia != 'r':
|
|
675
663
|
notSelected = True
|
|
@@ -694,7 +682,7 @@ def main():
|
|
|
694
682
|
removeFromCrono(scelta)
|
|
695
683
|
continue
|
|
696
684
|
|
|
697
|
-
anime.load_info() if not offline else downloaded_episodes(anime,f"{downloadPath()}/{anime.name}")
|
|
685
|
+
anime.load_info() if not offline else ut.downloaded_episodes(anime,f"{downloadPath()}/{anime.name}")
|
|
698
686
|
|
|
699
687
|
if info:
|
|
700
688
|
anime.print_info()
|
|
@@ -703,8 +691,8 @@ def main():
|
|
|
703
691
|
continue
|
|
704
692
|
|
|
705
693
|
if anime.ep == 0:
|
|
706
|
-
my_print("Eh, volevi! L'anime non è ancora stato rilasciato", color="rosso")
|
|
707
|
-
sleep(1)
|
|
694
|
+
ut.my_print("Eh, volevi! L'anime non è ancora stato rilasciato", color="rosso")
|
|
695
|
+
ut.sleep(1)
|
|
708
696
|
reload = False
|
|
709
697
|
continue
|
|
710
698
|
|
|
@@ -715,8 +703,8 @@ def main():
|
|
|
715
703
|
anime.ep_corrente = listaEpisodi[0] - 1
|
|
716
704
|
|
|
717
705
|
if listaEpisodi[0] > anime.ep:
|
|
718
|
-
my_print(f"L'episodio {listaEpisodi[0]} di {anime.name} non è ancora stato rilasciato!", color='rosso')
|
|
719
|
-
sleep(1)
|
|
706
|
+
ut.my_print(f"L'episodio {listaEpisodi[0]} di {anime.name} non è ancora stato rilasciato!", color='rosso')
|
|
707
|
+
ut.sleep(1)
|
|
720
708
|
if len(animelist) == 1:
|
|
721
709
|
safeExit()
|
|
722
710
|
reload = False
|
|
@@ -730,7 +718,7 @@ def main():
|
|
|
730
718
|
for ep in listaEpisodi:
|
|
731
719
|
scaricaEpisodio(ep, path)
|
|
732
720
|
|
|
733
|
-
my_print(f"\nVideo scaricato correttamente!\nLo puoi trovare nella cartella {path}\n", color="verde")
|
|
721
|
+
ut.my_print(f"\nVideo scaricato correttamente!\nLo puoi trovare nella cartella {path}\n", color="verde")
|
|
734
722
|
|
|
735
723
|
risp = fzf(["esci","indietro","guarda"])
|
|
736
724
|
if risp == "esci":
|
|
@@ -768,13 +756,10 @@ def main():
|
|
|
768
756
|
reload = True
|
|
769
757
|
|
|
770
758
|
log = []
|
|
771
|
-
player_path = ""
|
|
772
|
-
syncplay_path = ""
|
|
773
759
|
scelta_anime = ""
|
|
774
760
|
openPlayer = None
|
|
775
761
|
notSelected = True
|
|
776
762
|
completeLimit = 90
|
|
777
|
-
mpv = True
|
|
778
763
|
|
|
779
764
|
anime = Anime("", "")
|
|
780
765
|
|
|
@@ -1,22 +1,28 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import re
|
|
3
|
+
import toml
|
|
3
4
|
import requests
|
|
4
|
-
from platform import system
|
|
5
5
|
from time import sleep
|
|
6
6
|
from html import unescape
|
|
7
|
-
|
|
7
|
+
from collections import defaultdict
|
|
8
8
|
from awcli.anime import Anime
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
_url = "https://www.animeworld.so"
|
|
11
|
+
configData = defaultdict(dict)
|
|
12
|
+
|
|
11
13
|
# controllo il tipo del dispositivo
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
def get_os() -> str:
|
|
15
|
+
out = os.popen("uname -a").read().strip().split()
|
|
16
|
+
nome_os = out[0]
|
|
17
|
+
if nome_os == "Linux":
|
|
18
|
+
if "Android" == out[-1]:
|
|
19
|
+
nome_os = "Android"
|
|
20
|
+
elif "WSL" in out[2]:
|
|
21
|
+
nome_os = "WSL"
|
|
22
|
+
return nome_os
|
|
23
|
+
|
|
24
|
+
nome_os = get_os()
|
|
25
|
+
|
|
20
26
|
|
|
21
27
|
def my_print(text: str = "", format: int = 1, color: str = "bianco", bg_color: str = "nero", cls: bool = False, end: str = "\n"):
|
|
22
28
|
"""
|
|
@@ -234,40 +240,26 @@ def downloaded_episodes(anime: Anime, path: str) -> None:
|
|
|
234
240
|
anime.ep = massimo
|
|
235
241
|
anime.ep_ini = minimo
|
|
236
242
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
def getConfig() -> tuple[bool, str, str]:
|
|
243
|
+
|
|
244
|
+
def getConfig() -> None:
|
|
240
245
|
"""
|
|
241
246
|
Prende le impostazioni scelte dall'utente
|
|
242
247
|
dal file di configurazione.
|
|
243
248
|
|
|
244
249
|
Returns:
|
|
245
|
-
|
|
246
|
-
mpv restituisce True se è stato scelto MPV, altrimenti false se è VLC.
|
|
247
|
-
player_path restituisce il path del player predefinito.
|
|
248
|
-
syncplay_path restituisce il path di syncplay.
|
|
250
|
+
None
|
|
249
251
|
"""
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
anilist.tokenAnilist = lines[1]
|
|
263
|
-
anilist.ratingAnilist = True if lines[2] == "ratingAnilist: True" else False
|
|
264
|
-
anilist.preferitoAnilist = True if lines[3] == "preferitoAnilist: True" else False
|
|
265
|
-
anilist.dropAnilist = True if lines[4] == "dropAnilist: True" else False
|
|
266
|
-
anilist.user_id = int(lines[5])
|
|
267
|
-
|
|
268
|
-
syncplay_path = f"/mnt/c/Windows/System32/cmd.exe /C '{lines[6]}'" if wsl else lines[6]
|
|
269
|
-
return mpv, player_path, syncplay_path
|
|
270
|
-
|
|
252
|
+
global configData
|
|
253
|
+
|
|
254
|
+
configPath = f"{os.path.dirname(__file__)}/config.toml"
|
|
255
|
+
|
|
256
|
+
with open(configPath, 'r') as f:
|
|
257
|
+
configData = toml.load(f)
|
|
258
|
+
|
|
259
|
+
if nome_os == "WSL":
|
|
260
|
+
configData["player"]["path"] = f'''"$(wslpath '{configData["player"]["path"]}')"'''
|
|
261
|
+
if "syncplay" in configData:
|
|
262
|
+
configData["syncplay"]["path"] = f"/mnt/c/Windows/System32/cmd.exe /C '{configData["syncplay"]["path"]}'"
|
|
271
263
|
|
|
272
264
|
headers = {
|
|
273
265
|
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
versione = "2.1.2"
|
|
@@ -5,15 +5,15 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
installRequires = [
|
|
7
7
|
"requests",
|
|
8
|
-
"lxml",
|
|
9
8
|
"pySmartDL",
|
|
10
9
|
"wheel",
|
|
11
|
-
"regex",
|
|
10
|
+
"regex",
|
|
11
|
+
"toml",]
|
|
12
12
|
|
|
13
13
|
setup(
|
|
14
14
|
name="aw-cli",
|
|
15
15
|
packages=find_packages(include=["awcli"]),
|
|
16
|
-
version="2.1",
|
|
16
|
+
version="2.1.2",
|
|
17
17
|
python_requires=">3.10",
|
|
18
18
|
description="guarda anime dal terminale e molto altro!",
|
|
19
19
|
long_description=long_description,
|
aw_cli-2.1/awcli/version.py
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
versione = "2.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|