From d3f0064e285fb2f5527758a775efbe13d421b3c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D0=BE=D1=80=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=A0=D0=BE?= =?UTF-8?q?=D0=BC=D0=B0=D0=BD?= Date: Sat, 12 Mar 2022 22:34:42 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B0=D0=B4=D0=B0=D0=BF=D1=82=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=BF=D0=BE=D0=B4=20Kodi=2019=20=D0=B8=20=D0=B8?= =?UTF-8?q?=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B0=D0=B2?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8=20VK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- addon.xml | 3 +- default.py | 788 +++++++++++++++----------- resources/language/English/strings.po | 4 + resources/language/Russian/strings.po | 4 + 4 files changed, 474 insertions(+), 325 deletions(-) diff --git a/addon.xml b/addon.xml index b21149a..5479d38 100644 --- a/addon.xml +++ b/addon.xml @@ -1,8 +1,9 @@ - + + image video diff --git a/default.py b/default.py index 4165571..b0b041a 100644 --- a/default.py +++ b/default.py @@ -1,23 +1,28 @@ # -*- coding: utf-8 -*- +from __future__ import absolute_import, division, unicode_literals import sys, os, vk, time, pickle, binascii +from vk.exceptions import VkAPIError +from vk.api import Session, AuthSession from math import ceil import xbmc, xbmcplugin, xbmcaddon, xbmcgui -import urlparse -import urllib2 -from urllib import urlencode +import urllib.parse +import urllib.request, urllib.error, urllib.parse +from urllib.parse import urlencode +from urllib.request import urlopen +import simplejson as json import re _VERSION = '1.2.5' -_ADDON_NAME = 'kodi-vk.inpos.ru' -_addon = xbmcaddon.Addon(id = _ADDON_NAME) -_addon_id = int(sys.argv[1]) -_addon_url = sys.argv[0] -_addon_path = _addon.getAddonInfo('path').decode('utf-8') +_ADDON_NAME = 'kodi-vk.inpos.ru' +_addon = xbmcaddon.Addon(id=_ADDON_NAME) +_addon_id = int(sys.argv[1]) +_addon_url = sys.argv[0] +_addon_path = _addon.getAddonInfo('path') _APP_ID = '4353740' -_SCOPE = 'friends,photos,audio,video,groups,messages,offline' - +_APP_SEC = 'GRDdDhHJ8qzyPQczrwqC' +_SCOPE = 'friends,photos,audio,video,groups,messages,offline' _SETTINGS_ID_TOKEN = 'vk_token' _SETTINGS_ID_MAX_RES = 'video_resolution' @@ -30,11 +35,15 @@ _SETTINGS_BOOL = {'true': 1, 'false': 0} _SETTINGS_INV_BOOL = {'true': 0, 'false': 1} _SETTINGS_PAGE_ITEMS = int(_addon.getSetting(_SETTINGS_ID_LIST_LEN)) +# _SETTINGS_PAGE_ITEMS = 50 _SETTINGS_MAX_RES = int(_addon.getSetting(_SETTINGS_ID_MAX_RES)) +# _SETTINGS_MAX_RES = 1080 _SETTINGS_VIDEO_SEARCH_SORT = int(_addon.getSetting(_SETTINGS_ID_VIDEO_SEARCH_SORT)) +# _SETTINGS_VIDEO_SEARCH_SORT = 0 _SETTINGS_VIDEO_SEARCH_HD = _SETTINGS_BOOL[_addon.getSetting(_SETTINGS_ID_VIDEO_SEARCH_HD)] +# _SETTINGS_VIDEO_SEARCH_HD = False _SETTINGS_VIDEO_SEARCH_ADULT = _SETTINGS_INV_BOOL[_addon.getSetting(_SETTINGS_ID_VIDEO_SEARCH_ADULT)] - +# _SETTINGS_VIDEO_SEARCH_ADULT = True _FILE_VIDEO_SEARCH_HISTORY = _ADDON_NAME + '_vsh.pkl' _FILE_GROUP_SEARCH_HISTORY = _ADDON_NAME + '_gsh.pkl' @@ -81,9 +90,9 @@ _VK_VIDEO_SOURCE = 'vk_video' _YOUTUBE_VIDEO_SOURCE = 'youtube_video' _UNKNOWN_VIDEO_SOURCE = 'unknown_video' - DELAY = 1.0 / 3 # 3 запроса в секунду + # Служебные классы class APIMethod(object): __slots__ = ['conn', '_method_name'] @@ -91,23 +100,28 @@ class APIMethod(object): def __init__(self, conn, method_name): self.conn = conn self._method_name = method_name + def __getattr__(self, method_name): return APIMethod(self.conn, self._method_name + '.' + method_name) def __call__(self, **method_kwargs): return self.conn(self._method_name, **method_kwargs) + class Connection(object): - '''Соединяемся с сайтом''' - def __init__(self, app_id, username = None, password = None, access_token = None, scope = ''): - if access_token: - session = vk.api.Session(access_token = access_token) + """Соединяемся с сайтом""" + + def __init__(self, app_id, username=None, password=None, access_token=None, scope=''): + if access_token is not None: + session = Session(access_token=access_token) else: - session = vk.api.AuthSession(app_id, username, password, scope = scope) + session = AuthSession(app_id, username, password, scope=scope) self.conn = vk.API(session) self.last_request = 0.0 + def __getattr__(self, method_name): return APIMethod(self, method_name) + def __call__(self, method_name, **method_kwargs): # Ограничение 3 запроса в секунду delay = DELAY - (time.time() - self.last_request) @@ -118,19 +132,23 @@ class Connection(object): self.last_request = time.time() return res + class Group(object): - '''Группа''' + """Группа""" + def __init__(self, gid, conn): self.conn = conn self.id = gid self.info = {} + def set_info(self): - self.info = self.conn.groups.getById(group_id = int(self.id) * -1)[0] - def members(self, page_items = _SETTINGS_PAGE_ITEMS, page = 1): - m = self.conn.groups.getMembers(group_id = self.id, - offset = ((page_items * page) - page_items), - fields = 'first_name,last_name,photo_50,photo_100,photo_200', - count = page_items) + self.info = self.conn.groups.getById(group_id=int(self.id) * -1)[0] + + def members(self, page_items=_SETTINGS_PAGE_ITEMS, page=1): + m = self.conn.groups.getMembers(group_id=self.id, + offset=((page_items * page) - page_items), + fields='first_name,last_name,photo_50,photo_100,photo_200', + count=page_items) count = m['count'] pages = ceil(float(count) / float(page_items)) l = [] @@ -140,42 +158,47 @@ class Group(object): l.append(member) return {'pages': pages, 'total': count, 'items': l} + # Благодарю автора статьи https://habrahabr.ru/post/193374/ def switch_view(): skin_used = xbmc.getSkinDir() if skin_used == 'skin.confluence': - xbmc.executebuiltin('Container.SetViewMode(500)') # Вид "Эскизы". + xbmc.executebuiltin('Container.SetViewMode(500)') # Вид "Эскизы". elif skin_used == 'skin.aeon.nox': - xbmc.executebuiltin('Container.SetViewMode(512)') # Вид "Инфо-стена" + xbmc.executebuiltin('Container.SetViewMode(512)') # Вид "Инфо-стена" + def get_search_history(h_file_name): - path = os.path.join(xbmc.translatePath('special://temp/').decode('utf-8'), h_file_name.decode('utf-8')) + path = os.path.join(xbmc.translatePath('special://temp/'), h_file_name) if not os.path.exists(path): return [] with open(path, 'rb') as f: history = pickle.load(f) return history + def put_search_history(history, h_file_name): - path = os.path.join(xbmc.translatePath('special://temp/').decode('utf-8'), h_file_name.decode('utf-8')) + path = os.path.join(xbmc.translatePath('special://temp/'), h_file_name) with open(path, 'wb') as f: pickle.dump(history, f, -1) + def media_entries(e_method, conn, oid, **kwargs): page_items = kwargs.pop('page_items', _SETTINGS_PAGE_ITEMS) page = kwargs.pop('page', 1) album = kwargs.pop('album', None) kwargs.update({ - 'offset': ((page_items * page) - page_items), - 'count': page_items - }) + 'offset': ((page_items * page) - page_items), + 'count': page_items + }) if oid != _NO_OWNER: kwargs['owner_id'] = oid - if album: kwargs['album_id'] = album + if album: + kwargs['album_id'] = album try: entries = getattr(conn, e_method)(**kwargs) - except vk.exceptions.VkAPIError, e: - if e.code == 15 or (e.code >= 200 and e.code < 300): + except VkAPIError as exc: + if exc.code == 15 or (200 <= exc.code < 300): entries = {'count': 0, 'items': []} else: raise @@ -187,44 +210,50 @@ def media_entries(e_method, conn, oid, **kwargs): entry_id = str(i['id']) else: entry_id = str(i['owner_id']) + '_' + str(i['id']) - e = Entry(e_method, entry_id, conn) - e.info = i - l.append(e) + ent = Entry(e_method, entry_id, conn) + ent.info = i + l.append(ent) del entries['count'] del entries['items'] res = {'pages': pages, 'total': count, 'items': l} - for k in entries.keys(): + for k in list(entries.keys()): res[k] = entries[k] return res + class Entry(object): def __init__(self, e_method, eid, conn): self.method = e_method self.id = eid self.conn = conn self.info = {} + def set_info(self): if self.method == 'video.get': - self.info = self.conn.video.get(videos = self.id)['items'][0] + self.info = self.conn.video.get(videos=self.id)['items'][0] elif self.method == 'audio.get': - self.info = self.conn.audio.getById(audios = self.id)['items'][0] + self.info = self.conn.audio.getById(audios=self.id)['items'][0] elif self.method == 'photos.get': - self.info = self.conn.photos.getById(photos = self.id)['items'][0] + self.info = self.conn.photos.getById(photos=self.id)['items'][0] + class User(object): - '''Этот класс описывает свойства и методы пользователя.''' + """Этот класс описывает свойства и методы пользователя.""" + def __init__(self, uid, conn): self.conn = conn self.id = uid self.info = {} + def set_info(self): - self.info = self.conn.users.get(user_id = self.id, fields = 'first_name,last_name,photo_50,photo_100,photo_200')[0] - def friends(self, page_items = _SETTINGS_PAGE_ITEMS, page = 1, order = 'hints'): - f = self.conn.friends.get(user_id = self.id, - offset = ((page_items * page) - page_items), - count = page_items, - fields = 'first_name,last_name,photo_50,photo_100,photo_200', - order = order) + self.info = self.conn.users.get(user_id=self.id, fields='first_name,last_name,photo_50,photo_100,photo_200')[0] + + def friends(self, page_items=_SETTINGS_PAGE_ITEMS, page=1, order='hints'): + f = self.conn.friends.get(user_id=self.id, + offset=((page_items * page) - page_items), + count=page_items, + fields='first_name,last_name,photo_50,photo_100,photo_200', + order=order) count = f['count'] pages = ceil(float(count) / float(page_items)) l = [] @@ -233,11 +262,12 @@ class User(object): u.info = i l.append(u) return {'pages': pages, 'total': count, 'items': l} - def user_search(self, q = '', page_items = _SETTINGS_PAGE_ITEMS, page = 1): - usr = self.conn.users.search(q = q, - offset = ((page_items * page) - page_items), - count = page_items, - fields = 'first_name,last_name,photo_50,photo_100,photo_200') + + def user_search(self, q='', page_items=_SETTINGS_PAGE_ITEMS, page=1): + usr = self.conn.users.search(q=q, + offset=((page_items * page) - page_items), + count=page_items, + fields='first_name,last_name,photo_50,photo_100,photo_200') count = usr['count'] pages = ceil(float(count) / float(page_items)) l = [] @@ -246,24 +276,12 @@ class User(object): u.info = i l.append(u) return {'pages': pages, 'total': count, 'items': l} - def groups(self, page_items = _SETTINGS_PAGE_ITEMS, page = 1): - gr = self.conn.groups.get(user_id = self.id, - offset = ((page_items * page) - page_items), - count = page_items, - extended = 1) - count = gr['count'] - pages = ceil(float(count) / float(page_items)) - l = [] - for i in gr['items']: - if i['is_closed'] > 0 and i['is_member'] == 0: continue - g = Group(i['id'], self.conn) - g.info = i - l.append(g) - return {'pages': pages, 'total': count, 'items': l} - def group_search(self, q = '', page_items = _SETTINGS_PAGE_ITEMS, page = 1): - gr = self.conn.groups.search(q = q, - offset = ((page_items * page) - page_items), - count = page_items) + + def groups(self, page_items=_SETTINGS_PAGE_ITEMS, page=1): + gr = self.conn.groups.get(user_id=self.id, + offset=((page_items * page) - page_items), + count=page_items, + extended=1) count = gr['count'] pages = ceil(float(count) / float(page_items)) l = [] @@ -274,47 +292,65 @@ class User(object): l.append(g) return {'pages': pages, 'total': count, 'items': l} + def group_search(self, q='', page_items=_SETTINGS_PAGE_ITEMS, page=1): + gr = self.conn.groups.search(q=q, + offset=((page_items * page) - page_items), + count=page_items) + count = gr['count'] + pages = ceil(float(count) / float(page_items)) + l = [] + for i in gr['items']: + if i['is_closed'] > 0 and i['is_member'] == 0: continue + g = Group(i['id'], self.conn) + g.info = i + l.append(g) + return {'pages': pages, 'total': count, 'items': l} + + class KodiVKGUIFave(object): def __init__(self, root): self.root = root - def _main_fave(self): + + def m_main_fave(self): if self.root.c_type == _CTYPE_VIDEO: - self.root.add_folder(self.root.gui._string(400502), {'do': _DO_FAVE_VIDEO, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400502), {'do': _DO_FAVE_VIDEO, 'page': 1}) elif self.root.c_type == _CTYPE_IMAGE: - self.root.add_folder(self.root.gui._string(400504), {'do': _DO_FAVE_PHOTO, 'page': 1}) - self.root.add_folder(self.root.gui._string(400513), {'do': _DO_FAVE_USERS, 'page': 1}) - self.root.add_folder(self.root.gui._string(400506), {'do': _DO_FAVE_GROUPS, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400504), {'do': _DO_FAVE_PHOTO, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400513), {'do': _DO_FAVE_USERS, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400506), {'do': _DO_FAVE_GROUPS, 'page': 1}) xbmcplugin.endOfDirectory(_addon_id) - def _video(self): + + def m_video(self): page = int(self.root.params['page']) kwargs = {'page': page, 'extended': 1} vids = media_entries('fave.getVideos', self.root.conn, _NO_OWNER, **kwargs) if page < vids['pages']: params = {'do': _DO_FAVE_VIDEO, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) for v in vids['items']: list_item = xbmcgui.ListItem(v.info['title']) list_item.setInfo('video', { - 'title' : v.info['title'], - 'duration' : int(v.info['duration']), - 'plot' : v.info['description'] - } + 'title': v.info['title'], + 'duration': int(v.info['duration']), + 'plot': v.info['description'] + } ) - p_key = 'photo_%d' % (max(map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), v.info.keys()))),) + p_key = 'photo_%d' % ( + max([int(x.split('_')[1]) for x in [x for x in list(v.info.keys()) if x.startswith('photo_')]]),) list_item.setArt({'thumb': v.info['photo_130'], 'icon': v.info['photo_130'], 'fanart': v.info[p_key]}) list_item.setProperty('IsPlayable', 'true') - if 'files' in v.info.keys(): + if 'files' in list(v.info.keys()): if 'external' in v.info['files']: - v_source = self.root.gui.videos._get_video_source(v.info['files']['external']) + v_source = self.root.gui.videos.m_get_video_source(v.info['files']['external']) else: v_source = _VK_VIDEO_SOURCE else: - v_source = self.root.gui.videos._get_video_source(v.info['player']) + v_source = self.root.gui.videos.m_get_video_source(v.info['player']) if v_source == _VK_VIDEO_SOURCE: params = {'do': _DO_PLAY_VIDEO, 'vid': v.id, 'source': _VK_VIDEO_SOURCE} url = self.root.url(**params) elif v_source == _YOUTUBE_VIDEO_SOURCE: - if 'files' in v.info.keys(): + if 'files' in list(v.info.keys()): y_url = v.info['files']['external'] else: y_url = v.info['player'] @@ -324,108 +360,116 @@ class KodiVKGUIFave(object): xbmc.log('WARN: Unknown youtube url: %s' % (y_url,)) continue y_id = sr[0][1] - url = u'plugin://plugin.video.youtube/?action=play_video&videoid=' + y_id + url = 'plugin://plugin.video.youtube/?action=play_video&videoid=' + y_id else: continue - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = False) + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=False) if page < vids['pages']: params = {'do': _DO_FAVE_VIDEO, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def _photo(self): + + def m_photo(self): page = int(self.root.params['page']) kwargs = {'page': page} photos = media_entries('photos.getAll', self.root.conn, _NO_OWNER, **kwargs) if page < photos['pages']: params = {'do': _DO_FAVE_PHOTO, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) for index in range(len(photos['items'])): p = photos['items'][index] num = (_SETTINGS_PAGE_ITEMS * page) + index + 1 list_item = xbmcgui.ListItem('%04d' % (num,)) p_info = { - 'title' : '%04d' % (num,), - 'tagline' : p.info['text'] - } - if 'width' in p.info.keys(): p_info['exif:resolution'] = '%d,%d' % (p.info['width'], p.info['height']) + 'title': '%04d' % (num,), + 'tagline': p.info['text'] + } + if 'width' in list(p.info.keys()): p_info['exif:resolution'] = '%d,%d' % (p.info['width'], p.info['height']) list_item.setInfo('pictures', p_info) list_item.setArt({'thumb': p.info['photo_130'], 'icon': p.info['photo_75']}) - r = map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), p.info.keys())) + r = [int(x.split('_')[1]) for x in [x for x in list(p.info.keys()) if x.startswith('photo_')]] ### Здесь надо подумать над настройкой url_key = max(r) url = p.info['photo_%d' % (url_key,)] - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = False) + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=False) if page < photos['pages']: params = {'do': _DO_FAVE_PHOTO, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) switch_view() - def _users(self): + + def m_users(self): page = int(self.root.params['page']) - users = media_entries('fave.getUsers', self.root.conn, _NO_OWNER, page = page) + users = media_entries('fave.getUsers', self.root.conn, _NO_OWNER, page=page) if page < users['pages']: params = {'do': _DO_FAVE_USERS, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) for u in users['items']: - list_item = xbmcgui.ListItem(u'%s %s' % (u.info['last_name'], u.info['first_name'])) - #p_key = 'photo_%d' % (max(map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), m.info.keys()))),) - #list_item.setArt({'thumb': m.info[p_key], 'icon': m.info[p_key]}) + list_item = xbmcgui.ListItem('%s %s' % (u.info['last_name'], u.info['first_name'])) + # p_key = 'photo_%d' % (max(map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), m.info.keys()))),) + # list_item.setArt({'thumb': m.info[p_key], 'icon': m.info[p_key]}) params = {'do': _DO_HOME, 'oid': u.id} url = self.root.url(**params) - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = True) + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=True) if page < users['pages']: params = {'do': _DO_FAVE_USERS, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def _groups(self): + + def m_groups(self): page = int(self.root.params['page']) - links = media_entries('fave.getLinks', self.root.conn, _NO_OWNER, page = page) + links = media_entries('fave.getLinks', self.root.conn, _NO_OWNER, page=page) if page < links['pages']: params = {'do': _DO_FAVE_GROUPS, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) for l in links['items']: l_id = l.info['id'].split('_') if l_id[0] == '2': list_item = xbmcgui.ListItem(l.info['title']) - p_key = 'photo_%d' % (max(map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), l.info.keys()))),) + p_key = 'photo_%d' % ( + max([int(x.split('_')[1]) for x in [x for x in list(l.info.keys()) if x.startswith('photo_')]]),) list_item.setArt({'thumb': l.info[p_key], 'icon': l.info[p_key]}) params = {'do': _DO_HOME, 'oid': -int(l_id[-1])} url = self.root.url(**params) - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = True) + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=True) if page < links['pages']: params = {'do': _DO_FAVE_GROUPS, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) + class KodiVKGUIPhotos(object): def __init__(self, root): self.root = root - def _main_photo(self): + + def m_main_photo(self): oid = self.root.params['oid'] - self.root.add_folder(self.root.gui._string(400508), {'do': _DO_PHOTO, 'oid': oid, 'page': 1}) - self.root.add_folder(self.root.gui._string(400511), {'do': _DO_PHOTO_ALBUMS, 'oid': oid, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400508), {'do': _DO_PHOTO, 'oid': oid, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400511), {'do': _DO_PHOTO_ALBUMS, 'oid': oid, 'page': 1}) xbmcplugin.endOfDirectory(_addon_id) - def _photo_albums(self): + + def m_photo_albums(self): page = int(self.root.params['page']) oid = self.root.params['oid'] kwargs = {'page': page, 'need_covers': 1, 'need_system': 1} albums = media_entries('photos.getAlbums', self.root.conn, oid, **kwargs) if page < albums['pages']: - params = {'do': _DO_PHOTO_ALBUMS,'oid': oid,'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + params = {'do': _DO_PHOTO_ALBUMS, 'oid': oid, 'page': page + 1} + self.root.add_folder(self.root.gui.m_string(400602), params) for a in albums['items']: list_item = xbmcgui.ListItem(a.info['title']) list_item.setInfo('pictures', {'title': a.info['title']}) list_item.setArt({'thumb': a.info['thumb_src'], 'icon': a.info['thumb_src']}) params = {'do': _DO_PHOTO, 'oid': oid, 'album': a.id, 'page': 1} url = self.root.url(**params) - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = True) + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=True) if page < albums['pages']: - params = {'do': _DO_PHOTO_ALBUMS,'oid': oid,'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + params = {'do': _DO_PHOTO_ALBUMS, 'oid': oid, 'page': page + 1} + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) switch_view() - def _photo(self): + + def m_photo(self): page = int(self.root.params['page']) oid = self.root.params['oid'] album = self.root.params.get('album', None) @@ -436,51 +480,54 @@ class KodiVKGUIPhotos(object): else: photos = media_entries('photos.getAll', self.root.conn, oid, **kwargs) if page < photos['pages']: - params = {'do': _DO_PHOTO,'oid': oid,'page': page + 1} + params = {'do': _DO_PHOTO, 'oid': oid, 'page': page + 1} if album: params['album'] = album - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) for index in range(len(photos['items'])): p = photos['items'][index] num = (_SETTINGS_PAGE_ITEMS * (page - 1)) + index + 1 list_item = xbmcgui.ListItem('%04d' % (num,)) p_info = { - 'title' : '%04d' % (num,), - 'tagline' : p.info['text'] - } - if 'width' in p.info.keys(): p_info['exif:resolution'] = '%d,%d' % (p.info['width'], p.info['height']) + 'title': '%04d' % (num,), + 'tagline': p.info['text'] + } + if 'width' in list(p.info.keys()): p_info['exif:resolution'] = '%d,%d' % (p.info['width'], p.info['height']) list_item.setInfo('pictures', p_info) list_item.setArt({'thumb': p.info['photo_130'], 'icon': p.info['photo_75']}) - r = map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), p.info.keys())) - ### Здесь надо подумать над настройкой + r = [int(x.split('_')[1]) for x in [x for x in list(p.info.keys()) if x.startswith('photo_')]] + # Здесь надо подумать над настройкой url_key = max(r) url = p.info['photo_%d' % (url_key,)] - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = False) + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=False) if page < photos['pages']: - params = {'do': _DO_PHOTO,'oid': oid,'page': page + 1} + params = {'do': _DO_PHOTO, 'oid': oid, 'page': page + 1} if album: params['album'] = album - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) switch_view() + class KodiVKGUIVideos(object): def __init__(self, root): self.root = root - def _get_video_source(self, v_url): + + def m_get_video_source(self, v_url): is_vk_url_re = re.compile('https?\:\/\/[^\/]*vk.com\/.*') is_youtube_url_re = re.compile('https\:\/\/www.youtube.com\/.*') if len(is_vk_url_re.findall(v_url)) > 0: return _VK_VIDEO_SOURCE if len(is_youtube_url_re.findall(v_url)) > 0: return _YOUTUBE_VIDEO_SOURCE return _UNKNOWN_VIDEO_SOURCE - def _main_video_search(self): + + def m_main_video_search(self): page = int(self.root.params['page']) - self.root.add_folder(self.root.gui._string(400516), {'do': _DO_VIDEO_SEARCH, 'q':'none', 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400516), {'do': _DO_VIDEO_SEARCH, 'q': 'none', 'page': 1}) history = get_search_history(_FILE_VIDEO_SEARCH_HISTORY) count = len(history) pages = int(ceil(count / float(_SETTINGS_PAGE_ITEMS))) if page < pages: params = {'do': _DO_MAIN_VIDEO_SEARCH, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) - h_start = _SETTINGS_PAGE_ITEMS * (page -1) + self.root.add_folder(self.root.gui.m_string(400602), params) + h_start = _SETTINGS_PAGE_ITEMS * (page - 1) h_end = h_start + _SETTINGS_PAGE_ITEMS history = history[h_start:h_end] for h in history: @@ -488,23 +535,24 @@ class KodiVKGUIVideos(object): list_item = xbmcgui.ListItem(h) params = {'do': _DO_VIDEO_SEARCH, 'q': query_hex, 'page': 1} url = self.root.url(**params) - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = True) + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=True) if page < pages: params = {'do': _DO_MAIN_VIDEO_SEARCH, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def _video_search(self): + + def m_video_search(self): page = int(self.root.params['page']) q = self.root.params['q'] if q == 'none': s_win = xbmc.Keyboard() - s_win.setHeading(self.root.gui._string(400515)) + s_win.setHeading(self.root.gui.m_string(400515)) s_win.setHiddenInput(False) s_win.doModal() if s_win.isConfirmed(): q = s_win.getText() else: - self.root.gui.notify(self.root.gui._string(400525), '') + self.root.gui.notify(self.root.gui.m_string(400525), '') return else: q = pickle.loads(binascii.unhexlify(q)) @@ -517,64 +565,66 @@ class KodiVKGUIVideos(object): put_search_history(history, _FILE_VIDEO_SEARCH_HISTORY) query_hex = binascii.hexlify(pickle.dumps(q, -1)) kwargs = { - 'page': page, - 'sort': _SETTINGS_VIDEO_SEARCH_SORT, - 'hd' : _SETTINGS_VIDEO_SEARCH_HD, - 'adult': _SETTINGS_VIDEO_SEARCH_ADULT, - 'q': q, - 'extended': 1 - } + 'page': page, + 'sort': _SETTINGS_VIDEO_SEARCH_SORT, + 'hd': _SETTINGS_VIDEO_SEARCH_HD, + 'adult': _SETTINGS_VIDEO_SEARCH_ADULT, + 'q': q, + 'extended': 1 + } search_res = media_entries('video.search', self.root.conn, _NO_OWNER, **kwargs) if page < search_res['pages']: params = {'do': _DO_VIDEO_SEARCH, 'q': query_hex, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) - self.__create_video_list_(search_res) + self.root.add_folder(self.root.gui.m_string(400602), params) + self.m__create_video_list_(search_res) if page < search_res['pages']: params = {'do': _DO_VIDEO_SEARCH, 'q': query_hex, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def _main_video(self): + + def m_main_video(self): oid = self.root.params['oid'] - self.root.add_folder(self.root.gui._string(400509), {'do': _DO_VIDEO, 'oid': oid, 'page': 1}) - self.root.add_folder(self.root.gui._string(400510), {'do': _DO_VIDEO_ALBUMS, 'oid': oid, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400509), {'do': _DO_VIDEO, 'oid': oid, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400510), {'do': _DO_VIDEO_ALBUMS, 'oid': oid, 'page': 1}) if int(oid) == self.root.u.id: - self.root.add_folder(self.root.gui._string(400515), {'do': _DO_MAIN_VIDEO_SEARCH, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400515), {'do': _DO_MAIN_VIDEO_SEARCH, 'page': 1}) xbmcplugin.endOfDirectory(_addon_id) - def __create_video_list_(self, vids): + + def m__create_video_list_(self, vids): for v in vids['items']: list_item = xbmcgui.ListItem(v.info['title']) oid = v.info['owner_id'] if int(oid) < 0: gid = oid * -1 - g = filter(lambda x: x['id'] == gid, vids['groups'])[0] - cm_title = u'%s [I]%s[/I]' % (self.root.gui._string(400604).decode('utf-8'), g['name']) + g = [x for x in vids['groups'] if x['id'] == gid][0] + cm_title = '%s [I]%s[/I]' % (self.root.gui.m_string(400604), g['name']) else: - u = filter(lambda x: x['id'] == oid, vids['profiles'])[0] - cm_title = u'%s [I]%s %s[/I]' % (self.root.gui._string(400603).decode('utf-8'), u['last_name'], u['first_name']) + u = [x for x in vids['profiles'] if x['id'] == oid][0] + cm_title = '%s [I]%s %s[/I]' % (self.root.gui.m_string(400603), u['last_name'], u['first_name']) cm_params = {'do': _DO_HOME, 'oid': oid} cm_url = self.root.url(**cm_params) list_item.addContextMenuItems([(cm_title, 'xbmc.Container.update(%s)' % (cm_url,))]) list_item.setInfo('video', { - 'title' : v.info['title'], - 'duration' : int(v.info['duration']), - 'plot' : v.info['description'] - } + 'title': v.info['title'], + 'duration': int(v.info['duration']), + 'plot': v.info['description'] + } ) - p_key = 'photo_%d' % (max(map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), v.info.keys()))),) + p_key = 'photo_%d' % (max([int(x.split('_')[1]) for x in [x for x in list(v.info.keys()) if x.startswith('photo_')]]),) list_item.setArt({'thumb': v.info['photo_130'], 'icon': v.info['photo_130'], 'fanart': v.info[p_key]}) list_item.setProperty('IsPlayable', 'true') - if 'files' in v.info.keys(): + if 'files' in list(v.info.keys()): if 'external' in v.info['files']: - v_source = self._get_video_source(v.info['files']['external']) + v_source = self.m_get_video_source(v.info['files']['external']) else: v_source = _VK_VIDEO_SOURCE else: - v_source = self._get_video_source(v.info['player']) + v_source = self.m_get_video_source(v.info['player']) if v_source == _VK_VIDEO_SOURCE: params = {'do': _DO_PLAY_VIDEO, 'vid': v.id, 'source': _VK_VIDEO_SOURCE} url = self.root.url(**params) elif v_source == _YOUTUBE_VIDEO_SOURCE: - if 'files' in v.info.keys(): + if 'files' in list(v.info.keys()): y_url = v.info['files']['external'] else: y_url = v.info['player'] @@ -584,34 +634,37 @@ class KodiVKGUIVideos(object): xbmc.log('WARN: Unknown youtube url: %s' % (y_url,)) continue y_id = sr[0][1] - url = u'plugin://plugin.video.youtube/?action=play_video&videoid=' + y_id + url = 'plugin://plugin.video.youtube/?action=play_video&videoid=' + y_id else: continue - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = False) - def _video_albums(self): + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=False) + + def m_video_albums(self): page = int(self.root.params['page']) oid = self.root.params['oid'] kwargs = { - 'page': page, - 'extended': 1 - } + 'page': page, + 'extended': 1 + } albums = media_entries('video.getAlbums', self.root.conn, oid, **kwargs) if page < albums['pages']: - params = {'do': _DO_VIDEO_ALBUMS,'oid': oid,'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + params = {'do': _DO_VIDEO_ALBUMS, 'oid': oid, 'page': page + 1} + self.root.add_folder(self.root.gui.m_string(400602), params) for a in albums['items']: list_item = xbmcgui.ListItem(a.info['title']) list_item.setInfo('video', {'title': a.info['title']}) - if 'photo_320' in a.info.keys(): - list_item.setArt({'thumb': a.info['photo_160'], 'icon': a.info['photo_160'], 'fanart': a.info['photo_320']}) + if 'photo_320' in list(a.info.keys()): + list_item.setArt( + {'thumb': a.info['photo_160'], 'icon': a.info['photo_160'], 'fanart': a.info['photo_320']}) params = {'do': _DO_VIDEO, 'oid': oid, 'album': a.id, 'page': 1} url = self.root.url(**params) - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = True) + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=True) if page < albums['pages']: - params = {'do': _DO_VIDEO_ALBUMS,'oid': oid,'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + params = {'do': _DO_VIDEO_ALBUMS, 'oid': oid, 'page': page + 1} + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def _video(self): + + def m_video(self): page = int(self.root.params['page']) oid = self.root.params['oid'] album = self.root.params.get('album', None) @@ -619,28 +672,29 @@ class KodiVKGUIVideos(object): if album: kwargs['album'] = album vids = media_entries('video.get', self.root.conn, oid, **kwargs) if page < vids['pages']: - params = {'do': _DO_VIDEO,'oid': oid,'page': page + 1} + params = {'do': _DO_VIDEO, 'oid': oid, 'page': page + 1} if album: params['album'] = album - self.root.add_folder(self.root.gui._string(400602), params) - self.__create_video_list_(vids) + self.root.add_folder(self.root.gui.m_string(400602), params) + self.m__create_video_list_(vids) if page < vids['pages']: - params = {'do': _DO_VIDEO,'oid': oid,'page': page + 1} + params = {'do': _DO_VIDEO, 'oid': oid, 'page': page + 1} if album: params['album'] = album - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def _play_video(self): + + def m_play_video(self): vid = self.root.params['vid'] src = self.root.params['source'] v = Entry('video.get', vid, self.root.conn) try: v.set_info() except: - self.root.gui.notify(self.root.gui._string(400524), '') + self.root.gui.notify(self.root.gui.m_string(400524), '') return - if 'files' in v.info.keys(): + if 'files' in list(v.info.keys()): paths = {} if src == _VK_VIDEO_SOURCE: - for k in v.info['files'].keys(): + for k in list(v.info['files'].keys()): if '_' not in k: try: local_idx = int(k) @@ -653,35 +707,40 @@ class KodiVKGUIVideos(object): v_url = v.info['player'] if src == _VK_VIDEO_SOURCE: paths = self.root.parse_vk_player_html(v_url) - ### Здесь должно браться разрешение из настроек - k = max(filter(lambda x: x <= _SETTINGS_MAX_RES, paths.keys())) + # Здесь должно браться разрешение из настроек + k = max([x for x in list(paths.keys()) if x <= _SETTINGS_MAX_RES]) path = paths[k] - play_item = xbmcgui.ListItem(path = path) - xbmcplugin.setResolvedUrl(_addon_id, True, listitem = play_item) + play_item = xbmcgui.ListItem(path=path) + xbmcplugin.setResolvedUrl(_addon_id, True, listitem=play_item) + class KodiVkGUI: - '''Окошки, диалоги, сообщения''' + """Окошки, диалоги, сообщения""" + def __init__(self, root): self.root = root self.photos = KodiVKGUIPhotos(self.root) self.videos = KodiVKGUIVideos(self.root) self.faves = KodiVKGUIFave(self.root) - def notify(self,title, msg): + + def notify(self, title, msg): dialog = xbmcgui.Dialog() dialog.notification(title, msg, xbmcgui.NOTIFICATION_WARNING, 3000) - def _string(self, string_id): - return _addon.getLocalizedString(string_id).encode('utf-8') - def _login_form(self): + + def m_string(self, string_id): + return _addon.getLocalizedString(string_id) + + def m_login_form(self): login_window = xbmc.Keyboard() - login_window.setHeading(self._string(400500)) + login_window.setHeading(self.m_string(400500)) login_window.setHiddenInput(False) login_window.setDefault(_addon.getSetting(_USERNAME)) login_window.doModal() if login_window.isConfirmed(): username = login_window.getText() password_window = xbmc.Keyboard() - password_window.setHeading(self._string(400501)) + password_window.setHeading(self.m_string(400501)) password_window.setHiddenInput(True) password_window.doModal() if password_window.isConfirmed(): @@ -690,7 +749,8 @@ class KodiVkGUI: raise Exception("Password input was cancelled.") else: raise Exception("Login input was cancelled.") - def _home(self): + + def m_home(self): c_type = self.root.params.get('content_type', None) oid = self.root.params['oid'] if not c_type: @@ -699,117 +759,126 @@ class KodiVkGUI: if int(oid) < 0: g = Group(oid, self.root.conn) g.set_info() - header_string = u'%s [I]%s[/I]' % (self._string(400604).decode('utf-8'), g.info['name']) - p_key = 'photo_%d' % (max(map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), g.info.keys()))),) + header_string = '%s [I]%s[/I]' % (self.m_string(400604), g.info['name']) + p_key = 'photo_%d' % ( + max([int(x.split('_')[1]) for x in [x for x in list(g.info.keys()) if x.startswith('photo_')]]),) thumb_url = g.info[p_key] icon_url = g.info[p_key] else: u = User(oid, self.root.conn) u.set_info() - header_string = u'%s [I]%s %s[/I]' % (self._string(400603).decode('utf-8'), u.info['last_name'], u.info['first_name']) - p_key = 'photo_%d' % (max(map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), u.info.keys()))),) + header_string = '%s [I]%s %s[/I]' % (self.m_string(400603), u.info['last_name'], u.info['first_name']) + p_key = 'photo_%d' % (max([int(x.split('_')[1]) for x in [x for x in list(u.info.keys()) if x.startswith('photo_')]]),) thumb_url = u.info[p_key] icon_url = u.info[p_key] list_item = xbmcgui.ListItem(header_string) list_item.setArt({'thumb': thumb_url, 'icon': icon_url}) h_url = self.root.url({'do': _DO_HOME, 'oid': oid}) - xbmcplugin.addDirectoryItem(_addon_id, h_url, list_item, isFolder = True) + xbmcplugin.addDirectoryItem(_addon_id, h_url, list_item, isFolder=True) if c_type == _CTYPE_VIDEO: - self.root.add_folder(self._string(400502), {'do': _DO_MAIN_VIDEO, 'oid': oid}) - #elif c_type == _CTYPE_AUDIO: + self.root.add_folder(self.m_string(400502), {'do': _DO_MAIN_VIDEO, 'oid': oid}) + # elif c_type == _CTYPE_AUDIO: # self.root.add_folder(self._string(400503), {'do': _DO_MAIN_AUDIO, 'oid': oid}) elif c_type == _CTYPE_IMAGE: - self.root.add_folder(self._string(400504), {'do': _DO_MAIN_PHOTO, 'oid': oid}) + self.root.add_folder(self.m_string(400504), {'do': _DO_MAIN_PHOTO, 'oid': oid}) else: xbmc.log('Unknown content_type: %s' % (c_type,)) return if int(oid) > 0: - self.root.add_folder(self._string(400505), {'do': _DO_FRIENDS, 'oid': oid, 'page': 1}) - self.root.add_folder(self._string(400506), {'do': _DO_GROUPS, 'oid': oid, 'page': 1}) + self.root.add_folder(self.m_string(400505), {'do': _DO_FRIENDS, 'oid': oid, 'page': 1}) + self.root.add_folder(self.m_string(400506), {'do': _DO_GROUPS, 'oid': oid, 'page': 1}) else: - self.root.add_folder(self._string(400512), {'do': _DO_MEMBERS, 'oid': -int(oid), 'page': 1}) + self.root.add_folder(self.m_string(400512), {'do': _DO_MEMBERS, 'oid': -int(oid), 'page': 1}) if oid == self.root.u.id: - self.root.add_folder(self._string(400514), {'do': _DO_MAIN_FAVE}) - xbmcplugin.addDirectoryItem(_addon_id, None, xbmcgui.ListItem(''), isFolder = False) - xbmcplugin.addDirectoryItem(_addon_id, None, xbmcgui.ListItem(''), isFolder = False) - xbmcplugin.addDirectoryItem(_addon_id, None, xbmcgui.ListItem(''), isFolder = False) - self.root.add_folder(self._string(400526), {'do': _DO_LOGOUT}) + self.root.add_folder(self.m_string(400514), {'do': _DO_MAIN_FAVE}) + xbmcplugin.addDirectoryItem(_addon_id, '', xbmcgui.ListItem(''), isFolder=False) + xbmcplugin.addDirectoryItem(_addon_id, '', xbmcgui.ListItem(''), isFolder=False) + xbmcplugin.addDirectoryItem(_addon_id, '', xbmcgui.ListItem(''), isFolder=False) + self.root.add_folder(self.m_string(400526), {'do': _DO_LOGOUT}) xbmcplugin.endOfDirectory(_addon_id) - def __create_group_list_(self, groups): + + def m__create_group_list_(self, groups): for g in groups['items']: list_item = xbmcgui.ListItem(g.info['name']) - p_key = 'photo_%d' % (max(map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), g.info.keys()))),) + p_key = 'photo_%d' % ( + max([int(x.split('_')[1]) for x in [x for x in list(g.info.keys()) if x.startswith('photo_')]]),) list_item.setArt({'thumb': g.info[p_key], 'icon': g.info[p_key]}) params = {'do': _DO_HOME, 'oid': -g.id} url = self.root.url(**params) - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = True) - def _groups(self): + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=True) + + def m_groups(self): oid = self.root.params['oid'] page = int(self.root.params['page']) if int(oid) == self.root.u.id: - self.root.add_folder(self.root.gui._string(400515), {'do': _DO_MAIN_GROUP_SEARCH, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400515), {'do': _DO_MAIN_GROUP_SEARCH, 'page': 1}) user = User(oid, self.root.conn) - groups = user.groups(page = page) + groups = user.groups(page=page) if page < groups['pages']: params = {'do': _DO_GROUPS, 'oid': oid, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) - self.__create_group_list_(groups) + self.root.add_folder(self.root.gui.m_string(400602), params) + self.m__create_group_list_(groups) if page < groups['pages']: params = {'do': _DO_GROUPS, 'oid': oid, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def __create_user_list_(self, users): + + def m__create_user_list_(self, users): for f in users['items']: - list_item = xbmcgui.ListItem(u'%s %s' % (f.info['last_name'], f.info['first_name'])) - p_key = 'photo_%d' % (max(map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), f.info.keys()))),) + list_item = xbmcgui.ListItem('%s %s' % (f.info['last_name'], f.info['first_name'])) + p_key = 'photo_%d' % (max([int(x.split('_')[1]) for x in [x for x in list(f.info.keys()) if x.startswith('photo_')]]),) list_item.setArt({'thumb': f.info[p_key], 'icon': f.info[p_key]}) params = {'do': _DO_HOME, 'oid': f.id} url = self.root.url(**params) - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = True) - def _friends(self): + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=True) + + def m_friends(self): oid = self.root.params['oid'] page = int(self.root.params['page']) if int(oid) == self.root.u.id: - self.root.add_folder(self.root.gui._string(400515), {'do': _DO_MAIN_USER_SEARCH, 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400515), {'do': _DO_MAIN_USER_SEARCH, 'page': 1}) user = User(oid, self.root.conn) - friends = user.friends(page = page) + friends = user.friends(page=page) if page < friends['pages']: params = {'do': _DO_FRIENDS, 'oid': oid, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) - self.__create_user_list_(friends) + self.root.add_folder(self.root.gui.m_string(400602), params) + self.m__create_user_list_(friends) if page < friends['pages']: params = {'do': _DO_FRIENDS, 'oid': oid, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def _members(self): + + def m_members(self): oid = self.root.params['oid'] page = int(self.root.params['page']) group = Group(oid, self.root.conn) - members = group.members(page = page) + members = group.members(page=page) if page < members['pages']: params = {'do': _DO_MEMBERS, 'oid': oid, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) for m in members['items']: - list_item = xbmcgui.ListItem(u'%s %s' % (m.info['last_name'], m.info['first_name'])) - p_key = 'photo_%d' % (max(map(lambda x: int(x.split('_')[1]), filter(lambda x: x.startswith('photo_'), m.info.keys()))),) + list_item = xbmcgui.ListItem('%s %s' % (m.info['last_name'], m.info['first_name'])) + p_key = 'photo_%d' % ( + max([int(x.split('_')[1]) for x in [x for x in list(m.info.keys()) if x.startswith('photo_')]]),) list_item.setArt({'thumb': m.info[p_key], 'icon': m.info[p_key]}) params = {'do': _DO_HOME, 'oid': m.id} url = self.root.url(**params) - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = True) + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=True) if page < members['pages']: params = {'do': _DO_MEMBERS, 'oid': oid, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def __create_user_group_search_page_(self, do_current, do_target, h_file): + + def m__create_user_group_search_page_(self, do_current, do_target, h_file): page = int(self.root.params['page']) - self.root.add_folder(self.root.gui._string(400516), {'do': do_target, 'q':'none', 'page': 1}) + self.root.add_folder(self.root.gui.m_string(400516), {'do': do_target, 'q': 'none', 'page': 1}) history = get_search_history(h_file) count = len(history) pages = int(ceil(count / float(_SETTINGS_PAGE_ITEMS))) if page < pages: params = {'do': do_current, 'page': page + 1} - self.root.add_folder(self._string(400602), params) - h_start = _SETTINGS_PAGE_ITEMS * (page -1) + self.root.add_folder(self.m_string(400602), params) + h_start = _SETTINGS_PAGE_ITEMS * (page - 1) h_end = h_start + _SETTINGS_PAGE_ITEMS history = history[h_start:h_end] for h in history: @@ -817,25 +886,27 @@ class KodiVkGUI: list_item = xbmcgui.ListItem(h) params = {'do': do_target, 'q': query_hex, 'page': 1} url = self.root.url(**params) - xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder = True) + xbmcplugin.addDirectoryItem(_addon_id, url, list_item, isFolder=True) if page < pages: params = {'do': do_current, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def _main_group_search(self): - self.__create_user_group_search_page_(_DO_MAIN_GROUP_SEARCH, _DO_GROUP_SEARCH, _FILE_GROUP_SEARCH_HISTORY) - def _group_search(self): + + def m_main_group_search(self): + self.m__create_user_group_search_page_(_DO_MAIN_GROUP_SEARCH, _DO_GROUP_SEARCH, _FILE_GROUP_SEARCH_HISTORY) + + def m_group_search(self): page = int(self.root.params['page']) q = self.root.params['q'] if q == 'none': s_win = xbmc.Keyboard() - s_win.setHeading(self._string(400515)) + s_win.setHeading(self.m_string(400515)) s_win.setHiddenInput(False) s_win.doModal() if s_win.isConfirmed(): q = s_win.getText() else: - self.notify(self._string(400525), '') + self.notify(self.m_string(400525), '') return else: q = pickle.loads(binascii.unhexlify(q)) @@ -848,33 +919,35 @@ class KodiVkGUI: put_search_history(history, _FILE_GROUP_SEARCH_HISTORY) query_hex = binascii.hexlify(pickle.dumps(q, -1)) kwargs = { - 'page': page, - 'q': q - } + 'page': page, + 'q': q + } u = User(self.root.u.id, self.root.conn) search_res = u.group_search(**kwargs) if page < search_res['pages']: params = {'do': _DO_GROUP_SEARCH, 'q': query_hex, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) - self.__create_group_list_(search_res) + self.root.add_folder(self.root.gui.m_string(400602), params) + self.m__create_group_list_(search_res) if page < search_res['pages']: params = {'do': _DO_GROUP_SEARCH, 'q': query_hex, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def _main_user_search(self): - self.__create_user_group_search_page_(_DO_MAIN_USER_SEARCH, _DO_USER_SEARCH, _FILE_USER_SEARCH_HISTORY) - def _user_search(self): + + def m_main_user_search(self): + self.m__create_user_group_search_page_(_DO_MAIN_USER_SEARCH, _DO_USER_SEARCH, _FILE_USER_SEARCH_HISTORY) + + def m_user_search(self): page = int(self.root.params['page']) q = self.root.params['q'] if q == 'none': s_win = xbmc.Keyboard() - s_win.setHeading(self.root.gui._string(400515)) + s_win.setHeading(self.root.gui.m_string(400515)) s_win.setHiddenInput(False) s_win.doModal() if s_win.isConfirmed(): q = s_win.getText() else: - self.notify(self._string(400525), '') + self.notify(self.m_string(400525), '') return else: q = pickle.loads(binascii.unhexlify(q)) @@ -887,30 +960,35 @@ class KodiVkGUI: put_search_history(history, _FILE_USER_SEARCH_HISTORY) query_hex = binascii.hexlify(pickle.dumps(q, -1)) kwargs = { - 'page': page, - 'q': q - } + 'page': page, + 'q': q + } u = User(self.root.u.id, self.root.conn) search_res = u.user_search(**kwargs) if page < search_res['pages']: params = {'do': _DO_USER_SEARCH, 'q': query_hex, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) - self.__create_user_list_(search_res) + self.root.add_folder(self.root.gui.m_string(400602), params) + self.m__create_user_list_(search_res) if page < search_res['pages']: params = {'do': _DO_USER_SEARCH, 'q': query_hex, 'page': page + 1} - self.root.add_folder(self.root.gui._string(400602), params) + self.root.add_folder(self.root.gui.m_string(400602), params) xbmcplugin.endOfDirectory(_addon_id) - def _logout(self): + + def m_logout(self): dialog = xbmcgui.Dialog() - ret = dialog.yesno(self._string(400526), self._string(400527), nolabel=self._string(400529), yeslabel=self._string(400528)) + ret = dialog.yesno(self.m_string(400526), self.m_string(400527), nolabel=self.m_string(400529), + yeslabel=self.m_string(400528)) if ret: _addon.setSetting(_SETTINGS_ID_TOKEN, '') xbmc.executebuiltin("XBMC.Container.Update(path,replace)") xbmc.executebuiltin("XBMC.ActivateWindow(Home)") else: return + + class KodiVk: conn = None + def __init__(self): self.gui = KodiVkGUI(self) self.conn = self.__connect_() @@ -920,60 +998,80 @@ class KodiVk: self.u.set_info() p = {'do': _DO_HOME} if sys.argv[2]: - p.update(dict(urlparse.parse_qsl(sys.argv[2][1:]))) + p.update(dict(urllib.parse.parse_qsl(sys.argv[2][1:]))) p['oid'] = int(p.get('oid', self.u.info['id'])) self.params = p - if 'content_type' not in self.params.keys(): + if 'content_type' not in list(self.params.keys()): cw_id = xbmcgui.getCurrentWindowId() if cw_id in (10006, 10024, 10025, 10028): self.params['content_type'] = _CTYPE_VIDEO - #elif id in (10005, 10500, 10501, 10502): + # elif id in (10005, 10500, 10501, 10502): # self.params['content_type'] = _CTYPE_AUDIO elif id in (10002,): self.params['content_type'] = _CTYPE_IMAGE self.c_type = self.params.get('content_type', None) - def url(self, params=dict(), **kwparams): + + def url(self, params={}, **kwparams): if self.c_type: kwparams['content_type'] = self.c_type params.update(kwparams) return _addon_url + "?" + urlencode(params) + def add_folder(self, name, params): url = self.url(**params) item = xbmcgui.ListItem(name) - xbmcplugin.addDirectoryItem(_addon_id, url, item, isFolder = True) + xbmcplugin.addDirectoryItem(_addon_id, url, item, isFolder=True) + def __connect_(self): token = _addon.getSetting(_SETTINGS_ID_TOKEN) - conn = Connection(_APP_ID, access_token = token) + conn = Connection(_APP_ID, access_token=token) try: tmp__ = conn.users.get()[0] - except vk.exceptions.VkAPIError, e: + except vk.exceptions.VkAPIError as e: if e.code == 5: token = None else: raise - if not token: + if token in [None, '']: token = None count = _LOGIN_RETRY - while not token and count > 0: + while token in [None, ''] and count > 0: count -= 1 try: - login, password = self.gui._login_form() + login, password = self.gui.m_login_form() except: - self.gui.notify(self.gui._string(400525), '') + self.gui.notify(self.gui.m_string(400525), '') try: - conn = Connection(_APP_ID, login, password, scope = _SCOPE) - token = conn.conn._session.access_token - _addon.setSetting(_SETTINGS_ID_TOKEN, token) + token = auth(login, password, _APP_ID, _APP_SEC, _SCOPE,"0") + if token == '-1': + code = self.m_ask_code() + token = auth(login, password, _APP_ID, _APP_SEC, _SCOPE, code) + if token not in (None, ''): + _addon.setSetting(_SETTINGS_ID_TOKEN, token) + conn = Connection(_APP_ID, login, password, scope=_SCOPE) + else: + raise vk.api.VkAuthError except vk.api.VkAuthError: continue - if not token: + if token in [None, '']: return return conn + + def m_ask_code(self): + code_keyboard = xbmc.Keyboard() + code_keyboard.setHeading(self.gui.m_string(400700)) + code_keyboard.setHiddenInput(False) + code_keyboard.doModal() + if code_keyboard.isConfirmed(): + return code_keyboard.getText() + else: + raise Exception("2FA Code input was cancelled") + def parse_vk_player_html(self, v_url): p = re.compile('"url(\d+)":"([^"]+)"') - headers = {'User-Agent' : 'Kodi-vk/%s (linux gnu)' % (_VERSION,)} - req = urllib2.Request(v_url, None, headers) - http_res = urllib2.urlopen(req) + headers = {'User-Agent': 'Kodi-vk/%s (linux gnu)' % (_VERSION,)} + req = urllib.request.Request(v_url, None, headers) + http_res = urllib.request.urlopen(req) if http_res.code != 200: return None html = http_res.read() @@ -985,37 +1083,79 @@ class KodiVk: res[int(tup[0])] = tup[1].replace('\\', '') return res + +# взято с https://github.com/VkKodi/vkkodi/blob/master/xbmc-vk.svoka.com/vk_auth.py +def auth(email, password, client_id, secret,scope,code): + if code == "0": + try: + url = urlopen("https://oauth.vk.com/token?" + urlencode({ + "grant_type": "password", + "client_id": client_id, + "client_secret": secret, + "username": email, + "password": password, + "scope": scope, + "2fa_supported": "1" + })) + + out = json.load(url) + + except IOError as e: + xbmc.log(e.message) + xbmc.log("===VK 2FA Code requested===") + return "-1" + else: + url = urlopen("https://oauth.vk.com/token?" + urlencode({ + "grant_type": "password", + "client_id": client_id, + "client_secret": secret, + "username": email, + "password": password, + "scope": scope, + "2fa_supported": "1", + "code": code + })) + + out = json.load(url) + + if "access_token" not in out: + xbmc.log(f'kodi-vk auth: {out}') + return out["access_token"] + + if __name__ == '__main__': try: kvk = KodiVk() - except Exception, e: + except Exception as e: + import traceback + xbmc.log(traceback.format_exc()) sys.exit() _DO = { - _DO_HOME: kvk.gui._home, - _DO_MAIN_PHOTO: kvk.gui.photos._main_photo, - _DO_PHOTO: kvk.gui.photos._photo, - _DO_PHOTO_ALBUMS: kvk.gui.photos._photo_albums, - _DO_MAIN_VIDEO: kvk.gui.videos._main_video, - _DO_VIDEO: kvk.gui.videos._video, - _DO_VIDEO_ALBUMS: kvk.gui.videos._video_albums, - _DO_PLAY_VIDEO: kvk.gui.videos._play_video, - _DO_MAIN_VIDEO_SEARCH: kvk.gui.videos._main_video_search, - _DO_VIDEO_SEARCH: kvk.gui.videos._video_search, - _DO_GROUPS: kvk.gui._groups, - _DO_MAIN_GROUP_SEARCH: kvk.gui._main_group_search, - _DO_GROUP_SEARCH: kvk.gui._group_search, - _DO_FRIENDS: kvk.gui._friends, - _DO_MAIN_USER_SEARCH:kvk.gui._main_user_search, - _DO_USER_SEARCH: kvk.gui._user_search, - _DO_MEMBERS: kvk.gui._members, - _DO_MAIN_FAVE: kvk.gui.faves._main_fave, - _DO_FAVE_VIDEO: kvk.gui.faves._video, - _DO_FAVE_PHOTO: kvk.gui.faves._photo, - _DO_FAVE_USERS: kvk.gui.faves._users, - _DO_FAVE_GROUPS: kvk.gui.faves._groups, - _DO_LOGOUT: kvk.gui._logout - } + _DO_HOME: kvk.gui.m_home, + _DO_MAIN_PHOTO: kvk.gui.photos.m_main_photo, + _DO_PHOTO: kvk.gui.photos.m_photo, + _DO_PHOTO_ALBUMS: kvk.gui.photos.m_photo_albums, + _DO_MAIN_VIDEO: kvk.gui.videos.m_main_video, + _DO_VIDEO: kvk.gui.videos.m_video, + _DO_VIDEO_ALBUMS: kvk.gui.videos.m_video_albums, + _DO_PLAY_VIDEO: kvk.gui.videos.m_play_video, + _DO_MAIN_VIDEO_SEARCH: kvk.gui.videos.m_main_video_search, + _DO_VIDEO_SEARCH: kvk.gui.videos.m_video_search, + _DO_GROUPS: kvk.gui.m_groups, + _DO_MAIN_GROUP_SEARCH: kvk.gui.m_main_group_search, + _DO_GROUP_SEARCH: kvk.gui.m_group_search, + _DO_FRIENDS: kvk.gui.m_friends, + _DO_MAIN_USER_SEARCH: kvk.gui.m_main_user_search, + _DO_USER_SEARCH: kvk.gui.m_user_search, + _DO_MEMBERS: kvk.gui.m_members, + _DO_MAIN_FAVE: kvk.gui.faves.m_main_fave, + _DO_FAVE_VIDEO: kvk.gui.faves.m_video, + _DO_FAVE_PHOTO: kvk.gui.faves.m_photo, + _DO_FAVE_USERS: kvk.gui.faves.m_users, + _DO_FAVE_GROUPS: kvk.gui.faves.m_groups, + _DO_LOGOUT: kvk.gui.m_logout + } _do_method = kvk.params['do'] - if _do_method in _DO.keys(): + if _do_method in list(_DO.keys()): _DO[_do_method]() diff --git a/resources/language/English/strings.po b/resources/language/English/strings.po index d9bb134..5596be3 100644 --- a/resources/language/English/strings.po +++ b/resources/language/English/strings.po @@ -143,3 +143,7 @@ msgstr "[I][COLOR orange]User:[/COLOR][/I]" msgctxt "#400604" msgid "Group" msgstr "[I][COLOR orange]Group:[/COLOR][/I]" + +msgctxt "#400700" +msgid "2fa_code" +msgstr "2FA Code" diff --git a/resources/language/Russian/strings.po b/resources/language/Russian/strings.po index a2e00ea..fcf1494 100644 --- a/resources/language/Russian/strings.po +++ b/resources/language/Russian/strings.po @@ -143,3 +143,7 @@ msgstr "[I][COLOR orange]Пользователь:[/COLOR][/I]" msgctxt "#400604" msgid "Group" msgstr "[I][COLOR orange]Сообщество:[/COLOR][/I]" + +msgctxt "#400700" +msgid "2fa_code" +msgstr "Код подтверждения авторизации"