Move the "empty search for latest" to collections

There is now a "latest" collection (or "latest_nsfw").
The feature didn't look much used, since it didn't work on many
backends.
Using collections will make it easy to support other things
like most viewed, featured, etc.
As a bonus, I added tests for every backend with the feature.
This commit is contained in:
Laurent Bachelier 2012-03-16 02:55:58 +01:00
commit e958c229e6
32 changed files with 366 additions and 112 deletions

View file

@ -20,7 +20,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.video import ICapVideo from weboob.capabilities.video import ICapVideo, BaseVideo
from weboob.capabilities.collection import ICapCollection, CollectionNotFound
from weboob.tools.backend import BaseBackend, BackendConfig from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.value import Value from weboob.tools.value import Value
@ -31,7 +32,7 @@ from .video import ArteVideo
__all__ = ['ArteBackend'] __all__ = ['ArteBackend']
class ArteBackend(BaseBackend, ICapVideo): class ArteBackend(BaseBackend, ICapVideo, ICapCollection):
NAME = 'arte' NAME = 'arte'
MAINTAINER = 'Romain Bignon' MAINTAINER = 'Romain Bignon'
EMAIL = 'romain@weboob.org' EMAIL = 'romain@weboob.org'
@ -50,7 +51,7 @@ class ArteBackend(BaseBackend, ICapVideo):
with self.browser: with self.browser:
return self.browser.get_video(_id) return self.browser.get_video(_id)
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None): def search_videos(self, pattern, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
with self.browser: with self.browser:
return self.browser.search_videos(pattern) return self.browser.search_videos(pattern)
@ -65,4 +66,21 @@ class ArteBackend(BaseBackend, ICapVideo):
return video return video
def iter_resources(self, objs, split_path):
if BaseVideo in objs:
collection = self.get_collection(objs, split_path)
if collection.path_level == 0:
yield self.get_collection(objs, [u'latest'])
if collection.split_path == [u'latest']:
for video in self.browser.latest_videos():
yield video
def validate_collection(self, objs, collection):
if collection.path_level == 0:
return
if BaseVideo in objs and collection.split_path == [u'latest']:
collection.title = u'Latest Arte videos'
return
raise CollectionNotFound(collection.split_path)
OBJECTS = {ArteVideo: fill_video} OBJECTS = {ArteVideo: fill_video}

View file

@ -36,7 +36,7 @@ class ArteBrowser(BaseBrowser):
r'http://videos.arte.tv/\w+/videos/(?P<id>.+)\.html': VideoPage r'http://videos.arte.tv/\w+/videos/(?P<id>.+)\.html': VideoPage
} }
SEARCH_LANG = {'fr': 'recherche', 'de':'suche', 'en': 'search'} SEARCH_LANG = {'fr': 'recherche', 'de': 'suche', 'en': 'search'}
def __init__(self, lang, quality, *args, **kwargs): def __init__(self, lang, quality, *args, **kwargs):
BaseBrowser.__init__(self, *args, **kwargs) BaseBrowser.__init__(self, *args, **kwargs)
@ -52,9 +52,11 @@ class ArteBrowser(BaseBrowser):
self.location('http://videos.arte.tv/fr/videos/toutesLesVideos') self.location('http://videos.arte.tv/fr/videos/toutesLesVideos')
def search_videos(self, pattern): def search_videos(self, pattern):
if not pattern: self.location(self.buildurl('/%s/do_search/videos/%s' % (self.lang, self.SEARCH_LANG[self.lang]), q=pattern.encode('utf-8')))
self.home() assert self.is_on_page(IndexPage)
else: return self.page.iter_videos()
self.location(self.buildurl('/%s/do_search/videos/%s' % (self.lang, self.SEARCH_LANG[self.lang]), q=pattern.encode('utf-8')))
def latest_videos(self):
self.home()
assert self.is_on_page(IndexPage) assert self.is_on_page(IndexPage)
return self.page.iter_videos() return self.page.iter_videos()

View file

@ -19,13 +19,22 @@
from weboob.tools.test import BackendTest from weboob.tools.test import BackendTest
from weboob.capabilities.video import BaseVideo
class ArteTest(BackendTest): class ArteTest(BackendTest):
BACKEND = 'arte' BACKEND = 'arte'
def test_arte(self): def test_search(self):
l = list(self.backend.search_videos('arte')) l = list(self.backend.search_videos('arte'))
if len(l) > 0: if len(l) > 0:
v = l[0] v = l[0]
self.backend.fillobj(v, ('url',)) self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('rtmp://'), 'URL for video "%s" not found: %s' % (v.id, v.url)) self.assertTrue(v.url and v.url.startswith('rtmp://'), 'URL for video "%s" not found: %s' % (v.id, v.url))
def test_latest(self):
l = list(self.backend.iter_resources([BaseVideo], [u'latest']))
assert len(l)
v = l[0]
self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('rtmp://'), 'URL for video "%s" not found: %s' % (v.id, v.url))

View file

