diff --git a/contrib/plugin.video.videoobmc/addon.xml b/contrib/plugin.video.videoobmc/addon.xml
new file mode 100644
index 00000000..820a844c
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/addon.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ video
+
+
+ linux
+
+ Plugin for Videoob
+
+ [B]Videoob[/B] is an application able to handle videos on supported websites. More information available on http://videoob.org/.
+
+ [B]Videoob[/B] est une application qui permet de récupérer des vidéos depuis divers sites. Pour plus d'informations à ce sujet, n'hésitez pas à visiter le site : http://videoob.org/
+
+
+
diff --git a/contrib/plugin.video.videoobmc/changelog.txt b/contrib/plugin.video.videoobmc/changelog.txt
new file mode 100644
index 00000000..f70f3cc5
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/changelog.txt
@@ -0,0 +1,8 @@
+[B]Dependance :[B]
+- weboob (http://weboob.org/install)
+
+[B]Version 0.1.0[/B]
+-Call weboob directly
+
+[B]Version 0.0.1[/B]
+-First try
diff --git a/contrib/plugin.video.videoobmc/default.py b/contrib/plugin.video.videoobmc/default.py
new file mode 100644
index 00000000..de04e623
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/default.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+import sys
+import resources.lib.base.common_xbmc as common_xbmc
+import resources.lib.constants as constants
+from resources.lib.actions import actions
+
+# Plugin constants
+version = "0.1.0"
+plugin = "videoobmc" + version
+addon_id = "plugin.video.videoobmc"
+author = "Bezleputh"
+mail = "carton_ben@yahoo.fr"
+
+#import lxml.html import Element
+#print Element.__file__
+
+#TODO gestion du logger, gestion des modules via XBMC (activation/desactivation)
+
+#Bug encodge des categories
+#corriger version 1 pour que v2 et v1 donctionnent
+
+if (__name__ == "__main__"):
+ if not (sys.argv[2]):
+ actions[constants.DISPLAY_MENU]()._do()
+ else:
+ params = common_xbmc.parse_params(sys.argv[2])
+ action = params.get("action")
+ if (action):
+ actions[action]()._do(params)
+ else:
+ common_xbmc.display_error(" ARGV Nothing done.. verify params " + repr(params))
diff --git a/contrib/plugin.video.videoobmc/default_test.py b/contrib/plugin.video.videoobmc/default_test.py
new file mode 100755
index 00000000..f045c825
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/default_test.py
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import sys
+import resources.lib.test.common_test as common_xbmc
+import resources.lib.constants as constants
+
+from resources.lib.actions import actions
+
+print sys.argv
+if len(sys.argv) < 2:
+ actions[constants.DISPLAY_MENU]()._do()
+else:
+ params = common_xbmc.parse_params(sys.argv[1])
+ #print params
+ action = params.get("action")
+ if (action):
+ actions[action]()._do(params)
+ else:
+ common_xbmc.display_error(" ARGV Nothing done.. verify params " + repr(params))
diff --git a/contrib/plugin.video.videoobmc/icon.png b/contrib/plugin.video.videoobmc/icon.png
new file mode 100644
index 00000000..03846cae
Binary files /dev/null and b/contrib/plugin.video.videoobmc/icon.png differ
diff --git a/contrib/plugin.video.videoobmc/resources/language/english/strings.xml b/contrib/plugin.video.videoobmc/resources/language/english/strings.xml
new file mode 100644
index 00000000..f5f6e83a
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/language/english/strings.xml
@@ -0,0 +1,23 @@
+
+
+
+ Search
+ Search:
+
+ Download
+ Information
+
+ Error!
+
+ Information
+ Download started
+ Download succeed
+
+ Download folder:
+ Number of videos per backends:
+ Display Non Safe For Work videos:
+ Enable debug mode:
+ Update weboob backends
+ Start updating weboob backends
+ Weboob backends successfully updated
+
diff --git a/contrib/plugin.video.videoobmc/resources/language/french/strings.xml b/contrib/plugin.video.videoobmc/resources/language/french/strings.xml
new file mode 100644
index 00000000..09c8d746
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/language/french/strings.xml
@@ -0,0 +1,23 @@
+
+
+
+ Recherche
+ Recherche:
+
+ Télécharger
+ Information
+
+ Erreur!
+
+ Information
+ Lancement du téléchargement
+ Fichier téléchargé avec succès
+
+ Répertoire de Téléchargement:
+ Nombre de vidéos par backends:
+ Afficher les vidéos interdites aux moins de 18 ans :
+ Enable debug mode :
+ Mise à jour des modules weboob
+ Debut de la mise à jour
+ Weboob est maintenant à jour
+
diff --git a/contrib/plugin.video.videoobmc/resources/lib/__init__.py b/contrib/plugin.video.videoobmc/resources/lib/__init__.py
new file mode 100644
index 00000000..ee074ac5
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/__init__.py
@@ -0,0 +1 @@
+# Dummy file to make this directory a package.
diff --git a/contrib/plugin.video.videoobmc/resources/lib/actions.py b/contrib/plugin.video.videoobmc/resources/lib/actions.py
new file mode 100644
index 00000000..4cb029ba
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/actions.py
@@ -0,0 +1,108 @@
+# -*- coding: utf-8 -*-
+import sys
+import constants
+
+from base.actions import BaseAction
+from menu import MenuItem, MenuItemVideo, MenuItemPath
+from threading import Thread
+from videoobmc2 import Videoobmc
+
+if hasattr(sys.modules["__main__"], "common_xbmc"):
+ common_xbmc = sys.modules["__main__"].common_xbmc
+else:
+ import common_xbmc
+
+
+class VideoobBaseAction(BaseAction):
+ def __init__(self):
+ count = common_xbmc.get_settings('nbVideoPerBackend')
+ numbers = ["10", "25", "50", "100"]
+ self.videoobmc = Videoobmc(count=numbers[int(count)], nsfw=common_xbmc.get_settings('nsfw'))
+
+
+class DisplayMenuAction(VideoobBaseAction):
+ def _do(self, param={}):
+ backends = self.videoobmc.backends
+ if backends:
+ MenuItem(common_xbmc.get_translation('30000'), constants.SEARCH).add_to_menu()
+ for backend in backends:
+ icon = self.videoobmc.get_backend_icon(backend)
+ MenuItem(backend, constants.DISPLAY_BACKENDS, backend=backend, iconimage=icon).add_to_menu()
+ common_xbmc.end_of_directory(False)
+ else:
+ common_xbmc.display_error(" Please install and configure weboob")
+
+
+class DisplayCollectionMenuAction(VideoobBaseAction):
+ def _do(self, param={}):
+ path = param.get('path') if 'path' in param.keys() else ''
+ collections, videos = self.videoobmc.ls(param.get('backend'), path=path)
+ threads = []
+
+ for col in collections:
+ MenuItemPath(col).add_to_menu()
+ for video in videos:
+ aThread = Thread(target=self.add_videos, args=(video, video.backend))
+ threads.append(aThread)
+ aThread.start()
+
+ for t in threads:
+ t.join()
+
+ common_xbmc.end_of_directory(False)
+
+ def add_videos(self, _video, backend):
+ print _video
+ video = self.videoobmc.get_video(_video, backend)
+ if video:
+ MenuItemVideo(video).add_to_menu()
+
+
+class DownloadAction(VideoobBaseAction):
+ def _do(self, param={}):
+ _id = param.get('id')
+ backend = param.get('backend')
+ if _id:
+ aThread = Thread(target=self.download, args=(_id, backend))
+ aThread.start()
+ common_xbmc.display_info(common_xbmc.get_translation('30301'))
+ common_xbmc.end_of_directory(False)
+
+ def download(self, _id, backend):
+ dl_dir = common_xbmc.get_settings('downloadPath')
+ self.videoobmc.download(_id, dl_dir if dl_dir else common_xbmc.get_addon_dir(), backend)
+ common_xbmc.display_info(common_xbmc.get_translation('30302'))
+
+
+class SearchAction(VideoobBaseAction):
+ def _do(self, param={}):
+ pattern = common_xbmc.ask_user('', common_xbmc.get_translation('30001'))
+ if pattern:
+ for video in self.videoobmc.search(pattern, param.get('backend')):
+ MenuItemVideo(video).add_to_menu()
+ common_xbmc.end_of_directory(False)
+
+
+class DisplayBackendsAction(VideoobBaseAction):
+ def _do(self, param={}):
+ backend = param.get('backend')
+ if backend:
+ MenuItem('Search', constants.SEARCH, backend=backend).add_to_menu()
+ DisplayCollectionMenuAction()._do(param)
+ else:
+ common_xbmc.end_of_directory(False)
+
+
+class UpdateWeboobAction(VideoobBaseAction):
+ def _do(self, param={}):
+ common_xbmc.display_info(common_xbmc.get_translation('30551'))
+ self.videoobmc.update()
+ common_xbmc.display_info(common_xbmc.get_translation('30552'))
+
+
+actions = {constants.DISPLAY_MENU: DisplayMenuAction,
+ constants.DISPLAY_COLLECTION_MENU: DisplayCollectionMenuAction,
+ constants.SEARCH: SearchAction,
+ constants.DOWNLOAD: DownloadAction,
+ constants.DISPLAY_BACKENDS: DisplayBackendsAction,
+ constants.UPDATE: UpdateWeboobAction}
diff --git a/contrib/plugin.video.videoobmc/resources/lib/base/__init__.py b/contrib/plugin.video.videoobmc/resources/lib/base/__init__.py
new file mode 100644
index 00000000..ee074ac5
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/base/__init__.py
@@ -0,0 +1 @@
+# Dummy file to make this directory a package.
diff --git a/contrib/plugin.video.videoobmc/resources/lib/base/actions.py b/contrib/plugin.video.videoobmc/resources/lib/base/actions.py
new file mode 100644
index 00000000..470da7d3
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/base/actions.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+from abc import ABCMeta, abstractmethod
+
+
+class BaseAction():
+ __metaclass__ = ABCMeta
+
+ @abstractmethod
+ def _do(self, param=None):
+ """
+ Overload this method in application type subclass
+ if you want to associate an action to the menu
+ """
+ pass
+
+actions = {}
diff --git a/contrib/plugin.video.videoobmc/resources/lib/base/common_xbmc.py b/contrib/plugin.video.videoobmc/resources/lib/base/common_xbmc.py
new file mode 100644
index 00000000..1835ca75
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/base/common_xbmc.py
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+
+import xbmc
+import xbmcgui
+import xbmcplugin
+import xbmcaddon
+
+import urllib
+import sys
+
+from traceback import print_exc
+
+
+def get_addon():
+ if hasattr(sys.modules["__main__"], "addon_id"):
+ _id = sys.modules["__main__"].addon_id
+ return xbmcaddon.Addon(id=_id)
+
+
+def get_translation(key):
+ addon = get_addon()
+ if addon:
+ return addon.getLocalizedString(int(key))
+
+
+def get_settings(key):
+ addon = get_addon()
+ if addon:
+ return addon.getSetting(key)
+
+
+def get_addon_dir():
+ addon = get_addon()
+ if addon:
+ addonDir = addon.getAddonInfo("path")
+ else:
+ addonDir = xbmc.translatePath("special://profile/addon_data/")
+
+ return addonDir
+
+
+def display_error(msg):
+ xbmc.executebuiltin("XBMC.Notification(%s, %s)" % (get_translation('30200').decode('utf-8'), msg))
+ print msg
+ print_exc(msg)
+
+
+def display_info(msg):
+ xbmc.executebuiltin("XBMC.Notification(%s, %s, 3000, DefaultFolder.png)" % (get_translation('30300').encode('utf-8'),
+ msg.encode('utf-8')))
+ #print msg
+ print_exc()
+
+
+def parse_params(param_str):
+ param_dic = {}
+ # Parameters are on the 3rd arg passed to the script
+ param_str = sys.argv[2]
+ if len(param_str) > 1:
+ param_str = param_str.replace('?', '')
+
+ # Ignore last char if it is a '/'
+ if param_str[len(param_str) - 1] == '/':
+ param_str = param_str[0:len(param_str) - 2]
+
+ # Processing each parameter splited on '&'
+ for param in param_str.split('&'):
+ try:
+ # Spliting couple key/value
+ key, value = param.split('=')
+ except:
+ key = param
+ value = ''
+
+ key = urllib.unquote_plus(key)
+ value = urllib.unquote_plus(value)
+
+ # Filling dictionnary
+ param_dic[key] = value
+
+ return param_dic
+
+
+def ask_user(content, title):
+ keyboard = xbmc.Keyboard(content, title)
+ keyboard.doModal()
+ if keyboard.isConfirmed() and keyboard.getText():
+ return keyboard.getText()
+ return ""
+
+
+def create_param_url(param_dic, quote_plus=False):
+ """
+ Create an plugin URL based on the key/value passed in a dictionary
+ """
+ url = sys.argv[0]
+ sep = '?'
+
+ try:
+ for param in param_dic:
+ if quote_plus:
+ url = url + sep + urllib.quote_plus(param) + '=' + urllib.quote_plus(param_dic[param])
+ else:
+ url = "%s%s%s=%s" % (url, sep, param, param_dic[param])
+
+ sep = '&'
+ except Exception, msg:
+ display_error("create_param_url %s" % msg)
+ url = None
+ return url
+
+
+def create_list_item(name, itemInfoType="Video", itemInfoLabels=None, iconimage="DefaultFolder.png",
+ c_items=None, isPlayable=False):
+ lstItem = xbmcgui.ListItem(label=name, iconImage=iconimage, thumbnailImage=iconimage)
+
+ if c_items:
+ lstItem.addContextMenuItems(c_items, replaceItems=True)
+
+ if itemInfoLabels:
+ iLabels = itemInfoLabels
+ else:
+ iLabels = {"Title": name, }
+
+ lstItem.setInfo(type=itemInfoType, infoLabels=iLabels)
+ if isPlayable:
+ lstItem.setProperty('IsPlayable', "true")
+
+ return lstItem
+
+
+def add_menu_item(params={}):
+ url = create_param_url(params)
+ if params.get('name'):
+ if params.get('iconimage'):
+ lstItem = create_list_item(params.get('name'), iconimage=params.get('iconimage'))
+ else:
+ lstItem = create_list_item(params.get('name'))
+ xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url, listitem=lstItem, isFolder=True)
+ else:
+ display_error('add_menu_item : Fail to add item to menu')
+
+
+def add_menu_link(params={}):
+ if params.get('name') and params.get('iconimage') and params.get('url') and \
+ params.get('itemInfoLabels') and params.get('c_items'):
+ url = params.get('url')
+ lstItem = create_list_item(params.get('name'), iconimage=params.get('iconimage'),
+ itemInfoLabels=params.get('itemInfoLabels'), c_items=params.get('c_items'),
+ isPlayable=True)
+ xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]), url=url, listitem=lstItem)
+ else:
+ display_error('add_menu_link : Fail to add item to menu')
+
+
+def end_of_directory(update=False):
+ xbmcplugin.endOfDirectory(handle=int(sys.argv[1]), succeeded=True, updateListing=update) # , cacheToDisc=True)
diff --git a/contrib/plugin.video.videoobmc/resources/lib/base/menu.py b/contrib/plugin.video.videoobmc/resources/lib/base/menu.py
new file mode 100644
index 00000000..4add6315
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/base/menu.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+import sys
+
+if hasattr(sys.modules["__main__"], "common_xbmc"):
+ common_xbmc = sys.modules["__main__"].common_xbmc
+else:
+ import common_xbmc
+
+
+class BaseMenuItem():
+
+ def __init__(self, name, action, iconimage="DefaultFolder.png"):
+ self.params = {}
+ self.params['name'] = name
+ self.params['action'] = action
+ self.params['iconimage'] = iconimage
+
+ def get(self, element):
+ return self.params[element]
+
+ def add_to_menu(self):
+ common_xbmc.add_menu_item(self.params)
+
+
+class BaseMenuLink(BaseMenuItem):
+
+ def __init__(self, name, url, action, iconimage="DefaultFolder.png"):
+ BaseMenuItem.__init__(self, name, action, iconimage)
+ self.params["url"] = url
+
+ def createVideoContextMenu(self):
+ return ""
+
+ def create_info_labels(self):
+ return ""
+
+ def add_to_menu(self):
+ self.params["itemInfoLabels"] = self.create_info_labels()
+ self.params["c_items"] = self.createVideoContextMenu()
+ common_xbmc.add_menu_link(self.params)
diff --git a/contrib/plugin.video.videoobmc/resources/lib/base/weboobmc.py b/contrib/plugin.video.videoobmc/resources/lib/base/weboobmc.py
new file mode 100644
index 00000000..d1247594
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/base/weboobmc.py
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import sys
+import os
+import re
+import subprocess
+import simplejson as json
+
+if hasattr(sys.modules["__main__"], "common_xbmc"):
+ common_xbmc = sys.modules["__main__"].common_xbmc
+else:
+ import common_xbmc
+
+
+class Weboobmc():
+ def __init__(self, count=10):
+ self.count = count
+
+ def update(self):
+ #weboob-config update
+ self._call_weboob('weboob-config', 'update')
+
+ def _call_weboob(self, application, command, options={}, argument=""):
+ options['-n'] = self.count
+ _opt = " ".join(["%s %s " % (k, v) for k, v in options.items()])
+ _cmd = "%s %s %s %s" % (application, _opt, command, argument)
+ #print _cmd.encode('utf-8')
+ return subprocess.check_output(_cmd, shell=True)
+
+ def _json_call_weboob(self, application, command, options={}, argument=""):
+ options['-f'] = 'json'
+ try:
+ result = self._call_weboob(application, command, options, argument)
+ m = re.search(r"(\[{.+\}])", result)
+ if m:
+ result = u'%s' % m.group(1)
+ #print result
+ return json.loads(result) if result else []
+ except subprocess.CalledProcessError as e:
+ common_xbmc.display_error(" Error while calling weboob : %s " % e)
+
+ def get_loaded_backends(self, caps):
+ #weboob-config list ICapVideo -f json
+ backends = self._json_call_weboob('weboob-config', 'list', argument=caps)
+ for backend in backends:
+ if "_enabled=0" not in backend['Configuration']:
+ yield backend['Name'] # , self.get_backend_icon(backend['Module'])
+
+ def get_backend_icon(self, module):
+ if 'WEBOOB_WORKDIR' in os.environ:
+ datadir = os.environ.get('WEBOOB_WORKDIR')
+ else:
+ datadir = os.path.join(os.environ.get('XDG_DATA_HOME',
+ os.path.join(os.path.expanduser('~'), '.local', 'share')
+ ), 'weboob')
+ icons_dir = os.path.join(datadir, 'icons')
+
+ return os.path.join(icons_dir, '%s.png' % module)
+
+ def is_category(self, obj):
+ return 'split_path' in obj.keys()
diff --git a/contrib/plugin.video.videoobmc/resources/lib/base/weboobmc2.py b/contrib/plugin.video.videoobmc/resources/lib/base/weboobmc2.py
new file mode 100644
index 00000000..4ec65fb1
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/base/weboobmc2.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from weboob.tools.application.base import BaseApplication
+import os
+import re
+import subprocess
+
+
+class Weboobmc(BaseApplication):
+ def __init__(self, count=10):
+ BaseApplication.__init__(self)
+ self.count = int(count)
+ self._is_default_count = False
+
+ def update(self):
+ self.weboob.update()
+
+ def get_backend_icon(self, module):
+ minfo = self.weboob.repositories.get_module_info(module)
+ return self.weboob.repositories.get_module_icon_path(minfo)
+
+ def obj_to_filename(self, obj, dest=None, default=None):
+ """
+ This method can be used to get a filename from an object, using a mask
+ filled by information of this object.
+ All patterns are braces-enclosed, and are name of available fields in
+ the object.
+ :param obj: object type obj: BaseObject param dest: dest given by user (default None)
+ type dest: str param default: default file mask (if not given, this is
+ :'{id}-{title}.{ext}') type default: str rtype: str
+ """
+
+ if default is None:
+ default = '{id}-{title}.{ext}'
+ if dest is None:
+ dest = '.'
+ if os.path.isdir(dest):
+ dest = os.path.join(dest, default)
+
+ def repl(m):
+ field = m.group(1)
+ if hasattr(obj, field):
+ return re.sub('[?:/]', '-', '%s' % getattr(obj, field))
+ else:
+ return m.group(0)
+
+ return re.sub(r'\{(.+?)\}', repl, dest)
+
+ def download_obj(self, obj, dest):
+
+ def check_exec(executable):
+ with open('/dev/null', 'w') as devnull:
+ process = subprocess.Popen(['which', executable], stdout=devnull)
+ if process.wait() != 0:
+ print 'Please install "%s"' % executable
+ return False
+ return True
+
+ dest = self.obj_to_filename(obj, dest)
+ if obj.url.startswith('rtmp'):
+ if not check_exec('rtmpdump'):
+ return 1
+ args = ('rtmpdump', '-e', '-r', obj.url, '-o', dest)
+ elif obj.url.startswith('mms'):
+ if not check_exec('mimms'):
+ return 1
+ args = ('mimms', '-r', obj.url, dest)
+ elif u'm3u8' == obj.ext:
+ _dest, _ = os.path.splitext(dest)
+ dest = u'%s.%s' % (_dest, 'mp4')
+ args = ('wget',) + tuple(line for line in self.read_url(obj.url) if not line.startswith('#')) + ('-O', dest)
+ else:
+ if check_exec('wget'):
+ args = ('wget', '-c', obj.url, '-O', dest)
+ elif check_exec('curl'):
+ args = ('curl', '-C', '-', obj.url, '-o', dest)
+ else:
+ return 1
+ os.spawnlp(os.P_WAIT, args[0], *args)
diff --git a/contrib/plugin.video.videoobmc/resources/lib/constants.py b/contrib/plugin.video.videoobmc/resources/lib/constants.py
new file mode 100644
index 00000000..f74b91cf
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/constants.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+
+DISPLAY_MENU = "display_menu"
+DISPLAY_COLLECTION_MENU = "display_collection_menu"
+DISPLAY_BACKENDS = "display_backends"
+
+SEARCH = "search"
+VIDEO = "video"
+DOWNLOAD = "download"
+UPDATE = "update"
diff --git a/contrib/plugin.video.videoobmc/resources/lib/menu.py b/contrib/plugin.video.videoobmc/resources/lib/menu.py
new file mode 100644
index 00000000..8f3d3e5c
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/menu.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+import sys
+import constants
+
+from datetime import datetime, timedelta
+from base.menu import BaseMenuItem, BaseMenuLink
+
+if hasattr(sys.modules["__main__"], "common_xbmc"):
+ common_xbmc = sys.modules["__main__"].common_xbmc
+else:
+ import common_xbmc
+
+
+class MenuItem(BaseMenuItem):
+ params = {}
+
+ def __init__(self, name, action, iconimage="DefaultFolder.png", backend=''):
+ BaseMenuItem.__init__(self, name, action, iconimage)
+ self.params['backend'] = backend
+
+
+class MenuItemPath(MenuItem):
+
+ def __init__(self, collection, action=constants.DISPLAY_COLLECTION_MENU, iconimage="DefaultFolder.png"):
+ MenuItem.__init__(self, collection.title, action, iconimage, collection.fullid.split('@')[-1])
+ self.params["path"] = '/'.join(collection.split_path)
+
+
+class MenuItemVideo(BaseMenuLink):
+ def __init__(self, video, iconimage="DefaultFolder.png"):
+ name = '[%s] %s' % (video.backend, video.title)
+ BaseMenuLink.__init__(self, name, video.url, constants.VIDEO,
+ video.thumbnail.url if video.thumbnail.url else iconimage)
+ self.video = video
+ self.params["id"] = self.video.id
+
+ def createVideoContextMenu(self):
+ cm = []
+
+ #Information
+ cm.append((common_xbmc.get_translation('30110'), "XBMC.Action(Info)"))
+
+ #Téléchargement
+ url = "%s?action=%s&id=%s&backend=%s" % (sys.argv[0], constants.DOWNLOAD, self.video.id, self.video.backend)
+ cm.append((common_xbmc.get_translation('30100'), "XBMC.PlayMedia(%s)" % (url)))
+
+ return cm
+
+ def create_info_labels(self):
+ date, year = self.format_date(self.video.date)
+
+ duration = 0
+ if self.video.duration:
+ duration = u'%s' % str(self.video.duration.total_seconds()/60) if isinstance(self.video.duration, timedelta) else self.video.duration
+
+ description = u'%s' % self.video.description
+
+ return {"Title": self.video.title,
+ "Year": year,
+ "Plot": description,
+ "PlotOutline": description[0:30] if len(description) > 30 else description,
+ "Director": self.video.author if self.video.author else 'Unknown',
+ "Duration": duration,
+ "Date": date}
+
+ def format_date(self, video_date):
+ date = datetime.now().strftime("%d/%m/%Y")
+ if video_date:
+ date = video_date.strftime("%d/%m/%Y")
+
+ year = date.split('/')[-1]
+ return date, year
diff --git a/contrib/plugin.video.videoobmc/resources/lib/test/__init__.py b/contrib/plugin.video.videoobmc/resources/lib/test/__init__.py
new file mode 100644
index 00000000..ee074ac5
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/test/__init__.py
@@ -0,0 +1 @@
+# Dummy file to make this directory a package.
diff --git a/contrib/plugin.video.videoobmc/resources/lib/test/common_test.py b/contrib/plugin.video.videoobmc/resources/lib/test/common_test.py
new file mode 100644
index 00000000..112cc496
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/test/common_test.py
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+
+import urllib
+
+
+def get_addon():
+ pass
+
+
+def get_translation(key):
+ translation = {'30000': 'Recherche',
+ '30001': 'Recherche :',
+ '30100': 'Télécharger',
+ '30110': 'Information',
+ '30200': 'Erreur!',
+ '30300': 'Information',
+ '30301': 'Lancement du téléchargement',
+ '30302': 'Fichier téléchargé avec succès',
+ '30551': 'Debut de la mise à jour',
+ '30552': 'Weboob est maintenant à jour'}
+ return translation.get(key)
+
+
+def get_addon_dir():
+ return '/home/benjamin'
+
+
+def get_settings(key):
+ settings = {'downloadPath': get_addon_dir(),
+ 'nbVideoPerBackend': '0',
+ 'nsfw': 'False'}
+ return settings.get(key)
+
+
+def display_error(error):
+ print "%s: %s" % ("ERROR", error)
+
+
+def display_info(msg):
+ print "%s: %s" % ("INFO", msg)
+
+
+def parse_params(paramStr):
+
+ paramDic = {}
+ # Parameters are on the 3rd arg passed to the script
+ if len(paramStr) > 1:
+ paramStr = paramStr.replace('?', '')
+
+ # Ignore last char if it is a '/'
+ if paramStr[len(paramStr) - 1] == '/':
+ paramStr = paramStr[0:len(paramStr) - 2]
+
+ # Processing each parameter splited on '&'
+ for param in paramStr.split('&'):
+ try:
+ # Spliting couple key/value
+ key, value = param.split('=')
+ except:
+ key = param
+ value = ''
+
+ key = urllib.unquote_plus(key)
+ value = urllib.unquote_plus(value)
+
+ # Filling dictionnary
+ paramDic[key] = value
+ return paramDic
+
+
+def ask_user(content, title):
+ return raw_input(title)
+
+
+def create_param_url(paramsDic, quote_plus=False):
+
+ #url = sys.argv[0]
+ url = ''
+ sep = '?'
+
+ try:
+ for param in paramsDic:
+ if quote_plus:
+ url = url + sep + urllib.quote_plus(param) + '=' + urllib.quote_plus(paramsDic[param])
+ else:
+ url = "%s%s%s=%s" % (url, sep, param, paramsDic[param])
+
+ sep = '&'
+ except Exception, msg:
+ display_error("create_param_url %s" % msg)
+ url = None
+ return url
+
+
+def add_menu_item(params={}):
+ print '%s => "%s"' % (params.get('name'), create_param_url(params))
+
+
+def add_menu_link(params={}):
+ print '[%s] %s (%s)' % (params.get('id'), params.get('name'), params.get('url'))
+ #print params.get('itemInfoLabels')
+ #print params.get('c_items')
+
+
+def end_of_directory(update=False):
+ print '******************************************************'
+
+
+def download_video(url, name, dir='./'):
+ print 'Downlaod a video %s from %s' % (name, url)
diff --git a/contrib/plugin.video.videoobmc/resources/lib/videoobmc.py b/contrib/plugin.video.videoobmc/resources/lib/videoobmc.py
new file mode 100644
index 00000000..da5c995b
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/videoobmc.py
@@ -0,0 +1,94 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import time
+
+from datetime import timedelta, datetime
+from .base.weboobmc import Weboobmc
+from weboob.capabilities.video import BaseVideo
+from weboob.capabilities.image import BaseImage
+from weboob.capabilities.collection import Collection
+
+class Videoobmc(Weboobmc):
+ def __init__(self, count=10, nsfw=False):
+ Weboobmc.__init__(self, count=count)
+ self.backends =list(self.get_loaded_backends('CapVideo'))
+ _nsfw = 'on' if nsfw else 'off'
+ self._call_weboob('videoob', 'nsfw', argument=_nsfw)
+
+ def search(self, pattern, backend=''):
+ #videoob search pattern -f json
+ options = {'--select': 'id,title,date,description,author,duration,thumbnail,url'}
+ if backend:
+ options['-b'] = backend
+ _videos = self._json_call_weboob('videoob', 'search', argument=pattern, options=options)
+ if _videos:
+ for _video in _videos:
+ yield self.create_video_from_json(_video)
+
+ def create_video_from_json(self, _video):
+ video = BaseVideo()
+ video.id = u'%s' % _video['id']
+ video.backend = u'%s' % _video['id'].split('@')[-1]
+
+ if 'url' in _video.keys():
+ video.url = u'%s' % _video['url']
+
+ if 'thumbnail' in _video.keys() and _video['thumbnail'] and 'url' in _video['thumbnail'].keys():
+ video.thumbnail = BaseImage()
+ video.thumbnail.url = u'%s' % _video['thumbnail']['url']
+ else:
+ video.thumbnail.url = u''
+ video.title = u'%s' % _video['title']
+
+ if _video['date']:
+
+ try:
+ datetime.strptime(_video['date'].split('.')[0], '%Y-%m-%d %H:%M:%S')
+ except TypeError:
+ datetime(*(time.strptime(_video['date'].split('.')[0], '%Y-%m-%d %H:%M:%S')[0:6]))
+
+ video.description = u'%s' % _video['description']
+ video.author = u'%s' % _video['author']
+
+ if _video['duration']:
+ _duration = _video['duration'].split(':')
+ video.duration = timedelta(hours=int(_duration[0]), minutes=int(_duration[1]), seconds=int(_duration[2]))
+
+ return video
+
+ def get_video(self, video, backend):
+ #videoob info _id -f json
+ _video = self._json_call_weboob('videoob', 'info', argument=video.id)
+ if _video and len(_video) > 0:
+ return self.create_video_from_json(_video[0])
+
+ def ls(self, backend, path=''):
+ options = {'-b': backend}
+ result = self._json_call_weboob('videoob', 'ls', options=options, argument=path)
+ return self.separate_collections_and_videos(result)
+
+ def separate_collections_and_videos(self, objs):
+ videos = []
+ categories = []
+ for obj in objs:
+ if self.is_category(obj):
+ categories.append(self.create_category_from_json(obj))
+ else:
+ video = BaseVideo()
+ video.id = obj['id'].split('@')[0]
+ video.backend = obj['id'].split('@')[-1]
+ videos.append(video)
+ return categories, videos
+
+ def create_category_from_json(self, obj):
+ collection = Collection(obj['split_path'].split('/'))
+ collection.title = obj['title']
+ collection.id = obj['id'].split('@')[0]
+ collection.backend = obj['id'].split('@')[1]
+ return collection
+
+ def download(self, _id, path, backend):
+ #videoob download _id path
+ options = {'-b': backend}
+ self._call_weboob('videoob', 'download', options=options, argument=u'%s %s' % (_id, path))
diff --git a/contrib/plugin.video.videoobmc/resources/lib/videoobmc.py b/contrib/plugin.video.videoobmc/resources/lib/videoobmc.py
new file mode 100644
index 00000000..73fcfd15
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/videoobmc.py
@@ -0,0 +1,93 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import time
+
+from datetime import timedelta, datetime
+from .base.weboobmc import Weboobmc
+from weboob.capabilities.video import BaseVideo
+from weboob.capabilities.image import BaseImage
+from weboob.capabilities.collection import Collection
+
+class Videoobmc(Weboobmc):
+ def __init__(self, count=10, nsfw=False):
+ Weboobmc.__init__(self, count=count)
+ self.backends =list(self.get_loaded_backends('CapVideo'))
+ _nsfw = 'on' if nsfw else 'off'
+ self._call_weboob('videoob', 'nsfw', argument=_nsfw)
+
+ def search(self, pattern, backend=''):
+ #videoob search pattern -f json
+ options = {'--select': 'id,title,date,description,author,duration,thumbnail,url'}
+ if backend:
+ options['-b'] = backend
+ _videos = self._json_call_weboob('videoob', 'search', argument=pattern, options=options)
+ if _videos:
+ for _video in _videos:
+ yield self.create_video_from_json(_video)
+
+ def create_video_from_json(self, _video):
+ video = BaseVideo()
+ video.id = u'%s' % _video['id']
+ print video.id
+ print _video['id']
+ video.backend = u'%s' % _video['id'].split('@')[-1]
+
+ if 'url' in _video.keys():
+ video.url = u'%s' % _video['url']
+
+ if 'thumbnail' in _video.keys() and _video['thumbnail'] and 'url' in _video['thumbnail'].keys():
+ video.thumbnail = BaseImage()
+ video.thumbnail.url = u'%s' % _video['thumbnail']['url']
+ else:
+ video.thumbnail.url = u''
+ video.title = u'%s' % _video['title']
+
+ if _video['date']:
+
+ try:
+ video.date = datetime.strptime(_video['date'].split('.')[0], '%Y-%m-%d %H:%M:%S')
+ except TypeError:
+ video.date = datetime(*(time.strptime(_video['date'].split('.')[0], '%Y-%m-%d %H:%M:%S')[0:6]))
+
+ video.description = u'%s' % _video['description']
+ video.author = u'%s' % _video['author']
+
+ if _video['duration']:
+ _duration = _video['duration'].split(':')
+ video.duration = timedelta(hours=int(_duration[0]), minutes=int(_duration[1]), seconds=int(_duration[2]))
+
+ return video
+
+ def get_video(self, _id, backend):
+ #videoob info _id -f json
+ _video = self._json_call_weboob('videoob', 'info', argument=_id)
+ if _video and len(_video) > 0:
+ return self.create_video_from_json(_video[0])
+
+ def ls(self, backend, path=''):
+ options = {'-b': backend}
+ result = self._json_call_weboob('videoob', 'ls', options=options, argument=path)
+ return self.separate_collections_and_videos(result)
+
+ def separate_collections_and_videos(self, objs):
+ videos = []
+ categories = []
+ for obj in objs:
+ if self.is_category(obj):
+ categories.append(self.create_category_from_json(obj))
+ else:
+ #videos.append(self.get_video(obj['id']))
+ videos.append(self.create_video_from_json(obj))
+ return categories, videos
+
+ def create_category_from_json(self, obj):
+ collection = Collection(obj['split_path'].split('/'))
+ collection.title = obj['title']
+ collection.id = obj['id'].split('@')[0]
+ collection.backend = obj['id'].split('@')[1]
+ return collection
+
+ def download(self, _id, path):
+ #videoob download _id path
+ self._call_weboob('videoob', 'download', argument=u'%s %s' % (_id, path))
diff --git a/contrib/plugin.video.videoobmc/resources/lib/videoobmc2.py b/contrib/plugin.video.videoobmc/resources/lib/videoobmc2.py
new file mode 100644
index 00000000..1f98ff76
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/lib/videoobmc2.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+from .base.weboobmc2 import Weboobmc
+from weboob.capabilities.video import BaseVideo, CapVideo
+from weboob.capabilities.collection import CapCollection, Collection
+
+
+class Videoobmc(Weboobmc):
+ def __init__(self, count=10, nsfw=False):
+ Weboobmc.__init__(self, count=count)
+ self.backends = self.weboob.load_backends(CapVideo)
+ self.nsfw = nsfw
+
+ def search(self, pattern, backend=''):
+ kwargs = {'pattern': pattern,
+ 'nsfw': self.nsfw,
+ 'backends': backend}
+
+ fields = ['id', 'title', 'date', 'description', 'author', 'duration', 'thumbnail', 'url']
+ try:
+ for _backend, video in self.weboob.do(self._do_complete, self.count, fields, 'search_videos', **kwargs):
+ yield video
+ except Exception as e:
+ print e
+
+ def get_video(self, video, _backend):
+ backend = self.weboob.get_backend(_backend)
+ fields = ['id', 'title', 'date', 'description', 'author', 'duration', 'thumbnail', 'url']
+ return backend.fillobj(video, fields)
+
+ def ls(self, backend, path=''):
+ kwargs = {'split_path': path.split('/') if path else [],
+ 'caps': CapCollection,
+ 'objs': (BaseVideo, ),
+ 'backends': backend}
+ fields = [] # ['id', 'title', 'date', 'description', 'author', 'duration', 'thumbnail', 'url']
+ result = self.weboob.do(self._do_complete, self.count, fields, 'iter_resources', **kwargs)
+ return self.separate_collections_and_videos(result)
+
+ def separate_collections_and_videos(self, objs):
+ videos = []
+ categories = []
+ for backend, obj in objs:
+ if isinstance(obj, Collection):
+ categories.append(obj)
+ else:
+ videos.append(obj)
+ return categories, videos
+
+ def download(self, _id, dest, backend):
+ for backend, _video in self.weboob.do('get_video', _id, backends=backend):
+ self.download_obj(_video, dest)
diff --git a/contrib/plugin.video.videoobmc/resources/settings.xml b/contrib/plugin.video.videoobmc/resources/settings.xml
new file mode 100644
index 00000000..8a760d36
--- /dev/null
+++ b/contrib/plugin.video.videoobmc/resources/settings.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+