diff --git a/plugin.audio.baidu/default.py b/plugin.audio.baidu/default.py index d1898d0..fcd7f63 100644 --- a/plugin.audio.baidu/default.py +++ b/plugin.audio.baidu/default.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- from xbmcswift2 import Plugin +from urllib import quote_plus +import urllib2 from json import loads from common import get_html from iqiyi import video_from_vid as IQIYI_from_vid @@ -11,6 +13,8 @@ __UserAgent = 'Mozilla/5.0 (X11; Linux x86_64; rv:6.0.2) Gecko/20100101 Firefox/6.0.2' plugin = Plugin() +url_for = plugin.url_for + HOST = 'http://music.baidu.com' BANNER_FMT = '[COLOR gold][%s][/COLOR]' @@ -19,11 +23,14 @@ def pageList(tree, endpoint): pages = tree.find_all('a', {'class': 'page-navigator-number'}) items = [{ 'label': page.text.strip(), - 'path': plugin.url_for(endpoint, url=page['href'].encode('utf-8')) + 'path': url_for(endpoint, url=page['href'].encode('utf-8')) } for page in pages] return items +@plugin.route('/stay') +def stay(): + pass @plugin.route('/playMV/////') def playMV(source, tvid, vid, mvid, url): @@ -61,13 +68,13 @@ def MVList(url): items.append({ 'label': item['title'], - 'path': plugin.url_for('playMV', - source=item['source'], - tvid='0' if tvid == '' else tvid, - vid='0' if vid == '' else vid, - mvid='0' if mvid == '' else mvid, - url=file_link), - 'info': {'duration': item['time']}, + 'path': url_for('playMV', + source=item['source'], + tvid='0' if tvid == '' else tvid, + vid='0' if vid == '' else vid, + mvid='0' if mvid == '' else mvid, + url=file_link), + 'info': {'title': item['title'], 'duration': item['time']}, 'is_playable': True }) @@ -86,7 +93,7 @@ def musiclist(url): items = [{ 'label': item.a['title'], 'thumbnail': item.img['org_src'], - 'path': plugin.url_for('MVList', url=item.a['href']), + 'path': url_for('MVList', url=item.a['href']), } for item in soup] items += pageList(tree, 'musiclist') @@ -106,7 +113,7 @@ def mv(): for item in p: items.append({ 'label': item.text.strip(), - 'path': plugin.url_for('musiclist', url=item.a['href']) + 'path': url_for('musiclist', url=item.a['href']) }) return items @@ -122,7 +129,6 @@ def playBD(sid): plugin.set_resolved_url(url) - @plugin.route('/taglist/') def taglist(url): if url[0] == '/': @@ -140,8 +146,9 @@ def taglist(url): items.append({ 'label': js['songTitle'], - 'path': plugin.url_for('playBD', sid=js['id']), - 'is_playable': True + 'path': url_for('playBD', sid=js['id']), + 'is_playable': True, + 'info': {'title': js['songTitle']} }) items += pageList(tree, 'taglist') @@ -155,12 +162,12 @@ def tag(): soups = tree.find_all('dl', {'class': 'tag-mod'}) for soup in soups: - items += [{'label': BANNER_FMT % soup.dt.text}] + items += [{'label': BANNER_FMT % soup.dt.text, 'path': url_for('stay')}] p = soup.find_all('span', {'class': 'tag-list clearfix'}) for item in p: items.append({ 'label': item.text.strip(), - 'path': plugin.url_for('taglist', url=item.a['href']) + 'path': url_for('taglist', url=item.a['href']) }) return items @@ -177,7 +184,7 @@ def artistAlbum(url): items = [] # songs - items += [{'label': '单曲'}] + items += [{'label': '单曲', 'path': url_for('stay')}] soup1 = tree.find_all('div', {'class': 'song-list-wrap'}) soups = soup1[0].find_all('span', {'class': 'music-icon-hook'}) for item in soups: @@ -186,14 +193,15 @@ def artistAlbum(url): items.append({ 'label': js['songTitle'], - 'path': plugin.url_for('playBD', sid=js['id']), - 'is_playable': True + 'path': url_for('playBD', sid=js['id']), + 'is_playable': True, + 'info': {'title': js['songTitle']} }) items += pageList(pages[0], 'artistAlbum') # albums - items += [{'label': '专辑'}] + items += [{'label': '专辑', 'path': url_for('stay')}] soup2 = tree.find_all('div', {'class': 'album-list-wrap'}) soups = soup2[0].find_all('div', {'class': 'album-cover'}) for item in soups: @@ -201,20 +209,20 @@ def artistAlbum(url): items.append({ 'label': js['albumTitle'], 'thumbnail': js['albumPic'], - 'path': plugin.url_for('taglist', url='/album/'+js['id']), + 'path': url_for('taglist', url='/album/'+js['id']), }) items += pageList(pages[1], 'artistAlbum') # mvs - items += [{'label': 'MV'}] + items += [{'label': 'MV', 'path': url_for('stay')}] soup3 = tree.find_all('div', {'class': 'mv-list-wrap'}) soups = soup3[0].find_all('li', {'class': 'mv-item'}) for item in soups: items.append({ 'label': item.a['title'], 'thumbnail': item.img['org_src'], - 'path': plugin.url_for('MVList', url=item.a['href']), + 'path': url_for('MVList', url=item.a['href']), }) items += pageList(pages[2], 'artistAlbum') return items @@ -235,7 +243,7 @@ def artistName(url): try: items.append({ 'label': item.text.strip(), - 'path': plugin.url_for('artistAlbum', url=item.a['href']) + 'path': url_for('artistAlbum', url=item.a['href']) }) except: pass @@ -254,7 +262,7 @@ def artist(): for item in p: items.append({ 'label': item.text.strip(), - 'path': plugin.url_for('artistName', url=item.a['href']) + 'path': url_for('artistName', url=item.a['href']) }) return items @@ -274,7 +282,7 @@ def albumlist(url): c = item.find_all('p', {'class': 'text-title'}) items.append({ 'label': c[0].text, - 'path': plugin.url_for('MVList', url=c[0].a['href']), + 'path': url_for('MVList', url=c[0].a['href']), 'thumbnail': item.img['src'], }) @@ -292,12 +300,12 @@ def songlist(): items = [] for soup in soups: - items += [{'label': BANNER_FMT % soup.dt.text}] + items += [{'label': BANNER_FMT % soup.dt.text, 'path': url_for('stay')}] p = soup.find_all('dd') for item in p: items.append({ 'label': item.text.strip(), - 'path': plugin.url_for('albumlist', url=item.a['href'].encode('utf-8')) + 'path': url_for('albumlist', url=item.a['href'].encode('utf-8')) }) return items @@ -313,7 +321,7 @@ def root(): items = [{ 'label': item, - 'path': plugin.url_for(mainlist[item]), + 'path': url_for(mainlist[item]), } for item in mainlist] return items diff --git a/plugin.audio.qingting/addon.py b/plugin.audio.qingting/addon.py new file mode 100644 index 0000000..64e9b46 --- /dev/null +++ b/plugin.audio.qingting/addon.py @@ -0,0 +1,182 @@ +# -*- coding: utf-8 -*- + +from xbmcswift2 import Plugin +from urllib import urlencode +import urllib2 +from json import loads + +userAgent = 'Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10' +headers = {'User-Agent': userAgent} + +plugin = Plugin() +url_for = plugin.url_for + +HOST = 'http://www.qingting.fm' + +BANNER_FMT = '[COLOR gold][%s][/COLOR]' +def get_html(url): + req = urllib2.Request(url, headers=headers) + response = urllib2.urlopen(req) + httpdata = response.read() + response.close() + return httpdata + + +@plugin.route('/stay') +def stay(): + pass + +@plugin.route('/pagelist/') +def pagelist(id): + plugin.set_content('music') + pageAPI = 'http://i.qingting.fm/wapi/channels/{}/programs/page/1/pagesize/1000' + page = get_html(pageAPI.format(id)) + js = loads(page) + + for item in js['data']: + thisitem = { + 'label': item['name'], + 'info': {'title': item['name'], 'duration': int(item['duration'])} + } + path = item['file_path'] + if path is not None: + thisitem['path'] = 'http://od.qingting.fm/' + path + thisitem['is_playable'] = True + else: + thisitem['path'] = url_for('stay') + yield thisitem + + +@plugin.route('/Regions//') +def Regions(id, page=1): + req = { + 'page': 1, + 'pagesize': 12, + 'with_total': 'true' + } + + regionAPI = 'http://rapi.qingting.fm/categories/{}/channels?' + html = get_html(regionAPI.format(id) + urlencode(req)) + js = loads(html)['Data'] + + page = int(page) + total_page = (js['total'] + 11) // 12 + if page > 1: + yield { + 'label': u'上一页 - {0}/{1}'.format(page, total_page), + 'path': url_for('Regions', id=id, page=page-1) + } + + for item in js['items']: + cid = item['content_id'] + try: + title = item['title'] + '(%s)' % (item['nowplaying']['title']) + dur = int(item['nowplaying']['duration']) + except: + title = item['title'] + dur = 0 + yield { + 'label': title, + 'path': 'http://lhttp.qingting.fm/live/{}/64k.mp3'.format(cid), + 'thumbnail': item['cover'], + 'is_playable': True, + 'info': {'title': title, 'duration': dur} + } + if page < total_page: + yield { + 'label': u'下一页 - {0}/{1}'.format(page, total_page), + 'path': url_for('Regions', id=id, page=page+1) + } + + +@plugin.route('/radiopage') +def radiopage(): + radioPage = 'http://rapi.qingting.fm/categories' + page = get_html(radioPage) + js = loads(page) + + data = js['Data']['regions'] + js['Data']['regions_map'] + + for item in data: + if item['id'] < 0: + continue + yield { + 'label': item['title'], + 'path': url_for('Regions', id=item['id'], page=1) + } + + for topic in js['Data']['program_categories']: + continue + yield { + 'label': topic['title'], + 'path': url_for('Regions', id=topic['id'], page=1), + 'thumbnail': topic['cover'] + } + +@plugin.route('/sublist///') +def sublist(id, attrs=0, page=1): + req = { + 'category': id, + 'attrs': attrs, + 'curpage': page + } + cateAPI = 'http://i.qingting.fm/capi/neo-channel-filter?' + html = get_html(cateAPI + urlencode(req)) + js = loads(html) + + total_page = (int(js['total']) + 11) // 12 + page = int(page) + if page > 1: + yield { + 'label': u'上一页 - {0}/{1}'.format(page, total_page), + 'path': url_for('sublist', id=id, attrs=attrs, page=page-1) + } + + for item in js['data']['channels']: + yield { + 'label': item['title'], + 'path': url_for('pagelist', id=item['id']), + 'thumbnail': item['cover'], + 'info': {'plot': item['description']} + } + + if page < total_page: + yield { + 'label': u'下一页 - {0}/{1}'.format(page, total_page), + 'path': url_for('sublist', id=id, attrs=attrs, page=page+1) + } + for filter in js['data']['filters']: + for j in filter['values']: + yield { + 'label': j['name'], + 'path': url_for('sublist', id=id, attrs=j['id'], page=1) + } + +@plugin.route('/categories') +def categories(): + cateAPI = 'http://i.qingting.fm/capi/neo-channel-filter?' + page = get_html(cateAPI) + js = loads(page) + + for item in js['data']['categories']: + yield { + 'label': item['name'], + 'path': url_for('sublist', id=item['id'], attrs=0, page=1) + } + +@plugin.route('/') +def root(): + mainlist = { + '分类': 'categories', + '电台': 'radiopage' + } + + items = [{ + 'label': item, + 'path': url_for(mainlist[item]), + } for item in mainlist] + + return items + +if __name__ == '__main__': + plugin.run() diff --git a/plugin.audio.qingting/addon.xml b/plugin.audio.qingting/addon.xml new file mode 100644 index 0000000..6a95e49 --- /dev/null +++ b/plugin.audio.qingting/addon.xml @@ -0,0 +1,22 @@ + + + + + + + + audio + + + QingTing FM plugin for kodi + 蜻蜓fm插件 + QingTing FM plugin for kodi + 蜻蜓fm插件 + https://github.com/yfang1644/kodi_plugins/plugin.audio.baidu + yfang1644@gmail.com + all + + diff --git a/plugin.audio.qingting/changelog.txt b/plugin.audio.qingting/changelog.txt new file mode 100644 index 0000000..72bd7f7 --- /dev/null +++ b/plugin.audio.qingting/changelog.txt @@ -0,0 +1,3 @@ + +2017.10.10 +- 初始版本 diff --git a/plugin.audio.qingting/fanart.jpg b/plugin.audio.qingting/fanart.jpg new file mode 100644 index 0000000..65d6af6 Binary files /dev/null and b/plugin.audio.qingting/fanart.jpg differ diff --git a/plugin.audio.qingting/fanart.png b/plugin.audio.qingting/fanart.png new file mode 100644 index 0000000..e672d0b Binary files /dev/null and b/plugin.audio.qingting/fanart.png differ diff --git a/plugin.audio.qingting/icon.png b/plugin.audio.qingting/icon.png new file mode 100644 index 0000000..53213f6 Binary files /dev/null and b/plugin.audio.qingting/icon.png differ diff --git a/plugin.audio.qingting/plugin.audio.qingting-1.0.0.zip b/plugin.audio.qingting/plugin.audio.qingting-1.0.0.zip new file mode 100644 index 0000000..cb726fe Binary files /dev/null and b/plugin.audio.qingting/plugin.audio.qingting-1.0.0.zip differ diff --git a/plugin.video.bigmovies/addon.py b/plugin.video.bigmovies/addon.py new file mode 100644 index 0000000..9b88b75 --- /dev/null +++ b/plugin.video.bigmovies/addon.py @@ -0,0 +1,259 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- + +from xbmcswift2 import Plugin, xbmc +from json import loads +from bigmovie import BigMovie + +plugin = Plugin() +Bigmovie = BigMovie() +HISTORY = plugin.get_storage('history') + +def colorize(label, color): + return "[COLOR %s]" % color + label + "[/COLOR]" + +def setSettingByRPC(key, value): + """Set Kodi Setting by JSON-RPC + + Args: + key (TYPE): Description + value (TYPE): Description + + Returns: + TYPE: Description + """ + result = xbmc.executeJSONRPC('{"jsonrpc":"2.0", "method":"Settings.SetSettingValue", "params":{"setting":"%s", "value":%s}, "id":1}' % (key, value)) + result = loads(result) + return result + + +def getSettingByRPC(key): + """Get Kodi Setting by JSON-RPC + + Args: + key (TYPE): Description + + Returns: + TYPE: Description + """ + result = xbmc.executeJSONRPC('{"jsonrpc":"2.0","method":"Settings.GetSettingValue","params":{"setting":"%s"},"id":1}' % key) + result = loads(result) + return result["result"]["value"] + +def set_auto_play(): + auto_play_setting = plugin.get_setting("auto_next") + print setSettingByRPC("videoplayer.autoplaynextitem", auto_play_setting) + +# main entrance +@plugin.route('/') +def index(): + set_auto_play() + data = Bigmovie.index() + yield { + 'label': "电影" + colorize("最新", "green"), + 'path': plugin.url_for("movie_list", method="new"), + } + yield { + 'label': "电影" + colorize("最热", "green"), + 'path': plugin.url_for("movie_list", method="hot"), + } + yield { + 'label': "电影" + colorize("全部", "green"), + 'path': plugin.url_for("movie_list", method="all"), + } + for movie in data["movies"]: + yield { + 'label': movie.get("title"), + 'path': plugin.url_for("more_movies", movie_id=movie.get("id", "")), + 'thumbnail': movie.get("img"), + } + + yield { + 'label': "电视剧" + colorize("最新", "green"), + 'path': plugin.url_for("tv_list", method="new"), + } + yield { + 'label': "电视剧" + colorize("最热", "green"), + 'path': plugin.url_for("tv_list", method="hot"), + } + yield { + 'label': "电视剧" + colorize("全部", "green"), + 'path': plugin.url_for("tv_list", method="all"), + } + for tvshow in data["tvplays"]: + yield { + 'label': tvshow["title"], + 'path': plugin.url_for("episode_list", tv_id=tvshow.get("id", "")), + 'icon': tvshow["img"], + 'thumbnail': tvshow["img"], + } + + yield { + 'label': colorize("输入关键字搜索", "yellow"), + 'path': plugin.url_for("input_keyword"), + } + + +# search entrance +@plugin.route('/hotword/') +def hotword(): + yield { + 'label': colorize("输入关键字搜索", "yellow"), + 'path': plugin.url_for("input_keyword"), + } + hotwords = Bigmovie.hot_word() + for word in hotwords["data"]["wordList"]: + word = word.encode("utf8") + item = { + 'label': colorize(word, "green"), + 'path': plugin.url_for("search", title=word), + } + yield item + + +# get search result by input keyword +@plugin.route("/input/") +def input_keyword(): + keyboard = xbmc.Keyboard('', '请输入搜索内容') + xbmc.sleep(1500) + keyboard.doModal() + if (keyboard.isConfirmed()): + keyword = keyboard.getText() + url = plugin.url_for("search", keyword=keyword) + plugin.redirect(url) + + +@plugin.route('/search//') +def search(keyword): + c_list = Bigmovie.search(keyword) + for movie in c_list["movies"]: + yield { + 'label': movie.get("title"), + 'path': plugin.url_for("more_movies", movie_id=movie.get("id", "")), + 'thumbnail': movie.get("img"), + } + + for tvshow in c_list["tvplays"]: + yield { + 'label': tvshow["title"], + 'path': plugin.url_for("episode_list", tv_id=tvshow.get("id", "")), + 'icon': tvshow["img"], + 'thumbnail': tvshow["img"], + } + +@plugin.route('/movie_list//') +def movie_list(method): + if method not in ["hot", "new", "all"]: + return + if method in ["hot", "new"]: + r_method = "new_hot" + else: + r_method = "all" + detail = Bigmovie.movie_list(r_method) + for movie in detail[method + "list"]: + item = { + 'label': movie.get("title"), + 'path': plugin.url_for("more_movies", movie_id=movie.get("id", "")), + 'thumbnail': movie.get("img"), + } + yield item + +@plugin.route('/more_movies/') +def more_movies(movie_id): + detail = Bigmovie.movie_detail(movie_id) + yield { + 'label': detail['title'] + colorize(u'(播放)', 'yellow'), + 'path': detail['list'][0]['url'], + 'thumbnail': detail['img'], + 'is_playable': True, + 'info': { + 'title': detail['title'], + 'plot': detail['info'], + 'duration': int(detail.get('duration',0))*60 + } + } + + for others in detail['reclist']: + yield { + 'label': others['title'], + 'thumbnail': others['img'], + 'path': plugin.url_for('more_movies', movie_id=others['id']) + } + +@plugin.route('/tv_list//') +def tv_list(method): + if method not in ["hot", "new", "all"]: + return + if method in ["hot", "new"]: + r_method = "new_hot" + else: + r_method = "all" + detail = Bigmovie.tv_list(r_method) + for tvshow in detail[method + "list"]: + yield { + 'label': tvshow["title"], + 'path': plugin.url_for("episode_list", tv_id=tvshow.get("id", "")), + 'icon': tvshow["img"], + 'thumbnail': tvshow["img"], + } + +@plugin.route('/detail/', name='detail') +def movie_detail(movie_id): + detail = Bigmovie.movie_detail(movie_id) + plugin.set_resolved_url(detail["list"][0]["url"]) + + +@plugin.route('/play/') +def play(url): + plugin.set_resolved_url(url) + + +@plugin.route('/episode_list//') +def episode_list(tv_id): + detail = Bigmovie.tv_detail(tv_id) + for index, episode in enumerate(detail["list"]): + yield { + 'label': episode['title'] + str(index + 1) + colorize(u'(播放)', 'yellow'), + 'thumbnail': detail['img'], + 'path': plugin.url_for('play', url=episode['url'].encode('utf-8')), + 'is_playable': True, + 'info': {'plot': detail['info']} + } + + for others in detail['reclist']: + yield { + 'label': others['title'], + 'thumbnail': others['img'], + 'path': plugin.url_for('episode_list', tv_id=others['id']) + } + + +def add_history(seasonId, index, Esid, title): + if "list" not in HISTORY: + HISTORY["list"] = [] + for l in HISTORY["list"]: + if l["seasonId"] == seasonId: + HISTORY["list"].remove(l) + item = {"seasonId": seasonId, + "index": index, + "sid": Esid, + "season_name": title} + HISTORY["list"].insert(0, item) + + +@plugin.route('/history/list/') +def list_history(): + if "list" in HISTORY: + for l in HISTORY["list"]: + seasonId = l["seasonId"] + index = l["index"] + sid = l["sid"] + yield { + 'label': u"[COLOR green]{title}[/COLOR] 观看到第[COLOR yellow]{index}[/COLOR]集".format(title=l["season_name"], index=l["index"]), + 'path': plugin.url_for("detail", seasonId=seasonId), + 'is_playable': False + } + + +if __name__ == '__main__': + plugin.run() diff --git a/plugin.video.bigmovies/addon.xml b/plugin.video.bigmovies/addon.xml new file mode 100644 index 0000000..d50695c --- /dev/null +++ b/plugin.video.bigmovies/addon.xml @@ -0,0 +1,21 @@ + + + + + + + + video + + + 大电影 + + all + + + + + diff --git a/plugin.video.bigmovies/bigmovie.py b/plugin.video.bigmovies/bigmovie.py new file mode 100644 index 0000000..b02a979 --- /dev/null +++ b/plugin.video.bigmovies/bigmovie.py @@ -0,0 +1,41 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from json import loads +from urllib import urlencode +from common import get_html +SERVER = "http://www.lajiaovod.com:22435/index.php" + +class BigMovie(object): + """docstring for RenRenMeiJu""" + def __init__(self): + pass + + def get_json(self, url, data=None): + s = loads(get_html(url, data=data)) + return s + + def index(self): + API = '/api/index' + return self.get_json(SERVER + API) + + def movie_detail(self, id): + API = '/api/movieinfo/' + return self.get_json(SERVER + API + str(id)) + + def movie_list(self, method): + API = '/api/movielist/' + return self.get_json(SERVER + API + method) + + def tv_list(self, method): + API = '/api/tvplaylist/' + return self.get_json(SERVER + API + method) + + def tv_detail(self, id): + API = '/api/tvplayinfo/' + return self.get_json(SERVER + API + str(id)) + + def search(self, keyword): + API = '/api/search' + data = {"keyword": keyword} + return self.get_json(SERVER + API, urlencode(data)) diff --git a/plugin.video.bigmovies/changelog.txt b/plugin.video.bigmovies/changelog.txt new file mode 100644 index 0000000..146e50b --- /dev/null +++ b/plugin.video.bigmovies/changelog.txt @@ -0,0 +1,44 @@ +v0.1.6 +- fix album error 修复专辑进入错误 + +v0.1.5 +- fix api error + +v0.1.3 +- add auto play setting +- auto enable auto play + +v0.1.2 +- auto play next episode works + +v0.1.1 +- better history + +v0.1.0 +- fix new api +- fix history + +v0.0.7 +- fix error with new api +- add history for testing + +v0.0.6 +- fix missing lib +- add content menu play whole episodes 增加右键菜单剧集自动播放 +- add choose quality 增加选择清晰度 + +v0.0.5 +- fix search exception 修复一个搜索的错误 + +v0.0.4 +- add search 增加搜索 + +v0.0.3 +- fix error 修复一个无法启动的错误 +- add thumbnail 增加 缩略图 + +v0.0.2 +- added: category 增加分类 + +v0.0.1 +- initial release diff --git a/plugin.video.bigmovies/icon.png b/plugin.video.bigmovies/icon.png new file mode 100644 index 0000000..a53ed9c Binary files /dev/null and b/plugin.video.bigmovies/icon.png differ diff --git a/plugin.video.bigmovies/plugin.video.bigmovies-0.0.1.zip b/plugin.video.bigmovies/plugin.video.bigmovies-0.0.1.zip new file mode 100644 index 0000000..71ddfc3 Binary files /dev/null and b/plugin.video.bigmovies/plugin.video.bigmovies-0.0.1.zip differ diff --git a/plugin.video.bigmovies/resources/language/Chinese (Simple)/strings.po b/plugin.video.bigmovies/resources/language/Chinese (Simple)/strings.po new file mode 100644 index 0000000..f6b673e --- /dev/null +++ b/plugin.video.bigmovies/resources/language/Chinese (Simple)/strings.po @@ -0,0 +1,49 @@ +# Kodi Media Center language file +# Addon Name: Picture Slideshow Screensaver +# Addon id: screensaver.picture.slideshow +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Addons\n" +"Report-Msgid-Bugs-To: alanwww1@xbmc.org\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (http://www.transifex.com/projects/p/xbmc-addons/language/en/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Lines of every page" +msgstr "每页数量" + +msgctxt "#30001" +msgid "Video Quality" +msgstr "清晰度" + +msgctxt "#30002" +msgid "yuanhua" +msgstr "原画" + +msgctxt "#30003" +msgid "super" +msgstr "超清" + +msgctxt "#30004" +msgid "high" +msgstr "高清" + +msgctxt "#30005" +msgid "low" +msgstr "低清" + +msgctxt "#30006" +msgid "max" +msgstr "最高" + +msgctxt "#30007" +msgid "auto play next" +msgstr "自动连播" diff --git a/plugin.video.bigmovies/resources/language/English/strings.po b/plugin.video.bigmovies/resources/language/English/strings.po new file mode 100644 index 0000000..e1b0a5b --- /dev/null +++ b/plugin.video.bigmovies/resources/language/English/strings.po @@ -0,0 +1,49 @@ +# Kodi Media Center language file +# Addon Name: Picture Slideshow Screensaver +# Addon id: screensaver.picture.slideshow +# Addon Provider: Team-Kodi +msgid "" +msgstr "" +"Project-Id-Version: XBMC Addons\n" +"Report-Msgid-Bugs-To: alanwww1@xbmc.org\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (http://www.transifex.com/projects/p/xbmc-addons/language/en/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Lines of every page" +msgstr "" + +msgctxt "#30001" +msgid "Video Quality" +msgstr "" + +msgctxt "#30002" +msgid "yuanhua" +msgstr "" + +msgctxt "#30003" +msgid "super" +msgstr "" + +msgctxt "#30004" +msgid "high" +msgstr "" + +msgctxt "#30005" +msgid "low" +msgstr "" + +msgctxt "#30006" +msgid "max" +msgstr "" + +msgctxt "#30007" +msgid "auto play next" +msgstr "" diff --git a/plugin.video.bigmovies/resources/settings.xml b/plugin.video.bigmovies/resources/settings.xml new file mode 100644 index 0000000..eecd87e --- /dev/null +++ b/plugin.video.bigmovies/resources/settings.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/plugin.video.bilibili/addon.py b/plugin.video.bilibili/addon.py index 43f6967..800afd5 100644 --- a/plugin.video.bilibili/addon.py +++ b/plugin.video.bilibili/addon.py @@ -67,22 +67,29 @@ def next_page(endpoint, page, total_page, **kwargs): def get_av_item(aid, **kwargs): result = bilibili.get_av_list(aid) item = dict(**kwargs) + if not result: + return {'label': '(空)', 'path': plugin.url_for('stay')} if len(result) == 1: vid = result[0].get('vid', '') + #item['icon'] = kwargs.get('thumbnail') item['is_playable'] = True if len(vid) > 0: item['label'] += '(QQ)' else: vid = '0' - item['path'] = plugin.url_for('playmovie', cid=result[0]['cid'], vid=vid) + item['path'] = plugin.url_for('playmovie', cid=result[0]['cid'], vid=vid, name=item['label'].encode('utf-8')) else: item['path'] = plugin.url_for('list_video', aid=aid) return item -@plugin.route('/playmovie//') -def playmovie(cid, vid): +@plugin.route('/stay') +def stay(): + pass + +@plugin.route('/playmovie///') +def playmovie(cid, vid, name): if vid != '0': urls = video_from_vid(vid) else: @@ -94,7 +101,7 @@ def playmovie(cid, vid): playlist = xbmc.PlayList(1) playlist.clear() player = BiliPlayer() - list_item = xbmcgui.ListItem(u'播放') + list_item = xbmcgui.ListItem(name) playlist.add(stack_url, list_item) if danmu == 'true': @@ -121,7 +128,7 @@ def list_video(aid): vid = '0' item = ListItem(**{ 'label': x['pagename'], - 'path': plugin.url_for('playmovie', cid=x['cid'], vid=vid) + 'path': plugin.url_for('playmovie', cid=x['cid'], vid=vid, name=x['pagename'].encode('utf-8')) }) item.set_info("video", {}) item.set_is_playable(True) diff --git a/plugin.video.bilibili/plugin.video.bilibili-1.0.4.zip b/plugin.video.bilibili/plugin.video.bilibili-1.0.4.zip index 24052c1..34830c9 100644 Binary files a/plugin.video.bilibili/plugin.video.bilibili-1.0.4.zip and b/plugin.video.bilibili/plugin.video.bilibili-1.0.4.zip differ diff --git a/plugin.video.bilibili/resources/lib/login_dialog.py b/plugin.video.bilibili/resources/lib/login_dialog.py index c74b82f..97772ca 100644 --- a/plugin.video.bilibili/resources/lib/login_dialog.py +++ b/plugin.video.bilibili/resources/lib/login_dialog.py @@ -1,6 +1,5 @@ #coding=utf-8 from xbmcswift2 import xbmc, xbmcgui -from bilibili import Bilibili class LoginDialog(xbmcgui.WindowDialog): def __init__(self, *args, **kwargs): @@ -15,8 +14,7 @@ def get(self): self.kbd.doModal() if (self.kbd.isConfirmed()): text = self.kbd.getText() - self.close() - return text + else: + text = False self.close() - return False - + return text diff --git a/plugin.video.funshion/default.py b/plugin.video.funshion/default.py index e676d83..e4638a2 100644 --- a/plugin.video.funshion/default.py +++ b/plugin.video.funshion/default.py @@ -242,7 +242,7 @@ def relatedList(params, playlist, j): u += '&name=' + quote_plus(name) u += '&title=%d.%s' % (k+j, p_name) u += '&thumb=' + p_thumb - addDirectoryItem(pluginhandle, u, li, False) + xbmcplugin.addDirectoryItem(pluginhandle, u, li, False) playlist.add(href, li) diff --git a/plugin.video.letv/default.py b/plugin.video.letv/default.py index 9693412..f776785 100644 --- a/plugin.video.letv/default.py +++ b/plugin.video.letv/default.py @@ -5,19 +5,16 @@ import xbmcgui import xbmcplugin import xbmcaddon -import urllib2 from urllib import quote_plus from urlparse import parse_qsl import re import sys import os import time -import random -import hashlib -import socket -import cookielib from json import loads from bs4 import BeautifulSoup +from common import get_html +from letv import video_from_url ######################################################################## # 乐视网(LeTv) by cmeng @@ -127,10 +124,10 @@ def geturl(self): pDialog.close() v_url = self.v_urls[i] - bfile = getHttpData(v_url, True, True) + bfile = get_html(v_url) # give another trial if playback is active and bfile is invalid if ((len(bfile) < 30) and self.isPlayingVideo()): - bfile = getHttpData(v_url, True, True) + bfile = get_html(v_url) fs.write(bfile) # Start playback after fetching 4th video files, restart every 4 fetches if playback aborted unless stop by user @@ -182,7 +179,7 @@ def geturl(self): self.videourl = __profile__ + 'vfile-' + str(x) + '.ts' fs = open(self.videourl, 'wb') - v_urls = decrypt_url(p_url, self.mCheck) + v_urls = video_from_url(p_url, m3u8=__m3u8__) self.v_urls_size = len(v_urls) self.title = "UGC list @ %s (size = %s): %s" % (str(self.curpos), str(self.v_urls_size), p_list) # print "### Preparing: " + self.title @@ -199,7 +196,7 @@ def geturl(self): else: pDialog.close() - bfile = getHttpData(v_url, True, True) + bfile = get_html(v_url) fs.write(bfile) # Start playback after fetching 4th video files, restart every 4 fetches if playback aborted unless stop by user @@ -296,128 +293,6 @@ def delTsFile(self, end_index): except: pass - -################################################################################## -# LeTV Video Link Decode Algorithm -# Extract all the video list and start playing first found valid link -# http://www.letv.com/ptv/vplay/1967644.html -################################################################################## -def calcTimeKey(t): - ror = lambda val, r_bits, : ((val & (2 ** 32 - 1)) >> r_bits % 32) | (val << (32 - (r_bits % 32)) & (2 ** 32 - 1)) - magic = 185025305 - return ror(t, magic % 17) ^ magic - - -# # --- decrypt m3u8 data --------- ## -def m3u8decode(data): - version = data[0:5] - if version.lower() == b'vc_01': - # get real m3u8 - loc2 = bytearray(data[5:]) - length = len(loc2) - loc4 = [0] * (2 * length) - for i in range(length): - loc4[2 * i] = loc2[i] >> 4 - loc4[2 * i + 1] = loc2[i] & 15 - loc6 = loc4[len(loc4) - 11:] + loc4[:len(loc4) - 11] - loc7 = [0] * length - for i in range(length): - loc7[i] = (loc6[2 * i] << 4) + loc6[2 * i + 1] - return ''.join([chr(i) for i in loc7]) - else: - # directly return - return data - - -# ------ video links decrypt ---------------------- ## -def decrypt_url(url, mCheck=True): - videoRes = int(__addon__.getSetting('video_resolution')) - serverIndex = int(__addon__.getSetting('video_server')) - 1 - vparamap = {0: '1300', 1: '720p', 2: '1080p'} - - t_url = 'http://player-pc.le.com/mms/out/video/playJson?id={}&platid=1&splatid=101&format=1&tkey={}&domain=www.le.com®ion=cn&source=1000&accesyx=1' - - t_url2 = '&m3v=1&termid=1&format=1&hwtype=un&ostype=MacOS10.12.4&p1=1&p2=10&p3=-&expect=3&tn={}&vid={}&uuid={}&sign=letv' - - try: - vid = re.compile('/vplay/(\d+).html').findall(url)[0] - j_url = t_url.format(vid, calcTimeKey(int(time.time()))) - link = getHttpData(j_url) - info = loads(link) - playurl = info['msgs']['playurl'] - except: - return '' - - if (mCheck): - pDialog.update(30) - stream_id = None - support_stream_id = playurl["dispatch"].keys() -# print("Current Video Supports:") -# for i in support_stream_id: -# print("\t--format",i,"") - if "1080p" in support_stream_id: - stream_id = '1080p' - elif "720p" in support_stream_id: - stream_id = '720p' - else: - stream_id = sorted(support_stream_id, key=lambda i: int(i[1:]))[-1] - - # pick a random domain or user selected to minimize overloading single server - if (serverIndex == -1): - index = random.randint(0, len(playurl['domain']) - 1) - else: - index = serverIndex % len(playurl['domain']) - domain = playurl['domain'][index] - # print "### Video Server Selection: %i %i = %s" % (serverIndex, index, playurl['domain']) - - vodRes = playurl['dispatch'] - vod = None - while (vod is None) and (videoRes >= 0): - vRes = vparamap.get(videoRes, 0) - try: - vod = vodRes.get(vRes)[0] - except: - pass - videoRes -= 1 - if vod is None: - try: - vod = playurl['dispatch']['1000'][0] - except KeyError: - vod = playurl['dispatch']['350'][0] - except: - return '' - - url = domain + vod - uuid = hashlib.sha1(url.encode('utf8')).hexdigest() + '_0' - url = url.replace('tss=0', 'tss=ios') - url += t_url2.format(random.random(), vid, uuid) - # ext = vodRes[stream_id][1].split('.')[-1] - - r2 = getHttpData(url.encode('utf-8')) - if (mCheck): - pDialog.update(60, line2="### 服务器 [ %i ]" % (index + 1)) - - # try: - info2 = loads(r2) - suffix = '&r=' + str(int(time.time() * 1000)) + '&appid=500' - - # need to decrypt m3u8 (encoded) - may hang here - m3u8 = getHttpData(info2['location'] + suffix) - if (m3u8 is None): - return None - - if (mCheck): - pDialog.update(90) - m3u8_list = m3u8decode(m3u8) - with open(__m3u8__, "wb") as m3u8File: - m3u8File.write(m3u8_list) - m3u8File.close() - - # urls contains array of v_url video links for playback - urls = re.findall(r'^[^#][^\r]*', m3u8_list, re.MULTILINE) - return urls - - ################################################################################## # Continuous Player start playback from user selected video # User backspace to previous menu will not work - playlist = last selected @@ -426,14 +301,12 @@ def playVideoUgc(params): pDialog.create('匹配视频', '请耐心等候! 尝试匹配视频文件 ...') pDialog.update(0) videom3u8 = __addon__.getSetting('video_m3u8') - vid = params.get('vid') - if vid: # pack vid address (cheating) - url = 'http://www.google.com/vplay/%s.html' % vid - else: - url = params['url'] + + url = params['url'] name = params['name'] thumb = params['thumb'] - v_urls = decrypt_url(url) + v_urls = video_from_url(url, m3u8=__m3u8__) + pDialog.close() if len(v_urls): @@ -452,77 +325,6 @@ def playVideoUgc(params): xbmcgui.Dialog().ok(__addonname__, '未匹配到视频文件') -################################################################################## -# Routine to fetech url site data using Mozilla browser -# - deletc '\r|\n|\t' for easy re.compile -# - do not delete ' ' i.e. as some url include spaces -# - unicode with 'replace' option to avoid exception on some url -# - translate to utf8 -################################################################################## -def getHttpData(url, binary=False, mCheck=False): - print "getHttpData: " + url - # setup proxy support - proxy = __addon__.getSetting('http_proxy') - type = 'http' - if proxy != '': - ptype = re.split(':', proxy) - if len(ptype) < 3: - # full path requires by Python 2.4 - proxy = type + '://' + proxy - else: - type = ptype[0] - httpProxy = {type: proxy} - else: - httpProxy = {} - proxy_support = urllib2.ProxyHandler(httpProxy) - - # setup cookie support - cj = cookielib.MozillaCookieJar(cookieFile) - if os.path.isfile(cookieFile): - cj.load(ignore_discard=True, ignore_expires=True) - else: - if not os.path.isdir(os.path.dirname(cookieFile)): - os.makedirs(os.path.dirname(cookieFile)) - - # create opener for both proxy and cookie - opener = urllib2.build_opener(proxy_support, urllib2.HTTPCookieProcessor(cj)) - req = urllib2.Request(url) - req.add_header('User-Agent', UserAgent) - # req.add_header('cookie', 'PHPSESSID=ruebtvftj69ervhpt24n1b86i3') - - for k in range(3): # give 3 trails to fetch url data - if (mCheck and pDialog.iscanceled()): # exit if cancelled by user - return None - - try: - response = opener.open(req) - except urllib2.HTTPError, e: - httpdata = e.read() - except urllib2.URLError, e: - httpdata = "IO Timeout Error" - except socket.timeout, e: - httpdata = "IO Timeout Error" - else: - httpdata = response.read() - response.close() - # Retry if exception: {"exception":{.... - if not "exception" in httpdata: - cj.save(cookieFile, ignore_discard=True, ignore_expires=True) - # for cookie in cj: - # print('%s --> %s'%(cookie.name,cookie.value)) - break - - if (not binary): - httpdata = re.sub('\r|\n|\t', ' ', httpdata) - match = re.compile('/') +def episodelist(url, page): + plugin.set_content('video') episode_api = 'http://pcweb.api.mgtv.com/movie/list' # ??? episode_api = 'http://pcweb.api.mgtv.com/episode/list' episode_api += '?video_id=%s&page=%d&size=40' - thumb = params.get('thumb') - page = params.get('page', '0') page = int(page) if url[-1] == '/': # is a directory html = get_html(url) @@ -192,42 +157,13 @@ def episodesList(params): jsdata = loads(html) data = jsdata['data'] - list = data.get('list') + list = data.get('list', []) + data.get('short', []) total_page = data.get('total_page', 1) - playlist = xbmc.PlayList(1) - playlist.clear() - j = 0 for series in list: title = series['t1'] + ' ' + series['t2'] if series['isnew'] != '0': title = title + u'(预)' - img = series['img'] - href = httphead(series['url']) - vid = series['video_id'] - - vip = series.get('isvip') - if vip and vip != '0': - pay = '(VIP)' - else: - pay = '' - - li = ListItem(title + pay, iconImage=img, thumbnailImage=img) - li.setInfo(type='Video', infoLabels={'Title': title}) - u = sys.argv[0] + '?url=' + href + '&mode=playvideo' - u += '&thumb=' + img + '&vid=%d.%s' % (j, vid) - xbmcplugin.addDirectoryItem(int(sys.argv[1]), u, li, False) - playlist.add(vid, li) - j += 1 - - short = data.get('short') - for series in short: - title = series['t1'] + ' ' + series['t2'] - if series['isnew'] != '0': - title = title + u'(预)' - img = series['img'] - href = httphead(series['url']) - vid = series['video_id'] vip = series.get('isvip') if vip and vip != '0': @@ -235,94 +171,60 @@ def episodesList(params): else: pay = '' - li = ListItem(title + pay, iconImage=img, thumbnailImage=img) - li.setInfo(type='Video', infoLabels={'Title': title}) - u = sys.argv[0] + '?url=' + href + '&mode=playvideo' - u += '&thumb=' + img + '&vid=%d.%s' % (j, vid) - xbmcplugin.addDirectoryItem(int(sys.argv[1]), u, li, False) - playlist.add(vid, li) - j += 1 + yield { + 'label': title + pay, + 'path': url_for('playvideo', vid=series['video_id']), + 'is_playable': True, + 'thumbnail': series['img'], + 'info': {'title': title} + } if page > 0: - li = ListItem(BANNER_FMT % '上一页') - u = sys.argv[0] + '?url=' + url + '&mode=episodelist' - u += '&thumb=' + thumb + '&page=%d' % (page-1) - xbmcplugin.addDirectoryItem(int(sys.argv[1]), u, li, True) + yield { + 'label': BANNER_FMT % u'上一页', + 'path': url_for('episodelist', url=url, page=page-1) + } if page < total_page - 1: - li = ListItem(BANNER_FMT % '下一页') - u = sys.argv[0] + '?url=' + url + '&mode=episodelist' - u += '&thumb=' + thumb + '&page=%d' % (page+1) - xbmcplugin.addDirectoryItem(int(sys.argv[1]), u, li, True) + yield { + 'label': BANNER_FMT % u'下一页', + 'path': url_for('episodelist', url=url, page=page+1) + } related = data.get('related') if related: title = related['t1'] + ' ' + related['t2'] img = related['img'] href = httphead(related['url']) + yield { + 'label': BANNER_FMT2 % title, + 'path': url_for('episodelist', url=href, page=page), + 'thumbnail': img, + 'info': {'title': title} + } + +@plugin.route('/playvideo/') +def playvideo(vid): + level = int(__addon__.getSetting('resolution')) - li = ListItem(BANNER_FMT2 % title, - iconImage=img, thumbnailImage=img) - li.setInfo(type='Video', infoLabels={'Title': title}) - u = sys.argv[0] + '?url=' + href + '&mode=episodelist' - u += '&thumb=' + img - xbmcplugin.addDirectoryItem(int(sys.argv[1]), u, li, True) + m3u_url = video_from_vid(vid, level=level) - xbmcplugin.setContent(int(sys.argv[1]), 'episodes') - xbmcplugin.endOfDirectory(int(sys.argv[1])) + plugin.set_resolved_url(m3u_url) -def playVideo(params): - level = int(__addon__.getSetting('resolution')) - thumb = params['thumb'] - vid = params['vid'].split('.') - v_pos = int(vid[0]) - vid = vid[1] - - playlistA = xbmc.PlayList(1) - playlist = xbmc.PlayList(0) - playlist.clear() - psize = playlistA.size() - - playmode = __addon__.getSetting('video_vplaycont') - - for x in range(v_pos, psize): - p_item = playlistA.__getitem__(x) - p_vid = p_item.getfilename(x) - p_list = p_item.getdescription(x) - li = p_item # pass all li items including the embedded thumb image - li.setInfo(type='Video', infoLabels={'Title': p_list}) - - m3u_url = video_from_vid(p_vid, level=level) - - playlist.add(m3u_url, li) - if x == v_pos: - xbmc.Player(0).play(playlist) - if playmode == 'false': - break - - ''' - urllist = get_mgtv_real_url(m3u_url) - playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) - playlist.clear() - ulen = len(urllist) - for i in range(ulen): - playlist.add(urllist[i], li) - - xbmc.Player().play(playlist) - ''' - -# main programs goes here ######################################### -params = sys.argv[2][1:] -params = dict(parse_qsl(params)) - -mode = params.get('mode') - -runlist = { - None: 'mainMenu()', - 'mainlist': 'listSubMenu(params)', - 'episodelist': 'episodesList(params)', - 'select': 'changeList(params)', - 'playvideo': 'playVideo(params)' - } - -exec(runlist[mode]) +@plugin.route('/') +def root(): + mainAPI = 'http://pc.bz.mgtv.com/odin/c1/channel/list?version=5.0&type=4&pageSize=999' + jsdata = loads(get_html(mainAPI)) + + for item in jsdata['data']: + url = LIST_URL + '/-------------.html?channelId=' + item['pageType'] + yield { + 'label': item['title'], + 'path': url_for('mainlist', + url=url, + filter='0'), + 'info': {'title': item['title'], 'plot': item['vclassName']} + } + +if __name__ == '__main__': + plugin.run()