@ -48,7 +48,7 @@ class CanalplusBackend(BaseBackend, ICapVideo, ICapCollection):
def create_default_browser(self): def create_default_browser(self):
return self.create_browser(quality=self.config['quality'].get()) return self.create_browser(quality=self.config['quality'].get())
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None): def search_videos(self, pattern, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
with self.browser: with self.browser:
return self.browser.search_videos(pattern) return self.browser.search_videos(pattern)

View file

@ -10,7 +10,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.video import ICapVideo from weboob.capabilities.video import ICapVideo, BaseVideo
from weboob.capabilities.collection import ICapCollection, CollectionNotFound
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend
from .browser import CappedBrowser, CappedVideo from .browser import CappedBrowser, CappedVideo
@ -18,7 +19,7 @@ from .browser import CappedBrowser, CappedVideo
__all__ = ['CappedBackend'] __all__ = ['CappedBackend']
class CappedBackend(BaseBackend, ICapVideo): class CappedBackend(BaseBackend, ICapVideo, ICapCollection):
NAME = 'cappedtv' NAME = 'cappedtv'
MAINTAINER = 'Lord' MAINTAINER = 'Lord'
EMAIL = 'lord@lordtoniok.com' EMAIL = 'lord@lordtoniok.com'
@ -31,7 +32,7 @@ class CappedBackend(BaseBackend, ICapVideo):
with self.browser: with self.browser:
return self.browser.get_video(_id) return self.browser.get_video(_id)
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=None, max_results=None): def search_videos(self, pattern, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=None, max_results=None):
with self.browser: with self.browser:
return self.browser.search_videos(pattern) return self.browser.search_videos(pattern)
@ -45,4 +46,21 @@ class CappedBackend(BaseBackend, ICapVideo):
return video return video
def iter_resources(self, objs, split_path):
if BaseVideo in objs:
collection = self.get_collection(objs, split_path)
if collection.path_level == 0:
yield self.get_collection(objs, [u'latest'])
if collection.split_path == [u'latest']:
for video in self.browser.latest_videos():
yield video
def validate_collection(self, objs, collection):
if collection.path_level == 0:
return
if BaseVideo in objs and collection.split_path == [u'latest']:
collection.title = u'Latest CappedTV videos'
return
raise CollectionNotFound(collection.split_path)
OBJECTS = {CappedVideo: fill_video} OBJECTS = {CappedVideo: fill_video}

View file

@ -67,7 +67,7 @@ class IndexPage(BasePage):
seconds = parts[0] seconds = parts[0]
elif len(parts) == 2: elif len(parts) == 2:
hours = 0 hours = 0
minutes , seconds = parts minutes, seconds = parts
elif len(parts) == 3: elif len(parts) == 3:
hours, minutes, seconds = parts hours, minutes, seconds = parts
else: else:
@ -78,7 +78,6 @@ class IndexPage(BasePage):
yield video yield video
# parser for the video page # parser for the video page
class VideoPage(BasePage): class VideoPage(BasePage):
def get_video(self, video=None): def get_video(self, video=None):
@ -118,10 +117,12 @@ class CappedBrowser(BaseBrowser):
assert self.is_on_page(VideoPage), 'Should be on video page.' assert self.is_on_page(VideoPage), 'Should be on video page.'
return self.page.get_video(video) return self.page.get_video(video)
def search_videos(self,pattern): def search_videos(self, pattern):
if not pattern: self.location('/search?s=%s' % (urllib.quote_plus(pattern.encode('utf-8'))))
self.home() assert self.is_on_page(IndexPage)
else: return self.page.iter_videos()
self.location('/search?s=%s' % (urllib.quote_plus(pattern.encode('utf-8'))))
def latest_videos(self):
self.home()
assert self.is_on_page(IndexPage) assert self.is_on_page(IndexPage)
return self.page.iter_videos() return self.page.iter_videos()

View file

@ -10,18 +10,23 @@
from weboob.tools.test import BackendTest from weboob.tools.test import BackendTest
from weboob.capabilities.video import BaseVideo
__all__ = ['CappedTest']
class CappedTest(BackendTest): class CappedTest(BackendTest):
BACKEND = 'cappedtv' BACKEND = 'cappedtv'
def test_capped(self): def test_search(self):
l = list(self.backend.search_videos('kewlers')) l = list(self.backend.search_videos('kewlers'))
self.assertTrue(len(l) > 0) self.assertTrue(len(l) > 0)
v = l[0] v = l[0]
self.backend.fillobj(v, ('url',)) self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url)) self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))
self.backend.browser.openurl(v.url) self.backend.browser.openurl(v.url)
def test_latest(self):
l = list(self.backend.iter_resources([BaseVideo], [u'latest']))
self.assertTrue(len(l) > 0)
v = l[0]
self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))

View file

@ -20,7 +20,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.video import ICapVideo from weboob.capabilities.video import ICapVideo, BaseVideo
from weboob.capabilities.collection import ICapCollection, CollectionNotFound
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend
from .browser import DailymotionBrowser from .browser import DailymotionBrowser
@ -30,7 +31,7 @@ from .video import DailymotionVideo
__all__ = ['DailymotionBackend'] __all__ = ['DailymotionBackend']
class DailymotionBackend(BaseBackend, ICapVideo): class DailymotionBackend(BaseBackend, ICapVideo, ICapCollection):
NAME = 'dailymotion' NAME = 'dailymotion'
MAINTAINER = 'Romain Bignon' MAINTAINER = 'Romain Bignon'
EMAIL = 'romain@weboob.org' EMAIL = 'romain@weboob.org'
@ -44,7 +45,7 @@ class DailymotionBackend(BaseBackend, ICapVideo):
return self.browser.get_video(_id) return self.browser.get_video(_id)
SORTBY = ['relevance', 'rated', 'visited', None] SORTBY = ['relevance', 'rated', 'visited', None]
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None): def search_videos(self, pattern, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
with self.browser: with self.browser:
return self.browser.search_videos(pattern, self.SORTBY[sortby]) return self.browser.search_videos(pattern, self.SORTBY[sortby])
@ -59,4 +60,21 @@ class DailymotionBackend(BaseBackend, ICapVideo):
return video return video
def iter_resources(self, objs, split_path):
if BaseVideo in objs:
collection = self.get_collection(objs, split_path)
if collection.path_level == 0:
yield self.get_collection(objs, [u'latest'])
if collection.split_path == [u'latest']:
for video in self.browser.latest_videos():
yield video
def validate_collection(self, objs, collection):
if collection.path_level == 0:
return
if BaseVideo in objs and collection.split_path == [u'latest']:
collection.title = u'Latest Dailymotion videos'
return
raise CollectionNotFound(collection.split_path)
OBJECTS = {DailymotionVideo: fill_video} OBJECTS = {DailymotionVideo: fill_video}

View file

@ -47,15 +47,18 @@ class DailymotionBrowser(BaseBrowser):
self.location('/1') self.location('/1')
def search_videos(self, pattern, sortby): def search_videos(self, pattern, sortby):
if not pattern: pattern = pattern.replace('/', '').encode('utf-8')
self.home() if sortby is None:
url = '/search/%s/1' % quote_plus(pattern)
else: else:
pattern = pattern.replace('/', '').encode('utf-8') url = '/%s/search/%s/1' % (sortby, quote_plus(pattern))
if sortby is None: self.location(url)
url = '/search/%s/1' % quote_plus(pattern)
else: assert self.is_on_page(IndexPage)
url = '/%s/search/%s/1' % (sortby, quote_plus(pattern)) return self.page.iter_videos()
self.location(url)
def latest_videos(self):
self.home()
assert self.is_on_page(IndexPage) assert self.is_on_page(IndexPage)
return self.page.iter_videos() return self.page.iter_videos()

View file

@ -19,14 +19,23 @@
from weboob.tools.test import BackendTest from weboob.tools.test import BackendTest
from weboob.capabilities.video import BaseVideo
class DailymotionTest(BackendTest): class DailymotionTest(BackendTest):
BACKEND = 'dailymotion' BACKEND = 'dailymotion'
def test_dailymotion(self): def test_search(self):
l = list(self.backend.search_videos('chirac')) l = list(self.backend.search_videos('chirac'))
self.assertTrue(len(l) > 0) self.assertTrue(len(l) > 0)
v = l[0] v = l[0]
self.backend.fillobj(v, ('url',)) self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url)) self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))
self.backend.browser.openurl(v.url) self.backend.browser.openurl(v.url)
def test_latest(self):
l = list(self.backend.iter_resources([BaseVideo], [u'latest']))
assert len(l)
v = l[0]
self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))

