chore: clean up codebase

This commit is contained in:
Benex254
2024-08-23 16:05:26 +03:00
parent 6346ea7343
commit 7743b0423e
26 changed files with 525 additions and 523 deletions

View File

@@ -12,7 +12,6 @@ from .libs.anime_provider import anime_sources
if TYPE_CHECKING:
from typing import Iterator
from .libs.anilist.types import AnilistBaseMediaDataSchema
from .libs.anime_provider.types import Anime, SearchResults, Server
logger = logging.getLogger(__name__)
@@ -51,7 +50,6 @@ class AnimeProvider:
self,
user_query,
translation_type,
anilist_obj: "AnilistBaseMediaDataSchema | None" = None,
nsfw=True,
unknown=True,
) -> "SearchResults | None":
@@ -73,14 +71,14 @@ class AnimeProvider:
user_query, translation_type, nsfw, unknown
)
except Exception as e:
logger.error(e)
logger.error(f"[ANIMEPROVIDER-ERROR]: {e}")
results = None
return results
def get_anime(
self,
anime_id: str,
anilist_obj: "AnilistBaseMediaDataSchema | None" = None,
) -> "Anime | None":
"""core abstraction over getting info of an anime from all providers
@@ -95,7 +93,8 @@ class AnimeProvider:
try:
results = anime_provider.get_anime(anime_id)
except Exception as e:
logger.error(e)
logger.error(f"[ANIMEPROVIDER-ERROR]: {e}")
results = None
return results
@@ -104,7 +103,6 @@ class AnimeProvider:
anime,
episode: str,
translation_type: str,
anilist_obj: "AnilistBaseMediaDataSchema|None" = None,
) -> "Iterator[Server] | None":
"""core abstractions for getting juicy streams from all providers
@@ -123,6 +121,7 @@ class AnimeProvider:
anime, episode, translation_type
)
except Exception as e:
logger.error(e)
logger.error(f"[ANIMEPROVIDER-ERROR]: {e}")
results = None
return results # pyright:ignore
return results

View File

