新增: 星座运势+AI资讯+知识卡片+桌面设置窗口+秒显示开关
- 星座运势: 天聚数行API集成,5维进度条+幸运标签+今日概述 - AI资讯: 天聚数行API,图文布局5条展示,文件缓存2小时刷新 - 知识卡片: AI生成,关键字+提示词配置,30分钟刷新 - 桌面设置: 独立WebView2窗口,760x1350,含壁纸/布局/城市/颜色等配置 - 显示控制: 壁纸/时间/天气/星座/知识/AI资讯独立开关,秒显示开关 - 文件缓存: 星座运势+AI资讯缓存到本地,启动即显示上次数据 - initDone防抖: 防止设置窗口初始化触发卡片重载
This commit is contained in:
165
ainews.go
Normal file
165
ainews.go
Normal file
@@ -0,0 +1,165 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const tianapiAIURL = "https://apis.tianapi.com/ai/index"
|
||||
|
||||
type aiNewsResp struct {
|
||||
Code int `json:"code"`
|
||||
Result struct {
|
||||
Newslist []struct {
|
||||
ID string `json:"id"`
|
||||
CTime string `json:"ctime"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Source string `json:"source"`
|
||||
URL string `json:"url"`
|
||||
PicUrl string `json:"picUrl"`
|
||||
} `json:"newslist"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
type aiNewsItem struct {
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Source string `json:"source"`
|
||||
CTime string `json:"ctime"`
|
||||
URL string `json:"url"`
|
||||
PicURL string `json:"picUrl"`
|
||||
}
|
||||
|
||||
var (
|
||||
aiNewsMu sync.Mutex
|
||||
aiNewsCache []aiNewsItem
|
||||
aiNewsCacheAt time.Time
|
||||
)
|
||||
|
||||
func aiNewsCachePath() string {
|
||||
return filepath.Join(configDir(), "ainews_cache.json")
|
||||
}
|
||||
|
||||
func fetchAINews() []aiNewsItem {
|
||||
aiNewsMu.Lock()
|
||||
if aiNewsCache != nil && time.Since(aiNewsCacheAt) < 2*time.Hour {
|
||||
cached := aiNewsCache
|
||||
aiNewsMu.Unlock()
|
||||
return cached
|
||||
}
|
||||
aiNewsMu.Unlock()
|
||||
|
||||
url := fmt.Sprintf("%s?key=%s", tianapiAIURL, tianapiKey)
|
||||
data, err := httpGet(url)
|
||||
if err != nil {
|
||||
log.Println("AI资讯请求失败:", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
var resp aiNewsResp
|
||||
if json.Unmarshal(data, &resp) != nil || resp.Code != 200 {
|
||||
log.Println("AI资讯解析失败:", string(data[:min(len(data), 100)]))
|
||||
return nil
|
||||
}
|
||||
|
||||
var items []aiNewsItem
|
||||
for _, n := range resp.Result.Newslist {
|
||||
items = append(items, aiNewsItem{
|
||||
Title: n.Title,
|
||||
Description: n.Description,
|
||||
Source: n.Source,
|
||||
CTime: n.CTime,
|
||||
URL: n.URL,
|
||||
PicURL: n.PicUrl,
|
||||
})
|
||||
}
|
||||
|
||||
aiNewsMu.Lock()
|
||||
aiNewsCache = items
|
||||
aiNewsCacheAt = time.Now()
|
||||
aiNewsMu.Unlock()
|
||||
|
||||
// 缓存到文件
|
||||
cacheData, _ := json.Marshal(map[string]interface{}{
|
||||
"items": items,
|
||||
"at": time.Now().Format(time.RFC3339),
|
||||
})
|
||||
if err := os.WriteFile(aiNewsCachePath(), cacheData, 0644); err != nil {
|
||||
log.Println("AI资讯缓存写入失败:", err)
|
||||
}
|
||||
|
||||
log.Printf("AI资讯已获取: %d条", len(items))
|
||||
return items
|
||||
}
|
||||
|
||||
func loadAINewsCache() []aiNewsItem {
|
||||
data, err := os.ReadFile(aiNewsCachePath())
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var cached struct {
|
||||
Items []aiNewsItem `json:"items"`
|
||||
At string `json:"at"`
|
||||
}
|
||||
if json.Unmarshal(data, &cached) != nil {
|
||||
return nil
|
||||
}
|
||||
return cached.Items
|
||||
}
|
||||
|
||||
func pushAINews(items []aiNewsItem) {
|
||||
if len(items) == 0 {
|
||||
return
|
||||
}
|
||||
jsonData, _ := json.Marshal(items)
|
||||
js := fmt.Sprintf(`if(window.updateAINewsFromGo) window.updateAINewsFromGo(%s)`, string(jsonData))
|
||||
evalJS(js)
|
||||
}
|
||||
|
||||
func aiNewsLoop() {
|
||||
cfg := loadConfig()
|
||||
if cfg.HideAINews {
|
||||
return
|
||||
}
|
||||
|
||||
// 先推送缓存
|
||||
if cached := loadAINewsCache(); cached != nil {
|
||||
pushAINews(cached)
|
||||
}
|
||||
|
||||
time.Sleep(8 * time.Second)
|
||||
|
||||
cfg = loadConfig()
|
||||
if cfg.HideAINews {
|
||||
return
|
||||
}
|
||||
|
||||
items := fetchAINews()
|
||||
if items != nil {
|
||||
pushAINews(items)
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(2 * time.Hour)
|
||||
for range ticker.C {
|
||||
cfg := loadConfig()
|
||||
if !cfg.HideAINews {
|
||||
if items := fetchAINews(); items != nil {
|
||||
pushAINews(items)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func triggerAINewsRefresh() {
|
||||
go func() {
|
||||
if items := fetchAINews(); items != nil {
|
||||
pushAINews(items)
|
||||
}
|
||||
}()
|
||||
}
|
||||
Reference in New Issue
Block a user