This commit is contained in:
fanxb 2023-07-28 20:12:34 +08:00
parent 4002db4c22
commit 69dcbd22b0
8 changed files with 141 additions and 112 deletions

View File

@ -1,4 +1,4 @@
import { Context } from "koa";
import {Context} from "koa";
import service from "../service/QbService";
const router = {};
@ -7,7 +7,14 @@ const router = {};
*
*/
router["POST /qb/saveQbInfo"] = async function (ctx: Context) {
ctx.body = await service.saveAddress(ctx.request.body);
ctx.body = await service.saveAddress(ctx.request.body);
};
/**
* qb配置
*/
router["GET /qb/config"] = async function (ctx: Context) {
ctx.body = await service.getAddress();
};

View File

@ -1,5 +1,6 @@
export default interface QbAddressDto {
address: string;
username: string;
password: string;
address: string;
username: string;
password: string;
valid: boolean;
}

View File

@ -9,8 +9,8 @@ import handleError from "./middleware/handleError";
import init from "./middleware/init";
import SqliteUtil from './util/SqliteHelper';
import log from './util/LogUtil';
import {updateQbInfo} from './util/QbApiUtil';
import QbService from './service/QbService';
import qbService from "./service/QbService";
console.log(config);
@ -32,7 +32,7 @@ app.use(handleError);
app.use(RouterMW(router, path.join(config.rootPath, "dist/api")));
(async () => {
await SqliteUtil.createPool();
await updateQbInfo(null, null);
await qbService.init();
app.listen(config.port);
log.info(`server listened `, config.port);
})();

View File

@ -22,6 +22,7 @@
"log4js": "^6.3.0",
"moment": "^2.22.2",
"mysql2": "^2.2.5",
"querystring": "^0.2.1",
"sqlite": "^4.0.23",
"sqlite3": "^5.0.2",
"uuid": "^3.3.2",

View File

@ -1,17 +1,41 @@
import QbAddressDto from "../entity/dto/QbAddressDto";
import { tryLogin, updateQbInfo } from '../util/QbApiUtil';
import {tryLogin, updateQbInfo, getQbInfo} from '../util/QbApiUtil';
import GlobalConfigService from "./GlobalConfigService";
import GlobalConfig from "../entity/po/GlobalConfig";
class QbService {
static async saveAddress(body: QbAddressDto) {
await tryLogin(body.address, body.username, body.password, false);
await GlobalConfigService.insertOrReplace(new GlobalConfig("qbAddress", body.address, "qbAdress"));
await GlobalConfigService.insertOrReplace(new GlobalConfig("qbUsername", body.username, ""));
await GlobalConfigService.insertOrReplace(new GlobalConfig("qbPassword", body.password, ""));
await updateQbInfo(body, true);
}
/**
*
* @param body
*/
static async saveAddress(body: QbAddressDto): Promise<boolean> {
await GlobalConfigService.insertOrReplace(new GlobalConfig("qbAddress", body.address, "qbAdress"));
await GlobalConfigService.insertOrReplace(new GlobalConfig("qbUsername", body.username, ""));
await GlobalConfigService.insertOrReplace(new GlobalConfig("qbPassword", body.password, ""));
body.valid = await tryLogin();
updateQbInfo(body);
return body.valid;
}
/**
*
*/
static async getAddress(): Promise<QbAddressDto> {
return getQbInfo();
}
static async init() {
let config = await GlobalConfigService.getMultVal(["qbAddress", "qbUsername", "qbPassword"]);
let qbInfo: QbAddressDto = {
address: config.qbAddress,
username: config.qbUsername,
password: config.qbPassword,
valid: true
}
updateQbInfo(qbInfo);
qbInfo.valid = await tryLogin();
}
}
export default QbService;

View File

