(path string)
| 194 | } |
| 195 | |
| 196 | func singBoxPatcher(path string) func(string, uint16) error { |
| 197 | return func(origHost string, origPort uint16) error { |
| 198 | raw, err := os.ReadFile(path) |
| 199 | if err != nil { |
| 200 | return err |
| 201 | } |
| 202 | var doc map[string]any |
| 203 | if err := json.Unmarshal(raw, &doc); err != nil { |
| 204 | return fmt.Errorf("unparseable JSON: %w", err) |
| 205 | } |
| 206 | outbounds, ok := doc["outbounds"].([]any) |
| 207 | if !ok { |
| 208 | return errors.New("no outbounds array") |
| 209 | } |
| 210 | patched := false |
| 211 | for _, ob := range outbounds { |
| 212 | obm, ok := ob.(map[string]any) |
| 213 | if !ok { |
| 214 | continue |
| 215 | } |
| 216 | t, _ := obm["type"].(string) |
| 217 | switch t { |
| 218 | case "vless", "vmess", "trojan", "shadowsocks", "hysteria", "hysteria2", "tuic": |
| 219 | if _, has := obm["server"]; has { |
| 220 | obm["server"] = "127.0.0.1" |
| 221 | obm["server_port"] = 40443 |
| 222 | patched = true |
| 223 | } |
| 224 | } |
| 225 | } |
| 226 | if !patched { |
| 227 | return errors.New("no applicable outbound with type VLESS/VMess/Trojan") |
| 228 | } |
| 229 | if err := os.WriteFile(path+".bak", raw, 0o644); err != nil { |
| 230 | return fmt.Errorf("backup: %w", err) |
| 231 | } |
| 232 | updated, err := json.MarshalIndent(doc, "", " ") |
| 233 | if err != nil { |
| 234 | return err |
| 235 | } |
| 236 | return os.WriteFile(path, updated, 0o644) |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | // -- platform-specific config search paths -------------------------------- |
| 241 |
no outgoing calls