Skip to content
Snippets Groups Projects
app.py 4.09 KiB
Newer Older
  • Learn to ignore specific revisions
  • John Xina's avatar
    John Xina committed
    # 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