75 lines
1.8 KiB
Go
75 lines
1.8 KiB
Go
package app
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
_ "modernc.org/sqlite"
|
|
)
|
|
|
|
type Store struct{ db *sql.DB }
|
|
|
|
func OpenStore(dir string) (*Store, error) {
|
|
if err := os.MkdirAll(dir, 0700); err != nil {
|
|
return nil, err
|
|
}
|
|
p := filepath.Join(dir, "clashweb.sqlite")
|
|
f, err := os.OpenFile(p, os.O_CREATE|os.O_RDWR, 0600)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
f.Close()
|
|
db, err := sql.Open("sqlite", p)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
db.SetMaxOpenConns(1)
|
|
_, err = db.Exec(`PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000;
|
|
CREATE TABLE IF NOT EXISTS kv (key TEXT PRIMARY KEY, value TEXT NOT NULL);
|
|
CREATE TABLE IF NOT EXISTS sessions (token_hash TEXT PRIMARY KEY, csrf TEXT NOT NULL, expires INTEGER NOT NULL);
|
|
PRAGMA user_version=1;`)
|
|
if err != nil {
|
|
db.Close()
|
|
return nil, err
|
|
}
|
|
return &Store{db: db}, nil
|
|
}
|
|
|
|
func (s *Store) Close() error { return s.db.Close() }
|
|
func (s *Store) Get(key string) (string, error) {
|
|
var value string
|
|
err := s.db.QueryRow("SELECT value FROM kv WHERE key=?", key).Scan(&value)
|
|
if err == sql.ErrNoRows {
|
|
return "", nil
|
|
}
|
|
return value, err
|
|
}
|
|
func (s *Store) Set(key, value string) error {
|
|
_, err := s.db.Exec("INSERT INTO kv(key,value) VALUES(?,?) ON CONFLICT(key) DO UPDATE SET value=excluded.value", key, value)
|
|
return err
|
|
}
|
|
func (s *Store) Load() (State, error) {
|
|
text, err := s.Get("state")
|
|
if err != nil {
|
|
return State{}, err
|
|
}
|
|
if text == "" {
|
|
return defaultState(), nil
|
|
}
|
|
var state State
|
|
if err := json.Unmarshal([]byte(text), &state); err != nil {
|
|
return State{}, fmt.Errorf("数据库中的配置损坏: %w", err)
|
|
}
|
|
return state, validateState(state)
|
|
}
|
|
func (s *Store) Save(state State) error {
|
|
b, err := json.Marshal(state)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return s.Set("state", string(b))
|
|
}
|