@@ -31,8 +31,6 @@ class YtDLPDownloader:
self._thread.daemon = True
self._thread.start()
# Function to download the file
# TODO: untpack the title to its actual values episode_title and anime_title
def _download_file(
self,
url: str,

View File

@@ -42,5 +42,5 @@ def completed(config: "Config", dump_json):
from ...interfaces import anilist_interfaces
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = anime_list[1]
fastanime_runtime_state.current_anilist_data = anime_list[1]
anilist_interfaces.anilist_results_menu(config, fastanime_runtime_state)

View File

@@ -42,5 +42,5 @@ def dropped(config: "Config", dump_json):
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = anime_list[1]
fastanime_runtime_state.current_anilist_data = anime_list[1]
anilist_interfaces.anilist_results_menu(config, fastanime_runtime_state)

View File

@@ -26,7 +26,7 @@ def favourites(config, dump_json):
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = anime_data[1]
fastanime_runtime_state.current_anilist_data = anime_data[1]
anilist_results_menu(config, fastanime_runtime_state)
else:
from sys import exit

View File

@@ -42,5 +42,5 @@ def planning(config: "Config", dump_json):
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = anime_list[1]
fastanime_runtime_state.current_anilist_data = anime_list[1]
anilist_interfaces.anilist_results_menu(config, fastanime_runtime_state)

View File

@@ -25,7 +25,7 @@ def popular(config, dump_json):
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = anime_data[1]
fastanime_runtime_state.current_anilist_data = anime_data[1]
anilist_results_menu(config, fastanime_runtime_state)
else:
from sys import exit

View File

@@ -33,7 +33,7 @@ def random_anime(config, dump_json):
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = anime_data[1]
fastanime_runtime_state.current_anilist_data = anime_data[1]
anilist_results_menu(config, fastanime_runtime_state)
else:
exit(1)

View File

@@ -26,7 +26,7 @@ def recent(config, dump_json):
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = anime_data[1]
fastanime_runtime_state.current_anilist_data = anime_data[1]
anilist_results_menu(config, fastanime_runtime_state)
else:
from sys import exit

View File

@@ -42,5 +42,5 @@ def rewatching(config: "Config", dump_json):
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = anime_list[1]
fastanime_runtime_state.current_anilist_data = anime_list[1]
anilist_interfaces.anilist_results_menu(config, fastanime_runtime_state)

View File

@@ -548,7 +548,7 @@ def search(
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = search_results
fastanime_runtime_state.current_anilist_data = search_results
anilist_results_menu(config, fastanime_runtime_state)
else:
from sys import exit

View File

@@ -26,7 +26,7 @@ def trending(config, dump_json):
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = data
fastanime_runtime_state.current_anilist_data = data
anilist_results_menu(config, fastanime_runtime_state)
else:
from sys import exit

View File

@@ -25,7 +25,7 @@ def upcoming(config, dump_json):
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = data
fastanime_runtime_state.current_anilist_data = data
anilist_results_menu(config, fastanime_runtime_state)
else:
from sys import exit

View File

@@ -42,5 +42,5 @@ def watching(config: "Config", dump_json):
from ...utils.tools import FastAnimeRuntimeState
fastanime_runtime_state = FastAnimeRuntimeState()
fastanime_runtime_state.anilist_data = anime_list[1]
fastanime_runtime_state.current_anilist_data = anime_list[1]
anilist_interfaces.anilist_results_menu(config, fastanime_runtime_state)

View File

@@ -6,20 +6,20 @@ ANILIST_ENDPOINT = "https://graphql.anilist.co"
anime_title_query = """
query($query:String){
Page(perPage:50){
pageInfo{
total
}
media(search:$query,type:ANIME){
id
idMal
title{
romaji
english
}
}
query ($query: String) {
Page(perPage: 50) {
pageInfo {
total
}
media(search: $query, type: ANIME) {
id
idMal
title {
romaji
english
}
}
}
}
"""

View File

@@ -370,7 +370,7 @@ def provider_anime_episode_servers_menu(
anime_id_anilist: int = fastanime_runtime_state.selected_anime_id_anilist
provider_anime: "Anime" = fastanime_runtime_state.provider_anime
server_name = None
server_name = ""
# get streams for episode from provider
with Progress() as progress:
progress.add_task("Fetching Episode Streams...", total=None)
@@ -378,7 +378,6 @@ def provider_anime_episode_servers_menu(
provider_anime,
current_episode_number,
translation_type,
fastanime_runtime_state.selected_anime_anilist,
)
if not episode_streams_generator:
if not config.use_rofi:
@@ -582,7 +581,7 @@ def provider_anime_episode_servers_menu(
# this will try to update the episode to be the next episode if delta has reached a specific threshhold
# this update will only apply locally
# the remote(anilist) is only updated when its certain you are going to open the player
available_episodes: list = sorted(
available_episodes: list[str] = sorted(
fastanime_runtime_state.provider_available_episodes, key=float
)
if stop_time == "0" or total_time == "0":
@@ -786,7 +785,6 @@ def anime_provider_search_results_menu(
provider_search_results = anime_provider.search_for_anime(
selected_anime_title,
translation_type,
selected_anime_anilist,
)
if not provider_search_results:
print(
@@ -1279,7 +1277,9 @@ def anilist_results_menu(
config: [TODO:description]
fastanime_runtime_state: [TODO:description]
"""
search_results = fastanime_runtime_state.anilist_data["data"]["Page"]["media"]
search_results = fastanime_runtime_state.current_anilist_data["data"]["Page"][
"media"
]
anime_data = {}
for anime in search_results:
@@ -1558,7 +1558,7 @@ def fastanime_main_menu(
# anilist data is a (bool,data)
# the bool indicated success
if anilist_data[0]:
fastanime_runtime_state.anilist_data = anilist_data[1]
fastanime_runtime_state.current_anilist_data = anilist_data[1]
anilist_results_menu(config, fastanime_runtime_state)
else:

View File

@@ -10,6 +10,7 @@ if TYPE_CHECKING:
from ...AnimeProvider import AnimeProvider
from ..config import Config
from .tools import FastAnimeRuntimeState
def format_time(duration_in_secs: float):
@@ -164,7 +165,7 @@ class MpvPlayer(object):
self,
stream_link,
anime_provider: "AnimeProvider",
fastanime_runtime_state,
fastanime_runtime_state: "FastAnimeRuntimeState",
config: "Config",
title,
start_time,

View File

@@ -9,70 +9,70 @@ fzf_preview = r"""
# - https://github.com/sharkdp/bat
# - https://github.com/hpjansson/chafa
# - https://iterm2.com/utilities/imgcat
fzf-preview(){
if [[ $# -ne 1 ]]; then
>&2 echo "usage: $0 FILENAME"
exit 1
fi
fzf-preview() {
if [[ $# -ne 1 ]]; then
>&2 echo "usage: $0 FILENAME"
exit 1
fi
file=${1/#\~\//$HOME/}
type=$(file --dereference --mime -- "$file")
file=${1/#\~\//$HOME/}
type=$(file --dereference --mime -- "$file")
if [[ ! $type =~ image/ ]]; then
if [[ $type =~ =binary ]]; then
file "$1"
exit
fi
if [[ ! $type =~ image/ ]]; then
if [[ $type =~ =binary ]]; then
file "$1"
exit
fi
# Sometimes bat is installed as batcat.
if command -v batcat > /dev/null; then
batname="batcat"
elif command -v bat > /dev/null; then
batname="bat"
else
cat "$1"
exit
fi
# Sometimes bat is installed as batcat.
if command -v batcat >/dev/null; then
batname="batcat"
elif command -v bat >/dev/null; then
batname="bat"
else
cat "$1"
exit
fi
${batname} --style="${BAT_STYLE:-numbers}" --color=always --pager=never -- "$file"
exit
fi
${batname} --style="${BAT_STYLE:-numbers}" --color=always --pager=never -- "$file"
exit
fi
dim=${FZF_PREVIEW_COLUMNS}x${FZF_PREVIEW_LINES}
if [[ $dim = x ]]; then
dim=$(stty size < /dev/tty | awk '{print $2 "x" $1}')
elif ! [[ $KITTY_WINDOW_ID ]] && (( FZF_PREVIEW_TOP + FZF_PREVIEW_LINES == $(stty size < /dev/tty | awk '{print $1}') )); then
# Avoid scrolling issue when the Sixel image touches the bottom of the screen
# * https://github.com/junegunn/fzf/issues/2544
dim=${FZF_PREVIEW_COLUMNS}x$((FZF_PREVIEW_LINES - 1))
fi
dim=${FZF_PREVIEW_COLUMNS}x${FZF_PREVIEW_LINES}
if [[ $dim = x ]]; then
dim=$(stty size </dev/tty | awk '{print $2 "x" $1}')
elif ! [[ $KITTY_WINDOW_ID ]] && ((FZF_PREVIEW_TOP + FZF_PREVIEW_LINES == $(stty size </dev/tty | awk '{print $1}'))); then
# Avoid scrolling issue when the Sixel image touches the bottom of the screen
# * https://github.com/junegunn/fzf/issues/2544
dim=${FZF_PREVIEW_COLUMNS}x$((FZF_PREVIEW_LINES - 1))
fi
# 1. Use kitty icat on kitty terminal
if [[ $KITTY_WINDOW_ID ]]; then
# 1. 'memory' is the fastest option but if you want the image to be scrollable,
# you have to use 'stream'.
#
# 2. The last line of the output is the ANSI reset code without newline.
# This confuses fzf and makes it render scroll offset indicator.
# So we remove the last line and append the reset code to its previous line.
kitty icat --clear --transfer-mode=memory --unicode-placeholder --stdin=no --place="$dim@0x0" "$file" | sed '$d' | sed $'$s/$/\e[m/'
# 1. Use kitty icat on kitty terminal
if [[ $KITTY_WINDOW_ID ]]; then
# 1. 'memory' is the fastest option but if you want the image to be scrollable,
# you have to use 'stream'.
#
# 2. The last line of the output is the ANSI reset code without newline.
# This confuses fzf and makes it render scroll offset indicator.
# So we remove the last line and append the reset code to its previous line.
kitty icat --clear --transfer-mode=memory --unicode-placeholder --stdin=no --place="$dim@0x0" "$file" | sed '$d' | sed $'$s/$/\e[m/'
# 2. Use chafa with Sixel output
elif command -v chafa > /dev/null; then
chafa -f sixel -s "$dim" "$file"
# Add a new line character so that fzf can display multiple images in the preview window
echo
# 2. Use chafa with Sixel output
elif command -v chafa >/dev/null; then
chafa -f sixel -s "$dim" "$file"
# Add a new line character so that fzf can display multiple images in the preview window
echo
# 3. If chafa is not found but imgcat is available, use it on iTerm2
elif command -v imgcat > /dev/null; then
# NOTE: We should use https://iterm2.com/utilities/it2check to check if the
# user is running iTerm2. But for the sake of simplicity, we just assume
# that's the case here.
imgcat -W "${dim%%x*}" -H "${dim##*x}" "$file"
# 3. If chafa is not found but imgcat is available, use it on iTerm2
elif command -v imgcat >/dev/null; then
# NOTE: We should use https://iterm2.com/utilities/it2check to check if the
# user is running iTerm2. But for the sake of simplicity, we just assume
# that's the case here.
imgcat -W "${dim%%x*}" -H "${dim##*x}" "$file"
# 4. Cannot find any suitable method to preview the image
else
file "$file"
fi
# 4. Cannot find any suitable method to preview the image
else
file "$file"
fi
}
"""

View File

@@ -1,17 +1,30 @@
# TODO: add typing
class FastAnimeRuntimeState(dict):
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import Any
from ...libs.anilist.types import AnilistBaseMediaDataSchema
from ...libs.anime_provider.types import Anime, EpisodeStream, SearchResult, Server
class FastAnimeRuntimeState(object):
"""A class that manages fastanime runtime during anilist command runtime"""
def __getattr__(self, attr):
try:
return self.__getitem__(attr)
except KeyError:
raise AttributeError(
"%r object has no attribute %r" % (self.__class__.__name__, attr)
)
provider_current_episode_stream_link: str
provider_current_server: "Server"
provider_current_server_name: str
provider_available_episodes: list[str]
provider_current_episode_number: str
provider_server_episode_streams: list["EpisodeStream"]
provider_anime_title: str
provider_anime: "Anime"
provider_anime_search_result: "SearchResult"
def __setattr__(self, attr, value):
self.__setitem__(attr, value)
selected_anime_anilist: "AnilistBaseMediaDataSchema"
selected_anime_id_anilist: int
selected_anime_title_anilist: str
# current_anilist_data: "AnilistDataSchema | AnilistMediaList"
current_anilist_data: "Any"
def exit_app(exit_code=0, *args):

View File

@@ -3,7 +3,6 @@ This module contains all the preset queries for the sake of neatness and convini
Mostly for internal usage
"""
# TODO: Format the queries
mark_as_read_mutation = """
mutation{
UpdateUser{
@@ -17,7 +16,6 @@ query($id:Int){
pageInfo{
total
}
reviews(mediaId:$id){
summary
user{
@@ -35,50 +33,48 @@ query($id:Int){
"""
notification_query = """
query{
Page(perPage:5){
pageInfo {
total
}
notifications(resetNotificationCount:true,type:AIRING) {
... on AiringNotification {
id
type
episode
contexts
createdAt
media {
id
idMal
title {
romaji
english
}
coverImage{
medium
}
}
}
}
query {
Page(perPage: 5) {
pageInfo {
total
}
notifications(resetNotificationCount: true, type: AIRING) {
... on AiringNotification {
id
type
episode
contexts
createdAt
media {
id
idMal
title {
romaji
english
}
coverImage {
medium
}
}
}
}
}
}
"""
get_medialist_item_query = """
query($mediaId:Int){
MediaList(mediaId:$mediaId){
id
}
query ($mediaId: Int) {
MediaList(mediaId: $mediaId) {
id
}
}
"""
delete_list_entry_query = """
mutation($id:Int){
DeleteMediaListEntry(id:$id){
deleted
}
mutation ($id: Int) {
DeleteMediaListEntry(id: $id) {
deleted
}
}
"""
@@ -98,8 +94,20 @@ query{
"""
media_list_mutation = """
mutation($mediaId:Int,$scoreRaw:Int,$repeat:Int,$progress:Int,$status:MediaListStatus){
SaveMediaListEntry(mediaId:$mediaId,scoreRaw:$scoreRaw,progress:$progress,repeat:$repeat,status:$status){
mutation (
$mediaId: Int
$scoreRaw: Int
$repeat: Int
$progress: Int
$status: MediaListStatus
) {
SaveMediaListEntry(
mediaId: $mediaId
scoreRaw: $scoreRaw
progress: $progress
repeat: $repeat
status: $status
) {
id
status
mediaId
@@ -116,21 +124,19 @@ mutation($mediaId:Int,$scoreRaw:Int,$repeat:Int,$progress:Int,$status:MediaListS
month
day
}
}
}
"""
media_list_query = """
query ($userId: Int, $status: MediaListStatus,$type:MediaType) {
query ($userId: Int, $status: MediaListStatus, $type: MediaType) {
Page {
pageInfo {
currentPage
total
currentPage
total
}
mediaList(userId: $userId, status: $status, type: $type) {
mediaId
media {
id
idMal
@@ -147,11 +153,10 @@ query ($userId: Int, $status: MediaListStatus,$type:MediaType) {
id
}
popularity
streamingEpisodes{
title
thumbnail
}
streamingEpisodes {
title
thumbnail
}
favourites
averageScore
episodes
@@ -177,10 +182,10 @@ query ($userId: Int, $status: MediaListStatus,$type:MediaType) {
}
status
description
mediaListEntry{
status
id
progress
mediaListEntry {
status
id
progress
}
nextAiringEpisode {
timeUntilAiring
@@ -204,7 +209,6 @@ query ($userId: Int, $status: MediaListStatus,$type:MediaType) {
day
}
createdAt
}
}
}
@@ -236,75 +240,71 @@ $format_in:[MediaFormat],\
$type:MediaType\
$season:MediaSeason\
"
# FuzzyDateInt = (yyyymmdd)
# MediaStatus = (FINISHED,RELEASING,NOT_YET_RELEASED,CANCELLED,HIATUS)
search_query = (
"""
query($query:String,%s){
Page(perPage:50,page:$page){
pageInfo{
Page(perPage: 50, page: $page) {
pageInfo {
total
currentPage
hasNextPage
}
media(
search:$query,
id_in:$id_in,
genre_in:$genre_in,
genre_not_in:$genre_not_in,
tag_in:$tag_in,
tag_not_in:$tag_not_in,
status_in:$status_in,
status:$status,
startDate:$startDate,
status_not_in:$status_not_in,
popularity_greater:$popularity_greater,
popularity_lesser:$popularity_lesser,
averageScore_greater:$averageScore_greater,
averageScore_lesser:$averageScore_lesser,
startDate_greater:$startDate_greater,
startDate_lesser:$startDate_lesser,
endDate_greater:$endDate_greater,
endDate_lesser:$endDate_lesser,
format_in:$format_in,
sort:$sort,
season:$season,
seasonYear:$seasonYear,
type:$type
)
{
search: $query
id_in: $id_in
genre_in: $genre_in
genre_not_in: $genre_not_in
tag_in: $tag_in
tag_not_in: $tag_not_in
status_in: $status_in
status: $status
startDate: $startDate
status_not_in: $status_not_in
popularity_greater: $popularity_greater
popularity_lesser: $popularity_lesser
averageScore_greater: $averageScore_greater
averageScore_lesser: $averageScore_lesser
startDate_greater: $startDate_greater
startDate_lesser: $startDate_lesser
endDate_greater: $endDate_greater
endDate_lesser: $endDate_lesser
format_in: $format_in
sort: $sort
season: $season
seasonYear: $seasonYear
type: $type
) {
id
idMal
title{
idMal
title {
romaji
english
}
coverImage{
coverImage {
medium
large
}
trailer {
site
id
}
mediaListEntry{
status
mediaListEntry {
status
id
progress
}
}
popularity
streamingEpisodes{
streamingEpisodes {
title
thumbnail
}
}
favourites
averageScore
episodes
genres
studios{
nodes{
studios {
nodes {
name
isAnimationStudio
}
@@ -337,17 +337,16 @@ query($query:String,%s){
)
trending_query = """
query($type:MediaType){
Page(perPage:15){
media(sort:TRENDING_DESC,type:$type,genre_not_in:["hentai"]){
query ($type: MediaType) {
Page(perPage: 15) {
media(sort: TRENDING_DESC, type: $type, genre_not_in: ["hentai"]) {
id
idMal
title{
idMal
title {
romaji
english
}
coverImage{
coverImage {
medium
large
}
@@ -356,11 +355,10 @@ query($type:MediaType){
id
}
popularity
streamingEpisodes{
streamingEpisodes {
title
thumbnail
}
}
favourites
averageScore
genres
@@ -373,18 +371,18 @@ query($type:MediaType){
}
}
tags {
name
name
}
startDate {
year
month
day
}
mediaListEntry{
mediaListEntry {
status
id
progress
}
}
endDate {
year
month
@@ -403,39 +401,37 @@ query($type:MediaType){
# mosts
most_favourite_query = """
query($type:MediaType){
Page(perPage:15){
media(sort:FAVOURITES_DESC,type:$type,genre_not_in:["hentai"]){
query ($type: MediaType) {
Page(perPage: 15) {
media(sort: FAVOURITES_DESC, type: $type, genre_not_in: ["hentai"]) {
id
idMal
title{
idMal
title {
romaji
english
}
coverImage{
coverImage {
medium
large
}
trailer {
site
id
}
mediaListEntry{
mediaListEntry {
status
id
progress
}
}
popularity
streamingEpisodes{
streamingEpisodes {
title
thumbnail
}
streamingEpisodes{
}
streamingEpisodes {
title
thumbnail
}
}
favourites
averageScore
episodes
@@ -448,7 +444,7 @@ query($type:MediaType){
}
}
tags {
name
name
}
startDate {
year
@@ -472,35 +468,33 @@ query($type:MediaType){
"""
most_scored_query = """
query($type:MediaType){
Page(perPage:15){
media(sort:SCORE_DESC,type:$type,genre_not_in:["hentai"]){
query ($type: MediaType) {
Page(perPage: 15) {
media(sort: SCORE_DESC, type: $type, genre_not_in: ["hentai"]) {
id
idMal
title{
idMal
title {
romaji
english
}
coverImage{
coverImage {
medium
large
}
trailer {
site
id
}
mediaListEntry{
mediaListEntry {
status
id
progress
}
}
popularity
streamingEpisodes{
streamingEpisodes {
title
thumbnail
}
}
episodes
favourites
averageScore
@@ -513,7 +507,7 @@ query($type:MediaType){
}
}
tags {
name
name
}
startDate {
year
@@ -537,40 +531,38 @@ query($type:MediaType){
"""
most_popular_query = """
query($type:MediaType){
Page(perPage:15){
media(sort:POPULARITY_DESC,type:$type,genre_not_in:["hentai"]){
query ($type: MediaType) {
Page(perPage: 15) {
media(sort: POPULARITY_DESC, type: $type, genre_not_in: ["hentai"]) {
id
idMal
title{
idMal
title {
romaji
english
}
coverImage{
coverImage {
medium
large
}
trailer {
site
id
}
popularity
streamingEpisodes{
streamingEpisodes {
title
thumbnail
}
}
favourites
averageScore
description
episodes
genres
mediaListEntry{
mediaListEntry {
status
id
progress
}
}
studios {
nodes {
name
@@ -578,8 +570,8 @@ query($type:MediaType){
}
}
tags {
name
}
name
}
startDate {
year
month
@@ -595,40 +587,46 @@ query($type:MediaType){
timeUntilAiring
airingAt
episode
}
}
}
}
}
"""
most_recently_updated_query = """
query($type:MediaType){
Page(perPage:15){
media(sort:UPDATED_AT_DESC,type:$type,averageScore_greater:50,genre_not_in:["hentai"],status:RELEASING){
query ($type: MediaType) {
Page(perPage: 15) {
media(
sort: UPDATED_AT_DESC
type: $type
averageScore_greater: 50
genre_not_in: ["hentai"]
status: RELEASING
) {
id
idMal
title{
idMal
title {
romaji
english
}
coverImage{
coverImage {
medium
large
}
trailer {
site
id
id
}
mediaListEntry{
mediaListEntry {
status
id
progress
}
}
popularity
streamingEpisodes{
streamingEpisodes {
title
thumbnail
}
}
favourites
averageScore
@@ -642,7 +640,7 @@ query($type:MediaType){
}
}
tags {
name
name
}
startDate {
year
@@ -666,43 +664,41 @@ query($type:MediaType){
"""
recommended_query = """
query($type:MediaType){
Page(perPage:15) {
media( type: $type,genre_not_in:["hentai"]) {
recommendations(sort:RATING_DESC){
nodes{
media{
query ($type: MediaType) {
Page(perPage: 15) {
media(type: $type, genre_not_in: ["hentai"]) {
recommendations(sort: RATING_DESC) {
nodes {
media {
id
idMal
title{
idMal
title {
english
romaji
native
}
coverImage{
coverImage {
medium
large
}
mediaListEntry{
status
id
progress
mediaListEntry {
status
id
progress
}
description
episodes
trailer{
trailer {
site
id
}
genres
averageScore
popularity
streamingEpisodes{
title
thumbnail
}
streamingEpisodes {
title
thumbnail
}
favourites
tags {
name
@@ -732,9 +728,9 @@ query($type:MediaType){
"""
anime_characters_query = """
query($id:Int,$type:MediaType){
query ($id: Int, $type: MediaType) {
Page {
media(id:$id, type: $type) {
media(id: $id, type: $type) {
characters {
nodes {
name {
@@ -767,13 +763,18 @@ query($id:Int,$type:MediaType){
anime_relations_query = """
query ($id: Int,$type:MediaType) {
query ($id: Int, $type: MediaType) {
Page(perPage: 20) {
media(id: $id, sort: POPULARITY_DESC, type: $type,genre_not_in:["hentai"]) {
media(
id: $id
sort: POPULARITY_DESC
type: $type
genre_not_in: ["hentai"]
) {
relations {
nodes {
id
idMal
idMal
title {
english
romaji
@@ -783,11 +784,11 @@ query ($id: Int,$type:MediaType) {
medium
large
}
mediaListEntry{
status
id
progress
}
mediaListEntry {
status
id
progress
}
description
episodes
trailer {
@@ -797,31 +798,30 @@ query ($id: Int,$type:MediaType) {
genres
averageScore
popularity
streamingEpisodes{
title
thumbnail
}
streamingEpisodes {
title
thumbnail
}
favourites
tags {
name
}
startDate {
year
month
day
}
endDate {
year
month
day
}
status
nextAiringEpisode {
timeUntilAiring
airingAt
episode
}
year
month
day
}
endDate {
year
month
day
}
status
nextAiringEpisode {
timeUntilAiring
airingAt
episode
}
}
}
}
@@ -847,7 +847,7 @@ query ($id: Int,$type:MediaType) {
"""
upcoming_anime_query = """
query ($page: Int,$type:MediaType) {
query ($page: Int, $type: MediaType) {
Page(page: $page) {
pageInfo {
total
@@ -855,9 +855,14 @@ query ($page: Int,$type:MediaType) {
currentPage
hasNextPage
}
media(type: $type, status: NOT_YET_RELEASED,sort:POPULARITY_DESC,genre_not_in:["hentai"]) {
media(
type: $type
status: NOT_YET_RELEASED
sort: POPULARITY_DESC
genre_not_in: ["hentai"]
) {
id
idMal
idMal
title {
romaji
english
@@ -870,17 +875,16 @@ query ($page: Int,$type:MediaType) {
site
id
}
mediaListEntry{
status
mediaListEntry {
status
id
progress
}
}
popularity
streamingEpisodes{
streamingEpisodes {
title
thumbnail
}
}
favourites
averageScore
genres
@@ -917,20 +921,20 @@ query ($page: Int,$type:MediaType) {
"""
anime_query = """
query($id:Int){
Page{
media(id:$id) {
query ($id: Int) {
Page {
media(id: $id) {
id
idMal
idMal
title {
romaji
english
}
mediaListEntry{
status
mediaListEntry {
status
id
progress
}
}
nextAiringEpisode {
timeUntilAiring
airingAt
@@ -944,7 +948,6 @@ query($id:Int){
node {
name {
full
}
gender
dateOfBirth {
@@ -997,10 +1000,10 @@ query($id:Int){
countryOfOrigin
averageScore
popularity
streamingEpisodes{
streamingEpisodes {
title
thumbnail
}
}
favourites
source

View File

@@ -15,10 +15,7 @@ from .constants import ALLANIME_API_ENDPOINT, ALLANIME_BASE, ALLANIME_REFERER
from .gql_queries import ALLANIME_EPISODES_GQL, ALLANIME_SEARCH_GQL, ALLANIME_SHOW_GQL
if TYPE_CHECKING:
from typing import Iterator
from ....libs.anime_provider.allanime.types import AllAnimeEpisode
from ....libs.anime_provider.types import Anime, Server
from .types import AllAnimeEpisode
logger = logging.getLogger(__name__)
@@ -54,18 +51,18 @@ class AllAnimeAPI(AnimeProvider):
},
timeout=10,
)
if response.status_code == 200:
if response.ok:
return response.json()["data"]
else:
logger.error("allanime(ERROR): ", response.text)
logger.error("[ALLANIME-ERROR]: ", response.text)
return {}
except Timeout:
logger.error(
"allanime(Error):Timeout exceeded this could mean allanime is down or you have lost internet connection"
"[ALLANIME-ERROR]: Timeout exceeded this could mean allanime is down or you have lost internet connection"
)
return {}
except Exception as e:
logger.error(f"allanime:Error: {e}")
logger.error(f"[ALLANIME-ERROR]: {e}")
return {}
def search_for_anime(
@@ -120,7 +117,7 @@ class AllAnimeAPI(AnimeProvider):
return normalized_search_results
except Exception as e:
logger.error(f"FA(AllAnime): {e}")
logger.error(f"[ALLANIME-ERROR]: {e}")
return {}
def get_anime(self, allanime_show_id: str):
@@ -147,8 +144,8 @@ class AllAnimeAPI(AnimeProvider):
}
return normalized_anime
except Exception as e:
logger.error(f"AllAnime(get_anime): {e}")
return None
logger.error(f"[ALLANIME-ERROR]: {e}")
return {}
def _get_anime_episode(
self, allanime_show_id: str, episode_string: str, translation_type: str = "sub"
@@ -172,12 +169,10 @@ class AllAnimeAPI(AnimeProvider):
episode = self._fetch_gql(ALLANIME_EPISODES_GQL, variables)
return episode["episode"]
except Exception as e:
logger.error(f"FA(AllAnime): {e}")
logger.error(f"[ALLANIME-ERROR]: {e}")
return {}
def get_episode_streams(
self, anime: "Anime", episode_number: str, translation_type="sub"
) -> "Iterator[Server] | None":
def get_episode_streams(self, anime, episode_number: str, translation_type="sub"):
"""get the streams of an episode
Args:
@@ -235,7 +230,7 @@ class AllAnimeAPI(AnimeProvider):
"quality": "1080",
}
],
} # pyright:ignore
}
continue
# get the stream url for an episode of the defined source names
@@ -247,7 +242,7 @@ class AllAnimeAPI(AnimeProvider):
timeout=10,
)
if resp.status_code == 200:
if resp.ok:
match embed["sourceName"]:
case "Luf-mp4":
logger.debug("allanime:Found streams from gogoanime")
@@ -260,7 +255,7 @@ class AllAnimeAPI(AnimeProvider):
)
+ f"; Episode {episode_number}",
"links": give_random_quality(resp.json()["links"]),
} # pyright:ignore
}
case "Kir":
logger.debug("allanime:Found streams from wetransfer")
yield {
@@ -272,7 +267,7 @@ class AllAnimeAPI(AnimeProvider):
)
+ f"; Episode {episode_number}",
"links": give_random_quality(resp.json()["links"]),
} # pyright:ignore
}
case "S-mp4":
logger.debug("allanime:Found streams from sharepoint")
yield {
@@ -284,7 +279,7 @@ class AllAnimeAPI(AnimeProvider):
)
+ f"; Episode {episode_number}",
"links": give_random_quality(resp.json()["links"]),
} # pyright:ignore
}
case "Sak":
logger.debug("allanime:Found streams from dropbox")
yield {
@@ -296,7 +291,7 @@ class AllAnimeAPI(AnimeProvider):
)
+ f"; Episode {episode_number}",
"links": give_random_quality(resp.json()["links"]),
} # pyright:ignore
}
case "Default":
logger.debug("allanime:Found streams from wixmp")
yield {
@@ -308,16 +303,13 @@ class AllAnimeAPI(AnimeProvider):
)
+ f"; Episode {episode_number}",
"links": give_random_quality(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"
"[ALLANIME-ERROR]: Timeout has been exceeded this could mean allanime is down or you have lost internet connection"
)
except Exception as e:
logger.error(f"FA(Allanime): {e}")
logger.error(f"[ALLANIME-ERROR]: {e}")
except Exception as e:
logger.error(f"FA(Allanime): {e}")
logger.error(f"[ALLANIME-ERROR]: {e}")
return []

View File

@@ -1,56 +1,56 @@
ALLANIME_SEARCH_GQL = """
query(
$search: SearchInput
$limit: Int
$page: Int
$translationType: VaildTranslationTypeEnumType
$countryOrigin: VaildCountryOriginEnumType
) {
shows(
search: $search
limit: $limit
page: $page
translationType: $translationType
countryOrigin: $countryOrigin
) {
pageInfo {
total
}
edges {
_id
name
availableEpisodes
__typename
}
query (
$search: SearchInput
$limit: Int
$page: Int
$translationType: VaildTranslationTypeEnumType
$countryOrigin: VaildCountryOriginEnumType
) {
shows(
search: $search
limit: $limit
page: $page
translationType: $translationType
countryOrigin: $countryOrigin
) {
pageInfo {
total
}
edges {
_id
name
availableEpisodes
__typename
}
}
}
"""
ALLANIME_EPISODES_GQL = """\
query ($showId: String!, $translationType: VaildTranslationTypeEnumType!, $episodeString: String!) {
episode(
showId: $showId
translationType: $translationType
episodeString: $episodeString
) {
episodeString
sourceUrls
notes
}
}"""
query (
$showId: String!
$translationType: VaildTranslationTypeEnumType!
$episodeString: String!
) {
episode(
showId: $showId
translationType: $translationType
episodeString: $episodeString
) {
episodeString
sourceUrls
notes
}
}
"""
ALLANIME_SHOW_GQL = """
query ($showId: String!) {
show(
_id: $showId
) {
_id
name
availableEpisodesDetail
}
show(_id: $showId) {
_id
name
availableEpisodesDetail
}
}
"""

View File

@@ -20,7 +20,6 @@ from .constants import (
from .utils import process_animepahe_embed_page
if TYPE_CHECKING:
from ..types import Anime
from .types import AnimePaheAnimePage, AnimePaheSearchPage, AnimeSearchResult
JUICY_STREAM_REGEX = re.compile(r"source='(.*)';")
logger = logging.getLogger(__name__)
@@ -40,7 +39,7 @@ class AnimePaheApi(AnimeProvider):
response = self.session.get(
url,
)
if not response.status_code == 200:
if not response.ok:
return
data: "AnimePaheSearchPage" = response.json()
self.search_page = data
@@ -68,7 +67,7 @@ class AnimePaheApi(AnimeProvider):
}
except Exception as e:
logger.error(f"AnimePahe(search): {e}")
logger.error(f"[ANIMEPAHE-ERROR]: {e}")
return {}
def get_anime(self, session_id: str, *args):
@@ -90,7 +89,7 @@ class AnimePaheApi(AnimeProvider):
response = self.session.get(
url,
)
if response.status_code == 200:
if response.ok:
if not data:
data.update(response.json())
else:
@@ -151,12 +150,10 @@ class AnimePaheApi(AnimeProvider):
],
}
except Exception as e:
logger.error(f"AnimePahe(anime): {e}")
logger.error(f"[ANIMEPAHE-ERROR]: {e}")
return {}
def get_episode_streams(
self, anime: "Anime", episode_number: str, translation_type, *args
):
def get_episode_streams(self, anime, episode_number: str, translation_type, *args):
try:
# extract episode details from memory
episode = [
@@ -167,7 +164,7 @@ class AnimePaheApi(AnimeProvider):
if not episode:
logger.error(
f"AnimePahe(streams): episode {episode_number} doesn't exist"
f"[ANIMEPAHE-ERROR]: episode {episode_number} doesn't exist"
)
return []
episode = episode[0]
@@ -207,24 +204,24 @@ class AnimePaheApi(AnimeProvider):
if not embed_url:
logger.warn(
"AnimePahe: embed url not found please report to the developers"
"[ANIMEPAHE-WARN]: embed url not found please report to the developers"
)
return []
# get embed page
embed_response = self.session.get(
embed_url, headers={"User-Agent": self.USER_AGENT, **SERVER_HEADERS}
)
if not response.status_code == 200:
if not response.ok:
continue
embed_page = embed_response.text
decoded_js = process_animepahe_embed_page(embed_page)
if not decoded_js:
logger.error("Animepahe: failed to decode embed page")
logger.error("[ANIMEPAHE-ERROR]: failed to decode embed page")
return
juicy_stream = JUICY_STREAM_REGEX.search(decoded_js)
if not juicy_stream:
logger.error("Animepahe: failed to find juicy stream")
logger.error("[ANIMEPAHE-ERROR]: failed to find juicy stream")
return
juicy_stream = juicy_stream.group(1)
# add the link
@@ -237,4 +234,4 @@ class AnimePaheApi(AnimeProvider):
)
yield streams
except Exception as e:
logger.error(f"Animepahe: {e}")
logger.error(f"[ANIMEPAHE-ERROR]: {e}")

View File

@@ -45,7 +45,7 @@ class AniWatchApi(AnimeProvider):
query = quote_plus(anime_title)
url = f"https://hianime.to/search?keyword={query}"
response = self.session.get(url)
if response.status_code != 200:
if not response.ok:
return
search_page = response.text
search_results_html_items = get_elements_by_class("flw-item", search_page)
@@ -88,7 +88,7 @@ class AniWatchApi(AnimeProvider):
return {"pageInfo": {}, "results": results}
except Exception as e:
logger.error(e)
logger.error(f"[ANIWATCH-ERROR]: {e}")
def get_anime(self, aniwatch_id, *args):
try:
@@ -99,7 +99,7 @@ class AniWatchApi(AnimeProvider):
break
anime_url = f"https://hianime.to/ajax/v2/episode/list/{aniwatch_id}"
response = self.session.get(anime_url, timeout=10)
if response.status_code == 200:
if response.ok:
response_json = response.json()
aniwatch_anime_page = response_json["html"]
episodes_info_container_html = get_element_html_by_class(
@@ -140,7 +140,7 @@ class AniWatchApi(AnimeProvider):
"episodes_info": self.episodes_info,
}
except Exception as e:
logger.error(e)
logger.error(f"[ANIWACTCH-ERROR]: {e}")
def get_episode_streams(self, anime, episode, translation_type, *args):
try:
@@ -154,7 +154,7 @@ class AniWatchApi(AnimeProvider):
episode_details = episode_details[0]
episode_url = f"https://hianime.to/ajax/v2/episode/servers?episodeId={episode_details['id']}"
response = self.session.get(episode_url)
if response.status_code == 200:
if response.ok:
response_json = response.json()
episode_page_html = response_json["html"]
servers_containers_html = get_elements_html_by_class(
@@ -194,7 +194,7 @@ class AniWatchApi(AnimeProvider):
servers_info = extract_attributes(server_html)
embed_url = f"https://hianime.to/ajax/v2/episode/sources?id={servers_info['data-id']}"
embed_response = self.session.get(embed_url)
if embed_response.status_code == 200:
if embed_response.ok:
embed_json = embed_response.json()
raw_link_to_streams = embed_json["link"]
match = LINK_TO_STREAMS_REGEX.match(raw_link_to_streams)
@@ -207,7 +207,7 @@ class AniWatchApi(AnimeProvider):
link_to_streams = f"https://{provider_domain}/embed-{embed_type}/ajax/e-{episode_number}/getSources?id={source_id}"
link_to_streams_response = self.session.get(link_to_streams)
if link_to_streams_response.status_code == 200:
if link_to_streams_response.ok:
juicy_streams_json: "AniWatchStream" = (
link_to_streams_response.json()
)
@@ -231,6 +231,6 @@ class AniWatchApi(AnimeProvider):
),
}
except Exception as e:
logger.error(e)
logger.error(f"[ANIWATCH_ERROR]: {e}")
except Exception as e:
logger.error(e)
logger.error(f"[ANIWATCH_ERROR]: {e}")

View File

@@ -10,27 +10,27 @@ logger = logging.getLogger(__name__)
ANILIST_ENDPOINT = "https://graphql.anilist.co"
"""
query($query:String){
Page(perPage:50){
pageInfo{
total
currentPage
hasNextPage
}
media(search:$query,type:ANIME){
id
idMal
title{
romaji
english
}
episodes
status
nextAiringEpisode {
timeUntilAiring
airingAt
episode
}
query ($query: String) {
Page(perPage: 50) {
pageInfo {
total
currentPage
hasNextPage
}
media(search: $query, type: ANIME) {
id
idMal
title {
romaji
english
}
episodes
status
nextAiringEpisode {
timeUntilAiring
airingAt
episode
}
}
}
}
@@ -39,27 +39,27 @@ query($query:String){
def search_for_manga_with_anilist(manga_title: str):
query = """
query($query:String){
Page(perPage:50){
pageInfo{
currentPage
query ($query: String) {
Page(perPage: 50) {
pageInfo {
currentPage
}
media(search:$query,type:MANGA){
id
idMal
title{
romaji
english
}
chapters
status
coverImage{
media(search: $query, type: MANGA) {
id
idMal
title {
romaji
english
}
chapters
status
coverImage {
medium
large
}
}
}
}
}
}
"""
response = post(
ANILIST_ENDPOINT,
@@ -98,30 +98,30 @@ def search_for_manga_with_anilist(manga_title: str):
def search_for_anime_with_anilist(anime_title: str):
query = """
query($query:String){
Page(perPage:50){
pageInfo{
total
currentPage
hasNextPage
query ($query: String) {
Page(perPage: 50) {
pageInfo {
total
currentPage
hasNextPage
}
media(search: $query, type: ANIME) {
id
idMal
title {
romaji
english
}
episodes
status
nextAiringEpisode {
timeUntilAiring
airingAt
episode
}
media(search:$query,type:ANIME){
id
idMal
title{
romaji
english
}
episodes
status
nextAiringEpisode {
timeUntilAiring
airingAt
episode
}
}
}
}
}
"""
response = post(
ANILIST_ENDPOINT,
@@ -170,23 +170,23 @@ def get_mal_id_and_anilist_id(anime_title: str) -> "dict[str,int] | None":
a boolean indicating success and none or an anilist object depending on success
"""
query = """
query($query:String){
Page(perPage:50){
pageInfo{
total
currentPage
hasNextPage
query ($query: String) {
Page(perPage: 50) {
pageInfo {
total
currentPage
hasNextPage
}
media(search: $query, type: ANIME) {
id
idMal
title {
romaji
english
}
media(search:$query,type:ANIME){
id
idMal
title{
romaji
english
}
}
}
}
}
"""
try:
@@ -223,24 +223,24 @@ def get_basic_anime_info_by_title(anime_title: str):
a boolean indicating success and none or an anilist object depending on success
"""
query = """
query($query:String){
Page(perPage:50){
pageInfo{
total
query ($query: String) {
Page(perPage: 50) {
pageInfo {
total
}
media(search:$query,type:ANIME){
id
idMal
title{
romaji
english
}
streamingEpisodes{
media(search: $query, type: ANIME) {
id
idMal
title {
romaji
english
}
streamingEpisodes {
title
}
}
}
}
}
}
"""
from ...Utility.data import anime_normalizer

View File

@@ -1,4 +1,3 @@
# TODO: Write tests to make sure all click commands work
import pytest
from click.testing import CliRunner