Fix ui bug,add login page for biliup (#155)
* Add Douyin Mainpage Url Support For Douyin Recorder * Fix issues 119 * Delete Tid Table
This commit is contained in:
1 parent
1521b8b1b6
commit
f260a50582
10 files changed
+530
-2113
No files matched your search
@@ -6,6 +6,7 @@ import math
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import urllib.parse
|
||||
from dataclasses import asdict, dataclass, field, InitVar
|
||||
from json import JSONDecodeError
|
||||
from os.path import splitext, basename
|
||||
@@ -56,7 +57,7 @@ class BiliWeb(UploadBase):
|
||||
video_part = bili.upload_file(file, self.lines, self.threads) # 上传视频
|
||||
video_part['title'] = video_part['title'][:80]
|
||||
video.append(video_part) # 添加已经上传的视频
|
||||
video.title = self.data["format_title"][:80] #稿件标题限制80字
|
||||
video.title = self.data["format_title"][:80] # 稿件标题限制80字
|
||||
video.desc = self.desc
|
||||
video.copyright = self.copyright
|
||||
if self.copyright == 2:
|
||||
@@ -95,6 +96,42 @@ class BiliBili:
|
||||
self._auto_os = None
|
||||
self.persistence_path = 'engine/bili.cookie'
|
||||
|
||||
def get_qrcode(self):
|
||||
params = {
|
||||
"appkey": "4409e2ce8ffd12b8",
|
||||
"local_id": "0",
|
||||
"ts": int(time.time()),
|
||||
}
|
||||
params["sign"] = hashlib.md5(
|
||||
f"{urllib.parse.urlencode(params)}59b43e04ad6965f34319062b478f83dd".encode()).hexdigest()
|
||||
response = self.__session.post("http://passport.bilibili.com/x/passport-tv-login/qrcode/auth_code", data=params,
|
||||
timeout=5)
|
||||
r = response.json()
|
||||
if r and r["code"] == 0:
|
||||
return r
|
||||
|
||||
async def login_by_qrcode(self, value):
|
||||
params = {
|
||||
"appkey": "4409e2ce8ffd12b8",
|
||||
"auth_code": value["data"]["auth_code"],
|
||||
"local_id": "0",
|
||||
"ts": int(time.time()),
|
||||
}
|
||||
params["sign"] = hashlib.md5(
|
||||
f"{urllib.parse.urlencode(params)}59b43e04ad6965f34319062b478f83dd".encode()).hexdigest()
|
||||
for i in range(0, 120):
|
||||
await asyncio.sleep(1)
|
||||
response = self.__session.post("http://passport.bilibili.com/x/passport-tv-login/qrcode/poll", data=params,
|
||||
timeout=5)
|
||||
r = response.json()
|
||||
if r and r["code"] == 0:
|
||||
return r
|
||||
raise "Qrcode timeout"
|
||||
def tid_archive(self,cookies):
|
||||
requests.utils.add_dict_to_cookiejar(self.__session.cookies, cookies)
|
||||
response = self.__session.get("https://member.bilibili.com/x/vupre/web/archive/pre")
|
||||
return response.json()
|
||||
|
||||
def login(self, persistence_path, user):
|
||||
self.persistence_path = persistence_path
|
||||
if os.path.isfile(persistence_path):
|
||||
@@ -131,6 +168,35 @@ class BiliBili:
|
||||
'refresh_token': self.refresh_token
|
||||
}, f)
|
||||
|
||||
def send_sms(self, phone_number, country_code ):
|
||||
params = {
|
||||
"actionKey": "appkey",
|
||||
"appkey": "783bbb7264451d82",
|
||||
"build": 6510400,
|
||||
"channel": "bili",
|
||||
"cid": country_code,
|
||||
"device": "phone",
|
||||
"mobi_app": "android",
|
||||
"platform": "android",
|
||||
"tel": phone_number,
|
||||
"ts": int(time.time()),
|
||||
}
|
||||
sign = hashlib.md5(f"{urllib.parse.urlencode(params)}2653583c8873dea268ab9386918b1d65".encode()).hexdigest()
|
||||
payload = f"{urllib.parse.urlencode(params)}&sign={sign}"
|
||||
response = self.__session.post("https://passport.bilibili.com/x/passport-login/sms/send", data=payload,
|
||||
timeout=5)
|
||||
return response.json()
|
||||
|
||||
def login_by_sms(self, code, params):
|
||||
params["code"] = code
|
||||
params["sign"] = hashlib.md5(
|
||||
f"{urllib.parse.urlencode(params)}59b43e04ad6965f34319062b478f83dd".encode()).hexdigest()
|
||||
response = self.__session.post("https://passport.bilibili.com/x/passport-login/login/sms", data=params,
|
||||
timeout=5)
|
||||
r = response.json()
|
||||
if r and r["code"] == 0:
|
||||
return r
|
||||
|
||||
def login_by_password(self, username, password):
|
||||
print('使用账号上传')
|
||||
key_hash, pub_key = self.get_key()
|
||||
@@ -175,7 +241,6 @@ class BiliBili:
|
||||
requests.utils.add_dict_to_cookiejar(self.__session.cookies, cookie)
|
||||
if 'bili_jct' in cookie:
|
||||
self.__bili_jct = cookie["bili_jct"]
|
||||
|
||||
data = self.__session.get("https://api.bilibili.com/x/web-interface/nav", timeout=5).json()
|
||||
if data["code"] != 0:
|
||||
raise Exception(data)
|
||||
|
||||
+58
-7
@@ -2,6 +2,9 @@ from aiohttp import web
|
||||
from .aiohttp_basicauth_middleware import basic_auth_middleware
|
||||
|
||||
from biliup.config import config
|
||||
from biliup.plugins.bili_webup import BiliBili, Data
|
||||
|
||||
BiliBili = BiliBili(Data())
|
||||
|
||||
|
||||
async def get_basic_config(request):
|
||||
@@ -25,11 +28,14 @@ async def set_basic_config(request):
|
||||
if config.data['lines'] == 'cos':
|
||||
config.data['lines'] = 'cos-internal'
|
||||
config.data['threads'] = post_data['limit']
|
||||
config.data['user']['cookies']['SESSDATA'] = post_data['user']['SESSDATA']
|
||||
config.data['user']['cookies']['bili_jct'] = post_data['user']['bili_jct']
|
||||
config.data['user']['cookies']['DedeUserID__ckMd5'] = post_data['user']['DedeUserID__ckMd5']
|
||||
config.data['user']['cookies']['DedeUserID'] = post_data['user']['DedeUserID']
|
||||
config.data['user']['access_token'] = post_data['user']['access_token']
|
||||
cookies ={
|
||||
"SESSDATA": str(post_data['user']['SESSDATA']),
|
||||
"bili_jct": str(post_data['user']['bili_jct']),
|
||||
"DedeUserID__ckMd5": str(post_data['user']['DedeUserID__ckMd5']),
|
||||
"DedeUserID": str(post_data['user']['DedeUserID']),
|
||||
}
|
||||
config.data['user']['cookies'] = cookies
|
||||
config.data['user']['access_token'] = str(post_data['user']['access_token'])
|
||||
return web.json_response({"status": 200})
|
||||
|
||||
|
||||
@@ -62,10 +68,49 @@ async def root_handler(request):
|
||||
return web.HTTPFound('/index.html')
|
||||
|
||||
|
||||
async def service(args, event_manager):
|
||||
async def cookie_login(request):
|
||||
cookie = config.data['user']['cookies']
|
||||
try:
|
||||
BiliBili.login_by_cookies(cookie)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return web.HTTPBadRequest(text="login failed")
|
||||
return web.json_response({"status": 200})
|
||||
|
||||
|
||||
async def sms_login(request):
|
||||
pass
|
||||
|
||||
|
||||
async def sms_send(request):
|
||||
post_data = await request.json()
|
||||
pass
|
||||
|
||||
|
||||
async def qrcode_get(request):
|
||||
r = BiliBili.get_qrcode()
|
||||
return web.json_response(r)
|
||||
|
||||
|
||||
async def qrcode_login(request):
|
||||
post_data = await request.json()
|
||||
try:
|
||||
r = await BiliBili.login_by_qrcode(post_data)
|
||||
except:
|
||||
return web.HTTPBadRequest(text="timeout for qrcode validate")
|
||||
for cookie in r['data']['cookie_info']['cookies']:
|
||||
config.data['user']['cookies'][cookie['name']] = cookie['value']
|
||||
config.data['user']['access_token'] = r['data']['token_info']['access_token']
|
||||
return web.json_response(r)
|
||||
async def pre_archive(request):
|
||||
cookies = config.data['user']['cookies']
|
||||
return web.json_response(BiliBili.tid_archive(cookies))
|
||||
|
||||
|
||||
async def service(args, event_manager):
|
||||
async def url_status(request):
|
||||
return web.json_response(event_manager.context['KernelFunc'].get_url_status())
|
||||
|
||||
app = web.Application()
|
||||
try:
|
||||
from importlib.resources import files
|
||||
@@ -77,7 +122,13 @@ async def service(args, event_manager):
|
||||
app.add_routes([web.post('/api/setbasic', set_basic_config)])
|
||||
app.add_routes([web.get('/api/getconfig', get_streamer_config)])
|
||||
app.add_routes([web.post('/api/setconfig', set_streamer_config)])
|
||||
app.add_routes([web.get('/api/login_by_cookie', cookie_login)])
|
||||
app.add_routes([web.get('/api/login_by_sms', sms_login)])
|
||||
app.add_routes([web.post('/api/send_sms', sms_send)])
|
||||
app.add_routes([web.get('/api/save', save_config)])
|
||||
app.add_routes([web.get('/api/get_qrcode', qrcode_get)])
|
||||
app.add_routes([web.post('/api/login_by_qrcode', qrcode_login)])
|
||||
app.add_routes([web.get('/api/archive_pre', pre_archive)])
|
||||
app.add_routes([web.get('/', root_handler)])
|
||||
if args.static_dir:
|
||||
app.add_routes([web.static('/', args.static_dir, show_index=False)])
|
||||
@@ -91,4 +142,4 @@ async def service(args, event_manager):
|
||||
runner = web.AppRunner(app)
|
||||
await runner.setup()
|
||||
site = web.TCPSite(runner, host=args.host, port=args.port)
|
||||
return runner, site
|
||||
return runner, site
|
||||
+3
-2
@@ -17,6 +17,7 @@
|
||||
"@tsconfig/svelte": "^2.0.0",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"daisyui": "^2.6.4",
|
||||
"ncp": "^2.0.0",
|
||||
"postcss": "^8.4.5",
|
||||
"postcss-import": "^14.0.2",
|
||||
"postcss-load-config": "^3.1.0",
|
||||
@@ -31,11 +32,11 @@
|
||||
"svelte-preprocess": "^4.9.8",
|
||||
"tailwindcss": "^3.0.16",
|
||||
"tslib": "^2.0.0",
|
||||
"typescript": "^4.0.0",
|
||||
"ncp": "^2.0.0"
|
||||
"typescript": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"sirv-cli": "^1.0.0",
|
||||
"svelte-qrcode": "^1.0.0",
|
||||
"tippy.js": "^6.3.7"
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,37 @@
|
||||
<script lang="ts">
|
||||
import Home from './Home.svelte';
|
||||
import Modal from "./Modal.svelte";
|
||||
import {isLogin} from './store.ts';
|
||||
import {notifyHistory} from "./common";
|
||||
import Login from "./Login.svelte";
|
||||
fetch('/api/login_by_cookie')
|
||||
.then((res) => {
|
||||
if (res.ok) {
|
||||
isLogin.set(true);
|
||||
console.log(`Message: ${res}`);
|
||||
} else {
|
||||
$notifyHistory = [...$notifyHistory, {
|
||||
type: 'Error',
|
||||
msg: '校验Cookies失败',
|
||||
date: new Date(),
|
||||
duration: 3000
|
||||
}];
|
||||
isLogin.set(false);
|
||||
}
|
||||
}).catch((e) => $notifyHistory = [...$notifyHistory, {
|
||||
type: 'Error',
|
||||
msg: e,
|
||||
date: new Date(),
|
||||
}]);
|
||||
</script>
|
||||
|
||||
<main class="bg-gray-100" on:dragenter|preventDefault on:dragleave|preventDefault on:dragover|preventDefault
|
||||
on:drop|preventDefault>
|
||||
{#if $isLogin}
|
||||
<Home/>
|
||||
{:else}
|
||||
<Login/>
|
||||
{/if}
|
||||
<div class="fixed space-y-2.5 top-0 right-0 w-1/2" id="alerts">
|
||||
</div>
|
||||
<ul class="menu bg-base-100 rounded-box fixed bottom-16 right-3 w-max drop-shadow">
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
<script lang="ts">
|
||||
import {isLogin} from './store.js';
|
||||
import {fade, scale} from 'svelte/transition';
|
||||
import {createPop, notifyHistory} from "./common";
|
||||
import QrCode from 'svelte-qrcode';
|
||||
|
||||
let rememberMe: boolean = false;
|
||||
let username;
|
||||
let password;
|
||||
let loginMethod = "password";
|
||||
let countryCode = 86;
|
||||
let telephone: number = null;
|
||||
let verificationCode = null;
|
||||
let qrcode;
|
||||
let ret;
|
||||
let throttle = false;
|
||||
let maxtime = 60;
|
||||
|
||||
|
||||
function login_by_sms() {
|
||||
fetch('/api/login_by_sms', {
|
||||
method: 'POST'
|
||||
})
|
||||
.then((res) => {
|
||||
fetch('login_by_cookie')
|
||||
.then((res) => {
|
||||
isLogin.set(true);
|
||||
console.log(`Message: ${res}`)
|
||||
}).catch((e) => createPop(e, 5000))
|
||||
}).catch((e) => createPop(e, 5000))
|
||||
}
|
||||
|
||||
function sendSms() {
|
||||
throttle = true;
|
||||
|
||||
function CountDown() {
|
||||
if (maxtime >= 0) {
|
||||
--maxtime;
|
||||
} else {
|
||||
throttle = false;
|
||||
clearInterval(timer);
|
||||
maxtime = 60;
|
||||
}
|
||||
}
|
||||
|
||||
let timer = setInterval(CountDown, 1000);
|
||||
fetch('/api/send_sms', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
bodycountrycode: countryCode,
|
||||
phone: telephone
|
||||
})
|
||||
})
|
||||
.then((res) => ret = res).catch((e) => createPop(e, 5000));
|
||||
}
|
||||
|
||||
function loginByQrcode() {
|
||||
loginMethod = "qrcode";
|
||||
fetch('/api/get_qrcode')
|
||||
.then(ret => ret.json()).then((res) => {
|
||||
qrcode = res["data"]["url"];
|
||||
fetch('/api/login_by_qrcode', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(res),
|
||||
}).then((res) => {
|
||||
if (res.ok) {
|
||||
fetch('/api/login_by_cookie')
|
||||
.then((res) => {
|
||||
isLogin.set(true)
|
||||
console.log(`Message: ${res}`)
|
||||
}).catch((e) => createPop(e, 5000));
|
||||
} else {
|
||||
createPop(res.body, 5000);
|
||||
}
|
||||
|
||||
}).catch((e) => {
|
||||
createPop(e, 5000);
|
||||
console.log(e);
|
||||
})
|
||||
}).catch((e) => {
|
||||
createPop(e, 5000);
|
||||
console.log(e);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
async function browser() {
|
||||
let ret = await fetch('/api/get_qrcode');
|
||||
let res = await ret.json();
|
||||
await open(res["data"]["url"],'','noreferrer,popup');
|
||||
await fetch('/api/login_by_qrcode', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(res),
|
||||
})
|
||||
await fetch('/api/login_by_cookie')
|
||||
.then((res) => {
|
||||
if (res.ok) {
|
||||
isLogin.set(true);
|
||||
console.log(`Message: ${res}`);
|
||||
} else {
|
||||
$notifyHistory = [...$notifyHistory, {
|
||||
type: 'Error',
|
||||
msg: '校验Cookies失败',
|
||||
date: new Date(),
|
||||
duration: 3000
|
||||
}];
|
||||
isLogin.set(false);
|
||||
}
|
||||
})
|
||||
console.log(`Message: ${res}`);
|
||||
}
|
||||
|
||||
function login() {
|
||||
console.log(rememberMe);
|
||||
invoke('login', {username: username, password: password, rememberMe: rememberMe})
|
||||
.then((res) => {
|
||||
isLogin.set(true);
|
||||
console.log(`Message: ${res}`)
|
||||
}).catch((e) => {
|
||||
createPop(e, 5000);
|
||||
console.log(e);
|
||||
// e = JSON.parse(e);
|
||||
// {"code":0,"data":{"cookie_info":null,"message":
|
||||
// "本次登录环境存在风险, 需使用手机号进行验证或绑定",
|
||||
// "sso":null,"status":2,
|
||||
// "token_info":null,
|
||||
// "url":"https://passport.bilibili.com/account/mobile/security/managephone/phone/verify?tmp_token=&requestId=&source=risk"},
|
||||
// "message":"0","ttl":1}
|
||||
// const webview = new WebviewWindow('theUniqueLabel', {
|
||||
// url: e.data.url
|
||||
// })
|
||||
// createPop(JSON.stringify(e), 5000);
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<div class="abs min-h-screen flex flex-col sm:justify-center items-center bg-white " transition:fade>
|
||||
<div class="relative sm:max-w-sm w-full" transition:scale>
|
||||
<div class="card bg-blue-400 shadow-lg w-full h-full rounded-3xl absolute transform -rotate-6"></div>
|
||||
<div class="card bg-red-400 shadow-lg w-full h-full rounded-3xl absolute transform rotate-6"></div>
|
||||
<div class="relative w-full rounded-3xl px-10 py-5 bg-zinc-50 shadow-md">
|
||||
|
||||
{#if loginMethod === "password"}
|
||||
<div class="indicator w-full -mx-10">
|
||||
<button class="indicator-item link flex text-sm" on:click={browser}>浏览器登录
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<form>
|
||||
<label class="block text-sm text-gray-800">用户名</label>
|
||||
<input bind:value={username}
|
||||
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border rounded-md focus:border-blue-500 focus:outline-none focus:ring"
|
||||
type="text">
|
||||
|
||||
<div class="mt-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<label class="block text-sm text-gray-800" for="password">密码</label>
|
||||
</div>
|
||||
|
||||
<input bind:value={password}
|
||||
class="block w-full px-4 py-2 mt-2 text-gray-700 bg-white border rounded-md focus:border-blue-500 focus:outline-none focus:ring"
|
||||
type="password">
|
||||
</div>
|
||||
<label class="flex items-center mt-4">
|
||||
<input bind:checked={rememberMe} class="form-checkbox" type="checkbox"/>
|
||||
<span class="block ml-2 text-xs font-medium text-gray-700 cursor-pointer">Remember me</span>
|
||||
</label>
|
||||
<div class="mt-6">
|
||||
<button class="w-full px-4 py-2 tracking-wide text-white transition-colors duration-200 transform bg-gray-700 rounded-md hover:bg-gray-600 focus:outline-none focus:bg-gray-600"
|
||||
on:click|preventDefault={login}>
|
||||
登录
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{:else if loginMethod === "qrcode"}
|
||||
<div class="flex items-center justify-center">
|
||||
<QrCode background="#fafafa" value={qrcode}/>
|
||||
</div>
|
||||
{:else if loginMethod === "sms"}
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">国家代码+手机号</span>
|
||||
</label>
|
||||
<div class="flex">
|
||||
<input type="text" placeholder="国家代码" bind:value={countryCode}
|
||||
class="input input-bordered w-[5.75rem]">
|
||||
<input type="text" placeholder="phone numbers" bind:value={telephone} class="input ml-2 w-full">
|
||||
</div>
|
||||
<label class="label">
|
||||
<span class="label-text">验证码</span>
|
||||
</label>
|
||||
<div class="relative">
|
||||
<input type="text" placeholder="verification code" bind:value={verificationCode}
|
||||
class="w-full pr-16 input input-primary">
|
||||
<button on:click={sendSms} class:loading={throttle} disabled={throttle}
|
||||
class="absolute top-0 right-0 rounded-l-none btn btn-primary">
|
||||
{#if !throttle}
|
||||
发送验证码
|
||||
{:else}
|
||||
已发送(
|
||||
<span class="countdown">
|
||||
<span style="--value:{maxtime};"></span>
|
||||
</span>)
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-block mt-2.5" on:click={login_by_sms}>登录</button>
|
||||
{/if}
|
||||
<div class="flex items-center justify-between mt-4">
|
||||
<span class="w-1/5 border-b dark:border-gray-600 lg:w-1/5"></span>
|
||||
|
||||
<a on:click={() => loginMethod='password'} href="#"
|
||||
class="text-xs text-center text-gray-500 uppercase dark:text-gray-400 hover:underline">若登录失败,尝试其他登录方式</a>
|
||||
|
||||
<span class="w-1/5 border-b dark:border-gray-400 lg:w-1/5"></span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center mt-6 -mx-2">
|
||||
<button type="button" on:click={() => loginMethod = "sms"}
|
||||
class="flex items-center justify-center w-full px-6 py-2 mx-2 text-sm font-medium text-white transition-colors duration-200 transform bg-blue-500 rounded-md hover:bg-blue-400 focus:bg-blue-400 focus:outline-none">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z"/>
|
||||
</svg>
|
||||
<span class="hidden mx-2 sm:inline">短信登录</span>
|
||||
</button>
|
||||
|
||||
<a href="#" on:click={loginByQrcode}
|
||||
class="flex items-center justify-center px-6 py-2 mx-2 w-full text-sm font-medium text-gray-500 transition-colors duration-200 transform bg-gray-300 rounded-md hover:bg-gray-200">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm12 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1zM5 20h2a1 1 0 001-1v-2a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1z"/>
|
||||
</svg>
|
||||
<!-- <svg class="w-5 h-5 fill-current" viewBox="0 0 24 24">-->
|
||||
<!-- <path-->
|
||||
<!-- d="M23.954 4.569c-.885.389-1.83.654-2.825.775 1.014-.611 1.794-1.574 2.163-2.723-.951.555-2.005.959-3.127 1.184-.896-.959-2.173-1.559-3.591-1.559-2.717 0-4.92 2.203-4.92 4.917 0 .39.045.765.127 1.124C7.691 8.094 4.066 6.13 1.64 3.161c-.427.722-.666 1.561-.666 2.475 0 1.71.87 3.213 2.188 4.096-.807-.026-1.566-.248-2.228-.616v.061c0 2.385 1.693 4.374 3.946 4.827-.413.111-.849.171-1.296.171-.314 0-.615-.03-.916-.086.631 1.953 2.445 3.377 4.604 3.417-1.68 1.319-3.809 2.105-6.102 2.105-.39 0-.779-.023-1.17-.067 2.189 1.394 4.768 2.209 7.557 2.209 9.054 0 13.999-7.496 13.999-13.986 0-.209 0-.42-.015-.63.961-.689 1.8-1.56 2.46-2.548l-.047-.02z">-->
|
||||
<!-- </path>-->
|
||||
<!-- </svg>-->
|
||||
<span class="hidden mx-2 sm:inline">扫码登录</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.abs {
|
||||
/*overflow-y: overlay;*/
|
||||
margin-right: calc(100% - 100vw);
|
||||
}
|
||||
</style>
|
||||
@@ -2,8 +2,7 @@
|
||||
</script>
|
||||
<script>
|
||||
import {createEventDispatcher} from 'svelte';
|
||||
import { partition} from "./common";
|
||||
import {tid_table} from "./tid";
|
||||
import { partition,createPop} from "./common";
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let currentChildren;
|
||||
@@ -15,7 +14,13 @@
|
||||
let currentTypelist = [];
|
||||
if ($partition === null) {
|
||||
$partition = [];
|
||||
$partition = tid_table.typelist;
|
||||
fetch("/api/archive_pre").then(res => res.json()).then(data => {
|
||||
if(data.code!==0){
|
||||
createPop("加载分区表失败");
|
||||
}
|
||||
$partition = data['data']['typelist'];
|
||||
console.log("加载分区表", data);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -17,7 +17,7 @@
|
||||
url: '',
|
||||
copyright: 1,
|
||||
source: "",
|
||||
tid: 0,
|
||||
tid: 171,
|
||||
description: "",
|
||||
tags: '',
|
||||
dynamic: "",
|
||||
@@ -25,7 +25,6 @@
|
||||
desc_format_id: 0,
|
||||
atomicInt: 0
|
||||
};
|
||||
// $currentTemplate = $template[name];
|
||||
let res;
|
||||
res = await fetch('/api/getconfig')
|
||||
let res_json = await res.json();
|
||||
@@ -34,6 +33,7 @@
|
||||
method: "POST",
|
||||
body:JSON.stringify(res_json)
|
||||
})
|
||||
select(name);
|
||||
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
let ret = await fetch('/api/basic');
|
||||
let ret_json = await ret.json();
|
||||
console.log(ret_json);
|
||||
ret_json.line = ret_json.line.toLowerCase();
|
||||
if (ret_json.line === null) {
|
||||
line = 'auto';
|
||||
} else {
|
||||
|
||||
+108
-50
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {receive, template} from './store';
|
||||
import {currentTemplate, receive, template} from './store';
|
||||
import {archivePre, createPop, partition} from "./common";
|
||||
import {flip} from 'svelte/animate';
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
export let selected;
|
||||
export let selectedTemplate;
|
||||
let oldSelected = selected;
|
||||
let uploaders = ["bili_web", "Noop"];
|
||||
// let title: string = ;
|
||||
let nocopyright: boolean;
|
||||
$ : nocopyright = selectedTemplate?.copyright === 2;
|
||||
let noReprint = true;
|
||||
|
||||
function handleClick(e) {
|
||||
selectedTemplate.copyright = e.target.checked ? 2 : 1;
|
||||
}
|
||||
@@ -25,10 +27,10 @@
|
||||
selectedTemplate.changed = true;
|
||||
$template[selected] = selectedTemplate;
|
||||
console.log($template);
|
||||
let data={
|
||||
let data = {
|
||||
"streamers": $template,
|
||||
}
|
||||
fetch('/api/setconfig',{
|
||||
fetch('/api/setconfig', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
@@ -40,14 +42,30 @@
|
||||
}
|
||||
|
||||
async function del() {
|
||||
let len = Object.keys($template).length;
|
||||
const keys = Object.keys($template);
|
||||
const index = keys.indexOf(selected);
|
||||
if (len==1){
|
||||
createPop("已经是最后一个模板无法删除");
|
||||
return;
|
||||
}
|
||||
delete $template[selected];
|
||||
if (len > 1) {
|
||||
selected = keys[index + 1] || keys[index - 1];
|
||||
$currentTemplate.selectedTemplate = $template[selected];
|
||||
$currentTemplate.current = selected;
|
||||
} else {
|
||||
selected = '';
|
||||
$currentTemplate.selectedTemplate = null;
|
||||
$currentTemplate.current = '';
|
||||
}
|
||||
$template = $template;
|
||||
let data = {
|
||||
"streamers":$template
|
||||
"streamers": $template
|
||||
}
|
||||
console.log($template);
|
||||
try {
|
||||
await fetch('/api/setconfig',{
|
||||
await fetch('/api/setconfig', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
headers: {
|
||||
@@ -59,6 +77,7 @@
|
||||
console.log(e);
|
||||
createPop(e, 5000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// console.log()
|
||||
@@ -109,28 +128,36 @@
|
||||
tempTag = null;
|
||||
return;
|
||||
}
|
||||
if(tags.length > 10) {
|
||||
createPop("标签数量超过10个,无法添加");
|
||||
tempTag = null;
|
||||
return;
|
||||
}
|
||||
tags = [...tags, tempTag];
|
||||
selectedTemplate.tags = tags;
|
||||
tempTag = null;
|
||||
return false;
|
||||
}
|
||||
function urlhandleKeypress(){
|
||||
|
||||
function urlhandleKeypress() {
|
||||
console.log(urls);
|
||||
if(urls.includes(tempUrl)){
|
||||
if (urls.includes(tempUrl)) {
|
||||
createPop("已有相同链接");
|
||||
tempUrl = null;
|
||||
return;
|
||||
}
|
||||
urls = [...urls, tempUrl];
|
||||
selectedTemplate.url = urls;
|
||||
tempUrl=null;
|
||||
tempUrl = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
function removeTag(tag) {
|
||||
tags = tags.filter(t => t !== tag);
|
||||
selectedTemplate.tags = tags;
|
||||
console.log(tag);
|
||||
}
|
||||
|
||||
function removeUrl(url) {
|
||||
urls = urls.filter(u => u !== url);
|
||||
selectedTemplate.url = urls;
|
||||
@@ -143,6 +170,7 @@
|
||||
parent = detailParent;
|
||||
children = detailChildren;
|
||||
}
|
||||
|
||||
let dtime;
|
||||
let isDtime = false;
|
||||
let date;
|
||||
@@ -156,22 +184,24 @@
|
||||
in:receive={{key: selected}}>
|
||||
<div class="space-y-3">
|
||||
<div class="flex flex-row-reverse">
|
||||
<button class="ml-2 py-2 px-2 flex justify-center items-center bg-red-600 hover:bg-red-700 focus:ring-red-500 focus:ring-offset-red-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 w-8 h-8 rounded-lg " on:click|preventDefault={del}
|
||||
<button class="ml-2 py-2 px-2 flex justify-center items-center bg-red-600 hover:bg-red-700 focus:ring-red-500 focus:ring-offset-red-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 w-8 h-8 rounded-lg "
|
||||
on:click|preventDefault={del}
|
||||
type="button">
|
||||
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" stroke-linecap="round" stroke-linejoin="round"
|
||||
<path d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
||||
stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2"/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- <button class="py-2 px-2 flex justify-center items-center bg-blue-600 hover:bg-blue-700 focus:ring-blue-500 focus:ring-offset-blue-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 w-8 h-8 rounded-lg " on:click|preventDefault={save}-->
|
||||
<!-- type="button">-->
|
||||
<!-- <svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"-->
|
||||
<!-- xmlns="http://www.w3.org/2000/svg">-->
|
||||
<!-- <path d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4" stroke-linecap="round" stroke-linejoin="round"-->
|
||||
<!-- stroke-width="2"/>-->
|
||||
<!-- </svg>-->
|
||||
<!-- </button>-->
|
||||
<!-- <button class="py-2 px-2 flex justify-center items-center bg-blue-600 hover:bg-blue-700 focus:ring-blue-500 focus:ring-offset-blue-200 text-white transition ease-in duration-200 text-center text-base font-semibold shadow-md focus:outline-none focus:ring-2 focus:ring-offset-2 w-8 h-8 rounded-lg " on:click|preventDefault={save}-->
|
||||
<!-- type="button">-->
|
||||
<!-- <svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"-->
|
||||
<!-- xmlns="http://www.w3.org/2000/svg">-->
|
||||
<!-- <path d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4" stroke-linecap="round" stroke-linejoin="round"-->
|
||||
<!-- stroke-width="2"/>-->
|
||||
<!-- </svg>-->
|
||||
<!-- </button>-->
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<label class="text-sm font-bold text-gray-500 tracking-wide mb-2">
|
||||
@@ -198,17 +228,18 @@
|
||||
placeholder="标题">
|
||||
|
||||
</div>
|
||||
<!-- <div class="flex flex-col">-->
|
||||
<!-- <label class="label">-->
|
||||
<!-- <span class="text-sm font-bold text-gray-500 tracking-wide">直播间链接</span>-->
|
||||
<!-- </label>-->
|
||||
<!-- <input bind:value={selectedTemplate.url}-->
|
||||
<!-- class="text-base p-2 border border-gray-300 rounded-lg focus:outline-none focus:border-indigo-500"-->
|
||||
<!-- placeholder="www.douyu.com/3484">-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="flex flex-col">-->
|
||||
<!-- <label class="label">-->
|
||||
<!-- <span class="text-sm font-bold text-gray-500 tracking-wide">直播间链接</span>-->
|
||||
<!-- </label>-->
|
||||
<!-- <input bind:value={selectedTemplate.url}-->
|
||||
<!-- class="text-base p-2 border border-gray-300 rounded-lg focus:outline-none focus:border-indigo-500"-->
|
||||
<!-- placeholder="www.douyu.com/3484">-->
|
||||
<!-- </div>-->
|
||||
<div class="flex flex-wrap rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-transparent">
|
||||
{#each urls as url(url)}
|
||||
<span animate:flip="{{duration: 300}}" class="flex ml-1 my-1.5 px-3 py-0.5 text-base rounded-full text-white bg-indigo-500 ">
|
||||
<span animate:flip="{{duration: 300}}"
|
||||
class="flex ml-1 my-1.5 px-3 py-0.5 text-base rounded-full text-white bg-indigo-500 ">
|
||||
{url}
|
||||
<button on:click={(e)=>{removeUrl(url)}} class="bg-transparent hover">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="currentColor"
|
||||
@@ -220,28 +251,28 @@
|
||||
</span>
|
||||
{/each}
|
||||
|
||||
<input bind:value={tempUrl} class="outline-none rounded-lg flex-1 appearance-none w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base " on:keypress={e=>e.key==='Enter' && urlhandleKeypress()}
|
||||
<input bind:value={tempUrl}
|
||||
class="outline-none rounded-lg flex-1 appearance-none w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base "
|
||||
on:keypress={e=>e.key==='Enter' && urlhandleKeypress()}
|
||||
placeholder="录制链接, 回车输入"
|
||||
type="text"/>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="mb-3 flex justify-between items-center">
|
||||
<!-- <div>-->
|
||||
<!-- <div class="relative inline-block w-10 mr-2 align-middle select-none">-->
|
||||
<!-- bind:checked={nocopyright}-->
|
||||
<input checked={nocopyright} class="toggle" id="Orange"
|
||||
name="toggle" on:change={(event) => handleClick(event)}
|
||||
type="checkbox"/>
|
||||
<!-- <label class="block overflow-hidden h-6 rounded-full bg-gray-100 cursor-pointer" for="Orange">-->
|
||||
<!-- </label>-->
|
||||
<!-- </div>-->
|
||||
<span class="mx-2 w-auto text-sm text-gray-500 tracking-wide">
|
||||
<!-- <div>-->
|
||||
<!-- <div class="relative inline-block w-10 mr-2 align-middle select-none">-->
|
||||
<!-- bind:checked={nocopyright}-->
|
||||
<input checked={nocopyright} class="toggle" id="Orange"
|
||||
name="toggle" on:change={(event) => handleClick(event)}
|
||||
type="checkbox"/>
|
||||
<!-- <label class="block overflow-hidden h-6 rounded-full bg-gray-100 cursor-pointer" for="Orange">-->
|
||||
<!-- </label>-->
|
||||
<!-- </div>-->
|
||||
<span class="mx-2 w-auto text-sm text-gray-500 tracking-wide">
|
||||
是否转载
|
||||
</span>
|
||||
<!-- </div>-->
|
||||
<!-- </div>-->
|
||||
<div class="pl-4 invisible flex-grow" class:copyright={nocopyright}>
|
||||
<input bind:value={selectedTemplate.source} class="input input-bordered w-full" id="rounded-email"
|
||||
placeholder="转载来源"
|
||||
@@ -256,16 +287,16 @@
|
||||
</label>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="flex w-52" use:archivePre={{callback, current, currentChildren}}>
|
||||
<button class="border border-gray-300 relative w-full bg-white rounded-md pl-3 pr-10 py-3 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
type="button">
|
||||
<div class="flex">
|
||||
<div class="flex w-52" use:archivePre={{callback, current, currentChildren}}>
|
||||
<button class="border border-gray-300 relative w-full bg-white rounded-md pl-3 pr-10 py-3 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
||||
type="button">
|
||||
<span class="flex items-center">
|
||||
<span class="ml-1 block truncate">
|
||||
{parent} → {children}
|
||||
</span>
|
||||
</span>
|
||||
<span class="ml-3 absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
||||
<span class="ml-3 absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
|
||||
<svg aria-hidden="true" class="h-5 w-5 text-gray-400" fill="currentColor"
|
||||
viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path clip-rule="evenodd"
|
||||
@@ -274,12 +305,37 @@
|
||||
</path>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
<!-- <input bind:this={archivePre} bind:value={tid} type="text" class=" rounded-lg border-transparent flex-1 appearance-none border border-gray-300 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-transparent" placeholder="分区"/>-->
|
||||
</button>
|
||||
<!-- <input bind:this={archivePre} bind:value={tid} type="text" class=" rounded-lg border-transparent flex-1 appearance-none border border-gray-300 w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-transparent" placeholder="分区"/>-->
|
||||
</div>
|
||||
<!-- <div class="flex w-48">-->
|
||||
<!-- <select class="border border-gray-300 relative w-full bg-white rounded-md pl-3 pr-10 py-3 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"-->
|
||||
<!-- type="button" bind:value={selectedTemplate.uploader}>-->
|
||||
|
||||
<!-- {#each uploaders as uploader}-->
|
||||
<!-- <option class="text-xl" value={uploader}>-->
|
||||
<!-- {uploader}-->
|
||||
<!-- </option>-->
|
||||
<!-- {/each}-->
|
||||
|
||||
<!-- <span class="ml-3 absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">-->
|
||||
<!-- <svg aria-hidden="true" class="h-5 w-5 text-gray-400" fill="currentColor"-->
|
||||
<!-- viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">-->
|
||||
<!-- <path clip-rule="evenodd"-->
|
||||
<!-- d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z"-->
|
||||
<!-- fill-rule="evenodd">-->
|
||||
<!-- </path>-->
|
||||
<!-- </svg>-->
|
||||
<!-- </span>-->
|
||||
<!-- </select>-->
|
||||
<!-- </div>-->
|
||||
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap rounded-lg border border-gray-300 focus:outline-none focus:ring-2 focus:ring-purple-600 focus:border-transparent">
|
||||
{#each tags as tag(tag)}
|
||||
<span animate:flip="{{duration: 300}}" class="flex ml-1 my-1.5 px-3 py-0.5 text-base rounded-full text-white bg-indigo-500 ">
|
||||
<span animate:flip="{{duration: 300}}"
|
||||
class="flex ml-1 my-1.5 px-3 py-0.5 text-base rounded-full text-white bg-indigo-500 ">
|
||||
{tag}
|
||||
<button on:click={(e)=>{removeTag(tag)}} class="bg-transparent hover">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="currentColor"
|
||||
@@ -291,7 +347,9 @@
|
||||
</span>
|
||||
{/each}
|
||||
|
||||
<input bind:value={tempTag} class="outline-none rounded-lg flex-1 appearance-none w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base " on:keypress={e=>e.key==='Enter' && handleKeypress()}
|
||||
<input bind:value={tempTag}
|
||||
class="outline-none rounded-lg flex-1 appearance-none w-full py-2 px-4 bg-white text-gray-700 placeholder-gray-400 shadow-sm text-base "
|
||||
on:keypress={e=>e.key==='Enter' && handleKeypress()}
|
||||
placeholder="标签"
|
||||
type="text"/>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { writable } from "svelte/store";
|
||||
import { crossfade, fly } from "svelte/transition";
|
||||
|
||||
|
||||
export const isLogin = writable(true);
|
||||
export const isLogin = writable(false);
|
||||
export const template = writable({});
|
||||
|
||||
export const currentTemplate = writable({
|
||||
|
||||
-2046
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user