mirror of
https://github.com/jiangrui1994/CloudSaver.git
synced 2026-04-07 21:35:08 +08:00
Refactoring the backend
This commit is contained in:
17
backend/src/controllers/BaseController.ts
Normal file
17
backend/src/controllers/BaseController.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { Request, Response } from "express";
|
||||
import { ApiResponse } from "../core/ApiResponse";
|
||||
|
||||
export abstract class BaseController {
|
||||
protected async handleRequest<T>(
|
||||
req: Request,
|
||||
res: Response,
|
||||
action: () => Promise<T>
|
||||
): Promise<void> {
|
||||
try {
|
||||
const result = await action();
|
||||
res.json(ApiResponse.success(result));
|
||||
} catch (error: any) {
|
||||
res.status(500).json(ApiResponse.error(error?.message || "未知错误"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,9 @@ import { Request, Response } from "express";
|
||||
import { Cloud115Service } from "../services/Cloud115Service";
|
||||
import { sendSuccess, sendError } from "../utils/response";
|
||||
import UserSetting from "../models/UserSetting";
|
||||
import { BaseController } from "./BaseController";
|
||||
import { injectable, inject } from "inversify";
|
||||
import { TYPES } from "../core/types";
|
||||
|
||||
const cloud115 = new Cloud115Service();
|
||||
const setCookie = async (req: Request): Promise<void> => {
|
||||
@@ -16,18 +19,19 @@ const setCookie = async (req: Request): Promise<void> => {
|
||||
}
|
||||
};
|
||||
|
||||
export const cloud115Controller = {
|
||||
@injectable()
|
||||
export class Cloud115Controller extends BaseController {
|
||||
constructor(@inject(TYPES.Cloud115Service) private cloud115Service: Cloud115Service) {
|
||||
super();
|
||||
}
|
||||
|
||||
async getShareInfo(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
await this.handleRequest(req, res, async () => {
|
||||
const { shareCode, receiveCode } = req.query;
|
||||
await setCookie(req);
|
||||
const result = await cloud115.getShareInfo(shareCode as string, receiveCode as string);
|
||||
sendSuccess(res, result);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
sendError(res, { message: (error as Error).message || "获取分享信息失败" });
|
||||
}
|
||||
},
|
||||
await this.cloud115Service.setCookie(req);
|
||||
return await this.cloud115Service.getShareInfo(shareCode as string, receiveCode as string);
|
||||
});
|
||||
}
|
||||
|
||||
async getFolderList(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
@@ -38,7 +42,7 @@ export const cloud115Controller = {
|
||||
} catch (error) {
|
||||
sendError(res, { message: (error as Error).message || "获取目录列表失败" });
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
async saveFile(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
@@ -54,7 +58,7 @@ export const cloud115Controller = {
|
||||
} catch (error) {
|
||||
sendError(res, { message: (error as Error).message || "保存文件失败" });
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const Cloud115ServiceInstance = cloud115;
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
import { Request, Response } from "express";
|
||||
import DoubanService from "../services/DoubanService";
|
||||
import { sendSuccess, sendError } from "../utils/response";
|
||||
import { injectable, inject } from "inversify";
|
||||
import { TYPES } from "../core/types";
|
||||
import { DoubanService } from "../services/DoubanService";
|
||||
import { BaseController } from "./BaseController";
|
||||
|
||||
const doubanService = new DoubanService();
|
||||
@injectable()
|
||||
export class DoubanController extends BaseController {
|
||||
constructor(@inject(TYPES.DoubanService) private doubanService: DoubanService) {
|
||||
super();
|
||||
}
|
||||
|
||||
export const doubanController = {
|
||||
async getDoubanHotList(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
await this.handleRequest(req, res, async () => {
|
||||
const { type = "movie", tag = "热门", page_limit = "50", page_start = "0" } = req.query;
|
||||
const result = await doubanService.getHotList({
|
||||
const result = await this.doubanService.getHotList({
|
||||
type: type as string,
|
||||
tag: tag as string,
|
||||
page_limit: page_limit as string,
|
||||
page_start: page_start as string,
|
||||
});
|
||||
sendSuccess(res, result);
|
||||
} catch (error) {
|
||||
sendError(res, { message: "获取热门列表失败" });
|
||||
}
|
||||
},
|
||||
};
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +1,42 @@
|
||||
import { Request, Response } from "express";
|
||||
import { injectable, inject } from "inversify";
|
||||
import { TYPES } from "../core/types";
|
||||
import { QuarkService } from "../services/QuarkService";
|
||||
import { sendSuccess, sendError } from "../utils/response";
|
||||
import UserSetting from "../models/UserSetting";
|
||||
import { BaseController } from "./BaseController";
|
||||
import { sendSuccess } from "../utils/response";
|
||||
|
||||
const quark = new QuarkService();
|
||||
|
||||
const setCookie = async (req: Request): Promise<void> => {
|
||||
const userId = req.user?.userId;
|
||||
const userSetting = await UserSetting.findOne({
|
||||
where: { userId },
|
||||
});
|
||||
if (userSetting && userSetting.dataValues.quarkCookie) {
|
||||
quark.setCookie(userSetting.dataValues.quarkCookie);
|
||||
} else {
|
||||
throw new Error("请先设置夸克网盘cookie");
|
||||
@injectable()
|
||||
export class QuarkController extends BaseController {
|
||||
constructor(@inject(TYPES.QuarkService) private quarkService: QuarkService) {
|
||||
super();
|
||||
}
|
||||
};
|
||||
|
||||
export const quarkController = {
|
||||
async getShareInfo(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { pwdId, passcode } = req.query;
|
||||
await setCookie(req);
|
||||
const result = await quark.getShareInfo(pwdId as string, passcode as string);
|
||||
await this.handleRequest(req, res, async () => {
|
||||
const { shareCode, receiveCode } = req.query;
|
||||
await this.quarkService.setCookie(req);
|
||||
const result = await this.quarkService.getShareInfo(
|
||||
shareCode as string,
|
||||
receiveCode as string
|
||||
);
|
||||
sendSuccess(res, result);
|
||||
} catch (error) {
|
||||
sendError(res, { message: "获取分享信息失败" });
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async getFolderList(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
await this.handleRequest(req, res, async () => {
|
||||
const { parentCid } = req.query;
|
||||
await setCookie(req);
|
||||
const result = await quark.getFolderList(parentCid as string);
|
||||
await this.quarkService.setCookie(req);
|
||||
const result = await this.quarkService.getFolderList(parentCid as string);
|
||||
sendSuccess(res, result);
|
||||
} catch (error) {
|
||||
sendError(res, { message: (error as Error).message || "获取目录列表失败" });
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async saveFile(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
await setCookie(req);
|
||||
const result = await quark.saveSharedFile(req.body);
|
||||
await this.handleRequest(req, res, async () => {
|
||||
await this.quarkService.setCookie(req);
|
||||
const result = await this.quarkService.saveSharedFile(req.body);
|
||||
sendSuccess(res, result);
|
||||
} catch (error) {
|
||||
sendError(res, { message: (error as Error).message || "保存文件失败" });
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
import { Request, Response } from "express";
|
||||
import Searcher from "../services/Searcher";
|
||||
import { sendSuccess, sendError } from "../utils/response";
|
||||
import { injectable, inject } from "inversify";
|
||||
import { TYPES } from "../core/types";
|
||||
import { Searcher } from "../services/Searcher";
|
||||
import { BaseController } from "./BaseController";
|
||||
import { sendSuccess } from "../utils/response";
|
||||
|
||||
@injectable()
|
||||
export class ResourceController extends BaseController {
|
||||
constructor(@inject(TYPES.Searcher) private searcher: Searcher) {
|
||||
super();
|
||||
}
|
||||
|
||||
export const resourceController = {
|
||||
async search(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const { keyword, channelId = "", lastMessageId = "" } = req.query; // Remove `: string` from here
|
||||
const result = await Searcher.searchAll(
|
||||
await this.handleRequest(req, res, async () => {
|
||||
const { keyword, channelId = "", lastMessageId = "" } = req.query;
|
||||
const result = await this.searcher.searchAll(
|
||||
keyword as string,
|
||||
channelId as string,
|
||||
lastMessageId as string
|
||||
);
|
||||
sendSuccess(res, result);
|
||||
} catch (error) {
|
||||
sendError(res, {
|
||||
message: (error as Error).message || "搜索资源失败",
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +1,28 @@
|
||||
import { Request, Response } from "express";
|
||||
import { sendSuccess, sendError } from "../utils/response";
|
||||
import Searcher from "../services/Searcher";
|
||||
import UserSetting from "../models/UserSetting";
|
||||
import GlobalSetting from "../models/GlobalSetting";
|
||||
import { iamgesInstance } from "./teleImages";
|
||||
import { injectable, inject } from "inversify";
|
||||
import { TYPES } from "../core/types";
|
||||
import { SettingService } from "../services/SettingService";
|
||||
import { BaseController } from "./BaseController";
|
||||
|
||||
@injectable()
|
||||
export class SettingController extends BaseController {
|
||||
constructor(@inject(TYPES.SettingService) private settingService: SettingService) {
|
||||
super();
|
||||
}
|
||||
|
||||
export const settingController = {
|
||||
async get(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const userId = req.user?.userId;
|
||||
const role = req.user?.role;
|
||||
if (userId !== null) {
|
||||
let userSettings = await UserSetting.findOne({ where: { userId } });
|
||||
if (!userSettings) {
|
||||
userSettings = {
|
||||
userId: userId,
|
||||
cloud115Cookie: "",
|
||||
quarkCookie: "",
|
||||
} as UserSetting;
|
||||
if (userSettings) {
|
||||
await UserSetting.create(userSettings);
|
||||
}
|
||||
}
|
||||
const globalSetting = await GlobalSetting.findOne();
|
||||
sendSuccess(res, {
|
||||
data: {
|
||||
userSettings,
|
||||
globalSetting: role === 1 ? globalSetting : null,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
sendError(res, { message: "用户ID无效" });
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("获取设置失败:" + error);
|
||||
sendError(res, { message: (error as Error).message || "获取设置失败" });
|
||||
}
|
||||
},
|
||||
await this.handleRequest(req, res, async () => {
|
||||
const userId = Number(req.user?.userId);
|
||||
const role = Number(req.user?.role);
|
||||
return await this.settingService.getSettings(userId, role);
|
||||
});
|
||||
}
|
||||
|
||||
async save(req: Request, res: Response): Promise<void> {
|
||||
try {
|
||||
const userId = req.user?.userId;
|
||||
const role = req.user?.role;
|
||||
if (userId !== null) {
|
||||
const { userSettings, globalSetting } = req.body;
|
||||
await UserSetting.update(userSettings, { where: { userId } });
|
||||
if (role === 1 && globalSetting) await GlobalSetting.update(globalSetting, { where: {} });
|
||||
Searcher.updateAxiosInstance();
|
||||
iamgesInstance.updateProxyConfig();
|
||||
sendSuccess(res, {
|
||||
message: "保存成功",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("保存设置失败:" + error);
|
||||
sendError(res, { message: (error as Error).message || "保存设置失败" });
|
||||
}
|
||||
},
|
||||
};
|
||||
await this.handleRequest(req, res, async () => {
|
||||
const userId = Number(req.user?.userId);
|
||||
const role = Number(req.user?.role);
|
||||
return await this.settingService.saveSettings(userId, role, req.body);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +1,19 @@
|
||||
import axios, { AxiosInstance } from "axios";
|
||||
import e, { Request, Response } from "express";
|
||||
import tunnel from "tunnel";
|
||||
import GlobalSetting from "../models/GlobalSetting";
|
||||
import { GlobalSettingAttributes } from "../models/GlobalSetting";
|
||||
import { Request, Response } from "express";
|
||||
import { injectable, inject } from "inversify";
|
||||
import { TYPES } from "../core/types";
|
||||
import { ImageService } from "../services/ImageService";
|
||||
import { BaseController } from "./BaseController";
|
||||
|
||||
export class ImageControll {
|
||||
private axiosInstance: AxiosInstance | null = null;
|
||||
private settings: GlobalSetting | null = null;
|
||||
|
||||
constructor() {
|
||||
this.initializeAxiosInstance();
|
||||
@injectable()
|
||||
export class ImageController extends BaseController {
|
||||
constructor(@inject(TYPES.ImageService) private imageService: ImageService) {
|
||||
super();
|
||||
}
|
||||
|
||||
private async initializeAxiosInstance(): Promise<void> {
|
||||
try {
|
||||
this.settings = await GlobalSetting.findOne();
|
||||
} catch (error) {
|
||||
console.error("Error fetching global settings:", error);
|
||||
}
|
||||
const globalSetting = this.settings?.dataValues || ({} as GlobalSettingAttributes);
|
||||
this.axiosInstance = axios.create({
|
||||
timeout: 3000,
|
||||
httpsAgent: globalSetting.isProxyEnabled
|
||||
? tunnel.httpsOverHttp({
|
||||
proxy: {
|
||||
host: globalSetting.httpProxyHost,
|
||||
port: globalSetting.httpProxyPort,
|
||||
headers: {
|
||||
"Proxy-Authorization": "",
|
||||
},
|
||||
},
|
||||
})
|
||||
: undefined,
|
||||
withCredentials: true,
|
||||
async getImages(req: Request, res: Response): Promise<void> {
|
||||
await this.handleRequest(req, res, async () => {
|
||||
const url = req.query.url as string;
|
||||
return await this.imageService.getImages(url);
|
||||
});
|
||||
}
|
||||
public async updateProxyConfig(): Promise<void> {
|
||||
try {
|
||||
this.settings = await GlobalSetting.findOne();
|
||||
const globalSetting = this.settings?.dataValues || ({} as GlobalSettingAttributes);
|
||||
if (this.axiosInstance) {
|
||||
this.axiosInstance.defaults.httpsAgent = globalSetting.isProxyEnabled
|
||||
? tunnel.httpsOverHttp({
|
||||
proxy: {
|
||||
host: globalSetting.httpProxyHost,
|
||||
port: globalSetting.httpProxyPort,
|
||||
headers: {
|
||||
"Proxy-Authorization": "",
|
||||
},
|
||||
},
|
||||
})
|
||||
: undefined;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating proxy config:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async getImages(req: Request, res: Response, url: string): Promise<void> {
|
||||
try {
|
||||
const response = await this.axiosInstance?.get(url, { responseType: "stream" });
|
||||
res.set("Content-Type", response?.headers["content-type"]);
|
||||
response?.data.pipe(res);
|
||||
} catch (error) {
|
||||
res.status(500).send("Image fetch error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const iamgesInstance = new ImageControll();
|
||||
|
||||
export const imageControll = {
|
||||
getImages: async (req: Request, res: Response): Promise<void> => {
|
||||
const url = req.query.url as string;
|
||||
iamgesInstance.getImages(req, res, url);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,62 +1,26 @@
|
||||
import { Request, Response } from "express";
|
||||
import bcrypt from "bcrypt";
|
||||
import jwt from "jsonwebtoken";
|
||||
import GlobalSetting from "../models/GlobalSetting";
|
||||
import User from "../models/User";
|
||||
import { config } from "../config";
|
||||
import { sendSuccess, sendError } from "../utils/response";
|
||||
import { injectable, inject } from "inversify";
|
||||
import { TYPES } from "../core/types";
|
||||
import { UserService } from "../services/UserService";
|
||||
import { BaseController } from "./BaseController";
|
||||
|
||||
@injectable()
|
||||
export class UserController extends BaseController {
|
||||
constructor(@inject(TYPES.UserService) private userService: UserService) {
|
||||
super();
|
||||
}
|
||||
|
||||
const isValidInput = (input: string): boolean => {
|
||||
// 检查是否包含空格或汉字
|
||||
const regex = /^[^\s\u4e00-\u9fa5]+$/;
|
||||
return regex.test(input);
|
||||
};
|
||||
export const userController = {
|
||||
async register(req: Request, res: Response): Promise<void> {
|
||||
const { username, password, registerCode } = req.body;
|
||||
const globalSetting = await GlobalSetting.findOne();
|
||||
const registerCodeList = [
|
||||
globalSetting?.dataValues.CommonUserCode,
|
||||
globalSetting?.dataValues.AdminUserCode,
|
||||
];
|
||||
if (!registerCode || !registerCodeList.includes(Number(registerCode))) {
|
||||
return sendError(res, { message: "注册码错误" });
|
||||
}
|
||||
// 验证输入
|
||||
if (!isValidInput(username) || !isValidInput(password)) {
|
||||
return sendError(res, { message: "用户名、密码或注册码不能包含空格或汉字" });
|
||||
}
|
||||
// 检查用户名是否已存在
|
||||
const existingUser = await User.findOne({ where: { username } });
|
||||
if (existingUser) {
|
||||
return sendError(res, { message: "用户名已存在" });
|
||||
}
|
||||
const hashedPassword = await bcrypt.hash(password, 10);
|
||||
try {
|
||||
const role = registerCodeList.findIndex((x) => x === Number(registerCode));
|
||||
const user = await User.create({ username, password: hashedPassword, role });
|
||||
sendSuccess(res, {
|
||||
data: user,
|
||||
message: "用户注册成功",
|
||||
});
|
||||
} catch (error) {
|
||||
sendError(res, { message: (error as Error).message || "用户注册失败" });
|
||||
}
|
||||
},
|
||||
await this.handleRequest(req, res, async () => {
|
||||
const { username, password, code } = req.body;
|
||||
return await this.userService.register(username, password, code);
|
||||
});
|
||||
}
|
||||
|
||||
async login(req: Request, res: Response): Promise<void> {
|
||||
const { username, password } = req.body;
|
||||
const user = await User.findOne({ where: { username } });
|
||||
if (!user || !(await bcrypt.compare(password, user.password))) {
|
||||
return sendError(res, { message: "用户名或密码错误" });
|
||||
}
|
||||
const token = jwt.sign({ userId: user.userId, role: user.role }, config.jwtSecret, {
|
||||
expiresIn: "6h",
|
||||
await this.handleRequest(req, res, async () => {
|
||||
const { username, password } = req.body;
|
||||
return await this.userService.login(username, password);
|
||||
});
|
||||
sendSuccess(res, {
|
||||
data: {
|
||||
token,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user