mirror of
https://github.com/Benexl/FastAnime.git
synced 2025-12-26 04:41:34 -08:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c1f8d09e6 | ||
|
|
6bb2c89a8c | ||
|
|
9f56b74ff0 | ||
|
|
4d03b86498 | ||
|
|
fab86090a3 | ||
|
|
71d258385c | ||
|
|
bc55ed6e81 |
@@ -8,7 +8,7 @@ from subprocess import PIPE, Popen
|
||||
import requests
|
||||
from rich import print
|
||||
|
||||
from .. import APP_NAME, AUTHOR, GIT_REPO, REPO, __version__
|
||||
from .. import APP_NAME, AUTHOR, GIT_REPO, __version__
|
||||
|
||||
API_URL = f"https://api.{GIT_REPO}/repos/{AUTHOR}/{APP_NAME}/releases/latest"
|
||||
|
||||
@@ -91,13 +91,12 @@ def update_app():
|
||||
else:
|
||||
executable = sys.executable
|
||||
|
||||
app_package_url = f"https://{REPO}/releases/download/{tag_name}/fastanime-{tag_name.replace("v","")}.tar.gz"
|
||||
args = [
|
||||
executable,
|
||||
"-m",
|
||||
"pip",
|
||||
"install",
|
||||
app_package_url,
|
||||
APP_NAME,
|
||||
"--user",
|
||||
"--no-warn-script-location",
|
||||
]
|
||||
|
||||
@@ -2,7 +2,7 @@ import json
|
||||
import logging
|
||||
import os
|
||||
|
||||
from .. import USER_DATA_PATH
|
||||
from ..constants import USER_DATA_PATH
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
@@ -10,6 +11,7 @@ from fastanime.libs.anilist.anilist_data_schema import AnilistBaseMediaDataSchem
|
||||
|
||||
from .data import anime_normalizer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# TODO: make it use color_text instead of fixed vals
|
||||
# from .kivy_markup_helper import color_text
|
||||
|
||||
@@ -127,6 +129,7 @@ def anime_title_percentage_match(
|
||||
fuzz.ratio(title_a.lower(), possible_user_requested_anime_title.lower()),
|
||||
fuzz.ratio(title_b.lower(), possible_user_requested_anime_title.lower()),
|
||||
)
|
||||
logger.info(f"{locals()}")
|
||||
return percentage_ratio
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from platform import platform
|
||||
|
||||
from dotenv import load_dotenv
|
||||
from platformdirs import PlatformDirs
|
||||
|
||||
load_dotenv()
|
||||
|
||||
@@ -15,43 +13,12 @@ if os.environ.get("FA_RICH_TRACEBACK", False):
|
||||
|
||||
|
||||
# initiate constants
|
||||
__version__ = "v0.30.0"
|
||||
__version__ = "v0.32.0"
|
||||
|
||||
PLATFORM = platform()
|
||||
APP_NAME = "FastAnime"
|
||||
AUTHOR = "Benex254"
|
||||
GIT_REPO = "github.com"
|
||||
REPO = f"{GIT_REPO}/{AUTHOR}/{APP_NAME}"
|
||||
USER_NAME = os.environ.get("USERNAME", f"{APP_NAME} user")
|
||||
|
||||
|
||||
dirs = PlatformDirs(appname=APP_NAME, appauthor=AUTHOR, ensure_exists=True)
|
||||
|
||||
|
||||
# ---- app deps ----
|
||||
APP_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
CONFIGS_DIR = os.path.join(APP_DIR, "configs")
|
||||
ASSETS_DIR = os.path.join(APP_DIR, "assets")
|
||||
|
||||
# ----- user configs and data -----
|
||||
APP_DATA_DIR = dirs.user_config_dir
|
||||
if not APP_DATA_DIR:
|
||||
APP_DATA_DIR = dirs.user_data_dir
|
||||
|
||||
USER_DATA_PATH = os.path.join(APP_DATA_DIR, "user_data.json")
|
||||
USER_CONFIG_PATH = os.path.join(APP_DATA_DIR, "config.ini")
|
||||
|
||||
# cache dir
|
||||
APP_CACHE_DIR = dirs.user_cache_dir
|
||||
|
||||
# video dir
|
||||
USER_VIDEOS_DIR = os.path.join(dirs.user_videos_dir, APP_NAME)
|
||||
|
||||
# web dirs
|
||||
|
||||
WEB_DIR = os.path.join(APP_DIR, "web")
|
||||
FRONTEND_DIR = os.path.join(WEB_DIR, "frontend")
|
||||
BACKEND_DIR = os.path.join(WEB_DIR, "backend")
|
||||
|
||||
|
||||
def FastAnime():
|
||||
|
||||
@@ -4,7 +4,9 @@ import subprocess
|
||||
import click
|
||||
from rich import print
|
||||
|
||||
from ... import USER_CONFIG_PATH
|
||||
from fastanime.cli.config import Config
|
||||
|
||||
from ...constants import USER_CONFIG_PATH
|
||||
from ..utils.tools import exit_app
|
||||
|
||||
|
||||
@@ -13,7 +15,8 @@ from ..utils.tools import exit_app
|
||||
short_help="Edit your config",
|
||||
)
|
||||
@click.option("--path", "-p", help="Print the config location and exit", is_flag=True)
|
||||
def configure(path):
|
||||
@click.pass_obj
|
||||
def configure(config: Config, path):
|
||||
if path:
|
||||
print(USER_CONFIG_PATH)
|
||||
else:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import click
|
||||
from rich import print
|
||||
from rich.progress import Progress
|
||||
from thefuzz import fuzz
|
||||
|
||||
from ...libs.anime_provider.types import Anime
|
||||
@@ -28,9 +29,11 @@ def download(config: Config, anime_title, episode_range):
|
||||
anime_provider = config.anime_provider
|
||||
translation_type = config.translation_type
|
||||
download_dir = config.downloads_dir
|
||||
search_results = anime_provider.search_for_anime(
|
||||
anime_title, translation_type=translation_type
|
||||
)
|
||||
with Progress() as progress:
|
||||
progress.add_task("Fetching Search Results...", total=None)
|
||||
search_results = anime_provider.search_for_anime(
|
||||
anime_title, translation_type=translation_type
|
||||
)
|
||||
if not search_results:
|
||||
print("Search results failed")
|
||||
input("Enter to retry")
|
||||
@@ -51,7 +54,11 @@ def download(config: Config, anime_title, episode_range):
|
||||
list(search_results_.keys()), "Please Select title: ", "FastAnime"
|
||||
)
|
||||
|
||||
anime: Anime | None = anime_provider.get_anime(search_results_[search_result]["id"])
|
||||
with Progress() as progress:
|
||||
progress.add_task("Fetching Anime...", total=None)
|
||||
anime: Anime | None = anime_provider.get_anime(
|
||||
search_results_[search_result]["id"]
|
||||
)
|
||||
if not anime:
|
||||
print("Sth went wring anime no found")
|
||||
input("Enter to continue...")
|
||||
@@ -70,20 +77,24 @@ def download(config: Config, anime_title, episode_range):
|
||||
if episode not in episodes:
|
||||
print(f"[cyan]Warning[/]: Episode {episode} not found, skipping")
|
||||
continue
|
||||
streams = anime_provider.get_episode_streams(
|
||||
anime, episode, config.translation_type
|
||||
)
|
||||
if not streams:
|
||||
print("No streams skipping")
|
||||
continue
|
||||
with Progress() as progress:
|
||||
progress.add_task("Fetching Episode Streams...", total=None)
|
||||
streams = anime_provider.get_episode_streams(
|
||||
anime, episode, config.translation_type
|
||||
)
|
||||
if not streams:
|
||||
print("No streams skipping")
|
||||
continue
|
||||
|
||||
streams = list(streams)
|
||||
links = [
|
||||
(link.get("priority", 0), link["link"])
|
||||
for server in streams
|
||||
for link in server["links"]
|
||||
]
|
||||
link = max(links, key=lambda x: x[0])[1]
|
||||
print(f"[purple]Now Downloading:[/] {search_result} Episode {episode}")
|
||||
|
||||
streams = list(streams)
|
||||
links = [
|
||||
(link.get("priority", 0), link["link"])
|
||||
for server in streams
|
||||
for link in server["links"]
|
||||
]
|
||||
link = max(links, key=lambda x: x[0])[1]
|
||||
downloader._download_file(
|
||||
link,
|
||||
download_dir,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import click
|
||||
from rich import print
|
||||
from rich.progress import Progress
|
||||
from thefuzz import fuzz
|
||||
|
||||
from ...cli.config import Config
|
||||
@@ -23,9 +24,11 @@ from ..utils.utils import clear
|
||||
@click.pass_obj
|
||||
def search(config: Config, anime_title: str, episode_range: str):
|
||||
anime_provider = config.anime_provider
|
||||
search_results = anime_provider.search_for_anime(
|
||||
anime_title, config.translation_type
|
||||
)
|
||||
with Progress() as progress:
|
||||
progress.add_task("Fetching Search Results...", total=None)
|
||||
search_results = anime_provider.search_for_anime(
|
||||
anime_title, config.translation_type
|
||||
)
|
||||
if not search_results:
|
||||
print("Search results not found")
|
||||
input("Enter to retry")
|
||||
@@ -50,7 +53,12 @@ def search(config: Config, anime_title: str, episode_range: str):
|
||||
list(search_results_.keys()), "Please Select title: ", "FastAnime"
|
||||
)
|
||||
|
||||
anime: Anime | None = anime_provider.get_anime(search_results_[search_result]["id"])
|
||||
with Progress() as progress:
|
||||
progress.add_task("Fetching Anime...", total=None)
|
||||
anime: Anime | None = anime_provider.get_anime(
|
||||
search_results_[search_result]["id"]
|
||||
)
|
||||
|
||||
if not anime:
|
||||
print("Sth went wring anime no found")
|
||||
input("Enter to continue...")
|
||||
@@ -82,17 +90,20 @@ def search(config: Config, anime_title: str, episode_range: str):
|
||||
|
||||
if not episode or episode not in episodes:
|
||||
episode = fzf.run(episodes, "Select an episode: ", header=search_result)
|
||||
streams = anime_provider.get_episode_streams(
|
||||
anime, episode, config.translation_type
|
||||
)
|
||||
if not streams:
|
||||
print("Failed to get streams")
|
||||
return
|
||||
links = [link["link"] for server in streams for link in server["links"]]
|
||||
with Progress() as progress:
|
||||
progress.add_task("Fetching Episode Streams...", total=None)
|
||||
streams = anime_provider.get_episode_streams(
|
||||
anime, episode, config.translation_type
|
||||
)
|
||||
if not streams:
|
||||
print("Failed to get streams")
|
||||
return
|
||||
links = [link["link"] for server in streams for link in server["links"]]
|
||||
|
||||
# TODO: Come up with way to know quality and better server interface
|
||||
link = links[config.quality]
|
||||
# TODO: Come up with way to know quality and better server interface
|
||||
link = links[config.quality]
|
||||
# link = fzf.run(links, "Select stream", "Streams")
|
||||
print(f"[purple]Now Playing:[/] {search_result} Episode {episode}")
|
||||
|
||||
mpv(link, search_result)
|
||||
stream_anime()
|
||||
|
||||
@@ -3,8 +3,8 @@ from configparser import ConfigParser
|
||||
|
||||
from rich import print
|
||||
|
||||
from .. import USER_CONFIG_PATH, USER_VIDEOS_DIR
|
||||
from ..AnimeProvider import AnimeProvider
|
||||
from ..constants import USER_CONFIG_PATH, USER_VIDEOS_DIR
|
||||
from ..Utility.user_data_helper import user_data_helper
|
||||
|
||||
|
||||
|
||||
@@ -4,10 +4,11 @@ import os
|
||||
import random
|
||||
|
||||
from rich import print
|
||||
from rich.progress import Progress
|
||||
from rich.prompt import Prompt
|
||||
|
||||
from ... import USER_CONFIG_PATH
|
||||
from ...anilist import AniList
|
||||
from ...constants import USER_CONFIG_PATH
|
||||
from ...libs.anilist.anilist_data_schema import AnilistBaseMediaDataSchema
|
||||
from ...libs.anime_provider.types import Anime, SearchResult, Server
|
||||
from ...libs.fzf import fzf
|
||||
@@ -154,17 +155,20 @@ def fetch_streams(config: Config, anilist_config: QueryDict):
|
||||
anime_provider = config.anime_provider
|
||||
|
||||
# get streams for episode from provider
|
||||
episode_streams = anime_provider.get_episode_streams(
|
||||
anime, episode_number, translation_type
|
||||
)
|
||||
if not episode_streams:
|
||||
print("Failed to fetch :cry:")
|
||||
input("Enter to retry...")
|
||||
return fetch_streams(config, anilist_config)
|
||||
with Progress() as progress:
|
||||
progress.add_task("Fetching Episode Streams...", total=None)
|
||||
episode_streams = anime_provider.get_episode_streams(
|
||||
anime, episode_number, translation_type
|
||||
)
|
||||
if not episode_streams:
|
||||
print("Failed to fetch :cry:")
|
||||
input("Enter to retry...")
|
||||
return fetch_streams(config, anilist_config)
|
||||
|
||||
episode_streams = {
|
||||
episode_stream["server"]: episode_stream for episode_stream in episode_streams
|
||||
}
|
||||
episode_streams = {
|
||||
episode_stream["server"]: episode_stream
|
||||
for episode_stream in episode_streams
|
||||
}
|
||||
|
||||
# prompt for preferred server
|
||||
server = None
|
||||
@@ -267,7 +271,9 @@ def fetch_episode(config: Config, anilist_config: QueryDict):
|
||||
def fetch_anime_episode(config, anilist_config: QueryDict):
|
||||
selected_anime: SearchResult = anilist_config._anime
|
||||
anime_provider = config.anime_provider
|
||||
anilist_config.anime = anime_provider.get_anime(selected_anime["id"])
|
||||
with Progress() as progress:
|
||||
progress.add_task("Fetching Anime Info...", total=None)
|
||||
anilist_config.anime = anime_provider.get_anime(selected_anime["id"])
|
||||
if not anilist_config.anime:
|
||||
|
||||
print(
|
||||
@@ -291,9 +297,11 @@ def provide_anime(config: Config, anilist_config: QueryDict):
|
||||
anime_provider = config.anime_provider
|
||||
|
||||
# search and get the requested title from provider
|
||||
search_results = anime_provider.search_for_anime(
|
||||
selected_anime_title, translation_type
|
||||
)
|
||||
with Progress() as progress:
|
||||
progress.add_task("Fetching Search Results...", total=None)
|
||||
search_results = anime_provider.search_for_anime(
|
||||
selected_anime_title, translation_type
|
||||
)
|
||||
if not search_results:
|
||||
print(
|
||||
"Sth went wrong :cry: while fetching this could mean you have poor internet connection or the provider is down"
|
||||
|
||||
@@ -5,7 +5,7 @@ from threading import Thread
|
||||
|
||||
import requests
|
||||
|
||||
from ... import APP_CACHE_DIR
|
||||
from ...constants import APP_CACHE_DIR
|
||||
from ...libs.anilist.anilist_data_schema import AnilistBaseMediaDataSchema
|
||||
from ...Utility import anilist_data_helper
|
||||
from ...Utility.utils import remove_html_tags, sanitize_filename
|
||||
|
||||
@@ -1,23 +1,87 @@
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def mpv(link, title: None | str = "anime", *custom_args):
|
||||
# legacy
|
||||
# def mpv(link, title: None | str = "anime", *custom_args):
|
||||
# MPV = shutil.which("mpv")
|
||||
# if not MPV:
|
||||
# args = [
|
||||
# "nohup",
|
||||
# "am",
|
||||
# "start",
|
||||
# "--user",
|
||||
# "0",
|
||||
# "-a",
|
||||
# "android.intent.action.VIEW",
|
||||
# "-d",
|
||||
# link,
|
||||
# "-n",
|
||||
# "is.xyz.mpv/.MPVActivity",
|
||||
# ]
|
||||
# subprocess.run(args)
|
||||
# else:
|
||||
# subprocess.run([MPV, *custom_args, f"--title={title}", link])
|
||||
#
|
||||
#
|
||||
def mpv(link: str, title: Optional[str] = "anime", *custom_args):
|
||||
# Determine if mpv is available
|
||||
MPV = shutil.which("mpv")
|
||||
|
||||
# If title is None, set a default value
|
||||
if title is None:
|
||||
title = "anime"
|
||||
|
||||
# Regex to check if the link is a YouTube URL
|
||||
youtube_regex = r"(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/.+"
|
||||
|
||||
if not MPV:
|
||||
args = [
|
||||
"nohup",
|
||||
"am",
|
||||
"start",
|
||||
"--user",
|
||||
"0",
|
||||
"-a",
|
||||
"android.intent.action.VIEW",
|
||||
"-d",
|
||||
link,
|
||||
"-n",
|
||||
"is.xyz.mpv/.MPVActivity",
|
||||
]
|
||||
# Determine if the link is a YouTube URL
|
||||
if re.match(youtube_regex, link):
|
||||
# Android specific commands to launch mpv with a YouTube URL
|
||||
args = [
|
||||
"nohup",
|
||||
"am",
|
||||
"start",
|
||||
"--user",
|
||||
"0",
|
||||
"-a",
|
||||
"android.intent.action.VIEW",
|
||||
"-d",
|
||||
link,
|
||||
"-n",
|
||||
"com.google.android.youtube/.UrlActivity",
|
||||
]
|
||||
else:
|
||||
# Android specific commands to launch mpv with a regular URL
|
||||
args = [
|
||||
"nohup",
|
||||
"am",
|
||||
"start",
|
||||
"--user",
|
||||
"0",
|
||||
"-a",
|
||||
"android.intent.action.VIEW",
|
||||
"-d",
|
||||
link,
|
||||
"-n",
|
||||
"is.xyz.mpv/.MPVActivity",
|
||||
]
|
||||
|
||||
subprocess.run(args)
|
||||
else:
|
||||
subprocess.run([MPV, *custom_args, f"--title={title}", link])
|
||||
# General mpv command with custom arguments
|
||||
mpv_args = [MPV, *custom_args, f"--title={title}", link]
|
||||
subprocess.run(mpv_args)
|
||||
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
mpv(
|
||||
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
|
||||
"Example Video",
|
||||
"--fullscreen",
|
||||
"--volume=50",
|
||||
)
|
||||
|
||||
@@ -18,7 +18,7 @@ def exit_app(*args):
|
||||
|
||||
from rich import print
|
||||
|
||||
from ... import USER_NAME
|
||||
from ...constants import USER_NAME
|
||||
|
||||
print("Have a good day :smile:", USER_NAME)
|
||||
sys.exit(0)
|
||||
|
||||
@@ -4,7 +4,7 @@ import os
|
||||
from InquirerPy import inquirer
|
||||
from thefuzz import fuzz
|
||||
|
||||
from ... import PLATFORM
|
||||
from ...constants import PLATFORM
|
||||
from ...Utility.data import anime_normalizer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -54,20 +54,3 @@ def anime_title_percentage_match(
|
||||
fuzz.ratio(title[1].lower(), possible_user_requested_anime_title.lower()),
|
||||
)
|
||||
return percentage_ratio
|
||||
|
||||
|
||||
def get_selected_anime(anime_title, results):
|
||||
def _get_result(result, compare):
|
||||
return result["name"] == compare
|
||||
|
||||
return list(
|
||||
filter(lambda x: _get_result(x, anime_title), results["shows"]["edges"])
|
||||
)
|
||||
|
||||
|
||||
def get_selected_server(_server, servers):
|
||||
def _get_server(server, server_name):
|
||||
return server[0] == server_name
|
||||
|
||||
server = list(filter(lambda x: _get_server(x, _server), servers)).pop()
|
||||
return server
|
||||
|
||||
32
fastanime/constants.py
Normal file
32
fastanime/constants.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import os
|
||||
from platform import platform
|
||||
|
||||
from platformdirs import PlatformDirs
|
||||
|
||||
from . import APP_NAME, AUTHOR
|
||||
|
||||
PLATFORM = platform()
|
||||
dirs = PlatformDirs(appname=APP_NAME, appauthor=AUTHOR, ensure_exists=True)
|
||||
|
||||
|
||||
# ---- app deps ----
|
||||
APP_DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
CONFIGS_DIR = os.path.join(APP_DIR, "configs")
|
||||
ASSETS_DIR = os.path.join(APP_DIR, "assets")
|
||||
|
||||
# ----- user configs and data -----
|
||||
APP_DATA_DIR = dirs.user_config_dir
|
||||
if not APP_DATA_DIR:
|
||||
APP_DATA_DIR = dirs.user_data_dir
|
||||
|
||||
USER_DATA_PATH = os.path.join(APP_DATA_DIR, "user_data.json")
|
||||
USER_CONFIG_PATH = os.path.join(APP_DATA_DIR, "config.ini")
|
||||
|
||||
# cache dir
|
||||
APP_CACHE_DIR = dirs.user_cache_dir
|
||||
|
||||
# video dir
|
||||
USER_VIDEOS_DIR = os.path.join(dirs.user_videos_dir, APP_NAME)
|
||||
|
||||
|
||||
USER_NAME = os.environ.get("USERNAME", f"{APP_NAME} user")
|
||||
@@ -4,8 +4,6 @@ from typing import Iterator
|
||||
|
||||
import requests
|
||||
from requests.exceptions import Timeout
|
||||
from rich import print
|
||||
from rich.progress import Progress
|
||||
|
||||
from ....libs.anime_provider.allanime.types import AllAnimeEpisode
|
||||
from ....libs.anime_provider.types import Anime, Server
|
||||
@@ -43,14 +41,12 @@ class AllAnimeAPI:
|
||||
timeout=10,
|
||||
)
|
||||
return response.json()["data"]
|
||||
except Timeout as e:
|
||||
print(
|
||||
"Timeout has been exceeded :cry:. This could mean allanime is down or your internet is down"
|
||||
except Timeout:
|
||||
Logger.error(
|
||||
"allanime(Error):Timeout exceeded this could mean allanime is down or you have lost internet connection"
|
||||
)
|
||||
Logger.error(f"allanime(Error): {e}")
|
||||
return {}
|
||||
except Exception as e:
|
||||
print("sth went wrong :confused:")
|
||||
Logger.error(f"allanime:Error: {e}")
|
||||
return {}
|
||||
|
||||
@@ -75,22 +71,20 @@ class AllAnimeAPI:
|
||||
"countryorigin": countryorigin,
|
||||
}
|
||||
try:
|
||||
with Progress() as progress:
|
||||
progress.add_task("[cyan]searching..", start=False, total=None)
|
||||
|
||||
search_results = self._fetch_gql(ALLANIME_SEARCH_GQL, variables)
|
||||
return normalize_search_results(search_results) # pyright:ignore
|
||||
except Exception:
|
||||
search_results = self._fetch_gql(ALLANIME_SEARCH_GQL, variables)
|
||||
return normalize_search_results(search_results) # pyright:ignore
|
||||
except Exception as e:
|
||||
Logger.error(f"FA(AllAnime): {e}")
|
||||
return {}
|
||||
|
||||
def get_anime(self, allanime_show_id: str):
|
||||
variables = {"showId": allanime_show_id}
|
||||
try:
|
||||
with Progress() as progress:
|
||||
progress.add_task("[cyan]fetching anime..", start=False, total=None)
|
||||
anime = self._fetch_gql(ALLANIME_SHOW_GQL, variables)
|
||||
return normalize_anime(anime["show"])
|
||||
except Exception:
|
||||
anime = self._fetch_gql(ALLANIME_SHOW_GQL, variables)
|
||||
return normalize_anime(anime["show"])
|
||||
except Exception as e:
|
||||
Logger.error(f"FA(AllAnime): {e}")
|
||||
return None
|
||||
|
||||
def get_anime_episode(
|
||||
@@ -102,11 +96,10 @@ class AllAnimeAPI:
|
||||
"episodeString": episode_string,
|
||||
}
|
||||
try:
|
||||
with Progress() as progress:
|
||||
progress.add_task("[cyan]fetching episode..", start=False, total=None)
|
||||
episode = self._fetch_gql(ALLANIME_EPISODES_GQL, variables)
|
||||
return episode["episode"] # pyright: ignore
|
||||
except Exception:
|
||||
episode = self._fetch_gql(ALLANIME_EPISODES_GQL, variables)
|
||||
return episode["episode"] # pyright: ignore
|
||||
except Exception as e:
|
||||
Logger.error(f"FA(AllAnime): {e}")
|
||||
return {}
|
||||
|
||||
def get_episode_streams(
|
||||
@@ -121,99 +114,86 @@ class AllAnimeAPI:
|
||||
|
||||
embeds = allanime_episode["sourceUrls"]
|
||||
try:
|
||||
with Progress() as progress:
|
||||
progress.add_task("[cyan]fetching streams..", start=False, total=None)
|
||||
for embed in embeds:
|
||||
try:
|
||||
# filter the working streams
|
||||
if embed.get("sourceName", "") not in (
|
||||
"Sak",
|
||||
"Kir",
|
||||
"S-mp4",
|
||||
"Luf-mp4",
|
||||
):
|
||||
continue
|
||||
url = embed.get("sourceUrl")
|
||||
for embed in embeds:
|
||||
try:
|
||||
# filter the working streams
|
||||
if embed.get("sourceName", "") not in (
|
||||
"Sak",
|
||||
"Kir",
|
||||
"S-mp4",
|
||||
"Luf-mp4",
|
||||
):
|
||||
continue
|
||||
url = embed.get("sourceUrl")
|
||||
|
||||
if not url:
|
||||
continue
|
||||
if url.startswith("--"):
|
||||
url = url[2:]
|
||||
if not url:
|
||||
continue
|
||||
if url.startswith("--"):
|
||||
url = url[2:]
|
||||
|
||||
# get the stream url for an episode of the defined source names
|
||||
parsed_url = decode_hex_string(url)
|
||||
embed_url = f"https://{ALLANIME_BASE}{parsed_url.replace('clock','clock.json')}"
|
||||
resp = requests.get(
|
||||
embed_url,
|
||||
headers={
|
||||
"Referer": ALLANIME_REFERER,
|
||||
"User-Agent": USER_AGENT,
|
||||
},
|
||||
timeout=10,
|
||||
)
|
||||
if resp.status_code == 200:
|
||||
match embed["sourceName"]:
|
||||
case "Luf-mp4":
|
||||
Logger.debug(
|
||||
"allanime:Found streams from gogoanime"
|
||||
# get the stream url for an episode of the defined source names
|
||||
parsed_url = decode_hex_string(url)
|
||||
embed_url = f"https://{ALLANIME_BASE}{parsed_url.replace('clock','clock.json')}"
|
||||
resp = requests.get(
|
||||
embed_url,
|
||||
headers={
|
||||
"Referer": ALLANIME_REFERER,
|
||||
"User-Agent": USER_AGENT,
|
||||
},
|
||||
timeout=10,
|
||||
)
|
||||
if resp.status_code == 200:
|
||||
match embed["sourceName"]:
|
||||
case "Luf-mp4":
|
||||
Logger.debug("allanime:Found streams from gogoanime")
|
||||
yield {
|
||||
"server": "gogoanime",
|
||||
"episode_title": (
|
||||
allanime_episode["notes"] or f'{anime["title"]}'
|
||||
)
|
||||
print("[yellow]GogoAnime Fetched")
|
||||
yield {
|
||||
"server": "gogoanime",
|
||||
"episode_title": (
|
||||
allanime_episode["notes"]
|
||||
or f'{anime["title"]}'
|
||||
)
|
||||
+ f"; Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
case "Kir":
|
||||
Logger.debug(
|
||||
"allanime:Found streams from wetransfer"
|
||||
+ f"; Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
case "Kir":
|
||||
Logger.debug("allanime:Found streams from wetransfer")
|
||||
yield {
|
||||
"server": "wetransfer",
|
||||
"episode_title": (
|
||||
allanime_episode["notes"] or f'{anime["title"]}'
|
||||
)
|
||||
print("[yellow]WeTransfer Fetched")
|
||||
yield {
|
||||
"server": "wetransfer",
|
||||
"episode_title": (
|
||||
allanime_episode["notes"]
|
||||
or f'{anime["title"]}'
|
||||
)
|
||||
+ f"; Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
case "S-mp4":
|
||||
Logger.debug(
|
||||
"allanime:Found streams from sharepoint"
|
||||
+ f"; Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
case "S-mp4":
|
||||
Logger.debug("allanime:Found streams from sharepoint")
|
||||
yield {
|
||||
"server": "sharepoint",
|
||||
"episode_title": (
|
||||
allanime_episode["notes"] or f'{anime["title"]}'
|
||||
)
|
||||
print("[yellow]Sharepoint Fetched")
|
||||
yield {
|
||||
"server": "sharepoint",
|
||||
"episode_title": (
|
||||
allanime_episode["notes"]
|
||||
or f'{anime["title"]}'
|
||||
)
|
||||
+ f"; Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
case "Sak":
|
||||
Logger.debug("allanime:Found streams from dropbox")
|
||||
print("[yellow]Dropbox Fetched")
|
||||
yield {
|
||||
"server": "dropbox",
|
||||
"episode_title": (
|
||||
allanime_episode["notes"]
|
||||
or f'{anime["title"]}'
|
||||
)
|
||||
+ f"; Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
except Timeout:
|
||||
print(
|
||||
"Timeout has been exceeded :cry: this could mean allanime is down or your internet connection is poor"
|
||||
)
|
||||
except Exception as e:
|
||||
print("Sth went wrong :confused:", e)
|
||||
except Exception:
|
||||
+ f"; Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
case "Sak":
|
||||
Logger.debug("allanime:Found streams from dropbox")
|
||||
yield {
|
||||
"server": "dropbox",
|
||||
"episode_title": (
|
||||
allanime_episode["notes"] or f'{anime["title"]}'
|
||||
)
|
||||
+ f"; Episode {episode_number}",
|
||||
"links": resp.json()["links"],
|
||||
} # pyright:ignore
|
||||
except Timeout:
|
||||
Logger.error(
|
||||
"Timeout has been exceeded this could mean allanime is down or you have lost internet connection"
|
||||
)
|
||||
return []
|
||||
except Exception as e:
|
||||
Logger.error(f"FA(Allanime): {e}")
|
||||
return []
|
||||
except Exception as e:
|
||||
Logger.error(f"FA(Allanime): {e}")
|
||||
return []
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from typing import Callable, List
|
||||
from art import text2art
|
||||
from rich import print
|
||||
|
||||
from ... import PLATFORM
|
||||
from ...constants import PLATFORM
|
||||
from .config import FZF_DEFAULT_OPTS, FzfOptions
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "fastanime"
|
||||
version = "0.31.3"
|
||||
version = "0.32.0"
|
||||
description = "A fast and efficient anime scrapper and exploration tool"
|
||||
authors = ["Benex254 <benedictx855@gmail.com>"]
|
||||
license = "UNLICENSE"
|
||||
|
||||
Reference in New Issue
Block a user