Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

44 add some improvements #45

Merged
merged 6 commits into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export NCORE_USERNAME="<username>"
export NCORE_PASSWORD="<password>"
export RSS_URL="<rss_url>"
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ build/
dist/
ncoreparser.egg-info/
.venv
.vscode
.vscode
.env.sh
*.torrent
.tox*
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ prefer-stubs=no

# Minimum Python version to use for version dependent checks. Will default to
# the version used to run pylint.
py-version=3.9
py-version=3.12

# Discover python modules and packages in the file system subtree.
recursive=no
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ reqs: .venv

lint:
$(ACTIVATE) && pylint ncoreparser
$(ACTIVATE) && mypy ncoreparser

format:
$(ACTIVATE) && black .

test:
$(ACTIVATE) && tox
Expand Down
14 changes: 2 additions & 12 deletions ncoreparser/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
# flake8: noqa
from .client import Client
from .client_async import AsyncClient
from .data import (
SearchParamType,
SearchParamWhere,
ParamSeq,
ParamSort
)
from .error import (
NcoreDownloadError,
NcoreParserError,
NcoreCredentialError,
NcoreConnectionError
)
from .data import SearchParamType, SearchParamWhere, ParamSeq, ParamSort
from .error import NcoreDownloadError, NcoreParserError, NcoreCredentialError, NcoreConnectionError
from .util import Size
115 changes: 52 additions & 63 deletions ncoreparser/client.py
Original file line number Diff line number Diff line change
@@ -1,87 +1,71 @@
import os
import httpx
from ncoreparser.data import (
URLs,
SearchParamType,
SearchParamWhere,
ParamSort,
ParamSeq
)
from ncoreparser.error import (
NcoreConnectionError,
NcoreCredentialError,
NcoreDownloadError
)
from ncoreparser.parser import (
TorrentsPageParser,
TorrenDetailParser,
RssParser,
ActivityParser,
RecommendedParser
)
from typing_extensions import Any, Generator, Union
from ncoreparser.data import URLs, SearchParamType, SearchParamWhere, ParamSort, ParamSeq
from ncoreparser.error import NcoreConnectionError, NcoreCredentialError, NcoreDownloadError
from ncoreparser.parser import TorrentsPageParser, TorrenDetailParser, RssParser, ActivityParser, RecommendedParser
from ncoreparser.util import Size, check_login
from ncoreparser.torrent import Torrent


class Client:
def __init__(self, timeout=1):
self._client = httpx.Client(headers={'User-Agent': 'python ncoreparser'},
timeout=timeout,
follow_redirects=True)
def __init__(self, timeout: int = 1) -> None:
self._client = httpx.Client(
headers={"User-Agent": "python ncoreparser"}, timeout=timeout, follow_redirects=True
)
self._logged_in = False
self._page_parser = TorrentsPageParser()
self._detailed_parser = TorrenDetailParser()
self._rss_parser = RssParser()
self._activity_parser = ActivityParser()
self._recommended_parser = RecommendedParser()

def login(self, username, password):
def login(self, username: str, password: str) -> None:
self._client.cookies.clear()
try:
r = self._client.post(URLs.LOGIN.value,
data={"nev": username, "pass": password})
r = self._client.post(URLs.LOGIN.value, data={"nev": username, "pass": password})
except Exception as e:
raise NcoreConnectionError(f"Error while perform post "
f"method to url '{URLs.LOGIN.value}'.") from e
raise NcoreConnectionError(f"Error while perform post " f"method to url '{URLs.LOGIN.value}'.") from e
if r.url != URLs.INDEX.value:
self.logout()
raise NcoreCredentialError(f"Error while login, check "
f"credentials for user: '{username}'")
raise NcoreCredentialError(f"Error while login, check " f"credentials for user: '{username}'")
self._logged_in = True

