mirror of
https://github.com/suyiiyii/nonebot-bison.git
synced 2025-07-15 12:43:00 +08:00
still bugs
This commit is contained in:
parent
dce58580f2
commit
5e153b0d2f
@ -2,7 +2,7 @@ import React, { useContext, useEffect, useState } from 'react';
|
|||||||
import { HashRouter as Router, Route, Switch } from 'react-router-dom';
|
import { HashRouter as Router, Route, Switch } from 'react-router-dom';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import { LoginContext, loginContextDefault, GlobalConfContext } from './utils/context';
|
import { LoginContext, loginContextDefault, GlobalConfContext } from './utils/context';
|
||||||
import { LoginStatus, GlobalConf } from './utils/type';
|
import { LoginStatus, GlobalConf, AllPlatformConf } from './utils/type';
|
||||||
import { Admin } from './pages/admin';
|
import { Admin } from './pages/admin';
|
||||||
import { getGlobalConf } from './api/config';
|
import { getGlobalConf } from './api/config';
|
||||||
import { Auth } from './pages/auth';
|
import { Auth } from './pages/auth';
|
||||||
@ -27,19 +27,20 @@ function LoginSwitch() {
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [loginStatus, setLogin] = useState(loginContextDefault.login);
|
const [loginStatus, setLogin] = useState(loginContextDefault.login);
|
||||||
const [globalConf, setGlobalConf] = useState<GlobalConf>({platformConf: []});
|
const [globalConf, setGlobalConf] = useState<GlobalConf>({platformConf: {} as AllPlatformConf, loaded: false});
|
||||||
// const globalConfContext = useContext(GlobalConfContext);
|
// const globalConfContext = useContext(GlobalConfContext);
|
||||||
const save = (login: LoginStatus) => setLogin(_ => login);
|
const save = (login: LoginStatus) => setLogin(_ => login);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchGlobalConf = async () => {
|
const fetchGlobalConf = async () => {
|
||||||
const res = await getGlobalConf();
|
const res = await getGlobalConf();
|
||||||
setGlobalConf(_ => res);
|
setGlobalConf(_ => {return {...res, loaded: true}});
|
||||||
};
|
};
|
||||||
fetchGlobalConf();
|
fetchGlobalConf();
|
||||||
}, []);
|
}, []);
|
||||||
return (
|
return (
|
||||||
<LoginContext.Provider value={{login: loginStatus, save}}>
|
<LoginContext.Provider value={{login: loginStatus, save}}>
|
||||||
<GlobalConfContext.Provider value={globalConf}>
|
<GlobalConfContext.Provider value={globalConf}>
|
||||||
|
{ globalConf.loaded &&
|
||||||
<Router>
|
<Router>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path="/auth/:code">
|
<Route path="/auth/:code">
|
||||||
@ -50,6 +51,7 @@ function App() {
|
|||||||
</Route>
|
</Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Router>
|
</Router>
|
||||||
|
}
|
||||||
</GlobalConfContext.Provider>
|
</GlobalConfContext.Provider>
|
||||||
</LoginContext.Provider>
|
</LoginContext.Provider>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { GlobalConf, TokenResp } from "../utils/type";
|
import { GlobalConf, TokenResp, SubscribeResp, TargetNameResp } from "../utils/type";
|
||||||
import { baseUrl } from './utils';
|
import { baseUrl } from './utils';
|
||||||
|
|
||||||
export async function getGlobalConf(): Promise<GlobalConf> {
|
export async function getGlobalConf(): Promise<GlobalConf> {
|
||||||
@ -11,3 +11,13 @@ export async function auth(token: string): Promise<TokenResp> {
|
|||||||
const res = await axios.get<TokenResp>(`${baseUrl}auth`, {params: {token}});
|
const res = await axios.get<TokenResp>(`${baseUrl}auth`, {params: {token}});
|
||||||
return res.data;
|
return res.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getSubscribe(): Promise<SubscribeResp> {
|
||||||
|
const res = await axios.get(`${baseUrl}subs`);
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTargetName(platformName: string, target: string): Promise<TargetNameResp> {
|
||||||
|
const res = await axios.get(`${baseUrl}target_name`, {params: {platformName, target}});
|
||||||
|
return res.data;
|
||||||
|
}
|
||||||
|
@ -18,4 +18,23 @@ axios.interceptors.request.use(function (config) {
|
|||||||
return config;
|
return config;
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
})
|
});
|
||||||
|
|
||||||
|
axios.interceptors.response.use(function (response) {
|
||||||
|
// const data = response.data;
|
||||||
|
// const parseToMap = (item: any): any => {
|
||||||
|
// if (item instanceof Array) {
|
||||||
|
// return item.map(parseToMap);
|
||||||
|
// } else if (item instanceof Object) {
|
||||||
|
// let res = new Map();
|
||||||
|
// for (const key of Object.keys(item)) {
|
||||||
|
// res.set(key, parseToMap(item[key]));
|
||||||
|
// }
|
||||||
|
// return res;
|
||||||
|
// } else {
|
||||||
|
// return item;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// response.data = parseToMap(data);
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import React, { FC, useContext, useState } from "react";
|
import React, { ReactElement, useContext, useEffect, useState } from "react";
|
||||||
import { LoginContext, GlobalConfContext } from "../utils/context";
|
import { LoginContext, GlobalConfContext } from "../utils/context";
|
||||||
import { Layout, Menu } from 'antd';
|
import { Layout, Menu, Empty, Collapse, Card, Tag, Row, Col, Form, Tooltip, Button, Modal, Select,
|
||||||
import { SubscribeConfig } from '../utils/type';
|
Input} from 'antd';
|
||||||
import { SettingOutlined, BugOutlined } from '@ant-design/icons';
|
import { SubscribeConfig, SubscribeResp, PlatformConfig } from '../utils/type';
|
||||||
|
import { SettingOutlined, BugOutlined, DeleteOutlined, CopyOutlined, PlusOutlined } from '@ant-design/icons';
|
||||||
|
import { getSubscribe, getTargetName } from '../api/config';
|
||||||
import './admin.css';
|
import './admin.css';
|
||||||
|
|
||||||
export function Admin() {
|
export function Admin() {
|
||||||
@ -26,7 +28,7 @@ export function Admin() {
|
|||||||
<div style={{margin: '24px', background: '#fff', minHeight: '640px'}}>
|
<div style={{margin: '24px', background: '#fff', minHeight: '640px'}}>
|
||||||
{
|
{
|
||||||
tab == 'manage' ?
|
tab == 'manage' ?
|
||||||
<div>123</div>
|
<ConfigPage tab={tab}/>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -35,13 +37,113 @@ export function Admin() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConfigPage() {
|
interface ConfigPageProp {
|
||||||
const [ configData, setConfigData ] = useState<Array<SubscribeConfig>>([
|
tab: string
|
||||||
{
|
}
|
||||||
platform: 'weibo',
|
function ConfigPage(prop: ConfigPageProp) {
|
||||||
target: '123333',
|
const [ configData, setConfigData ] = useState<SubscribeResp>({});
|
||||||
catetories: [1, 2],
|
const [ showModal, setShowModal ] = useState<boolean>(false);
|
||||||
tags: []
|
const globalConf = useContext(GlobalConfContext);
|
||||||
}
|
useEffect(() => {
|
||||||
]);
|
getSubscribe()
|
||||||
|
.then(res => {
|
||||||
|
setConfigData(_ => res);
|
||||||
|
});
|
||||||
|
}, [prop.tab]);
|
||||||
|
const clickNew = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||||
|
setShowModal(_ => true);
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
const genCard = (config: SubscribeConfig) => {
|
||||||
|
const platformConf = globalConf.platformConf[config.targetType] as PlatformConfig;
|
||||||
|
return (
|
||||||
|
<Col span={6} key={`${config.targetType}-${config.target}`}>
|
||||||
|
<Card title={`${platformConf.name} - ${config.targetName}`}
|
||||||
|
actions={[
|
||||||
|
<Tooltip title="删除"><DeleteOutlined /></Tooltip>,
|
||||||
|
<Tooltip title="添加到其他群"><CopyOutlined /></Tooltip>
|
||||||
|
]}>
|
||||||
|
<Form labelCol={{ span: 4 }}>
|
||||||
|
<Form.Item label="订阅类型">
|
||||||
|
{Object.keys(platformConf.categories).length > 0 ?
|
||||||
|
config.cats.map((catKey: number) => (<Tag color="green" key={catKey}>{platformConf.categories[catKey]}</Tag>)) :
|
||||||
|
<Tag color="red">不支持类型</Tag>}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="订阅Tag">
|
||||||
|
{platformConf.enabledTag ? config.tags.length > 0 ? config.tags.map(tag => (<Tag color="green" key={tag}>{tag}</Tag>)) : (<Tag color="blue">全部标签</Tag>) :
|
||||||
|
<Tag color="red">不支持Tag</Tag>}
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (Object.keys(configData).length === 0) {
|
||||||
|
return <Empty />
|
||||||
|
} else {
|
||||||
|
let groups: Array<ReactElement> = [];
|
||||||
|
for (let key of Object.keys(configData)) {
|
||||||
|
let value = configData[key];
|
||||||
|
groups.push(
|
||||||
|
<Collapse.Panel header={<span>{`${key} - ${value.name}`}<Button style={{float: "right"}} onClick={clickNew}>添加</Button></span>} key={key}>
|
||||||
|
<Row gutter={{ xs: 8, sm: 16, md: 24, lg: 32 }} align="middle">
|
||||||
|
{value.subscribes.map(genCard)}
|
||||||
|
</Row>
|
||||||
|
</Collapse.Panel>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Collapse>
|
||||||
|
{groups}
|
||||||
|
</Collapse>
|
||||||
|
<AddModal showModal={showModal} setShowModal={(s: boolean) => setShowModal(_ => s)} />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddModalProp {
|
||||||
|
showModal: boolean,
|
||||||
|
setShowModal: (s: boolean) => void
|
||||||
|
}
|
||||||
|
function AddModal(prop: AddModalProp) {
|
||||||
|
const [ confirmLoading, setConfirmLoading ] = useState<boolean>(false);
|
||||||
|
const { platformConf } = useContext(GlobalConfContext);
|
||||||
|
const [ hasTarget, setHasTarget ] = useState(false);
|
||||||
|
const [ form ] = Form.useForm();
|
||||||
|
const changePlatformSelect = (platform: string) => {
|
||||||
|
setHasTarget(_ => platformConf[platform].hasTarget);
|
||||||
|
if (! platformConf[platform].hasTarget) {
|
||||||
|
getTargetName(platform, 'default')
|
||||||
|
.then(res => {
|
||||||
|
console.log(res)
|
||||||
|
form.setFieldsValue(() => { return {
|
||||||
|
targetName: res.targetName
|
||||||
|
}})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const handleSubmit = (value: any) => {
|
||||||
|
console.log(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Modal title="添加订阅" visible={prop.showModal}
|
||||||
|
confirmLoading={confirmLoading} onCancel={() => prop.setShowModal(false)}>
|
||||||
|
<Form form={form} labelCol={{ span: 6 }} name="b">
|
||||||
|
<Form.Item label="平台" name="platformType" rules={[]}>
|
||||||
|
<Select style={{ width: '80%' }} onChange={changePlatformSelect}>
|
||||||
|
{Object.keys(platformConf).map(platformName =>
|
||||||
|
<Select.Option key={platformName} value={platformName}>{platformConf[platformName].name}</Select.Option>
|
||||||
|
)}
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="账号" name="target" rules={[]}>
|
||||||
|
<Input placeholder={hasTarget ? "获取方式见文档" : "此平台不需要账号"} disabled={! hasTarget} style={{ width: "80%" }} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="账号名称" name="targetName">
|
||||||
|
<Input style={{ width: "80%" }} />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
}
|
}
|
||||||
|
@ -14,4 +14,4 @@ export const loginContextDefault: LoginContextType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const LoginContext = createContext(loginContextDefault);
|
export const LoginContext = createContext(loginContextDefault);
|
||||||
export const GlobalConfContext = createContext<GlobalConf>({platformConf: []});
|
export const GlobalConfContext = createContext<GlobalConf>({platformConf: {}, loaded: false});
|
||||||
|
@ -18,20 +18,30 @@ export type LoginContextType = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface SubscribeConfig {
|
export interface SubscribeConfig {
|
||||||
platform: string
|
targetType: string
|
||||||
target?: string
|
target?: string
|
||||||
catetories: Array<number>
|
targetName: string
|
||||||
|
cats: Array<number>
|
||||||
tags: Array<string>
|
tags: Array<string>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GlobalConf {
|
export interface GlobalConf {
|
||||||
platformConf: Array<PlatformConfig>
|
platformConf: AllPlatformConf,
|
||||||
|
loaded: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AllPlatformConf {
|
||||||
|
[idx: string]: PlatformConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CategoryConfig {
|
||||||
|
[idx: number]: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PlatformConfig {
|
export interface PlatformConfig {
|
||||||
name: string
|
name: string
|
||||||
catetories: Map<number, string>,
|
categories: CategoryConfig
|
||||||
enableTag: boolean,
|
enabledTag: boolean,
|
||||||
platformName: string,
|
platformName: string,
|
||||||
hasTarget: boolean
|
hasTarget: boolean
|
||||||
}
|
}
|
||||||
@ -43,3 +53,16 @@ export interface TokenResp {
|
|||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SubscribeGroupDetail {
|
||||||
|
name: string,
|
||||||
|
subscribes: Array<SubscribeConfig>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SubscribeResp {
|
||||||
|
[idx: string]: SubscribeGroupDetail
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TargetNameResp {
|
||||||
|
targetName: string
|
||||||
|
}
|
||||||
|
86
poetry.lock
generated
86
poetry.lock
generated
@ -1,3 +1,16 @@
|
|||||||
|
[[package]]
|
||||||
|
name = "aiofiles"
|
||||||
|
version = "0.7.0"
|
||||||
|
description = "File support for asyncio."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6,<4.0"
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
type = "legacy"
|
||||||
|
url = "https://mirrors.aliyun.com/pypi/simple"
|
||||||
|
reference = "aliyun"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyio"
|
name = "anyio"
|
||||||
version = "3.3.0"
|
version = "3.3.0"
|
||||||
@ -158,6 +171,19 @@ type = "legacy"
|
|||||||
url = "https://mirrors.aliyun.com/pypi/simple"
|
url = "https://mirrors.aliyun.com/pypi/simple"
|
||||||
reference = "aliyun"
|
reference = "aliyun"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bidict"
|
||||||
|
version = "0.21.3"
|
||||||
|
description = "The bidirectional mapping library for Python."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
type = "legacy"
|
||||||
|
url = "https://mirrors.aliyun.com/pypi/simple"
|
||||||
|
reference = "aliyun"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bs4"
|
name = "bs4"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
@ -928,6 +954,44 @@ type = "legacy"
|
|||||||
url = "https://mirrors.aliyun.com/pypi/simple"
|
url = "https://mirrors.aliyun.com/pypi/simple"
|
||||||
reference = "aliyun"
|
reference = "aliyun"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-engineio"
|
||||||
|
version = "4.2.1"
|
||||||
|
description = "Engine.IO server and client for Python"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
asyncio_client = ["aiohttp (>=3.4)"]
|
||||||
|
client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
type = "legacy"
|
||||||
|
url = "https://mirrors.aliyun.com/pypi/simple"
|
||||||
|
reference = "aliyun"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-socketio"
|
||||||
|
version = "5.4.0"
|
||||||
|
description = "Socket.IO server and client for Python"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
bidict = ">=0.21.0"
|
||||||
|
python-engineio = ">=4.1.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
asyncio_client = ["aiohttp (>=3.4)"]
|
||||||
|
client = ["requests (>=2.21.0)", "websocket-client (>=0.54.0)"]
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
type = "legacy"
|
||||||
|
url = "https://mirrors.aliyun.com/pypi/simple"
|
||||||
|
reference = "aliyun"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytz"
|
name = "pytz"
|
||||||
version = "2021.1"
|
version = "2021.1"
|
||||||
@ -1301,9 +1365,13 @@ reference = "aliyun"
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.9"
|
python-versions = "^3.9"
|
||||||
content-hash = "e485e40f6187e8125f78e7595072280c2a67830ef8cfc3718ecd5f89c0d1064a"
|
content-hash = "2094fead0b3c31a3d27536045ff4bdf6e26ab874ec9f79a6460db14f90bf8140"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
|
aiofiles = [
|
||||||
|
{file = "aiofiles-0.7.0-py3-none-any.whl", hash = "sha256:c67a6823b5f23fcab0a2595a289cec7d8c863ffcb4322fb8cd6b90400aedfdbc"},
|
||||||
|
{file = "aiofiles-0.7.0.tar.gz", hash = "sha256:a1c4fc9b2ff81568c83e21392a82f344ea9d23da906e4f6a52662764545e19d4"},
|
||||||
|
]
|
||||||
anyio = [
|
anyio = [
|
||||||
{file = "anyio-3.3.0-py3-none-any.whl", hash = "sha256:929a6852074397afe1d989002aa96d457e3e1e5441357c60d03e7eea0e65e1b0"},
|
{file = "anyio-3.3.0-py3-none-any.whl", hash = "sha256:929a6852074397afe1d989002aa96d457e3e1e5441357c60d03e7eea0e65e1b0"},
|
||||||
{file = "anyio-3.3.0.tar.gz", hash = "sha256:ae57a67583e5ff8b4af47666ff5651c3732d45fd26c929253748e796af860374"},
|
{file = "anyio-3.3.0.tar.gz", hash = "sha256:ae57a67583e5ff8b4af47666ff5651c3732d45fd26c929253748e796af860374"},
|
||||||
@ -1341,8 +1409,12 @@ beautifulsoup4 = [
|
|||||||
{file = "beautifulsoup4-4.9.3-py3-none-any.whl", hash = "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666"},
|
{file = "beautifulsoup4-4.9.3-py3-none-any.whl", hash = "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666"},
|
||||||
{file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"},
|
{file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"},
|
||||||
]
|
]
|
||||||
|
bidict = [
|
||||||
|
{file = "bidict-0.21.3-py3-none-any.whl", hash = "sha256:2cce0d01eb3db9b3fa85db501c00aaa3389ee4cab7ef82178604552dfa943a1b"},
|
||||||
|
{file = "bidict-0.21.3.tar.gz", hash = "sha256:d50bd81fae75e34198ffc94979a0eb0939ff9adb3ef32bcc93a913d8b3e3ed1d"},
|
||||||
|
]
|
||||||
bs4 = [
|
bs4 = [
|
||||||
{file = "bs4-0.0.1.tar.gz", hash = "md5:fe7e51587ac3b174608f3c4f8bd893ac"},
|
{file = "bs4-0.0.1.tar.gz", hash = "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"},
|
||||||
]
|
]
|
||||||
certifi = [
|
certifi = [
|
||||||
{file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
|
{file = "certifi-2021.5.30-py2.py3-none-any.whl", hash = "sha256:50b1e4f8446b06f41be7dd6338db18e0990601dce795c2b1686458aa7e8fa7d8"},
|
||||||
@ -1651,6 +1723,14 @@ python-dotenv = [
|
|||||||
{file = "python-dotenv-0.19.0.tar.gz", hash = "sha256:f521bc2ac9a8e03c736f62911605c5d83970021e3fa95b37d769e2bbbe9b6172"},
|
{file = "python-dotenv-0.19.0.tar.gz", hash = "sha256:f521bc2ac9a8e03c736f62911605c5d83970021e3fa95b37d769e2bbbe9b6172"},
|
||||||
{file = "python_dotenv-0.19.0-py2.py3-none-any.whl", hash = "sha256:aae25dc1ebe97c420f50b81fb0e5c949659af713f31fdb63c749ca68748f34b1"},
|
{file = "python_dotenv-0.19.0-py2.py3-none-any.whl", hash = "sha256:aae25dc1ebe97c420f50b81fb0e5c949659af713f31fdb63c749ca68748f34b1"},
|
||||||
]
|
]
|
||||||
|
python-engineio = [
|
||||||
|
{file = "python-engineio-4.2.1.tar.gz", hash = "sha256:d510329b6d8ed5662547862f58bc73659ae62defa66b66d745ba021de112fa62"},
|
||||||
|
{file = "python_engineio-4.2.1-py3-none-any.whl", hash = "sha256:f3ef9a2c048d08990f294c5f8991f6f162c3b12ecbd368baa0d90441de907d1c"},
|
||||||
|
]
|
||||||
|
python-socketio = [
|
||||||
|
{file = "python-socketio-5.4.0.tar.gz", hash = "sha256:ca807c9e1f168e96dea412d64dd834fb47c470d27fd83da0504aa4b248ba2544"},
|
||||||
|
{file = "python_socketio-5.4.0-py3-none-any.whl", hash = "sha256:7ed57f6c024abdfeb9b25c74c0c00ffc18da47d903e8d72deecb87584370d1fc"},
|
||||||
|
]
|
||||||
pytz = [
|
pytz = [
|
||||||
{file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
|
{file = "pytz-2021.1-py2.py3-none-any.whl", hash = "sha256:eb10ce3e7736052ed3623d49975ce333bcd712c7bb19a58b9e2089d4057d0798"},
|
||||||
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
|
{file = "pytz-2021.1.tar.gz", hash = "sha256:83a4a90894bf38e243cf052c8b58f381bfe9a7a483f6a9cab140bc7f702ac4da"},
|
||||||
@ -1695,7 +1775,7 @@ rfc3986 = [
|
|||||||
{file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"},
|
{file = "rfc3986-1.5.0.tar.gz", hash = "sha256:270aaf10d87d0d4e095063c65bf3ddbc6ee3d0b226328ce21e036f946e421835"},
|
||||||
]
|
]
|
||||||
sgmllib3k = [
|
sgmllib3k = [
|
||||||
{file = "sgmllib3k-1.0.0.tar.gz", hash = "md5:d70efde06e40797f37e867123aa080ec"},
|
{file = "sgmllib3k-1.0.0.tar.gz", hash = "sha256:7868fb1c8bfa764c1ac563d3cf369c381d1325d36124933a726f29fcdaa812e9"},
|
||||||
]
|
]
|
||||||
six = [
|
six = [
|
||||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||||
|
@ -31,6 +31,8 @@ nonebot-adapter-cqhttp = "^2.0.0-alpha.15"
|
|||||||
apscheduler = "^3.7.0"
|
apscheduler = "^3.7.0"
|
||||||
expiringdict = "^1.2.1"
|
expiringdict = "^1.2.1"
|
||||||
pyjwt = "^2.1.0"
|
pyjwt = "^2.1.0"
|
||||||
|
aiofiles = "^0.7.0"
|
||||||
|
python-socketio = "^5.4.0"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
ipdb = "^0.13.4"
|
ipdb = "^0.13.4"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import importlib
|
import importlib
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
from fastapi.staticfiles import StaticFiles
|
from fastapi.staticfiles import StaticFiles
|
||||||
from nonebot import get_driver, on_command
|
from nonebot import get_driver, on_command
|
||||||
@ -11,25 +12,49 @@ from nonebot.log import logger
|
|||||||
from nonebot.rule import to_me
|
from nonebot.rule import to_me
|
||||||
from nonebot.typing import T_State
|
from nonebot.typing import T_State
|
||||||
import socketio
|
import socketio
|
||||||
|
import functools
|
||||||
|
|
||||||
from .api import test, get_global_conf, auth
|
from .api import test, get_global_conf, auth, get_subs_info, get_target_name
|
||||||
from .token_manager import token_manager as tm
|
from .token_manager import token_manager as tm
|
||||||
|
from .jwt import load_jwt
|
||||||
from ..plugin_config import plugin_config
|
from ..plugin_config import plugin_config
|
||||||
|
|
||||||
URL_BASE = '/hk_reporter/'
|
URL_BASE = '/hk_reporter/'
|
||||||
GLOBAL_CONF_URL = f'{URL_BASE}api/global_conf'
|
GLOBAL_CONF_URL = f'{URL_BASE}api/global_conf'
|
||||||
AUTH_URL = f'{URL_BASE}api/auth'
|
AUTH_URL = f'{URL_BASE}api/auth'
|
||||||
|
SUBSCRIBE_URL = f'{URL_BASE}api/subs'
|
||||||
|
GET_TARGET_NAME_URL = f'{URL_BASE}api/target_name'
|
||||||
TEST_URL = f'{URL_BASE}test'
|
TEST_URL = f'{URL_BASE}test'
|
||||||
|
|
||||||
sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*")
|
sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins="*")
|
||||||
socket_app = socketio.ASGIApp(sio, socketio_path="socket")
|
socket_app = socketio.ASGIApp(sio, socketio_path="socket")
|
||||||
|
|
||||||
|
|
||||||
def register_router_fastapi(driver: Driver, socketio):
|
def register_router_fastapi(driver: Driver, socketio):
|
||||||
|
from fastapi.security import OAuth2PasswordBearer
|
||||||
|
from fastapi.param_functions import Depends
|
||||||
|
from fastapi import HTTPException, status
|
||||||
|
|
||||||
|
oath_scheme = OAuth2PasswordBearer(tokenUrl='token')
|
||||||
|
|
||||||
|
async def get_jwt_obj(token: str = Depends(oath_scheme)):
|
||||||
|
obj = load_jwt(token)
|
||||||
|
if not obj:
|
||||||
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
|
||||||
|
return obj
|
||||||
|
|
||||||
app = driver.server_app
|
app = driver.server_app
|
||||||
static_path = str((Path(__file__).parent / "dist").resolve())
|
static_path = str((Path(__file__).parent / "dist").resolve())
|
||||||
app.get(TEST_URL)(test)
|
app.get(TEST_URL)(test)
|
||||||
app.get(GLOBAL_CONF_URL)(get_global_conf)
|
app.get(GLOBAL_CONF_URL)(get_global_conf)
|
||||||
app.get(AUTH_URL)(auth)
|
app.get(AUTH_URL)(auth)
|
||||||
|
|
||||||
|
@app.get(SUBSCRIBE_URL)
|
||||||
|
async def subs(jwt_obj: dict = Depends(get_jwt_obj)):
|
||||||
|
return await get_subs_info(jwt_obj)
|
||||||
|
@app.get(GET_TARGET_NAME_URL)
|
||||||
|
async def _get_target_name(platformName: str, target: str, jwt_obj: dict = Depends(get_jwt_obj)):
|
||||||
|
return await get_target_name(platformName, target, jwt_obj)
|
||||||
app.mount(URL_BASE, StaticFiles(directory=static_path, html=True), name="hk_reporter")
|
app.mount(URL_BASE, StaticFiles(directory=static_path, html=True), name="hk_reporter")
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from ..platform import platform_manager
|
from ..platform import platform_manager, check_sub_target
|
||||||
from .token_manager import token_manager
|
from .token_manager import token_manager
|
||||||
from .jwt import pack_jwt
|
from .jwt import pack_jwt
|
||||||
from ..config import Config
|
from ..config import Config
|
||||||
@ -9,15 +9,15 @@ async def test():
|
|||||||
return {"status": 200, "text": "test"}
|
return {"status": 200, "text": "test"}
|
||||||
|
|
||||||
async def get_global_conf():
|
async def get_global_conf():
|
||||||
res = []
|
res = {}
|
||||||
for platform_name, platform in platform_manager.items():
|
for platform_name, platform in platform_manager.items():
|
||||||
res.append({
|
res[platform_name] = {
|
||||||
'platformName': platform_name,
|
'platformName': platform_name,
|
||||||
'categories': platform.categories,
|
'categories': platform.categories,
|
||||||
'enabledTag': platform.enable_tag,
|
'enabledTag': platform.enable_tag,
|
||||||
'name': platform.name,
|
'name': platform.name,
|
||||||
'hasTarget': getattr(platform, 'has_target')
|
'hasTarget': getattr(platform, 'has_target')
|
||||||
})
|
}
|
||||||
return { 'platformConf': res }
|
return { 'platformConf': res }
|
||||||
|
|
||||||
|
|
||||||
@ -52,5 +52,14 @@ async def get_subs_info(jwt_obj: dict):
|
|||||||
for group in groups:
|
for group in groups:
|
||||||
group_id = group['id']
|
group_id = group['id']
|
||||||
config = Config()
|
config = Config()
|
||||||
|
subs = list(map(lambda sub: {
|
||||||
|
'targetType': sub['target_type'], 'target': sub['target'], 'targetName': sub['target_name'], 'cats': sub['cats'], 'tags': sub['tags']
|
||||||
|
}, config.list_subscribe(group_id, 'group')))
|
||||||
|
res[group_id] = {
|
||||||
|
'name': group['name'],
|
||||||
|
'subscribes': subs
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
|
||||||
subs = list(map(lambda sub: {'targetType': sub['target_type'], 'target': sub['target'], 'targetName': sub['target_name'], 'cats': sub['cats'], 'tags': sub['tags']},
|
async def get_target_name(platform_name: str, target: str, jwt_obj: dict):
|
||||||
|
return {'targetName': await check_sub_target(platform_name, target)}
|
||||||
|
@ -14,7 +14,7 @@ def pack_jwt(obj: dict) -> str:
|
|||||||
|
|
||||||
def load_jwt(token: str) -> Optional[dict]:
|
def load_jwt(token: str) -> Optional[dict]:
|
||||||
try:
|
try:
|
||||||
return jwt.decode(token, _key, algorithm='HS256')
|
return jwt.decode(token, _key, algorithms=['HS256'])
|
||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user