View file

@ -20,7 +20,8 @@
from __future__ import with_statement from __future__ import with_statement
import re import re
from weboob.capabilities.gallery import ICapGallery from weboob.capabilities.gallery import ICapGallery, BaseGallery
from weboob.capabilities.collection import ICapCollection, CollectionNotFound
from weboob.tools.backend import BaseBackend, BackendConfig from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.misc import ratelimit from weboob.tools.misc import ratelimit
from weboob.tools.value import Value, ValueBackendPassword from weboob.tools.value import Value, ValueBackendPassword
@ -32,7 +33,7 @@ from .gallery import EHentaiGallery, EHentaiImage
__all__ = ['EHentaiBackend'] __all__ = ['EHentaiBackend']
class EHentaiBackend(BaseBackend, ICapGallery): class EHentaiBackend(BaseBackend, ICapGallery, ICapCollection):
NAME = 'ehentai' NAME = 'ehentai'
MAINTAINER = 'Roger Philibert' MAINTAINER = 'Roger Philibert'
EMAIL = 'roger.philibert@gmail.com' EMAIL = 'roger.philibert@gmail.com'
@ -53,7 +54,7 @@ class EHentaiBackend(BaseBackend, ICapGallery):
password = None password = None
return self.create_browser(self.config['domain'].get(), username, password) return self.create_browser(self.config['domain'].get(), username, password)
def search_gallery(self, pattern=None, sortby=None, max_results=None): def search_gallery(self, pattern, sortby=None, max_results=None):
with self.browser: with self.browser:
return self.browser.search_gallery(pattern) return self.browser.search_gallery(pattern)
@ -94,6 +95,23 @@ class EHentaiBackend(BaseBackend, ICapGallery):
ratelimit("ehentai_get", 2) ratelimit("ehentai_get", 2)
image.data = self.browser.readurl(image.url) image.data = self.browser.readurl(image.url)
def iter_resources(self, objs, split_path):
if BaseGallery in objs:
collection = self.get_collection(objs, split_path)
if collection.path_level == 0:
yield self.get_collection(objs, [u'latest_nsfw'])
if collection.split_path == [u'latest_nsfw']:
for gallery in self.browser.latest_gallery():
yield gallery
def validate_collection(self, objs, collection):
if collection.path_level == 0:
return
if BaseGallery in objs and collection.split_path == [u'latest_nsfw']:
collection.title = u'Latest E-Hentai galleries (NSFW)'
return
raise CollectionNotFound(collection.split_path)
OBJECTS = { OBJECTS = {
EHentaiGallery: fill_gallery, EHentaiGallery: fill_gallery,
EHentaiImage: fill_image} EHentaiImage: fill_image}

View file

@ -56,6 +56,11 @@ class EHentaiBrowser(BaseBrowser):
assert self.is_on_page(IndexPage) assert self.is_on_page(IndexPage)
return self.page.iter_galleries() return self.page.iter_galleries()
def latest_gallery(self):
self.location('/')
assert self.is_on_page(IndexPage)
return self.page.iter_galleries()
def iter_gallery_images(self, gallery): def iter_gallery_images(self, gallery):
self.location(gallery.url) self.location(gallery.url)
assert self.is_on_page(GalleryPage) assert self.is_on_page(GalleryPage)

View file

@ -19,12 +19,13 @@
from weboob.tools.test import BackendTest from weboob.tools.test import BackendTest
from weboob.capabilities.gallery import BaseGallery
class EHentaiTest(BackendTest): class EHentaiTest(BackendTest):
BACKEND = 'ehentai' BACKEND = 'ehentai'
def test_ehentai(self): def test_search(self):
l = list(self.backend.search_gallery('lol')) l = list(self.backend.search_gallery('lol'))
self.assertTrue(len(l) > 0) self.assertTrue(len(l) > 0)
v = l[0] v = l[0]
@ -36,3 +37,7 @@ class EHentaiTest(BackendTest):
self.backend.fillobj(img, ('url',)) self.backend.fillobj(img, ('url',))
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for first image in gallery "%s" not found: %s' % (v.id, img.url)) self.assertTrue(v.url and v.url.startswith('http://'), 'URL for first image in gallery "%s" not found: %s' % (v.id, img.url))
self.backend.browser.openurl(img.url) self.backend.browser.openurl(img.url)
def test_latest(self):
l = list(self.backend.iter_resources([BaseGallery], [u'latest_nsfw']))
assert len(l) > 0

