122 lines
2.6 KiB
Go
122 lines
2.6 KiB
Go
package openwechat
|
||
|
||
import (
|
||
"io"
|
||
"os"
|
||
"sync"
|
||
"time"
|
||
)
|
||
|
||
// Storage 身份信息, 维持整个登陆的Session会话
|
||
type Storage struct {
|
||
LoginInfo *LoginInfo
|
||
Request *BaseRequest
|
||
Response *WebInitResponse
|
||
}
|
||
|
||
type HotReloadStorageItem struct {
|
||
Jar *Jar
|
||
BaseRequest *BaseRequest
|
||
LoginInfo *LoginInfo
|
||
WechatDomain WechatDomain
|
||
UUID string
|
||
}
|
||
|
||
// HotReloadStorage 热登陆存储接口
|
||
type HotReloadStorage io.ReadWriter
|
||
|
||
// fileHotReloadStorage 实现HotReloadStorage接口
|
||
// 以文件的形式存储
|
||
type fileHotReloadStorage struct {
|
||
filename string
|
||
file *os.File
|
||
lock sync.Mutex
|
||
}
|
||
|
||
func (j *fileHotReloadStorage) Read(p []byte) (n int, err error) {
|
||
j.lock.Lock()
|
||
defer j.lock.Unlock()
|
||
if j.file == nil {
|
||
j.file, err = os.OpenFile(j.filename, os.O_RDWR, 0600)
|
||
if os.IsNotExist(err) {
|
||
return 0, ErrInvalidStorage
|
||
}
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
}
|
||
return j.file.Read(p)
|
||
}
|
||
|
||
func (j *fileHotReloadStorage) Write(p []byte) (n int, err error) {
|
||
j.lock.Lock()
|
||
defer j.lock.Unlock()
|
||
if j.file == nil {
|
||
j.file, err = os.Create(j.filename)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
}
|
||
// reset offset and truncate file
|
||
if _, err = j.file.Seek(0, io.SeekStart); err != nil {
|
||
return
|
||
}
|
||
if err = j.file.Truncate(0); err != nil {
|
||
return
|
||
}
|
||
// json decode only write once
|
||
return j.file.Write(p)
|
||
}
|
||
|
||
func (j *fileHotReloadStorage) Close() error {
|
||
j.lock.Lock()
|
||
defer j.lock.Unlock()
|
||
if j.file == nil {
|
||
return nil
|
||
}
|
||
return j.file.Close()
|
||
}
|
||
|
||
// Deprecated: use NewFileHotReloadStorage instead
|
||
// 不再单纯以json的格式存储,支持了用户自定义序列化方式
|
||
func NewJsonFileHotReloadStorage(filename string) io.ReadWriteCloser {
|
||
return NewFileHotReloadStorage(filename)
|
||
}
|
||
|
||
// NewFileHotReloadStorage implements HotReloadStorage
|
||
func NewFileHotReloadStorage(filename string) io.ReadWriteCloser {
|
||
return &fileHotReloadStorage{filename: filename}
|
||
}
|
||
|
||
var _ HotReloadStorage = (*fileHotReloadStorage)(nil)
|
||
|
||
type HotReloadStorageSyncer struct {
|
||
duration time.Duration
|
||
bot *Bot
|
||
}
|
||
|
||
// Sync 定时同步数据到登陆存储中
|
||
func (h *HotReloadStorageSyncer) Sync() error {
|
||
if h.duration <= 0 {
|
||
return nil
|
||
}
|
||
// 定时器
|
||
ticker := time.NewTicker(h.duration)
|
||
for {
|
||
select {
|
||
case <-ticker.C:
|
||
// 每隔一段时间, 将数据同步到storage中
|
||
if err := h.bot.DumpHotReloadStorage(); err != nil {
|
||
return err
|
||
}
|
||
case <-h.bot.Context().Done():
|
||
// 当Bot关闭的时候, 退出循环
|
||
return nil
|
||
}
|
||
}
|
||
}
|
||
|
||
func NewHotReloadStorageSyncer(bot *Bot, duration time.Duration) *HotReloadStorageSyncer {
|
||
return &HotReloadStorageSyncer{duration: duration, bot: bot}
|
||
}
|