Files
fanqie-go/internal/fqapi/audio.go
T
chenxin 5bcc8a962e ♻️ refactor(handlers): status 与 review 页面模板化
- HTML 提取至 templates/status.html、templates/review.html(go:embed 内嵌)
- status.go 1022→271 行、review.go 1281→438 行,动态数据全部经 html/template 按上下文自动转义
- 评论循环/作者徽章/贴纸/图片条件渲染翻译为模板 range/if;emojiMap 以 template.JS 注入
- 与旧版渲染输出实测对比:22 条评论结构完全一致;差异仅为 JS 上下文安全转义(& 等)与 html/template 剥除 CSS 注释,均无功能影响
- 其余文件为 gofmt 顺手格式化
2026-09-30 00:25:09 +08:00

135 lines
4.0 KiB
Go

package fqapi
import (
"encoding/json"
"fanqie/internal/common"
"fmt"
)
var audioLogger = common.NewLogger("audio", "INFO", "")
// HandleAudio 处理获取音频
func HandleAudio(itemIDs interface{}, toneID interface{}, output interface{}) (string, error) {
if itemIDs == nil || itemIDs == "" {
return BuildSuccessResponse([]interface{}{}), nil
}
// 处理itemIDs - 使用ParseStringParam
itemIDStr := ParseStringParam(itemIDs, "")
// 处理toneID - 使用ParseIntParam
toneIDInt := ParseIntParam(toneID, 1)
// 处理output参数
outputStr := ParseStringParam(output, "url")
// 使用 BuildURL 添加设备参数
url := BuildURL("https://reading.snssdk.com/reading/reader/audio/playinfo/",
fmt.Sprintf("item_ids=%s", itemIDStr),
fmt.Sprintf("tone_id=%d", toneIDInt),
"pv_player=-1",
)
// 使用 GorgonRequest 添加签名和设备信息
resp, err := GorgonRequest(url, map[string]interface{}{
"method": "GET",
"headers": map[string]string{
"User-Agent": "com.dragon.read",
},
})
if err != nil {
audioLogger.Error(fmt.Sprintf("获取音频失败: %v", err))
return BuildErrorResponse("获取音频失败"), err
}
respJSON, err := resp.JSON()
if err != nil {
audioLogger.Error(fmt.Sprintf("解析响应失败: %v", err))
return BuildErrorResponse("解析响应失败"), err
}
// 检查响应码
var respCode float64
var okCode bool
if code, ok := respJSON["code"].(float64); ok {
respCode, okCode = code, code == 0
} else if code, ok := respJSON["Code"].(float64); ok {
respCode, okCode = code, code == 0
}
if okCode {
// 转换响应格式:只修改 code 和 message,保留原始数据结构
respJSON["code"] = 200
respJSON["message"] = "SUCCESS"
// 处理output参数,替换音频URL
if outputStr != "url" {
// 获取当前使用的设备信息
currentDevice := GetCurrentDevice()
deviceID := ""
if currentDevice != nil {
deviceID = currentDevice.DeviceHeader
}
// 准备请求头
headers := map[string]string{
"User-Agent": "com.dragon.read",
}
// 处理音频URL,支持多种可能的结构
if dataArray, ok := respJSON["data"].([]interface{}); ok {
// 情况1:data是数组格式(实际返回的格式)
for _, item := range dataArray {
if audioItem, ok := item.(map[string]interface{}); ok {
// 处理main_url
if mainURL, ok := audioItem["main_url"].(string); ok && mainURL != "" {
processedURL := processMediaURL(mainURL, deviceID, headers, outputStr, "audio")
audioItem["main_url"] = processedURL
}
// 处理backup_url
if backupURL, ok := audioItem["backup_url"].(string); ok && backupURL != "" {
processedURL := processMediaURL(backupURL, deviceID, headers, outputStr, "audio")
audioItem["backup_url"] = processedURL
}
}
}
} else if data, ok := respJSON["data"].(map[string]interface{}); ok {
// 情况2:单个音频在audio_info下
if audioInfo, ok := data["audio_info"].(map[string]interface{}); ok {
if playURL, ok := audioInfo["play_url"].(string); ok && playURL != "" {
processedURL := processMediaURL(playURL, deviceID, headers, outputStr, "audio")
audioInfo["play_url"] = processedURL
}
}
// 情况3:音频列表在audio_list下
if audioList, ok := data["audio_list"].([]interface{}); ok {
for _, item := range audioList {
if audioItem, ok := item.(map[string]interface{}); ok {
if playURL, ok := audioItem["play_url"].(string); ok && playURL != "" {
processedURL := processMediaURL(playURL, deviceID, headers, outputStr, "audio")
audioItem["play_url"] = processedURL
}
}
}
}
}
}
resultBytes, _ := json.Marshal(respJSON)
return string(resultBytes), nil
}
// 返回错误信息
errMsg := "获取音频失败"
if msg, ok := respJSON["message"].(string); ok {
errMsg = msg
} else if msg, ok := respJSON["Message"].(string); ok {
errMsg = msg
}
audioLogger.Error(fmt.Sprintf("获取音频失败: code=%v, msg=%s", respCode, errMsg))
return BuildErrorResponse(errMsg), nil
}