feat:create cli subpackage

This commit is contained in:
Benex254
2024-08-05 09:47:00 +03:00
parent fe33633d15
commit 1bbca16e60
77 changed files with 161 additions and 212 deletions
+23 -166
View File
@@ -1,191 +1,48 @@
import os
import random
import sys
from rich import print
from rich.traceback import install
import plyer
from kivy.config import Config
from kivy.loader import Loader
from kivy.logger import Logger
from kivy.resources import resource_add_path, resource_find
from kivy.storage.jsonstore import JsonStore
from kivy.uix.screenmanager import FadeTransition, ScreenManager
from kivy.uix.settings import Settings, SettingsWithSidebar
from kivymd.app import MDApp
from .libs.mpv.player import mpv_player
from .Utility import (
themes_available,
)
from .Utility.show_notification import show_notification
from .View.components.media_card.components.media_popup import MediaPopup
from .View.screens import screens
install()
os.environ["KIVY_VIDEO"] = "ffpyplayer" # noqa: E402
# TODO:confirm data integrity
Config.set("graphics", "width", "1000") # noqa: E402
Config.set("graphics", "minimum_width", "1000") # noqa: E402
Config.set("kivy", "window_icon", resource_find("logo.ico")) # noqa: E402
Config.write() # noqa: E402
Loader.num_workers = 5
Loader.max_upload_per_frame = 10
# print(plyer.storagepath.get_application_dir(), plyer.storagepath.get_home_dir())
# ----- some useful paths -----
app_dir = os.path.abspath(os.path.dirname(__file__))
data_folder = os.path.join(app_dir, "data")
configs_folder = os.path.join(app_dir, "configs")
if not os.path.exists(data_folder):
os.mkdir(data_folder)
if vid_path := plyer.storagepath.get_videos_dir(): # type: ignore
downloads_dir = os.path.join(vid_path, "FastAnime")
if not os.path.exists(downloads_dir):
os.mkdir(downloads_dir)
else:
# fallback
downloads_dir = os.path.join(app_dir, "videos")
if not os.path.exists(downloads_dir):
os.mkdir(downloads_dir)
# TODO:confirm data integrity
if os.path.exists(os.path.join(data_folder, "user_data.json")):
user_data = JsonStore(os.path.join(data_folder, "user_data.json"))
else:
user_data_path = os.path.join(data_folder, "user_data.json")
user_data = JsonStore(user_data_path)
user_data_path = os.path.join(data_folder, "user_data.json")
assets_folder = os.path.join(app_dir, "assets")
resource_add_path(assets_folder)
conigs_folder = os.path.join(app_dir, "configs")
resource_add_path(conigs_folder)
from .Utility import user_data_helper
def FastAnime(gui=False):
if "--gui" in sys.argv:
gui = True
sys.argv.remove("--gui")
print(f"Hello {os.environ.get("USERNAME")} from the fastanime team")
if gui:
print(__name__)
from .gui.gui import run_gui
print("Run GUI")
run_gui()
else:
from .cli import run_cli
from .Utility.downloader.downloader import downloader
class FastAnime(MDApp):
# Ensure the user data fields exist
if not (user_data.exists("user_anime_list")):
user_data_helper.update_user_anime_list([])
def __init__(self, **kwargs):
self.default_banner_image = resource_find(
random.choice(["banner_1.jpg", "banner.jpg"])
)
self.default_anime_image = resource_find(
random.choice(["default_1.jpg", "default.jpg"])
)
super().__init__(**kwargs)
self.icon = resource_find("logo.png")
self.load_all_kv_files(self.directory)
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Lightcoral"
self.manager_screens = ScreenManager()
self.manager_screens.transition = FadeTransition()
def build(self) -> ScreenManager:
self.settings_cls = SettingsWithSidebar
self.generate_application_screens()
if config := self.config:
if theme_color := config.get("Preferences", "theme_color"):
self.theme_cls.primary_palette = theme_color
if theme_style := config.get("Preferences", "theme_style"):
self.theme_cls.theme_style = theme_style
self.anime_screen = self.manager_screens.get_screen("anime screen")
self.search_screen = self.manager_screens.get_screen("search screen")
self.download_screen = self.manager_screens.get_screen("downloads screen")
self.home_screen = self.manager_screens.get_screen("home screen")
return self.manager_screens
def on_start(self, *args):
self.media_card_popup = MediaPopup()
def generate_application_screens(self) -> None:
for i, name_screen in enumerate(screens.keys()):
model = screens[name_screen]["model"]()
controller = screens[name_screen]["controller"](model)
view = controller.get_view()
view.manager_screens = self.manager_screens
view.name = name_screen
self.manager_screens.add_widget(view)
def build_config(self, config):
# General settings setup
config.setdefaults(
"Preferences",
{
"theme_color": "Cyan",
"theme_style": "Dark",
"downloads_dir": downloads_dir,
},
)
def build_settings(self, settings: Settings):
settings.add_json_panel(
"Settings", self.config, resource_find("general_settings_panel.json")
)
def on_config_change(self, config, section, key, value):
# TODO: Change to match case
if section == "Preferences":
match key:
case "theme_color":
if value in themes_available:
self.theme_cls.primary_palette = value
else:
Logger.warning(
"AniXStream Settings: An invalid theme has been entered and will be ignored"
)
config.set("Preferences", "theme_color", "Cyan")
config.write()
case "theme_style":
self.theme_cls.theme_style = value
def on_stop(self):
pass
def search_for_anime(self, search_field, **kwargs):
if self.manager_screens.current != "search screen":
self.manager_screens.current = "search screen"
self.search_screen.handle_search_for_anime(search_field, **kwargs)
def add_anime_to_user_anime_list(self, id: int):
updated_list = user_data_helper.get_user_anime_list()
updated_list.append(id)
user_data_helper.update_user_anime_list(updated_list)
def remove_anime_from_user_anime_list(self, id: int):
updated_list = user_data_helper.get_user_anime_list()
if updated_list.count(id):
updated_list.remove(id)
user_data_helper.update_user_anime_list(updated_list)
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, title, caller_screen_name)
def play_on_mpv(self, anime_video_url: str):
if mpv_player.mpv_process:
mpv_player.stop_mpv()
mpv_player.run_mpv(anime_video_url)
def download_anime_video(self, url: str, anime_title: tuple):
self.download_screen.new_download_task(anime_title)
show_notification("New Download", f"{anime_title[0]} episode: {anime_title[1]}")
progress_hook = self.download_screen.on_episode_download_progress
downloader.download_file(url, anime_title, progress_hook)
def main():
FastAnime().run()
run_cli()
+3 -3
View File
@@ -11,13 +11,13 @@ if __package__ is None and not getattr(sys, "frozen", False):
if __name__ == "__main__":
in_development = bool(os.environ.get("IN_DEVELOPMENT", False))
import fastanime
from . import FastAnime
if in_development:
fastanime.main()
FastAnime()
else:
try:
fastanime.main()
FastAnime()
except Exception as e:
from .Utility.utils import write_crash
+10
View File
@@ -0,0 +1,10 @@
import click
from rich import print
from .commands import search, download, anilist
commands = {"search": search, "download": download, "anilist": anilist}
@click.group(commands=commands)
def run_cli():
print("Yellow")
+3
View File
@@ -0,0 +1,3 @@
from .anilist import anilist
from .download import download
from .search import search
@@ -0,0 +1,23 @@
import click
from .favourites import favourites
from .recent import recent
from .search import search
from .popular import popular
from .trending import trending
from .upcoming import upcoming
commands = {
"favourites": favourites,
"recent": recent,
"search": search,
"popular": popular,
"trending": trending,
"upcoming": upcoming,
}
@click.group(commands=commands)
def anilist():
pass
@@ -0,0 +1,6 @@
import click
@click.command()
def favourites():
print("favourites")
@@ -0,0 +1,6 @@
import click
@click.command()
def popular():
print("popular")
+6
View File
@@ -0,0 +1,6 @@
import click
@click.command()
def recent():
print("recent")
+6
View File
@@ -0,0 +1,6 @@
import click
@click.command()
def search():
print("search")
@@ -0,0 +1,6 @@
import click
@click.command()
def trending():
print("trending")
@@ -0,0 +1,6 @@
import click
@click.command()
def upcoming():
print("upcoming")
+6
View File
@@ -0,0 +1,6 @@
import click
@click.command()
def download():
print("download")
+6
View File
@@ -0,0 +1,6 @@
import click
@click.command()
def search():
print("Searching")
+31
View File
@@ -0,0 +1,31 @@
import subprocess
import logging
logger = logging.getLogger(__name__)
def run_fzf(options: tuple[str], *custom_commands):
"""
Run fzf with a list of options and return the selected option.
"""
# Join the list of options into a single string with newlines
options_str = "\n".join(options)
# Run fzf as a subprocess
result = subprocess.run(
["fzf", *custom_commands],
input=options_str,
text=True,
stdout=subprocess.PIPE,
)
# Check if fzf was successful
if result.returncode == 0:
# Return the selected option
selection = result.stdout.strip()
logger.info(f"fzf: selected {selection}")
return selection
else:
# Handle the case where fzf fails or is canceled
logger.error("fzf was canceled or failed")
return None
View File
+18 -20
View File
@@ -4,39 +4,37 @@ import random
from kivy.config import Config
from kivy.loader import Loader
from kivy.logger import Logger
from kivy.resources import resource_find
from kivy.resources import resource_add_path, resource_find
from kivy.uix.screenmanager import FadeTransition, ScreenManager
from kivy.uix.settings import Settings, SettingsWithSidebar
from kivymd.app import MDApp
from fastanime.Utility.show_notification import show_notification
from ..Utility.show_notification import show_notification
from . import downloads_dir
from .libs.mpv.player import mpv_player
from .Utility import (
from .. import downloads_dir, assets_folder, configs_folder
from ..libs.mpv.player import mpv_player
from ..Utility import (
themes_available,
user_data_helper,
)
from .Utility.downloader.downloader import downloader
from .Utility.utils import write_crash
from ..Utility.downloader.downloader import downloader
from .View.components.media_card.components.media_popup import MediaPopup
from .View.screens import screens
os.environ["KIVY_VIDEO"] = "ffpyplayer" # noqa: E402
Config.set("graphics", "width", "1000") # noqa: E402
Config.set("graphics", "minimum_width", "1000") # noqa: E402
Config.set("kivy", "window_icon", resource_find("logo.ico")) # noqa: E402
Config.write() # noqa: E402
def setup_app():
os.environ["KIVY_VIDEO"] = "ffpyplayer" # noqa: E402
Config.set("graphics", "width", "1000") # noqa: E402
Config.set("graphics", "minimum_width", "1000") # noqa: E402
Config.set("kivy", "window_icon", resource_find("logo.ico")) # noqa: E402
Config.write() # noqa: E402
Loader.num_workers = 5
Loader.max_upload_per_frame = 10
Loader.num_workers = 5
Loader.max_upload_per_frame = 10
# Ensure the user data fields exist
if not (user_data_helper.user_data.exists("user_anime_list")):
user_data_helper.update_user_anime_list([])
resource_add_path(assets_folder)
resource_add_path(configs_folder)
class FastAnime(MDApp):
@@ -149,5 +147,5 @@ class FastAnime(MDApp):
downloader.download_file(url, anime_title, progress_hook)
def run_app():
def run_gui():
FastAnime().run()
-23
View File
@@ -1,23 +0,0 @@
All this instructions should be done from the folder you chose to install
aniXstream but incase you have never installed python should work any where
1. First install pyenv with the following command:
Invoke-WebRequest -UseBasicParsing -Uri
"https://raw.githubusercontent.com/pyenv-win/pyenv-win/master/pyenv-win/install-pyenv-win.ps1"
-OutFile "./install-pyenv-win.ps1"; &"./install-pyenv-win.ps1"
2. run the following command:
pyenv --version to check whether installation was a success
3. run pyenv install 3.10 and confirm success by running pyenv -l and check
for 3.10
4. run pyenv local 3.10 (if in anixstream directory) or pyenv global 3.10 (if
in another directory to set python version 3.10 as global interpreter)
5. check if success by running python --version and checking if output is 3.10
6. run python -m pip install animdl
7. check if success by running python -m animdl and if no error then you are
ready to use anixstream to stream anime
8. additionally you can use animdl independently by running python -m animdl
and any arguments specified in the animdl documentation eg python -m animdl
stream naruto
-----------------------------
Now enjoy :)
------------------------------
+2
View File
@@ -5,3 +5,5 @@ plyer
https://github.com/kivymd/KivyMD/archive/master.zip
fuzzywuzzy
python-Levenshtein
rich
click