View file

@ -20,7 +20,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.video import ICapVideo from weboob.capabilities.video import ICapVideo, BaseVideo
from weboob.capabilities.collection import ICapCollection, CollectionNotFound
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend
from .browser import PluzzBrowser from .browser import PluzzBrowser
@ -30,7 +31,7 @@ from .video import PluzzVideo
__all__ = ['PluzzBackend'] __all__ = ['PluzzBackend']
class PluzzBackend(BaseBackend, ICapVideo): class PluzzBackend(BaseBackend, ICapVideo, ICapCollection):
NAME = 'francetelevisions' NAME = 'francetelevisions'
MAINTAINER = 'Romain Bignon' MAINTAINER = 'Romain Bignon'
EMAIL = 'romain@weboob.org' EMAIL = 'romain@weboob.org'
@ -43,7 +44,7 @@ class PluzzBackend(BaseBackend, ICapVideo):
with self.browser: with self.browser:
return self.browser.get_video(_id) return self.browser.get_video(_id)
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None): def search_videos(self, pattern, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
with self.browser: with self.browser:
return self.browser.search_videos(pattern) return self.browser.search_videos(pattern)
@ -58,4 +59,21 @@ class PluzzBackend(BaseBackend, ICapVideo):
return video return video
def iter_resources(self, objs, split_path):
if BaseVideo in objs:
collection = self.get_collection(objs, split_path)
if collection.path_level == 0:
yield self.get_collection(objs, [u'latest'])
if collection.split_path == [u'latest']:
for video in self.browser.latest_videos():
yield video
def validate_collection(self, objs, collection):
if collection.path_level == 0:
return
if BaseVideo in objs and collection.split_path == [u'latest']:
collection.title = u'Latest France Télévisions videos'
return
raise CollectionNotFound(collection.split_path)
OBJECTS = {PluzzVideo: fill_video} OBJECTS = {PluzzVideo: fill_video}

View file

@ -59,10 +59,13 @@ class PluzzBrowser(BaseBrowser):
self.location('/replay/1') self.location('/replay/1')
def search_videos(self, pattern): def search_videos(self, pattern):
if not pattern: self.location(self.buildurl('/recherche.html', q=pattern.encode('utf-8')))
self.home()
else: assert self.is_on_page(IndexPage)
self.location(self.buildurl('/recherche.html', q=pattern.encode('utf-8'))) return self.page.iter_videos()
def latest_videos(self):
self.home()
assert self.is_on_page(IndexPage) assert self.is_on_page(IndexPage)
return self.page.iter_videos() return self.page.iter_videos()
@ -79,11 +82,11 @@ class PluzzBrowser(BaseBrowser):
for vid in root.find('videos'): for vid in root.find('videos'):
if vid.findtext('statut') == 'ONLINE' and vid.findtext('format') == 'wmv': if vid.findtext('statut') == 'ONLINE' and vid.findtext('format') == 'wmv':
video.url = vid.findtext('url') video.url = vid.findtext('url')
date = root.findtext('diffusions/diffusion') date = root.findtext('diffusions/diffusion')
if date: if date:
video.date = datetime.datetime.strptime(date, '%d/%m/%Y %H:%M') video.date = datetime.datetime.strptime(date, '%d/%m/%Y %H:%M')
video.description = root.findtext('synopsis') video.description = root.findtext('synopsis')

View file

@ -19,14 +19,22 @@
from weboob.tools.test import BackendTest from weboob.tools.test import BackendTest
from weboob.capabilities.video import BaseVideo
class PluzzTest(BackendTest): class PluzzTest(BackendTest):
BACKEND = 'francetelevisions' BACKEND = 'francetelevisions'
def test_francetelevisions(self): def test_search(self):
# If the test fails, it might be good news! # If the test fails, it might be good news!
l = list(self.backend.search_videos('Plus belle la vie')) l = list(self.backend.search_videos('Plus belle la vie'))
self.assertTrue(len(l) > 0) self.assertTrue(len(l) > 0)
v = l[0] v = l[0]
self.backend.fillobj(v, ('url',)) self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('mms://'), 'URL for video "%s" not found: %s' % (v.id, v.url)) self.assertTrue(v.url and v.url.startswith('mms://'), 'URL for video "%s" not found: %s' % (v.id, v.url))
def test_latest(self):
l = list(self.backend.iter_resources([BaseVideo], [u'latest']))
assert len(l)
v = l[0]
self.backend.fillobj(v, ('url',))
assert v.url

View file

