Merge pull request #59 from Benexl/minor-fixes

Minor fixes
This commit is contained in:
Benedict Xavier
2025-01-29 04:38:53 +03:00
committed by GitHub
13 changed files with 118 additions and 53 deletions

View File

@@ -60,7 +60,7 @@ signal.signal(signal.SIGINT, handle_exit)
fastanime --icons --default anilist
\b
# viewing manga
fastanime --manga search -t <manga-title>
fastanime --manga search -t <manga-title>
""",
)
@click.version_option(__version__, "--version")
@@ -142,7 +142,7 @@ signal.signal(signal.SIGINT, handle_exit)
@click.option(
"--normalize-titles/--no-normalize-titles",
type=bool,
help="whether to normalize anime and episode titls given by providers",
help="whether to normalize anime and episode titles given by providers",
)
@click.option("-d", "--downloads-dir", type=click.Path(), help="Downloads location")
@click.option("--fzf", is_flag=True, help="Use fzf for the ui")

View File

@@ -19,7 +19,7 @@ def login(config: "Config", status, erase):
if status:
is_logged_in = True if config.user else False
message = (
"You are logged in :smile:" if is_logged_in else "You arent logged in :cry:"
"You are logged in :smile:" if is_logged_in else "You aren't logged in :cry:"
)
print(message)
print(config.user)

View File

@@ -2,7 +2,7 @@ import click
@click.command(
help="Get random anime from anilist based on a range of anilist anime ids that are seected at random",
help="Get random anime from anilist based on a range of anilist anime ids that are selected at random",
short_help="View random anime",
)
@click.option(

View File

@@ -2,7 +2,7 @@ import click
@click.command(
help="Fetch the 15 most anticipited anime", short_help="View upcoming anime"
help="Fetch the 15 most anticipated anime", short_help="View upcoming anime"
)
@click.option(
"--dump-json",

View File

@@ -59,7 +59,7 @@ def get_anime_titles(query: str, variables: dict = {}):
else:
return []
except Exception as e:
logger.error(f"Something unexpected occured {e}")
logger.error(f"Something unexpected occurred {e}")
return []

View File

@@ -764,18 +764,22 @@ def provider_anime_episodes_menu(
if not current_episode_number or current_episode_number not in available_episodes:
choices = [*available_episodes, "Back"]
preview = None
if config.preview:
from .utils import get_fzf_episode_preview
e = fastanime_runtime_state.selected_anime_anilist["episodes"]
if e:
eps = range(0, e + 1)
else:
eps = available_episodes
preview = get_fzf_episode_preview(
fastanime_runtime_state.selected_anime_anilist, eps
)
if config.use_fzf:
if config.preview:
from .utils import get_fzf_episode_preview
e = fastanime_runtime_state.selected_anime_anilist["episodes"]
if e:
eps = range(0, e + 1)
else:
eps = available_episodes
preview = get_fzf_episode_preview(
fastanime_runtime_state.selected_anime_anilist, eps
)
if not preview:
print("Failed to find bash executable which is necessary for preview with fzf.\nIf you are on Windows, please make sure Git is installed and available in PATH.")
current_episode_number = fzf.run(
choices, prompt="Select Episode", header=anime_title, preview=preview
)
@@ -1498,6 +1502,9 @@ def anilist_results_menu(
from .utils import get_fzf_anime_preview
preview = get_fzf_anime_preview(search_results, anime_data.keys())
if not preview:
print("Failed to find bash executable which is necessary for preview with fzf.\nIf you are on Windows, please make sure Git is installed and available in PATH.")
selected_anime_title = fzf.run(
choices,
prompt="Select Anime",

View File

@@ -13,7 +13,7 @@ from ...constants import APP_CACHE_DIR, S_PLATFORM
from ...libs.anilist.types import AnilistBaseMediaDataSchema
from ...Utility import anilist_data_helper
from ..utils.scripts import fzf_preview
from ..utils.utils import get_true_fg
from ..utils.utils import get_true_fg, which_bashlike
logger = logging.getLogger(__name__)
@@ -96,7 +96,7 @@ def write_search_results(
titles: list[str],
workers: int | None = None,
):
"""A helper function used by and run in a background thread by get_fzf_preview function inorder to get the actual preview data to be displayed by fzf
"""A helper function used by and run in a background thread by get_fzf_preview function in order to get the actual preview data to be displayed by fzf
Args:
anilist_results: the anilist results from an anilist action
@@ -122,7 +122,7 @@ def write_search_results(
# handle the text data
template = f"""
ll=2
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
echo -n -e "{get_true_fg("",*SEPARATOR_COLOR,bold=False)}"
((ll++))
done
@@ -130,7 +130,7 @@ def write_search_results(
echo "{get_true_fg('Title(jp):',*HEADER_COLOR)} {(anime['title']['romaji'] or "").replace('"',SINGLE_QUOTE)}"
echo "{get_true_fg('Title(eng):',*HEADER_COLOR)} {(anime['title']['english'] or "").replace('"',SINGLE_QUOTE)}"
ll=2
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
echo -n -e "{get_true_fg("",*SEPARATOR_COLOR,bold=False)}"
((ll++))
done
@@ -141,7 +141,7 @@ def write_search_results(
echo "{get_true_fg('Next Episode:',*HEADER_COLOR)} {anilist_data_helper.extract_next_airing_episode(anime['nextAiringEpisode']).replace('"',SINGLE_QUOTE)}"
echo "{get_true_fg('Genres:',*HEADER_COLOR)} {anilist_data_helper.format_list_data_with_comma(anime['genres']).replace('"',SINGLE_QUOTE)}"
ll=2
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
echo -n -e "{get_true_fg("",*SEPARATOR_COLOR,bold=False)}"
((ll++))
done
@@ -150,7 +150,7 @@ def write_search_results(
echo "{get_true_fg('Start Date:',*HEADER_COLOR)} {anilist_data_helper.format_anilist_date_object(anime['startDate']).replace('"',SINGLE_QUOTE)}"
echo "{get_true_fg('End Date:',*HEADER_COLOR)} {anilist_data_helper.format_anilist_date_object(anime['endDate']).replace('"',SINGLE_QUOTE)}"
ll=2
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
echo -n -e "{get_true_fg("",*SEPARATOR_COLOR,bold=False)}"
((ll++))
done
@@ -158,7 +158,7 @@ def write_search_results(
echo "{get_true_fg('Media List:',*HEADER_COLOR)} {mediaListName.replace('"',SINGLE_QUOTE)}"
echo "{get_true_fg('Progress:',*HEADER_COLOR)} {progress}"
ll=2
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
echo -n -e "{get_true_fg("",*SEPARATOR_COLOR,bold=False)}"
((ll++))
done
@@ -279,6 +279,9 @@ def get_fzf_episode_preview(
titles (list[str]): sanitized titles of the anime; NOTE: its important that they are sanitized since they are used as the filenames of the images
workers ([TODO:parameter]): Number of threads to use to download the images; defaults to as many as possible
anilist_results: the anilist results from an anilist action
Returns:
The fzf preview script to use or None if the bash is not found
"""
# HEADER_COLOR = 215, 0, 95
@@ -305,7 +308,7 @@ def get_fzf_episode_preview(
template = textwrap.dedent(
f"""
ll=2
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
echo -n -e "{get_true_fg("",*SEPARATOR_COLOR,bold=False)}"
((ll++))
done
@@ -313,13 +316,13 @@ def get_fzf_episode_preview(
echo "{get_true_fg('Anime Title(jp):',*HEADER_COLOR)} {(anilist_result['title']['romaji'] or '').replace('"',SINGLE_QUOTE)}"
ll=2
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
echo -n -e "{get_true_fg("",*SEPARATOR_COLOR,bold=False)}"
((ll++))
done
echo "{str(episode_title).replace('"',SINGLE_QUOTE)}"
ll=2
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
while [ $ll -le $FZF_PREVIEW_COLUMNS ];do
echo -n -e "{get_true_fg("",*SEPARATOR_COLOR,bold=False)}"
((ll++))
done
@@ -345,22 +348,26 @@ def get_fzf_episode_preview(
background_worker.start()
# the preview script is in bash so making sure fzf doesnt use any other shell lang to process the preview script
os.environ["SHELL"] = shutil.which("bash") or "bash"
bash_path = which_bashlike()
if not bash_path:
return
os.environ["SHELL"] = bash_path
if S_PLATFORM == "win32":
preview = """
%s
title={}
show_image_previews="%s"
dim=${FZF_PREVIEW_COLUMNS}x${FZF_PREVIEW_LINES}
if [ $show_image_previews = "true" ];then
if [ -s "%s\\\\\\${title}.png" ]; then
if [ $show_image_previews = "true" ];then
if [ -s "%s\\\\\\${title}.png" ]; then
if command -v "chafa">/dev/null;then
chafa -s $dim "%s\\\\\\${title}.png"
else
echo please install chafa to enjoy image previews
fi
echo
else
echo
else
echo Loading...
fi
fi
@@ -380,7 +387,7 @@ def get_fzf_episode_preview(
title={}
%s
show_image_previews="%s"
if [ $show_image_previews = "true" ];then
if [ $show_image_previews = "true" ];then
if [ -s %s/${title}.png ]; then fzf-preview %s/${title}.png
else echo Loading...
fi
@@ -412,7 +419,7 @@ def get_fzf_anime_preview(
anilist_results: the anilist results got from an anilist action
Returns:
THe fzf preview script to use
The fzf preview script to use or None if the bash is not found
"""
# ensure images and info exists
@@ -423,7 +430,12 @@ def get_fzf_anime_preview(
background_worker.start()
# the preview script is in bash so making sure fzf doesnt use any other shell lang to process the preview script
os.environ["SHELL"] = shutil.which("bash") or "bash"
bash_path = which_bashlike()
if not bash_path:
return
os.environ["SHELL"] = bash_path
if S_PLATFORM == "win32":
preview = """
%s
@@ -431,14 +443,14 @@ def get_fzf_anime_preview(
show_image_previews="%s"
dim=${FZF_PREVIEW_COLUMNS}x${FZF_PREVIEW_LINES}
if [ $show_image_previews = "true" ];then
if [ -s "%s\\\\\\${title}.png" ]; then
if [ -s "%s\\\\\\${title}.png" ]; then
if command -v "chafa">/dev/null;then
chafa -s $dim "%s\\\\\\${title}.png"
else
echo please install chafa to enjoy image previews
fi
echo
else
echo
else
echo Loading...
fi
fi

View File

@@ -5,7 +5,7 @@ import requests
def print_img(url: str):
"""helper funtion to print an image given its url
"""helper function to print an image given its url
Args:
url: [TODO:description]
@@ -25,7 +25,7 @@ def print_img(url: str):
return
img_bytes = res.content
"""
Change made in call to chafa. Chafa dev dropped abilty
Change made in call to chafa. Chafa dev dropped ability
to pull from urls. Keeping old line here just in case.
subprocess.run([EXECUTABLE, url, "--size=15x15"], input=img_bytes)

View File

@@ -1,8 +1,11 @@
import logging
import shutil
from typing import TYPE_CHECKING
from InquirerPy import inquirer
from fastanime.constants import S_PLATFORM
logger = logging.getLogger(__name__)
if TYPE_CHECKING:
from ...libs.anime_provider.types import EpisodeStream
@@ -92,7 +95,7 @@ def filter_by_quality(quality: str, stream_links: "list[EpisodeStream]", default
def format_bytes_to_human(num_of_bytes: float, suffix: str = "B"):
"""Helper function usedd to format bytes to human
"""Helper function used to format bytes to human
Args:
num_of_bytes: the number of bytes to format
@@ -155,3 +158,41 @@ def fuzzy_inquirer(choices: list, prompt: str, **kwargs):
**kwargs,
).execute()
return action
def which_win32_gitbash():
"""Helper function that returns absolute path to the git bash executable
(came with Git for Windows) on Windows
Returns:
the path to the git bash executable or None if not found
"""
from os import path
gb_path = shutil.which("bash")
# Windows came with its own bash.exe but it's just an entry point for WSL not Git Bash
if gb_path and not path.dirname(gb_path).lower().endswith("windows\\system32"):
return gb_path
git_path = shutil.which("git")
if git_path:
if path.dirname(git_path).endswith("cmd"):
gb_path = path.abspath(
path.join(path.dirname(git_path), "..", "bin", "bash.exe")
)
else:
gb_path = path.join(path.dirname(git_path), "bash.exe")
if path.exists(gb_path):
return gb_path
def which_bashlike():
"""Helper function that returns absolute path to the bash executable for the current platform
Returns:
the path to the bash executable or None if not found
"""
return (shutil.which("bash") or "bash") if S_PLATFORM != "win32" else which_win32_gitbash()

View File

@@ -64,7 +64,7 @@ class AniListApi:
self.session = requests.session()
def login_user(self, token: str):
"""methosd used to login a new user enabling authenticated requests
"""method used to login a new user enabling authenticated requests
Args:
token: anilist app token
@@ -247,7 +247,7 @@ class AniListApi:
return (False, None)
except Exception as e:
logger.error(f"Something unexpected occured {e}")
logger.error(f"Something unexpected occurred {e}")
return (False, None) # type: ignore
def get_data(
@@ -311,7 +311,7 @@ class AniListApi:
},
) # type: ignore
except Exception as e:
logger.error(f"Something unexpected occured {e}")
logger.error(f"Something unexpected occurred {e}")
return (False, {"Error": f"{e}"}) # type: ignore
def search(
@@ -456,7 +456,7 @@ class AniListApi:
recommended_anime = self.get_data(recommended_query, variables)
return recommended_anime
def get_charcters_of(self, id: int, type="ANIME", *_, **kwargs):
def get_characters_of(self, id: int, type="ANIME", *_, **kwargs):
variables = {"id": id}
characters = self.get_data(anime_characters_query, variables)
return characters

View File

@@ -1,5 +1,5 @@
"""
This module contains all the preset queries for the sake of neatness and convinience
This module contains all the preset queries for the sake of neatness and convenience
Mostly for internal usage
"""
@@ -26,7 +26,7 @@ query($id:Int){
}
}
body
}
}
}
@@ -88,7 +88,7 @@ query{
large
medium
}
}
}
"""
@@ -909,7 +909,7 @@ query ($id: Int,$type:MediaType) {
airingAt
timeUntilAiring
episode
}
}
}

View File

@@ -246,7 +246,7 @@ def get_mal_id_and_anilist_id(anime_title: str) -> "dict[str,int] | None":
)
return {"id_anilist": anime["id"], "id_mal": anime["idMal"]}
except Exception as e:
logger.error(f"Something unexpected occured {e}")
logger.error(f"Something unexpected occurred {e}")
def get_basic_anime_info_by_title(anime_title: str):
@@ -320,4 +320,4 @@ def get_basic_anime_info_by_title(anime_title: str):
],
}
except Exception as e:
logger.error(f"Something unexpected occured {e}")
logger.error(f"Something unexpected occurred {e}")

View File

@@ -8,10 +8,12 @@ from typing import Callable, List
from click import clear
from rich import print
from ...cli.utils.tools import exit_app
logger = logging.getLogger(__name__)
FZF_DEFAULT_OPTS = """
FZF_DEFAULT_OPTS = """
--color=fg:#d0d0d0,fg+:#d0d0d0,bg:#121212,bg+:#262626
--color=hl:#5f87af,hl+:#5fd7ff,info:#afaf87,marker:#87ff00
--color=prompt:#d7005f,spinner:#af5fff,pointer:#af5fff,header:#87afaf
@@ -127,7 +129,10 @@ class FZF:
encoding="utf-8",
)
if not result or result.returncode != 0 or not result.stdout:
print("sth went wrong:confused:")
if result.returncode == 130: # fzf terminated by ctrl-c
exit_app()
print("sth went wrong :confused:")
input("press enter to try again...")
clear()
return self._run_fzf(commands, _fzf_input)