diff --git a/fastanime/Controller/anime_screen.py b/fastanime/Controller/anime_screen.py index a08d6e0..b3f60ab 100644 --- a/fastanime/Controller/anime_screen.py +++ b/fastanime/Controller/anime_screen.py @@ -1,6 +1,4 @@ from kivy.cache import Cache -from kivy.clock import Clock -from kivy.logger import Logger from ..Model import AnimeScreenModel from ..View import AnimeScreenView @@ -18,25 +16,13 @@ class AnimeScreenController: def get_view(self) -> AnimeScreenView: return self.view - def update_anime_view(self, id: int, caller_screen_name: str): - """method called to update the anime screen when a new + def fetch_streams(self, anime_title, episode="1"): + self.view.current_anime_data = self.model.get_anime_data_from_provider( + anime_title + ) + self.view.current_links = self.model.get_episode_streams(episode) - Args: - id (int): the anilst id of the anime - caller_screen_name (str): the screen thats calling this method; used internally to switch back to this screen - """ - if self.model.anime_id != id: - if cached_anime_data := Cache.get("data.anime", f"{id}"): - data = cached_anime_data - else: - data = self.model.get_anime_data(id) - - if data[0]: - self.model.anime_id = id - Clock.schedule_once( - lambda _: self.view.update_layout( - data[1]["data"]["Page"]["media"][0], caller_screen_name - ) - ) - Logger.info(f"Anime Screen:Success in opening anime of id: {id}") - Cache.append("data.anime", f"{id}", data) + def update_anime_view(self, id, title, caller_screen_name): + self.fetch_streams(title) + self.view.current_title = title + self.view.caller_screen_name = caller_screen_name diff --git a/fastanime/Controller/home_screen.py b/fastanime/Controller/home_screen.py index 16af637..c0e4b6e 100644 --- a/fastanime/Controller/home_screen.py +++ b/fastanime/Controller/home_screen.py @@ -120,9 +120,9 @@ class HomeScreenController: Clock.schedule_once(lambda _: self.trending_anime(), 1) Clock.schedule_once(lambda _: self.highest_scored_anime(), 2) Clock.schedule_once(lambda _: self.popular_anime(), 3) - Clock.schedule_once(lambda _: self.favourite_anime(), 4) - Clock.schedule_once(lambda _: self.recently_updated_anime(), 5) - Clock.schedule_once(lambda _: self.upcoming_anime(), 6) + # Clock.schedule_once(lambda _: self.favourite_anime(), 4) + # Clock.schedule_once(lambda _: self.recently_updated_anime(), 5) + # Clock.schedule_once(lambda _: self.upcoming_anime(), 6) if self.populate_errors: show_notification( diff --git a/fastanime/Controller/my_list_screen.py b/fastanime/Controller/my_list_screen.py index 2073394..86e640c 100644 --- a/fastanime/Controller/my_list_screen.py +++ b/fastanime/Controller/my_list_screen.py @@ -21,8 +21,8 @@ class MyListScreenController: def __init__(self, model: MyListScreenModel): self.model = model self.view = MyListScreenView(controller=self, model=self.model) - if len(self.requested_update_my_list_screen()) > 30: - self.requested_update_my_list_screen(2) + # if len(self.requested_update_my_list_screen()) > 30: + # self.requested_update_my_list_screen(2) def get_view(self) -> MyListScreenView: return self.view diff --git a/fastanime/Model/anime_screen.py b/fastanime/Model/anime_screen.py index f03a69b..ab94659 100644 --- a/fastanime/Model/anime_screen.py +++ b/fastanime/Model/anime_screen.py @@ -1,5 +1,30 @@ from ..libs.anilist import AniList from .base_model import BaseScreenModel +from ..libs.anime_provider.allanime_api import anime_provider +from kivy.cache import Cache +from fuzzywuzzy import fuzz + + +def anime_title_percentage_match( + possible_user_requested_anime_title: str, title: str +) -> int: + """Returns the percentage match between the possible title and user title + + Args: + possible_user_requested_anime_title (str): an Animdl search result title + title (str): the anime title the user wants + + Returns: + int: the percentage match + """ + print(locals()) + + percentage_ratio = fuzz.ratio(title, possible_user_requested_anime_title) + print(percentage_ratio) + return percentage_ratio + + +Cache.register("streams.anime", limit=10) class AnimeScreenModel(BaseScreenModel): @@ -7,6 +32,48 @@ class AnimeScreenModel(BaseScreenModel): data = {} anime_id = 0 + current_anime_data = None + current_anime_id = "0" + current_title = "" + + def get_anime_data_from_provider(self, anime_title: str, id=None): + if self.current_title == anime_title and self.current_anime_data: + return self.current_anime_data + + search_results = anime_provider.search_for_anime(anime_title) + + if search_results: + _search_results = search_results["shows"]["edges"] + result = max( + _search_results, + key=lambda x: anime_title_percentage_match(x["name"], anime_title), + ) + self.current_anime_id = result["_id"] + self.current_anime_data = anime_provider.get_anime(result["_id"]) + self.current_title = anime_title + return self.current_anime_data + + def get_episode_streams(self, episode): + if self.current_anime_data: + episode_streams = anime_provider.get_anime_episode( + self.current_anime_id, episode + ) + streams = anime_provider.get_episode_streams(episode_streams) + + if streams: + _streams = list(streams) + streams = [] + for stream in _streams: + streams.append( + { + f"{stream[0]}": [ + _stream["link"] for _stream in stream[1]["links"] + ] + } + ) + return streams + + # should return {type:{provider:streamlink}} def get_anime_data(self, id: int): return AniList.get_anime(id) diff --git a/fastanime/Utility/media_card_loader.py b/fastanime/Utility/media_card_loader.py index c0cded2..fc21047 100644 --- a/fastanime/Utility/media_card_loader.py +++ b/fastanime/Utility/media_card_loader.py @@ -19,10 +19,10 @@ class MediaCardDataLoader(object): media_card_data["anime_id"] = anime_id = anime_item["id"] # TODO: ADD language preference - if anime_item["title"].get("english"): - media_card_data["title"] = anime_item["title"]["english"] - else: + if anime_item["title"].get("romaji"): media_card_data["title"] = anime_item["title"]["romaji"] + else: + media_card_data["title"] = anime_item["title"]["english"] media_card_data["cover_image_url"] = anime_item["coverImage"]["medium"] diff --git a/fastanime/View/AnimeScreen/anime_screen.kv b/fastanime/View/AnimeScreen/anime_screen.kv index 416e3ea..90601bc 100644 --- a/fastanime/View/AnimeScreen/anime_screen.kv +++ b/fastanime/View/AnimeScreen/anime_screen.kv @@ -1,61 +1,54 @@ +: + adaptive_height:True + orientation:'vertical' + +: + adaptive_height:True + bold:True + : md_bg_color: self.theme_cls.backgroundColor - header:header - side_bar:side_bar - rankings_bar:rankings_bar - anime_description:anime_description - anime_characters:anime_characters - anime_reviews:anime_reviews MDBoxLayout: orientation: 'vertical' MDBoxLayout: - orientation: 'vertical' - size_hint_y:None - height: self.minimum_height - MDBoxLayout: - adaptive_height:True - MDIconButton: - icon: "arrow-left" - on_release: - root.manager_screens.current = root.caller_screen_name - MDScrollView: - size_hint:1,1 - MDBoxLayout: - id:main_container - size_hint_y:None - padding:"10dp" - spacing:"10dp" - height: self.minimum_height - orientation:"vertical" - AnimeHeader: - id:header - MDBoxLayout: - size_hint_y:None - height: self.minimum_height - AnimeSideBar: - id:side_bar - screen:root - size_hint_y:None - height:max(self.parent.height,self.minimum_height) + adaptive_height:True + MDIconButton: + icon:"arrow-left" + on_press:root.manager_screens.current = root.caller_screen_name + MDTextField: + on_text_validate: + root.update_current_link(self) + + VideoPlayer: + source:root.current_link + AnimeBoxLayout: + AnimeLabel: + text:"Sub" + MDSegmentedButton: + id:pl + multiselect:False + MDSegmentedButtonItem: + on_active: + pl.selected_segments = [self] + root.update_current_video_stream("gogoanime") + MDSegmentButtonLabel: + text:"GoGoAnime" + MDSegmentedButtonItem: + on_active: + root.update_current_video_stream("dropbox") + pl.selected_segments = [self] + MDSegmentButtonLabel: + text:"DropBox" + MDSegmentedButtonItem: + on_active: + root.update_current_video_stream("sharepoint") + pl.selected_segments = [self] + MDSegmentButtonLabel: + text:"Share Point" + MDSegmentedButtonItem: + on_active: + root.update_current_video_stream("wetransfer") + pl.selected_segments = [self] + MDSegmentButtonLabel: + text:"weTransfer" - MDBoxLayout: - spacing:"10dp" - orientation:"vertical" - size_hint_y:None - height: max(self.parent.height,self.minimum_height) - RankingsBar: - id:rankings_bar - Controls: - screen:root - cols:3 if root.width < 1100 else 5 - MDBoxLayout: - adaptive_height:True - padding:"20dp" - orientation:"vertical" - AnimeDescription: - id:anime_description - AnimeCharacters: - id:anime_characters - AnimeReviews: - id:anime_reviews - BoxLayout: diff --git a/fastanime/View/AnimeScreen/anime_screen.py b/fastanime/View/AnimeScreen/anime_screen.py index 37ee5bf..f96a9a1 100644 --- a/fastanime/View/AnimeScreen/anime_screen.py +++ b/fastanime/View/AnimeScreen/anime_screen.py @@ -1,134 +1,33 @@ -from kivy.properties import DictProperty, ObjectProperty, StringProperty +from kivy.properties import ListProperty, ObjectProperty, StringProperty from ...libs.anilist import AnilistBaseMediaDataSchema -from ...Utility import anilist_data_helper from ...View.base_screen import BaseScreenView -from .components import ( - AnimdlStreamDialog, - AnimeCharacters, - AnimeDescription, - AnimeHeader, - AnimeReviews, - AnimeSideBar, - DownloadAnimeDialog, - RankingsBar, -) class AnimeScreenView(BaseScreenView): """The anime screen view""" - caller_screen_name = StringProperty() - header: AnimeHeader = ObjectProperty() - side_bar: AnimeSideBar = ObjectProperty() - rankings_bar: RankingsBar = ObjectProperty() - anime_description: AnimeDescription = ObjectProperty() - anime_characters: AnimeCharacters = ObjectProperty() - anime_reviews: AnimeReviews = ObjectProperty() - data = DictProperty() - anime_id = 0 + current_link = StringProperty( + "https://uc951f724c20bbec8df447bac605.dl.dropboxusercontent.com/cd/0/get/CUdx6k2qw-zqY86ftfFHqkmPqGuVrfjpE68B_EkcvZXcZLnjim_ZTHd-qNVb_mEbos9UsuhY8FJGdgf86RUZ-IJqZtz3tt8_CUVTloQAeZ47HtNiKjQ0ESvYdLuwqDjqwK2rNfsfiZI2cXBaKiUyJtljEeRL8whSff2wA9Z4tX1cow/file" + ) + current_links = ListProperty([]) + current_anime_data = ObjectProperty() + caller_screen_name = ObjectProperty() + current_title = StringProperty() def update_layout(self, data: AnilistBaseMediaDataSchema, caller_screen_name: str): - self.caller_screen_name = caller_screen_name - self.data = data - # uitlity functions + return - # variables - english_title = data["title"]["english"] - jp_title = data["title"]["romaji"] - studios = data["studios"]["nodes"] + def update_current_video_stream(self, server, is_dub=False): + for link in self.current_links: + if stream_link := link.get(server): + print(link) + self.current_link = stream_link[0] + break + # print(link) - # update header - self.header.titles = f"{english_title}\n{jp_title}" - if banner_image := data["bannerImage"]: - self.header.banner_image = banner_image - - # -----side bar----- - - # update image - self.side_bar.image = data["coverImage"]["extraLarge"] - - # update alternative titles - alternative_titles = { - "synonyms": anilist_data_helper.format_list_data_with_comma( - data["synonyms"] - ), # list - "japanese": jp_title, - "english": english_title, - } - self.side_bar.alternative_titles = alternative_titles - - # update information - information = { - "episodes": data["episodes"], - "status": data["status"], - "nextAiringEpisode": anilist_data_helper.extract_next_airing_episode( - data["nextAiringEpisode"] - ), - "aired": f"{anilist_data_helper.format_anilist_date_object(data['startDate'])} to {anilist_data_helper.format_anilist_date_object(data['endDate'])}", - "premiered": f"{data['season']} {data['seasonYear']}", - "broadcast": data["format"], - "countryOfOrigin": data["countryOfOrigin"], - "hashtag": data["hashtag"], - "studios": anilist_data_helper.format_list_data_with_comma( - [studio["name"] for studio in studios if studio["isAnimationStudio"]] - ), # { "name": "Sunrise", "isAnimationStudio": true } - "producers": anilist_data_helper.format_list_data_with_comma( - [ - studio["name"] - for studio in studios - if not studio["isAnimationStudio"] - ] - ), - "source": data["source"], - "genres": anilist_data_helper.format_list_data_with_comma(data["genres"]), - "duration": data["duration"], - } - self.side_bar.information = information - - # update statistics - statistics = [*[(stat["context"], stat["rank"]) for stat in data["rankings"]]] - self.side_bar.statistics = statistics - - # update tags - self.side_bar.tags = [(tag["name"], tag["rank"]) for tag in data["tags"]] - - # update external links - - external_links = [ - ("AniList", data["siteUrl"]), - *[(site["site"], site["url"]) for site in data["externalLinks"]], - ] - self.side_bar.external_links = external_links - - self.rankings_bar.rankings = { - "Popularity": data["popularity"], - "Favourites": data["favourites"], - "AverageScore": data["averageScore"] if data["averageScore"] else 0, - } - - self.anime_description.description = data["description"] - - self.anime_characters.characters = [ - (character["node"], character["voiceActors"]) - for character in data["characters"]["edges"] - ] # list (character,actor) - - self.anime_reviews.reviews = data["reviews"]["nodes"] - - def stream_anime_with_custom_cmds_dialog(self, mpv=False): - """ - Called when user wants to stream with custom commands - """ - - AnimdlStreamDialog(self.data, mpv).open() - - def open_download_anime_dialog(self): - """ - Opens the download anime dialog - """ - - DownloadAnimeDialog(self.data).open() + def update_current_link(self, field): + self.controller.fetch_streams(self.current_title, field.text) def add_to_user_anime_list(self, *args): self.app.add_anime_to_user_anime_list(self.model.anime_id) diff --git a/fastanime/View/AnimeScreen/components/__init__.py b/fastanime/View/AnimeScreen/components/__init__.py deleted file mode 100644 index 5d4ac98..0000000 --- a/fastanime/View/AnimeScreen/components/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -from .animdl_stream_dialog import AnimdlStreamDialog -from .characters import AnimeCharacters -from .controls import Controls -from .description import AnimeDescription -from .download_anime_dialog import DownloadAnimeDialog -from .header import AnimeHeader -from .rankings_bar import RankingsBar -from .review import AnimeReviews -from .side_bar import AnimeSideBar diff --git a/fastanime/View/AnimeScreen/components/animdl_download_dialog.kv b/fastanime/View/AnimeScreen/components/animdl_download_dialog.kv deleted file mode 100644 index e69de29..0000000 diff --git a/fastanime/View/AnimeScreen/components/animdl_stream_dialog.kv b/fastanime/View/AnimeScreen/components/animdl_stream_dialog.kv deleted file mode 100644 index 1828089..0000000 --- a/fastanime/View/AnimeScreen/components/animdl_stream_dialog.kv +++ /dev/null @@ -1,63 +0,0 @@ -: - adaptive_height:True - max_lines:0 - shorten:False - markup:True - font_style: "Label" - role: "medium" - bold:True -: - adaptive_height:True - halign:"center" - max_lines:0 - shorten:False - bold:True - markup:True - font_style: "Title" - role: "medium" - md_bg_color:self.theme_cls.secondaryContainerColor - padding:"10dp" - - - - - md_bg_color:self.theme_cls.backgroundColor - radius:8 - size_hint:None,None - height:"500dp" - width:"400dp" - MDBoxLayout: - spacing: '10dp' - padding:"10dp" - orientation:"vertical" - StreamDialogHeaderLabel: - text:"Stream Anime" - StreamDialogLabel: - text:"Title" - MDTextField: - id:title_field - required:True - StreamDialogLabel: - text:"Range" - MDTextField: - id:range_field - required:True - StreamDialogLabel: - text:"Latest" - MDTextField: - id:latest_field - required:True - StreamDialogLabel: - text:"Quality" - MDTextField: - id:quality_field - required:True - MDBoxLayout: - orientation:"vertical" - MDButton: - pos_hint: {'center_x': 0.5} - on_press:root.stream_anime(app) - MDButtonIcon: - icon:"rss" - MDButtonText: - text:"Stream" \ No newline at end of file diff --git a/fastanime/View/AnimeScreen/components/animdl_stream_dialog.py b/fastanime/View/AnimeScreen/components/animdl_stream_dialog.py deleted file mode 100644 index 51b420a..0000000 --- a/fastanime/View/AnimeScreen/components/animdl_stream_dialog.py +++ /dev/null @@ -1,69 +0,0 @@ -from kivy.clock import Clock -from kivy.uix.modalview import ModalView -from kivymd.theming import ThemableBehavior -from kivymd.uix.behaviors import ( - BackgroundColorBehavior, - CommonElevationBehavior, - StencilBehavior, -) - - -class AnimdlStreamDialog( - ThemableBehavior, - StencilBehavior, - CommonElevationBehavior, - BackgroundColorBehavior, - ModalView, -): - """The anime streaming dialog""" - - def __init__(self, data, mpv, **kwargs): - super().__init__(**kwargs) - self.data = data - self.mpv = mpv - if title := data["title"].get("romaji"): - self.ids.title_field.text = title - elif title := data["title"].get("english"): - self.ids.title_field.text = title - - self.ids.quality_field.text = "best" - - def _stream_anime(self, app): - if self.mpv: - streaming_cmds = {} - title = self.ids.title_field.text - streaming_cmds["title"] = title - - episodes_range = self.ids.range_field.text - if episodes_range: - streaming_cmds["episodes_range"] = episodes_range - - quality = self.ids.quality_field.text - if quality: - streaming_cmds["quality"] = quality - else: - streaming_cmds["quality"] = "best" - - app.watch_on_animdl(streaming_cmds) - else: - cmds = [] - title = self.ids.title_field.text - cmds.append(title) - - episodes_range = self.ids.range_field.text - if episodes_range: - cmds = [*cmds, "-r", episodes_range] - - latest = self.ids.latest_field.text - if latest: - cmds = [*cmds, "-s", latest] - - quality = self.ids.quality_field.text - if quality: - cmds = [*cmds, "-q", quality] - - app.watch_on_animdl(custom_options=cmds) - self.dismiss() - - def stream_anime(self, app): - Clock.schedule_once(lambda _: self._stream_anime(app)) diff --git a/fastanime/View/AnimeScreen/components/characters.kv b/fastanime/View/AnimeScreen/components/characters.kv deleted file mode 100644 index a2e3b67..0000000 --- a/fastanime/View/AnimeScreen/components/characters.kv +++ /dev/null @@ -1,71 +0,0 @@ -#:import get_hex_from_color kivy.utils.get_hex_from_color - -: - adaptive_height:True - md_bg_color:self.theme_cls.surfaceContainerLowColor - padding:"10dp" - orientation:"vertical" - -: - adaptive_height:True - max_lines:0 - shorten:False - markup:True - font_style: "Body" - role: "small" - -: - adaptive_height:True - spacing:"10dp" - - radius:50 - size_hint:None,None - height:"50dp" - width:"50dp" - -: - adaptive_height:True - orientation:"vertical" -: - spacing:"5dp" - adaptive_height:True - orientation:"vertical" - CharacterHeader: - padding:"10dp" - CharacterAvatar: - source:root.character["image"] - CharacterText: - text: root.character["name"] - pos_hint:{"center_y":.5} - - CharacterSecondaryContainer: - spacing:"5dp" - MDDivider: - CharacterText: - text: "Details" - MDDivider: - CharacterText: - text:"[color={}]Gender:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.character["gender"]) - CharacterText: - text:"[color={}]Date Of Birth:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.character["dateOfBirth"]) - CharacterText: - text:"[color={}]Age:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.character["age"]) - CharacterText: - text:"[color={}]Description:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.character["description"]) - max_lines:5 - CharacterText: - text:"[color={}]Voice Actors:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.voice_actors["name"]) - MDDivider: - - -: - adaptive_height:True - container:container - orientation:"vertical" - HeaderLabel: - text:"Characters" - halign:"left" - CharactersContainer: - id:container - - diff --git a/fastanime/View/AnimeScreen/components/characters.py b/fastanime/View/AnimeScreen/components/characters.py deleted file mode 100644 index 8a6ba05..0000000 --- a/fastanime/View/AnimeScreen/components/characters.py +++ /dev/null @@ -1,53 +0,0 @@ -from kivy.clock import Clock -from kivy.properties import ListProperty, ObjectProperty -from kivymd.uix.boxlayout import MDBoxLayout - -from ....Utility.anilist_data_helper import format_anilist_date_object - - -class AnimeCharacter(MDBoxLayout): - """an Anime character data""" - - voice_actors = ObjectProperty({"name": "", "image": ""}) - character = ObjectProperty( - { - "name": "", - "gender": "", - "dateOfBirth": "", - "image": "", - "age": "", - "description": "", - } - ) - - -class AnimeCharacters(MDBoxLayout): - """The anime characters card""" - - container = ObjectProperty() - characters = ListProperty() - - def update_characters_card(self, instance, characters): - self.container.clear_widgets() - for character_ in characters: # character (character,actor) - character = character_[0] - actors = character_[1] - - anime_character = AnimeCharacter() - anime_character.character = { - "name": character["name"]["full"], - "gender": character["gender"], - "dateOfBirth": format_anilist_date_object(character["dateOfBirth"]), - "image": character["image"]["medium"], - "age": character["age"], - "description": character["description"], - } - anime_character.voice_actors = { - "name": ", ".join([actor["name"]["full"] for actor in actors]) - } - - # anime_character.voice_actor = - self.container.add_widget(anime_character) - - def on_characters(self, *args): - Clock.schedule_once(lambda _: self.update_characters_card(*args)) diff --git a/fastanime/View/AnimeScreen/components/controls.kv b/fastanime/View/AnimeScreen/components/controls.kv deleted file mode 100644 index 3698d4a..0000000 --- a/fastanime/View/AnimeScreen/components/controls.kv +++ /dev/null @@ -1,32 +0,0 @@ - - adaptive_height:True - padding:"10dp" - spacing:"10dp" - pos_hint: {'center_x': 0.5} - cols:3 - MDButton: - on_press: - root.screen.add_to_user_anime_list() - add_to_user_list_label.text = "Added to MyAnimeList" - MDButtonText: - id:add_to_user_list_label - text:"Add to MyAnimeList" - MDButton: - on_press: - if root.screen:root.screen.stream_anime_with_custom_cmds_dialog() - MDButtonText: - text:"Watch on Animdl" - MDButton: - on_press: - if root.screen:root.screen.stream_anime_with_custom_cmds_dialog(mpv=True) - MDButtonText: - text:"Watch on mpv" - MDButton: - on_press: app.watch_on_allanime(root.screen.data["title"]["romaji"]) if root.screen.data["title"]["romaji"] else app.watch_on_allanime(root.screen.data["title"]["english"]) - MDButtonText: - text:"Watch on AllAnime" - MDButton: - on_press: - if root.screen:root.screen.open_download_anime_dialog() - MDButtonText: - text:"Download Anime" diff --git a/fastanime/View/AnimeScreen/components/controls.py b/fastanime/View/AnimeScreen/components/controls.py deleted file mode 100644 index 1768904..0000000 --- a/fastanime/View/AnimeScreen/components/controls.py +++ /dev/null @@ -1,8 +0,0 @@ -from kivy.properties import ObjectProperty -from kivymd.uix.gridlayout import MDGridLayout - - -class Controls(MDGridLayout): - """The diferent controls available""" - - screen = ObjectProperty() diff --git a/fastanime/View/AnimeScreen/components/description.kv b/fastanime/View/AnimeScreen/components/description.kv deleted file mode 100644 index a4f5b02..0000000 --- a/fastanime/View/AnimeScreen/components/description.kv +++ /dev/null @@ -1,23 +0,0 @@ -: - adaptive_height:True - md_bg_color:self.theme_cls.surfaceContainerLowColor - padding:"10dp" - -: - adaptive_height:True - max_lines:0 - shorten:False - markup:True - font_style: "Body" - role: "small" -: - orientation:"vertical" - adaptive_height:True - HeaderLabel: - halign:"left" - text:"Description" - DescriptionContainer: - DescriptionText: - text:root.description - - \ No newline at end of file diff --git a/fastanime/View/AnimeScreen/components/description.py b/fastanime/View/AnimeScreen/components/description.py deleted file mode 100644 index a726172..0000000 --- a/fastanime/View/AnimeScreen/components/description.py +++ /dev/null @@ -1,8 +0,0 @@ -from kivy.properties import StringProperty -from kivymd.uix.boxlayout import MDBoxLayout - - -class AnimeDescription(MDBoxLayout): - """The anime description""" - - description = StringProperty() diff --git a/fastanime/View/AnimeScreen/components/download_anime_dialog.kv b/fastanime/View/AnimeScreen/components/download_anime_dialog.kv deleted file mode 100644 index 73b9df5..0000000 --- a/fastanime/View/AnimeScreen/components/download_anime_dialog.kv +++ /dev/null @@ -1,58 +0,0 @@ -: - adaptive_height:True - max_lines:0 - shorten:False - markup:True - font_style: "Label" - role: "medium" - bold:True -: - adaptive_height:True - halign:"center" - max_lines:0 - shorten:False - bold:True - markup:True - font_style: "Title" - role: "medium" - md_bg_color:self.theme_cls.secondaryContainerColor - padding:"10dp" - - - - - md_bg_color:self.theme_cls.backgroundColor - radius:8 - size_hint:None,None - height:"500dp" - width:"400dp" - MDBoxLayout: - spacing: '10dp' - padding:"10dp" - orientation:"vertical" - DownloadDialogHeaderLabel: - text:"Download Anime" - DownloadDialogLabel: - text:"Title" - MDTextField: - id:title_field - required:True - DownloadDialogLabel: - text:"Range" - MDTextField: - id:range_field - required:True - DownloadDialogLabel: - text:"Quality" - MDTextField: - id:quality_field - required:True - MDBoxLayout: - orientation:"vertical" - MDButton: - pos_hint: {'center_x': 0.5} - on_press:root.download_anime(app) - MDButtonIcon: - icon:"download" - MDButtonText: - text:"Download" \ No newline at end of file diff --git a/fastanime/View/AnimeScreen/components/download_anime_dialog.py b/fastanime/View/AnimeScreen/components/download_anime_dialog.py deleted file mode 100644 index 2414318..0000000 --- a/fastanime/View/AnimeScreen/components/download_anime_dialog.py +++ /dev/null @@ -1,41 +0,0 @@ -from kivy.uix.modalview import ModalView -from kivymd.theming import ThemableBehavior -from kivymd.uix.behaviors import ( - BackgroundColorBehavior, - CommonElevationBehavior, - StencilBehavior, -) - - -# from main import AniXStreamApp -class DownloadAnimeDialog( - ThemableBehavior, - StencilBehavior, - CommonElevationBehavior, - BackgroundColorBehavior, - ModalView, -): - """The download anime dialog""" - - def __init__(self, data, **kwargs): - super(DownloadAnimeDialog, self).__init__(**kwargs) - self.data = data - self.anime_id = self.data["id"] - if title := data["title"].get("romaji"): - self.ids.title_field.text = title - elif title := data["title"].get("english"): - self.ids.title_field.text = title - self.ids.quality_field.text = "best" - - def download_anime(self, app): - default_cmds = {} - title = self.ids.title_field.text - default_cmds["title"] = title - if episodes_range := self.ids.range_field.text: - default_cmds["episodes_range"] = episodes_range - - if quality := self.ids.range_field.text: - default_cmds["quality"] = quality - - app.download_anime(self.anime_id, default_cmds) - self.dismiss() diff --git a/fastanime/View/AnimeScreen/components/header.kv b/fastanime/View/AnimeScreen/components/header.kv deleted file mode 100644 index e6d0292..0000000 --- a/fastanime/View/AnimeScreen/components/header.kv +++ /dev/null @@ -1,20 +0,0 @@ -: - adaptive_height:True - orientation: 'vertical' - MDBoxLayout: - adaptive_height:True - md_bg_color:self.theme_cls.secondaryContainerColor - MDLabel: - text: root.titles - adaptive_height:True - padding:"5dp" - bold:True - shorten:False - max_lines:2 - font_style:"Label" - role:"large" - FitImage: - size_hint_y: None - height: dp(250) - source: root.banner_image if root.banner_image else app.default_banner_image - \ No newline at end of file diff --git a/fastanime/View/AnimeScreen/components/header.py b/fastanime/View/AnimeScreen/components/header.py deleted file mode 100644 index 9f1c290..0000000 --- a/fastanime/View/AnimeScreen/components/header.py +++ /dev/null @@ -1,7 +0,0 @@ -from kivy.properties import StringProperty -from kivymd.uix.boxlayout import MDBoxLayout - - -class AnimeHeader(MDBoxLayout): - titles = StringProperty() - banner_image = StringProperty() diff --git a/fastanime/View/AnimeScreen/components/rankings_bar.kv b/fastanime/View/AnimeScreen/components/rankings_bar.kv deleted file mode 100644 index b5531ea..0000000 --- a/fastanime/View/AnimeScreen/components/rankings_bar.kv +++ /dev/null @@ -1,81 +0,0 @@ -#:set yellow [.9,.9,0,.9] - -: - max_lines:0 - shorten:False - markup:True - font_style: "Label" - role: "medium" - -: - color:self.theme_cls.primaryColor - bold:True - max_lines:0 - shorten:False - font_style: "Label" - role: "large" - - -: - orientation:"vertical" - -: - orientation:"vertical" - padding:"20dp" -: - size_hint_y:None - height:dp(100) - line_color:self.theme_cls.secondaryColor - padding:"10dp" - RankingsBoxLayout: - size_hint_x:.4 - RankingsHeaderLabel: - text:"Average Score" - MDBoxLayout: - adaptive_width:True - MDBoxLayout: - adaptive_size:True - pos_hint: {'center_y': .5} - MDIcon: - icon: "star" - color:yellow - disabled: not((root.rankings["AverageScore"]/100)*6>=1) - MDIcon: - color:yellow - disabled: not(root.rankings["AverageScore"]/100*6>=2) - icon: "star" - MDIcon: - color:yellow - disabled: not(root.rankings["AverageScore"]/100*6>=3) - icon: "star" - MDIcon: - color:yellow - disabled: not(root.rankings["AverageScore"]/100*6>=4) - icon: "star" - MDIcon: - color:yellow - icon: "star" - disabled: not(root.rankings["AverageScore"]/100*6>=5) - MDIcon: - color:yellow - icon: "star" - disabled: not(root.rankings["AverageScore"]/100*6>=6) - RankingsLabel: - adaptive_width:True - text: '{}'.format(root.rankings["AverageScore"]/10) - RankingsDivider: - RankingsBoxLayout: - size_hint_x:.3 - RankingsHeaderLabel: - text:"Popularity" - RankingsLabel: - text: '{}'.format(root.rankings["Popularity"]) - RankingsDivider: - RankingsBoxLayout: - size_hint_x:.3 - RankingsHeaderLabel: - text:"Favourites" - RankingsLabel: - text: '{}'.format(root.rankings["Favourites"]) - - \ No newline at end of file diff --git a/fastanime/View/AnimeScreen/components/rankings_bar.py b/fastanime/View/AnimeScreen/components/rankings_bar.py deleted file mode 100644 index 630f5ba..0000000 --- a/fastanime/View/AnimeScreen/components/rankings_bar.py +++ /dev/null @@ -1,12 +0,0 @@ -from kivy.properties import DictProperty -from kivymd.uix.boxlayout import MDBoxLayout - - -class RankingsBar(MDBoxLayout): - rankings = DictProperty( - { - "Popularity": 0, - "Favourites": 0, - "AverageScore": 0, - } - ) diff --git a/fastanime/View/AnimeScreen/components/review.kv b/fastanime/View/AnimeScreen/components/review.kv deleted file mode 100644 index 5a9fee7..0000000 --- a/fastanime/View/AnimeScreen/components/review.kv +++ /dev/null @@ -1,50 +0,0 @@ -#:import get_hex_from_color kivy.utils.get_hex_from_color - - -: - adaptive_height:True - md_bg_color:self.theme_cls.surfaceContainerLowColor - padding:"10dp" - orientation:"vertical" - -: - adaptive_height:True - max_lines:0 - shorten:False - markup:True - font_style: "Body" - role: "small" - -: - adaptive_height:True - spacing:"10dp" - padding:"10dp" - - - radius:50 - size_hint:None,None - height:"50dp" - width:"50dp" - - - orientation:"vertical" - adaptive_height:True - ReviewHeader: - ReviewerAvatar: - source:root.review["avatar"] - ReviewText: - pos_hint: {'center_y': 0.5} - text:root.review["username"] - MDDivider: - ReviewText: - text:root.review["summary"] - MDDivider: -: - container:container - adaptive_height:True - orientation:"vertical" - HeaderLabel: - halign:"left" - text:"reviews" - ReviewContainer: - id:container \ No newline at end of file diff --git a/fastanime/View/AnimeScreen/components/review.py b/fastanime/View/AnimeScreen/components/review.py deleted file mode 100644 index aef77ed..0000000 --- a/fastanime/View/AnimeScreen/components/review.py +++ /dev/null @@ -1,28 +0,0 @@ -from kivy.clock import Clock -from kivy.properties import ListProperty, ObjectProperty -from kivymd.uix.boxlayout import MDBoxLayout - - -class AnimeReview(MDBoxLayout): - review = ObjectProperty({"username": "", "avatar": "", "summary": ""}) - - -class AnimeReviews(MDBoxLayout): - """anime reviews""" - - reviews = ListProperty() - container = ObjectProperty() - - def on_reviews(self, *args): - Clock.schedule_once(lambda _: self.update_reviews_card(*args)) - - def update_reviews_card(self, instance, reviews): - self.container.clear_widgets() - for review in reviews: - review_ = AnimeReview() - review_.review = { - "username": review["user"]["name"], - "avatar": review["user"]["avatar"]["medium"], - "summary": review["summary"], - } - self.container.add_widget(review_) diff --git a/fastanime/View/AnimeScreen/components/side_bar.kv b/fastanime/View/AnimeScreen/components/side_bar.kv deleted file mode 100644 index d9c008a..0000000 --- a/fastanime/View/AnimeScreen/components/side_bar.kv +++ /dev/null @@ -1,102 +0,0 @@ -#:import get_hex_from_color kivy.utils.get_hex_from_color - -: - size_hint_y:None - height:self.minimum_height - padding:"10dp" - spacing:"10dp" - orientation: 'vertical' - pos_hint: {'center_x': 0.5} -: - adaptive_height:True - max_lines:0 - shorten:False - markup:True - font_style: "Label" - role: "medium" -: - adaptive_height:True - md_bg_color:self.theme_cls.secondaryContainerColor - MDLabel: - text:root.text - adaptive_height:True - halign:root.halign - max_lines:0 - shorten:False - bold:True - font_style: "Label" - role: "large" - padding:"10dp" - -: - size_hint_x: None - width: dp(300) - orientation: 'vertical' - line_color:self.theme_cls.secondaryColor - statistics_container:statistics_container - tags_container:tags_container - external_links_container:external_links_container - FitBoxLayout: - FitImage: - source:root.image - size_hint:None,None - height:dp(250) - width:dp(200) - pos_hint: {'center_x': 0.5} - MDButton: - pos_hint: {'center_x': 0.5} - on_press: - if root.screen:root.screen.stream_anime_with_custom_cmds_dialog(mpv=True) - MDButtonText: - text:"Watch with mpv" - FitBoxLayout: - HeaderLabel: - text:"Alternative Titles" - SideBarLabel: - text: "[color={}]Synonyms:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.alternative_titles["synonyms"]) - SideBarLabel: - text: "[color={}]English:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.alternative_titles["english"]) - SideBarLabel: - text: "[color={}]Japanese:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.alternative_titles["japanese"]) - FitBoxLayout: - HeaderLabel: - text:"Information" - SideBarLabel: - text: "[color={}]Episodes:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["episodes"]) - SideBarLabel: - text: "[color={}]Status:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["status"]) - SideBarLabel: - text: "[color={}]Next Airing Episode:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["nextAiringEpisode"]) - SideBarLabel: - text: "[color={}]Aired:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["aired"]) - SideBarLabel: - text: "[color={}]Premiered:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["premiered"]) - SideBarLabel: - text: "[color={}]Broadcast:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["broadcast"]) - SideBarLabel: - text: "[color={}]Country Of Origin:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["countryOfOrigin"]) - SideBarLabel: - text: "[color={}]Hashtag:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["hashtag"]) - SideBarLabel: - text: "[color={}]Studios:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["studios"]) - SideBarLabel: - text: "[color={}]Producers:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["producers"]) - SideBarLabel: - text: "[color={}]Source:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["source"]) - SideBarLabel: - text: "[color={}]Genres:[/color] {}".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["genres"]) - SideBarLabel: - text: "[color={}]Duration:[/color] {} minutes".format(get_hex_from_color(self.theme_cls.primaryColor),root.information["duration"]) - FitBoxLayout: - id:statistics_container - HeaderLabel: - text:"Rankings" - FitBoxLayout: - id:tags_container - HeaderLabel: - text:"Tags" - FitBoxLayout: - id:external_links_container - HeaderLabel: - text:"External Links" - BoxLayout: \ No newline at end of file diff --git a/fastanime/View/AnimeScreen/components/side_bar.py b/fastanime/View/AnimeScreen/components/side_bar.py deleted file mode 100644 index e733182..0000000 --- a/fastanime/View/AnimeScreen/components/side_bar.py +++ /dev/null @@ -1,97 +0,0 @@ -from kivy.factory import Factory -from kivy.properties import DictProperty, ListProperty, ObjectProperty, StringProperty -from kivy.utils import get_hex_from_color -from kivymd.uix.boxlayout import MDBoxLayout -from kivymd.uix.label import MDLabel - - -class HeaderLabel(MDBoxLayout): - text = StringProperty() - halign = StringProperty("center") - - -Factory.register("HeaderLabel", HeaderLabel) - - -class SideBarLabel(MDLabel): - pass - - -# TODO:Switch to using the kivy_markup_module -class AnimeSideBar(MDBoxLayout): - screen = ObjectProperty() - image = StringProperty() - alternative_titles = DictProperty( - { - "synonyms": "", - "english": "", - "japanese": "", - } - ) - information = DictProperty( - { - "episodes": "", - "status": "", - "aired": "", - "nextAiringEpisode": "", - "premiered": "", - "broadcast": "", - "countryOfOrigin": "", - "hashtag": "", - "studios": "", # { "name": "Sunrise", "isAnimationStudio": true } - "source": "", - "genres": "", - "duration": "", - "producers": "", - } - ) - statistics = ListProperty() - statistics_container = ObjectProperty() - external_links = ListProperty() - external_links_container = ObjectProperty() - tags = ListProperty() - tags_container = ObjectProperty() - - def on_statistics(self, instance, value): - self.statistics_container.clear_widgets() - header = HeaderLabel() - header.text = "Rankings" - self.statistics_container.add_widget(header) - for stat in value: - # stat (rank,context) - label = SideBarLabel() - label.text = "[color={}]{}:[/color] {}".format( - get_hex_from_color(label.theme_cls.primaryColor), - stat[0].capitalize(), - f"{stat[1]}", - ) - self.statistics_container.add_widget(label) - - def on_tags(self, instance, value): - self.tags_container.clear_widgets() - header = HeaderLabel() - header.text = "Tags" - self.tags_container.add_widget(header) - for tag in value: - label = SideBarLabel() - label.text = "[color={}]{}:[/color] {}".format( - get_hex_from_color(label.theme_cls.primaryColor), - tag[0].capitalize(), - f"{tag[1]} %", - ) - self.tags_container.add_widget(label) - - def on_external_links(self, instance, value): - self.external_links_container.clear_widgets() - header = HeaderLabel() - header.text = "External Links" - self.external_links_container.add_widget(header) - for site in value: - # stat (rank,context) - label = SideBarLabel() - label.text = "[color={}]{}:[/color] {}".format( - get_hex_from_color(label.theme_cls.primaryColor), - site[0].capitalize(), - site[1], - ) - self.external_links_container.add_widget(label) diff --git a/fastanime/View/base_screen.py b/fastanime/View/base_screen.py index 117cc4c..16398bf 100644 --- a/fastanime/View/base_screen.py +++ b/fastanime/View/base_screen.py @@ -30,6 +30,11 @@ class CommonNavigationRailItem(MDNavigationRailItem): text = StringProperty() +class HeaderLabel(MDBoxLayout): + text = StringProperty() + halign = StringProperty("left") + + class BaseScreenView(MDScreen, Observer): """ A base class that implements a visual representation of the model data. diff --git a/fastanime/View/components/general.kv b/fastanime/View/components/general.kv index 31019bc..ad75330 100644 --- a/fastanime/View/components/general.kv +++ b/fastanime/View/components/general.kv @@ -1,3 +1,19 @@ : allow_copy:True - allow_selection:True \ No newline at end of file + allow_selection:True + +: + adaptive_height:True + md_bg_color:self.theme_cls.secondaryContainerColor + MDLabel: + text:root.text + adaptive_height:True + halign:root.halign + max_lines:0 + shorten:False + bold:True + font_style: "Label" + role: "large" + padding:"10dp" + + diff --git a/fastanime/View/components/media_card/components/media_popup.kv b/fastanime/View/components/media_card/components/media_popup.kv index 3ca4b8f..a564ad1 100644 --- a/fastanime/View/components/media_card/components/media_popup.kv +++ b/fastanime/View/components/media_card/components/media_popup.kv @@ -107,7 +107,7 @@ icon: "play-circle" on_press: root.dismiss() - app.show_anime_screen(root.caller.anime_id,root.caller.screen.name) + app.show_anime_screen(root.caller.anime_id,root.caller.title,root.caller.screen.name) TooltipMDIconButton: tooltip_text:"Add to your anime list" icon: "plus-circle" if not(root.caller.is_in_my_list) else "check-circle" diff --git a/fastanime/__main__.py b/fastanime/__main__.py index 59b8227..71526a7 100644 --- a/fastanime/__main__.py +++ b/fastanime/__main__.py @@ -244,9 +244,9 @@ class AniXStreamApp(MDApp): updated_list.append(id) user_data_helper.get_user_downloads() - def show_anime_screen(self, id: int, caller_screen_name: str): + def show_anime_screen(self, id: int, title, caller_screen_name: str): self.manager_screens.current = "anime screen" - self.anime_screen.controller.update_anime_view(id, caller_screen_name) + self.anime_screen.controller.update_anime_view(id, title, caller_screen_name) def download_anime_complete( self, successful_downloads: list, failed_downloads: list, anime_title: str diff --git a/fastanime/libs/anime_provider/allanime_api.py b/fastanime/libs/anime_provider/allanime_api.py index 0293260..5cd4a39 100644 --- a/fastanime/libs/anime_provider/allanime_api.py +++ b/fastanime/libs/anime_provider/allanime_api.py @@ -196,15 +196,15 @@ class AllAnimeAPI: if resp.status_code == 200: match embed["sourceName"]: case "Luf-mp4": - return "gogoanime", resp.json() + yield "gogoanime", resp.json() case "Kir": - return "wetransfer", resp.json() + yield "wetransfer", resp.json() case "S-mp4": - return "sharepoint", resp.json() + yield "sharepoint", resp.json() case "Sak": - return "dropbox", resp.json() + yield "dropbox", resp.json() case _: - return "Unknown", resp.json() + yield "Unknown", resp.json() else: return None @@ -247,6 +247,7 @@ if __name__ == "__main__": search_results = anime_provider.search_for_anime( anime, translation_type=translation.strip() ) + print(search_results) if not search_results: raise Exception("No results found") @@ -259,7 +260,7 @@ if __name__ == "__main__": anime_result = list(filter(lambda x: x["name"] == anime, search_results))[0] anime_data = anime_provider.get_anime(anime_result["_id"]) - + print(anime_data) if anime_data is None: raise Exception("Anime not found") availableEpisodesDetail = anime_data["show"]["availableEpisodesDetail"] @@ -279,11 +280,15 @@ if __name__ == "__main__": raise Exception("Episode not found") episode_streams = anime_provider.get_episode_streams(episode_data) + if not episode_streams: raise Exception("No streams found") - stream_links = [stream["link"] for stream in episode_streams[1]["links"]] - stream_link = run_fzf([*stream_links, "quit"]) + episode_streams = list(episode_streams) + print(episode_streams) + stream_links = [stream["link"] for stream in episode_streams[2][1]["links"]] + stream_link = run_fzf([*stream_links, "quit"]) + print(stream_link) if stream_link == "quit": print("Have a nice day") sys.exit()