Skip to content

Commit c584e41

Browse files
committed
feat: 源码上传
1 parent 2bad269 commit c584e41

18 files changed

+1237
-0
lines changed

.gitignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
### Go template
2+
# If you prefer the allow list template instead of the deny list, see community template:
3+
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
4+
#
5+
# Binaries for programs and plugins
6+
*.exe
7+
*.exe~
8+
*.dll
9+
*.so
10+
*.dylib
11+
12+
# Test binary, built with `go test -c`
13+
*.test
14+
15+
# Output of the go coverage tool, specifically when used with LiteIDE
16+
*.out
17+
18+
# Dependency directories (remove the comment below to include it)
19+
# vendor/
20+
21+
# Go workspace file
22+
go.work
23+
24+
/logs/
25+
/bin/
26+
/cookie.txt
27+
/cache.json
28+
.idea

battery_checker.go

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// 电池检测
2+
package main
3+
4+
import (
5+
"fmt"
6+
"github.com/gookit/slog"
7+
"os/exec"
8+
"strconv"
9+
"strings"
10+
"time"
11+
)
12+
13+
// StartBatteryCheckByCmd 读取系统文件的电量
14+
func StartBatteryCheckByCmd() {
15+
go func() {
16+
for {
17+
// 获取电量
18+
cmd := exec.Command("cat", "/sys/class/power_supply/battery/capacity")
19+
output, err := cmd.Output()
20+
if err != nil {
21+
return
22+
}
23+
capacityStr := strings.TrimSpace(string(output))
24+
capacity, err := strconv.Atoi(capacityStr)
25+
if err != nil {
26+
return
27+
}
28+
29+
// 检查电池是否在充电,1:在充电,0:没有在充电
30+
cmdOnline := exec.Command("cat", "/sys/class/power_supply/battery/online")
31+
onlineOutput, err := cmdOnline.Output()
32+
if err != nil {
33+
return
34+
}
35+
onlineStr := strings.TrimSpace(string(onlineOutput))
36+
online, err := strconv.Atoi(onlineStr)
37+
if err != nil {
38+
return
39+
}
40+
41+
var interval = Yaml.Battery.CheckInterval
42+
currentPower := capacity - 1
43+
if online == 0 && currentPower <= Yaml.Battery.Low {
44+
text := fmt.Sprintf("R106随身WiFi电量%d%%过低,请充电", currentPower)
45+
slog.Warn(text)
46+
DingDingNotify(text)
47+
interval = Yaml.Battery.NotifyInterval
48+
} else {
49+
interval = Yaml.Battery.CheckInterval
50+
}
51+
time.Sleep(interval)
52+
}
53+
}()
54+
}
55+
56+
//// ResponseData 定义响应结构体
57+
//type ResponseData struct {
58+
// DeviceBatteryChargeStatus string `json:"device_battery_charge_status"`
59+
// DeviceBatteryLevelPercent string `json:"device_battery_level_percent"`
60+
//}
61+
//
62+
//type ResponsePayload struct {
63+
// Retcode int `json:"retcode"`
64+
// Data ResponseData `json:"data"`
65+
//}
66+
//
67+
//// StartBatteryCheck 启动电量检测任务
68+
//func StartBatteryCheck(cookie string, cookieManager *CookieManager) {
69+
// go func() {
70+
// for {
71+
// // 调用统一方法获取并解析电量状态
72+
// batteryLevel, isLow, err := fetchBatteryStatus(cookie, cookieManager)
73+
// if err != nil {
74+
// continue
75+
// }
76+
//
77+
// var interval = Yaml.BatteryCheckInterval
78+
// if isLow {
79+
// text := fmt.Sprintf("R106随身WiFi电量%d%%过低,请充电", batteryLevel)
80+
// slog.Warn(text)
81+
// DingDingNotify(text)
82+
// interval = 10 * time.Minute
83+
// } else {
84+
// interval = Yaml.BatteryCheckInterval
85+
// }
86+
// time.Sleep(interval)
87+
// }
88+
// }()
89+
//}
90+
//
91+
//// Deprecated
92+
//func sendPostRequest(url string, cookie string, body []byte) ([]byte, error) {
93+
// req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
94+
// if err != nil {
95+
// return nil, fmt.Errorf("failed to create HTTP request: %w", err)
96+
// }
97+
//
98+
// req.Header.Set("Content-Type", "application/json")
99+
// req.Header.Set("Cookie", cookie)
100+
//
101+
// client := &http.Client{}
102+
// resp, err := client.Do(req)
103+
// if err != nil {
104+
// return nil, fmt.Errorf("failed to send HTTP request: %w", err)
105+
// }
106+
// defer resp.Body.Close()
107+
//
108+
// respBody, err := ioutil.ReadAll(resp.Body)
109+
// if err != nil {
110+
// return nil, fmt.Errorf("failed to read response body: %w", err)
111+
// }
112+
//
113+
// return respBody, nil
114+
//}
115+
//
116+
//// Deprecated
117+
//// 解析响应数据
118+
//func parseResponse(body []byte) (ResponsePayload, error) {
119+
// var responsePayload ResponsePayload
120+
// err := json.Unmarshal(body, &responsePayload)
121+
// if err != nil {
122+
// return ResponsePayload{}, fmt.Errorf("failed to unmarshal response: %w", err)
123+
// }
124+
// return responsePayload, nil
125+
//}
126+
//
127+
//// Deprecated
128+
//// 检查电池状态是否低
129+
//func isBatteryLow(responsePayload ResponsePayload) (int, bool, error) {
130+
// if responsePayload.Retcode != 0 {
131+
// return -1, false, fmt.Errorf("error in response: retcode = %d", responsePayload.Retcode)
132+
// }
133+
//
134+
// chargeStatus := responsePayload.Data.DeviceBatteryChargeStatus
135+
// batteryLevel := responsePayload.Data.DeviceBatteryLevelPercent
136+
//
137+
// batteryLevelInt, err := strconv.Atoi(batteryLevel)
138+
// if err != nil {
139+
// return -1, false, fmt.Errorf("failed to parse battery level: %v", err)
140+
// }
141+
//
142+
// // 检查条件
143+
// if chargeStatus == "none" && batteryLevelInt <= Yaml.LowBatteryValue {
144+
// return batteryLevelInt, true, nil
145+
// }
146+
//
147+
// return batteryLevelInt, false, nil
148+
//}
149+
//
150+
//// StartBatteryStatusAPI 对外提供查询电量状态的API
151+
//func StartBatteryStatusAPI(cookie string, cookieManager *CookieManager) {
152+
// http.HandleFunc("/api/battery-status", func(w http.ResponseWriter, r *http.Request) {
153+
// if r.Method != http.MethodGet {
154+
// http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
155+
// return
156+
// }
157+
// batteryLevel, _, err := fetchBatteryStatus(cookie, cookieManager)
158+
// if err != nil {
159+
// return
160+
// }
161+
// w.Header().Set("Content-Type", "text/plain")
162+
// fmt.Fprintf(w, "%d", batteryLevel)
163+
// })
164+
// http.ListenAndServe(":8686", nil)
165+
//}
166+
//
167+
//// Deprecated
168+
//// fetchBatteryStatus 获取并解析电量状态数据
169+
//func fetchBatteryStatus(cookie string, cookieManager *CookieManager) (int, bool, error) {
170+
// body := []byte(`{
171+
// "keys": [
172+
// "device_battery_charge_status",
173+
// "device_battery_level_percent"
174+
// ]
175+
// }`)
176+
// respBody, err := sendPostRequest(Yaml.GetMgdbParamsURL, cookie, body)
177+
//
178+
// // 检查响应是否有效
179+
// if !json.Valid(respBody) {
180+
// time.Sleep(5 * time.Second)
181+
// cookieTmp := cookie
182+
// cookie, _ = cookieManager.Load()
183+
// slog.Warnf("电量检测,cookie失效,%s,尝试从本地文件加载Cookie:%s", cookieTmp, cookie)
184+
// // 重新发送请求
185+
// respBody, _ = sendPostRequest(Yaml.GetMgdbParamsURL, cookie, body)
186+
// }
187+
// if err != nil {
188+
// return -1, false, err
189+
// }
190+
//
191+
// // 解析并校验响应
192+
// responsePayload, err := parseResponse(respBody)
193+
// if err != nil {
194+
// return -1, false, err
195+
// }
196+
//
197+
// // 检查电量状态
198+
// batteryLevel, isLow, err := isBatteryLow(responsePayload)
199+
// if err != nil {
200+
// return -1, false, err
201+
// }
202+
//
203+
// return batteryLevel, isLow, nil
204+
//}

