123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- # Copyright (C) 2023 MikuInvidious Team
- #
- # MikuInvidious is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License as
- # published by the Free Software Foundation; either version 3 of
- # the License, or (at your option) any later version.
- #
- # MikuInvidious is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- # General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with MikuInvidious. If not, see <http://www.gnu.org/licenses/>.
- '''Bilibili extra apis'''
- import subprocess
- from bilibili_api.utils.network import Api
- from bilibili_api.exceptions import ArgsException
- from bs4 import BeautifulSoup
- from shared import appconf
- '''Format the result returned by cv link.'''
- def article_to_html(article_text):
- article_soup = BeautifulSoup(article_text, features='lxml')
- article_body = article_soup.find('div', id='read-article-holder')
- article_body.attrs = {}
- article_body['id'] = 'main-article'
- del_elems = []
- purge_elems = []
- for child in article_body.descendants:
- if not child.name:
- continue
- if child.name.startswith('h'):
- child.name = f'h{int(child.name[1:])+1}'
- if child.name == 'strong' and child.parent.name.startswith('h'):
- purge_elems.append(child.parent)
- if not hasattr(child, 'attrs'):
- continue
- if child.name == 'a':
- if 'href' not in child:
- continue
-
- child['href'] = child['href'].split('//')[1].strip('www.bilibili.com')
- continue
- elif child.name == 'img':
- try:
- if appconf['proxy']['image']:
- child['src'] = '/proxy/pic/' + child['data-src'].split('//')[1]
- else:
- child['src'] = child['data-src']
- del child['data-src']
- del child['data-size']
- except:
- pass
- continue
- elif child.name == 'span' and not child.parent in purge_elems:
- purge_elems.append(child.parent)
-
- child.attrs = {}
- for purge_elem in purge_elems:
- try:
- purge_elem.string = purge_elem.get_text()
- except:
- pass
- for del_elem in del_elems:
- try:
- del_elem.extract()
- except:
- pass
- return str(article_body)
- '''Convert the article to any file.'''
- def article_to_any(article_text, dest_fmt):
- cmd = ['pandoc', '-f', 'html', '-t', dest_fmt, '-']
- p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
- output, _ = p.communicate(input=article_to_html(article_text).encode("utf-8"))
- return output.decode("utf-8")
- async def video_get_src_for_qn(vi, idx, quality = 16):
- '''Get a specific available source for video.'''
- cid = await vi.get_cid(idx)
- api = Api('https://api.bilibili.com/x/player/playurl', 'GET',
- verify=(not not vi.credential.sessdata),
- credential=vi.credential)
- api.params={ 'avid': vi.get_aid(), 'cid': cid, 'qn': quality }
- return await api.request()
- async def video_get_dash_for_qn(vi, idx):
- '''Get a specific available source for video.'''
- cid = await vi.get_cid(idx)
- api = Api('https://api.bilibili.com/x/player/playurl', 'GET',
- verify=(not not vi.credential.sessdata),
- json_body=True,
- credential=vi.credential)
- api.params = { 'avid': vi.get_aid(), 'cid': cid, 'fnval': '16' }
- return await api.request()
- # The following algorithm is adopted from bilibili-API-collect.
- # https://github.com/SocialSisterYi/bilibili-API-collect/blob/master/other/bvid_desc.md
- table = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'
- itable = { table[i]: i for i in range(len(table)) }
- s = [11, 10, 3, 8, 4, 6]
- XOR = 177451812
- ADD = 8728348608
- def bv2av(x):
- r = 0
- for i in range(6):
- r += itable[x[s[i]]] * 58 ** i
- return (r - ADD) ^ XOR
- def av2bv(x):
- try:
- x = int(x[2:] if str(x).startswith('av') else x)
- x = (x ^ XOR) + ADD
- r = list('BV1 4 1 7 ')
- for i in range(6):
- r[s[i]] = table[x // 58 ** i % 58]
- return ''. join(r)
- except ValueError:
- raise ArgsException("avid 提供错误,必须是以 av 开头的数字组成的字符串。")
-
|