Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# 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/>.
import requests
from urllib.parse import urlparse
import asyncio
from aioflask import request, make_response, redirect, url_for
import subprocess
from bs4 import BeautifulSoup
from shared import *
from views import *
from res import *
from filters import *
from extra import video_get_src_for_qn, video_get_dash_for_qn, bv2av, av2bv
import traceback
from bilibili_api import exceptions
##########################################
# APIs
##########################################
@app.route('/toggle_theme')
def toggle_theme_api():
resp = make_response()
if dark_theme := request.cookies.get('dark-theme'):
dark_theme = not int(dark_theme)
else:
dark_theme = False
resp.set_cookie('dark-theme', '1' if dark_theme else '0')
return resp
##########################################
# Additional features
##########################################
@app.route('/<b32tvid>')
async def b32tv_redirect(b32tvid):
req = requests.get(f'https://b23.tv/{b32tvid}', allow_redirects=False)
if req.status_code != 302:
e = req.json()
return await render_template_with_theme('error.html',
status = e['message'],
desc = e['message'],
suggest='请检查您的请求并重试。'), -e['code']
url = urlparse(req.headers['Location'])
if url.path.startswith('/read/mobile'):
return redirect(url_for('read_view', cid = f'cv{url.path[13:]}'))
elif url.path.startswith('/video/'):
return redirect(url_for('video_view', vid = req.headers['Location'].split('/')[-1][:12]))
@app.route('/download', methods=['POST'])
def dl_redirect():
bvid = request.form.get('id')
cvid = request.form.get('cvid')
qual = request.form.get('qual')
return redirect(f'/proxy/video/{bvid}_{cvid}_{qual}', code=302)
##########################################
# Misc
##########################################
@app.route('/preferences')
async def pref_view():
return await render_template_with_theme('pref.html')
@app.route('/test')
async def test_view():
theme = detect_theme()
resp = make_response(theme)
resp.set_cookie('theme', 'default')
return resp
##########################################
# Error handling
##########################################
@app.errorhandler(exceptions.ArgsException)
async def args_exception_view(e):
return await render_template_with_theme('error.html',
status = '请求错误',
desc = e), 400
@app.errorhandler(exceptions.ResponseCodeException)
async def resp_exception_view(e):
suggest = None
if e.code == -404:
suggest = '这很可能说明您访问的视频/文章不存在,请检查您的请求。' \
'如果您认为这是站点的问题,请联系网站管理员。'
return await render_template_with_theme('error.html',
status = e.msg,
desc = (e.raw if appconf['site']['site_show_unsafe_error_response'] else f'后端服务器发送了无效的回复。'), suggest=suggest), -e.code
@app.errorhandler(Exception)
async def general_exception_view(e):
error_msg = f'{type(e).__name__}: {e}'
print(error_msg)
return await render_template_with_theme('error.html', status='服务器错误', desc=error_msg), 500