@check_login
# pylint: disable=too-many-arguments, too-many-positional-arguments
def search(
self,
pattern,
type=SearchParamType.ALL_OWN,
where=SearchParamWhere.NAME,
sort_by=ParamSort.UPLOAD,
sort_order=ParamSeq.DECREASING,
number=None
):
pattern: str,
type: SearchParamType = SearchParamType.ALL_OWN,
where: SearchParamWhere = SearchParamWhere.NAME,
sort_by: ParamSort = ParamSort.UPLOAD,
sort_order: ParamSeq = ParamSeq.DECREASING,
number: Union[int, None] = None,
) -> list[Torrent]:
page_count = 1
torrents = []
torrents: list[Torrent] = []
while number is None or len(torrents) < number:
url = URLs.DOWNLOAD_PATTERN.value.format(page=page_count,
t_type=type.value,
sort=sort_by.value,
seq=sort_order.value,
pattern=pattern,
where=where.value)
url = URLs.DOWNLOAD_PATTERN.value.format(
page=page_count,
t_type=type.value,
sort=sort_by.value,
seq=sort_order.value,
pattern=pattern,
where=where.value,
)
try:
request = self._client.get(url)
except Exception as e:
raise NcoreConnectionError(f"Error while searhing torrents. {e}") from e
new_torrents = [Torrent(**params) for params in self._page_parser.get_items(request.text)]
torrents.extend(new_torrents)
if number is None or len(new_torrents) == 0:
return torrents
torrents.extend(new_torrents)
page_count += 1
return torrents[:number]

@check_login
def get_torrent(self, id, **ext_params):
def get_torrent(self, id: str, **ext_params: Any) -> Torrent:
url = URLs.DETAIL_PATTERN.value.format(id=id)
try:
content = self._client.get(url)
Expand All @@ -93,7 +77,7 @@ def get_torrent(self, id, **ext_params):
return Torrent(**params)

@check_login
def get_by_rss(self, url):
def get_by_rss(self, url: str) -> Generator[Torrent, None, None]:
try:
content = self._client.get(url)
except Exception as e:
Expand All @@ -103,51 +87,56 @@ def get_by_rss(self, url):
yield self.get_torrent(id)

@check_login
def get_by_activity(self):
def get_by_activity(self) -> list[Torrent]:
try:
content = self._client.get(URLs.ACTIVITY.value)
except Exception as e:
raise NcoreConnectionError(f"Error while get activity. Url: '{URLs.ACTIVITY.value}'. {e}") from e

torrents = []
for id, start_t, updated_t, status, uploaded, downloaded, remaining_t, rate in \
self._activity_parser.get_params(content.text):
torrents.append(self.get_torrent(id,
start=start_t,
updated=updated_t,
status=status,
uploaded=Size(uploaded),
downloaded=Size(downloaded),
remaining=remaining_t,
rate=float(rate)))
for id, start_t, updated_t, status, uploaded, downloaded, remaining_t, rate in self._activity_parser.get_params(
content.text
):
torrents.append(
self.get_torrent(
id,
start=start_t,
updated=updated_t,
status=status,
uploaded=Size(uploaded),
downloaded=Size(downloaded),
remaining=remaining_t,
rate=float(rate),
)
)
return torrents

@check_login
def get_recommended(self, type=None):
def get_recommended(self, type: Union[SearchParamType, None] = None) -> Generator[Torrent, None, None]:
try:
content = self._client.get(URLs.RECOMMENDED.value)
except Exception as e:
raise NcoreConnectionError(f"Error while get recommended. Url: '{URLs.RECOMMENDED.value}'. {e}") from e

for id in self._recommended_parser.get_ids(content.text):
torrent = self.get_torrent(id)
if not type or torrent['type'] == type:
if not type or torrent["type"] == type:
yield torrent

@check_login
def download(self, torrent, path, override=False):
def download(self, torrent: Torrent, path: str, override: bool = False) -> str:
file_path, url = torrent.prepare_download(path)
try:
content = self._client.get(url)
except Exception as e:
raise NcoreConnectionError(f"Error while downloading torrent. Url: '{url}'. {e}") from e
if not override and os.path.exists(file_path):
raise NcoreDownloadError(f"Error while downloading file: '{file_path}'. It is already exists.")
with open(file_path, 'wb') as fh:
with open(file_path, "wb") as fh:
fh.write(content.content)
return file_path

def logout(self):
def logout(self) -> None:
self._client.cookies.clear()
self._client.close()
self._logged_in = False
Loading
Loading