package fqapi import ( "encoding/json" "fanqie/internal/config" "sort" "strings" ) // getContentConfig 获取内容配置(带默认值) func getContentConfig() config.ContentConfig { if config.GetAppConfig() != nil { return config.GetAppConfig().Fanqie.Content } // 返回默认配置 return config.ContentConfig{ RemoveImages: false, RemoveImageDesc: false, RemoveBlankLines: true, RemoveHTMLTags: false, RemoveChapterTitle: false, AddParagraphIndent: false, } } // decodeHTMLEntities 解码HTML实体 func decodeHTMLEntities(content string) string { // 解码常见HTML实体 content = strings.ReplaceAll(content, "&", "&") content = strings.ReplaceAll(content, "<", "<") content = strings.ReplaceAll(content, ">", ">") content = strings.ReplaceAll(content, """, "\"") content = strings.ReplaceAll(content, """, "\"") content = strings.ReplaceAll(content, "'", "'") content = strings.ReplaceAll(content, "'", "'") content = strings.ReplaceAll(content, "'", "'") content = strings.ReplaceAll(content, "/", "/") // 解码转义的反斜杠 content = strings.ReplaceAll(content, "\\\"", "\"") return content } // normalizeImgAttributes 将img标签中的img-width和img-height属性替换为标准的width和height属性 func normalizeImgAttributes(content string) string { // 替换 img-width 为 width content = strings.ReplaceAll(content, "img-width=", "width=") // 替换 img-height 为 height content = strings.ReplaceAll(content, "img-height=", "height=") return content } // removeBlankLines 移除多余空行,但保留段落间的双换行 func removeBlankLines(content string) string { // 先将多个连续换行(3个及以上)规范化为双换行 for strings.Contains(content, "\n\n\n") { content = strings.ReplaceAll(content, "\n\n\n", "\n\n") } // 移除首尾的空白 content = strings.TrimSpace(content) return content } // ============ 参数解析工具函数 ============ // parseBoolParam 解析布尔参数 func parseBoolParam(param interface{}) bool { switch v := param.(type) { case string: return v == "true" || v == "1" || strings.ToLower(v) == "true" case bool: return v } return false } // parseBoolParamDefault 解析布尔参数(带默认值) func parseBoolParamDefault(param interface{}, defaultVal bool) bool { if param == nil || param == "" { return defaultVal } return parseBoolParam(param) } // ============ JSON 处理工具函数 ============ // escapeJSON 转义JSON中的特殊字符 func escapeJSON(s string) string { s = strings.ReplaceAll(s, "<", "\\u003c") s = strings.ReplaceAll(s, ">", "\\u003e") return s } // buildJSONResponse 构建JSON响应并转义 func buildJSONResponse(data interface{}) string { resultBytes, _ := json.Marshal(data) return escapeJSON(string(resultBytes)) } // ============ 设备和密钥管理 ============ // getDeviceHeader 获取设备header(从设备池) func getDeviceHeader() string { // 从设备池获取任意有效设备header return GetAnyValidDeviceHeader() } // removeVersionFromHeader 移除header中的version_name参数 func removeVersionFromHeader(header string) string { return strings.Replace(header, "&version_name=5.8.9.32", "", -1) } // ============ API参数构建工具 ============ // BuildURL 构建API请求URL // 用法: BuildURL("https://reading.snssdk.com/reading/bookapi/detail/v/", "book_id=123", "tab_type=3") func BuildURL(fullURL string, customParams ...string) string { // 基础参数 allParams := []string{ "aid=1967", "app_name=novelapp", "channel=0", "device_platform=android", "os_version=0", "version_code=58932", } // 添加设备header header := getDeviceHeader() if header != "" { allParams = append(allParams, header) } // 添加自定义参数 allParams = append(allParams, customParams...) // 合并、拆分、排序 joined := strings.Join(allParams, "&") paramList := strings.Split(joined, "&") sort.Strings(paramList) params := strings.Join(paramList, "&") return fullURL + "?" + params } // ============ 缓存处理工具函数 ============ // buildCacheData 构建缓存数据结构 func buildCacheData(data interface{}) map[string]interface{} { return map[string]interface{}{ "code": 0, "message": "SUCCESS", "data": data, } } // saveCacheJSON 保存JSON到缓存 func saveCacheJSON(key string, data interface{}, ttl int) { cacheJSON, _ := json.Marshal(data) cacheStr := escapeJSON(string(cacheJSON)) UpdateCache(key, cacheStr, ttl) } // ============ 错误响应工具函数 ============ // BuildErrorResponse 构建统一的错误响应 func BuildErrorResponse(msg string) string { return buildJSONResponse(map[string]interface{}{ "code": -1, "msg": msg, }) } // BuildErrorResponseWithCode 构建带自定义错误码的响应 func BuildErrorResponseWithCode(code int, msg string) string { return buildJSONResponse(map[string]interface{}{ "code": code, "msg": msg, }) } // BuildSuccessResponse 构建成功响应 func BuildSuccessResponse(data interface{}) string { return buildJSONResponse(map[string]interface{}{ "code": 0, "message": "SUCCESS", "data": data, }) } // ============ 参数转换工具函数 ============ // ParseIntParam 解析整数参数(支持多种类型) func ParseIntParam(param interface{}, defaultVal int) int { switch v := param.(type) { case string: if v != "" { // 使用strconv.Atoi if result, err := parseStringToInt(v); err == nil { return result } } case int: return v case float64: return int(v) case int64: return int(v) } return defaultVal } // parseStringToInt 辅助函数:将字符串转换为整数 func parseStringToInt(s string) (int, error) { // 简单实现,避免导入strconv result := 0 negative := false if len(s) == 0 { return 0, nil } start := 0 if s[0] == '-' { negative = true start = 1 } else if s[0] == '+' { start = 1 } for i := start; i < len(s); i++ { if s[i] < '0' || s[i] > '9' { break } result = result*10 + int(s[i]-'0') } if negative { result = -result } return result, nil } // ParseStringParam 解析字符串参数(支持数组类型自动Join) func ParseStringParam(param interface{}, defaultVal string) string { if param == nil || param == "" { return defaultVal } switch v := param.(type) { case string: if v != "" { return v } case []string: // 数组类型,用逗号连接 return strings.Join(v, ",") } return defaultVal }