mirror of
https://github.com/Benexl/FastAnime.git
synced 2026-01-06 09:43:53 -08:00
feat: add aniskip intergration and scoring of anime
This commit is contained in:
@@ -66,6 +66,11 @@ signal.signal(signal.SIGINT, handle_exit)
|
||||
type=bool,
|
||||
help="Continue from last episode?",
|
||||
)
|
||||
@click.option(
|
||||
"--skip/--no-skip",
|
||||
type=bool,
|
||||
help="Skip opening and ending theme songs?",
|
||||
)
|
||||
@click.option(
|
||||
"-q",
|
||||
"--quality",
|
||||
@@ -112,6 +117,7 @@ def run_cli(
|
||||
server,
|
||||
format,
|
||||
continue_,
|
||||
skip,
|
||||
translation_type,
|
||||
quality,
|
||||
auto_next,
|
||||
@@ -134,6 +140,9 @@ def run_cli(
|
||||
ctx.obj.format = format
|
||||
if ctx.get_parameter_source("continue_") == click.core.ParameterSource.COMMANDLINE:
|
||||
ctx.obj.continue_from_history = continue_
|
||||
if ctx.get_parameter_source("skip") == click.core.ParameterSource.COMMANDLINE:
|
||||
ctx.obj.skip = skip
|
||||
|
||||
if quality:
|
||||
ctx.obj.quality = quality
|
||||
if ctx.get_parameter_source("auto-next") == click.core.ParameterSource.COMMANDLINE:
|
||||
|
||||
@@ -27,7 +27,8 @@ def login(config: Config, status):
|
||||
exit_app()
|
||||
# ---- new loggin -----
|
||||
print(
|
||||
f"A browser session will be opened ( [link]{config.fastanime_anilist_app_login_url}[/link] )",
|
||||
f"A browser session will be opened ( [link]{
|
||||
config.fastanime_anilist_app_login_url}[/link] )",
|
||||
)
|
||||
webbrowser.open(config.fastanime_anilist_app_login_url)
|
||||
print("Please paste the token provided here")
|
||||
|
||||
@@ -49,7 +49,8 @@ def notifier(config: Config):
|
||||
time.sleep(timeout * 60)
|
||||
continue
|
||||
data = result[1]
|
||||
notifications = data["data"]["Page"]["notifications"] # pyright:ignore
|
||||
# pyright:ignore
|
||||
notifications = data["data"]["Page"]["notifications"]
|
||||
if not notifications:
|
||||
logger.info("Nothing to notify")
|
||||
else:
|
||||
@@ -59,13 +60,15 @@ def notifier(config: Config):
|
||||
anime_title = notification_["media"]["title"][
|
||||
config.preferred_language
|
||||
]
|
||||
message = f"{anime_title}\nBe sure to watch so you are not left out of the loop." # pyright:ignore
|
||||
# pyright:ignore
|
||||
message = f"{anime_title}\nBe sure to watch so you are not left out of the loop."
|
||||
# message = str(textwrap.wrap(message, width=50))
|
||||
|
||||
id = notification_["media"]["id"]
|
||||
if past_notifications.get(str(id)) == notification_["episode"]:
|
||||
logger.info(
|
||||
f"skipping id={id} title={anime_title} episode={anime_episode} already notified"
|
||||
f"skipping id={id} title={anime_title} episode={
|
||||
anime_episode} already notified"
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
@@ -37,6 +37,7 @@ class Config(object):
|
||||
"error": "3",
|
||||
"icons": "false",
|
||||
"notification_duration": "2",
|
||||
"skip": "false",
|
||||
}
|
||||
)
|
||||
self.configparser.add_section("stream")
|
||||
@@ -51,6 +52,7 @@ class Config(object):
|
||||
self.downloads_dir = self.get_downloads_dir()
|
||||
self.provider = self.get_provider()
|
||||
self.use_fzf = self.get_use_fzf()
|
||||
self.skip = self.get_skip()
|
||||
self.icons = self.get_icons()
|
||||
self.preview = self.get_preview()
|
||||
self.translation_type = self.get_translation_type()
|
||||
@@ -112,6 +114,9 @@ class Config(object):
|
||||
def get_use_fzf(self):
|
||||
return self.configparser.getboolean("general", "use_fzf")
|
||||
|
||||
def get_skip(self):
|
||||
return self.configparser.getboolean("stream", "skip")
|
||||
|
||||
def get_icons(self):
|
||||
return self.configparser.getboolean("general", "icons")
|
||||
|
||||
|
||||
@@ -4,9 +4,11 @@ import os
|
||||
import random
|
||||
from datetime import datetime
|
||||
|
||||
from InquirerPy import inquirer
|
||||
from InquirerPy.validator import EmptyInputValidator
|
||||
from rich import print
|
||||
from rich.progress import Progress
|
||||
from rich.prompt import Prompt
|
||||
from rich.prompt import Confirm, Prompt
|
||||
|
||||
from ...anilist import AniList
|
||||
from ...constants import USER_CONFIG_PATH
|
||||
@@ -19,6 +21,7 @@ from ..config import Config
|
||||
from ..utils.mpv import mpv
|
||||
from ..utils.tools import QueryDict, exit_app
|
||||
from ..utils.utils import clear, fuzzy_inquirer
|
||||
from .utils import aniskip
|
||||
|
||||
|
||||
def calculate_time_delta(start_time, end_time):
|
||||
@@ -62,8 +65,17 @@ def player_controls(config: Config, anilist_config: QueryDict):
|
||||
|
||||
start_time = config.watch_history[str(anime_id)]["start_time"]
|
||||
print("[green]Continuing from:[/] ", start_time)
|
||||
custom_args = []
|
||||
if config.skip:
|
||||
if args := aniskip(
|
||||
anilist_config.selected_anime_anilist["idMal"], current_episode
|
||||
):
|
||||
custom_args = args
|
||||
stop_time, total_time = mpv(
|
||||
current_link, selected_server["episode_title"], start_time=start_time
|
||||
current_link,
|
||||
selected_server["episode_title"],
|
||||
start_time=start_time,
|
||||
custom_args=custom_args,
|
||||
)
|
||||
if stop_time == "0":
|
||||
episode = str(int(current_episode) + 1)
|
||||
@@ -263,8 +275,18 @@ def fetch_streams(config: Config, anilist_config: QueryDict):
|
||||
start_time = config.watch_history.get(str(anime_id), {}).get("start_time", "0")
|
||||
if start_time != "0":
|
||||
print("[green]Continuing from:[/] ", start_time)
|
||||
custom_args = []
|
||||
if config.skip:
|
||||
if args := aniskip(
|
||||
anilist_config.selected_anime_anilist["idMal"], episode_number
|
||||
):
|
||||
custom_args = args
|
||||
|
||||
stop_time, total_time = mpv(
|
||||
stream_link, selected_server["episode_title"], start_time=start_time
|
||||
stream_link,
|
||||
selected_server["episode_title"],
|
||||
start_time=start_time,
|
||||
custom_args=custom_args,
|
||||
)
|
||||
print("Finished at: ", stop_time)
|
||||
|
||||
@@ -441,7 +463,7 @@ def anilist_options(config, anilist_config: QueryDict):
|
||||
"Paused": "PAUSED",
|
||||
"Planning": "PLANNING",
|
||||
"Dropped": "DROPPED",
|
||||
"Repeating": "REPEATING",
|
||||
"Rewatching": "REPEATING",
|
||||
"Completed": "COMPLETED",
|
||||
}
|
||||
if config.use_fzf:
|
||||
@@ -454,15 +476,52 @@ def anilist_options(config, anilist_config: QueryDict):
|
||||
anime_list = fuzzy_inquirer(
|
||||
"Choose the list you want to add to", list(anime_lists.keys())
|
||||
)
|
||||
AniList.update_anime_list(
|
||||
result = AniList.update_anime_list(
|
||||
{"status": anime_lists[anime_list], "mediaId": selected_anime["id"]}
|
||||
)
|
||||
print("Successfully updated your list")
|
||||
if not result[0]:
|
||||
print("Failed to update", result)
|
||||
else:
|
||||
print(
|
||||
f"Successfully added {selected_anime_title} to your {anime_list} list :smile:"
|
||||
)
|
||||
input("Enter to continue...")
|
||||
anilist_options(config, anilist_config)
|
||||
|
||||
def _score_anime(config: Config, anilist_config: QueryDict):
|
||||
score = inquirer.number(
|
||||
message="Enter the score:",
|
||||
min_allowed=0,
|
||||
max_allowed=100,
|
||||
validate=EmptyInputValidator(),
|
||||
).execute()
|
||||
|
||||
result = AniList.update_anime_list(
|
||||
{"scoreRaw": score, "mediaId": selected_anime["id"]}
|
||||
)
|
||||
if not result[0]:
|
||||
print("Failed to update", result)
|
||||
else:
|
||||
print(f"Successfully scored {selected_anime_title}; score: {score}")
|
||||
input("Enter to continue...")
|
||||
anilist_options(config, anilist_config)
|
||||
|
||||
def _remove_from_list(config: Config, anilist_config: QueryDict):
|
||||
config.update_anime_list(anilist_config.anime_id, True)
|
||||
if Confirm.ask(
|
||||
f"Are you sure you want to procede, the folowing action will permanently remove {
|
||||
selected_anime_title} from your list and your progress will be erased",
|
||||
default=False,
|
||||
):
|
||||
success, data = AniList.delete_medialist_entry(selected_anime["id"])
|
||||
if not success:
|
||||
print("Failed to delete", data)
|
||||
elif not data.get("deleted"):
|
||||
print("Failed to delete", data)
|
||||
else:
|
||||
print("Successfully deleted :cry:", selected_anime_title)
|
||||
else:
|
||||
print(selected_anime_title, ":relieved:")
|
||||
input("Enter to continue...")
|
||||
anilist_options(config, anilist_config)
|
||||
|
||||
def _change_translation_type(config: Config, anilist_config: QueryDict):
|
||||
@@ -537,6 +596,7 @@ def anilist_options(config, anilist_config: QueryDict):
|
||||
options = {
|
||||
f"{'📽️ ' if icons else ''}Stream": provide_anime,
|
||||
f"{'📼 ' if icons else ''}Watch Trailer": _watch_trailer,
|
||||
f"{'✨ ' if icons else ''}Score Anime": _score_anime,
|
||||
f"{'📥 ' if icons else ''}Add to List": _add_to_list,
|
||||
f"{'📤 ' if icons else ''}Remove from List": _remove_from_list,
|
||||
f"{'📖 ' if icons else ''}View Info": _view_info,
|
||||
@@ -683,7 +743,7 @@ def anilist(config: Config, anilist_config: QueryDict):
|
||||
f"{'✅ ' if icons else ''}Completed": lambda x="Completed": handle_animelist(
|
||||
anilist_config, config, x
|
||||
),
|
||||
f"{'🔁 ' if icons else ''}Repeating": lambda x="Repeating": handle_animelist(
|
||||
f"{'🔁 ' if icons else ''}Rewatching": lambda x="Repeating": handle_animelist(
|
||||
anilist_config, config, x
|
||||
),
|
||||
f"{'🔔 ' if icons else ''}Recently Updated Anime": AniList.get_most_recently_updated,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import textwrap
|
||||
from threading import Thread
|
||||
|
||||
@@ -92,6 +93,19 @@ fzf-preview(){
|
||||
SEARCH_RESULTS_CACHE = os.path.join(APP_CACHE_DIR, "search_results")
|
||||
|
||||
|
||||
def aniskip(mal_id, episode):
|
||||
ANISKIP = shutil.which("ani-skip")
|
||||
if not ANISKIP:
|
||||
print("Aniskip not found, please install and try again")
|
||||
return
|
||||
args = [ANISKIP, "-q", str(mal_id), "-e", str(episode)]
|
||||
aniskip_result = subprocess.run(args, text=True, stdout=subprocess.PIPE)
|
||||
if aniskip_result.returncode != 0:
|
||||
return
|
||||
mpv_skip_args = aniskip_result.stdout.strip()
|
||||
return mpv_skip_args.split(" ")
|
||||
|
||||
|
||||
def write_search_results(
|
||||
search_results: list[AnilistBaseMediaDataSchema], config: Config
|
||||
):
|
||||
@@ -126,7 +140,8 @@ def write_search_results(
|
||||
Favourites: {anime['favourites']}
|
||||
Status: {anime['status']}
|
||||
Episodes: {anime['episodes']}
|
||||
Genres: {anilist_data_helper.format_list_data_with_comma(anime['genres'])}
|
||||
Genres: {anilist_data_helper.format_list_data_with_comma(
|
||||
anime['genres'])}
|
||||
Next Episode: {anilist_data_helper.extract_next_airing_episode(anime['nextAiringEpisode'])}
|
||||
Start Date: {anilist_data_helper.format_anilist_date_object(anime['startDate'])}
|
||||
End Date: {anilist_data_helper.format_anilist_date_object(anime['endDate'])}
|
||||
@@ -136,7 +151,8 @@ def write_search_results(
|
||||
template = textwrap.dedent(template)
|
||||
template = f"""
|
||||
{template}
|
||||
{textwrap.fill(remove_html_tags(str(anime['description'])),width=45)}
|
||||
{textwrap.fill(remove_html_tags(
|
||||
str(anime['description'])), width=45)}
|
||||
"""
|
||||
f.write(template)
|
||||
|
||||
|
||||
@@ -26,9 +26,9 @@ from typing import Optional
|
||||
#
|
||||
|
||||
|
||||
def stream_video(url, mpv_args):
|
||||
def stream_video(url, mpv_args, custom_args):
|
||||
process = subprocess.Popen(
|
||||
["mpv", url, *mpv_args],
|
||||
["mpv", url, *mpv_args, *custom_args],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
text=True,
|
||||
@@ -67,7 +67,13 @@ def stream_video(url, mpv_args):
|
||||
return last_time, total_time
|
||||
|
||||
|
||||
def mpv(link: str, title: Optional[str] = "", start_time: str = "0", ytdl_format=""):
|
||||
def mpv(
|
||||
link: str,
|
||||
title: Optional[str] = "",
|
||||
start_time: str = "0",
|
||||
ytdl_format="",
|
||||
custom_args=[],
|
||||
):
|
||||
# Determine if mpv is available
|
||||
MPV = shutil.which("mpv")
|
||||
|
||||
@@ -121,7 +127,7 @@ def mpv(link: str, title: Optional[str] = "", start_time: str = "0", ytdl_format
|
||||
mpv_args.append(f"--title={title}")
|
||||
if ytdl_format:
|
||||
mpv_args.append(f"--ytdl-format={ytdl_format}")
|
||||
stop_time, total_time = stream_video(link, mpv_args)
|
||||
stop_time, total_time = stream_video(link, mpv_args, custom_args)
|
||||
return stop_time, total_time
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user