platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
135
selective-vpn-api/app/resolver/io_helpers.go
Normal file
135
selective-vpn-api/app/resolver/io_helpers.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package resolver
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ReadLinesAllowMissing(path string) []string {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(strings.ReplaceAll(string(data), "\r\n", "\n"), "\n")
|
||||
}
|
||||
|
||||
func LoadJSONMap(path string) map[string]any {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return map[string]any{}
|
||||
}
|
||||
var out map[string]any
|
||||
if err := json.Unmarshal(data, &out); err != nil {
|
||||
return map[string]any{}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func SaveJSON(data any, path string) {
|
||||
tmp := path + ".tmp"
|
||||
b, err := json.MarshalIndent(data, "", " ")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_ = os.WriteFile(tmp, b, 0o644)
|
||||
_ = os.Rename(tmp, path)
|
||||
}
|
||||
|
||||
func parseAnyInt(raw any) (int, bool) {
|
||||
switch v := raw.(type) {
|
||||
case int:
|
||||
return v, true
|
||||
case int64:
|
||||
return int(v), true
|
||||
case float64:
|
||||
return int(v), true
|
||||
case json.Number:
|
||||
n, err := v.Int64()
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
return int(n), true
|
||||
case string:
|
||||
s := strings.TrimSpace(v)
|
||||
if s == "" {
|
||||
return 0, false
|
||||
}
|
||||
n, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
return n, true
|
||||
default:
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
func LoadResolverPrecheckLastRun(path string) int {
|
||||
m := LoadJSONMap(path)
|
||||
if len(m) == 0 {
|
||||
return 0
|
||||
}
|
||||
v, ok := parseAnyInt(m["last_run"])
|
||||
if !ok || v <= 0 {
|
||||
return 0
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func LoadResolverLiveBatchTarget(path string, fallback, minV, maxV int) int {
|
||||
if fallback < minV {
|
||||
fallback = minV
|
||||
}
|
||||
if fallback > maxV {
|
||||
fallback = maxV
|
||||
}
|
||||
m := LoadJSONMap(path)
|
||||
if len(m) == 0 {
|
||||
return fallback
|
||||
}
|
||||
raw := m["live_batch_next_target"]
|
||||
if raw == nil {
|
||||
raw = m["live_batch_target"]
|
||||
}
|
||||
v, ok := parseAnyInt(raw)
|
||||
if !ok || v <= 0 {
|
||||
return fallback
|
||||
}
|
||||
if v < minV {
|
||||
v = minV
|
||||
}
|
||||
if v > maxV {
|
||||
v = maxV
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func LoadResolverLiveBatchNXHeavyPct(path string, fallback, minV, maxV int) int {
|
||||
if fallback < minV {
|
||||
fallback = minV
|
||||
}
|
||||
if fallback > maxV {
|
||||
fallback = maxV
|
||||
}
|
||||
m := LoadJSONMap(path)
|
||||
if len(m) == 0 {
|
||||
return fallback
|
||||
}
|
||||
raw := m["live_batch_nxheavy_next_pct"]
|
||||
if raw == nil {
|
||||
raw = m["live_batch_nxheavy_pct"]
|
||||
}
|
||||
v, ok := parseAnyInt(raw)
|
||||
if !ok {
|
||||
return fallback
|
||||
}
|
||||
if v < minV {
|
||||
v = minV
|
||||
}
|
||||
if v > maxV {
|
||||
v = maxV
|
||||
}
|
||||
return v
|
||||
}
|
||||
Reference in New Issue
Block a user