From d51238838c107e139d3eccfcc26bde58ed5f1861 Mon Sep 17 00:00:00 2001 From: Emile Clark-Boman Date: Sun, 6 Jul 2025 21:29:08 +1000 Subject: [PATCH] init (pre-existing): added template oop implementation --- .gitignore | 2 ++ NERD | 13 ++++++++++ README | 6 +++++ UWU | 54 +++++++++++++++++++++++++++++++++++++++ activate-venv | 1 + requirements.txt | 1 + src/core/__init__.py | 0 src/core/mirror.py | 3 +++ src/core/provider.py | 11 ++++++++ src/providers/__init__.py | 0 src/providers/hianime.py | 45 ++++++++++++++++++++++++++++++++ src/test.py | 30 ++++++++++++++++++++++ src/util/speedtest.py | 12 +++++++++ 13 files changed, 178 insertions(+) create mode 100644 .gitignore create mode 100644 NERD create mode 100644 README create mode 100644 UWU create mode 100644 activate-venv create mode 100644 requirements.txt create mode 100644 src/core/__init__.py create mode 100644 src/core/mirror.py create mode 100644 src/core/provider.py create mode 100644 src/providers/__init__.py create mode 100644 src/providers/hianime.py create mode 100644 src/test.py create mode 100644 src/util/speedtest.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92afa22 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +__pycache__/ +venv/ diff --git a/NERD b/NERD new file mode 100644 index 0000000..853e47b --- /dev/null +++ b/NERD @@ -0,0 +1,13 @@ +Anime is found on providers +Providers *can* have multiple mirrors +Each mirror acts the same +Each mirror provides anime +Each anime has episodes + + +To create an object oriented design I plan to reverse this and focus +around an `Anime` object. This object will reference which mirrors +supply it and etc. TODO: (fill this out more) + + +NOTE: We can ping each mirror to estimate which is best to stream from. diff --git a/README b/README new file mode 100644 index 0000000..985acd0 --- /dev/null +++ b/README @@ -0,0 +1,6 @@ +Watch anime from your terminal!! + +But smarter than ani-cli! Eva remembers where you're up to and let's you jump straight back into the funny japanese cartoons! + +Also shows you trending animes, and the release schedules for new episodes! +(https://animeschedule.net) diff --git a/UWU b/UWU new file mode 100644 index 0000000..aa72881 --- /dev/null +++ b/UWU @@ -0,0 +1,54 @@ +### Aspects +Ok so theres quite a few parts to this project. +I've ordered them based on the order I plan to implement them: +1. Searching providers for pages based on a query +2. Turning provider pages (above) into a python object with all relevant details using regex +3. Fetching a streaming link +4. Downloading an anime instead of streaming +5. Displaying in the current terminal (most likely with mpv) +6. Displaying a TUI interface +7. Allowing intros to be skipped + + +3. (Optional) A settings option that automatically translates anime names to English + + + + +Start by targetting HiAnime + + + + + +###### Which Providers to Use +This is the best possible list of sites +https://everythingmoe.com/ + +This is a pretty good overview too +https://www.reddit.com/r/animepiracy/comments/myfhk9/result_of_testing_every_website_on_animepiracy/ + + +###### Skipping Intros +I could either design my own system for this by looking at the frames and looking for +extremely similar segments. + +OR + +I could check out this project: +https://github.com/jonbarrow/open-anime-timestamps + +Open anime stamps developer talks [here](https://www.reddit.com/r/animepiracy/comments/oo1gbm/open_anime_timestamps_anime_openingending/) about how +it uses "acoustic fingerprinting" to detect timings! (sooooo cool) + + + +###### Related Anime +Also check out how cool this is: +https://anidb.net/anime/16951/relation/graph +They can provide relation graphs between animes (mind blown) + + +##### Changing Subtitle Language +Maybe I could have something that automatically translates an episode's +subtitles into another language? diff --git a/activate-venv b/activate-venv new file mode 100644 index 0000000..c2a1759 --- /dev/null +++ b/activate-venv @@ -0,0 +1 @@ +source ./venv/bin/activate.fish diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f229360 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +requests diff --git a/src/core/__init__.py b/src/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/core/mirror.py b/src/core/mirror.py new file mode 100644 index 0000000..8df7340 --- /dev/null +++ b/src/core/mirror.py @@ -0,0 +1,3 @@ +class Mirror: + def __init__(self, url: str) -> None: + self.url = url diff --git a/src/core/provider.py b/src/core/provider.py new file mode 100644 index 0000000..81ef316 --- /dev/null +++ b/src/core/provider.py @@ -0,0 +1,11 @@ +from core.mirror import Mirror + +''' +A provider can have multiple mirrors +''' +class Provider: + name = 'ProviderTemplate' + def __init__(self) -> None: + pass + def GetMirrors(self) -> list[str]: + raise NotImplementedError(f'method GetMirrors not implemented for {self.name} inheriting from Provider') diff --git a/src/providers/__init__.py b/src/providers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/providers/hianime.py b/src/providers/hianime.py new file mode 100644 index 0000000..b0bd231 --- /dev/null +++ b/src/providers/hianime.py @@ -0,0 +1,45 @@ +# Dependencies +import re +import requests +from urllib.parse import quote_plus as urlencode +# Assets +from core.provider import Provider + + + + +search_expr = '\s*' + '
\s*') + #'
.+
\s*' + #'
.+\s*' + #'
\s*' + #'
') + +class hianime(Provider): + _NAME = 'HiAnime' + _BOOTSTRAP = 'https://hianime.tv' + def __init__(self) -> None: + pass + def GetMirrors(self) -> list[str]: + content = requests.get('https://hianime.tv').text + expr = '
' + + # for some reason hianime doesn't advertise `hianime.to` as a mirror + matches = re.findall(expr, content) + if 'https://hianime.to' not in matches: + matches.append('https://hianime.to') + return matches + + def SearchAnime(self, mirror: str, query: str) -> list[str]: #-> list[Anime]: + urlsafe_query = urlencode(query) + url = f'{mirror}/search?keyword={urlsafe_query}&sort=default' + content = requests.get(url).text + #print(content) + + matches = re.findall(search_expr, content) + return matches + + + diff --git a/src/test.py b/src/test.py new file mode 100644 index 0000000..b844c50 --- /dev/null +++ b/src/test.py @@ -0,0 +1,30 @@ +from providers.hianime import hianime + +from requests import async + +def main(): + provider = hianime() + mirrors = provider.GetMirrors() + #print(mirrors) + + mirror = mirrors[0] + + tasks = [] + + animes = provider.SearchAnime(mirror, 'blue lock') + print(len(animes)) + for result in animes: + print(result) + result = mirror + result + + new_task = async.get(result) + tasks.append(new_task) + + # wait for tasks + async.map(tasks) + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/src/util/speedtest.py b/src/util/speedtest.py new file mode 100644 index 0000000..7f88e94 --- /dev/null +++ b/src/util/speedtest.py @@ -0,0 +1,12 @@ +from core.mirror import Mirror + +''' +Speedtest multiple mirrors to see which is faster + +My idea is to run some bash thing like +ping hianime.nz -c 1 -q | head -n 1 +And then run one of those asyncronyously (in parallel) +for each mirror we're testing +''' +def Speedtest(mirrors: list[Mirror]) -> list[int]: + pass