@ -42,7 +42,7 @@ class InaBackend(BaseBackend, ICapVideo):
def get_video(self, _id): def get_video(self, _id):
return self.browser.get_video(_id) return self.browser.get_video(_id)
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None): def search_videos(self, pattern, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
with self.browser: with self.browser:
return self.browser.search_videos(pattern) return self.browser.search_videos(pattern)

View file

@ -20,7 +20,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.video import ICapVideo from weboob.capabilities.video import ICapVideo, BaseVideo
from weboob.capabilities.collection import ICapCollection, CollectionNotFound
from weboob.tools.value import Value, ValueBackendPassword from weboob.tools.value import Value, ValueBackendPassword
from weboob.tools.backend import BaseBackend, BackendConfig from weboob.tools.backend import BaseBackend, BackendConfig
@ -31,7 +32,7 @@ from .video import NolifeTVVideo
__all__ = ['NolifeTVBackend'] __all__ = ['NolifeTVBackend']
class NolifeTVBackend(BaseBackend, ICapVideo): class NolifeTVBackend(BaseBackend, ICapVideo, ICapCollection):
NAME = 'nolifetv' NAME = 'nolifetv'
MAINTAINER = 'Romain Bignon' MAINTAINER = 'Romain Bignon'
EMAIL = 'romain@weboob.org' EMAIL = 'romain@weboob.org'
@ -55,7 +56,7 @@ class NolifeTVBackend(BaseBackend, ICapVideo):
video = self.browser.get_video(_id) video = self.browser.get_video(_id)
return video return video
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None): def search_videos(self, pattern, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
with self.browser: with self.browser:
return self.browser.search_videos(pattern) return self.browser.search_videos(pattern)
@ -70,4 +71,21 @@ class NolifeTVBackend(BaseBackend, ICapVideo):
return video return video
def iter_resources(self, objs, split_path):
if BaseVideo in objs:
collection = self.get_collection(objs, split_path)
if collection.path_level == 0:
yield self.get_collection(objs, [u'latest'])
if collection.split_path == [u'latest']:
for video in self.browser.latest_videos():
yield video
def validate_collection(self, objs, collection):
if collection.path_level == 0:
return
if BaseVideo in objs and collection.split_path == [u'latest']:
collection.title = u'Latest NoLiveTV videos'
return
raise CollectionNotFound(collection.split_path)
OBJECTS = {NolifeTVVideo: fill_video} OBJECTS = {NolifeTVVideo: fill_video}

View file

@ -70,9 +70,11 @@ class NolifeTVBrowser(BaseBrowser):
return self.page.get_video(video) return self.page.get_video(video)
def search_videos(self, pattern): def search_videos(self, pattern):
if not pattern: self.location('/index.php?', 'search=%s' % urllib.quote_plus(pattern.encode('utf-8')))
self.home() assert self.is_on_page(IndexPage)
else: return self.page.iter_videos()
self.location('/index.php?', 'search=%s' % urllib.quote_plus(pattern.encode('utf-8')))
def latest_videos(self):
self.home()
assert self.is_on_page(IndexPage) assert self.is_on_page(IndexPage)
return self.page.iter_videos() return self.page.iter_videos()

View file

@ -19,12 +19,15 @@
from weboob.tools.test import BackendTest from weboob.tools.test import BackendTest
from weboob.capabilities.video import BaseVideo
from .pages.video import ForbiddenVideo from .pages.video import ForbiddenVideo
class NolifeTVTest(BackendTest): class NolifeTVTest(BackendTest):
BACKEND = 'nolifetv' BACKEND = 'nolifetv'
def test_nolife(self): def test_search(self):
l = list(self.backend.search_videos('nolife')) l = list(self.backend.search_videos('nolife'))
self.assertTrue(len(l) > 0) self.assertTrue(len(l) > 0)
for v in l: for v in l:
@ -35,3 +38,15 @@ class NolifeTVTest(BackendTest):
else: else:
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url)) self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))
break break
def test_latest(self):
l = list(self.backend.iter_resources([BaseVideo], [u'latest']))
assert len(l) > 0
for v in l:
try:
self.backend.fillobj(v, ('url',))
except ForbiddenVideo:
continue
else:
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))
break

View file

@ -20,7 +20,8 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.video import ICapVideo from weboob.capabilities.video import ICapVideo, BaseVideo
from weboob.capabilities.collection import ICapCollection, CollectionNotFound
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend
from .browser import YoujizzBrowser from .browser import YoujizzBrowser
@ -30,7 +31,7 @@ from .video import YoujizzVideo
__all__ = ['YoujizzBackend'] __all__ = ['YoujizzBackend']
class YoujizzBackend(BaseBackend, ICapVideo): class YoujizzBackend(BaseBackend, ICapVideo, ICapCollection):
NAME = 'youjizz' NAME = 'youjizz'
MAINTAINER = 'Roger Philibert' MAINTAINER = 'Roger Philibert'
EMAIL = 'roger.philibert@gmail.com' EMAIL = 'roger.philibert@gmail.com'
@ -44,7 +45,7 @@ class YoujizzBackend(BaseBackend, ICapVideo):
video = self.browser.get_video(_id) video = self.browser.get_video(_id)
return video return video
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None): def search_videos(self, pattern, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
if not nsfw: if not nsfw:
return set() return set()
with self.browser: with self.browser:
@ -61,4 +62,21 @@ class YoujizzBackend(BaseBackend, ICapVideo):
return video return video
def iter_resources(self, objs, split_path):
if BaseVideo in objs:
collection = self.get_collection(objs, split_path)
if collection.path_level == 0:
yield self.get_collection(objs, [u'latest_nsfw'])
if collection.split_path == [u'latest_nsfw']:
for video in self.browser.latest_videos():
yield video
def validate_collection(self, objs, collection):
if collection.path_level == 0:
return
if BaseVideo in objs and collection.split_path == [u'latest_nsfw']:
collection.title = u'Latest Youjizz videos (NSFW)'
return
raise CollectionNotFound(collection.split_path)
OBJECTS = {YoujizzVideo: fill_video} OBJECTS = {YoujizzVideo: fill_video}

View file

@ -47,9 +47,11 @@ class YoujizzBrowser(BaseBrowser):
return self.page.get_video(video) return self.page.get_video(video)
def search_videos(self, pattern): def search_videos(self, pattern):
if not pattern: self.location('/search/%s-1.html' % (urllib.quote_plus(pattern.encode('utf-8'))))
self.home() assert self.is_on_page(IndexPage)
else: return self.page.iter_videos()
self.location('/search/%s-1.html' % (urllib.quote_plus(pattern.encode('utf-8'))))
def latest_videos(self):
self.home()
assert self.is_on_page(IndexPage) assert self.is_on_page(IndexPage)
return self.page.iter_videos() return self.page.iter_videos()

View file

@ -19,17 +19,25 @@
from weboob.tools.test import BackendTest from weboob.tools.test import BackendTest
from weboob.capabilities.video import BaseVideo
class YoujizzTest(BackendTest): class YoujizzTest(BackendTest):
BACKEND = 'youjizz' BACKEND = 'youjizz'
def test_youjizz(self): def test_search(self):
self.assertTrue(len(self.backend.search_videos('anus', nsfw=False)) == 0) self.assertTrue(len(self.backend.search_videos('anus', nsfw=False)) == 0)
l = list(self.backend.search_videos('sex', nsfw=True)) l = list(self.backend.search_videos('anus', nsfw=True))
self.assertTrue(len(l) > 0) self.assertTrue(len(l) > 0)
v = l[0] v = l[0]
self.backend.fillobj(v, ('url',)) self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url)) self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))
self.backend.browser.openurl(v.url) self.backend.browser.openurl(v.url)
def test_latest(self):
l = list(self.backend.iter_resources([BaseVideo], [u'latest_nsfw']))
self.assertTrue(len(l) > 0)
v = l[0]
self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))