cache.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
// 缓存管理
2+
package main
3+
4+
import (
5+
"encoding/json"
6+
"fmt"
7+
"github.com/gookit/slog"
8+
"os"
9+
"sync"
10+
"time"
11+
)
12+
13+
// Cache 缓存结构
14+
type Cache struct {
15+
Data map[string]time.Time
16+
Mutex sync.Mutex
17+
File string
18+
}
19+
20+
// NewCache 新建缓存对象
21+
func NewCache() *Cache {
22+
cache := &Cache{
23+
Data: make(map[string]time.Time),
24+
File: fmt.Sprintf("%s/tmp/cache.json", GetProgramDir()),
25+
}
26+
go cache.StartFileCleanupTask() // 启动定时清理任务
27+
return cache
28+
}
29+
30+
// Add 添加缓存记录并设置过期时间
31+
func (c *Cache) Add(key string) {
32+
c.Mutex.Lock()
33+
defer c.Mutex.Unlock()
34+
c.Data[key] = time.Now().Add(Yaml.Sms.CacheTTL)
35+
c.SaveToFile()
36+
}
37+
38+
// Exists 检查缓存记录是否存在且未过期
39+
func (c *Cache) Exists(key string) bool {
40+
c.Mutex.Lock()
41+
defer c.Mutex.Unlock()
42+
expiration, found := c.Data[key]
43+
if !found {
44+
return false
45+
}
46+
if time.Now().After(expiration) {
47+
delete(c.Data, key)
48+
c.SaveToFile()
49+
return false
50+
}
51+
return true
52+
}
53+
54+
// SaveToFile 保存缓存到本地文件(JSON 格式)
55+
func (c *Cache) SaveToFile() {
56+
file, err := os.Create(c.File)
57+
if err != nil {
58+
slog.Errorf("将缓存保存到文件时出错:%v", err)
59+
return
60+
}
61+
defer file.Close()
62+
encoder := json.NewEncoder(file)
63+
if err := encoder.Encode(c.Data); err != nil {
64+
slog.Errorf("缓存数据编码错误:%v", err)
65+
}
66+
}
67+
68+
// LoadFromFile 从本地文件加载缓存(JSON 格式)
69+
func (c *Cache) LoadFromFile() {
70+
file, err := os.Open(c.File)
71+
if err != nil {
72+
if !os.IsNotExist(err) {
73+
slog.Errorf("从文件加载缓存时出错:%v", err)
74+
}
75+
return
76+
}
77+
defer file.Close()
78+
79+
// 从 JSON 文件解码数据
80+
decoder := json.NewDecoder(file)
81+
if err := decoder.Decode(&c.Data); err != nil {
82+
slog.Errorf("缓存数据解码出错:%v", err)
83+
}
84+
85+
// 删除过期记录
86+
c.cleanupExpired()
87+
c.SaveToFile()
88+
}
89+
90+
// cleanupExpired 清理内存中过期的记录
91+
func (c *Cache) cleanupExpired() {
92+
now := time.Now()
93+
for key, expiration := range c.Data {
94+
if now.After(expiration) {
95+
delete(c.Data, key)
96+
}
97+
}
98+
}
99+
100+
// StartFileCleanupTask 定时清理本地文件中过期记录
101+
func (c *Cache) StartFileCleanupTask() {
102+
ticker := time.NewTicker(Yaml.Sms.FileCleanupPeriod)
103+
defer ticker.Stop()
104+
105+
for range ticker.C {
106+
c.Mutex.Lock()
107+
c.cleanupExpired()
108+
c.SaveToFile()
109+
c.Mutex.Unlock()
110+
}
111+
}

0 commit comments

Comments
 (0)