feat: add Handou plugin (#1283)

This commit is contained in:
方柳煜
2026-02-08 15:07:03 +08:00
committed by GitHub
parent 9cb3a5019f
commit e5b70d7fe6
5 changed files with 1221 additions and 0 deletions

182
plugin/handou/baiAPI.go Normal file
View File

@@ -0,0 +1,182 @@
// Package handou 猜成语
package handou
import (
"encoding/json"
"errors"
"net/url"
"os"
"slices"
"strings"
"sync"
"github.com/FloatTech/floatbox/web"
"github.com/sirupsen/logrus"
)
type baiduAPIData struct {
Errno int `json:"errno"`
Errmsg string `json:"errmsg"`
Data struct {
IdiomVersion int `json:"idiomVersion"`
Name string `json:"name"`
Sid string `json:"sid"`
Type string `json:"type"`
LessonInfo any `json:"lessonInfo"`
RelationInfo struct {
RelationName string `json:"relationName"`
RelationList []struct {
Name string `json:"name"`
Imgs []string `json:"imgs"`
} `json:"relationList"`
} `json:"relationInfo"`
Imgs []string `json:"imgs"`
Definition []struct {
Pinyin string `json:"pinyin"`
Voice string `json:"voice"`
Definition []string `json:"definition"`
DetailDefinition any `json:"detailDefinition"`
} `json:"definition"`
DefinitionInfo struct {
Definition string `json:"definition"`
SimilarDefinition string `json:"similarDefinition"`
AncientDefinition string `json:"ancientDefinition"`
ModernDefinition string `json:"modernDefinition"`
DetailMeans []struct {
Word string `json:"word"`
Definition string `json:"definition"`
} `json:"detailMeans"`
UsageTips any `json:"usageTips"`
Yicuodian any `json:"yicuodian"`
Baobian string `json:"baobian"`
WordFormation string `json:"wordFormation"`
} `json:"definitionInfo"`
Liju []struct {
Name string `json:"name"`
ShowName string `json:"showName"`
} `json:"liju"`
Source string `json:"source"`
Story any `json:"story"`
Antonym []struct {
Name string `json:"name"`
IsClick bool `json:"isClick"`
} `json:"antonym"`
Synonym []string `json:"synonym"`
Synonyms []struct {
Name string `json:"name"`
IsClick bool `json:"isClick"`
} `json:"synonyms"`
Tongyiyixing []struct {
Name string `json:"name"`
IsClick bool `json:"isClick"`
} `json:"tongyiyixing"`
ChuChu []struct {
SourceChapter string `json:"sourceChapter"`
Source string `json:"source"`
Dynasty string `json:"dynasty"`
CiteOriginalText string `json:"citeOriginalText"`
Author string `json:"author"`
} `json:"chuChu"`
YinZheng []struct {
SourceChapter string `json:"sourceChapter"`
Source string `json:"source"`
Dynasty string `json:"dynasty"`
CiteOriginalText string `json:"citeOriginalText"`
Author string `json:"author"`
} `json:"yinZheng"`
PictureList []any `json:"pictureList"`
LessonTerms struct {
TermList any `json:"termList"`
HasTerms int `json:"hasTerms"`
} `json:"lessonTerms"`
LessonTermsNew struct {
TermList any `json:"termList"`
HasTerms int `json:"hasTerms"`
} `json:"lessonTermsNew"`
Baobian string `json:"baobian"`
Structure string `json:"structure"`
Pinyin string `json:"pinyin"`
Voice string `json:"voice"`
ZuowenQuery string `json:"zuowen_query"`
} `json:"data"`
}
func geiAPIdata(s string) (*idiomJSON, error) {
url := "https://hanyuapp.baidu.com/dictapp/swan/termdetail?wd=" + url.QueryEscape(s) + "&client=pc&source_tag=2&lesson_from=xiaodu"
logrus.Debugln(url)
data, err := web.GetData(url)
if err != nil {
return nil, err
}
var apiData baiduAPIData
err = json.Unmarshal(data, &apiData)
if err != nil {
return nil, err
}
if apiData.Data.Name == "" {
return nil, errors.New("未找到该成语")
}
derivation := ""
for _, v := range apiData.Data.ChuChu {
if derivation != "" {
derivation += "\n"
}
derivation += v.Dynasty + "·" + v.Author + " " + v.Source + "" + v.CiteOriginalText
}
explanation := apiData.Data.DefinitionInfo.Definition + apiData.Data.DefinitionInfo.ModernDefinition
if derivation == "" && explanation == "" {
return nil, errors.New("无法获取成语词源和解释")
}
synonyms := make([]string, len(apiData.Data.Synonyms))
for i, synonym := range apiData.Data.Synonyms {
synonyms[i] = synonym.Name
}
for i, synonym := range apiData.Data.Synonym {
if !slices.Contains(synonyms, synonym) {
synonyms[i] = synonym
}
}
liju := ""
if len(apiData.Data.Liju) > 0 {
liju = apiData.Data.Liju[0].Name
}
// 生成字符切片
chars := make([]string, 0, len(s))
for _, r := range s {
chars = append(chars, string(r))
}
// 分割拼音
pinyinSlice := strings.Split(apiData.Data.Pinyin, " ")
if len(pinyinSlice) != len(chars) {
pinyinSlice = strings.Split(apiData.Data.Definition[0].Pinyin, " ")
}
newIdiom := idiomJSON{
Word: apiData.Data.Name,
Chars: chars,
Pinyin: pinyinSlice,
Baobian: apiData.Data.Baobian,
Explanation: explanation,
Derivation: derivation,
Example: liju,
Abbreviation: apiData.Data.Structure,
Synonyms: synonyms,
}
return &newIdiom, nil
}
var mu sync.Mutex
func saveIdiomJSON() error {
mu.Lock()
defer mu.Unlock()
f, err := os.Create(idiomFilePath)
if err != nil {
return err
}
defer f.Close()
return json.NewEncoder(f).Encode(&idiomInfoMap)
}