8277 lines
223 KiB
Go
8277 lines
223 KiB
Go
package service
|
||
|
||
import (
|
||
"context"
|
||
"encoding/json"
|
||
"fmt"
|
||
"net"
|
||
"net/http"
|
||
"regexp"
|
||
"strconv"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
tianxingjuhe "tyc-server/app/main/api/internal/service/tianxingjuhe_sdk"
|
||
"tyc-server/common/xerr"
|
||
"unicode"
|
||
|
||
"github.com/zeromicro/go-zero/core/logx"
|
||
)
|
||
|
||
// ============================================================================
|
||
// 工具箱服务 - 功能清单
|
||
// ============================================================================
|
||
//
|
||
// 【统计信息】
|
||
// 总工具数:146 个
|
||
// - 纯计算类工具(无外部依赖):10 个
|
||
// - 天行聚合 SDK 工具:136 个
|
||
//
|
||
// 【工具分类】
|
||
// 1️⃣ 实用查询类 (26个)
|
||
// ip-location, idcard-info, phone-location, beijing-time, bank-card,
|
||
// plate-parse, domain, domainparse, zone, areadata, addressparse,
|
||
// telecode, obdcode, charconvert, checkipv6, worldtime, timezone,
|
||
// shares, fxrate, oilprice, holiday, zone, scenic, lunar, aqi
|
||
//
|
||
// 2️⃣ 文字处理类 (20个)
|
||
// money-to-chinese, password-strength, days-between-dates, file-size-format,
|
||
// text-stats, pinyin, hanzipinyin, duoyinzi, chaizi, xhzd, jf-words,
|
||
// lexicon, enwords, ensentence, fanyi, dailytel, charconvert,
|
||
// slogan, zimi
|
||
//
|
||
// 3️⃣ 文化知识类 (35个)
|
||
// history-today, ten-why, duilian, gjdm, bcgm, idiom-quiz, poem-fill,
|
||
// fairytales, yuanqu, poetry, poetries, shijing, songci, verse,
|
||
// tianqishiju, chengyu, caichengyu, chengyujielong, pitlishi, riddle,
|
||
// cityriddle, caizimi, zimi, qingshi, flmj, xiehou, proverb, dictum,
|
||
// mingyan, sentence, mnpara, mgjuzi, duishici, msdl
|
||
//
|
||
// 4️⃣ 娱乐趣味类 (25个)
|
||
// jixiong, blood, zodiac, xingzuo, star, constellation, dob, saylove,
|
||
// caihongpi, dujitang, joke, naowan, wenda, decide, caipu, dream,
|
||
// rkl, godreply, tiangou, robotlog, dialogue, story, zmsc, targa,
|
||
// hsjz
|
||
//
|
||
// 5️⃣ 生活资讯类 (25个)
|
||
// everyday, woman, pyqwenan, healthskill, healthtip, nutrient,
|
||
// surname, jtwfcode, pet, bmi, zhongyao, yaopin, qiaomen,
|
||
// areanews, wxnew, wxhottopic, weibohot, nethot, hotword, hotreview,
|
||
// bulletin, douyinhot, zaowanwords, wananwords, caihongpi
|
||
//
|
||
// 6️⃣ 搜索查询类 (15个)
|
||
// one, proverb, slogan, chengyu, lexicon, cnmoney, lzmy, baiketiku,
|
||
// gjmj, shares, hotlajifenlei, garbage, lajifenlei, anslajifenlei,
|
||
// hotreview,
|
||
// ============================================================================
|
||
|
||
// ToolboxService 工具箱服务 —— 所有工具业务方法统一在此文件
|
||
type ToolboxService struct {
|
||
tianxingjuheClient *tianxingjuhe.Client
|
||
processors map[string]ToolProcessor
|
||
historyTodayCache sync.Map // key: MMDD -> value: historyTodayCacheItem
|
||
}
|
||
|
||
// historyTodayCacheItem 历史今天缓存条目
|
||
type historyTodayCacheItem struct {
|
||
Data map[string]interface{}
|
||
ExpiredAt time.Time
|
||
}
|
||
|
||
// ToolProcessor 工具处理函数签名
|
||
type ToolProcessor func(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error)
|
||
|
||
// NewToolboxService 创建工具箱服务实例
|
||
func NewToolboxService(tianxingjuheClient *tianxingjuhe.Client) *ToolboxService {
|
||
s := &ToolboxService{
|
||
tianxingjuheClient: tianxingjuheClient,
|
||
processors: make(map[string]ToolProcessor),
|
||
}
|
||
s.registerAllProcessors()
|
||
return s
|
||
}
|
||
|
||
// registerAllProcessors 注册所有工具处理器
|
||
func (s *ToolboxService) registerAllProcessors() {
|
||
// 纯计算类工具(无外部依赖)
|
||
s.processors["ip-location"] = processIPLocation
|
||
s.processors["idcard-info"] = processIDCardInfo
|
||
s.processors["beijing-time"] = processBeijingTime
|
||
s.processors["bank-card"] = processBankCard
|
||
s.processors["plate-parse"] = processPlateParse
|
||
s.processors["money-to-chinese"] = s.processMoneyToChinese
|
||
s.processors["password-strength"] = processPasswordStrength
|
||
s.processors["days-between-dates"] = processDaysBetweenDates
|
||
s.processors["file-size-format"] = processFileSizeFormat
|
||
s.processors["text-stats"] = processTextStats
|
||
// 天行聚合 SDK 工具
|
||
|
||
s.processors["phone-location"] = s.processPhoneLocation
|
||
s.processors["history-today"] = s.processHistoryToday
|
||
s.processors["ten-why"] = s.processTenWhy
|
||
s.processors["jf-words"] = s.processJFWords // 近义词反义词
|
||
s.processors["duilian"] = s.processDuilian // 经典对联
|
||
s.processors["gjdm"] = s.processGjDm // 古今地名
|
||
s.processors["bcgm"] = s.processBcgm // 本草纲目
|
||
s.processors["idiom-quiz"] = s.processIdiomQuiz // 成语填字
|
||
s.processors["poem-fill"] = s.processPoemFill // 诗词填空
|
||
s.processors["fairytales"] = s.processFairytales // 童话故事
|
||
s.processors["caihongpi"] = s.processCaiHongPi // 彩虹屁
|
||
s.processors["jixiong"] = s.processJixiong // 吉凶测试
|
||
s.processors["surname"] = s.processSurname // 姓氏起源
|
||
s.processors["jtwfcode"] = s.processJtwfcode // 违章代码
|
||
s.processors["healthskill"] = s.processHealthskill // 健康小妙招
|
||
s.processors["pyqwenan"] = s.processPyqwenan // 朋友圈文案
|
||
s.processors["woman"] = s.processWomanNews // 女性新闻
|
||
s.processors["decide"] = s.processDecide // 常识判断题
|
||
s.processors["everyday"] = s.processEveryday // 每日英语
|
||
s.processors["areanews"] = s.processAreaNews // 地区新闻
|
||
s.processors["yuanqu"] = s.processYuanqu // 元曲三百首
|
||
s.processors["bmi"] = s.processBMI // BMI标准体重
|
||
s.processors["zhongyao"] = s.processZhongyao // 中药大全
|
||
s.processors["yaopin"] = s.processYaopin // 药品说明书
|
||
s.processors["slogan"] = s.processSlogan // 猜广告语
|
||
s.processors["zimi"] = s.processZimi // 猜字谜
|
||
s.processors["dujitang"] = s.processDujitang // 毒鸡汤
|
||
s.processors["one"] = s.processOne // ONE一个
|
||
s.processors["proverb"] = s.processProverb // 文化谚语
|
||
s.processors["caichengyu"] = s.processCaichengyu // 猜成语
|
||
s.processors["qiaomen"] = s.processQiaomen // 生活小窍门
|
||
s.processors["riddle"] = s.processRiddle // 谜语大全
|
||
s.processors["healthtip"] = s.processHealthTip // 健康小贴士
|
||
s.processors["nutrient"] = s.processNutrient // 营养素查询
|
||
s.processors["fxrate"] = s.processFxRate // 汇率查询
|
||
s.processors["bulletin"] = s.processBulletin // 新闻简报
|
||
s.processors["caizimi"] = s.processCaizimi // 彩字谜
|
||
s.processors["hotlajifenlei"] = s.processHotLajifenlei // 热搜垃圾分类
|
||
s.processors["oilprice"] = s.processOilPrice // 实时油价
|
||
s.processors["chengyujielong"] = s.processChengyuJielong // 成语接龙
|
||
s.processors["weibohot"] = s.processWeiboHot // 微博热搜
|
||
s.processors["scenic"] = s.processScenic // 景点查询
|
||
s.processors["mingyan"] = s.processMingyan // 名言警句
|
||
s.processors["tianqishiju"] = s.processTianqiShiju // 天气诗句
|
||
s.processors["jieqi"] = s.processJieQi // 节气查询
|
||
s.processors["blood"] = s.processBloodPair // 血型配对
|
||
s.processors["zodiac"] = s.processZodiacPair // 生肖配对
|
||
s.processors["saylove"] = s.processSayLove // 情话大全
|
||
s.processors["star"] = s.processStar // 星座查询
|
||
s.processors["pinyin"] = s.processPinyin // 汉字转拼音
|
||
s.processors["nethot"] = s.processNetHot // 网络热搜
|
||
s.processors["ensentence"] = s.processEnSentence // 英文句子
|
||
s.processors["verse"] = s.processVerse // 诗词名句
|
||
s.processors["poetry"] = s.processPoetry // 古诗词
|
||
s.processors["poetries"] = s.processPoetries // 古诗词集
|
||
s.processors["pitlishi"] = s.processPiTongLiShi // 谐音历史
|
||
s.processors["mnpara"] = s.processMnPara // 美文段落
|
||
s.processors["skl"] = s.processSkl // 十苦乐
|
||
s.processors["sentence"] = s.processSentence // 唯美句子
|
||
s.processors["enwords"] = s.processEnWords // 英语单词
|
||
s.processors["lexicon"] = s.processLexicon // 词典查询
|
||
s.processors["lunar"] = s.processLunar // 农历查询
|
||
s.processors["xingzuo"] = s.processXingZuo // 星座配对
|
||
s.processors["godreply"] = s.processGodReply // 神回复
|
||
s.processors["xiehou"] = s.processXiehou // 歇后语
|
||
s.processors["rkl"] = s.processRKL // 绕口令
|
||
s.processors["cname"] = s.processCName // 起名大全
|
||
s.processors["shares"] = s.processShares // 股票查询
|
||
s.processors["hotword"] = s.processHotWord // 热词
|
||
s.processors["cityriddle"] = s.processCityRiddle // 城市谜语
|
||
s.processors["wenda"] = s.processWenDa // 问答
|
||
s.processors["chengyu"] = s.processChengYu // 成语词典
|
||
s.processors["naowan"] = s.processNaoWan // 脑筋急转弯
|
||
s.processors["dob"] = s.processDOB // 生日书
|
||
s.processors["dictum"] = s.processDictum // 格言
|
||
s.processors["joke"] = s.processJoke // 趣味笑话
|
||
s.processors["dream"] = s.processDream // 周公解梦
|
||
s.processors["caipu"] = s.processCaiPu // 菜谱大全
|
||
s.processors["wxnew"] = s.processWxNew // 微信新闻
|
||
// 新增工具(有天行SDK处理函数)
|
||
s.processors["constellation"] = s.processConstellation // 星座运势
|
||
s.processors["fanyi"] = s.processFanyi // 在线翻译
|
||
s.processors["holiday"] = s.processHoliday // 节假日查询
|
||
s.processors["garbage"] = s.processGarbage // 垃圾分类查询
|
||
s.processors["zone"] = s.processZone // 地区搜索查询
|
||
|
||
// ─── 第二批新增工具 ───
|
||
s.processors["timezone"] = s.processTimeZone
|
||
s.processors["domain"] = s.processDomainParse // 域名解析
|
||
s.processors["duoyinzi"] = s.processDuoYinZi //多音字
|
||
s.processors["dailytel"] = s.processDailyTel
|
||
s.processors["obdcode"] = s.processObdCode
|
||
s.processors["chaizi"] = s.processChaiZi //拆字
|
||
s.processors["huayu"] = s.processHuaYu
|
||
s.processors["moodpoetry"] = s.processMoodPoetry
|
||
s.processors["pcterm"] = s.processPcTerm
|
||
s.processors["targa"] = s.processTarga
|
||
s.processors["duishici"] = s.processDuiShiCi
|
||
s.processors["msdl"] = s.processMsdl
|
||
s.processors["shijing"] = s.processShiJing
|
||
s.processors["chepai"] = s.processChePai
|
||
s.processors["flmj"] = s.processFlmj
|
||
s.processors["xhzd"] = s.processXhZd
|
||
s.processors["telecode"] = s.processTeleCode
|
||
s.processors["charconvert"] = s.processCharConvert
|
||
s.processors["checkipv6"] = s.processCheckIPv6
|
||
s.processors["worldtime"] = s.processWorldTime
|
||
s.processors["wxhottopic"] = s.processWxHotTopic
|
||
s.processors["zmsc"] = s.processZmsc
|
||
s.processors["hsjz"] = s.processHsjz
|
||
s.processors["gjmj"] = s.processGjmj
|
||
s.processors["cnmoney"] = s.processCnMoney
|
||
s.processors["lzmy"] = s.processLzmy
|
||
s.processors["baiketiku"] = s.processBaiKeTiKu
|
||
s.processors["dialogue"] = s.processDialogue
|
||
s.processors["tiangou"] = s.processTianGou
|
||
s.processors["robotlog"] = s.processRobotLog
|
||
s.processors["aqi"] = s.processAqi
|
||
s.processors["addressparse"] = s.processAddressParse
|
||
s.processors["pet"] = s.processPet
|
||
s.processors["hotreview"] = s.processHotReview
|
||
s.processors["anslajifenlei"] = s.processAnsLaJiFenLei
|
||
s.processors["douyinhot"] = s.processDouYinHot
|
||
s.processors["zaowanwords"] = s.processZaoAnWords
|
||
s.processors["wananwords"] = s.processWanAnWords
|
||
s.processors["areadata"] = s.processAreaData // 全国五级行政区划
|
||
s.processors["mgjuzi"] = s.processMgJuZi
|
||
s.processors["songci"] = s.processSongCi
|
||
s.processors["story"] = s.processStory
|
||
s.processors["qingshi"] = s.processQingShi
|
||
s.processors["lajifenlei"] = s.processLaJiFenLei
|
||
s.processors["hanzipinyin"] = s.processHanZiPinYin
|
||
s.processors["shorthistory"] = s.processShortHistory
|
||
}
|
||
|
||
var (
|
||
ipv4Regex = regexp.MustCompile(`^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$`)
|
||
ipv6Regex = regexp.MustCompile(`^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$|^::1$|^::$|^([0-9a-fA-F]{1,4}:)*::([0-9a-fA-F]{1,4}:)*$`)
|
||
)
|
||
|
||
var httpClient = &http.Client{
|
||
Timeout: 3 * time.Second,
|
||
}
|
||
|
||
// Query 统一入口:根据 toolKey 分发到对应的处理函数
|
||
func (s *ToolboxService) Query(ctx context.Context, toolKey string, params map[string]interface{}) (map[string]interface{}, error) {
|
||
processor, ok := s.processors[toolKey]
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("不支持的工具类型: " + toolKey)
|
||
}
|
||
return processor(ctx, params)
|
||
}
|
||
|
||
// ==================== 具体工具方法 ====================
|
||
|
||
// processIPLocation IP属地查询
|
||
func processIPLocation(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
ip, _ := params["ip"].(string)
|
||
if ip == "" {
|
||
return nil, xerr.NewErrMsg("IP地址不能为空")
|
||
}
|
||
|
||
// 内网IP
|
||
if net.ParseIP(ip).IsPrivate() {
|
||
return map[string]interface{}{
|
||
"ip": ip,
|
||
"country": "内网",
|
||
"province": "内网",
|
||
"city": "内网",
|
||
"isp": "内网",
|
||
"latitude": 0,
|
||
"longitude": 0,
|
||
}, nil
|
||
}
|
||
|
||
// 格式校验
|
||
if !ipv4Regex.MatchString(ip) && !ipv6Regex.MatchString(ip) {
|
||
return nil, xerr.NewErrMsg("IP地址格式不正确")
|
||
}
|
||
|
||
logx.WithContext(ctx).Infof("IP属地查询: %s", ip)
|
||
|
||
// 默认空值
|
||
country, province, city, isp := "", "", "", ""
|
||
latitude, longitude := 0.0, 0.0
|
||
client := http.Client{Timeout: 3 * time.Second}
|
||
|
||
// ======================
|
||
// 1. 主接口:ip-api
|
||
// ======================
|
||
apiUrl := fmt.Sprintf("http://ip-api.com/json/%s?lang=zh-CN", ip)
|
||
resp, err := client.Get(apiUrl)
|
||
if err == nil && resp.StatusCode == 200 {
|
||
defer resp.Body.Close()
|
||
|
||
// 直接解析成 map,不定义结构体!
|
||
var res map[string]interface{}
|
||
if err := json.NewDecoder(resp.Body).Decode(&res); err == nil {
|
||
if res["status"] == "success" {
|
||
country, _ = res["country"].(string)
|
||
province, _ = res["regionName"].(string)
|
||
city, _ = res["city"].(string)
|
||
isp, _ = res["isp"].(string)
|
||
latitude, _ = res["lat"].(float64)
|
||
longitude, _ = res["lon"].(float64)
|
||
|
||
return map[string]interface{}{
|
||
"ip": ip,
|
||
"country": country,
|
||
"province": province,
|
||
"city": city,
|
||
"isp": isp,
|
||
"latitude": latitude,
|
||
"longitude": longitude,
|
||
}, nil
|
||
}
|
||
}
|
||
}
|
||
|
||
// ======================
|
||
// 2. 降级:淘宝IP
|
||
// ======================
|
||
logx.WithContext(ctx).Infof("ip-api 失败,降级淘宝IP: %s", ip)
|
||
taobaoUrl := fmt.Sprintf("https://ip.taobao.com/outGetIpInfo?ip=%s&accessKey=alibaba-inc", ip)
|
||
resp2, err2 := client.Get(taobaoUrl)
|
||
if err2 == nil && resp2.StatusCode == 200 {
|
||
defer resp2.Body.Close()
|
||
|
||
var res map[string]interface{}
|
||
if err := json.NewDecoder(resp2.Body).Decode(&res); err == nil {
|
||
data, ok := res["data"].(map[string]interface{})
|
||
if ok && res["code"].(float64) == 0 {
|
||
country, _ = data["country"].(string)
|
||
province, _ = data["region"].(string)
|
||
city, _ = data["city"].(string)
|
||
isp, _ = data["isp"].(string)
|
||
|
||
return map[string]interface{}{
|
||
"ip": ip,
|
||
"country": country,
|
||
"province": province,
|
||
"city": city,
|
||
"isp": isp,
|
||
"latitude": 0,
|
||
"longitude": 0,
|
||
}, nil
|
||
}
|
||
}
|
||
}
|
||
|
||
// 全部失败
|
||
return map[string]interface{}{
|
||
"ip": ip,
|
||
"country": "",
|
||
"province": "",
|
||
"city": "",
|
||
"isp": "",
|
||
"latitude": 0,
|
||
"longitude": 0,
|
||
}, nil
|
||
}
|
||
|
||
// processIDCardInfo 身份证归属地查询 + 真伪校验
|
||
func processIDCardInfo(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
idcard, _ := params["idcard"].(string)
|
||
if idcard == "" {
|
||
return nil, xerr.NewErrMsg("身份证号不能为空")
|
||
}
|
||
|
||
idcard = strings.ToUpper(idcard)
|
||
|
||
// 1. 长度校验
|
||
if len(idcard) != 18 {
|
||
return map[string]interface{}{
|
||
"idcard": idcard,
|
||
"valid": false,
|
||
"reason": "身份证号长度必须为18位",
|
||
}, nil
|
||
}
|
||
|
||
// 2. 格式校验
|
||
if matched, _ := regexp.MatchString(`^\d{17}[\dX]$`, idcard); !matched {
|
||
return map[string]interface{}{
|
||
"idcard": idcard,
|
||
"valid": false,
|
||
"reason": "身份证号格式不正确",
|
||
}, nil
|
||
}
|
||
|
||
// 3. 校验位验证
|
||
weights := []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
|
||
checksumMap := []byte{'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}
|
||
|
||
sum := 0
|
||
for i := 0; i < 17; i++ {
|
||
v, _ := strconv.Atoi(string(idcard[i]))
|
||
sum += v * weights[i]
|
||
}
|
||
|
||
if checksumMap[sum%11] != idcard[17] {
|
||
return map[string]interface{}{
|
||
"idcard": idcard,
|
||
"valid": false,
|
||
"reason": "身份证校验位错误",
|
||
}, nil
|
||
}
|
||
|
||
// 4. 出生日期
|
||
birthday := fmt.Sprintf("%s-%s-%s",
|
||
idcard[6:10],
|
||
idcard[10:12],
|
||
idcard[12:14],
|
||
)
|
||
|
||
// 5. 性别
|
||
gender := "男"
|
||
if (int(idcard[16])-'0')%2 == 0 {
|
||
gender = "女"
|
||
}
|
||
|
||
// 6. 年龄
|
||
age := 0
|
||
if t, err := time.Parse("2006-01-02", birthday); err == nil {
|
||
now := time.Now()
|
||
age = now.Year() - t.Year()
|
||
if now.YearDay() < t.YearDay() {
|
||
age--
|
||
}
|
||
}
|
||
|
||
// 7. 行政区划(内置常用省份,可按需扩展)
|
||
provinceMap := map[string]string{
|
||
"11": "北京市",
|
||
"12": "天津市",
|
||
"13": "河北省",
|
||
"14": "山西省",
|
||
"15": "内蒙古自治区",
|
||
"21": "辽宁省",
|
||
"22": "吉林省",
|
||
"23": "黑龙江省",
|
||
"31": "上海市",
|
||
"32": "江苏省",
|
||
"33": "浙江省",
|
||
"34": "安徽省",
|
||
"35": "福建省",
|
||
"36": "江西省",
|
||
"37": "山东省",
|
||
"41": "河南省",
|
||
"42": "湖北省",
|
||
"43": "湖南省",
|
||
"44": "广东省",
|
||
"45": "广西壮族自治区",
|
||
"46": "海南省",
|
||
"50": "重庆市",
|
||
"51": "四川省",
|
||
"52": "贵州省",
|
||
"53": "云南省",
|
||
"54": "西藏自治区",
|
||
"61": "陕西省",
|
||
"62": "甘肃省",
|
||
"63": "青海省",
|
||
"64": "宁夏回族自治区",
|
||
"65": "新疆维吾尔自治区",
|
||
}
|
||
|
||
province := provinceMap[idcard[0:2]]
|
||
city := ""
|
||
district := ""
|
||
|
||
logx.WithContext(ctx).Infof("身份证查询: %s", idcard)
|
||
|
||
return map[string]interface{}{
|
||
"idcard": idcard,
|
||
"valid": true,
|
||
"reason": "",
|
||
"province": province,
|
||
"city": city,
|
||
"district": district,
|
||
"birthday": birthday,
|
||
"gender": gender,
|
||
"age": age,
|
||
}, nil
|
||
}
|
||
|
||
// processPhoneLocation 手机号归属地查询
|
||
func (s *ToolboxService) processPhoneLocation(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填手机号
|
||
mobile, ok := params["mobile"].(string)
|
||
if !ok || mobile == "" {
|
||
return nil, xerr.NewErrMsg("mobile 手机号参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["phone"] = mobile
|
||
|
||
// 调用天行SDK 手机号归属地接口
|
||
resp, err := s.tianxingjuheClient.Get("mobilelocal/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据手机号归属地API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("手机号归属地接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析手机号归属地数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"id": mobile,
|
||
"mobile": mobile,
|
||
"areaid": resultMap["areaid"],
|
||
"areacode": resultMap["areacode"],
|
||
"postcode": resultMap["postcode"],
|
||
"proviceid": resultMap["proviceid"],
|
||
"mobilearea": resultMap["mobilearea"],
|
||
"mobiletype": resultMap["mobiletype"],
|
||
"mobileprovice": resultMap["mobileprovice"],
|
||
}, nil
|
||
}
|
||
|
||
// processBeijingTime 获取当前北京时间
|
||
func processBeijingTime(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
url := "http://124.222.204.22/api/time/getapi.php?id=88888888&key=88888888&type=20"
|
||
|
||
resp, err := httpClient.Get(url)
|
||
if err != nil {
|
||
logx.WithContext(ctx).Errorf("请求北京时间接口失败: %v", err)
|
||
return nil, xerr.NewErrMsg("获取北京时间失败")
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
var apiResult map[string]interface{}
|
||
if err := json.NewDecoder(resp.Body).Decode(&apiResult); err != nil {
|
||
return nil, xerr.NewErrMsg("解析北京时间响应失败")
|
||
}
|
||
|
||
// 接口级错误处理
|
||
if code, ok := apiResult["code"].(float64); ok && code != 200 {
|
||
return nil, xerr.NewErrMsg(" 系统繁忙!请一分钟后再试")
|
||
}
|
||
|
||
// 提取并转换数据
|
||
y, _ := apiResult["y"].(string)
|
||
m, _ := apiResult["m"].(string)
|
||
d, _ := apiResult["d"].(string)
|
||
h, _ := apiResult["h"].(string)
|
||
i, _ := apiResult["i"].(string)
|
||
s, _ := apiResult["s"].(string)
|
||
sjc, _ := apiResult["sjc"].(float64)
|
||
wecn, _ := apiResult["wecn"].(string)
|
||
|
||
// 构建北京时间字符串
|
||
dateStr := fmt.Sprintf("%s-%s-%s", y, m, d)
|
||
timeStr := fmt.Sprintf("%s:%s:%s", h, i, s)
|
||
datetimeStr := fmt.Sprintf("%s %s", dateStr, timeStr)
|
||
weekdayStr := fmt.Sprintf("星期%s", wecn)
|
||
|
||
// 转换返回格式为前端期望的格式
|
||
result := map[string]interface{}{
|
||
"datetime": datetimeStr,
|
||
"date": dateStr,
|
||
"time": timeStr,
|
||
"weekday": weekdayStr,
|
||
"timestamp": int64(sjc),
|
||
}
|
||
|
||
logx.WithContext(ctx).Infof("获取北京时间成功: %s", datetimeStr)
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// processBankCard 银行卡归属地查询
|
||
func processBankCard(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
cardNo, _ := params["card_no"].(string)
|
||
if cardNo == "" {
|
||
return nil, xerr.NewErrMsg("银行卡号不能为空")
|
||
}
|
||
|
||
cardNo = strings.ReplaceAll(cardNo, " ", "")
|
||
if matched, _ := regexp.MatchString(`^\d{16,19}$`, cardNo); !matched {
|
||
return nil, xerr.NewErrMsg("银行卡号格式不正确")
|
||
}
|
||
|
||
// Luhn 校验
|
||
sum, double := 0, false
|
||
for i := len(cardNo) - 1; i >= 0; i-- {
|
||
digit, _ := strconv.Atoi(string(cardNo[i]))
|
||
if double {
|
||
digit *= 2
|
||
if digit > 9 {
|
||
digit -= 9
|
||
}
|
||
}
|
||
sum += digit
|
||
double = !double
|
||
}
|
||
if sum%10 != 0 {
|
||
return map[string]interface{}{
|
||
"card_no": cardNo,
|
||
"valid": false,
|
||
"reason": "校验位错误",
|
||
}, nil
|
||
}
|
||
|
||
// 银行识别
|
||
bank, prefix := "未知银行", cardNo[:6]
|
||
switch {
|
||
case strings.HasPrefix(prefix, "622848"):
|
||
bank = "中国农业银行"
|
||
case strings.HasPrefix(prefix, "622260"):
|
||
bank = "交通银行"
|
||
case strings.HasPrefix(prefix, "436742"):
|
||
bank = "中国建设银行"
|
||
case strings.HasPrefix(prefix, "622202"):
|
||
bank = "中国工商银行"
|
||
}
|
||
|
||
// 卡种判断
|
||
cardType := "借记卡"
|
||
if len(cardNo) == 16 {
|
||
cardType = "信用卡"
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"card_no": cardNo,
|
||
"valid": true,
|
||
"bank": bank,
|
||
"card_type": cardType,
|
||
}, nil
|
||
}
|
||
|
||
// processPlateParse 车牌号解析
|
||
func processPlateParse(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
plate, _ := params["plate"].(string)
|
||
if plate == "" {
|
||
return nil, xerr.NewErrMsg("车牌号不能为空")
|
||
}
|
||
|
||
if matched, _ := regexp.MatchString(`^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤川青藏琼宁][A-Z][A-Z0-9]{4,5}[A-Z0-9挂学警港澳]$`, plate); !matched {
|
||
return nil, xerr.NewErrMsg("车牌号格式不正确")
|
||
}
|
||
|
||
provinceCode := string([]rune(plate)[0])
|
||
provinceMap := map[string]string{
|
||
"京": "北京", "津": "天津", "沪": "上海", "渝": "重庆",
|
||
"冀": "河北", "豫": "河南", "云": "云南", "辽": "辽宁",
|
||
"黑": "黑龙江", "湘": "湖南", "皖": "安徽", "鲁": "山东",
|
||
"新": "新疆", "苏": "江苏", "浙": "浙江", "赣": "江西",
|
||
"鄂": "湖北", "桂": "广西", "甘": "甘肃", "晋": "山西",
|
||
"蒙": "内蒙古", "陕": "陕西", "吉": "吉林", "闽": "福建",
|
||
"贵": "贵州", "粤": "广东", "川": "四川", "青": "青海",
|
||
"藏": "西藏", "琼": "海南", "宁": "宁夏",
|
||
}
|
||
|
||
province := provinceMap[provinceCode]
|
||
isNewEnergy := strings.ContainsAny(plate, "DF")
|
||
plateType := "普通小型车"
|
||
if isNewEnergy {
|
||
plateType = "新能源小型车"
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"plate": plate,
|
||
"plate_type": plateType,
|
||
"province": province,
|
||
"is_new_energy": isNewEnergy,
|
||
}, nil
|
||
}
|
||
|
||
// processMoneyToChinese 金额转换为中文
|
||
func (s *ToolboxService) processMoneyToChinese(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 金额(必填)
|
||
money, ok := params["money"].(string)
|
||
if !ok || money == "" {
|
||
return nil, xerr.NewErrMsg("金额不能为空")
|
||
}
|
||
reqParams["money"] = money
|
||
|
||
// 可选:单位类型,默认rmb(人民币元)
|
||
// type: usd美元单位元、usd_1美元单位分、rmb人民币单位元[默认]、rmb_1人民币单位分
|
||
if typ, ok := params["type"].(string); ok && typ != "" {
|
||
reqParams["type"] = typ
|
||
}
|
||
|
||
// 调用天行API
|
||
resp, err := s.tianxingjuheClient.Get("cnmoney/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求金额转大写接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("金额转大写接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析金额转大写数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"cnresult": result["cnresult"], // 中文大写金额
|
||
"enresult": result["enresult"], // 英语大写金额
|
||
"fnresult": result["fnresult"], // 西式三位分节法数字
|
||
}, nil
|
||
}
|
||
|
||
// processPasswordStrength 密码强度检测
|
||
func processPasswordStrength(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
pwd, _ := params["password"].(string)
|
||
if pwd == "" {
|
||
return nil, xerr.NewErrMsg("密码不能为空")
|
||
}
|
||
|
||
length := len(pwd)
|
||
hasUpper, hasLower, hasDigit, hasSpecial := false, false, false, false
|
||
|
||
for _, r := range pwd {
|
||
switch {
|
||
case unicode.IsUpper(r):
|
||
hasUpper = true
|
||
case unicode.IsLower(r):
|
||
hasLower = true
|
||
case unicode.IsDigit(r):
|
||
hasDigit = true
|
||
case unicode.IsPunct(r) || unicode.IsSymbol(r):
|
||
hasSpecial = true
|
||
}
|
||
}
|
||
|
||
score, tips := 0, []string{}
|
||
|
||
if length >= 8 {
|
||
score += 25
|
||
tips = append(tips, "长度足够")
|
||
} else {
|
||
tips = append(tips, "长度不足")
|
||
}
|
||
|
||
if hasUpper && hasLower {
|
||
score += 25
|
||
tips = append(tips, "包含大小写字母")
|
||
} else {
|
||
tips = append(tips, "建议包含大小写字母")
|
||
}
|
||
|
||
if hasDigit {
|
||
score += 25
|
||
tips = append(tips, "包含数字")
|
||
} else {
|
||
tips = append(tips, "建议包含数字")
|
||
}
|
||
|
||
if hasSpecial {
|
||
score += 25
|
||
tips = append(tips, "包含特殊字符")
|
||
} else {
|
||
tips = append(tips, "建议包含特殊字符")
|
||
}
|
||
|
||
level := "弱"
|
||
if score >= 75 {
|
||
level = "强"
|
||
} else if score >= 50 {
|
||
level = "中"
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"score": score,
|
||
"level": level,
|
||
"tips": tips,
|
||
}, nil
|
||
}
|
||
|
||
// processDaysBetweenDates 两个日期相差天数
|
||
func processDaysBetweenDates(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
startDate, _ := params["start_date"].(string)
|
||
endDate, _ := params["end_date"].(string)
|
||
|
||
if startDate == "" || endDate == "" {
|
||
return nil, xerr.NewErrMsg("起止日期不能为空")
|
||
}
|
||
|
||
layout := "2006-01-02"
|
||
start, err1 := time.Parse(layout, startDate)
|
||
end, err2 := time.Parse(layout, endDate)
|
||
|
||
if err1 != nil || err2 != nil {
|
||
return nil, xerr.NewErrMsg("日期格式不正确,应为 YYYY-MM-DD")
|
||
}
|
||
|
||
if start.After(end) {
|
||
start, end = end, start
|
||
}
|
||
|
||
days := int(end.Sub(start).Hours() / 24)
|
||
|
||
return map[string]interface{}{
|
||
"start_date": startDate,
|
||
"end_date": endDate,
|
||
"days": days,
|
||
}, nil
|
||
}
|
||
|
||
// 文件大小格式化 - 支持相互转换
|
||
func processFileSizeFormat(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
// 获取输入参数
|
||
sizeFloat, ok := params["size"].(float64)
|
||
if !ok || sizeFloat < 0 {
|
||
return nil, xerr.NewErrMsg("size 必须为非负数字")
|
||
}
|
||
|
||
inputUnit, _ := params["input_unit"].(string)
|
||
outputUnit, _ := params["output_unit"].(string)
|
||
|
||
// 如果没有指定输入单位,默认为字节
|
||
if inputUnit == "" {
|
||
inputUnit = "B"
|
||
}
|
||
|
||
// 如果没有指定输出单位,自动选择合适的单位
|
||
if outputUnit == "" {
|
||
outputUnit = "auto"
|
||
}
|
||
|
||
// 单位映射
|
||
unitMap := map[string]float64{
|
||
"B": 1,
|
||
"KB": 1024,
|
||
"MB": 1024 * 1024,
|
||
"GB": 1024 * 1024 * 1024,
|
||
"TB": 1024 * 1024 * 1024 * 1024,
|
||
}
|
||
|
||
// 转换为字节
|
||
bytes := sizeFloat * unitMap[inputUnit]
|
||
if bytes < 0 {
|
||
return nil, xerr.NewErrMsg("转换结果不能为负数")
|
||
}
|
||
|
||
result := map[string]interface{}{
|
||
"input_size": sizeFloat,
|
||
"input_unit": inputUnit,
|
||
"bytes": bytes,
|
||
}
|
||
|
||
// 如果输出单位是 "auto",自动选择合适的单位
|
||
if outputUnit == "auto" {
|
||
units := []string{"B", "KB", "MB", "GB", "TB"}
|
||
i := 0
|
||
value := bytes
|
||
|
||
for value >= 1024 && i < len(units)-1 {
|
||
value /= 1024
|
||
i++
|
||
}
|
||
|
||
result["output_size"] = value
|
||
result["output_unit"] = units[i]
|
||
result["human"] = fmt.Sprintf("%.2f %s", value, units[i])
|
||
} else {
|
||
// 指定单位转换
|
||
if _, exists := unitMap[outputUnit]; !exists {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("不支持的输出单位: %s", outputUnit))
|
||
}
|
||
|
||
outputSize := bytes / unitMap[outputUnit]
|
||
result["output_size"] = outputSize
|
||
result["output_unit"] = outputUnit
|
||
result["human"] = fmt.Sprintf("%.2f %s", outputSize, outputUnit)
|
||
}
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// processHistoryToday 历史今天查询
|
||
// processHistoryToday 历史今天查询(默认今天,3天缓存)
|
||
func (s *ToolboxService) processHistoryToday(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
dateStr, _ := params["date"].(string)
|
||
if dateStr == "" {
|
||
// 默认取今天的 MMDD
|
||
now := time.Now()
|
||
dateStr = fmt.Sprintf("%02d%02d", now.Month(), now.Day())
|
||
}
|
||
|
||
// 验证日期格式 (MMDD)
|
||
if len(dateStr) != 4 {
|
||
return nil, xerr.NewErrMsg("date 参数格式不正确,应为 MMDD 格式(如 0101)")
|
||
}
|
||
|
||
month := dateStr[:2]
|
||
day := dateStr[2:4]
|
||
|
||
monthInt, err := strconv.Atoi(month)
|
||
if err != nil || monthInt < 1 || monthInt > 12 {
|
||
return nil, xerr.NewErrMsg("月份参数不正确,应为 01-12")
|
||
}
|
||
|
||
dayInt, err := strconv.Atoi(day)
|
||
if err != nil || dayInt < 1 || dayInt > 31 {
|
||
return nil, xerr.NewErrMsg("日期参数不正确,应为 01-31")
|
||
}
|
||
|
||
// 查缓存
|
||
if cached, ok := s.historyTodayCache.Load(dateStr); ok {
|
||
item := cached.(historyTodayCacheItem)
|
||
if time.Now().Before(item.ExpiredAt) {
|
||
logx.WithContext(ctx).Infof("[历史今天] 缓存命中: date=%s, 过期时间=%s", dateStr, item.ExpiredAt.Format("2006-01-02 15:04:05"))
|
||
return item.Data, nil
|
||
}
|
||
// 缓存过期,删除
|
||
s.historyTodayCache.Delete(dateStr)
|
||
logx.WithContext(ctx).Infof("[历史今天] 缓存已过期,已删除: date=%s", dateStr)
|
||
}
|
||
|
||
// 调用天行聚合 SDK
|
||
resp, err := s.tianxingjuheClient.Get("lishi/index", map[string]interface{}{
|
||
"date": dateStr,
|
||
})
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析历史今天数据失败")
|
||
}
|
||
|
||
data := map[string]interface{}{
|
||
"list": resultMap["list"],
|
||
}
|
||
|
||
// 写入缓存,3天后过期
|
||
item := historyTodayCacheItem{
|
||
Data: data,
|
||
ExpiredAt: time.Now().Add(3 * 24 * time.Hour),
|
||
}
|
||
s.historyTodayCache.Store(dateStr, item)
|
||
|
||
logx.WithContext(ctx).Infof("[历史今天] API调用成功并写入缓存: date=%s, 过期时间=%s", dateStr, item.ExpiredAt.Format("2006-01-02 15:04:05"))
|
||
|
||
return data, nil
|
||
}
|
||
|
||
// processTenWhy 十万个为什么查询
|
||
func (s *ToolboxService) processTenWhy(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
// 构建请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
if num, ok := params["num"].(float64); ok {
|
||
numInt := int(num)
|
||
if numInt < 1 || numInt > 10 {
|
||
return nil, xerr.NewErrMsg("num 参数范围为 1-10")
|
||
}
|
||
reqParams["num"] = numInt
|
||
}
|
||
|
||
if page, ok := params["page"].(float64); ok {
|
||
pageInt := int(page)
|
||
if pageInt < 1 {
|
||
return nil, xerr.NewErrMsg("page 参数不能小于 1")
|
||
}
|
||
reqParams["page"] = pageInt
|
||
}
|
||
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
if typeid, ok := params["typeid"].(float64); ok {
|
||
typeidInt := int(typeid)
|
||
if typeidInt < 1 || typeidInt > 11 {
|
||
return nil, xerr.NewErrMsg("typeid 参数范围为 1-11")
|
||
}
|
||
reqParams["typeid"] = typeidInt
|
||
}
|
||
|
||
// 调用天行聚合 SDK
|
||
resp, err := s.tianxingjuheClient.Get("tenwhy/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据API失败: %v", err))
|
||
}
|
||
|
||
// 接口级错误处理
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 提取 result 数据
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析十万个为什么数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"list": resultMap["list"],
|
||
}, nil
|
||
}
|
||
|
||
// 文本字数统计
|
||
func processTextStats(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
text, _ := params["text"].(string)
|
||
if text == "" {
|
||
return map[string]interface{}{
|
||
"chars": 0,
|
||
"words": 0,
|
||
"lines": 0,
|
||
}, nil
|
||
}
|
||
|
||
chars := len([]rune(text))
|
||
|
||
words := 0
|
||
for _, w := range strings.Fields(text) {
|
||
if strings.TrimSpace(w) != "" {
|
||
words++
|
||
}
|
||
}
|
||
|
||
lines := 1
|
||
for _, r := range text {
|
||
if r == '\n' {
|
||
lines++
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"chars": chars,
|
||
"words": words,
|
||
"lines": lines,
|
||
}, nil
|
||
}
|
||
|
||
// processJFWords 近义词反义词查询(适合批量替换)
|
||
func (s *ToolboxService) processJFWords(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
// 构建请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验并获取必填参数 word(查询词)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("word 参数不能为空且必须为字符串类型")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 调用天行聚合 SDK(近义词反义词接口:jfwords/index)
|
||
resp, err := s.tianxingjuheClient.Get("jfwords/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据近义词反义词API失败: %v", err))
|
||
}
|
||
|
||
// 接口级错误处理
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 提取 result 数据
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析近义词反义词数据失败")
|
||
}
|
||
|
||
// 返回近义词、反义词、查询词(字段可能为空,调用方需做非空判断)
|
||
return map[string]interface{}{
|
||
"word": resultMap["word"], // 查询词
|
||
"jyc": resultMap["jyc"], // 近义词(可能为空)
|
||
"fyc": resultMap["fyc"], // 反义词(可能为空)
|
||
}, nil
|
||
}
|
||
|
||
// processDuilian 经典中华文化对联句子查询
|
||
func (s *ToolboxService) processDuilian(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
// 本接口无额外业务请求参数,只需SDK内部携带key
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行聚合 SDK 经典对联接口
|
||
resp, err := s.tianxingjuheClient.Get("duilian/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据对联API失败: %v", err))
|
||
}
|
||
|
||
// 接口级错误处理
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析result数据
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析经典对联数据失败")
|
||
}
|
||
|
||
// 返回对联内容,业务端自行做非空判断
|
||
return map[string]interface{}{
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processGjDm 古今地名查询
|
||
func (s *ToolboxService) processGjDm(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
// 构建请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填古地名 word
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("word 古地名参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 调用天行聚合 SDK 古今地名接口
|
||
resp, err := s.tianxingjuheClient.Get("gjdm/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据古今地名API失败: %v", err))
|
||
}
|
||
|
||
// 接口业务状态码校验
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("古今地名接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析result数据
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析古今地名数据失败")
|
||
}
|
||
|
||
// 返回古地名、沿革介绍,调用方自行做非空判断
|
||
return map[string]interface{}{
|
||
"area": resultMap["area"],
|
||
"introduce": resultMap["introduce"],
|
||
}, nil
|
||
}
|
||
|
||
// processBcgm 本草纲目药材查询
|
||
func (s *ToolboxService) processBcgm(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
// 构建请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 必传药材名称 name
|
||
name, ok := params["name"].(string)
|
||
if !ok || name == "" {
|
||
return nil, xerr.NewErrMsg("name 药材名称参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["name"] = name
|
||
|
||
// 可选 num 数量 1-10
|
||
if num, ok := params["num"].(float64); ok {
|
||
numInt := int(num)
|
||
if numInt < 1 || numInt > 10 {
|
||
return nil, xerr.NewErrMsg("num 参数范围为 1-10")
|
||
}
|
||
reqParams["num"] = numInt
|
||
}
|
||
|
||
// 可选 page 页码 最小1
|
||
if page, ok := params["page"].(float64); ok {
|
||
pageInt := int(page)
|
||
if pageInt < 1 {
|
||
return nil, xerr.NewErrMsg("page 参数不能小于 1")
|
||
}
|
||
reqParams["page"] = pageInt
|
||
}
|
||
|
||
// 调用天行SDK 本草纲目接口
|
||
resp, err := s.tianxingjuheClient.Get("bcgm/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据本草纲目API失败: %v", err))
|
||
}
|
||
|
||
// 接口状态码校验
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("本草纲目接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析result
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析本草纲目数据失败")
|
||
}
|
||
|
||
// 返回列表
|
||
return map[string]interface{}{
|
||
"list": resultMap["list"],
|
||
}, nil
|
||
}
|
||
|
||
// processIdiomQuiz 成语填字题目查询
|
||
func (s *ToolboxService) processIdiomQuiz(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
// 接口无额外自定义参数,仅内置key即可请求
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行聚合SDK 成语填字接口
|
||
resp, err := s.tianxingjuheClient.Get("idiomquiz/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据成语填字API失败: %v", err))
|
||
}
|
||
|
||
// 接口业务状态码校验
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("成语填字接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析result数据
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析成语填字数据失败")
|
||
}
|
||
|
||
// 返回所有题目、答案、选项、解释字段
|
||
return map[string]interface{}{
|
||
"diff": resultMap["diff"],
|
||
"full": resultMap["full"],
|
||
"explan": resultMap["explan"],
|
||
"correct": resultMap["correct"],
|
||
"wrong_a": resultMap["wrong_a"],
|
||
"wrong_b": resultMap["wrong_b"],
|
||
"wrong_c": resultMap["wrong_c"],
|
||
"question": resultMap["question"],
|
||
}, nil
|
||
}
|
||
|
||
// processPoemFill 诗词填空题目查询
|
||
func (s *ToolboxService) processPoemFill(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行聚合SDK 诗词填空接口
|
||
resp, err := s.tianxingjuheClient.Get("poemfill/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据诗词填空API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("诗词填空接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析诗词填空数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"diff": resultMap["diff"],
|
||
"full": resultMap["full"],
|
||
"note": resultMap["note"],
|
||
"title": resultMap["title"],
|
||
"author": resultMap["author"],
|
||
"correct": resultMap["correct"],
|
||
"dynasty": resultMap["dynasty"],
|
||
"wrong_a": resultMap["wrong_a"],
|
||
"wrong_b": resultMap["wrong_b"],
|
||
"wrong_c": resultMap["wrong_c"],
|
||
"category": resultMap["category"],
|
||
"question": resultMap["question"],
|
||
}, nil
|
||
}
|
||
|
||
// processFairytales 童话故事详情查询
|
||
func (s *ToolboxService) processFairytales(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填故事ID
|
||
id, ok := params["id"].(string)
|
||
if !ok || id == "" {
|
||
return nil, xerr.NewErrMsg("id 故事ID参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["id"] = id
|
||
|
||
// 调用天行SDK 童话故事接口
|
||
resp, err := s.tianxingjuheClient.Get("fairytales/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据童话故事API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("童话故事接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析童话故事数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"id": resultMap["id"],
|
||
"title": resultMap["title"],
|
||
"typeid": resultMap["typeid"],
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processCaiHongPi 随机彩虹屁语录
|
||
func (s *ToolboxService) processCaiHongPi(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行聚合SDK 彩虹屁接口
|
||
resp, err := s.tianxingjuheClient.Get("caihongpi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据彩虹屁API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("彩虹屁接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析彩虹屁数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processJixiong 吉凶测试查询
|
||
func (s *ToolboxService) processJixiong(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填数字号码
|
||
number, ok := params["number"].(string)
|
||
if !ok || number == "" {
|
||
return nil, xerr.NewErrMsg("number 数字号码参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["number"] = number
|
||
|
||
// 调用天行SDK 吉凶测试接口
|
||
resp, err := s.tianxingjuheClient.Get("jixiong/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据吉凶测试API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("吉凶测试接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析吉凶测试数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"number": number,
|
||
"score": resultMap["score"],
|
||
"shuli": resultMap["shuli"],
|
||
"gaishu": resultMap["gaishu"],
|
||
"result": resultMap["result"],
|
||
"conclusion": resultMap["conclusion"],
|
||
}, nil
|
||
}
|
||
|
||
// processSurname 姓氏起源查询
|
||
func (s *ToolboxService) processSurname(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填姓氏参数
|
||
xing, ok := params["xing"].(string)
|
||
if !ok || xing == "" {
|
||
return nil, xerr.NewErrMsg("xing 姓氏参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["xing"] = xing
|
||
|
||
// 调用天行SDK 姓氏起源接口
|
||
resp, err := s.tianxingjuheClient.Get("surname/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据姓氏起源API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("姓氏起源接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析姓氏起源数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"xing": resultMap["xing"],
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processJtwfcode 违章代码查询
|
||
func (s *ToolboxService) processJtwfcode(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填违章代码
|
||
code, ok := params["code"].(string)
|
||
if !ok || code == "" {
|
||
return nil, xerr.NewErrMsg("code 违章代码参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["code"] = code
|
||
|
||
// 调用天行SDK 违章代码查询接口
|
||
resp, err := s.tianxingjuheClient.Get("jtwfcode/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据违章代码API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("违章代码接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析违章代码数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"code": resultMap["code"],
|
||
"fine": resultMap["fine"],
|
||
"deduct": resultMap["deduct"],
|
||
"others": resultMap["others"],
|
||
"behavior": resultMap["behavior"],
|
||
}, nil
|
||
}
|
||
|
||
// processHealthskill 健康小妙招查询
|
||
func (s *ToolboxService) processHealthskill(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填关键词
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("word 关键词参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 调用天行SDK 健康小妙招接口
|
||
resp, err := s.tianxingjuheClient.Get("healthskill/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据健康小妙招API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("健康小妙招接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析健康小妙招数据失败")
|
||
}
|
||
|
||
list, ok := resultMap["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析健康小妙招列表失败")
|
||
}
|
||
|
||
var skills []map[string]interface{}
|
||
for _, item := range list {
|
||
if m, ok := item.(map[string]interface{}); ok {
|
||
skills = append(skills, map[string]interface{}{
|
||
"title": m["title"],
|
||
"content": m["content"],
|
||
})
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"list": skills,
|
||
}, nil
|
||
}
|
||
|
||
// processPyqwenan 朋友圈文案查询
|
||
func (s *ToolboxService) processPyqwenan(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 无额外业务参数,直接调用天行接口
|
||
resp, err := s.tianxingjuheClient.Get("pyqwenan/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据朋友圈文案API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("朋友圈文案接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析朋友圈文案数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"source": resultMap["source"],
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processWomanNews 女性新闻查询
|
||
func (s *ToolboxService) processWomanNews(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选参数:条数、页码、随机、关键词
|
||
if num, ok := params["num"].(string); ok && num != "" {
|
||
reqParams["num"] = num
|
||
}
|
||
if page, ok := params["page"].(string); ok && page != "" {
|
||
reqParams["page"] = page
|
||
}
|
||
if rand, ok := params["rand"].(string); ok && rand != "" {
|
||
reqParams["rand"] = rand
|
||
}
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
// 固定传form=1
|
||
reqParams["form"] = "1"
|
||
|
||
// 调用天行SDK 女性新闻接口
|
||
resp, err := s.tianxingjuheClient.Get("woman/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据女性新闻API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("女性新闻接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析女性新闻数据失败")
|
||
}
|
||
|
||
// 解析新闻列表
|
||
listArr, ok := resultMap["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析女性新闻列表失败")
|
||
}
|
||
|
||
var newsList []map[string]interface{}
|
||
for _, item := range listArr {
|
||
if m, ok := item.(map[string]interface{}); ok {
|
||
newsList = append(newsList, map[string]interface{}{
|
||
"id": m["id"],
|
||
"url": m["url"],
|
||
"ctime": m["ctime"],
|
||
"title": m["title"],
|
||
"picUrl": m["picUrl"],
|
||
"source": m["source"],
|
||
"description": m["description"],
|
||
})
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"list": newsList,
|
||
"allnum": resultMap["allnum"],
|
||
"curpage": resultMap["curpage"],
|
||
}, nil
|
||
}
|
||
|
||
// processDecide 常识判断题查询
|
||
func (s *ToolboxService) processDecide(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 无额外业务参数,直接调用接口
|
||
resp, err := s.tianxingjuheClient.Get("decide/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据判断题API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("判断题接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析判断题数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"title": resultMap["title"],
|
||
"answer": resultMap["answer"],
|
||
"analyse": resultMap["analyse"],
|
||
}, nil
|
||
}
|
||
|
||
// processEveryday 每日英语查询
|
||
func (s *ToolboxService) processEveryday(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 无业务自定义参数,直接调用天行接口
|
||
resp, err := s.tianxingjuheClient.Get("everyday/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据每日英语API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("每日英语接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析每日英语数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"id": resultMap["id"],
|
||
"date": resultMap["date"],
|
||
"note": resultMap["note"],
|
||
"source": resultMap["source"],
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processAreaNews 地区新闻查询
|
||
func (s *ToolboxService) processAreaNews(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填地区名称
|
||
areaname, ok := params["areaname"].(string)
|
||
if !ok || areaname == "" {
|
||
return nil, xerr.NewErrMsg("areaname 地区名称参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["areaname"] = areaname
|
||
|
||
// 可选参数:页码(默认1)
|
||
page := "1"
|
||
if pageStr, ok := params["page"].(string); ok && pageStr != "" {
|
||
page = pageStr
|
||
}
|
||
reqParams["page"] = page
|
||
|
||
// 可选参数:关键词
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
// 调用天行SDK 地区新闻接口
|
||
resp, err := s.tianxingjuheClient.Get("areanews/index", reqParams)
|
||
if err != nil {
|
||
logx.WithContext(ctx).Errorf("[地区新闻] 请求失败: %v", err)
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据地区新闻API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
logx.WithContext(ctx).Errorf("[地区新闻] API返回异常: code=%d, msg=%s", resp.Code, resp.Msg)
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("地区新闻接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
logx.WithContext(ctx).Infof("[地区新闻] API响应: %+v", resp.Result)
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
logx.WithContext(ctx).Errorf("[地区新闻] 解析result失败,类型: %T", resp.Result)
|
||
return nil, xerr.NewErrMsg("解析地区新闻数据失败")
|
||
}
|
||
|
||
// 解析新闻列表
|
||
listArr, ok := resultMap["list"].([]interface{})
|
||
if !ok {
|
||
logx.WithContext(ctx).Errorf("[地区新闻] 解析list失败,result结构: %+v", resultMap)
|
||
return nil, xerr.NewErrMsg("解析地区新闻列表失败")
|
||
}
|
||
|
||
logx.WithContext(ctx).Infof("[地区新闻] 列表长度: %d", len(listArr))
|
||
|
||
// 字段白名单
|
||
allowed := map[string]bool{
|
||
"id": true,
|
||
"url": true,
|
||
"ctime": true,
|
||
"title": true,
|
||
"picUrl": true,
|
||
"source": true,
|
||
"description": true,
|
||
}
|
||
|
||
var newsList []map[string]interface{}
|
||
for _, item := range listArr {
|
||
if m, ok := item.(map[string]interface{}); ok {
|
||
clean := map[string]interface{}{}
|
||
for k, v := range m {
|
||
if allowed[k] {
|
||
// 清理HTML标签(title和description)
|
||
if k == "title" || k == "description" {
|
||
if str, ok := v.(string); ok {
|
||
clean[k] = cleanHTMLContent(str)
|
||
}
|
||
} else {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
}
|
||
// 至少要有标题(允许清理后为空,但原始必须有值)
|
||
if m["title"] != nil {
|
||
newsList = append(newsList, clean)
|
||
}
|
||
}
|
||
}
|
||
|
||
logx.WithContext(ctx).Infof("[地区新闻] 清理后列表长度: %d", len(newsList))
|
||
|
||
// 如果清理后列表为空,但原始有数据,可能是HTML清理导致的问题
|
||
if len(newsList) == 0 && len(listArr) > 0 {
|
||
// logx.WithContext(ctx).Warnf("[地区新闻] 清理后列表为空,原始有%d条数据", len(listArr))
|
||
// 返回部分数据,不清理HTML
|
||
for _, item := range listArr {
|
||
if m, ok := item.(map[string]interface{}); ok {
|
||
clean := map[string]interface{}{}
|
||
for k, v := range m {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
if m["title"] != nil {
|
||
newsList = append(newsList, clean)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if len(newsList) == 0 {
|
||
return nil, xerr.NewErrMsg("未查询到该地区新闻")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(newsList),
|
||
"list": newsList,
|
||
}, nil
|
||
}
|
||
|
||
// processYuanqu 元曲三百首查询
|
||
func (s *ToolboxService) processYuanqu(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 必填参数 数量、页码
|
||
num, ok := params["num"].(string)
|
||
if !ok || num == "" {
|
||
return nil, xerr.NewErrMsg("num 返回数量参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["num"] = num
|
||
|
||
page, ok := params["page"].(string)
|
||
if !ok || page == "" {
|
||
return nil, xerr.NewErrMsg("page 页码参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["page"] = page
|
||
|
||
// 可选 关键词搜索
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
// 调用天行SDK 元曲三百首接口
|
||
resp, err := s.tianxingjuheClient.Get("yuanqu/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据元曲三百首API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("元曲三百首接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析元曲三百首数据失败")
|
||
}
|
||
|
||
listArr, ok := resultMap["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析元曲三百首列表失败")
|
||
}
|
||
|
||
var yuanquList []map[string]interface{}
|
||
for _, item := range listArr {
|
||
if m, ok := item.(map[string]interface{}); ok {
|
||
yuanquList = append(yuanquList, map[string]interface{}{
|
||
"note": m["note"],
|
||
"title": m["title"],
|
||
"author": m["author"],
|
||
"chapter": m["chapter"],
|
||
"content": m["content"],
|
||
"translation": m["translation"],
|
||
})
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"list": yuanquList,
|
||
}, nil
|
||
}
|
||
|
||
// processBMI BMI标准体重计算
|
||
func (s *ToolboxService) processBMI(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填身高
|
||
height, ok := params["height"].(string)
|
||
if !ok || height == "" {
|
||
return nil, xerr.NewErrMsg("height 身高参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["height"] = height
|
||
|
||
// 校验必填体重
|
||
weight, ok := params["weight"].(string)
|
||
if !ok || weight == "" {
|
||
return nil, xerr.NewErrMsg("weight 体重参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["weight"] = weight
|
||
|
||
// 可选性别
|
||
if sex, ok := params["sex"].(string); ok && sex != "" {
|
||
reqParams["sex"] = sex
|
||
}
|
||
|
||
// 调用天行SDK BMI接口
|
||
resp, err := s.tianxingjuheClient.Get("bmi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据BMI标准体重API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("BMI标准体重接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析BMI标准体重数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"bmi": resultMap["bmi"],
|
||
"tip": resultMap["tip"],
|
||
"healthy": resultMap["healthy"],
|
||
"normbmi": resultMap["normbmi"],
|
||
"normweight": resultMap["normweight"],
|
||
"idealweight": resultMap["idealweight"],
|
||
}, nil
|
||
}
|
||
|
||
// processZhongyao 中药大全查询
|
||
func (s *ToolboxService) processZhongyao(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填中药名称
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("word 中草药名称参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 可选返回数量(默认1)
|
||
num := 1
|
||
if numStr, ok := params["num"].(string); ok && numStr != "" {
|
||
if n, err := strconv.Atoi(numStr); err == nil && n > 0 {
|
||
num = n
|
||
}
|
||
}
|
||
reqParams["num"] = num
|
||
|
||
// 可选页码(默认1)
|
||
page := 1
|
||
if pageStr, ok := params["page"].(string); ok && pageStr != "" {
|
||
if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
|
||
page = p
|
||
}
|
||
}
|
||
reqParams["page"] = page
|
||
|
||
// 调用天行SDK 中药大全接口
|
||
resp, err := s.tianxingjuheClient.Get("zhongyao/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据中药大全API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("中药大全接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
logx.WithContext(ctx).Infof("[中药大全] API响应: %+v", resp.Result)
|
||
|
||
// 解析 result - 支持多种格式
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析中药大全数据失败:返回格式不是对象")
|
||
}
|
||
|
||
// 检查是否是列表格式(有些天行API返回 { list: [...] })
|
||
if listData, hasList := resultMap["list"].([]interface{}); hasList && len(listData) > 0 {
|
||
// 取第一条记录
|
||
if firstItem, ok := listData[0].(map[string]interface{}); ok {
|
||
resultMap = firstItem
|
||
}
|
||
}
|
||
|
||
// 检查是否有数据
|
||
if resultMap["title"] == nil && resultMap["content"] == nil {
|
||
return nil, xerr.NewErrMsg("未查询到该中药信息")
|
||
}
|
||
|
||
// 清理HTML标签
|
||
title, _ := resultMap["title"].(string)
|
||
content, _ := resultMap["content"].(string)
|
||
|
||
// 如果是字符串类型,清理HTML标签
|
||
if title != "" {
|
||
title = cleanHTMLContent(title)
|
||
}
|
||
if content != "" {
|
||
content = cleanHTMLContent(content)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"title": title,
|
||
"content": content,
|
||
}, nil
|
||
}
|
||
|
||
// processYaopin 药品说明书查询
|
||
func (s *ToolboxService) processYaopin(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 校验必填药品名称
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("word 药品名称参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 可选参数:数量(默认10)
|
||
num := 10
|
||
if numStr, ok := params["num"].(string); ok && numStr != "" {
|
||
if n, err := strconv.Atoi(numStr); err == nil && n > 0 {
|
||
num = n
|
||
}
|
||
}
|
||
reqParams["num"] = num
|
||
|
||
// 可选参数:页码(默认1)
|
||
page := 1
|
||
if pageStr, ok := params["page"].(string); ok && pageStr != "" {
|
||
if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
|
||
page = p
|
||
}
|
||
}
|
||
reqParams["page"] = page
|
||
|
||
// 调用天行SDK 药品说明书接口
|
||
resp, err := s.tianxingjuheClient.Get("yaopin/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据药品说明书API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("药品说明书接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
logx.WithContext(ctx).Infof("[药品说明书] API响应: %+v", resp.Result)
|
||
|
||
// 解析 result - 支持多种格式
|
||
var list []map[string]interface{}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析药品说明书数据失败:返回格式不是对象")
|
||
}
|
||
|
||
// 情况1:返回格式为 { list: [...] }
|
||
if listData, hasList := resultMap["list"].([]interface{}); hasList {
|
||
for _, item := range listData {
|
||
if m, ok := item.(map[string]interface{}); ok {
|
||
// 字段白名单 + 清理HTML标签
|
||
clean := map[string]interface{}{}
|
||
if v, ok := m["title"].(string); ok {
|
||
clean["title"] = cleanHTMLContent(v)
|
||
}
|
||
if v, ok := m["content"].(string); ok {
|
||
clean["content"] = cleanHTMLContent(v)
|
||
}
|
||
if clean["title"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
}
|
||
} else if resultMap["title"] != nil {
|
||
// 情况2:返回格式为 { title: "...", content: "..." }(单条记录)
|
||
title, _ := resultMap["title"].(string)
|
||
content, _ := resultMap["content"].(string)
|
||
|
||
clean := map[string]interface{}{
|
||
"title": cleanHTMLContent(title),
|
||
"content": cleanHTMLContent(content),
|
||
}
|
||
list = append(list, clean)
|
||
}
|
||
|
||
if len(list) == 0 {
|
||
return nil, xerr.NewErrMsg("未查询到该药品说明书")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processSlogan 猜广告语查询
|
||
func (s *ToolboxService) processSlogan(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行SDK 猜广告语接口
|
||
resp, err := s.tianxingjuheClient.Get("slogan/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据猜广告语API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("猜广告语接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析猜广告语数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"answer": resultMap["answer"],
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processZimi 猜字谜查询
|
||
func (s *ToolboxService) processZimi(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行SDK 猜字谜接口
|
||
resp, err := s.tianxingjuheClient.Get("zimi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据猜字谜API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("猜字谜接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析猜字谜数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"answer": resultMap["answer"],
|
||
"reason": resultMap["reason"],
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processDujitang 毒鸡汤语录查询
|
||
func (s *ToolboxService) processDujitang(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行SDK 毒鸡汤接口
|
||
resp, err := s.tianxingjuheClient.Get("dujitang/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据毒鸡汤API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("毒鸡汤接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析毒鸡汤数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processOne ONE一个每日句子
|
||
func (s *ToolboxService) processOne(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选指定日期
|
||
if date, ok := params["date"].(string); ok && date != "" {
|
||
reqParams["date"] = date
|
||
}
|
||
// 可选是否随机
|
||
if rand, ok := params["rand"].(string); ok && rand != "" {
|
||
reqParams["rand"] = rand
|
||
}
|
||
|
||
// 调用天行SDK ONE一个接口
|
||
resp, err := s.tianxingjuheClient.Get("one/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据ONE一个API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("ONE一个接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析ONE一个数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"date": resultMap["date"],
|
||
"word": resultMap["word"],
|
||
"oneid": resultMap["oneid"],
|
||
"imgurl": resultMap["imgurl"],
|
||
"wordfrom": resultMap["wordfrom"],
|
||
"imgauthor": resultMap["imgauthor"],
|
||
}, nil
|
||
}
|
||
|
||
// processProverb 文化谚语查询
|
||
func (s *ToolboxService) processProverb(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行SDK 文化谚语接口
|
||
resp, err := s.tianxingjuheClient.Get("proverb/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据文化谚语API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("文化谚语接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析文化谚语数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"front": resultMap["front"],
|
||
"behind": resultMap["behind"],
|
||
}, nil
|
||
}
|
||
|
||
// processCaichengyu 猜成语查询
|
||
func (s *ToolboxService) processCaichengyu(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行SDK 猜成语接口
|
||
resp, err := s.tianxingjuheClient.Get("caichengyu/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据猜成语API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("猜成语接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析猜成语数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"abbr": resultMap["abbr"],
|
||
"study": resultMap["study"],
|
||
"answer": resultMap["answer"],
|
||
"pinyin": resultMap["pinyin"],
|
||
"source": resultMap["source"],
|
||
"question": resultMap["question"],
|
||
}, nil
|
||
}
|
||
|
||
// processQiaomen 生活小窍门查询
|
||
func (s *ToolboxService) processQiaomen(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行SDK 生活小窍门接口
|
||
resp, err := s.tianxingjuheClient.Get("qiaomen/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据生活小窍门API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("生活小窍门接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析生活小窍门数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processRiddle 谜语大全查询
|
||
func (s *ToolboxService) processRiddle(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行SDK 谜语大全接口
|
||
resp, err := s.tianxingjuheClient.Get("riddle/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据谜语大全API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("谜语大全接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析谜语大全数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"quest": resultMap["quest"],
|
||
"result": resultMap["answer"],
|
||
}, nil
|
||
}
|
||
|
||
// processHealthTip 健康小提示
|
||
func (s *ToolboxService) processHealthTip(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
// 1. 请求参数(该接口无需额外参数)
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("healthtip/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天行数据健康小提示API失败: %v", err))
|
||
}
|
||
|
||
// 3. 校验返回状态
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("健康小提示接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析健康小提示数据失败")
|
||
}
|
||
|
||
// 5. 返回给上层
|
||
return map[string]interface{}{
|
||
"content": resultMap["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processNutrient 查询食物营养成分
|
||
func (s *ToolboxService) processNutrient(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数提取(必填)
|
||
var mode float64
|
||
switch v := params["mode"].(type) {
|
||
case float64:
|
||
mode = v
|
||
case string:
|
||
if v == "" {
|
||
return nil, xerr.NewErrMsg("缺少必填参数 mode")
|
||
}
|
||
modeInt, err := strconv.Atoi(v)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg("mode 参数必须是数字 0/1/2")
|
||
}
|
||
mode = float64(modeInt)
|
||
default:
|
||
return nil, xerr.NewErrMsg("缺少必填参数 mode")
|
||
}
|
||
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("缺少必填参数 word")
|
||
}
|
||
|
||
// 2. 可选参数
|
||
num := 10
|
||
if v, ok := params["num"].(float64); ok && v > 0 {
|
||
num = int(v)
|
||
}
|
||
|
||
page := 1
|
||
if v, ok := params["page"].(float64); ok && v > 0 {
|
||
page = int(v)
|
||
}
|
||
|
||
// 3. 组装请求参数
|
||
reqParams := map[string]interface{}{
|
||
"mode": mode,
|
||
"word": word,
|
||
"num": num,
|
||
"page": page,
|
||
}
|
||
|
||
// 4. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("nutrient/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求营养成分接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("营养成分接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 5. 解析 result(天行 API 返回格式为 { list: [...] })
|
||
var list []map[string]interface{}
|
||
|
||
// 尝试从 result 中提取 list 字段
|
||
switch v := resp.Result.(type) {
|
||
case map[string]interface{}:
|
||
// 天行 API 的标准格式:result.list 是数组
|
||
if dataList, ok := v["list"].([]interface{}); ok {
|
||
for _, item := range dataList {
|
||
if m, ok := item.(map[string]interface{}); ok {
|
||
list = append(list, m)
|
||
}
|
||
}
|
||
} else {
|
||
// 兼容单个对象的情况
|
||
list = append(list, v)
|
||
}
|
||
case []interface{}:
|
||
// 兼容直接返回数组的情况
|
||
for _, item := range v {
|
||
if m, ok := item.(map[string]interface{}); ok {
|
||
list = append(list, m)
|
||
}
|
||
}
|
||
default:
|
||
return nil, xerr.NewErrMsg("解析营养成分数据失败")
|
||
}
|
||
|
||
if len(list) == 0 {
|
||
return nil, xerr.NewErrMsg("未查询到相关数据")
|
||
}
|
||
|
||
// 6. 返回标准化结果
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processFxRate 汇率查询
|
||
func (s *ToolboxService) processFxRate(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
var money float64
|
||
switch v := params["money"].(type) {
|
||
case float64:
|
||
money = v
|
||
case string:
|
||
money, _ = strconv.ParseFloat(v, 64)
|
||
default:
|
||
return nil, xerr.NewErrMsg("参数 money 必须为大于 0 的数字")
|
||
}
|
||
if money <= 0 {
|
||
return nil, xerr.NewErrMsg("参数 money 必须为大于 0 的数字")
|
||
}
|
||
|
||
fromCoin, ok := params["fromcoin"].(string)
|
||
if !ok || fromCoin == "" {
|
||
return nil, xerr.NewErrMsg("参数 fromcoin 不能为空")
|
||
}
|
||
|
||
toCoin, ok := params["tocoin"].(string)
|
||
if !ok || toCoin == "" {
|
||
return nil, xerr.NewErrMsg("参数 tocoin 不能为空")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"money": int(money),
|
||
"fromcoin": fromCoin,
|
||
"tocoin": toCoin,
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("fxrate/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求汇率接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("汇率接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析结果
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析汇率数据失败")
|
||
}
|
||
|
||
amount, ok := result["money"].(string)
|
||
if !ok || amount == "" {
|
||
return nil, xerr.NewErrMsg("汇率金额异常")
|
||
}
|
||
|
||
// 5. 返回标准化结果
|
||
return map[string]interface{}{
|
||
"from": fromCoin,
|
||
"to": toCoin,
|
||
"amount": money,
|
||
"result": amount,
|
||
}, nil
|
||
}
|
||
|
||
// processBulletin 每日简报
|
||
func (s *ToolboxService) processBulletin(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数(该接口无需业务参数)
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("bulletin/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求每日简报接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("每日简报接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析每日简报数据失败")
|
||
}
|
||
|
||
// 4. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("简报列表数据异常")
|
||
}
|
||
|
||
// 5. 字段白名单过滤
|
||
allowed := map[string]bool{
|
||
"title": true,
|
||
"digest": true,
|
||
"mtime": true,
|
||
}
|
||
|
||
news := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 最少保证有标题
|
||
if clean["title"] != nil {
|
||
news = append(news, clean)
|
||
}
|
||
}
|
||
|
||
// 6. 返回标准化结果
|
||
return map[string]interface{}{
|
||
"count": len(news),
|
||
"list": news,
|
||
}, nil
|
||
}
|
||
|
||
// processCaizimi 猜灯谜
|
||
func (s *ToolboxService) processCaizimi(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数(无需业务参数)
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("caizimi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求猜灯谜接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("猜灯谜接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析猜灯谜数据失败")
|
||
}
|
||
|
||
// 4. 字段白名单(非常重要)
|
||
allowed := map[string]bool{
|
||
"type": true,
|
||
"answer": true,
|
||
"riddle": true,
|
||
"disturb": true,
|
||
"description": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 5. 基础校验
|
||
if clean["riddle"] == nil || clean["answer"] == nil {
|
||
return nil, xerr.NewErrMsg("灯谜数据不完整")
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processHotLajifenlei 热搜垃圾分类
|
||
func (s *ToolboxService) processHotLajifenlei(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选:日期
|
||
if date, ok := params["date"].(string); ok && date != "" {
|
||
reqParams["date"] = date
|
||
}
|
||
|
||
// 可选:垃圾类型
|
||
if typ, ok := params["type"].(float64); ok {
|
||
reqParams["type"] = int(typ)
|
||
}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("hotlajifenlei/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求热搜垃圾分类接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("热搜垃圾分类接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析热搜垃圾分类数据失败")
|
||
}
|
||
|
||
// 4. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("热搜列表数据异常")
|
||
}
|
||
|
||
// 5. 字段白名单 + 枚举映射
|
||
allowed := map[string]bool{
|
||
"name": true,
|
||
"type": true,
|
||
"index": true,
|
||
}
|
||
|
||
typeMap := map[int]string{
|
||
0: "可回收物",
|
||
1: "有害垃圾",
|
||
2: "厨余垃圾(湿)",
|
||
3: "其他垃圾(干)",
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 垃圾类型可读化
|
||
if t, ok := clean["type"].(float64); ok {
|
||
if name, exists := typeMap[int(t)]; exists {
|
||
clean["type_name"] = name
|
||
}
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
// 6. 返回标准化结果
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processOilPrice 实时油价查询
|
||
func (s *ToolboxService) processOilPrice(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
prov, ok := params["prov"].(string)
|
||
if !ok || prov == "" {
|
||
return nil, xerr.NewErrMsg("参数 prov 不能为空,例如:湖北、上海")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"prov": prov,
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("oilprice/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求实时油价接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("实时油价接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析油价数据失败")
|
||
}
|
||
|
||
// 5. 字段白名单 + 可读性增强
|
||
allowed := map[string]bool{
|
||
"p0": true,
|
||
"p89": true,
|
||
"p92": true,
|
||
"p95": true,
|
||
"p98": true,
|
||
"prov": true,
|
||
"time": true,
|
||
}
|
||
|
||
labelMap := map[string]string{
|
||
"p0": "0号柴油",
|
||
"p89": "89号汽油",
|
||
"p92": "92号汽油",
|
||
"p95": "95号汽油",
|
||
"p98": "98号汽油",
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 6. 生成前端友好的油价列表
|
||
prices := make([]map[string]interface{}, 0)
|
||
for k, label := range labelMap {
|
||
if v, ok := clean[k].(string); ok && v != "" {
|
||
prices = append(prices, map[string]interface{}{
|
||
"type": k,
|
||
"label": label,
|
||
"price": v,
|
||
})
|
||
}
|
||
}
|
||
|
||
// 7. 返回标准化结果
|
||
return map[string]interface{}{
|
||
"prov": clean["prov"],
|
||
"update": clean["time"],
|
||
"prices": prices,
|
||
}, nil
|
||
}
|
||
|
||
// processChengyuJielong 成语接龙
|
||
func (s *ToolboxService) processChengyuJielong(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("参数 word 不能为空,例如:一马当先")
|
||
}
|
||
|
||
// 用户ID:如果没有提供,使用默认值(方便单人游戏)
|
||
userID, ok := params["userid"].(string)
|
||
if !ok || userID == "" {
|
||
userID = "1212" // 默认用户标识,单人游戏模式
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"word": word,
|
||
"userid": userID,
|
||
}
|
||
|
||
// 可选:状态维持时间
|
||
if t, ok := params["statetime"].(float64); ok && t > 0 {
|
||
reqParams["statetime"] = int(t)
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("chengyujielong/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求成语接龙接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("成语接龙接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析成语接龙数据失败")
|
||
}
|
||
|
||
// 5. 字段白名单(非常重要)
|
||
allowed := map[string]bool{
|
||
"chengyu": true,
|
||
"pinyin": true,
|
||
"jieshi": true,
|
||
"chuchu": true,
|
||
"startstr": true,
|
||
"endstr": true,
|
||
"tip": true,
|
||
"grade": true,
|
||
"result": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 6. 游戏状态说明(给前端/AI用)
|
||
stateMap := map[int]string{
|
||
0: "开局",
|
||
1: "答对",
|
||
2: "开局失败",
|
||
3: "接错成语",
|
||
4: "不是成语",
|
||
5: "胜利结束",
|
||
}
|
||
|
||
if r, ok := clean["result"].(float64); ok {
|
||
clean["state"] = stateMap[int(r)]
|
||
clean["game_over"] = r >= 2
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processWeiboHot 微博热搜榜
|
||
func (s *ToolboxService) processWeiboHot(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
resp, err := s.tianxingjuheClient.Get("weibohot/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求微博热搜接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("微博热搜接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析微博热搜数据失败")
|
||
}
|
||
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("热搜列表数据异常")
|
||
}
|
||
|
||
var hotList []map[string]interface{}
|
||
for _, item := range rawList {
|
||
info, _ := item.(map[string]interface{})
|
||
hotList = append(hotList, map[string]interface{}{
|
||
"keyword": info["hotword"], // 搜索词
|
||
"brief": info["hottag"], // 简介
|
||
"index": info["hotwordnum"], // 热度
|
||
})
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(hotList),
|
||
"list": hotList,
|
||
}, nil
|
||
}
|
||
|
||
// processDomainParse 域名DNS解析查询
|
||
func (s *ToolboxService) processDomainParse(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
domain, ok := params["domain"].(string)
|
||
if !ok || domain == "" {
|
||
return nil, xerr.NewErrMsg("参数 domain 不能为空,例如:tianyuanapi.com")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"domain": domain,
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("domain/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求域名解析接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("域名解析接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析域名解析数据失败")
|
||
}
|
||
|
||
// 5. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析解析记录列表失败")
|
||
}
|
||
|
||
// 6. 不做字段白名单(DNS 字段不固定)
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
if m, ok := item.(map[string]interface{}); ok {
|
||
list = append(list, m)
|
||
}
|
||
}
|
||
|
||
// 7. 返回标准化结果
|
||
return map[string]interface{}{
|
||
"domain": domain,
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processScenic 旅游景区查询
|
||
func (s *ToolboxService) processScenic(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 至少一个检索参数
|
||
word, _ := params["word"].(string)
|
||
city, _ := params["city"].(string)
|
||
province, _ := params["province"].(string)
|
||
|
||
if word == "" && city == "" && province == "" {
|
||
return nil, xerr.NewErrMsg("word / city / province 至少填写一个")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{}
|
||
if word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
if city != "" {
|
||
reqParams["city"] = city
|
||
}
|
||
if province != "" {
|
||
reqParams["province"] = province
|
||
}
|
||
|
||
// 可选:分页
|
||
if num, ok := params["num"].(float64); ok && num > 0 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
if page, ok := params["page"].(string); ok && page != "" {
|
||
reqParams["page"] = page
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("scenic/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求旅游景区接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("旅游景区接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析旅游景区数据失败")
|
||
}
|
||
|
||
// 5. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("景区列表数据异常")
|
||
}
|
||
|
||
// 6. 字段白名单
|
||
allowed := map[string]bool{
|
||
"name": true,
|
||
"province": true,
|
||
"city": true,
|
||
"content": true,
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
if clean["name"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
|
||
// 7. 返回标准化结果
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processMingyan 名人名言查询
|
||
func (s *ToolboxService) processMingyan(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选:名言类型
|
||
if tid, ok := params["typeid"].(float64); ok {
|
||
reqParams["typeid"] = int(tid)
|
||
}
|
||
|
||
// 可选:返回数量
|
||
if num, ok := params["num"].(float64); ok && num > 0 {
|
||
reqParams["num"] = int(num)
|
||
} else {
|
||
reqParams["num"] = 1
|
||
}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("mingyan/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求名人名言接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("名人名言接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析名人名言数据失败")
|
||
}
|
||
|
||
// 4. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("名言列表数据异常")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"content": true,
|
||
"author": true,
|
||
"typeid": true,
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
if clean["content"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
|
||
// 6. 返回标准化结果
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processTianqiShiju 天气诗句查询
|
||
func (s *ToolboxService) processTianqiShiju(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选:天气类型
|
||
if tqtype, ok := params["tqtype"].(float64); ok {
|
||
reqParams["tqtype"] = int(tqtype)
|
||
}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("tianqishiju/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求天气诗句接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("天气诗句接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析天气诗句数据失败")
|
||
}
|
||
|
||
// 4. 字段白名单
|
||
allowed := map[string]bool{
|
||
"content": true,
|
||
"author": true,
|
||
"source": true,
|
||
"tqtype": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 5. 天气类型可读化
|
||
tqTypeMap := map[int]string{
|
||
1: "风", 2: "云", 3: "雨", 4: "雪",
|
||
5: "霜", 6: "露", 7: "雾", 8: "雷",
|
||
9: "晴", 10: "阴",
|
||
}
|
||
|
||
if t, ok := clean["tqtype"].(float64); ok {
|
||
if name, exists := tqTypeMap[int(t)]; exists {
|
||
clean["weather"] = name
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processJieQi 二十四节气查询
|
||
func (s *ToolboxService) processJieQi(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
name, ok := params["word"].(string)
|
||
if !ok || name == "" {
|
||
return nil, xerr.NewErrMsg("参数 word 不能为空,例如:立春")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"word": name,
|
||
}
|
||
|
||
// 可选:年份
|
||
if year, ok := params["year"].(string); ok && year != "" {
|
||
reqParams["year"] = year
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("jieqi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求二十四节气接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("二十四节气接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析二十四节气数据失败")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"name": true,
|
||
"day": true,
|
||
"jieshao": true,
|
||
"yiji": true,
|
||
"shiju": true,
|
||
"xishu": true,
|
||
"meishi": true,
|
||
"yuanyin": true,
|
||
"nameimg": true,
|
||
"date": true, // 内嵌对象
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 6. 公历 / 农历字段可读化(可选)
|
||
if date, ok := clean["date"].(map[string]interface{}); ok {
|
||
clean["greg_date"] = date["gregdate"]
|
||
clean["lunar_date"] = date["lunardate"]
|
||
clean["lunar_year"] = date["cnyear"]
|
||
clean["lunar_zodiac"] = date["cnzodiac"]
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processBloodPair 血型配对查询(娱乐)
|
||
func (s *ToolboxService) processBloodPair(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
me, ok1 := params["me"].(string)
|
||
he, ok2 := params["he"].(string)
|
||
|
||
if !ok1 || !ok2 || me == "" || he == "" {
|
||
return nil, xerr.NewErrMsg("参数 me 和 he 不能为空,例如:me=O&he=A")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"me": me,
|
||
"he": he,
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("blood/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求血型配对接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("血型配对接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析血型配对数据失败")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"pair": true,
|
||
"title": true,
|
||
"content": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 6. 增加娱乐声明(非常重要)
|
||
clean["notice"] = "本结果仅供娱乐,不代表科学结论"
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processZodiacPair 生肖配对查询(娱乐)
|
||
func (s *ToolboxService) processZodiacPair(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
me, ok1 := params["me"].(string)
|
||
he, ok2 := params["he"].(string)
|
||
|
||
if !ok1 || !ok2 || me == "" || he == "" {
|
||
return nil, xerr.NewErrMsg("参数 me 和 he 不能为空,例如:me=猴&he=羊")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"me": me,
|
||
"he": he,
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("zodiac/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求生肖配对接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("生肖配对接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析生肖配对数据失败")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"title": true,
|
||
"fcontent": true,
|
||
"mcontent": true,
|
||
"fcontent1": true,
|
||
"mcontent1": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 6. 明确娱乐声明(非常重要)
|
||
clean["notice"] = "本结果仅供娱乐,不代表科学结论"
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processSayLove 土味情话
|
||
func (s *ToolboxService) processSayLove(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数(无需业务参数)
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("saylove/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求土味情话接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("土味情话接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析土味情话数据失败")
|
||
}
|
||
|
||
// 4. 字段白名单
|
||
allowed := map[string]bool{
|
||
"content": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 5. 兜底校验
|
||
if clean["content"] == nil {
|
||
return nil, xerr.NewErrMsg("土味情话内容为空")
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processStar 星座运势查询(娱乐)
|
||
func (s *ToolboxService) processStar(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
astro, ok := params["astro"].(string)
|
||
if !ok || astro == "" {
|
||
return nil, xerr.NewErrMsg("参数 astro 不能为空,例如:金牛座 或 taurus")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"astro": astro,
|
||
}
|
||
|
||
// 可选:日期
|
||
if date, ok := params["date"].(string); ok && date != "" {
|
||
reqParams["date"] = date
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("star/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求星座运势接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("星座运势接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析星座运势数据失败")
|
||
}
|
||
|
||
// 5. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("星座运势列表数据异常")
|
||
}
|
||
|
||
// 6. 字段白名单
|
||
allowed := map[string]bool{
|
||
"type": true,
|
||
"content": true,
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
if clean["type"] != nil && clean["content"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
|
||
// 7. 返回标准化结果
|
||
return map[string]interface{}{
|
||
"astro": astro,
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processPinyin 汉字转拼音
|
||
func (s *ToolboxService) processPinyin(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
text, ok := params["text"].(string)
|
||
if !ok || text == "" {
|
||
return nil, xerr.NewErrMsg("参数 text 不能为空")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"text": text,
|
||
}
|
||
|
||
// 可选:type
|
||
if typ, ok := params["type"].(float64); ok {
|
||
reqParams["type"] = int(typ)
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("pinyin/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求汉字转拼音接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("汉字转拼音接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析汉字转拼音数据失败")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"pinyin": true,
|
||
"jianxie": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processNetHot 百度热搜榜
|
||
func (s *ToolboxService) processNetHot(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数(无需业务参数)
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("nethot/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求百度热搜接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("百度热搜接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析百度热搜数据失败")
|
||
}
|
||
|
||
// 4. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("热搜列表数据异常")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"keyword": true,
|
||
"brief": true,
|
||
"index": true,
|
||
"trend": true,
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
if clean["keyword"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processEnSentence 英语一句话
|
||
func (s *ToolboxService) processEnSentence(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数(无需业务参数)
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("ensentence/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求英语一句话接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("英语一句话接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析英语一句话数据失败")
|
||
}
|
||
|
||
// 4. 字段白名单
|
||
allowed := map[string]bool{
|
||
"en": true,
|
||
"zh": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processVerse 优美诗句查询
|
||
func (s *ToolboxService) processVerse(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选:返回数量
|
||
if num, ok := params["num"].(float64); ok && num > 0 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 可选:翻页
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 可选:搜索词
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("verse/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求优美诗句接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("优美诗句接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析优美诗句数据失败")
|
||
}
|
||
|
||
// 4. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("诗句列表数据异常")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"author": true,
|
||
"source": true,
|
||
"content": true,
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
if clean["content"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processPoetry 唐诗三百首查询
|
||
func (s *ToolboxService) processPoetry(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选:返回数量
|
||
if num, ok := params["num"].(float64); ok && num > 0 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 可选:翻页
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 可选:搜索词
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("poetry/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求唐诗三百首接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("唐诗三百首接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析唐诗三百首数据失败")
|
||
}
|
||
|
||
// 4. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("唐诗列表数据异常")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"title": true,
|
||
"author": true,
|
||
"kind": true,
|
||
"intro": true,
|
||
"content": true,
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
if clean["title"] != nil && clean["content"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processPoetries 唐诗大全查询
|
||
func (s *ToolboxService) processPoetries(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 必填参数校验
|
||
num, ok1 := params["num"].(float64)
|
||
page, ok2 := params["page"].(float64)
|
||
if !ok1 || !ok2 || num <= 0 || page <= 0 {
|
||
return nil, xerr.NewErrMsg("参数 num 和 page 为必填项")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"num": int(num),
|
||
"page": int(page),
|
||
}
|
||
|
||
// 可选:随机
|
||
if randVal, ok := params["rand"].(float64); ok {
|
||
reqParams["rand"] = int(randVal)
|
||
}
|
||
|
||
// 可选:关键词
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
// 可选:作者
|
||
if author, ok := params["author"].(string); ok && author != "" {
|
||
reqParams["author"] = author
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("poetries/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求唐诗大全接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("唐诗大全接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析唐诗大全数据失败")
|
||
}
|
||
|
||
// 5. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("唐诗列表数据异常")
|
||
}
|
||
|
||
// 6. 字段白名单
|
||
allowed := map[string]bool{
|
||
"title": true,
|
||
"author": true,
|
||
"content": true,
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
if clean["title"] != nil && clean["content"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processPiTongLiShi 简说历史查询
|
||
func (s *ToolboxService) processPiTongLiShi(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数(无需业务参数)
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("pitlishi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求简说历史接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("简说历史接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析简说历史数据失败")
|
||
}
|
||
|
||
// 4. 字段白名单
|
||
allowed := map[string]bool{
|
||
"content": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processMnPara 小段子查询
|
||
func (s *ToolboxService) processMnPara(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数(无需业务参数)
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("mnpara/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求小段子接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("小段子接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析小段子数据失败")
|
||
}
|
||
|
||
// 4. 字段白名单
|
||
allowed := map[string]bool{
|
||
"author": true,
|
||
"content": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processSkl 顺口溜查询
|
||
func (s *ToolboxService) processSkl(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数(无需业务参数)
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("skl/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求顺口溜接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("顺口溜接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析顺口溜数据失败")
|
||
}
|
||
|
||
// 4. 字段白名单
|
||
allowed := map[string]bool{
|
||
"content": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processSentence 精美句子查询
|
||
func (s *ToolboxService) processSentence(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数(无需业务参数)
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("sentence/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求精美句子接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("精美句子接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析精美句子数据失败")
|
||
}
|
||
|
||
// 4. 字段白名单
|
||
allowed := map[string]bool{
|
||
"author": true,
|
||
"content": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processEnWords 英汉词典查询
|
||
func (s *ToolboxService) processEnWords(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("参数 word 不能为空,例如:lexicon")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"word": word,
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("enwords/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求英汉词典接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("英汉词典接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析英汉词典数据失败")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"word": true,
|
||
"content": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processLexicon 中文词典查询
|
||
func (s *ToolboxService) processLexicon(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("参数 word 不能为空,例如:作坊")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"word": word,
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("lexicon/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求中文词典接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("中文词典接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析中文词典数据失败")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"word": true,
|
||
"content": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processLunar 中国老黄历查询
|
||
func (s *ToolboxService) processLunar(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选:日期
|
||
if date, ok := params["date"].(string); ok && date != "" {
|
||
reqParams["date"] = date
|
||
}
|
||
|
||
// 可选:按农历查询
|
||
if typ, ok := params["type"].(float64); ok {
|
||
reqParams["type"] = int(typ)
|
||
}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("lunar/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求老黄历接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("老黄历接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析老黄历数据失败")
|
||
}
|
||
|
||
// 4. 字段白名单(只保留常用字段)
|
||
allowed := map[string]bool{
|
||
"lunardate": true,
|
||
"gregoriandate": true,
|
||
"shengxiao": true,
|
||
"fitness": true,
|
||
"taboo": true,
|
||
"chongsha": true,
|
||
"shenwei": true,
|
||
"taishen": true,
|
||
"lunar_festival": true,
|
||
"festival": true,
|
||
"jieqi": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processXingZuo 星座配对查询(娱乐)
|
||
func (s *ToolboxService) processXingZuo(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 参数校验
|
||
me, ok := params["me"].(string)
|
||
if !ok || me == "" {
|
||
return nil, xerr.NewErrMsg("参数 me 不能为空,例如:金牛")
|
||
}
|
||
|
||
// 2. 请求参数
|
||
reqParams := map[string]interface{}{
|
||
"me": me,
|
||
}
|
||
|
||
// 可选:双人模式
|
||
if he, ok := params["he"].(string); ok && he != "" {
|
||
reqParams["he"] = he
|
||
}
|
||
|
||
// 可选:全部配对
|
||
if all, ok := params["all"].(float64); ok {
|
||
reqParams["all"] = int(all)
|
||
}
|
||
|
||
// 3. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("xingzuo/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求星座配对接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("星座配对接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 4. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析星座配对数据失败")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"title": true,
|
||
"grade": true,
|
||
"content": true,
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range result {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 6. 娱乐声明
|
||
clean["notice"] = "本结果仅供娱乐,不代表科学结论"
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processGodReply 神回复查询
|
||
func (s *ToolboxService) processGodReply(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选:返回数量
|
||
if num, ok := params["num"].(float64); ok && num > 0 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("godreply/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求神回复接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("神回复接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析神回复数据失败")
|
||
}
|
||
|
||
// 4. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("神回复列表数据异常")
|
||
}
|
||
|
||
// 5. 字段白名单
|
||
allowed := map[string]bool{
|
||
"title": true,
|
||
"content": true,
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
if clean["content"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processXiehou 歇后语查询
|
||
func (s *ToolboxService) processXiehou(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 1. 请求参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选:返回数量(1~10)
|
||
if num, ok := params["num"].(float64); ok && num > 0 && num <= 10 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 2. 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("xiehou/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求歇后语接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("歇后语接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 3. 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析歇后语数据失败")
|
||
}
|
||
|
||
// 4. 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("歇后语列表数据异常")
|
||
}
|
||
|
||
// 5. 字段白名单(只保留需要字段)
|
||
allowed := map[string]bool{
|
||
"quest": true, // 谜面
|
||
"result": true, // 谜底
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 至少要有谜面和谜底
|
||
if clean["quest"] != nil && clean["result"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processRKL 绕口令查询
|
||
func (s *ToolboxService) processRKL(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 可选:返回数量 1~10
|
||
if num, ok := params["num"].(float64); ok && num > 0 && num <= 10 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("rkl/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求绕口令接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("绕口令接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析绕口令数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("绕口令列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
// 字段白名单
|
||
clean := map[string]interface{}{}
|
||
if content, ok := raw["content"]; ok && content != nil {
|
||
// 去除HTML标签
|
||
if contentStr, ok := content.(string); ok {
|
||
// 移除所有HTML标签
|
||
re := regexp.MustCompile(`<[^>]+>`)
|
||
cleanContent := re.ReplaceAllString(contentStr, "")
|
||
// 替换<br>、<br/>等换行标签为换行符
|
||
cleanContent = regexp.MustCompile(`(?i)<br\s*/?>`).ReplaceAllString(cleanContent, "\n")
|
||
// 移除多余的空行
|
||
cleanContent = regexp.MustCompile(`\n{3,}`).ReplaceAllString(cleanContent, "\n\n")
|
||
// 去除首尾空白
|
||
cleanContent = strings.TrimSpace(cleanContent)
|
||
clean["content"] = cleanContent
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processCName 网络取名
|
||
func (s *ToolboxService) processCName(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 返回数量(1~50)
|
||
if num, ok := params["num"].(float64); ok && num > 0 && num <= 50 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 性别:1男 2女 3中性
|
||
if sex, ok := params["sex"].(float64); ok && sex >= 1 && sex <= 3 {
|
||
reqParams["sex"] = int(sex)
|
||
}
|
||
|
||
// 包含的字
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
// 名字字数(1~3)
|
||
if wordnum, ok := params["wordnum"].(float64); ok && wordnum >= 1 && wordnum <= 3 {
|
||
reqParams["wordnum"] = int(wordnum)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("cname/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求网络取名接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("网络取名接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析网络取名数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("网络取名列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if naming, ok := raw["naming"]; ok && naming != nil {
|
||
clean["naming"] = naming
|
||
}
|
||
if sex, ok := raw["sex"]; ok {
|
||
clean["sex"] = sex
|
||
}
|
||
if wordnum, ok := raw["wordnum"]; ok {
|
||
clean["wordnum"] = wordnum
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processShares 股市术语查询
|
||
func (s *ToolboxService) processShares(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 搜索词(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("股市术语查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 返回数量(必填)
|
||
num, ok := params["num"].(float64)
|
||
if !ok || num <= 0 {
|
||
num = 5 // 给一个安全默认值
|
||
}
|
||
reqParams["num"] = int(num)
|
||
|
||
// 页码(可选)
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("shares/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求股市术语接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("股市术语接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析股市术语数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("股市术语列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if term, ok := raw["term"]; ok {
|
||
clean["term"] = term
|
||
}
|
||
if content, ok := raw["content"]; ok {
|
||
clean["content"] = content
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processHotWord 网络流行语查询
|
||
func (s *ToolboxService) processHotWord(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 搜索词(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("网络流行语查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 返回数量(必填)
|
||
num, ok := params["num"].(float64)
|
||
if !ok || num <= 0 {
|
||
num = 5 // 给一个安全默认值
|
||
}
|
||
reqParams["num"] = int(num)
|
||
|
||
// 页码(可选)
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("hotword/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求网络流行语接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("网络流行语接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析网络流行语数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("网络流行语列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if title, ok := raw["title"]; ok {
|
||
clean["title"] = title
|
||
}
|
||
if content, ok := raw["content"]; ok {
|
||
clean["content"] = content
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processCityRiddle 地名谜语查询
|
||
func (s *ToolboxService) processCityRiddle(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 地名谜语接口无需额外参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("cityriddle/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求地名谜语接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("地名谜语接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析地名谜语数据失败")
|
||
}
|
||
|
||
// 字段白名单
|
||
clean := map[string]interface{}{}
|
||
if quest, ok := result["quest"]; ok {
|
||
clean["quest"] = quest
|
||
}
|
||
if answer, ok := result["result"]; ok {
|
||
clean["answer"] = answer
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": 1,
|
||
"list": []map[string]interface{}{clean},
|
||
}, nil
|
||
}
|
||
|
||
// processWenDa 一战到底知识竞答
|
||
func (s *ToolboxService) processWenDa(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 一战到底接口无需额外参数
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("wenda/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求一战到底接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("一战到底接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析一战到底数据失败")
|
||
}
|
||
|
||
// 字段白名单
|
||
clean := map[string]interface{}{}
|
||
if quest, ok := result["quest"]; ok {
|
||
clean["quest"] = quest
|
||
}
|
||
if answer, ok := result["result"]; ok {
|
||
clean["answer"] = answer
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": 1,
|
||
"list": []map[string]interface{}{clean},
|
||
}, nil
|
||
}
|
||
|
||
// processChengYu 成语典故查询
|
||
func (s *ToolboxService) processChengYu(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 搜索词(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("成语典故查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 返回数量(可选)
|
||
if num, ok := params["num"].(float64); ok && num > 0 && num <= 50 {
|
||
reqParams["num"] = int(num)
|
||
} else if numStr, ok := params["num"].(string); ok && numStr != "" {
|
||
if numInt, err := strconv.Atoi(numStr); err == nil && numInt > 0 && numInt <= 50 {
|
||
reqParams["num"] = numInt
|
||
}
|
||
}
|
||
|
||
// 搜索模式(可选)
|
||
if mode, ok := params["mode"].(float64); ok && mode >= 0 && mode <= 2 {
|
||
reqParams["mode"] = int(mode)
|
||
} else if modeStr, ok := params["mode"].(string); ok && modeStr != "" {
|
||
if modeInt, err := strconv.Atoi(modeStr); err == nil && modeInt >= 0 && modeInt <= 2 {
|
||
reqParams["mode"] = modeInt
|
||
}
|
||
}
|
||
|
||
// 页码(可选)
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
} else if pageStr, ok := params["page"].(string); ok && pageStr != "" {
|
||
if pageInt, err := strconv.Atoi(pageStr); err == nil && pageInt > 0 {
|
||
reqParams["page"] = pageInt
|
||
}
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("chengyu/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求成语典故接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("成语典故接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析成语典故数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("成语典故列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if chengyu, ok := raw["chengyu"]; ok {
|
||
clean["chengyu"] = chengyu
|
||
}
|
||
if pinyin, ok := raw["pinyin"]; ok {
|
||
clean["pinyin"] = pinyin
|
||
}
|
||
if diangu, ok := raw["diangu"]; ok {
|
||
clean["diangu"] = diangu
|
||
}
|
||
if chuchu, ok := raw["chuchu"]; ok {
|
||
clean["chuchu"] = chuchu
|
||
}
|
||
if fanli, ok := raw["fanli"]; ok {
|
||
clean["fanli"] = fanli
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processNaoWan 脑筋急转弯查询
|
||
func (s *ToolboxService) processNaoWan(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 返回数量(可选,默认5条)
|
||
if num, ok := params["num"].(float64); ok && num > 0 {
|
||
reqParams["num"] = int(num)
|
||
} else {
|
||
reqParams["num"] = 5 // 默认返回5条
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("naowan/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求脑筋急转弯接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("脑筋急转弯接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析脑筋急转弯数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("脑筋急转弯列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if quest, ok := raw["quest"]; ok {
|
||
clean["quest"] = quest
|
||
}
|
||
if result, ok := raw["result"]; ok {
|
||
clean["result"] = result
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
|
||
}
|
||
|
||
// processDOB 生日性格查询
|
||
func (s *ToolboxService) processDOB(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 月份(必填)- 支持字符串和数字类型
|
||
var m int
|
||
switch v := params["m"].(type) {
|
||
case float64:
|
||
if v < 1 || v > 12 {
|
||
return nil, xerr.NewErrMsg("生日性格查询缺少必填参数:m(月份 1-12)")
|
||
}
|
||
m = int(v)
|
||
case string:
|
||
if v == "" {
|
||
return nil, xerr.NewErrMsg("生日性格查询缺少必填参数:m(月份 1-12)")
|
||
}
|
||
mInt, err := strconv.Atoi(v)
|
||
if err != nil || mInt < 1 || mInt > 12 {
|
||
return nil, xerr.NewErrMsg("生日性格查询参数 m 必须是 1-12 的数字")
|
||
}
|
||
m = mInt
|
||
default:
|
||
return nil, xerr.NewErrMsg("生日性格查询缺少必填参数:m(月份 1-12)")
|
||
}
|
||
reqParams["m"] = m
|
||
|
||
// 日期(必填)- 支持字符串和数字类型
|
||
var d int
|
||
switch v := params["d"].(type) {
|
||
case float64:
|
||
if v < 1 || v > 31 {
|
||
return nil, xerr.NewErrMsg("生日性格查询缺少必填参数:d(日期 1-31)")
|
||
}
|
||
d = int(v)
|
||
case string:
|
||
if v == "" {
|
||
return nil, xerr.NewErrMsg("生日性格查询缺少必填参数:d(日期 1-31)")
|
||
}
|
||
dInt, err := strconv.Atoi(v)
|
||
if err != nil || dInt < 1 || dInt > 31 {
|
||
return nil, xerr.NewErrMsg("生日性格查询参数 d 必须是 1-31 的数字")
|
||
}
|
||
d = dInt
|
||
default:
|
||
return nil, xerr.NewErrMsg("生日性格查询缺少必填参数:d(日期 1-31)")
|
||
}
|
||
reqParams["d"] = d
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("dob/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求生日性格接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("生日性格接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析生日性格数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"title": result["title"],
|
||
"content": result["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processDictum 名言警句查询
|
||
func (s *ToolboxService) processDictum(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 返回数量(必填)
|
||
num, ok := params["num"].(float64)
|
||
if !ok || num <= 0 {
|
||
num = 5 // 给一个安全默认值
|
||
}
|
||
reqParams["num"] = int(num)
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("dictum/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求名言警句接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("名言警句接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析名言警句数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("名言警句列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if mrname, ok := raw["mrname"]; ok {
|
||
clean["mrname"] = mrname
|
||
}
|
||
if content, ok := raw["content"]; ok {
|
||
clean["content"] = content
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processJoke 雷人笑话查询
|
||
func (s *ToolboxService) processJoke(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 返回数量(必填)
|
||
num, ok := params["num"].(float64)
|
||
if !ok || num <= 0 {
|
||
num = 5 // 给一个安全默认值
|
||
}
|
||
reqParams["num"] = int(num)
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("joke/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求雷人笑话接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("雷人笑话接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析雷人笑话数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("雷人笑话列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if title, ok := raw["title"]; ok {
|
||
clean["title"] = title
|
||
}
|
||
if content, ok := raw["content"]; ok {
|
||
clean["content"] = content
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processDream 周公解梦查询
|
||
func (s *ToolboxService) processDream(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 搜索词(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("周公解梦查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 返回数量(必填)
|
||
num, ok := params["num"].(float64)
|
||
if !ok || num <= 0 {
|
||
num = 5 // 给一个安全默认值
|
||
}
|
||
reqParams["num"] = int(num)
|
||
|
||
// 页码(可选)
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("dream/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求周公解梦接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("周公解梦接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析周公解梦数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("周公解梦列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if title, ok := raw["title"]; ok {
|
||
clean["title"] = title
|
||
}
|
||
if typ, ok := raw["type"]; ok {
|
||
clean["type"] = typ
|
||
}
|
||
if content, ok := raw["result"]; ok {
|
||
clean["result"] = content
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processCaiPu 菜谱查询
|
||
func (s *ToolboxService) processCaiPu(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 搜索词(可选)
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
// 返回数量(可选)
|
||
if num, ok := params["num"].(float64); ok && num > 0 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 页码(可选)
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("caipu/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求菜谱查询接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("菜谱查询接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析菜谱查询数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("菜谱查询列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if name, ok := raw["cp_name"]; ok {
|
||
clean["cp_name"] = name
|
||
}
|
||
if typ, ok := raw["type_name"]; ok {
|
||
clean["type_name"] = typ
|
||
}
|
||
if yuanliao, ok := raw["yuanliao"]; ok {
|
||
clean["yuanliao"] = yuanliao
|
||
}
|
||
if tiaoliao, ok := raw["tiaoliao"]; ok {
|
||
clean["tiaoliao"] = tiaoliao
|
||
}
|
||
if zuofa, ok := raw["zuofa"]; ok {
|
||
clean["zuofa"] = zuofa
|
||
}
|
||
if tishi, ok := raw["tishi"]; ok {
|
||
clean["tishi"] = tishi
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processWxNew 微信文章精选查询
|
||
func (s *ToolboxService) processWxNew(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 返回数量(必填)
|
||
num, ok := params["num"].(float64)
|
||
if !ok || num <= 0 {
|
||
num = 10
|
||
}
|
||
reqParams["num"] = int(num)
|
||
|
||
// 页码(可选)
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 随机(可选)
|
||
if rand, ok := params["rand"].(float64); ok && rand == 1 {
|
||
reqParams["rand"] = 1
|
||
}
|
||
|
||
// 关键词(可选)
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("wxnew/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求微信文章精选接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("微信文章精选接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析微信文章精选数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("微信文章精选列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if title, ok := raw["title"]; ok {
|
||
clean["title"] = title
|
||
}
|
||
if url, ok := raw["url"]; ok {
|
||
clean["url"] = url
|
||
}
|
||
if username, ok := raw["username"]; ok {
|
||
clean["username"] = username
|
||
}
|
||
if ctime, ok := raw["ctime"]; ok {
|
||
clean["ctime"] = ctime
|
||
}
|
||
if picurl, ok := raw["picurl"]; ok {
|
||
clean["picurl"] = picurl
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processConstellation 星座运势查询
|
||
func (s *ToolboxService) processConstellation(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 必填:星座名称
|
||
astro, ok := params["astro"].(string)
|
||
if !ok || astro == "" {
|
||
return nil, xerr.NewErrMsg("astro 星座名称参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["astro"] = astro
|
||
|
||
// 可选:日期 (fortune参数转换为date)
|
||
if fortune, ok := params["fortune"].(string); ok && fortune != "" {
|
||
now := time.Now()
|
||
switch fortune {
|
||
case "tomorrow":
|
||
date := now.AddDate(0, 0, 1)
|
||
reqParams["date"] = date.Format("2006-01-02")
|
||
case "week":
|
||
// 本周返回当前日期
|
||
reqParams["date"] = now.Format("2006-01-02")
|
||
case "month":
|
||
// 本月返回当前日期
|
||
reqParams["date"] = now.Format("2006-01-02")
|
||
default: // today
|
||
reqParams["date"] = now.Format("2006-01-02")
|
||
}
|
||
}
|
||
|
||
resp, err := s.tianxingjuheClient.Get("star/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求星座运势API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("星座运势接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析星座运势数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := resultMap["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("星座运势列表数据异常")
|
||
}
|
||
|
||
// 将 list 转换为扁平化的 map
|
||
result := map[string]interface{}{
|
||
"astro": astro,
|
||
}
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
typeName, ok := raw["type"].(string)
|
||
content, hasContent := raw["content"].(string)
|
||
|
||
if !ok || !hasContent {
|
||
continue
|
||
}
|
||
|
||
// 将 type 映射到对应的字段名
|
||
switch typeName {
|
||
case "综合指数":
|
||
result["summary"] = content
|
||
case "爱情指数":
|
||
result["love"] = content
|
||
case "工作指数":
|
||
result["work"] = content
|
||
case "财运指数":
|
||
result["money"] = content
|
||
case "健康指数":
|
||
result["health"] = content
|
||
case "幸运颜色":
|
||
result["color"] = content
|
||
case "幸运数字":
|
||
result["number"] = content
|
||
case "贵人星座":
|
||
result["qfriend"] = content
|
||
case "今日概述":
|
||
result["today_summary"] = content
|
||
}
|
||
}
|
||
|
||
return result, nil
|
||
}
|
||
|
||
// processFanyi 在线翻译
|
||
func (s *ToolboxService) processFanyi(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 必填:待翻译文本
|
||
content, ok := params["content"].(string)
|
||
if !ok || content == "" {
|
||
return nil, xerr.NewErrMsg("content 待翻译文本参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["content"] = content
|
||
|
||
// 可选:源语言 (默认自动检测)
|
||
if from, ok := params["from"].(string); ok && from != "" {
|
||
reqParams["from"] = from
|
||
}
|
||
|
||
// 可选:目标语言 (默认中文)
|
||
if to, ok := params["to"].(string); ok && to != "" {
|
||
reqParams["to"] = to
|
||
}
|
||
|
||
resp, err := s.tianxingjuheClient.Get("fanyi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求在线翻译API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("在线翻译接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析翻译数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"content": resultMap["content"],
|
||
"from": resultMap["from"],
|
||
"to": resultMap["to"],
|
||
"result": resultMap["result"],
|
||
}, nil
|
||
}
|
||
|
||
// processHoliday 节假日查询
|
||
func (s *ToolboxService) processHoliday(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
// 调试日志:打印接收到的所有参数
|
||
logx.Infof("processHoliday 收到的参数: %+v", params)
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 获取查询方式(1=按年,2=按月),默认按年
|
||
var queryType int = 1
|
||
if typ, ok := params["type"]; ok {
|
||
switch v := typ.(type) {
|
||
case float64:
|
||
queryType = int(v)
|
||
case string:
|
||
if val, err := strconv.Atoi(v); err == nil {
|
||
queryType = val
|
||
}
|
||
case json.Number:
|
||
if val, err := strconv.Atoi(v.String()); err == nil {
|
||
queryType = val
|
||
}
|
||
}
|
||
}
|
||
|
||
// 将type直接传给天行API
|
||
reqParams["type"] = queryType
|
||
|
||
// 传当前日期
|
||
reqParams["date"] = time.Now().Format("2006-01-02")
|
||
|
||
logx.Infof("调用天行API: type=%d, date=%s", queryType, reqParams["date"])
|
||
|
||
resp, err := s.tianxingjuheClient.Get("jiejiari/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求节假日查询API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("节假日查询接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析节假日数据失败")
|
||
}
|
||
|
||
rawList, ok := resultMap["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("节假日列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
clean := map[string]interface{}{}
|
||
for _, k := range []string{"date", "name", "info", "tip", "cnweekday", "lunaryear", "lunarmonth", "lunarday", "wage", "isnotwork", "daycode"} {
|
||
if v, ok := raw[k]; ok {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processGarbage 垃圾分类查询
|
||
func (s *ToolboxService) processGarbage(ctx context.Context, params map[string]interface{}) (map[string]interface{}, error) {
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 必填:垃圾名称
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("word 垃圾名称参数不能为空且必须为字符串")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
resp, err := s.tianxingjuheClient.Get("lajifenlei/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求垃圾分类查询API失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("垃圾分类查询接口返回异常: %s", resp.Msg))
|
||
}
|
||
|
||
resultMap, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析垃圾分类数据失败")
|
||
}
|
||
|
||
// 解析列表
|
||
rawList, ok := resultMap["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("垃圾分类列表数据异常")
|
||
}
|
||
|
||
typeMap := map[int]string{
|
||
0: "可回收物",
|
||
1: "有害垃圾",
|
||
2: "厨余垃圾(湿)",
|
||
3: "其他垃圾(干)",
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
clean := map[string]interface{}{
|
||
"name": raw["name"],
|
||
}
|
||
if t, ok := raw["type"].(float64); ok {
|
||
clean["type"] = int(t)
|
||
if name, exists := typeMap[int(t)]; exists {
|
||
clean["type_name"] = name
|
||
}
|
||
}
|
||
if explain, ok := raw["explain"]; ok {
|
||
clean["explain"] = explain
|
||
}
|
||
if tip, ok := raw["tip"]; ok {
|
||
clean["tip"] = tip
|
||
}
|
||
if contain, ok := raw["contain"]; ok {
|
||
clean["contain"] = contain
|
||
}
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"word": word,
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processZone 地区搜索查询
|
||
func (s *ToolboxService) processZone(ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 地区名称(必填)
|
||
area, ok := params["area"].(string)
|
||
if !ok || area == "" {
|
||
return nil, xerr.NewErrMsg("地区搜索缺少必填参数:area")
|
||
}
|
||
reqParams["area"] = area
|
||
|
||
// 返回数量(可选)
|
||
if num, ok := params["num"].(float64); ok && num > 0 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 翻页(可选)
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("citylookup/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求地区搜索接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("地区搜索接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析地区搜索数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("地区搜索列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if v, ok := raw["adcode"]; ok {
|
||
clean["adcode"] = v
|
||
}
|
||
if v, ok := raw["areacn"]; ok {
|
||
clean["areacn"] = v
|
||
}
|
||
if v, ok := raw["areaen"]; ok {
|
||
clean["areaen"] = v
|
||
}
|
||
if v, ok := raw["areaid"]; ok {
|
||
clean["areaid"] = v
|
||
}
|
||
if v, ok := raw["citycn"]; ok {
|
||
clean["citycn"] = v
|
||
}
|
||
if v, ok := raw["cityen"]; ok {
|
||
clean["cityen"] = v
|
||
}
|
||
if v, ok := raw["areatype"]; ok {
|
||
clean["areatype"] = v
|
||
}
|
||
if v, ok := raw["latitude"]; ok {
|
||
clean["latitude"] = v
|
||
}
|
||
if v, ok := raw["longitude"]; ok {
|
||
clean["longitude"] = v
|
||
}
|
||
if v, ok := raw["provincecn"]; ok {
|
||
clean["provincecn"] = v
|
||
}
|
||
if v, ok := raw["provinceen"]; ok {
|
||
clean["provinceen"] = v
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processHuaYu 花语箴言查询
|
||
func (s *ToolboxService) processHuaYu(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 花的名字(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("花语箴言查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("huayu/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求花语箴言接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("花语箴言接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析花语箴言数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"cnflower": result["cnflower"],
|
||
"enflower": result["enflower"],
|
||
"flowerlang": result["flowerlang"],
|
||
"flowerprov": result["flowerprov"],
|
||
}, nil
|
||
}
|
||
|
||
// processMoodPoetry 情绪诗句查询
|
||
func (s *ToolboxService) processMoodPoetry(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 分类查询(可选,默认随机)
|
||
if typ, ok := params["type"].(float64); ok && typ >= 1 && typ <= 4 {
|
||
reqParams["type"] = int(typ)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("moodpoetry/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求情绪诗句接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("情绪诗句接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析情绪诗句数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"type": result["type"],
|
||
"title": result["title"],
|
||
"author": result["author"],
|
||
"content": result["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processPcTerm 计算机术语查询
|
||
func (s *ToolboxService) processPcTerm(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 术语缩写(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("计算机术语查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("pcterm/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求计算机术语接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("计算机术语接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析计算机术语数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"abbr": result["abbr"],
|
||
"type": result["type"],
|
||
"notes": result["notes"],
|
||
}, nil
|
||
}
|
||
|
||
// processTarga 扩展名查询
|
||
func (s *ToolboxService) processTarga(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 文件后缀名(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("扩展名查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("targa/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求扩展名查询接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("扩展名查询接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析扩展名查询数据失败")
|
||
}
|
||
|
||
// 清理HTML标签
|
||
targa := ""
|
||
notes := ""
|
||
|
||
if v, ok := result["targa"].(string); ok {
|
||
targa = v
|
||
}
|
||
|
||
if v, ok := result["notes"].(string); ok {
|
||
// 移除HTML标签
|
||
re := regexp.MustCompile(`<[^>]+>`)
|
||
notes = re.ReplaceAllString(v, "")
|
||
// 替换换行标签
|
||
notes = regexp.MustCompile(`(?i)<br\s*/?>`).ReplaceAllString(notes, "\n")
|
||
// 去除多余空行
|
||
notes = regexp.MustCompile(`\n{3,}`).ReplaceAllString(notes, "\n\n")
|
||
// 去除首尾空白
|
||
notes = strings.TrimSpace(notes)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"targa": targa,
|
||
"notes": notes,
|
||
}, nil
|
||
}
|
||
|
||
// processDuiShiCi 填对诗词查询
|
||
func (s *ToolboxService) processDuiShiCi(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 填对诗词接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("duishici/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求填对诗词接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("填对诗词接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析填对诗词数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"quest": result["quest"],
|
||
"answer": result["answer"],
|
||
"source": result["source"],
|
||
}, nil
|
||
}
|
||
|
||
// processMsdl 民俗对联查询
|
||
func (s *ToolboxService) processMsdl(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 返回数量(可选)
|
||
if num, ok := params["num"].(float64); ok && num > 0 && num <= 10 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 分类查询(可选)
|
||
if fenlei, ok := params["fenlei"].(string); ok && fenlei != "" {
|
||
reqParams["fenlei"] = fenlei
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("msdl/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求民俗对联接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("民俗对联接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析民俗对联数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("民俗对联列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if v, ok := raw["fenlei"]; ok {
|
||
clean["fenlei"] = v
|
||
}
|
||
if v, ok := raw["hengpi"]; ok {
|
||
clean["hengpi"] = v
|
||
}
|
||
if v, ok := raw["shanglian"]; ok {
|
||
clean["shanglian"] = v
|
||
}
|
||
if v, ok := raw["xialian"]; ok {
|
||
clean["xialian"] = v
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processTimeZone 国际时区查询
|
||
func (s *ToolboxService) processTimeZone(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 国家/地区(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("国际时区查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("timezone/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求国际时区接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("国际时区接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析国际时区数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("国际时区列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if country, ok := raw["country"]; ok {
|
||
clean["country"] = country
|
||
}
|
||
if areaname, ok := raw["areaname"]; ok {
|
||
clean["areaname"] = areaname
|
||
}
|
||
if timezone, ok := raw["timezone"]; ok {
|
||
clean["timezone"] = timezone
|
||
}
|
||
if continent, ok := raw["continent"]; ok {
|
||
clean["continent"] = continent
|
||
}
|
||
if countryen, ok := raw["countryen"]; ok {
|
||
clean["countryen"] = countryen
|
||
}
|
||
if countryezm, ok := raw["countryezm"]; ok {
|
||
clean["countryezm"] = countryezm
|
||
}
|
||
if countryszm, ok := raw["countryszm"]; ok {
|
||
clean["countryszm"] = countryszm
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processDuoYinZi 多音字查询
|
||
func (s *ToolboxService) processDuoYinZi(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
logx.Infof("processDuoYinZi 收到的参数: %+v", params)
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 多音字(必填)
|
||
word, ok := params["word"].(string)
|
||
logx.Infof("word 值: %v, 类型: %T, ok: %v", word, params["word"], ok)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("多音字查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
logx.Infof("调用天行API: word=%s", word)
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("duoyinzi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求多音字接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("该字无多音字."))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析多音字数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("多音字列表数据异常")
|
||
}
|
||
|
||
// 将多音字信息合并成一个字符串
|
||
list := make([]string, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
if s, ok := item.(string); ok {
|
||
list = append(list, s)
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"word": result["hanzi"],
|
||
"content": strings.Join(list, "\n"),
|
||
}, nil
|
||
}
|
||
|
||
// processDailyTel 全国常用电话
|
||
func (s *ToolboxService) processDailyTel(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 机构名称或电话(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("全国常用电话查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("dailytel/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求全国常用电话接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("全国常用电话接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析全国常用电话数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("全国常用电话列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if name, ok := raw["name"]; ok {
|
||
clean["name"] = name
|
||
}
|
||
if cate, ok := raw["cate"]; ok {
|
||
clean["cate"] = cate
|
||
}
|
||
if tel, ok := raw["tel"]; ok {
|
||
clean["tel"] = tel
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processObdCode 汽车 OBD 故障码查询
|
||
func (s *ToolboxService) processObdCode(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// OBD 故障码(必填)
|
||
code, ok := params["code"].(string)
|
||
if !ok || code == "" {
|
||
return nil, xerr.NewErrMsg("汽车OBD查询缺少必填参数:code")
|
||
}
|
||
reqParams["code"] = code
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("obdcode/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求汽车OBD接口失败: %v", err))
|
||
}
|
||
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("汽车OBD接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析汽车OBD数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("汽车OBD列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if v, ok := raw["code"]; ok {
|
||
clean["code"] = v
|
||
}
|
||
if v, ok := raw["descr"]; ok {
|
||
clean["descr"] = v
|
||
}
|
||
if v, ok := raw["ennote"]; ok {
|
||
clean["ennote"] = v
|
||
}
|
||
if v, ok := raw["zhnote"]; ok {
|
||
clean["zhnote"] = v
|
||
}
|
||
if v, ok := raw["carmodel"]; ok {
|
||
clean["carmodel"] = v
|
||
}
|
||
if v, ok := raw["category"]; ok {
|
||
clean["category"] = v
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processChaiZi 汉语拆字查询
|
||
func (s *ToolboxService) processChaiZi(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 查询内容(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("汉语拆字查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 查询类型(可选,默认 0)
|
||
var queryType int
|
||
if typ, ok := params["type"]; ok {
|
||
switch v := typ.(type) {
|
||
case float64:
|
||
queryType = int(v)
|
||
case string:
|
||
if val, err := strconv.Atoi(v); err == nil {
|
||
queryType = val
|
||
}
|
||
case json.Number:
|
||
if val, err := strconv.Atoi(v.String()); err == nil {
|
||
queryType = val
|
||
}
|
||
}
|
||
}
|
||
reqParams["type"] = queryType
|
||
|
||
logx.Infof("汉字拆解 - type: %d, word: %s", queryType, word)
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("chaizi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求汉语拆字接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("汉语拆字接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析汉语拆字数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("汉语拆字列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
clean := map[string]interface{}{}
|
||
if texts, ok := raw["texts"]; ok {
|
||
clean["texts"] = texts
|
||
}
|
||
if words, ok := raw["words"]; ok {
|
||
clean["words"] = words
|
||
}
|
||
list = append(list, clean)
|
||
}
|
||
|
||
// 将列表合并成文本格式
|
||
contentList := make([]string, 0, len(list))
|
||
for _, item := range list {
|
||
if texts, ok := item["texts"].(string); ok {
|
||
contentList = append(contentList, texts)
|
||
}
|
||
if words, ok := item["words"].(string); ok {
|
||
contentList = append(contentList, words)
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"word": word,
|
||
"content": strings.Join(contentList, "\n"),
|
||
}, nil
|
||
}
|
||
|
||
// processShiJing 诗经大全查询
|
||
func (s *ToolboxService) processShiJing(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 返回数量(可选)
|
||
if num, ok := params["num"].(float64); ok && num > 0 && num <= 10 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 关键词搜索(可选)
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("shijing/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求诗经大全接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("诗经大全接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析诗经大全数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("诗经大全列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if v, ok := raw["name"]; ok {
|
||
clean["name"] = v
|
||
}
|
||
if v, ok := raw["author"]; ok {
|
||
clean["author"] = v
|
||
}
|
||
if v, ok := raw["content"]; ok {
|
||
clean["content"] = v
|
||
}
|
||
if v, ok := raw["note"]; ok {
|
||
clean["note"] = v
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processChePai 车牌归属地查询
|
||
func (s *ToolboxService) processChePai(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 车牌代码/城市/省份(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("车牌归属地查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("chepai/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求车牌归属地接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("车牌归属地接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析车牌归属地数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"code": result["code"],
|
||
"province": result["province"],
|
||
"city": result["city"],
|
||
"citycode": result["citycode"],
|
||
}, nil
|
||
}
|
||
|
||
// processFlmj 分类名句查询
|
||
func (s *ToolboxService) processFlmj(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// Tag 类型(必填)
|
||
typ, ok := params["type"].(string)
|
||
if !ok || typ == "" {
|
||
return nil, xerr.NewErrMsg("分类名句查询缺少必填参数:type")
|
||
}
|
||
reqParams["type"] = typ
|
||
|
||
// 返回数量(可选)
|
||
if num, ok := params["num"].(float64); ok && num > 0 && num <= 20 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 翻页(可选)
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 随机(可选)
|
||
if randVal, ok := params["rand"].(float64); ok && randVal == 1 {
|
||
reqParams["rand"] = 1
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("flmj/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求分类名句接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("分类名句接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析分类名句数据失败")
|
||
}
|
||
|
||
// 检查是否返回了列表(num > 1 时)
|
||
if list, hasList := result["list"]; hasList {
|
||
if listArray, isArray := list.([]interface{}); isArray && len(listArray) > 0 {
|
||
// 返回第一个结果
|
||
if firstItem, ok := listArray[0].(map[string]interface{}); ok {
|
||
return map[string]interface{}{
|
||
"source": firstItem["source"],
|
||
"content": firstItem["content"],
|
||
}, nil
|
||
}
|
||
}
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"source": result["source"],
|
||
"content": result["content"],
|
||
}, nil
|
||
|
||
}
|
||
|
||
// processXhZd 新华字典查询
|
||
func (s *ToolboxService) processXhZd(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 查询内容(必填)
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("新华字典查询缺少必填参数:word")
|
||
}
|
||
reqParams["word"] = word
|
||
|
||
// 返回数量(可选)
|
||
if num, ok := params["num"].(float64); ok && num > 0 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 翻页(可选)
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 查询类型(可选,默认 0)
|
||
if typ, ok := params["type"].(float64); ok && typ >= 0 && typ <= 2 {
|
||
reqParams["type"] = int(typ)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("xhzd/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求新华字典接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("新华字典接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析新华字典数据失败")
|
||
}
|
||
|
||
logx.Infof("新华字典API返回的result: %+v", result)
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok || len(rawList) == 0 {
|
||
return nil, xerr.NewErrMsg("新华字典列表数据异常")
|
||
}
|
||
|
||
// 取第一个元素
|
||
firstItem, ok := rawList[0].(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("新华字典数据格式异常")
|
||
}
|
||
|
||
// 去除HTML标签
|
||
htmlTagRegex := regexp.MustCompile(`<[^>]+>`)
|
||
|
||
content := ""
|
||
if c, ok := firstItem["content"].(string); ok {
|
||
content = htmlTagRegex.ReplaceAllString(c, "")
|
||
}
|
||
|
||
explain := ""
|
||
if e, ok := firstItem["explain"].(string); ok {
|
||
explain = htmlTagRegex.ReplaceAllString(e, "")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"word": firstItem["hanzi"],
|
||
"py": firstItem["py"],
|
||
"pyyb": firstItem["pyyb"],
|
||
"wubi": firstItem["wubi"],
|
||
"bihua": firstItem["bihua"],
|
||
"bushou": firstItem["bushou"],
|
||
"bishun": firstItem["bishun"],
|
||
"content": content,
|
||
"explain": explain,
|
||
}, nil
|
||
}
|
||
|
||
// processTeleCode 标准电码查询 //改
|
||
func (s *ToolboxService) processTeleCode(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 查询内容(必填)
|
||
city, ok := params["city"].(string)
|
||
if !ok || city == "" {
|
||
return nil, xerr.NewErrMsg("标准电码查询缺少必填参数:city")
|
||
}
|
||
reqParams["text"] = city
|
||
|
||
// 返回类型(可选,默认 0)
|
||
if str, ok := params["str"].(float64); ok && (str == 0 || str == 1) {
|
||
reqParams["str"] = int(str)
|
||
}
|
||
|
||
// 转换类型(可选,默认 0)
|
||
if typ, ok := params["type"].(float64); ok && (typ == 0 || typ == 1) {
|
||
reqParams["type"] = int(typ)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("telecode/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求标准电码接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("标准电码接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析标准电码数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("标准电码列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if v, ok := raw["code"]; ok {
|
||
clean["code"] = v
|
||
}
|
||
if v, ok := raw["text"]; ok {
|
||
clean["text"] = v
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processCharConvert 简繁转换
|
||
func (s *ToolboxService) processCharConvert(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 待转换字符(必填)
|
||
text, ok := params["text"].(string)
|
||
if !ok || text == "" {
|
||
return nil, xerr.NewErrMsg("简繁转换缺少必填参数:text")
|
||
}
|
||
reqParams["text"] = text
|
||
|
||
// 转换类型(可选,默认 0 转繁体)
|
||
if typ, ok := params["type"].(float64); ok && (typ == 0 || typ == 1) {
|
||
reqParams["type"] = int(typ)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("charconvert/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求简繁转换接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("简繁转换接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析简繁转换数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"intext": result["intext"],
|
||
"outtext": result["outtext"],
|
||
}, nil
|
||
}
|
||
|
||
// processCheckIPv6 检查域名 IPv6 支持情况
|
||
func (s *ToolboxService) processCheckIPv6(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 域名(必填)
|
||
domain, ok := params["domain"].(string)
|
||
if !ok || domain == "" {
|
||
return nil, xerr.NewErrMsg("检查域名IPv6缺少必填参数:domain")
|
||
}
|
||
reqParams["domain"] = domain
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("checkipv6/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求检查域名IPv6接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("检查域名IPv6接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析检查域名IPv6数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"domain": result["domain"],
|
||
"ipv6": result["ipv6"],
|
||
"isipv6": result["isipv6"],
|
||
}, nil
|
||
}
|
||
|
||
// processWorldTime 全球时间查询
|
||
func (s *ToolboxService) processWorldTime(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 城市名称(必填)
|
||
city, ok := params["city"].(string)
|
||
if !ok || city == "" {
|
||
return nil, xerr.NewErrMsg("全球时间查询缺少必填参数:city")
|
||
}
|
||
reqParams["city"] = city
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("worldtime/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求全球时间接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("全球时间接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析全球时间数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"city": result["city"],
|
||
"encity": result["encity"],
|
||
"country": result["country"],
|
||
"encountry": result["encountry"],
|
||
"countryezm": result["countryezm"],
|
||
"countrycode": result["countrycode"],
|
||
"strtime": result["strtime"],
|
||
"timestamp": result["timestamp"],
|
||
"timeZone": result["timeZone"],
|
||
"week": result["week"],
|
||
"enweek": result["enweek"],
|
||
"weeknum": result["weeknum"],
|
||
"nowmonth": result["nowmonth"],
|
||
"ennowmonth": result["ennowmonth"],
|
||
"noon": result["noon"],
|
||
"ennoon": result["ennoon"],
|
||
"summertime": result["summertime"],
|
||
"cursummertime": result["cursummertime"],
|
||
}, nil
|
||
}
|
||
|
||
// processWxHotTopic 腾讯热搜榜查询
|
||
func (s *ToolboxService) processWxHotTopic(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("wxhottopic/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求腾讯热搜榜接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("腾讯热搜榜接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析腾讯热搜榜数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("腾讯热搜榜列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if v, ok := raw["word"]; ok {
|
||
clean["word"] = v
|
||
}
|
||
if v, ok := raw["index"]; ok {
|
||
clean["index"] = v
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processZmsc 最美宋词查询
|
||
func (s *ToolboxService) processZmsc(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("zmsc/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求最美宋词接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("最美宋词接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析最美宋词数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"source": result["source"],
|
||
"content": result["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processHsjz 失恋分手句子查询
|
||
func (s *ToolboxService) processHsjz(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("hsjz/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求失恋分手句子接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("失恋分手句子接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析失恋分手句子数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"content": result["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processGjmj 古籍名句查询
|
||
func (s *ToolboxService) processGjmj(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("gjmj/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求古籍名句接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("古籍名句接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析古籍名句数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"source": result["source"],
|
||
"content": result["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processCnMoney 金额转大写
|
||
func (s *ToolboxService) processCnMoney(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 金额(必填)
|
||
money, ok := params["money"].(string)
|
||
if !ok || money == "" {
|
||
return nil, xerr.NewErrMsg("金额转大写缺少必填参数:money")
|
||
}
|
||
reqParams["money"] = money
|
||
|
||
// 单位类型(可选)
|
||
if typ, ok := params["type"].(string); ok && typ != "" {
|
||
reqParams["type"] = typ
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("cnmoney/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求金额转大写接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("金额转大写接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析金额转大写数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"cnresult": result["cnresult"],
|
||
"enresult": result["enresult"],
|
||
"fnresult": result["fnresult"],
|
||
}, nil
|
||
}
|
||
|
||
// processLzmy 励志古言查询
|
||
func (s *ToolboxService) processLzmy(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("lzmy/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求励志古言接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("励志古言接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析励志古言数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"saying": result["saying"],
|
||
"source": result["source"],
|
||
"transl": result["transl"],
|
||
}, nil
|
||
}
|
||
|
||
// processBaiKeTiKu 百科题库查询
|
||
func (s *ToolboxService) processBaiKeTiKu(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("baiketiku/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求百科题库接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("百科题库接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析百科题库数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"title": result["title"],
|
||
"answer": result["answer"],
|
||
"answerA": result["answerA"],
|
||
"answerB": result["answerB"],
|
||
"answerC": result["answerC"],
|
||
"answerD": result["answerD"],
|
||
"analytic": result["analytic"],
|
||
}, nil
|
||
}
|
||
|
||
// processDialogue 经典台词查询
|
||
func (s *ToolboxService) processDialogue(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("dialogue/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求经典台词接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("经典台词接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析经典台词数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"type": result["type"],
|
||
"source": result["source"],
|
||
"english": result["english"],
|
||
"dialogue": result["dialogue"],
|
||
}, nil
|
||
}
|
||
|
||
// processTianGou 舔狗日记查询
|
||
func (s *ToolboxService) processTianGou(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("tiangou/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求舔狗日记接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("舔狗日记接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析舔狗日记数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"content": result["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processRobotLog 机器人日志查询
|
||
func (s *ToolboxService) processRobotLog(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 返回数量(可选)
|
||
if num, ok := params["num"].(float64); ok && num > 0 && num <= 50 {
|
||
reqParams["num"] = int(num)
|
||
}
|
||
|
||
// 翻页(可选)
|
||
if page, ok := params["page"].(float64); ok && page > 0 {
|
||
reqParams["page"] = int(page)
|
||
}
|
||
|
||
// 用户唯一身份ID(可选)
|
||
if uniqueID, ok := params["uniqueid"].(string); ok && uniqueID != "" {
|
||
reqParams["uniqueid"] = uniqueID
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("robotlog/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求机器人日志接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("机器人日志接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析机器人日志数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("机器人日志列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if v, ok := raw["time"]; ok {
|
||
clean["time"] = v
|
||
}
|
||
if v, ok := raw["content"]; ok {
|
||
clean["content"] = v
|
||
}
|
||
if v, ok := raw["datatype"]; ok {
|
||
clean["datatype"] = v
|
||
}
|
||
if v, ok := raw["uniqueid"]; ok {
|
||
clean["uniqueid"] = v
|
||
}
|
||
if v, ok := raw["inputword"]; ok {
|
||
clean["inputword"] = v
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processAqi 空气质量指数查询
|
||
func (s *ToolboxService) processAqi(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 地区名称(必填)
|
||
city, ok := params["city"].(string)
|
||
logx.Infof("city 值: %v, 类型: %T, ok: %v", city, params["city"], ok)
|
||
if !ok || city == "" {
|
||
return nil, xerr.NewErrMsg("空气质量指数查询缺少必填参数:area")
|
||
}
|
||
reqParams["area"] = city
|
||
|
||
logx.Infof("调用天行API: area=%s", city)
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("aqi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求空气质量指数接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("空气质量指数接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析空气质量指数数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"area": result["area"],
|
||
"area_code": result["area_code"],
|
||
"time": result["time"],
|
||
"aqi": result["aqi"],
|
||
"num": result["num"],
|
||
"quality": result["quality"],
|
||
"primary_pollutant": result["primary_pollutant"],
|
||
"co": result["co"],
|
||
"o3": result["o3"],
|
||
"o3_8h": result["o3_8h"],
|
||
"no2": result["no2"],
|
||
"so2": result["so2"],
|
||
"pm10": result["pm10"],
|
||
"pm2_5": result["pm2_5"],
|
||
}, nil
|
||
}
|
||
|
||
// processAddressParse 物流地址解析
|
||
func (s *ToolboxService) processAddressParse(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 待解析文本(必填)
|
||
address, ok := params["address"].(string)
|
||
if !ok || address == "" {
|
||
return nil, xerr.NewErrMsg("物流地址解析缺少必填参数:address")
|
||
}
|
||
reqParams["text"] = address
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("addressparse/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求物流地址解析接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("物流地址解析接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析物流地址解析数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"province": result["province"],
|
||
"city": result["city"],
|
||
"district": result["district"],
|
||
"detail": result["detail"],
|
||
"name": result["name"],
|
||
"mobile": result["mobile"],
|
||
"postcode": result["postcode"],
|
||
}, nil
|
||
}
|
||
|
||
// processPet 宠物大全查询
|
||
func (s *ToolboxService) processPet(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 每页返回数量(默认10,前端可选)
|
||
num := 10
|
||
if v, ok := params["num"].(float64); ok && v > 0 {
|
||
num = int(v)
|
||
}
|
||
reqParams["num"] = num
|
||
|
||
// 翻页(默认1,前端可选)
|
||
page := 1
|
||
if v, ok := params["page"].(float64); ok && v > 0 {
|
||
page = int(v)
|
||
}
|
||
reqParams["page"] = page
|
||
|
||
// 宠物名称(可选,用于搜索)
|
||
if name, ok := params["name"].(string); ok && name != "" {
|
||
reqParams["name"] = name
|
||
}
|
||
|
||
// 宠物类型(可选):0猫科、1犬类、2爬行类、3小宠物类、4水族类
|
||
if typ, ok := params["type"].(float64); ok && typ >= 0 && typ <= 4 {
|
||
reqParams["type"] = int(typ)
|
||
}
|
||
|
||
// 调用天行 API
|
||
resp, err := s.tianxingjuheClient.Get("pet/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求宠物大全接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("宠物大全接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析宠物大全数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("宠物大全列表数据异常")
|
||
}
|
||
|
||
// 字段白名单
|
||
allowed := map[string]bool{
|
||
"name": true,
|
||
"engName": true,
|
||
"pettype": true,
|
||
"nation": true,
|
||
"life": true,
|
||
"price": true,
|
||
"characters": true,
|
||
"feature": true,
|
||
"characterFeature": true,
|
||
"feedPoints": true,
|
||
"careKnowledge": true,
|
||
"easyOfDisease": true,
|
||
"coverURL": true,
|
||
"desc": true,
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
for k, v := range raw {
|
||
if allowed[k] {
|
||
clean[k] = v
|
||
}
|
||
}
|
||
|
||
// 至少要有宠物名称
|
||
if clean["name"] != nil {
|
||
list = append(list, clean)
|
||
}
|
||
}
|
||
|
||
if len(list) == 0 {
|
||
return nil, xerr.NewErrMsg("未查询到相关宠物信息")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processHotReview 云音乐热评查询
|
||
func (s *ToolboxService) processHotReview(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("hotreview/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求云音乐热评接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("云音乐热评接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析云音乐热评数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"source": result["source"],
|
||
"content": result["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processAnsLaJiFenLei 垃圾分类问答查询
|
||
func (s *ToolboxService) processAnsLaJiFenLei(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("anslajifenlei/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求垃圾分类问答接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("垃圾分类问答接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析垃圾分类问答数据失败")
|
||
}
|
||
|
||
typeMap := map[int]string{
|
||
0: "可回收物",
|
||
1: "有害垃圾",
|
||
2: "厨余垃圾",
|
||
3: "其他垃圾",
|
||
}
|
||
|
||
clean := map[string]interface{}{
|
||
"name": result["name"],
|
||
"type": result["type"],
|
||
"explain": result["explain"],
|
||
}
|
||
if t, ok := result["type"].(float64); ok {
|
||
if name, exists := typeMap[int(t)]; exists {
|
||
clean["type_name"] = name
|
||
}
|
||
}
|
||
|
||
return clean, nil
|
||
}
|
||
|
||
// processDouYinHot 抖音热搜榜查询
|
||
func (s *ToolboxService) processDouYinHot(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 该接口无需额外参数,仅需 key
|
||
resp, err := s.tianxingjuheClient.Get("douyinhot/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求抖音热搜榜接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("抖音热搜榜接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
// 解析 result
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析抖音热搜榜数据失败")
|
||
}
|
||
|
||
// 解析 list
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("抖音热搜榜列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
clean := map[string]interface{}{}
|
||
if v, ok := raw["word"]; ok {
|
||
clean["word"] = v
|
||
}
|
||
if v, ok := raw["label"]; ok {
|
||
clean["label"] = v
|
||
}
|
||
if v, ok := raw["hotindex"]; ok {
|
||
clean["hotindex"] = v
|
||
}
|
||
if v, ok := raw["label"]; ok {
|
||
// 转换label为可读文本
|
||
labelMap := map[int]string{
|
||
0: "普通",
|
||
1: "新",
|
||
2: "荐",
|
||
3: "热",
|
||
}
|
||
if labelInt, ok := v.(float64); ok {
|
||
clean["label_text"] = labelMap[int(labelInt)]
|
||
}
|
||
}
|
||
|
||
list = append(list, clean)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processZaoAnWords 获取早安心语
|
||
func (s *ToolboxService) processZaoAnWords(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 该接口无需额外业务参数,仅自带key
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 请求早安心语接口
|
||
resp, err := s.tianxingjuheClient.Get("zaoan/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求早安心语接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("早安心语接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析早安心语数据失败")
|
||
}
|
||
|
||
content, _ := result["content"].(string)
|
||
|
||
return map[string]interface{}{
|
||
"content": content,
|
||
}, nil
|
||
}
|
||
|
||
// processWanAnWords 获取晚安心语
|
||
func (s *ToolboxService) processWanAnWords(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 该接口无业务参数,仅自带 key
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 请求晚安心语接口
|
||
resp, err := s.tianxingjuheClient.Get("wanan/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求晚安心语接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("晚安心语接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析晚安心语数据失败")
|
||
}
|
||
|
||
content, _ := result["content"].(string)
|
||
|
||
return map[string]interface{}{
|
||
"content": content,
|
||
}, nil
|
||
}
|
||
|
||
// processAreaData 全国五级行政区划查询
|
||
func (s *ToolboxService) processAreaData(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 逐级行政区ID参数
|
||
if v, ok := params["province"].(string); ok && v != "" {
|
||
reqParams["province"] = v
|
||
}
|
||
if v, ok := params["city"].(string); ok && v != "" {
|
||
reqParams["city"] = v
|
||
}
|
||
if v, ok := params["county"].(string); ok && v != "" {
|
||
reqParams["county"] = v
|
||
}
|
||
if v, ok := params["town"].(string); ok && v != "" {
|
||
reqParams["town"] = v
|
||
}
|
||
if v, ok := params["village"].(string); ok && v != "" {
|
||
reqParams["village"] = v
|
||
}
|
||
|
||
// 请求行政区划接口
|
||
resp, err := s.tianxingjuheClient.Get("area/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求行政区划接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("行政区划接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析行政区划数据失败")
|
||
}
|
||
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("行政区划列表数据异常")
|
||
}
|
||
|
||
list := make([]map[string]interface{}, 0, len(rawList))
|
||
for _, item := range rawList {
|
||
raw, ok := item.(map[string]interface{})
|
||
if !ok {
|
||
continue
|
||
}
|
||
info := map[string]interface{}{
|
||
"provinceid": raw["provinceid"],
|
||
"provincename": raw["provincename"],
|
||
"cityid": raw["cityid"],
|
||
"cityname": raw["cityname"],
|
||
"countyid": raw["countyid"],
|
||
"countyname": raw["countyname"],
|
||
"townid": raw["townid"],
|
||
"townname": raw["townname"],
|
||
"villageid": raw["villageid"],
|
||
"villagename": raw["villagename"],
|
||
}
|
||
list = append(list, info)
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(list),
|
||
"list": list,
|
||
}, nil
|
||
}
|
||
|
||
// processMgJuZi 获取民国句子
|
||
func (s *ToolboxService) processMgJuZi(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 请求民国句子接口
|
||
resp, err := s.tianxingjuheClient.Get("mgjuzi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求民国句子接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("民国句子接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析民国句子数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"author": result["author"],
|
||
"content": result["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processSongCi 精选宋词查询
|
||
func (s *ToolboxService) processSongCi(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{
|
||
"num": 1,
|
||
"page": 1,
|
||
}
|
||
|
||
// 数量 1-10
|
||
if num, ok := params["num"].(int); ok && num >= 1 && num <= 10 {
|
||
reqParams["num"] = num
|
||
}
|
||
// 页码
|
||
if page, ok := params["page"].(int); ok && page > 0 {
|
||
reqParams["page"] = page
|
||
}
|
||
// 搜索关键词
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
resp, err := s.tianxingjuheClient.Get("songci/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求宋词接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("宋词接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析宋词数据失败")
|
||
}
|
||
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("宋词列表数据异常")
|
||
}
|
||
|
||
var songList []map[string]interface{}
|
||
for _, item := range rawList {
|
||
d, _ := item.(map[string]interface{})
|
||
songList = append(songList, map[string]interface{}{
|
||
"title": d["title"],
|
||
"author": d["author"],
|
||
"content": d["content"],
|
||
"translate": d["yiwen"],
|
||
"tags": d["tags"],
|
||
})
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(songList),
|
||
"list": songList,
|
||
}, nil
|
||
}
|
||
|
||
// processStory 故事大全查询
|
||
func (s *ToolboxService) processStory(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{
|
||
"num": 5,
|
||
"page": 1,
|
||
"type": 4,
|
||
}
|
||
|
||
// 故事类型 1成语 2睡前 3童话 4寓言
|
||
if t, ok := params["type"].(int); ok {
|
||
reqParams["type"] = t
|
||
}
|
||
// 数量
|
||
if num, ok := params["num"].(int); ok && num > 0 {
|
||
reqParams["num"] = num
|
||
}
|
||
// 页码
|
||
if page, ok := params["page"].(int); ok && page > 0 {
|
||
reqParams["page"] = page
|
||
}
|
||
// 搜索关键词
|
||
if word, ok := params["word"].(string); ok && word != "" {
|
||
reqParams["word"] = word
|
||
}
|
||
|
||
resp, err := s.tianxingjuheClient.Get("story/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求故事大全接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("故事大全接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析故事数据失败")
|
||
}
|
||
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("故事列表数据异常")
|
||
}
|
||
|
||
var storyList []map[string]interface{}
|
||
for _, item := range rawList {
|
||
d, _ := item.(map[string]interface{})
|
||
storyList = append(storyList, map[string]interface{}{
|
||
"title": d["title"],
|
||
"content": d["content"],
|
||
"storyType": d["storytype"],
|
||
})
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(storyList),
|
||
"list": storyList,
|
||
}, nil
|
||
}
|
||
|
||
// processHotLaJiFenLei 热搜垃圾分类查询
|
||
func (s *ToolboxService) processHotLaJiFenLei(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
// 查询日期
|
||
if date, ok := params["date"].(string); ok && date != "" {
|
||
reqParams["date"] = date
|
||
}
|
||
// 垃圾类型
|
||
if typ, ok := params["type"].(int); ok {
|
||
reqParams["type"] = typ
|
||
}
|
||
|
||
resp, err := s.tianxingjuheClient.Get("hotlajifenlei/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求热搜垃圾分类接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("热搜垃圾分类接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析垃圾分类数据失败")
|
||
}
|
||
|
||
rawList, ok := result["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("垃圾分类列表数据异常")
|
||
}
|
||
|
||
var garbageList []map[string]interface{}
|
||
for _, item := range rawList {
|
||
info, _ := item.(map[string]interface{})
|
||
garbageList = append(garbageList, map[string]interface{}{
|
||
"garbageName": info["name"],
|
||
"garbageType": info["type"],
|
||
"hotIndex": info["index"],
|
||
})
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"count": len(garbageList),
|
||
"list": garbageList,
|
||
}, nil
|
||
}
|
||
|
||
// processQingShi 获取古代情诗
|
||
func (s *ToolboxService) processQingShi(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
reqParams := map[string]interface{}{}
|
||
|
||
resp, err := s.tianxingjuheClient.Get("qingshi/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求古代情诗接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("古代情诗接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析古代情诗数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"author": result["author"],
|
||
"source": result["source"],
|
||
"content": result["content"],
|
||
}, nil
|
||
}
|
||
|
||
// processChengyuJieLong 成语接龙
|
||
func (s *ToolboxService) processChengyuJieLong(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
// 必填参数
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("缺少必填参数:word(成语)")
|
||
}
|
||
userid, ok := params["userid"].(string)
|
||
if !ok || userid == "" {
|
||
return nil, xerr.NewErrMsg("缺少必填参数:userid(用户唯一标识)")
|
||
}
|
||
|
||
reqParams := map[string]interface{}{
|
||
"word": word,
|
||
"userid": userid,
|
||
}
|
||
|
||
// 可选:状态维持时间(秒)
|
||
if statetime, ok := params["statetime"].(int); ok && statetime > 0 {
|
||
reqParams["statetime"] = statetime
|
||
}
|
||
|
||
// 调用天聚数行接口
|
||
resp, err := s.tianxingjuheClient.Get("chengyujielong/index", reqParams)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求成语接龙接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("成语接龙接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析成语接龙数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"tip": result["tip"],
|
||
"grade": result["grade"],
|
||
"chengyu": result["chengyu"],
|
||
"pinyin": result["pinyin"],
|
||
"jieshi": result["jieshi"],
|
||
"chuchu": result["chuchu"],
|
||
"startstr": result["startstr"],
|
||
"endstr": result["endstr"],
|
||
"result": result["result"], // 0=开局,1=胜,2-4=负,5=赢局
|
||
}, nil
|
||
}
|
||
|
||
// processLaJiFenLei 垃圾分类查询
|
||
func (s *ToolboxService) processLaJiFenLei(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
// 必传垃圾名称
|
||
word, ok := params["word"].(string)
|
||
if !ok || word == "" {
|
||
return nil, xerr.NewErrMsg("请传入要查询的垃圾名称word")
|
||
}
|
||
|
||
req := map[string]interface{}{
|
||
"word": word,
|
||
"num": 10,
|
||
"mode": 0,
|
||
"page": 1,
|
||
}
|
||
|
||
// 可选参数赋值
|
||
if num, v := params["num"].(int); v && num > 0 {
|
||
req["num"] = num
|
||
}
|
||
if mode, v := params["mode"].(int); v {
|
||
req["mode"] = mode
|
||
}
|
||
if page, v := params["page"].(int); v && page > 0 {
|
||
req["page"] = page
|
||
}
|
||
|
||
resp, err := s.tianxingjuheClient.Get("lajifenlei/index", req)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("垃圾分类接口请求失败:%v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("垃圾分类接口异常:%s", resp.Msg))
|
||
}
|
||
|
||
resData, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("垃圾分类数据解析失败")
|
||
}
|
||
|
||
listArr, ok := resData["list"].([]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("无垃圾分类结果数据")
|
||
}
|
||
|
||
var resList []map[string]interface{}
|
||
typeMap := map[int]string{
|
||
0: "可回收垃圾",
|
||
1: "有害垃圾",
|
||
2: "厨余(湿)垃圾",
|
||
3: "其他(干)垃圾",
|
||
}
|
||
|
||
for _, item := range listArr {
|
||
itemMap, _ := item.(map[string]interface{})
|
||
tp, _ := itemMap["type"].(int)
|
||
resList = append(resList, map[string]interface{}{
|
||
"garbageName": itemMap["name"],
|
||
"typeCode": tp,
|
||
"typeName": typeMap[tp],
|
||
"explain": itemMap["explain"],
|
||
"contain": itemMap["contain"],
|
||
"tip": itemMap["tip"],
|
||
"isPreJudge": itemMap["aipre"],
|
||
})
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"total": len(resList),
|
||
"list": resList,
|
||
}, nil
|
||
}
|
||
|
||
// processHanZiPinYin 汉字转拼音
|
||
func (s *ToolboxService) processHanZiPinYin(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
text, ok := params["text"].(string)
|
||
if !ok || text == "" {
|
||
return nil, xerr.NewErrMsg("请传入需要转换的汉字文本text")
|
||
}
|
||
|
||
req := map[string]interface{}{
|
||
"text": text,
|
||
"type": 0,
|
||
}
|
||
if typ, ok := params["type"].(int); ok {
|
||
req["type"] = typ
|
||
}
|
||
|
||
resp, err := s.tianxingjuheClient.Get("pinyin/index", req)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("汉字转拼音请求失败:%v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("接口异常:%s", resp.Msg))
|
||
}
|
||
|
||
res, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析拼音数据失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"fullPinyin": res["pinyin"],
|
||
"shortPinyin": res["jianxie"],
|
||
}, nil
|
||
}
|
||
|
||
// processShortHistory 简说历史
|
||
func (s *ToolboxService) processShortHistory(
|
||
ctx context.Context,
|
||
params map[string]interface{},
|
||
) (map[string]interface{}, error) {
|
||
|
||
resp, err := s.tianxingjuheClient.Get("pitlishi/index", nil)
|
||
if err != nil {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("请求简说历史接口失败: %v", err))
|
||
}
|
||
if resp.Code != 200 {
|
||
return nil, xerr.NewErrMsg(fmt.Sprintf("简说历史接口异常: %s", resp.Msg))
|
||
}
|
||
|
||
result, ok := resp.Result.(map[string]interface{})
|
||
if !ok {
|
||
return nil, xerr.NewErrMsg("解析历史内容失败")
|
||
}
|
||
|
||
return map[string]interface{}{
|
||
"historyInfo": result["content"],
|
||
}, nil
|
||
}
|
||
|
||
// ==================== 工具列表 ====================
|
||
|
||
// ToolInfo 工具信息
|
||
type ToolInfo struct {
|
||
Key string `json:"key"`
|
||
Name string `json:"name"`
|
||
Desc string `json:"desc"`
|
||
}
|
||
|
||
// ListTools 返回所有可用工具列表
|
||
func (s *ToolboxService) ListTools() []ToolInfo {
|
||
return []ToolInfo{
|
||
{Key: "ip-location", Name: "IP地址查询", Desc: "查询IP地址归属地、运营商等信息"},
|
||
{Key: "idcard-info", Name: "身份证归属地", Desc: "查询身份证归属地、性别、出生日期等信息"},
|
||
{Key: "phone-location", Name: "手机号归属地", Desc: "查询手机号码归属地、运营商等信息"},
|
||
{Key: "beijing-time", Name: "北京时间查询", Desc: "获取当前北京时间"},
|
||
{Key: "bank-card", Name: "银行卡识别", Desc: "识别银行卡发卡行与卡种"},
|
||
{Key: "plate-parse", Name: "车牌号解析", Desc: "解析车牌类型与归属地"},
|
||
{Key: "money-to-chinese", Name: "金额大写转换", Desc: "阿拉伯数字转中文大写金额"},
|
||
{Key: "password-strength", Name: "密码强度检测", Desc: "检测密码安全性并给出建议"},
|
||
{Key: "days-between-dates", Name: "日期间隔计算", Desc: "计算两个日期相差的天数"},
|
||
{Key: "file-size-format", Name: "文件大小格式化", Desc: "支持各种文件单位之间的相互转换"},
|
||
{Key: "text-stats", Name: "文本字数统计", Desc: "统计字符数、单词数、行数"},
|
||
{Key: "history-today", Name: "历史今天查询", Desc: "查询历史上指定日期的重要事件"},
|
||
{Key: "ten-why", Name: "十万个为什么", Desc: "百科类问答查询,支持分类检索和关键词搜索"},
|
||
{Key: "jf-words", Name: "近义词反义词", Desc: "查询词语的近义词和反义词,适合批量替换场景"},
|
||
{Key: "duilian", Name: "经典对联查询", Desc: "随机获取一句经典中华文化对联句子"},
|
||
{Key: "gjdm", Name: "古今地名查询", Desc: "查询古代地名对应的现代城市及沿革变迁说明"},
|
||
{Key: "bcgm", Name: "本草纲目查询", Desc: "按药材名模糊查询《本草纲目》原文及功效主治"},
|
||
{Key: "idiom-quiz", Name: "成语填字", Desc: "获取成语填空题目、答案、干扰项及成语解释"},
|
||
{Key: "poem-fill", Name: "诗词填空", Desc: "获取古诗词填空题目、作者、答案及干扰项"},
|
||
{Key: "fairytales", Name: "童话故事", Desc: "根据ID查询经典童话故事全文内容"},
|
||
{Key: "caihongpi", Name: "彩虹屁", Desc: "随机生成一条夸张走心的夸人语录"},
|
||
{Key: "joke", Name: "趣味笑话", Desc: "随机返回一条轻松幽默的笑话段子"},
|
||
{Key: "pinyin", Name: "汉字转拼音", Desc: "将中文汉字转换为带声调的标准拼音"},
|
||
{Key: "everyday", Name: "每日英语", Desc: "随机返回一句经典英文句子+中文释义+出处"},
|
||
{Key: "decide", Name: "常识判断题", Desc: "随机返回生活常识判断题,含答案与解析"},
|
||
{Key: "woman", Name: "女性新闻", Desc: "聚合女性关注的职场、健康、时尚新闻资讯"},
|
||
{Key: "pyqwenan", Name: "朋友圈文案", Desc: "随机返回适合发朋友圈的走心短句"},
|
||
{Key: "healthskill", Name: "健康小妙招", Desc: "提供饮食、睡眠、运动、减压等养生建议"},
|
||
{Key: "jtwfcode", Name: "违章代码查询", Desc: "查询交通违法代码对应的扣分、罚款、违法行为"},
|
||
{Key: "areanews", Name: "地区新闻", Desc: "全国各省市地方新闻,支持按地区筛选检索"},
|
||
{Key: "yuanqu", Name: "元曲三百首", Desc: "随机返回元曲名句,含作者、曲牌、注释、译文"},
|
||
{Key: "bmi", Name: "BMI标准体重", Desc: "根据身高体重计算BMI指数、健康评分、标准体重"},
|
||
{Key: "zhongyao", Name: "中药大全", Desc: "查询中草药别名、性味、功效、用法用量等信息"},
|
||
{Key: "yaopin", Name: "药品说明书", Desc: "查询中西药说明书、适应症、禁忌、用法用量"},
|
||
{Key: "slogan", Name: "猜广告语", Desc: "随机返回广告语,含谜面与品牌答案"},
|
||
{Key: "zimi", Name: "猜字谜", Desc: "随机返回传统字谜,附谜底与解析"},
|
||
{Key: "dujitang", Name: "毒鸡汤", Desc: "随机返回扎心毒鸡汤语录,清醒又真实"},
|
||
{Key: "one", Name: "ONE一个", Desc: "每日同步一句精美短句,支持指定日期与随机"},
|
||
{Key: "proverb", Name: "文化谚语", Desc: "随机返回中国传统谚语,富含生活哲理智慧"},
|
||
{Key: "caichengyu", Name: "猜成语", Desc: "根据提示猜成语,返回谜底、拼音、出处、释义"},
|
||
{Key: "qiaomen", Name: "生活小窍门", Desc: "提供清洁、收纳、烹饪、省电等实用生活技巧"},
|
||
{Key: "riddle", Name: "谜语大全", Desc: "随机返回传统谜语,含谜面、谜底及解释"},
|
||
// ─── 新增天行SDK工具 ───
|
||
{Key: "jixiong", Name: "吉凶测试", Desc: "输入数字测试吉凶寓意"},
|
||
{Key: "surname", Name: "姓氏起源", Desc: "查询百家姓起源、郡望、堂号等信息"},
|
||
{Key: "healthtip", Name: "健康小贴士", Desc: "随机返回一条实用健康养生小贴士"},
|
||
{Key: "nutrient", Name: "营养素查询", Desc: "查询食物营养成分、功效与推荐摄入量"},
|
||
{Key: "fxrate", Name: "汇率查询", Desc: "查询主要货币对的实时汇率"},
|
||
{Key: "bulletin", Name: "新闻简报", Desc: "获取最新热门新闻简报摘要"},
|
||
{Key: "caizimi", Name: "彩字谜", Desc: "随机返回彩字谜题目"},
|
||
{Key: "hotlajifenlei", Name: "热搜垃圾分类", Desc: "获取热搜垃圾分类榜单"},
|
||
{Key: "oilprice", Name: "实时油价", Desc: "查询全国各地最新油价"},
|
||
{Key: "chengyujielong", Name: "成语接龙", Desc: "输入成语进行接龙游戏"},
|
||
{Key: "weibohot", Name: "微博热搜", Desc: "获取微博实时热搜榜单"},
|
||
{Key: "domain", Name: "域名解析", Desc: "查询域名Whois信息与解析记录"},
|
||
{Key: "scenic", Name: "景点查询", Desc: "查询全国各地旅游景点信息"},
|
||
{Key: "mingyan", Name: "名言警句", Desc: "随机返回古今中外经典名言"},
|
||
{Key: "tianqishiju", Name: "天气诗句", Desc: "根据天气返回对应古诗词名句"},
|
||
{Key: "jieqi", Name: "节气查询", Desc: "查询二十四节气详情与习俗"},
|
||
{Key: "blood", Name: "血型配对", Desc: "查询血型之间的性格配对分析"},
|
||
{Key: "zodiac", Name: "生肖配对", Desc: "查询十二生肖之间的配对分析"},
|
||
{Key: "saylove", Name: "情话大全", Desc: "随机返回一句浪漫甜蜜情话"},
|
||
{Key: "star", Name: "星座查询", Desc: "查询十二星座详细信息"},
|
||
{Key: "nethot", Name: "网络热搜", Desc: "获取全网实时热搜排行榜"},
|
||
{Key: "ensentence", Name: "英文句子", Desc: "随机返回经典英文句子"},
|
||
{Key: "verse", Name: "诗词名句", Desc: "随机返回经典诗词名句"},
|
||
{Key: "poetry", Name: "古诗词", Desc: "按条件搜索古诗词"},
|
||
{Key: "poetries", Name: "古诗词集", Desc: "获取古诗词集合数据"},
|
||
{Key: "pitlishi", Name: "谐音历史", Desc: "查询谐音梗相关的历史知识"},
|
||
{Key: "mnpara", Name: "美文段落", Desc: "随机返回经典美文段落"},
|
||
{Key: "skl", Name: "十苦乐", Desc: "随机返回十苦乐相关内容"},
|
||
{Key: "sentence", Name: "唯美句子", Desc: "随机返回唯美文艺短句"},
|
||
{Key: "enwords", Name: "英语单词", Desc: "查询英语单词释义与用法"},
|
||
{Key: "lexicon", Name: "词典查询", Desc: "查询词语释义、近义词、反义词"},
|
||
{Key: "lunar", Name: "农历查询", Desc: "查询中国老黄历信息"},
|
||
{Key: "xingzuo", Name: "星座配对", Desc: "查询两个星座的配对指数"},
|
||
{Key: "godreply", Name: "神回复", Desc: "随机返回搞笑神回复段子"},
|
||
{Key: "xiehou", Name: "歇后语", Desc: "随机返回经典歇后语"},
|
||
{Key: "rkl", Name: "绕口令", Desc: "随机返回经典绕口令"},
|
||
{Key: "cname", Name: "起名大全", Desc: "根据姓氏推荐好听的名字"},
|
||
{Key: "shares", Name: "股票查询", Desc: "查询股票实时行情数据"},
|
||
{Key: "hotword", Name: "热词", Desc: "获取最新网络热词与解释"},
|
||
{Key: "cityriddle", Name: "城市谜语", Desc: "猜城市名称趣味谜语"},
|
||
{Key: "wenda", Name: "知识问答", Desc: "随机返回趣味知识问答"},
|
||
{Key: "chengyu", Name: "成语词典", Desc: "查询成语释义、出处、造句"},
|
||
{Key: "naowan", Name: "脑筋急转弯", Desc: "随机返回脑筋急转弯题目"},
|
||
{Key: "dob", Name: "生日书", Desc: "根据生日查询性格与命运分析"},
|
||
{Key: "dictum", Name: "格言", Desc: "随机返回经典格言警句"},
|
||
{Key: "dream", Name: "周公解梦", Desc: "查询梦境解析与寓意"},
|
||
{Key: "caipu", Name: "菜谱大全", Desc: "查询菜谱做法与食材信息"},
|
||
{Key: "wxnew", Name: "微信精选", Desc: "获取微信热门文章精选"},
|
||
{Key: "constellation", Name: "星座运势", Desc: "查询十二星座今日/明日/本周/月度运势"},
|
||
{Key: "fanyi", Name: "在线翻译", Desc: "支持多语种互译,自动识别源语言"},
|
||
{Key: "holiday", Name: "节假日查询", Desc: "查询指定年份公历、农历、节假日信息"},
|
||
{Key: "garbage", Name: "垃圾分类查询", Desc: "输入垃圾名称查询分类及投放说明"},
|
||
{Key: "zone", Name: "地区搜索查询", Desc: "查询省市区三级行政区划代码及名称"},
|
||
// ─── 第二批新增工具 ───
|
||
{Key: "timezone", Name: "时区查询", Desc: "查询全球各时区的当前时间"},
|
||
{Key: "duoyinzi", Name: "多音字查询", Desc: "查询汉字的多音字及不同读音"},
|
||
{Key: "dailytel", Name: "全国常用电话", Desc: "汇总政府机关、银行、电商、快递、学校等全国常用机构对外联系电话。"},
|
||
{Key: "obdcode", Name: "OBD故障码", Desc: "查询汽车OBD故障码含义及解决方案"},
|
||
{Key: "chaizi", Name: "汉字拆解", Desc: "查询汉字的拆字结构及含义"},
|
||
{Key: "huayu", Name: "华语句子", Desc: "随机返回优美华语句子"},
|
||
{Key: "moodpoetry", Name: "心情诗词", Desc: "根据心情推荐古诗词"},
|
||
{Key: "pcterm", Name: "电脑术语", Desc: "查询电脑相关术语解释"},
|
||
{Key: "targa", Name: "塔罗牌", Desc: "塔罗牌占卜解读"},
|
||
{Key: "duishici", Name: "对诗词", Desc: "诗词对仗游戏"},
|
||
{Key: "msdl", Name: "民乐歌词", Desc: "中国传统民乐歌词查询"},
|
||
{Key: "shijing", Name: "诗经", Desc: "《诗经》原文及释义"},
|
||
{Key: "chepai", Name: "车牌查询", Desc: "查询车牌归属地及限行信息"},
|
||
{Key: "flmj", Name: "法律名句", Desc: "法律法规经典名言"},
|
||
{Key: "xhzd", Name: "新华字典", Desc: "汉字部首、笔画、释义查询"},
|
||
{Key: "telecode", Name: "电话区号", Desc: "查询国内外电话区号"},
|
||
{Key: "charconvert", Name: "字符转换", Desc: "各种字符编码格式转换"},
|
||
{Key: "checkipv6", Name: "IPv6检测", Desc: "检测IPv6地址格式及归属"},
|
||
{Key: "worldtime", Name: "世界时间", Desc: "查询全球主要城市当前时间"},
|
||
{Key: "wxhottopic", Name: "微信热点", Desc: "获取微信实时热点话题"},
|
||
{Key: "zmsc", Name: "字明说", Desc: "汉字谐音趣味解读"},
|
||
{Key: "hsjz", Name: "失恋分手句子", Desc: "随机返回失恋分手相关的经典句子"},
|
||
{Key: "gjmj", Name: "国际民调", Desc: "国际民调数据查询"},
|
||
{Key: "lzmy", Name: "励志名言", Desc: "励志名言警句"},
|
||
{Key: "baiketiku", Name: "百科题库", Desc: "百科知识问答题库"},
|
||
{Key: "dialogue", Name: "对话生成", Desc: "智能对话内容生成"},
|
||
{Key: "tiangou", Name: "舔狗日记", Desc: "搞笑舔狗日记"},
|
||
{Key: "robotlog", Name: "机器人日志", Desc: "机器人运行日志查询"},
|
||
{Key: "aqi", Name: "空气质量", Desc: "查询城市空气质量指数"},
|
||
{Key: "addressparse", Name: "地址解析", Desc: "智能地址格式化与解析"},
|
||
{Key: "pet", Name: "宠物百科", Desc: "宠物饲养知识大全"},
|
||
{Key: "hotreview", Name: "热点评论", Desc: "热点事件网友评论"},
|
||
{Key: "anslajifenlei", Name: "按师垃圾分类", Desc: "按垃圾分类指南"},
|
||
{Key: "douyinhot", Name: "抖音热搜", Desc: "获取抖音实时热搜榜单"},
|
||
{Key: "zaowanwords", Name: "早安晚安语", Desc: "适合发朋友圈的早安晚安文案"},
|
||
{Key: "wananwords", Name: "晚安语", Desc: "温馨晚安问候语"},
|
||
{Key: "areadata", Name: "地区数据", Desc: "各地区统计数据分析"},
|
||
{Key: "mgjuzi", Name: "美工句子", Desc: "美工设计灵感句子"},
|
||
{Key: "songci", Name: "宋词", Desc: "宋词原文及赏析"},
|
||
{Key: "story", Name: "故事大全", Desc: "各类故事集锦"},
|
||
{Key: "qingshi", Name: "情诗", Desc: "经典情诗词句"},
|
||
{Key: "lajifenlei", Name: "垃圾分类", Desc: "垃圾分类查询指南"},
|
||
{Key: "hanzipinyin", Name: "汉字拼音", Desc: "汉字拼音查询"},
|
||
{Key: "shorthistory", Name: "简明历史", Desc: "历史事件简明介绍"},
|
||
}
|
||
}
|
||
|
||
// SupportedKeys 返回所有支持的 toolKey(用于校验)
|
||
func (s *ToolboxService) SupportedKeys() map[string]bool {
|
||
keys := make(map[string]bool, len(s.processors))
|
||
for k := range s.processors {
|
||
keys[k] = true
|
||
}
|
||
return keys
|
||
}
|
||
|
||
// RegisterTool 动态注册工具(可选,方便扩展)
|
||
func (s *ToolboxService) RegisterTool(key string, processor ToolProcessor) error {
|
||
if _, exists := s.processors[key]; exists {
|
||
return fmt.Errorf("工具 %s 已存在", key)
|
||
}
|
||
s.processors[key] = processor
|
||
return nil
|
||
}
|
||
|
||
// stripHTMLTags 移除HTML标签,保留纯文本
|
||
func stripHTMLTags(html string) string {
|
||
// 移除所有HTML标签
|
||
re := regexp.MustCompile(`<[^>]*>`)
|
||
text := re.ReplaceAllString(html, "")
|
||
|
||
// 移除多余的空白字符
|
||
text = strings.TrimSpace(text)
|
||
text = regexp.MustCompile(`\s+`).ReplaceAllString(text, " ")
|
||
|
||
return text
|
||
}
|
||
|
||
// cleanHTMLContent 清理HTML内容,智能处理换行
|
||
func cleanHTMLContent(html string) string {
|
||
if html == "" {
|
||
return html
|
||
}
|
||
|
||
// 移除<script>标签及其内容(使用非贪婪匹配)
|
||
html = regexp.MustCompile(`(?s)<script[^>]*>.*?</script>`).ReplaceAllString(html, "")
|
||
|
||
// 移除<style>标签及其内容(使用非贪婪匹配)
|
||
html = regexp.MustCompile(`(?s)<style[^>]*>.*?</style>`).ReplaceAllString(html, "")
|
||
|
||
// 移除所有HTML标签
|
||
re := regexp.MustCompile(`<[^>]*>`)
|
||
text := re.ReplaceAllString(html, "")
|
||
|
||
// 替换HTML实体
|
||
entityMap := map[string]string{
|
||
"<": "<",
|
||
">": ">",
|
||
"&": "&",
|
||
""": "\"",
|
||
" ": " ",
|
||
"'": "'",
|
||
"”": "”",
|
||
"“": "“",
|
||
"…": "…",
|
||
}
|
||
for entity, char := range entityMap {
|
||
text = strings.ReplaceAll(text, entity, char)
|
||
}
|
||
|
||
// 规范化空白字符:将连续空白替换为单个空格
|
||
text = regexp.MustCompile(`\s+`).ReplaceAllString(text, " ")
|
||
|
||
// 清理首尾空白
|
||
text = strings.TrimSpace(text)
|
||
|
||
return text
|
||
}
|