View file

@ -20,8 +20,9 @@
from __future__ import with_statement from __future__ import with_statement
from weboob.capabilities.video import ICapVideo from weboob.capabilities.video import ICapVideo, BaseVideo
from weboob.tools.backend import BaseBackend from weboob.tools.backend import BaseBackend
from weboob.capabilities.collection import ICapCollection, CollectionNotFound
from .browser import YoupornBrowser from .browser import YoupornBrowser
from .video import YoupornVideo from .video import YoupornVideo
@ -30,7 +31,7 @@ from .video import YoupornVideo
__all__ = ['YoupornBackend'] __all__ = ['YoupornBackend']
class YoupornBackend(BaseBackend, ICapVideo): class YoupornBackend(BaseBackend, ICapVideo, ICapCollection):
NAME = 'youporn' NAME = 'youporn'
MAINTAINER = 'Romain Bignon' MAINTAINER = 'Romain Bignon'
EMAIL = 'romain@weboob.org' EMAIL = 'romain@weboob.org'
@ -45,7 +46,7 @@ class YoupornBackend(BaseBackend, ICapVideo):
SORTBY = ['relevance', 'rating', 'views', 'time'] SORTBY = ['relevance', 'rating', 'views', 'time']
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None): def search_videos(self, pattern, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
if not nsfw: if not nsfw:
return set() return set()
with self.browser: with self.browser:
@ -62,4 +63,21 @@ class YoupornBackend(BaseBackend, ICapVideo):
return video return video
def iter_resources(self, objs, split_path):
if BaseVideo in objs:
collection = self.get_collection(objs, split_path)
if collection.path_level == 0:
yield self.get_collection(objs, [u'latest_nsfw'])
if collection.split_path == [u'latest_nsfw']:
for video in self.browser.latest_videos():
yield video
def validate_collection(self, objs, collection):
if collection.path_level == 0:
return
if BaseVideo in objs and collection.split_path == [u'latest_nsfw']:
collection.title = u'Latest YouPorn videos (NSFW)'
return
raise CollectionNotFound(collection.split_path)
OBJECTS = {YoupornVideo: fill_video} OBJECTS = {YoupornVideo: fill_video}

View file

@ -44,9 +44,11 @@ class YoupornBrowser(BaseBrowser):
return self.page.get_video(video) return self.page.get_video(video)
def search_videos(self, pattern, sortby): def search_videos(self, pattern, sortby):
if not pattern: self.location(self.buildurl('/search/%s' % sortby, query=pattern.encode('utf-8')))
self.home() assert self.is_on_page(IndexPage)
else: return self.page.iter_videos()
self.location(self.buildurl('/search/%s' % sortby, query=pattern.encode('utf-8')))
def latest_videos(self):
self.home()
assert self.is_on_page(IndexPage) assert self.is_on_page(IndexPage)
return self.page.iter_videos() return self.page.iter_videos()

View file

@ -19,12 +19,14 @@
from weboob.tools.test import BackendTest from weboob.tools.test import BackendTest
from weboob.capabilities.video import BaseVideo
class YoupornTest(BackendTest): class YoupornTest(BackendTest):
BACKEND = 'youporn' BACKEND = 'youporn'
def test_youporn(self): def test_search(self):
self.assertTrue(len(self.backend.search_videos('penis', nsfw=False)) == 0) self.assertTrue(len(self.backend.search_videos('ass to mouth', nsfw=False)) == 0)
l = list(self.backend.search_videos('ass to mouth', nsfw=True)) l = list(self.backend.search_videos('ass to mouth', nsfw=True))
self.assertTrue(len(l) > 0) self.assertTrue(len(l) > 0)
@ -32,3 +34,10 @@ class YoupornTest(BackendTest):
self.backend.fillobj(v, ('url',)) self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url)) self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))
self.backend.browser.openurl(v.url) self.backend.browser.openurl(v.url)
def test_latest(self):
l = list(self.backend.iter_resources([BaseVideo], [u'latest_nsfw']))
self.assertTrue(len(l) > 0)
v = l[0]
self.backend.fillobj(v, ('url',))
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))

View file

