feat: test cookie

resolve #181
This commit is contained in:
acgnhik 2023-10-14 19:22:16 +08:00
parent 5d3f54b02a
commit 38efd5a923
12 changed files with 109 additions and 49 deletions

View File

@ -4,7 +4,7 @@ import logging
import os
from abc import ABC
from datetime import datetime
from typing import Any, Dict, List, Mapping, Optional
from typing import Any, Dict, List, Mapping, Optional, Final
from urllib.parse import urlencode
import aiohttp
@ -20,6 +20,17 @@ logger = logging.getLogger(__name__)
TRACE_API_REQ = bool(os.environ.get('BLREC_TRACE_API_REQ'))
BASE_HEADERS: Final = {
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en;q=0.3,en-US;q=0.2', # noqa
'Accept': 'application/json, text/plain, */*',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Origin': 'https://live.bilibili.com',
'Pragma': 'no-cache',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', # noqa
}
class BaseApi(ABC):
def __init__(
@ -39,7 +50,7 @@ class BaseApi(ABC):
@headers.setter
def headers(self, value: Dict[str, str]) -> None:
self._headers = {**value}
self._headers = {**BASE_HEADERS, **value}
@staticmethod
def _check_response(json_res: JsonResponse) -> None:
@ -50,6 +61,7 @@ class BaseApi(ABC):
@retry(reraise=True, stop=stop_after_delay(5), wait=wait_exponential(0.1))
async def _get_json_res(self, *args: Any, **kwds: Any) -> JsonResponse:
should_check_response = kwds.pop('check_response', True)
kwds = {'timeout': self.timeout, 'headers': self.headers, **kwds}
async with self._session.get(*args, **kwds) as res:
if TRACE_API_REQ:
@ -60,6 +72,7 @@ class BaseApi(ABC):
text_res = await res.text()
logger.debug(f'Response text: {text_res[:200]}')
raise
if should_check_response:
self._check_response(json_res)
return json_res
@ -282,3 +295,8 @@ class WebApi(BaseApi):
params = {'id': room_id}
json_res = await self._get_json(self.base_live_api_urls, path, params=params)
return json_res['data']
async def get_nav(self) -> ResponseData:
path = '/x/web-interface/nav'
json_res = await self._get_json(self.base_api_urls, path, check_response=False)
return json_res

View File

@ -30,6 +30,17 @@ async def ensure_room_id(room_id: int) -> int:
return result['room_id']
async def get_nav(cookie: str) -> ResponseData:
async with aiohttp.ClientSession(raise_for_status=True) as session:
headers = {
'Origin': 'https://passport.bilibili.com',
'Referer': 'https://passport.bilibili.com/account/security',
'Cookie': cookie,
}
api = WebApi(session, headers)
return await api.get_nav()
def get_quality_name(qn: QualityNumber) -> str:
QUALITY_MAPPING = {
20000: '4K',

View File

@ -9,7 +9,7 @@ import aiohttp
from jsonpath import jsonpath
from tenacity import retry, retry_if_exception_type, stop_after_delay, wait_exponential
from .api import AppApi, WebApi
from .api import BASE_HEADERS, AppApi, WebApi
from .exceptions import (
LiveRoomEncrypted,
LiveRoomHidden,
@ -103,19 +103,10 @@ class Live:
@property
def headers(self) -> Dict[str, str]:
return {
'Accept': '*/*',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en;q=0.3,en-US;q=0.2', # noqa
**BASE_HEADERS,
'Referer': f'https://live.bilibili.com/{self._room_id}',
'Origin': 'https://live.bilibili.com',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-site',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
'User-Agent': self._user_agent,
'Cookie': self._cookie,
'Accept-Encoding': 'gzip',
}
@property

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -10,6 +10,6 @@
<body>
<app-root></app-root>
<noscript>Please enable JavaScript to continue using this application.</noscript>
<script src="runtime.42bd9fa8c3bc9be0.js" type="module"></script><script src="polyfills.4e5433063877ea34.js" type="module"></script><script src="main.f21b7d831ad9cafb.js" type="module"></script>
<script src="runtime.bad8d115055bada4.js" type="module"></script><script src="polyfills.4e5433063877ea34.js" type="module"></script><script src="main.f21b7d831ad9cafb.js" type="module"></script>
</body></html>

View File

@ -1,6 +1,6 @@
{
"configVersion": 1,
"timestamp": 1696650016532,
"timestamp": 1697282115210,
"index": "/index.html",
"assetGroups": [
{
@ -15,14 +15,14 @@
"/287.5c768f00dcd24631.js",
"/386.2404f3bc252e1df3.js",
"/503.6553f508f4a9247d.js",
"/548.b1ac5a3a14214886.js",
"/548.73ee5c2419f2617e.js",
"/688.7032fddba7983cf6.js",
"/common.1fc175bce139f4df.js",
"/index.html",
"/main.f21b7d831ad9cafb.js",
"/manifest.webmanifest",
"/polyfills.4e5433063877ea34.js",
"/runtime.42bd9fa8c3bc9be0.js",
"/runtime.bad8d115055bada4.js",
"/styles.ae81e04dfa5b2860.css"
],
"patterns": []
@ -1638,7 +1638,7 @@
"/287.5c768f00dcd24631.js": "4cd0f85040b1a482bf9796575738afdd2dcda00e",
"/386.2404f3bc252e1df3.js": "f937945645579b9651be2666f70cec2c5de4e367",
"/503.6553f508f4a9247d.js": "0878ea0e91bfd5458dd55875561e91060ecb0837",
"/548.b1ac5a3a14214886.js": "2af1216947b79b56b8cf62bda180712219aa89ae",
"/548.73ee5c2419f2617e.js": "93153313f106aed86859050288e59e6c19e3d4cf",
"/688.7032fddba7983cf6.js": "eae55044529782a51b7e534365255bbfa5522b05",
"/assets/animal/panda.js": "fec2868bb3053dd2da45f96bbcb86d5116ed72b1",
"/assets/animal/panda.svg": "bebd302cdc601e0ead3a6d2710acf8753f3d83b1",
@ -3234,11 +3234,11 @@
"/assets/twotone/warning.js": "fb2d7ea232f3a99bf8f080dbc94c65699232ac01",
"/assets/twotone/warning.svg": "8c7a2d3e765a2e7dd58ac674870c6655cecb0068",
"/common.1fc175bce139f4df.js": "af1775164711ec49e5c3a91ee45bd77509c17c54",
"/index.html": "3aea1e8ace7f41b3206fbf0c431c2988488a6167",
"/index.html": "8dc97bacb089295cf14011c3c3e21b14ba7108a1",
"/main.f21b7d831ad9cafb.js": "fc51efa446c2ac21ee17e165217dd3faeacc5290",
"/manifest.webmanifest": "62c1cb8c5ad2af551a956b97013ab55ce77dd586",
"/polyfills.4e5433063877ea34.js": "68159ab99e0608976404a17132f60b5ceb6f12d2",
"/runtime.42bd9fa8c3bc9be0.js": "14c097816962ec676cdf328954884c9885e562f9",
"/runtime.bad8d115055bada4.js": "a679fb0193729e75a72e77d0551dc85e080d9b41",
"/styles.ae81e04dfa5b2860.css": "5933b4f1c4d8fcc1891b68940ee78af4091472b7"
},
"navigationUrls": [

View File

@ -1 +1 @@
(()=>{"use strict";var e,v={},m={};function r(e){var n=m[e];if(void 0!==n)return n.exports;var t=m[e]={exports:{}};return v[e](t,t.exports,r),t.exports}r.m=v,e=[],r.O=(n,t,f,o)=>{if(!t){var a=1/0;for(i=0;i<e.length;i++){for(var[t,f,o]=e[i],c=!0,u=0;u<t.length;u++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[u]))?t.splice(u--,1):(c=!1,o<a&&(a=o));if(c){e.splice(i--,1);var d=f();void 0!==d&&(n=d)}}return n}o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[t,f,o]},r.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return r.d(n,{a:n}),n},r.d=(e,n)=>{for(var t in n)r.o(n,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((n,t)=>(r.f[t](e,n),n),[])),r.u=e=>(592===e?"common":e)+"."+{103:"4a2aea63cc3bf42b",287:"5c768f00dcd24631",386:"2404f3bc252e1df3",503:"6553f508f4a9247d",548:"b1ac5a3a14214886",592:"1fc175bce139f4df",688:"7032fddba7983cf6"}[e]+".js",r.miniCssF=e=>{},r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={},n="blrec:";r.l=(t,f,o,i)=>{if(e[t])e[t].push(f);else{var a,c;if(void 0!==o)for(var u=document.getElementsByTagName("script"),d=0;d<u.length;d++){var l=u[d];if(l.getAttribute("src")==t||l.getAttribute("data-webpack")==n+o){a=l;break}}a||(c=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",n+o),a.src=r.tu(t)),e[t]=[f];var s=(g,b)=>{a.onerror=a.onload=null,clearTimeout(p);var _=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),_&&_.forEach(h=>h(b)),g)return g(b)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),c&&document.head.appendChild(a)}}})(),r.r=e=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:n=>n},typeof trustedTypes<"u"&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(f,o)=>{var i=r.o(e,f)?e[f]:void 0;if(0!==i)if(i)o.push(i[2]);else if(666!=f){var a=new Promise((l,s)=>i=e[f]=[l,s]);o.push(i[2]=a);var c=r.p+r.u(f),u=new Error;r.l(c,l=>{if(r.o(e,f)&&(0!==(i=e[f])&&(e[f]=void 0),i)){var s=l&&("load"===l.type?"missing":l.type),p=l&&l.target&&l.target.src;u.message="Loading chunk "+f+" failed.\n("+s+": "+p+")",u.name="ChunkLoadError",u.type=s,u.request=p,i[1](u)}},"chunk-"+f,f)}else e[f]=0},r.O.j=f=>0===e[f];var n=(f,o)=>{var u,d,[i,a,c]=o,l=0;if(i.some(p=>0!==e[p])){for(u in a)r.o(a,u)&&(r.m[u]=a[u]);if(c)var s=c(r)}for(f&&f(o);l<i.length;l++)r.o(e,d=i[l])&&e[d]&&e[d][0](),e[d]=0;return r.O(s)},t=self.webpackChunkblrec=self.webpackChunkblrec||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})()})();
(()=>{"use strict";var e,v={},m={};function r(e){var n=m[e];if(void 0!==n)return n.exports;var t=m[e]={exports:{}};return v[e](t,t.exports,r),t.exports}r.m=v,e=[],r.O=(n,t,f,o)=>{if(!t){var a=1/0;for(i=0;i<e.length;i++){for(var[t,f,o]=e[i],c=!0,u=0;u<t.length;u++)(!1&o||a>=o)&&Object.keys(r.O).every(b=>r.O[b](t[u]))?t.splice(u--,1):(c=!1,o<a&&(a=o));if(c){e.splice(i--,1);var d=f();void 0!==d&&(n=d)}}return n}o=o||0;for(var i=e.length;i>0&&e[i-1][2]>o;i--)e[i]=e[i-1];e[i]=[t,f,o]},r.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return r.d(n,{a:n}),n},r.d=(e,n)=>{for(var t in n)r.o(n,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((n,t)=>(r.f[t](e,n),n),[])),r.u=e=>(592===e?"common":e)+"."+{103:"4a2aea63cc3bf42b",287:"5c768f00dcd24631",386:"2404f3bc252e1df3",503:"6553f508f4a9247d",548:"73ee5c2419f2617e",592:"1fc175bce139f4df",688:"7032fddba7983cf6"}[e]+".js",r.miniCssF=e=>{},r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={},n="blrec:";r.l=(t,f,o,i)=>{if(e[t])e[t].push(f);else{var a,c;if(void 0!==o)for(var u=document.getElementsByTagName("script"),d=0;d<u.length;d++){var l=u[d];if(l.getAttribute("src")==t||l.getAttribute("data-webpack")==n+o){a=l;break}}a||(c=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",n+o),a.src=r.tu(t)),e[t]=[f];var s=(g,b)=>{a.onerror=a.onload=null,clearTimeout(p);var _=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),_&&_.forEach(h=>h(b)),g)return g(b)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),c&&document.head.appendChild(a)}}})(),r.r=e=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:n=>n},typeof trustedTypes<"u"&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(f,o)=>{var i=r.o(e,f)?e[f]:void 0;if(0!==i)if(i)o.push(i[2]);else if(666!=f){var a=new Promise((l,s)=>i=e[f]=[l,s]);o.push(i[2]=a);var c=r.p+r.u(f),u=new Error;r.l(c,l=>{if(r.o(e,f)&&(0!==(i=e[f])&&(e[f]=void 0),i)){var s=l&&("load"===l.type?"missing":l.type),p=l&&l.target&&l.target.src;u.message="Loading chunk "+f+" failed.\n("+s+": "+p+")",u.name="ChunkLoadError",u.type=s,u.request=p,i[1](u)}},"chunk-"+f,f)}else e[f]=0},r.O.j=f=>0===e[f];var n=(f,o)=>{var u,d,[i,a,c]=o,l=0;if(i.some(p=>0!==e[p])){for(u in a)r.o(a,u)&&(r.m[u]=a[u]);if(c)var s=c(r)}for(f&&f(o);l<i.length;l++)r.o(e,d=i[l])&&e[d]&&e[d][0](),e[d]=0;return r.O(s)},t=self.webpackChunkblrec=self.webpackChunkblrec||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})()})();

View File

@ -1,30 +1,33 @@
import os
import errno
import os
from fastapi import APIRouter, Body
from ..schemas import ResponseMessage
from ...application import Application
from blrec.bili.helpers import get_nav
from ...application import Application
from ..schemas import ResponseMessage
app: Application = None # type: ignore # bypass flake8 F821
router = APIRouter(
prefix='/api/v1/validation',
tags=['validation'],
)
router = APIRouter(prefix='/api/v1/validation', tags=['validation'])
@router.post(
'/dir',
response_model=ResponseMessage,
)
@router.post('/dir', response_model=ResponseMessage)
async def validate_dir(path: str = Body(..., embed=True)) -> ResponseMessage:
"""Check if the path is a directory and grants the read, write permissions
"""
"""Check if the path is a directory and grants the read, write permissions"""
if not os.path.isdir(path):
return ResponseMessage(code=errno.ENOTDIR, message='not a directory')
elif not os.access(path, os.F_OK | os.R_OK | os.W_OK):
return ResponseMessage(code=errno.EACCES, message='no permissions')
else:
return ResponseMessage(code=0, message='ok')
@router.post('/cookie', response_model=ResponseMessage)
async def validate_cookie(cookie: str = Body(..., embed=True)) -> ResponseMessage:
"""Check if the cookie is valid"""
json_res = await get_nav(cookie)
return ResponseMessage(
code=json_res['code'], message=json_res['message'], data=json_res['data']
)

View File

@ -16,4 +16,9 @@ export class ValidationService {
const url = this.url.makeApiUrl(`/api/v1/validation/dir`);
return this.http.post<ResponseMessage>(url, { path });
}
validateCookie(cookie: string): Observable<ResponseMessage> {
const url = this.url.makeApiUrl(`/api/v1/validation/cookie`);
return this.http.post<ResponseMessage>(url, { cookie });
}
}

View File

@ -1,12 +1,4 @@
<nz-modal
nzTitle="修改 Cookie"
nzOkDanger
nzCentered
[(nzVisible)]="visible"
[nzOkDisabled]="control.invalid || control.value.trim() === value"
(nzOnOk)="handleConfirm()"
(nzOnCancel)="handleCancel()"
>
<nz-modal nzTitle="修改 Cookie" nzCentered [(nzVisible)]="visible">
<ng-container *nzModalContent>
<form nz-form [formGroup]="settingsForm">
<nz-form-item>
@ -28,4 +20,24 @@
</nz-form-item>
</form>
</ng-container>
<ng-template [nzModalFooter]>
<button
nz-button
nzType="primary"
(click)="testCookie()"
[disabled]="control.value.trim() === ''"
>
测试
</button>
<button nz-button nzType="default" (click)="handleCancel()">取消</button>
<button
nz-button
nzType="primary"
nzDanger
(click)="handleConfirm()"
[disabled]="control.invalid || control.value.trim() === value"
>
确定
</button>
</ng-template>
</nz-modal>

View File

@ -1,14 +1,18 @@
import {
Component,
ChangeDetectionStrategy,
Input,
Output,
ChangeDetectorRef,
Component,
EventEmitter,
Input,
OnChanges,
Output,
} from '@angular/core';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
import { NzMessageService } from 'ng-zorro-antd/message';
import { ValidationService } from 'src/app/core/services/validation.service';
@Component({
selector: 'app-cookie-edit-dialog',
templateUrl: './cookie-edit-dialog.component.html',
@ -28,7 +32,9 @@ export class CookieEditDialogComponent implements OnChanges {
constructor(
formBuilder: FormBuilder,
private changeDetector: ChangeDetectorRef
private changeDetector: ChangeDetectorRef,
private validationService: ValidationService,
private message: NzMessageService
) {
this.settingsForm = formBuilder.group({
cookie: [''],
@ -72,4 +78,18 @@ export class CookieEditDialogComponent implements OnChanges {
this.confirm.emit(this.control.value.trim());
this.close();
}
testCookie(): void {
this.validationService
.validateCookie(this.control.value)
.subscribe((result) => {
if (result.code === 0) {
this.message.success(
`uid: ${result.data?.mid}, uname: ${result.data?.uname}`
);
} else {
this.message.error(`${result.code}: ${result.message}`);
}
});
}
}