新增: 星座运势+AI资讯+知识卡片+桌面设置窗口+秒显示开关
- 星座运势: 天聚数行API集成,5维进度条+幸运标签+今日概述 - AI资讯: 天聚数行API,图文布局5条展示,文件缓存2小时刷新 - 知识卡片: AI生成,关键字+提示词配置,30分钟刷新 - 桌面设置: 独立WebView2窗口,760x1350,含壁纸/布局/城市/颜色等配置 - 显示控制: 壁纸/时间/天气/星座/知识/AI资讯独立开关,秒显示开关 - 文件缓存: 星座运势+AI资讯缓存到本地,启动即显示上次数据 - initDone防抖: 防止设置窗口初始化触发卡片重载
This commit is contained in:
220
knowledge.go
Normal file
220
knowledge.go
Normal file
@@ -0,0 +1,220 @@
|
||||
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()
|
||||
}
|
||||
Reference in New Issue
Block a user