cli/ytrssil/cli.py

188 lines
4.4 KiB
Python

from collections.abc import Iterator
from os import execv, fork
from subprocess import PIPE, Popen
from sys import argv, stderr
from inject import autoparams
from ytrssil.bindings import setup_dependencies
from ytrssil.config import Configuration
from ytrssil.datatypes import Video
from ytrssil.protocols import Client
def user_query(videos: list[Video], reverse: bool = False) -> list[str]:
p = Popen(
['fzf', '-m'],
stdout=PIPE,
stdin=PIPE,
)
video_list: Iterator[Video]
if reverse:
video_list = reversed(videos)
else:
video_list = iter(videos)
input_bytes = '\n'.join(map(str, video_list)).encode('UTF-8')
stdout, _ = p.communicate(input=input_bytes)
videos_str: list[str] = stdout.decode('UTF-8').strip().split('\n')
ret: list[str] = []
for video_str in videos_str:
*_, video_id = video_str.split(' - ')
try:
ret.append(video_id)
except KeyError:
pass
return ret
@autoparams()
def fetch_new_videos(client: Client) -> int:
client.fetch()
return 0
@autoparams()
def register(client: Client) -> int:
client.register()
return 0
@autoparams()
def watch_videos(config: Configuration, client: Client) -> int:
videos = client.get_new_videos()
if not videos:
print('No new videos', file=stderr)
return 1
selected_videos = user_query(videos)
if not selected_videos:
print('No video selected', file=stderr)
return 2
video_urls = [
f'https://www.youtube.com/watch?v={video_id}'
for video_id in selected_videos
]
cmd = ['/usr/bin/mpv', *config.mpv_options, *video_urls]
if (fork() == 0):
execv(cmd[0], cmd)
for video_id in selected_videos:
client.mark_video_as_watched(video_id)
return 0
@autoparams()
def print_url(client: Client) -> int:
videos = client.get_new_videos()
if not videos:
print('No new videos', file=stderr)
return 1
selected_videos = user_query(videos)
if not selected_videos:
print('No video selected', file=stderr)
return 2
for video_id in selected_videos:
client.mark_video_as_watched(video_id)
print(f'https://www.youtube.com/watch?v={video_id}')
return 0
@autoparams()
def mark_as_watched(client: Client) -> int:
videos = client.get_new_videos()
if not videos:
print('No new videos', file=stderr)
return 1
selected_videos = user_query(videos)
if not selected_videos:
print('No video selected', file=stderr)
return 2
for video_id in selected_videos:
client.mark_video_as_watched(video_id)
return 0
@autoparams()
def watch_history(config: Configuration, client: Client) -> int:
videos = client.get_watched_videos()
if not videos:
print('No new videos', file=stderr)
return 1
selected_videos = user_query(videos)
if not selected_videos:
print('No video selected', file=stderr)
return 2
video_urls = [
f'https://www.youtube.com/watch?v={video_id}'
for video_id in selected_videos
]
cmd = ['/usr/bin/mpv', *config.mpv_options, *video_urls]
if (fork() == 0):
execv(cmd[0], cmd)
return 0
@autoparams()
def mark_as_unwatched(client: Client) -> int:
videos = client.get_watched_videos()
if not videos:
print('No new videos', file=stderr)
return 1
selected_videos = user_query(videos)
if not selected_videos:
print('No video selected', file=stderr)
return 2
for video_id in selected_videos:
client.mark_video_as_unwatched(video_id)
return 0
def main(args: list[str] = argv) -> int:
setup_dependencies()
command: str
try:
command = args[1]
except IndexError:
command = 'watch'
if command == 'fetch':
return fetch_new_videos()
elif command == 'register':
return register()
elif command == 'watch':
return watch_videos()
elif command == 'print':
return print_url()
elif command == 'history':
return watch_history()
elif command == 'mark':
return mark_as_watched()
elif command == 'unmark':
return mark_as_unwatched()
else:
print(f'Unknown command "{command}"', file=stderr)
print(
'Available commands: fetch, watch, print, history, mark, unmark',
file=stderr,
)
return 1
return 0