Skip to content

Commit

Permalink
Merge tag '1.0.6' into develop
Browse files Browse the repository at this point in the history
v1.0.6
  • Loading branch information
XayOn committed Oct 1, 2017
2 parents 857a463 + 2bff1ad commit 5af0af8
Show file tree
Hide file tree
Showing 11 changed files with 1,023 additions and 62 deletions.
14 changes: 14 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
CHANGES
=======

* Segmented tests
* Fixed tests
* Fixed tests?
* Updated usage
* Fixed last commit
* Moved asciicast to gif
* Fixed tests, still no tests for new additions
* Added more engines
* Added todo

1.0.5
-----

* Added multiple-search-engine searches
* Fixed bot options

1.0.4
Expand Down
674 changes: 674 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

39 changes: 24 additions & 15 deletions Readme.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ Command Line Interface

katcr comes with a simple but powerful command line interface

.. image:: https://asciinema.org/a/139240.png
:target: https://asciinema.org/a/139240
.. image:: https://raw.githubusercontent.com/XayOn/katcr/master/screenshot.gif

::

Expand All @@ -32,23 +31,33 @@ katcr comes with a simple but powerful command line interface

- Katcr
- ThePirateBay
- Nyaa
- Skytorrents
- Digbt

Options:
-e --search-engine=<SearchEngine> Torrent search engine to use
[default: Any].
-p --pages=<PAGES_NUM> Number of pages to lookup
[default: 1]
-d --disable-shortener Disable url shortener
-s --sortener=<SHORTENER_URL> Use given magnet shortener to
prettify urls.
[default: http://www.shortmag.net]
-e --search-engines=<SearchEngine> Torrent search engine to use
[default: All].
-p --pages=<PAGES_NUM> Number of pages to lookup
[default: 1]
-d --disable-shortener Disable url shortener
-s --shortener=<SHORTENER_URL> Use given magnet shortener to
prettify urls.
[default: http://www.shortmag.net]
-t --token=<SHORTENER_TOKEN> Shortener token to use, if required
-t --token_file=<S_TOKEN_FILE> Shortener token file

Interactive Options:
-i --interactive Enable interactive mode
-o --open Launch with default torrent app
in interactive mode [default: True]
-h --help Show this help screen
-d --debug Enable debug mode
-i --interactive Enable interactive mode
-o --open Launch with default torrent app
in interactive mode [default: True]
-h --help Show this help screen
-v --verbose Enable debug mode


katcr Copyright (C) 2017 David Francos Cuartero
This program comes with ABSOLUTELY NO WARRANTY; This is free software, and
you are welcome to redistribute it under certain conditions;


Installation
Expand Down
8 changes: 8 additions & 0 deletions TODO.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Pending things
--------------

* Fix tests
* Add information about seeds/leeches on each torrent
* Add more search engines
* Maybe direct search to the DHT?

114 changes: 105 additions & 9 deletions katcr/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"""

from contextlib import suppress
from pathlib import Path
import abc
import itertools
import re
Expand Down Expand Up @@ -59,7 +60,7 @@ def get_torrents(self):

def search_magnets(self, query: str, page: int):
"""Return the list of magnets from a specific page."""
proxies = torrentmirror.get_proxies()[self.proxy_name]
proxies = torrentmirror.get_proxies().get(self.proxy_name, [])
proxies.insert(0, [self.url, None])
for site, _ in proxies:
self.logger.debug("Searching in %s", site)
Expand Down Expand Up @@ -106,6 +107,78 @@ def get_torrents(self):
return [self.tabulate(torrent) for torrent in torrents]


class NyaaSi(BaseSearch):
"""Nyaa.Si torrent search engine."""

proxy_name = ''
url = 'https://nyaa.si'
url_format = '{}{}/?f=0&c=0_0&q={}&p={}'

@staticmethod
def tabulate(link):
"""Extract all information from each href."""
row = link.parent.parent.parent
cols = row.find_all('td')

def _nocomments(where):
return where != 'comments'

name = ''.join((cols[1].find('a', class_=_nocomments).text.strip(),
' ', cols[0].find('img')['alt'].strip()))
return (name, cols[3].text.strip(), link.parent['href'])

def get_torrents(self):
"""Return torrents."""
# pylint: disable=not-callable
links = self.browser.find_all(class_='fa-magnet')
return [self.tabulate(link) for link in links]


class Skytorrents(BaseSearch):
"""Skytorrents.in torrent search engine."""

proxy_name = ''
url = 'https://skytorrents.in/'
url_format = '{0}{1}search/all/ed/{3}/?l=en-us&q={2}'

@staticmethod
def tabulate(row):
"""Extract all information from each href."""
with suppress(IndexError):
cols = row.find_all('td')
links = cols[0].find_all('a')
return (links[0].text, cols[1].text, links[1]['href'])

def get_torrents(self):
"""Return torrents."""
# pylint: disable=not-callable
return list(filter(
None, [self.tabulate(l) for l in self.browser.find_all('tr')]))


class DigBt(BaseSearch):
"""Digbt DHT search engine."""

proxy_name = ''
url = 'https://digbt.org/'
url_format = '{0}{1}search/{2}-relevance-{3}/'

@staticmethod
def tabulate(row):
"""Extract all information from each href."""
with suppress(IndexError, TypeError):
tail = row.find(class_='tail')
return (row.find('div').find('a').text.strip(),
list(filter(lambda x: x, tail.text.split(' ')))[4].strip(),
tail.find('a')['href'].strip())

def get_torrents(self):
"""Return torrents."""
# pylint: disable=not-callable
return list(filter(
None, [self.tabulate(l) for l in self.browser.find_all('tr')]))


class Katcr(BaseSearch):
"""KickAssTorrents search engine.
Expand Down Expand Up @@ -151,6 +224,17 @@ def limit_terminal_size(what, limit=-20):
return what[:Terminal().width + limit]


def get_shortener_from_opts(opt):
"""Return shortener with token if needed."""
shortener = opt['--shortener'][0]
token = opt.get('--token')
if not token and opt.get('--token_file'):
token = Path(opt.get('--token_file')).read_text()
if token:
shortener = shortener.format(token)
return shortener


def search_in_engines(logger, engines, search_term, pages):
"""Search in engines."""
search_res = None
Expand All @@ -159,9 +243,11 @@ def search_in_engines(logger, engines, search_term, pages):
engines = ("Katcr", "ThePirateBay")

for engine in engines:
search_res = list(globals()[engine](logger).search(search_term, pages))
if search_res:
return search_res
with suppress(TypeError):
search_res = list(globals()[engine](logger).search(
search_term, pages))
if search_res:
return search_res


def main():
Expand All @@ -173,34 +259,45 @@ def main():
- Katcr
- ThePirateBay
- Nyaa
- Skytorrents
- Digbt
Options:
-e --search-engines=<SearchEngine> Torrent search engine to use
Options: Katcr, ThePirateBay
[default: All].
-p --pages=<PAGES_NUM> Number of pages to lookup
[default: 1]
-d --disable-shortener Disable url shortener
-s --shortener=<SHORTENER_URL> Use given magnet shortener to
prettify urls.
[default: http://www.shortmag.net]
-t --token=<SHORTENER_TOKEN> Shortener token to use, if required
-t --token_file=<S_TOKEN_FILE> Shortener token file
Interactive Options:
-i --interactive Enable interactive mode
-o --open Launch with default torrent app
in interactive mode [default: True]
-h --help Show this help screen
-v --verbose Enable debug mode
katcr Copyright (C) 2017 David Francos Cuartero
This program comes with ABSOLUTELY NO WARRANTY; This is free software, and
you are welcome to redistribute it under certain conditions;
"""
opt = docopt(main.__doc__, version="0.0.1")
opt = docopt(main.__doc__, version="1.0.1")
logger = Gogo(__name__, verbose=opt.get('--verbose')).logger

search_res = search_in_engines(logger, opt['--search-engine'],
search_res = search_in_engines(logger, opt['--search-engines'],
opt["<SEARCH_TERM>"],
int(opt.get("--pages")[0]))

if not opt['--disable-shortener']:
search_res = list(get_from_short(opt['--shortener'][0], search_res))
shortener = get_shortener_from_opts(opt)
with suppress(TypeError):
search_res = list(get_from_short(shortener, search_res))

if not search_res:
return
Expand All @@ -213,7 +310,6 @@ def main():
res = {limit_terminal_size(a): b for a, _, b in search_res}
result = res[prompt([List('Link', message="",
choices=res.keys())])['Link']]
print(result)

if opt['--open']:
return subprocess.check_call(['xdg-open', result])
Binary file added screenshot.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ author-email = opensource@davidfrancos.net
summary = Kickasstorrents search lib with python3.5
description-file = Readme.rst
home-page = https://github.com/XayOn/katcr
license = Apache-2
license = GPL3+
classifier =
Environment :: Console
Intended Audience :: End Users/Desktop
Expand Down
30 changes: 30 additions & 0 deletions tests/unit/test_digbit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""Tets dibgit plugin."""


def test_digbit_search_magnets():
"""Test digbit search magnets method."""
from katcr import DigBt
from robobrowser import RoboBrowser
from unittest.mock import patch, MagicMock

with patch('katcr.torrentmirror.get_proxies',
side_effect=({},)) as mock:
with patch('katcr.robobrowser.RoboBrowser', spec=RoboBrowser) as mock:
DigBt(MagicMock()).search_magnets('foo', 1)
assert mock.open.called_once_with('foo')


def test_digbit_tabulate():
"""Test tabulate method given a known structure.
Note that this structure may change in the future or even between
different proxied sites... This needs to be handled somehow.
"""
from katcr import DigBt
import bs4
to_parse = """<tr><div class=head><a>Foo</a></div>
<div class=tail>1 2 3 4 Bar<a href='foo'>
</a></div></tr>"""
fakelink = bs4.BeautifulSoup(to_parse, "html.parser")
result = DigBt.tabulate(fakelink.find('tr'))
assert result == ('Foo', 'Bar', 'foo')
Loading

0 comments on commit 5af0af8

Please sign in to comment.