patch
This commit is contained in:
parent
4e2171fcda
commit
449dfa0ec7
3
.idea/.gitignore
generated
vendored
Normal file
3
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
8
.idea/Animecli.iml
generated
Normal file
8
.idea/Animecli.iml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="PYTHON_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="jdk" jdkName="Python 3.13" jdkType="Python SDK" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
4
.idea/encodings.xml
generated
Normal file
4
.idea/encodings.xml
generated
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<settings>
|
||||||
|
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||||
|
<version value="1.0" />
|
||||||
|
</settings>
|
||||||
|
</component>
|
12
.idea/material_theme_project_new.xml
generated
Normal file
12
.idea/material_theme_project_new.xml
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="MaterialThemeProjectNewConfig">
|
||||||
|
<option name="metadata">
|
||||||
|
<MTProjectMetadataState>
|
||||||
|
<option name="migrated" value="true" />
|
||||||
|
<option name="pristineConfig" value="false" />
|
||||||
|
<option name="userId" value="6cf94393:1970244d378:-7ffa" />
|
||||||
|
</MTProjectMetadataState>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
7
.idea/misc.xml
generated
Normal file
7
.idea/misc.xml
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.13" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13" project-jdk-type="Python SDK" />
|
||||||
|
</project>
|
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/Animecli.iml" filepath="$PROJECT_DIR$/.idea/Animecli.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
77
animecli.py
77
animecli.py
@ -129,9 +129,15 @@ def extract_episode_sources(url_page):
|
|||||||
return [(sources, None) for sources in episode_sources]
|
return [(sources, None) for sources in episode_sources]
|
||||||
|
|
||||||
def format_dernier(dernier_url, saison):
|
def format_dernier(dernier_url, saison):
|
||||||
m = re.search(r'[Ee](\d{1,3})', dernier_url or "")
|
if not dernier_url or dernier_url == "?":
|
||||||
ep = m.group(1) if m else "?"
|
return f"Saison {saison}, épisode ?, aucun"
|
||||||
return f"Saison {saison}, épisode {ep}, {dernier_url or 'aucun'}"
|
m = re.search(r'[Ee](\d{1,3})', dernier_url)
|
||||||
|
if m:
|
||||||
|
ep = m.group(1)
|
||||||
|
else:
|
||||||
|
m2 = re.search(r'(\d{1,3})(?!.*\d)', dernier_url)
|
||||||
|
ep = m2.group(1) if m2 else "?"
|
||||||
|
return f"Saison {saison}, épisode {ep}, {dernier_url}"
|
||||||
|
|
||||||
def telecharger_episode(url, saison_folder, filename, qualite):
|
def telecharger_episode(url, saison_folder, filename, qualite):
|
||||||
ydl_opts = {
|
ydl_opts = {
|
||||||
@ -195,27 +201,67 @@ def handle_multi_download(stdscr, conn):
|
|||||||
return
|
return
|
||||||
|
|
||||||
selected = [False] * len(episode_data)
|
selected = [False] * len(episode_data)
|
||||||
cursor = 0
|
cursor = 0 # 0 = "Tout sélectionner", 1...N = épisodes
|
||||||
|
scroll_offset = 0
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
stdscr.clear()
|
stdscr.clear()
|
||||||
|
max_y, max_x = stdscr.getmaxyx()
|
||||||
|
visible_lines = max_y - 3 # 1 ligne titre + 2 marges
|
||||||
|
total_lines = len(episode_data) + 1 # +1 pour "Tout sélectionner"
|
||||||
|
|
||||||
|
# Gestion du scroll
|
||||||
|
if cursor < scroll_offset:
|
||||||
|
scroll_offset = cursor
|
||||||
|
elif cursor >= scroll_offset + visible_lines:
|
||||||
|
scroll_offset = cursor - visible_lines + 1
|
||||||
|
|
||||||
stdscr.addstr(0, 0, "Sélectionnez les épisodes à télécharger (Espace pour cocher, Entrée pour valider) :")
|
stdscr.addstr(0, 0, "Sélectionnez les épisodes à télécharger (Espace pour cocher, Entrée pour valider) :")
|
||||||
for idx, (sources, _) in enumerate(episode_data):
|
|
||||||
mark = "[X]" if selected[idx] else "[ ]"
|
# Affichage de la case "Tout sélectionner"
|
||||||
line = f"{mark} Épisode {idx+1}"
|
tout_sel = all(selected) and len(selected) > 0
|
||||||
if idx == cursor:
|
mark = "[X]" if tout_sel else "[ ]"
|
||||||
|
y = 2
|
||||||
|
if scroll_offset == 0:
|
||||||
|
if cursor == 0:
|
||||||
stdscr.attron(curses.color_pair(1))
|
stdscr.attron(curses.color_pair(1))
|
||||||
safe_addstr(stdscr, 2 + idx, 2, line)
|
safe_addstr(stdscr, y, 2, f"{mark} Tout sélectionner")
|
||||||
stdscr.attroff(curses.color_pair(1))
|
stdscr.attroff(curses.color_pair(1))
|
||||||
else:
|
else:
|
||||||
safe_addstr(stdscr, 2 + idx, 2, line)
|
safe_addstr(stdscr, y, 2, f"{mark} Tout sélectionner")
|
||||||
|
y += 1
|
||||||
|
|
||||||
|
# Affichage des épisodes visibles
|
||||||
|
for idx in range(len(episode_data)):
|
||||||
|
line_idx = idx + 1 # +1 à cause de "Tout sélectionner"
|
||||||
|
if line_idx < scroll_offset:
|
||||||
|
continue
|
||||||
|
if y - 2 >= visible_lines:
|
||||||
|
break
|
||||||
|
mark = "[X]" if selected[idx] else "[ ]"
|
||||||
|
line = f"{mark} Épisode {idx+1}"
|
||||||
|
if cursor == line_idx:
|
||||||
|
stdscr.attron(curses.color_pair(1))
|
||||||
|
safe_addstr(stdscr, y, 2, line)
|
||||||
|
stdscr.attroff(curses.color_pair(1))
|
||||||
|
else:
|
||||||
|
safe_addstr(stdscr, y, 2, line)
|
||||||
|
y += 1
|
||||||
|
|
||||||
stdscr.refresh()
|
stdscr.refresh()
|
||||||
k = stdscr.getch()
|
k = stdscr.getch()
|
||||||
if k == curses.KEY_UP and cursor > 0:
|
if k == curses.KEY_UP and cursor > 0:
|
||||||
cursor -= 1
|
cursor -= 1
|
||||||
elif k == curses.KEY_DOWN and cursor < len(episode_data) - 1:
|
elif k == curses.KEY_DOWN and cursor < total_lines - 1:
|
||||||
cursor += 1
|
cursor += 1
|
||||||
elif k == ord(' '):
|
elif k == ord(' '):
|
||||||
selected[cursor] = not selected[cursor]
|
if cursor == 0:
|
||||||
|
# (Dé)sélectionner tout
|
||||||
|
new_val = not all(selected)
|
||||||
|
for i in range(len(selected)):
|
||||||
|
selected[i] = new_val
|
||||||
|
else:
|
||||||
|
selected[cursor - 1] = not selected[cursor - 1]
|
||||||
elif k in [curses.KEY_ENTER, 10, 13]:
|
elif k in [curses.KEY_ENTER, 10, 13]:
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -260,6 +306,13 @@ def handle_multi_download(stdscr, conn):
|
|||||||
else:
|
else:
|
||||||
print(f"Echec téléchargement: {url}")
|
print(f"Echec téléchargement: {url}")
|
||||||
|
|
||||||
|
# Mise à jour du dernier épisode téléchargé
|
||||||
|
if to_download:
|
||||||
|
dernier_url = download_queue[-1][0]
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("UPDATE animes SET dernier_episode = ? WHERE id = ?", (dernier_url, anime_id))
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
def curses_menu(stdscr, conn):
|
def curses_menu(stdscr, conn):
|
||||||
curses.curs_set(0)
|
curses.curs_set(0)
|
||||||
menu = [
|
menu = [
|
||||||
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
requests~=2.32.3
|
||||||
|
yt-dlp~=2025.6.3.233020.dev0
|
||||||
|
beautifulsoup4~=4.13.4
|
Loading…
x
Reference in New Issue
Block a user