package main import ( "encoding/json" "fmt" "log" "os" "path/filepath" "strings" "sync" "time" ) const tianapiKey = "da21ff665b09cbdcc29952a105aad97b" const tianapiStarURL = "https://apis.tianapi.com/star/index" var zodiacToSign = map[string]string{ "白羊座": "aries", "金牛座": "taurus", "双子座": "gemini", "巨蟹座": "cancer", "狮子座": "leo", "处女座": "virgo", "天秤座": "libra", "天蝎座": "scorpio", "射手座": "sagittarius", "摩羯座": "capricorn", "水瓶座": "aquarius", "双鱼座": "pisces", } var horoscopeMu sync.Mutex type tianapiStarResp struct { Code int `json:"code"` Result struct { List []struct { Type string `json:"type"` Content string `json:"content"` } `json:"list"` } `json:"result"` } type horoscopeInfo struct { Zodiac string `json:"zodiac"` Date string `json:"date"` All string `json:"all"` Love string `json:"love"` Work string `json:"work"` Money string `json:"money"` Health string `json:"health"` LuckyColor string `json:"luckyColor"` LuckyNum string `json:"luckyNum"` Noble string `json:"noble"` Summary string `json:"summary"` } func horoscopeCachePath() string { return filepath.Join(configDir(), "horoscope_cache.json") } func saveHoroscopeCache(info *horoscopeInfo) { info.Date = time.Now().Format("2006-01-02") data, _ := json.Marshal(info) os.WriteFile(horoscopeCachePath(), data, 0644) } func loadHoroscopeCache() *horoscopeInfo { data, err := os.ReadFile(horoscopeCachePath()) if err != nil { return nil } var info horoscopeInfo if json.Unmarshal(data, &info) != nil { return nil } return &info } func isCacheToday(info *horoscopeInfo) bool { return info != nil } func fetchHoroscope(zodiac string) *horoscopeInfo { sign := zodiacToSign[zodiac] if sign == "" { sign = "sagittarius" } url := fmt.Sprintf("%s?key=%s&astro=%s", tianapiStarURL, tianapiKey, sign) data, err := httpGet(url) if err != nil { log.Println("星座运势请求失败:", err) return nil } var resp tianapiStarResp if json.Unmarshal(data, &resp) != nil || resp.Code != 200 { log.Println("星座运势解析失败:", string(data)) return nil } info := &horoscopeInfo{Zodiac: zodiac} for _, item := range resp.Result.List { switch item.Type { case "综合指数": info.All = strings.TrimSuffix(item.Content, "%") case "爱情指数": info.Love = strings.TrimSuffix(item.Content, "%") case "工作指数": info.Work = strings.TrimSuffix(item.Content, "%") case "财运指数": info.Money = strings.TrimSuffix(item.Content, "%") case "健康指数": info.Health = strings.TrimSuffix(item.Content, "%") case "幸运颜色": info.LuckyColor = item.Content case "幸运数字": info.LuckyNum = item.Content case "贵人星座": info.Noble = item.Content case "今日概述": info.Summary = strings.TrimSpace(item.Content) } } log.Printf("星座运势已获取: %s", zodiac) return info } func pushHoroscopeInfo(info *horoscopeInfo) { jsonData, _ := json.Marshal(info) log.Printf("星座运势JS: %s", string(jsonData[:min(len(jsonData), 120)])) js := fmt.Sprintf(`if(window.updateHoroscopeFromGo) window.updateHoroscopeFromGo(%s)`, string(jsonData)) evalJS(js) } func pushHoroscope(zodiac string) { info := fetchHoroscope(zodiac) if info == nil { log.Println("星座运势: fetchHoroscope返回nil") return } saveHoroscopeCache(info) pushHoroscopeInfo(info) } func horoscopeLoop() { cfg := loadConfig() if cfg.HideZodiac { return } cached := loadHoroscopeCache() if cached != nil { pushHoroscopeInfo(cached) } time.Sleep(5 * time.Second) cfg = loadConfig() if cfg.HideZodiac { return } today := time.Now().Format("2006-01-02") if cached != nil && cached.Date == today && cached.Zodiac == cfg.Zodiac { return } pushHoroscope(cfg.Zodiac) ticker := time.NewTicker(24 * time.Hour) for range ticker.C { cfg := loadConfig() if !cfg.HideZodiac { pushHoroscope(cfg.Zodiac) } } } func triggerHoroscopeRefresh(zodiac string) { go func() { pushHoroscope(zodiac) }() }