mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
114 lines
2.3 KiB
Go
114 lines
2.3 KiB
Go
package wecom
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type wecomRoute struct {
|
|
ReqID string `json:"req_id"`
|
|
ChatID string `json:"chat_id"`
|
|
ChatType uint32 `json:"chat_type"`
|
|
ExpiresAt time.Time `json:"expires_at"`
|
|
}
|
|
|
|
type reqIDStore struct {
|
|
mu sync.Mutex
|
|
path string
|
|
routes map[string]wecomRoute
|
|
}
|
|
|
|
func newReqIDStore(path string) *reqIDStore {
|
|
if path == "" {
|
|
path = defaultReqIDStorePath()
|
|
}
|
|
s := &reqIDStore{
|
|
path: path,
|
|
routes: make(map[string]wecomRoute),
|
|
}
|
|
_ = s.load()
|
|
return s
|
|
}
|
|
|
|
func defaultReqIDStorePath() string {
|
|
if home, err := os.UserHomeDir(); err == nil && home != "" {
|
|
return filepath.Join(home, ".picoclaw", "wecom", "reqid-store.json")
|
|
}
|
|
return filepath.Join(os.TempDir(), "picoclaw-wecom-reqid-store.json")
|
|
}
|
|
|
|
func (s *reqIDStore) Put(chatID, reqID string, chatType uint32, ttl time.Duration) error {
|
|
if reqID == "" || chatID == "" {
|
|
return nil
|
|
}
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.deleteExpiredLocked(time.Now())
|
|
s.routes[chatID] = wecomRoute{
|
|
ReqID: reqID,
|
|
ChatID: chatID,
|
|
ChatType: chatType,
|
|
ExpiresAt: time.Now().Add(ttl),
|
|
}
|
|
return s.saveLocked()
|
|
}
|
|
|
|
func (s *reqIDStore) Get(chatID string) (wecomRoute, bool) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.deleteExpiredLocked(time.Now())
|
|
route, ok := s.routes[chatID]
|
|
return route, ok
|
|
}
|
|
|
|
func (s *reqIDStore) Delete(chatID string) error {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
delete(s.routes, chatID)
|
|
return s.saveLocked()
|
|
}
|
|
|
|
func (s *reqIDStore) load() error {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
|
|
data, err := os.ReadFile(s.path)
|
|
if err != nil {
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
var routes map[string]wecomRoute
|
|
if err := json.Unmarshal(data, &routes); err != nil {
|
|
return err
|
|
}
|
|
s.routes = routes
|
|
s.deleteExpiredLocked(time.Now())
|
|
return nil
|
|
}
|
|
|
|
func (s *reqIDStore) deleteExpiredLocked(now time.Time) {
|
|
for chatID, route := range s.routes {
|
|
if !route.ExpiresAt.IsZero() && now.After(route.ExpiresAt) {
|
|
delete(s.routes, chatID)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (s *reqIDStore) saveLocked() error {
|
|
if err := os.MkdirAll(filepath.Dir(s.path), 0o700); err != nil {
|
|
return err
|
|
}
|
|
data, err := json.MarshalIndent(s.routes, "", " ")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return os.WriteFile(s.path, data, 0o600)
|
|
}
|