Replace content CLI with Textual TUI
This commit is contained in:
1 parent
0d58ddd430
commit
737700a9a8
28 files changed
+2403
-167
No files matched your search
+30
-50
@@ -4,68 +4,48 @@ import youtube
|
||||
MUSIC_FILE = "music.json"
|
||||
|
||||
|
||||
def load_videos() -> tuple[dict, list[str]]:
|
||||
def load_playlist() -> tuple[dict, list[str]]:
|
||||
data = jsonfile.load(MUSIC_FILE)
|
||||
return data, data.setdefault("videos", [])
|
||||
|
||||
|
||||
def list_songs() -> list[str]:
|
||||
_, videos = load_playlist()
|
||||
return [youtube.video_id(video) or video for video in videos]
|
||||
|
||||
|
||||
def find_index(videos: list[str], identifier: str) -> int | None:
|
||||
return next((index for index, video in enumerate(videos) if youtube.video_id(video) == identifier), None)
|
||||
|
||||
|
||||
def list_songs(arguments) -> None:
|
||||
_, videos = load_videos()
|
||||
if not videos:
|
||||
print("The playlist is empty.")
|
||||
return
|
||||
for number, video in enumerate(videos, start=1):
|
||||
identifier = youtube.video_id(video) or "?"
|
||||
title = youtube.video_title(identifier) if arguments.titles else None
|
||||
print(f"{number:>3}. {identifier} {title or video}")
|
||||
def add_song(text: str) -> str:
|
||||
identifier = youtube.video_id(text)
|
||||
if not identifier:
|
||||
raise ValueError(f"{text} is not a YouTube link or video ID")
|
||||
data, videos = load_playlist()
|
||||
if find_index(videos, identifier) is not None:
|
||||
raise ValueError(f"{identifier} is already in the playlist")
|
||||
videos.append(youtube.watch_url(identifier))
|
||||
jsonfile.save(MUSIC_FILE, data)
|
||||
return identifier
|
||||
|
||||
|
||||
def add_songs(arguments) -> None:
|
||||
data, videos = load_videos()
|
||||
added = 0
|
||||
for text in arguments.songs:
|
||||
identifier = youtube.video_id(text)
|
||||
if not identifier:
|
||||
print(f"Skipped {text}: not a YouTube link or video ID.")
|
||||
continue
|
||||
if find_index(videos, identifier) is not None:
|
||||
print(f"Skipped {identifier}: already in the playlist.")
|
||||
continue
|
||||
videos.append(youtube.watch_url(identifier))
|
||||
added += 1
|
||||
print(f"Added {youtube.video_title(identifier) or identifier}")
|
||||
if added:
|
||||
jsonfile.save(MUSIC_FILE, data)
|
||||
|
||||
|
||||
def remove_song(arguments) -> None:
|
||||
data, videos = load_videos()
|
||||
identifier = youtube.video_id(arguments.song)
|
||||
index = find_index(videos, identifier) if identifier else None
|
||||
def remove_song(identifier: str) -> None:
|
||||
data, videos = load_playlist()
|
||||
index = find_index(videos, identifier)
|
||||
if index is None:
|
||||
print(f"{arguments.song} is not in the playlist.")
|
||||
return
|
||||
raise ValueError(f"{identifier} is not in the playlist")
|
||||
videos.pop(index)
|
||||
jsonfile.save(MUSIC_FILE, data)
|
||||
print(f"Removed {identifier}")
|
||||
|
||||
|
||||
def register(subparsers) -> None:
|
||||
parser = subparsers.add_parser("music", help="Manage the music playlist")
|
||||
actions = parser.add_subparsers(dest="action", required=True)
|
||||
|
||||
list_parser = actions.add_parser("list", help="List songs in the playlist")
|
||||
list_parser.add_argument("--titles", action="store_true", help="Look up song titles on YouTube")
|
||||
list_parser.set_defaults(handler=list_songs)
|
||||
|
||||
add_parser = actions.add_parser("add", help="Add songs by YouTube link or video ID")
|
||||
add_parser.add_argument("songs", nargs="+", help="YouTube links or video IDs")
|
||||
add_parser.set_defaults(handler=add_songs)
|
||||
|
||||
remove_parser = actions.add_parser("remove", help="Remove a song by YouTube link or video ID")
|
||||
remove_parser.add_argument("song", help="YouTube link or video ID")
|
||||
remove_parser.set_defaults(handler=remove_song)
|
||||
def move_song(identifier: str, step: int) -> None:
|
||||
data, videos = load_playlist()
|
||||
index = find_index(videos, identifier)
|
||||
if index is None:
|
||||
raise ValueError(f"{identifier} is not in the playlist")
|
||||
target = index + step
|
||||
if not 0 <= target < len(videos):
|
||||
return
|
||||
videos[index], videos[target] = videos[target], videos[index]
|
||||
jsonfile.save(MUSIC_FILE, data)
|
||||
Reference in new issue
Block a user