Compare commits

...

5 Commits

Author SHA1 Message Date
Benex254
00e5141152 chore: bump version (v2.6.7) 2024-10-12 01:08:14 +03:00
Benex254
158bc5710f docs: update readme 2024-10-11 10:49:53 +03:00
Benex254
a0b946a13d feat: add recent menu 2024-10-11 10:22:23 +03:00
Benex254
b547b75f03 feat: add environment variable that force updating of the cache db 2024-10-11 09:34:40 +03:00
Benex254
58c7427a47 feat(cli:serve): use the full executable path to python 2024-10-06 01:25:22 +03:00
8 changed files with 90 additions and 17 deletions

View File

@@ -85,11 +85,31 @@ If you have any difficulty consult for help on the [discord channel](https://dis
### Installation using your favourite package manager
Currently the app is only published on [pypi](https://pypi.org/project/fastanime/).
With the following extras available:
- standard -which installs all dependencies
- api - which installs dependencies required to use `fastanime serve`
- mpv - which installs python mpv
- notifications - which installs plyer required for desktop notifications
#### Using uv
Recommended method of installation
```bash
# generally:
uv tool install fastanime
# if you want other functionality:
uv tool install fastanime[standard]
uv tool install fastanime[api]
uv tool install fastanime[mpv]
uv tool install fastanime[notifications]
```
#### Using pipx
Preferred method of installation since [Pipx](https://github.com/pypa/pipx) creates an isolated environment for each app it installs.
```bash
pipx install fastanime
@@ -637,6 +657,19 @@ fastanime completions --bash
fastanime completions --zsh
```
#### fastanime serve
Helper command that starts a rest server.
This requires you to install fastanime with the api extra or standard extra.
```bash
# default options
fastanime serve
# specify host and port
fastanime serve --host <host> --port <port>
```
### MPV specific commands
The project now allows on the fly media controls directly from mpv. This means you can go to the next or previous episode without the window ever closing thus offering a seamless experience.
@@ -728,6 +761,8 @@ cache_requests = True
use_persistent_provider_store = False
recent = 50
[stream]
continue_from_history = True

View File

@@ -6,7 +6,7 @@ if sys.version_info < (3, 10):
) # noqa: F541
__version__ = "v2.6.6"
__version__ = "v2.6.7"
APP_NAME = "FastAnime"
AUTHOR = "Benex254"

View File

@@ -178,6 +178,9 @@ signal.signal(signal.SIGINT, handle_exit)
help="the player to use when streaming",
type=click.Choice(["mpv", "vlc"]),
)
@click.option(
"--fresh-requests", is_flag=True, help="Force the requests cache to be updated"
)
@click.pass_context
def run_cli(
ctx: click.Context,
@@ -212,7 +215,10 @@ def run_cli(
use_python_mpv,
sync_play,
player,
fresh_requests,
):
import os
from .config import Config
ctx.obj = Config()
@@ -251,6 +257,8 @@ def run_cli(
install()
if fresh_requests:
os.environ["FASTANIME_FRESH_REQUESTS"] = "1"
if sync_play:
ctx.obj.sync_play = sync_play
if provider:

View File

@@ -21,7 +21,7 @@ def serve(host, port):
from ...constants import APP_DIR
args = ["python", "-m", "fastapi", "run"]
args = [sys.executable, "-m", "fastapi", "run"]
if host:
args.extend(["--host", host])

View File

@@ -26,7 +26,7 @@ class Config(object):
"https://anilist.co/api/v2/oauth/authorize?client_id=20148&response_type=token"
)
anime_provider: "AnimeProvider"
user_data = {"watch_history": {}, "animelist": [], "user": {}}
user_data = {"recent_anime": [], "animelist": [], "user": {}}
default_config = {
"auto_next": "False",
"auto_select": "True",
@@ -49,6 +49,7 @@ class Config(object):
"preview": "False",
"provider": "allanime",
"quality": "1080",
"recent": "50",
"rofi_theme": "",
"rofi_theme_confirm": "",
"rofi_theme_input": "",
@@ -64,7 +65,7 @@ class Config(object):
}
def __init__(self) -> None:
self.initialize_user_data_and_watch_history()
self.initialize_user_data_and_watch_history_recent_anime()
self.load_config()
def load_config(self):
@@ -99,6 +100,7 @@ class Config(object):
self.provider = self.get_provider()
self.quality = self.get_quality()
self.recent = self.get_recent()
self.rofi_theme_confirm = self.get_rofi_theme_confirm()
self.rofi_theme_input = self.get_rofi_theme_input()
self.rofi_theme = self.get_rofi_theme()
@@ -136,6 +138,20 @@ class Config(object):
self.user_data["user"] = user
self._update_user_data()
def update_recent(self, recent_anime: list):
recent_anime_ids = []
_recent_anime = []
for anime in recent_anime[::-1]:
if (
anime["id"] not in recent_anime_ids
and len(recent_anime_ids) <= self.recent
):
_recent_anime.append(anime)
recent_anime_ids.append(anime["id"])
self.user_data["recent_anime"] = _recent_anime
self._update_user_data()
def media_list_track(
self,
anime_id: int,
@@ -157,7 +173,7 @@ class Config(object):
with open(USER_WATCH_HISTORY_PATH, "w") as f:
json.dump(self.watch_history, f)
def initialize_user_data_and_watch_history(self):
def initialize_user_data_and_watch_history_recent_anime(self):
try:
if os.path.isfile(USER_DATA_PATH):
with open(USER_DATA_PATH, "r") as f:
@@ -236,6 +252,9 @@ class Config(object):
def get_normalize_titles(self):
return self.configparser.getboolean("general", "normalize_titles")
def get_recent(self):
return self.configparser.getint("general", "recent")
# --- stream section ---
def get_skip(self):
return self.configparser.getboolean("stream", "skip")
@@ -408,6 +427,10 @@ cache_requests = {self.cache_requests}
# leave it as is
use_persistent_provider_store = {self.use_persistent_provider_store}
# no of recent anime to keep [0-50]
# 0 will disable recent anime tracking
recent = {self.recent}
[stream]
# Auto continue from watch history [True/False]

View File

@@ -539,6 +539,14 @@ def provider_anime_episode_servers_menu(
episode_title = episode_detail["title"]
break
if config.recent:
config.update_recent(
[
*config.user_data["recent_anime"],
fastanime_runtime_state.selected_anime_anilist,
]
)
print("Updating recent anime...")
if config.sync_play:
from ..utils.syncplay import SyncPlayer
@@ -1562,6 +1570,9 @@ def fastanime_main_menu(
watch_history = list(map(int, config.watch_history.keys()))
return AniList.search(id_in=watch_history, sort="TRENDING_DESC")
def _recent():
return (True, {"data": {"Page": {"media": config.user_data["recent_anime"]}}})
# WARNING: Will probably be depracated
def _anime_list():
anime_list = config.anime_list
@@ -1589,6 +1600,7 @@ def fastanime_main_menu(
# each option maps to anilist data that is described by the option name
options = {
f"{'🔥 ' if icons else ''}Trending": AniList.get_trending,
f"{'🎞️ ' if icons else ''}Recent": _recent,
f"{'📺 ' if icons else ''}Watching": lambda media_list_type="Watching": handle_animelist(
config, fastanime_runtime_state, media_list_type
),

View File

@@ -1,5 +1,6 @@
import json
import logging
import os
import re
import time
from datetime import datetime
@@ -49,7 +50,7 @@ class CachedRequestsSession(requests.Session):
def __init__(
self,
cache_db_path: str,
max_lifetime: int = 604800,
max_lifetime: int = 259200,
max_size: int = (1024**2) * 10,
table_name: str = "fastanime_requests_cache",
clean_db=False,
@@ -89,16 +90,10 @@ class CachedRequestsSession(requests.Session):
url,
params=None,
force_caching=False,
fresh=0,
fresh=int(os.environ.get("FASTANIME_FRESH_REQUESTS", 0)),
*args,
**kwargs,
):
# TODO: improve the caching functionality and add a layer to auto delete
# expired requests
if fresh:
logger.debug("Executing fresh request")
return super().request(method, url, params=params, *args, **kwargs)
if params:
url += "?" + urlencode(params)
@@ -128,7 +123,7 @@ class CachedRequestsSession(requests.Session):
cached_request = cursor.fetchone()
time_after_access_db = datetime.now()
if cached_request:
if cached_request and not fresh:
logger.debug("Found existing request in cache")
(
status_code,

View File

@@ -1,6 +1,6 @@
[tool.poetry]
name = "fastanime"
version = "2.6.6"
version = "2.6.7"
description = "A browser anime site experience from the terminal"
authors = ["Benextempest <benextempest@gmail.com>"]
license = "UNLICENSE"