Files
u-desktop/knowledge.go
绝尘 9fd3acede3 新增: 星座运势+AI资讯+知识卡片+桌面设置窗口+秒显示开关
- 星座运势: 天聚数行API集成,5维进度条+幸运标签+今日概述
- AI资讯: 天聚数行API,图文布局5条展示,文件缓存2小时刷新
- 知识卡片: AI生成,关键字+提示词配置,30分钟刷新
- 桌面设置: 独立WebView2窗口,760x1350,含壁纸/布局/城市/颜色等配置
- 显示控制: 壁纸/时间/天气/星座/知识/AI资讯独立开关,秒显示开关
- 文件缓存: 星座运势+AI资讯缓存到本地,启动即显示上次数据
- initDone防抖: 防止设置窗口初始化触发卡片重载
2026-05-26 04:34:00 +08:00

221 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"bytes"
"database/sql"
"encoding/json"
"fmt"
"log"
"math/rand"
"net/http"
"path/filepath"
"time"
_ "modernc.org/sqlite"
)
const cpaURL = "https://cpa.1216.top/v1/chat/completions"
const cpaKey = "alink-shared-key-1"
const cpaModel = "glm-4.5-air"
type knowledgeData struct {
Content string `json:"content"`
Keyword string `json:"keyword"`
}
var knowledgeDB *sql.DB
func initKnowledgeDB() {
dbPath := filepath.Join(configDir(), "knowledge.db")
var err error
knowledgeDB, err = sql.Open("sqlite", dbPath)
if err != nil {
log.Println("知识库打开失败:", err)
return
}
knowledgeDB.SetMaxOpenConns(1)
_, err = knowledgeDB.Exec(`CREATE TABLE IF NOT EXISTS knowledge_cards (
id INTEGER PRIMARY KEY AUTOINCREMENT,
keyword TEXT NOT NULL,
content TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`)
if err != nil {
log.Println("知识库建表失败:", err)
}
}
func saveKnowledgeCard(keyword, content string) {
if knowledgeDB == nil {
return
}
_, err := knowledgeDB.Exec("INSERT INTO knowledge_cards (keyword, content) VALUES (?, ?)", keyword, content)
if err != nil {
log.Println("知识保存失败:", err)
}
}
func getRandomKnowledgeCard(keyword string) string {
if knowledgeDB == nil {
return ""
}
var content string
err := knowledgeDB.QueryRow(
"SELECT content FROM knowledge_cards WHERE keyword = ? ORDER BY RANDOM() LIMIT 1",
keyword,
).Scan(&content)
if err != nil {
return ""
}
return content
}
func getKnowledgeCardCount(keyword string) int {
if knowledgeDB == nil {
return 0
}
var count int
err := knowledgeDB.QueryRow(
"SELECT COUNT(*) FROM knowledge_cards WHERE keyword = ?",
keyword,
).Scan(&count)
if err != nil {
return 0
}
return count
}
func fetchKnowledgeFromLLM(keyword string, cfg *Config) string {
basePrompt := fmt.Sprintf(
"根据关键词「%s」生成一条有趣的知识小卡片。要求控制在80字以内简洁有趣有知识性。直接输出内容不要加标题、序号或其他格式。",
keyword,
)
if cfg.KnowledgePrompt != "" {
basePrompt += "\n附加要求" + cfg.KnowledgePrompt
}
body := map[string]interface{}{
"model": cpaModel,
"max_tokens": 256,
"messages": []map[string]string{
{"role": "user", "content": basePrompt},
},
}
jsonData, _ := json.Marshal(body)
req, err := http.NewRequest("POST", cpaURL, bytes.NewReader(jsonData))
if err != nil {
log.Println("知识API请求创建失败:", err)
return ""
}
req.Header.Set("Authorization", "Bearer "+cpaKey)
req.Header.Set("Content-Type", "application/json")
resp, err := httpClient.Do(req)
if err != nil {
log.Println("知识API请求失败:", err)
return ""
}
defer resp.Body.Close()
var result struct {
Choices []struct {
Message struct {
Content string `json:"content"`
} `json:"message"`
} `json:"choices"`
}
if json.NewDecoder(resp.Body).Decode(&result) != nil {
log.Println("知识API响应解析失败")
return ""
}
if len(result.Choices) > 0 {
return result.Choices[0].Message.Content
}
return ""
}
func pushKnowledgeJSON(content, keyword string) {
data, _ := json.Marshal(knowledgeData{Content: content, Keyword: keyword})
evalJS(fmt.Sprintf(`if(window.updateKnowledgeFromGo) window.updateKnowledgeFromGo(%s)`, string(data)))
}
func fetchAndPushKnowledge() {
cfg := loadConfig()
keyword := cfg.KnowledgeKeyword
if keyword == "" {
return
}
var content string
count := getKnowledgeCardCount(keyword)
if count > 0 && rand.Intn(10) < 3 {
content = getRandomKnowledgeCard(keyword)
}
if content == "" {
content = fetchKnowledgeFromLLM(keyword, cfg)
if content != "" {
saveKnowledgeCard(keyword, content)
}
}
if content == "" && count > 0 {
content = getRandomKnowledgeCard(keyword)
}
if content == "" {
return
}
pushKnowledgeJSON(content, keyword)
preview := content
if len(preview) > 30 {
preview = preview[:30] + "..."
}
log.Println("知识卡片已推送:", preview)
}
func pushKnowledgeLoading(keyword string) {
pushKnowledgeJSON("加载中...", keyword)
}
func pushKnowledgePlaceholder() {
pushKnowledgeJSON("请设置知识关键字", "")
}
func knowledgeLoop() {
initKnowledgeDB()
cfg := loadConfig()
if cfg.KnowledgeKeyword != "" && !cfg.HideKnowledge {
if cached := getRandomKnowledgeCard(cfg.KnowledgeKeyword); cached != "" {
pushKnowledgeJSON(cached, cfg.KnowledgeKeyword)
} else {
pushKnowledgeLoading(cfg.KnowledgeKeyword)
}
} else if cfg.KnowledgeKeyword == "" {
pushKnowledgePlaceholder()
}
time.Sleep(3 * time.Second)
cfg = loadConfig()
if cfg.KnowledgeKeyword != "" && !cfg.HideKnowledge {
fetchAndPushKnowledge()
}
ticker := time.NewTicker(30 * time.Minute)
for range ticker.C {
cfg := loadConfig()
if cfg.KnowledgeKeyword != "" && !cfg.HideKnowledge {
fetchAndPushKnowledge()
}
}
}
func triggerKnowledgeRefresh() {
go fetchAndPushKnowledge()
}