@ -26,7 +26,8 @@ import re
import urllib import urllib
from weboob.capabilities.base import NotAvailable from weboob.capabilities.base import NotAvailable
from weboob.capabilities.video import ICapVideo from weboob.capabilities.video import ICapVideo, BaseVideo
from weboob.capabilities.collection import ICapCollection, CollectionNotFound
from weboob.tools.capabilities.thumbnail import Thumbnail from weboob.tools.capabilities.thumbnail import Thumbnail
from weboob.tools.backend import BaseBackend, BackendConfig from weboob.tools.backend import BaseBackend, BackendConfig
from weboob.tools.misc import to_unicode from weboob.tools.misc import to_unicode
@ -39,7 +40,7 @@ from .video import YoutubeVideo
__all__ = ['YoutubeBackend'] __all__ = ['YoutubeBackend']
class YoutubeBackend(BaseBackend, ICapVideo): class YoutubeBackend(BaseBackend, ICapVideo, ICapCollection):
NAME = 'youtube' NAME = 'youtube'
MAINTAINER = 'Christophe Benz' MAINTAINER = 'Christophe Benz'
EMAIL = 'christophe.benz@gmail.com' EMAIL = 'christophe.benz@gmail.com'
@ -110,7 +111,7 @@ class YoutubeBackend(BaseBackend, ICapVideo):
video.set_empty_fields(NotAvailable) video.set_empty_fields(NotAvailable)
return video return video
def search_videos(self, pattern=None, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None): def search_videos(self, pattern, sortby=ICapVideo.SEARCH_RELEVANCE, nsfw=False, max_results=None):
YOUTUBE_MAX_RESULTS = 50 YOUTUBE_MAX_RESULTS = 50
YOUTUBE_MAX_START_INDEX = 1000 YOUTUBE_MAX_START_INDEX = 1000
yt_service = gdata.youtube.service.YouTubeService() yt_service = gdata.youtube.service.YouTubeService()
@ -144,6 +145,9 @@ class YoutubeBackend(BaseBackend, ICapVideo):
if nb_yielded == max_results: if nb_yielded == max_results:
return return
def latest_videos(self):
return self.search_videos(None, ICapVideo.SEARCH_DATE)
def fill_video(self, video, fields): def fill_video(self, video, fields):
if 'thumbnail' in fields: if 'thumbnail' in fields:
video.thumbnail.data = urllib.urlopen(video.thumbnail.url).read() video.thumbnail.data = urllib.urlopen(video.thumbnail.url).read()
@ -151,4 +155,21 @@ class YoutubeBackend(BaseBackend, ICapVideo):
self._set_video_url(video) self._set_video_url(video)
return video return video
def iter_resources(self, objs, split_path):
if BaseVideo in objs:
collection = self.get_collection(objs, split_path)
if collection.path_level == 0:
yield self.get_collection(objs, [u'latest'])
if collection.split_path == [u'latest']:
for video in self.latest_videos():
yield video
def validate_collection(self, objs, collection):
if collection.path_level == 0:
return
if BaseVideo in objs and collection.split_path == [u'latest']:
collection.title = u'Latest YouTube videos'
return
raise CollectionNotFound(collection.split_path)
OBJECTS = {YoutubeVideo: fill_video} OBJECTS = {YoutubeVideo: fill_video}

View file

@ -19,11 +19,13 @@
from weboob.tools.test import BackendTest from weboob.tools.test import BackendTest
from weboob.capabilities.video import BaseVideo
class YoutubeTest(BackendTest): class YoutubeTest(BackendTest):
BACKEND = 'youtube' BACKEND = 'youtube'
def test_youtube(self): def test_search(self):
l = list(self.backend.search_videos('lol')) l = list(self.backend.search_videos('lol'))
self.assertTrue(len(l) > 0) self.assertTrue(len(l) > 0)
v = l[0] v = l[0]
@ -31,3 +33,7 @@ class YoutubeTest(BackendTest):
self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url)) self.assertTrue(v.url and v.url.startswith('http://'), 'URL for video "%s" not found: %s' % (v.id, v.url))
assert self.backend.get_video(v.shorturl) assert self.backend.get_video(v.shorturl)
self.backend.browser.openurl(v.url) self.backend.browser.openurl(v.url)
def test_latest(self):
l = list(self.backend.iter_resources([BaseVideo], [u'latest']))
assert len(l) > 0

View file

@ -25,7 +25,7 @@ from re import search, sub
from weboob.tools.application.repl import ReplApplication from weboob.tools.application.repl import ReplApplication
from weboob.capabilities.base import NotLoaded from weboob.capabilities.base import NotLoaded
from weboob.capabilities.gallery import ICapGallery from weboob.capabilities.gallery import ICapGallery, BaseGallery, BaseImage
from weboob.tools.application.formatters.iformatter import IFormatter from weboob.tools.application.formatters.iformatter import IFormatter
@ -60,22 +60,23 @@ class Galleroob(ReplApplication):
DESCRIPTION = 'galleroob browses and downloads web image galleries' DESCRIPTION = 'galleroob browses and downloads web image galleries'
CAPS = ICapGallery CAPS = ICapGallery
EXTRA_FORMATTERS = {'gallery_list': GalleryListFormatter} EXTRA_FORMATTERS = {'gallery_list': GalleryListFormatter}
COMMANDS_FORMATTERS = {'search': 'gallery_list'} COMMANDS_FORMATTERS = {'search': 'gallery_list', 'ls': 'gallery_list'}
COLLECTION_OBJECTS = (BaseGallery, BaseImage, )
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
ReplApplication.__init__(self, *args, **kwargs) ReplApplication.__init__(self, *args, **kwargs)
def do_search(self, pattern=None): def do_search(self, pattern):
""" """
search PATTERN search PATTERN
List galleries matching a PATTERN. List galleries matching a PATTERN.
If PATTERN is not given, the command will list all the galleries
""" """
if not pattern:
print >>sys.stderr, 'This command takes an argument: %s' % self.get_command_help('search', short=True)
return 2
self.set_formatter_header(u'Search pattern: %s' % self.set_formatter_header(u'Search pattern: %s' % pattern)
pattern if pattern else u'Latest galleries')
for backend, gallery in self.do('search_gallery', for backend, gallery in self.do('search_gallery',
pattern=pattern, max_results=self.options.count): pattern=pattern, max_results=self.options.count):
self.add_object(gallery) self.add_object(gallery)

View file

