6 Commits
0.1.1 ... dev

7 changed files with 174 additions and 57 deletions

View File

@@ -1,21 +0,0 @@
[tool.bumpversion]
current_version = "0.1.0"
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
serialize = ["{major}.{minor}.{patch}"]
search = "{current_version}"
replace = "{new_version}"
regex = false
ignore_missing_version = false
ignore_missing_files = false
tag = false
sign_tags = false
tag_name = "v{new_version}"
tag_message = "Bump version: {current_version} → {new_version}"
allow_dirty = false
commit = false
message = "Bump version: {current_version} → {new_version}"
moveable_tags = []
commit_args = ""
setup_hooks = []
pre_commit_hooks = []
post_commit_hooks = []

View File

@@ -25,10 +25,16 @@ jobs:
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@master uses: actions/checkout@master
with:
fetch-depth: 0
fetch-tags: true
- name: Install uv - name: Install uv
uses: astral-sh/setup-uv@v5 uses: astral-sh/setup-uv@v5
- name: Set up Python - name: Set up Python
run: uv python install run: uv python install
with:
python-version-file: "pyproject.toml"
- name: Set Git identity - name: Set Git identity
run: | run: |
git config user.name "Gitea CI" git config user.name "Gitea CI"

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "komsuite-nyaapy" name = "komsuite-nyaapy"
version = "0.1.0" version = "0.1.2"
description = "A rewritten hard fork of the original NyaaPy library." description = "A rewritten hard fork of the original NyaaPy library."
license = "MIT" license = "MIT"
readme = "README.md" readme = "README.md"
@@ -8,6 +8,8 @@ authors = [{ name = "WorldTeacher", email = "coding_contact@pm.me" }]
requires-python = ">=3.13" requires-python = ">=3.13"
dependencies = [ dependencies = [
"bencodepy>=0.9.5", "bencodepy>=0.9.5",
"httpx>=0.28.1",
"httpx-retries>=0.3.2",
"lxml>=5.3.1", "lxml>=5.3.1",
"regex>=2024.11.6", "regex>=2024.11.6",
] ]
@@ -16,3 +18,25 @@ dependencies = [
[build-system] [build-system]
requires = ["hatchling"] requires = ["hatchling"]
build-backend = "hatchling.build" build-backend = "hatchling.build"
[tool.bumpversion]
current_version = "0.1.2"
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
serialize = ["{major}.{minor}.{patch}"]
search = "{current_version}"
replace = "{new_version}"
regex = false
ignore_missing_version = false
ignore_missing_files = false
tag = true
sign_tags = false
tag_name = "v{new_version}"
tag_message = "Bump version: {current_version} → {new_version}"
allow_dirty = true
commit = true
message = "Bump version: {current_version} → {new_version}"
moveable_tags = []
commit_args = ""
setup_hooks = []
pre_commit_hooks = []
post_commit_hooks = []

View File

@@ -1,4 +1,4 @@
from .modules.anime_site import AnimeTorrentSite from .modules.anime_site import AnimeTorrentSite, AnimeTorrentSiteAsync
from .modules.torrent import TorrentSite from .modules.torrent import TorrentSite
from .sites.nyaa import Nyaa, SukebeiNyaa from .sites.nyaa import Nyaa, SukebeiNyaa
from .modules.torrent import Torrent from .modules.torrent import Torrent

View File

@@ -1,4 +1,4 @@
import requests import httpx
from komsuite_nyaapy.modules import torrent from komsuite_nyaapy.modules import torrent
from komsuite_nyaapy.modules.parser import parse_nyaa, parse_single, parse_nyaa_rss from komsuite_nyaapy.modules.parser import parse_nyaa, parse_single, parse_nyaa_rss
@@ -8,21 +8,20 @@ class AnimeTorrentSite:
URL = SITE URL = SITE
@classmethod @classmethod
def last_uploads(self, number_of_results: int): def last_uploads(cls, number_of_results: int):
r = requests.get(self.URL) with httpx.Client() as client:
r = client.get(cls.URL)
# If anything up with nyaa servers let the user know.
r.raise_for_status() r.raise_for_status()
json_data = parse_nyaa( json_data = parse_nyaa(
request_text=r.text, limit=number_of_results, site=self.SITE request_text=r.text, limit=number_of_results, site=cls.SITE
) )
return torrent.json_to_class(json_data) return torrent.json_to_class(json_data)
@classmethod @classmethod
def search( def search(
self, cls,
keyword: str, keyword: str,
category: int = 0, category: int = 0,
subcategory: int = 0, subcategory: int = 0,
@@ -32,10 +31,9 @@ class AnimeTorrentSite:
order: str = "desc", order: str = "desc",
**kwargs, **kwargs,
): ):
base_url = self.URL base_url = cls.URL
user = kwargs.get("user", None) user = kwargs.get("user", None)
user_uri = f"user/{user}" if user else "" user_uri = f"user/{user}" if user else ""
if page > 0: if page > 0:
@@ -64,34 +62,134 @@ class AnimeTorrentSite:
if not user: if not user:
search_uri += "&page=rss" search_uri += "&page=rss"
http_response = requests.get(search_uri)
with httpx.Client() as client:
http_response = client.get(search_uri)
http_response.raise_for_status() http_response.raise_for_status()
if user: if user:
json_data = parse_nyaa( json_data = parse_nyaa(
request_text=http_response.content, limit=None, site=self.SITE request_text=http_response.content, limit=None, site=cls.SITE
) )
else: else:
json_data = parse_nyaa_rss( json_data = parse_nyaa_rss(
request_text=http_response.content, limit=None, site=self.SITE request_text=http_response.content, limit=None, site=cls.SITE
) )
# Convert JSON data to a class object
return torrent.json_to_class(json_data) return torrent.json_to_class(json_data)
@classmethod @classmethod
def get(self, view_id: int): def get(cls, view_id: int):
r = requests.get(f"{self.URL}/view/{view_id}") with httpx.Client() as client:
r = client.get(f"{cls.URL}/view/{view_id}")
r.raise_for_status() r.raise_for_status()
json_data = parse_single(request_text=r.content, site=self.SITE) json_data = parse_single(request_text=r.content, site=cls.SITE)
return torrent.json_to_class(json_data) return torrent.json_to_class(json_data)
@classmethod @classmethod
def get_from_user(self, username): def get_from_user(cls, username):
r = requests.get(f"{self.URL}/user/{username}") with httpx.Client() as client:
r = client.get(f"{cls.URL}/user/{username}")
r.raise_for_status() r.raise_for_status()
json_data = parse_nyaa(request_text=r.content, limit=None, site=self.SITE) json_data = parse_nyaa(request_text=r.content, limit=None, site=cls.SITE)
return torrent.json_to_class(json_data)
class AnimeTorrentSiteAsync:
SITE = torrent.TorrentSite.NYAASI
URL = SITE
@classmethod
async def last_uploads(cls, number_of_results: int):
async with httpx.AsyncClient() as client:
r = await client.get(cls.URL)
r.raise_for_status()
json_data = parse_nyaa(
request_text=r.text, limit=number_of_results, site=cls.SITE
)
return torrent.json_to_class(json_data)
@classmethod
async def search(
cls,
keyword: str,
category: int = 0,
subcategory: int = 0,
filters: int = 0,
page: int = 0,
sorting: str = "id",
order: str = "desc",
**kwargs,
):
base_url = cls.URL
user = kwargs.get("user", None)
user_uri = f"user/{user}" if user else ""
if page > 0:
search_uri = "{}/{}?f={}&c={}_{}&q={}&p={}&s={}&o={}".format(
base_url,
user_uri,
filters,
category,
subcategory,
keyword,
page,
sorting,
order,
)
else:
search_uri = "{}/{}?f={}&c={}_{}&q={}&s={}&o={}".format(
base_url,
user_uri,
filters,
category,
subcategory,
keyword,
sorting,
order,
)
if not user:
search_uri += "&page=rss"
async with httpx.AsyncClient() as client:
http_response = await client.get(search_uri)
http_response.raise_for_status()
if user:
json_data = parse_nyaa(
request_text=http_response.content, limit=None, site=cls.SITE
)
else:
json_data = parse_nyaa_rss(
request_text=http_response.content, limit=None, site=cls.SITE
)
return torrent.json_to_class(json_data)
@classmethod
async def get(cls, view_id: int):
async with httpx.AsyncClient() as client:
r = await client.get(f"{cls.URL}/view/{view_id}")
r.raise_for_status()
json_data = parse_single(request_text=r.content, site=cls.SITE)
return torrent.json_to_class(json_data)
@classmethod
async def get_from_user(cls, username):
async with httpx.AsyncClient() as client:
r = await client.get(f"{cls.URL}/user/{username}")
r.raise_for_status()
json_data = parse_nyaa(request_text=r.content, limit=None, site=cls.SITE)
return torrent.json_to_class(json_data) return torrent.json_to_class(json_data)

View File

@@ -7,6 +7,7 @@ import regex
from typing import Optional from typing import Optional
import loguru import loguru
import sys import sys
import requests
log = loguru.logger log = loguru.logger
log.remove() log.remove()
@@ -66,10 +67,11 @@ class Torrent:
@property @property
def get_contents(self): def get_contents(self):
os.system(f"wget {self.download_url}> /dev/null 2>&1") resp = requests.get(self.download_url, timeout=15)
with open(f"{self.download_url.split('/')[-1]}", "rb") as f: resp.raise_for_status() # raises for HTTP 4xx/5xx
data = bencodepy.decode(f.read())
# 2. Decode directly from bytes
data = bencodepy.decode(resp.content)
info = data[b"info"] info = data[b"info"]
filetypes: list[str] = [] filetypes: list[str] = []
@@ -120,7 +122,6 @@ class Torrent:
else: else:
self.volumes = [0] self.volumes = [0]
# log.debug("Filetypes: {}, Volumes: {}".format(self.filetypes, self.volumes)) #! enable for debug # log.debug("Filetypes: {}, Volumes: {}".format(self.filetypes, self.volumes)) #! enable for debug
os.remove(f"{self.download_url.split('/')[-1]}")
class TorrentSite(Enum): class TorrentSite(Enum):

View File

@@ -1,4 +1,4 @@
from komsuite_nyaapy import AnimeTorrentSite, TorrentSite from komsuite_nyaapy import AnimeTorrentSite, TorrentSite, AnimeTorrentSiteAsync
class SukebeiNyaa(AnimeTorrentSite): class SukebeiNyaa(AnimeTorrentSite):
@@ -9,3 +9,12 @@ class SukebeiNyaa(AnimeTorrentSite):
class Nyaa(AnimeTorrentSite): class Nyaa(AnimeTorrentSite):
SITE = TorrentSite.NYAASI SITE = TorrentSite.NYAASI
URL = TorrentSite.get_site(SITE) URL = TorrentSite.get_site(SITE)
class SukebiNyaaAsync(AnimeTorrentSiteAsync):
SITE = TorrentSite.SUKEBEINYAASI
URL = TorrentSite.get_site(SITE)
class NyaaAsync(AnimeTorrentSiteAsync):
SITE = TorrentSite.NYAASI
URL = TorrentSite.get_site(SITE)