@ -1,36 +1,18 @@
import { Method } from "axios";
import {Method} from "axios";
import axios from "axios";
import querystring from "querystring";
import QbAddressDto from "../entity/dto/QbAddressDto";
import GlobalService from '../service/GlobalConfigService';
import { setUncaughtExceptionCaptureCallback } from "process";
//qb状态true正常false:无法访问
let qbStatus = true;
let qbInfo: QbAddressDto = null;
let cookie: string = null;
export function getQbStatus() {
return qbStatus;
export function updateQbInfo(info: QbAddressDto) {
qbInfo = info;
}
export async function updateQbInfo(info: QbAddressDto, status: boolean) {
if (!info) {
let obj = await GlobalService.getMultVal(["qbAddress", "qbUsername", "qbPassword"]);
if (!obj.qbAddress) {
qbStatus = false;
return;
}
qbInfo.address = obj.qbAddress;
qbInfo.username = obj.qbUsername;
qbInfo.password = obj.qbPassword;
} else {
qbInfo = info;
}
if (status) {
qbStatus = status;
}
axios.defaults.baseURL = qbInfo.address;
export function getQbInfo() {
return qbInfo;
}
export function get() {
@ -42,61 +24,60 @@ export function post() {
}
async function request(method: Method, url: string, query: any, body: any, isForm = false) {
if (!qbStatus) {
throw new Error("qbittorrent无法连接请检查配置");
}
let isTryLogin = false;
while (true) {
let headers = { "Cookie": cookie };
if (isForm) {
headers['content-type'] = "multipart/form-data";
} else if (method == "post") {
headers['content-type'] = "application/json";
}
let res = await axios.request({
baseURL: qbInfo.address,
url: url,
method,
params: query,
data: body,
headers,
});
if (res.status == 200) {
return res.data;
} if (res.status == 403) {
if (isTryLogin) {
throw new Error("qb用户名密码设置有误");
} else {
await tryLogin(qbInfo.address, qbInfo.username, qbInfo.password, true);
isTryLogin = true;
}
} else {
throw new Error("请求报错:" + res.data);
}
}
if (!qbInfo.valid) {
throw new Error("qbittorrent无法连接请检查配置");
}
let isTryLogin = false;
while (true) {
let headers = {"Cookie": cookie};
if (isForm) {
headers['content-type'] = "multipart/form-data";
} else if (method == "post") {
headers['content-type'] = "application/json";
}
let res = await axios.request({
baseURL: qbInfo.address,
url: url,
method,
params: query,
data: body,
headers,
});
if (res.status == 200) {
return res.data;
}
if (res.status == 403) {
if (isTryLogin) {
throw new Error("qb用户名密码设置有误");
} else {
await tryLogin();
isTryLogin = true;
}
} else {
throw new Error("请求报错:" + res.data);
}
}
}
export async function tryLogin(address: string, username: string, password: string, updateStatus: boolean): Promise<void> {
let body = { username, password };
try {
let res = await axios.post(address + "/api/v2/auth/login", body, {
headers: { "Content-Type": "multipart/form-data;boundary=--------------------------125002698093981740970152" }
});
let success = res.data.toLocaleLowerCase().contains('ok');
if (updateStatus) {
qbStatus = success;
}
if (!success) {
throw new Error("登录失败");
} else {
cookie = res.headers['Cookie'];
}
} catch (error) {
console.error("登录报错:", error);
if (updateStatus) {
qbStatus = false;
}
throw new Error("登录出错");
}
export async function tryLogin(): Promise<boolean> {
if (qbInfo == null || qbInfo.address == null || qbInfo.address == "") {
return false;
}
let body = {username: qbInfo.username, password: qbInfo.password};
try {
let res = await axios.post(qbInfo.address + `/api/v2/auth/login`, querystring.stringify(body), {
headers: {"Content-Type": "application/x-www-form-urlencoded"}
});
let success = res.data.toLocaleLowerCase().indexOf('ok') > -1;
if (success) {
cookie = res.headers['Cookie'];
}
qbInfo.valid = success;
return success;
} catch (error) {
console.error("登录报错:", error);
return false;
}
}

View File

@ -4,11 +4,11 @@
active-text-color="#ffd04b" router>
<el-menu-item index="/">重命名</el-menu-item>
<!-- <el-menu-item index="/auto">自动化</el-menu-item>-->
<!-- <el-sub-menu index="/download">
<el-sub-menu index="/download">
<template #title>bt下载</template>
<el-menu-item index="/download/center">下载中心</el-menu-item>
<el-menu-item index="/download/config">配置</el-menu-item>
</el-sub-menu> -->
</el-sub-menu>
</el-menu>
<div class="content">
<router-view/>

View File

@ -2,12 +2,20 @@
<div>配置qb</div>
<div class="item">
<div class="left">qb信息</div>
<div class="right">{{ qbInfo }}<el-button @click="editInfo = true">编辑</el-button></div>
<div class="right">{{ qbInfo }}
<el-button @click="editInfo = true">编辑</el-button>
</div>
</div>
<el-form v-if="editInfo" :model="qbBody" label-width="4em">
<el-form-item label="qb地址"><el-input type="text" v-model="qbBody.address" placeholder="例如:http://192.168.1.4:8080" /></el-form-item>
<el-form-item label="用户名"><el-input type="text" v-model="qbBody.username" placeholder="qb访问用户名" /></el-form-item>
<el-form-item label="密码"><el-input type="password" v-model="qbBody.password" placeholder="qb访问密码" /></el-form-item>
<el-form v-if="editInfo" :model="data.qbConfig" label-width="4em">
<el-form-item label="qb地址">
<el-input type="text" v-model="data.qbConfig.address" placeholder="例如:http://192.168.1.4:8080"/>
</el-form-item>
<el-form-item label="用户名">
<el-input type="text" v-model="data.qbConfig.username" placeholder="qb访问用户名"/>
</el-form-item>
<el-form-item label="密码">
<el-input type="password" v-model="data.qbConfig.password" placeholder="qb访问密码"/>
</el-form-item>
<div style="text-align: center">
<el-button type="" @click="editInfo = false">取消</el-button>
<el-button type="primary" @click="submitQb">提交</el-button>
@ -16,34 +24,39 @@
</template>
<script setup>
import { ref, reactive, onMounted, computed } from "vue";
import {ref, reactive, onMounted, computed} from "vue";
import http from "@/utils/HttpUtil";
//
const qbBody = reactive({
address: "",
username: "",
password: "",
const data = reactive({
currentQbConfig: {},
qbConfig: {
address: "",
username: "",
password: "",
},
});
//
let downloadConfig = reactive({});
//qb访
let qbReach = ref(true);
let editInfo = ref(false);
const qbInfo = computed(() => {
if (downloadConfig.qbAddress) {
return downloadConfig.qbAddress + " 用户名:" + downloadConfig.qbUsername;
console.log("数据变了", data.qbConfig);
if (data.currentQbConfig.address) {
return data.qbConfig.address + " 用户名:" + data.qbConfig.username + " " + (data.currentQbConfig.valid ? "配置有效" : "配置无效");
} else {
return "尚未配置";
}
});
onMounted(async () => {
downloadConfig = reactive(await http.post("/config/multCode", null, ["qbAddress", "qbUsername", "qbPassword"]));
data.currentQbConfig = await http.get("/qb/config");
data.qbConfig.address = data.currentQbConfig.address;
data.qbConfig.username = data.currentQbConfig.username;
data.qbConfig.password = data.currentQbConfig.password;
});
async function submitQb() {
let res = await http.post("");
let res = await http.post("/qb/saveQbInfo", null, qbBody);
}
</script>
@ -52,10 +65,12 @@ async function submitQb() {
display: flex;
text-align: left;
padding-bottom: 0.5em;
.left {
width: 6em;
font-weight: 600;
}
.right {
flex: 1;
}