Files
WebMusic/webmusic-server/src/controller/admin.controller.ts
T
CNLuminous a6af28e4c5 submit
2025-11-04 15:15:28 +08:00

345 lines
7.6 KiB
TypeScript

import { Controller, Get, Post, Body, Param, Inject } from '@midwayjs/core';
import { Context } from '@midwayjs/koa';
import { PlaybackService } from '../service/playback.service';
import { WebSocketService } from '../service/websocket.service';
@Controller('/api/admin')
export class AdminController {
@Inject()
ctx: Context;
@Inject()
playbackService: PlaybackService;
@Inject()
webSocketService: WebSocketService;
/**
* 验证管理员token
*/
private verifyAdminToken(): boolean {
const token = this.ctx.headers.authorization?.replace('Bearer ', '') || this.ctx.query.token;
if (!token) {
this.ctx.status = 401;
this.ctx.body = {
success: false,
message: '未提供认证token',
};
return false;
}
const adminToken = process.env.ADMIN_TOKEN || 'admin123';
if (token !== adminToken) {
this.ctx.status = 403;
this.ctx.body = {
success: false,
message: '无效的认证token',
};
return false;
}
return true;
}
/**
* 管理员登录(获取token)- 不需要token验证
*/
@Post('/login')
async login(@Body() body: { password: string }) {
const adminPassword = process.env.ADMIN_PASSWORD || 'admin';
if (body.password !== adminPassword) {
return {
success: false,
message: '密码错误',
data: null,
};
}
// 返回token(实际生产环境应使用JWT等更安全的方式)
const token = process.env.ADMIN_TOKEN || 'admin123';
return {
success: true,
message: '登录成功',
data: { token },
};
}
/**
* 控制播放/暂停
*/
@Post('/playback/play')
async play() {
if (!this.verifyAdminToken()) {
return;
}
try {
this.playbackService.play();
const state = this.playbackService.getState();
this.webSocketService.broadcastPlaybackState(state);
return {
success: true,
message: '播放命令已发送',
data: state,
};
} catch (error: any) {
return {
success: false,
message: error.message || '播放失败',
data: null,
};
}
}
@Post('/playback/pause')
async pause() {
if (!this.verifyAdminToken()) {
return;
}
try {
this.playbackService.pause();
const state = this.playbackService.getState();
this.webSocketService.broadcastPlaybackState(state);
return {
success: true,
message: '暂停命令已发送',
data: state,
};
} catch (error: any) {
return {
success: false,
message: error.message || '暂停失败',
data: null,
};
}
}
/**
* 发送公告
*/
@Post('/announcement')
async sendAnnouncement(@Body() body: { title: string; content: string; duration?: number }) {
if (!this.verifyAdminToken()) {
return;
}
if (!body.title || !body.content) {
return {
success: false,
message: '标题和内容不能为空',
data: null,
};
}
try {
this.webSocketService.broadcastAnnouncement({
title: body.title,
content: body.content,
duration: body.duration || 5000, // 默认5秒
});
return {
success: true,
message: '公告已发送',
data: null,
};
} catch (error: any) {
return {
success: false,
message: error.message || '发送公告失败',
data: null,
};
}
}
/**
* 控制特定用户的音量
*/
@Post('/user/:userId/volume')
async setUserVolume(@Body() body: { volume: number; muted?: boolean }, @Param('userId') userId: string) {
if (!this.verifyAdminToken()) {
return;
}
// 确保userId是字符串
if (typeof userId !== 'string') {
return {
success: false,
message: '无效的用户ID',
data: null,
};
}
const volume = body.volume;
const muted = body.muted;
if (volume === undefined || volume < 0 || volume > 1) {
return {
success: false,
message: '音量值必须在0-1之间',
data: null,
};
}
console.log(`管理员请求控制用户 ${userId} 的音量:`, { volume, muted });
try {
const success = this.webSocketService.sendVolumeControlToUser(userId, {
volume,
muted,
});
if (!success) {
return {
success: false,
message: '用户不在线或连接已断开',
data: null,
};
}
return {
success: true,
message: '音量控制命令已发送',
data: { volume, muted },
};
} catch (error: any) {
return {
success: false,
message: error.message || '设置音量失败',
data: null,
};
}
}
/**
* 控制特定用户的静音状态
*/
@Post('/user/:userId/mute')
async setUserMute(@Body() body: { muted: boolean }, @Param('userId') userId: string) {
if (!this.verifyAdminToken()) {
return;
}
// 确保userId是字符串
if (typeof userId !== 'string') {
return {
success: false,
message: '无效的用户ID',
data: null,
};
}
const muted = body.muted;
if (typeof muted !== 'boolean') {
return {
success: false,
message: 'muted必须是布尔值',
data: null,
};
}
console.log(`管理员请求控制用户 ${userId} 的静音状态:`, muted);
try {
// 静音时音量设为0,取消静音时恢复默认音量0.5(或根据实际情况调整)
const volume = muted ? 0 : 0.5;
const success = this.webSocketService.sendVolumeControlToUser(userId, {
volume,
muted,
});
if (!success) {
return {
success: false,
message: '用户不在线或连接已断开',
data: null,
};
}
return {
success: true,
message: muted ? '静音命令已发送' : '取消静音命令已发送',
data: { muted, volume },
};
} catch (error: any) {
return {
success: false,
message: error.message || '设置静音失败',
data: null,
};
}
}
/**
* 获取当前播放状态
*/
@Get('/playback/state')
async getPlaybackState() {
if (!this.verifyAdminToken()) {
return;
}
const state = this.playbackService.getState();
return {
success: true,
message: 'OK',
data: state,
};
}
/**
* 调整播放进度
*/
@Post('/playback/seek')
async seek(@Body() body: { time: number }) {
if (!this.verifyAdminToken()) {
return;
}
if (body.time === undefined || body.time === null) {
return {
success: false,
message: '时间不能为空',
data: null,
};
}
try {
this.playbackService.setCurrentTime(body.time);
const state = this.playbackService.getState();
this.webSocketService.broadcastPlaybackState(state);
return {
success: true,
message: 'OK',
data: state,
};
} catch (error: any) {
return {
success: false,
message: error.message || '调整进度失败',
data: null,
};
}
}
/**
* 获取所有在线用户
*/
@Get('/users')
async getAllUsers() {
if (!this.verifyAdminToken()) {
return;
}
const users = this.webSocketService.getAllUsers();
return {
success: true,
message: 'OK',
data: users,
};
}
}