@ -94,7 +94,7 @@ class Videoob(ReplApplication):
_id, dest = self.parse_command_args(line, 2, 1) _id, dest = self.parse_command_args(line, 2, 1)
video = self.get_object(_id, 'get_video', ['url']) video = self.get_object(_id, 'get_video', ['url'])
if not video: if not video:
print >>sys.stderr, 'Video not found: %s' % _id print >>sys.stderr, 'Video not found: %s' % _id
return 3 return 3
if not video.url: if not video.url:
@ -109,7 +109,6 @@ class Videoob(ReplApplication):
return False return False
return True return True
if dest is None: if dest is None:
ext = video.ext ext = video.ext
if not ext: if not ext:
@ -148,7 +147,7 @@ class Videoob(ReplApplication):
video = self.get_object(_id, 'get_video', ['url']) video = self.get_object(_id, 'get_video', ['url'])
if not video: if not video:
print >>sys.stderr, 'Video not found: %s' % _id print >>sys.stderr, 'Video not found: %s' % _id
return 3 return 3
if not video.url: if not video.url:
print >>sys.stderr, 'Error: the direct URL is not available.' print >>sys.stderr, 'Error: the direct URL is not available.'
@ -179,7 +178,7 @@ class Videoob(ReplApplication):
video = self.get_object(_id, 'get_video') video = self.get_object(_id, 'get_video')
if not video: if not video:
print >>sys.stderr, 'Video not found: %s' % _id print >>sys.stderr, 'Video not found: %s' % _id
return 3 return 3
self.format(video) self.format(video)
self.flush() self.flush()
@ -207,22 +206,17 @@ class Videoob(ReplApplication):
else: else:
print "on" if self.nsfw else "off" print "on" if self.nsfw else "off"
def do_search(self, pattern=None): def do_search(self, pattern):
""" """
search [PATTERN] search PATTERN
Search for videos matching a PATTERN. Search for videos matching a PATTERN.
If PATTERN is not given, this command will search for the latest videos.
""" """
if len(self.enabled_backends) == 0: if not pattern:
if self.interactive: print >>sys.stderr, 'This command takes an argument: %s' % self.get_command_help('search', short=True)
print >>sys.stderr, 'No backend loaded. Please use the "backends" command.' return 2
else:
print >>sys.stderr, 'No backend loaded.'
return 1
self.set_formatter_header(u'Search pattern: %s' % pattern if pattern else u'Latest videos') self.set_formatter_header(u'Search pattern: %s' % pattern)
self.change_path([u'search']) self.change_path([u'search'])
for backend, video in self.do('search_videos', pattern=pattern, nsfw=self.nsfw, for backend, video in self.do('search_videos', pattern=pattern, nsfw=self.nsfw,
max_results=self.options.count): max_results=self.options.count):

View file

@ -39,8 +39,8 @@ class BaseGallery(CapBaseObject):
self.add_field('description', basestring) self.add_field('description', basestring)
self.add_field('cardinality', int) self.add_field('cardinality', int)
self.add_field('date', datetime, date) self.add_field('date', datetime, date)
self.add_field('rating', (int,long,float), rating) self.add_field('rating', (int, long, float), rating)
self.add_field('rating_max', (int,long,float), rating_max) self.add_field('rating_max', (int, long, float), rating_max)
self.add_field('thumbnail', Thumbnail, thumbnail) self.add_field('thumbnail', Thumbnail, thumbnail)
@classmethod @classmethod
@ -55,13 +55,14 @@ class BaseGallery(CapBaseObject):
def iter_image(self): def iter_image(self):
raise NotImplementedError() raise NotImplementedError()
class BaseImage(CapBaseObject): class BaseImage(CapBaseObject):
def __init__(self, _id, index=None, thumbnail=NotLoaded, url=NotLoaded, def __init__(self, _id, index=None, thumbnail=NotLoaded, url=NotLoaded,
ext=NotLoaded, gallery=None): ext=NotLoaded, gallery=None):
CapBaseObject.__init__(self, unicode(_id)) CapBaseObject.__init__(self, unicode(_id))
self.add_field('index', int, index) # usually page number self.add_field('index', int, index) # usually page number
self.add_field('thumbnail', Thumbnail, thumbnail) self.add_field('thumbnail', Thumbnail, thumbnail)
self.add_field('url', basestring, url) self.add_field('url', basestring, url)
self.add_field('ext', basestring, ext) self.add_field('ext', basestring, ext)
@ -77,6 +78,7 @@ class BaseImage(CapBaseObject):
def __iscomplete__(self): def __iscomplete__(self):
return self.data is not NotLoaded return self.data is not NotLoaded
class ICapGallery(IBaseCap): class ICapGallery(IBaseCap):
""" """
This capability represents the ability for a website backend to provide videos. This capability represents the ability for a website backend to provide videos.
@ -86,10 +88,9 @@ class ICapGallery(IBaseCap):
SEARCH_VIEWS, SEARCH_VIEWS,
SEARCH_DATE) = range(4) SEARCH_DATE) = range(4)
def search_gallery(self, pattern=None, sortby=SEARCH_RELEVANCE, max_results=None): def search_gallery(self, pattern, sortby=SEARCH_RELEVANCE, max_results=None):
""" """
Iter results of a search on a pattern. Note that if pattern is None, Iter results of a search on a pattern.
it get the latest videos.
@param pattern [str] pattern to search on @param pattern [str] pattern to search on
@param sortby [enum] sort by... @param sortby [enum] sort by...

View file

@ -66,10 +66,9 @@ class ICapVideo(IBaseCap):
SEARCH_VIEWS, SEARCH_VIEWS,
SEARCH_DATE) = range(4) SEARCH_DATE) = range(4)
def search_videos(self, pattern=None, sortby=SEARCH_RELEVANCE, nsfw=False, max_results=None): def search_videos(self, pattern, sortby=SEARCH_RELEVANCE, nsfw=False, max_results=None):
""" """
Iter results of a search on a pattern. Note that if pattern is None, Iter results of a search on a pattern.
it get the latest videos.
@param pattern [str] pattern to search on @param pattern [str] pattern to search on
@param sortby [enum] sort by... @param sortby [enum] sort by...