cli/ytrssil/cli.py

177 lines
4.9 KiB
Python
Raw Normal View History

from collections.abc import Iterator
from datetime import datetime, timezone
from operator import attrgetter
2021-07-30 11:48:32 +02:00
from os import execv, fork
from subprocess import PIPE, Popen
from sys import argv, stderr
2021-07-30 11:48:32 +02:00
from inject import autoparams
from ytrssil.bindings import setup_dependencies
2021-07-30 11:48:32 +02:00
from ytrssil.constants import mpv_options
from ytrssil.datatypes import Video
from ytrssil.protocols import ChannelRepository, Fetcher
2021-07-30 11:48:32 +02:00
def user_query(videos: dict[str, Video], reverse: bool = False) -> list[Video]:
p = Popen(
['fzf', '-m'],
stdout=PIPE,
stdin=PIPE,
)
video_list: Iterator[Video]
if reverse:
video_list = reversed(videos.values())
else:
video_list = iter(videos.values())
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[Video] = []
for video_str in videos_str:
*_, video_id = video_str.split(' - ')
try:
ret.append(videos[video_id])
except KeyError:
pass
return ret
2021-07-30 11:48:32 +02:00
@autoparams()
def fetch_new_videos(
repository_manager: ChannelRepository,
fetcher: Fetcher,
) -> int:
with repository_manager as _:
_, new_videos = fetcher.fetch_new_videos()
if not new_videos:
print('No new videos', file=stderr)
return 1
return 0
@autoparams()
def watch_videos(
repository_manager: ChannelRepository,
fetcher: Fetcher,
) -> int:
with repository_manager as repository:
new_videos = repository.get_new_videos()
if not new_videos:
print('No new videos', file=stderr)
return 1
selected_videos = user_query(new_videos)
2021-07-30 11:48:32 +02:00
if not selected_videos:
print('No video selected', file=stderr)
return 2
2021-07-30 11:48:32 +02:00
video_urls = [video.url for video in selected_videos]
cmd = ['/usr/bin/mpv', *mpv_options, *video_urls]
if (fork() == 0):
execv(cmd[0], cmd)
for video in selected_videos:
selected_channel = repository.get_channel(video.channel_id)
2021-07-30 11:48:32 +02:00
selected_channel.mark_video_as_watched(video)
watch_timestamp = datetime.utcnow().replace(tzinfo=timezone.utc)
repository.update_video(video, watch_timestamp)
return 0
2021-10-13 23:53:35 +02:00
@autoparams()
def print_url(
repository_manager: ChannelRepository,
fetcher: Fetcher,
) -> int:
with repository_manager as repository:
new_videos = repository.get_new_videos()
2021-10-13 23:53:35 +02:00
if not new_videos:
print('No new videos', file=stderr)
return 1
selected_videos = user_query(new_videos)
if not selected_videos:
print('No video selected', file=stderr)
return 2
for video in selected_videos:
selected_channel = repository.get_channel(video.channel_id)
2021-10-13 23:53:35 +02:00
selected_channel.mark_video_as_watched(video)
watch_timestamp = datetime.utcnow().replace(tzinfo=timezone.utc)
repository.update_video(video, watch_timestamp)
print(video.url)
return 0
@autoparams()
def watch_history(
repository_manager: ChannelRepository,
fetcher: Fetcher,
) -> int:
with repository_manager as repository:
watched_videos = repository.get_watched_videos()
selected_videos = user_query(watched_videos, reverse=True)
if not selected_videos:
print('No video selected', file=stderr)
return 1
video_urls = [video.url for video in selected_videos]
cmd = ['/usr/bin/mpv', *mpv_options, *video_urls]
if (fork() == 0):
execv(cmd[0], cmd)
return 0
@autoparams()
def mark_as_watched(
repository_manager: ChannelRepository,
fetcher: Fetcher,
up_to_date: datetime
) -> int:
with repository_manager as repository:
channels, new_videos = fetcher.fetch_new_videos()
for video in sorted(new_videos.values(), key=attrgetter('timestamp')):
if video.timestamp >= up_to_date:
continue
selected_channel = channels[video.channel_id]
selected_channel.mark_video_as_watched(video)
watch_timestamp = datetime.utcnow().replace(tzinfo=timezone.utc)
repository.update_video(video, watch_timestamp)
2021-07-30 11:48:32 +02:00
return 0
2021-08-06 00:07:30 +02:00
def main(args: list[str] = argv) -> int:
setup_dependencies()
command: str
try:
2021-08-06 00:07:30 +02:00
command = args[1]
except IndexError:
command = 'watch'
if command == 'fetch':
return fetch_new_videos()
elif command == 'watch':
return watch_videos()
2021-10-13 23:53:35 +02:00
elif command == 'print':
return print_url()
elif command == 'history':
return watch_history()
elif command == 'mark':
2021-08-06 00:07:30 +02:00
up_to_date = datetime.fromisoformat(args[2])
return mark_as_watched(up_to_date=up_to_date)
else:
print(f'Unknown command "{command}"', file=stderr)
return 1
return 0