Skip to content

Instantly share code, notes, and snippets.

@nilbot
Created August 4, 2015 14:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nilbot/657e00072e75f56dd071 to your computer and use it in GitHub Desktop.
Save nilbot/657e00072e75f56dd071 to your computer and use it in GitHub Desktop.
zhujiceping.com 批量

#用法

太长了,不读

[BIN] -s [SERVER(range)] -p [PORT(range)] -c [SERVER_NAME] [-d]
  -c string
        comment for this server (group)
  -d    debug
  -p string
        80 or 80-8000
  -s string
        1.2.3.4 or 1.2.3.4-20

还是读一下吧……

本工具批量就暂时批量成支持范围,比如说 server ip: 1.2.3.4 - 1.2.3.6 可以写成 1.2.3.4-6;同理 port 支持 22-5000 这种写法。出来的结果就是 $$n*m$$ 个。

  • 先将二进制文件拷贝到放gui-config.json的文件夹,然后进入命令行,换到这个放gui-config.json的文件夹
  • 备份原有的json,然后
  • 整理一下你要添加的服务器信息,需要的是ip和port。例如: 1.2.3.4:80, 1.2.3.4:81, 1.2.3.4:82
  • 打命令 add.exe -s 1.2.3.4 -p 80-82 -c test_servers
  • Viola!

编译

到这里还在读,嗯,原来你是想折腾的,那么请先看test,看完你就会发现我这个大部分都还没来得及好好测试,不妨你就动手自己写个测试吧。

编译就是简单的

go build -o [THE_NAME_YOU_WANT] add_ss_configs.go

跨平台编译,比如linux编译windows,不在本文范畴,请自行google

package main
import (
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"
"reflect"
"strconv"
"strings"
)
type server_setting struct {
ip string `json:"server"`
port int `json:"server_port"`
password string `json:"password"`
method string `json:"method"`
remarks string `json:"remarks"`
}
type configStruct struct {
server_configs []server_setting `json:"configs"`
strategy string `json:"strategy"`
index int `json:"index"`
global bool `json:"global"`
enabled bool `json:"enabled"`
shareOverLan bool `json:"shareOverLan"`
isDefault bool `json:"isDefault"`
localPort int `json:"localPort"`
pacUrl string `json:"pacUrl"`
useOnlinePac bool `json:"useOnlinePac"`
}
func (s *server_setting) MarshalJSON() ([]byte, error) {
if s.ip != "" && s.port > 0 {
return json.Marshal(map[string]interface{}{
"server": s.ip,
"server_port": s.port,
"password": s.password,
"method": s.method,
"remarks": s.remarks,
})
}
return json.Marshal(nil)
}
func (c *configStruct) MarshalJSON() ([]byte, error) {
if len(c.server_configs) > 0 {
return json.Marshal(map[string]interface{}{
"configs": c.server_configs,
"strategy": c.strategy,
"index": c.index,
"global": c.global,
"enabled": c.enabled,
"shareOverLan": c.shareOverLan,
"isDefault": c.isDefault,
"localPort": c.localPort,
"pacUrl": c.pacUrl,
"useOnlinePac": c.useOnlinePac,
})
}
return json.Marshal(nil)
}
// type csAlias configStruct
func (c *configStruct) UnmarshalJSON(b []byte) (err error) {
j := make(map[string]interface{})
if err = json.Unmarshal(b, &j); err == nil {
if *debug {
fmt.Printf("\n---UNMARSHALLED---\n%v\n---\n", j)
}
var found bool
grp := j["configs"].([]interface{})
var old_servers []server_setting
for _, g := range grp {
var s server_setting
d := g.(map[string]interface{})
s.ip = d["server"].(string)
s.port = int(d["server_port"].(float64))
s.password = d["password"].(string)
s.method = d["method"].(string)
s.remarks = d["remarks"].(string)
old_servers = append(old_servers, s)
}
c.server_configs = old_servers
c.strategy, found = j["strategy"].(string)
if !found {
c.strategy = ""
}
c.index = int(j["index"].(float64))
c.global = j["global"].(bool)
c.enabled = j["enabled"].(bool)
c.shareOverLan = j["shareOverLan"].(bool)
c.isDefault = j["isDefault"].(bool)
c.localPort = int(j["localPort"].(float64))
c.pacUrl = j["pacUrl"].(string)
c.useOnlinePac = j["useOnlinePac"].(bool)
if *debug {
fmt.Printf("\n---ASSERTED---\n%v\n---\n", j)
}
return
}
if *debug {
fmt.Printf("\n---FAILED---\n%v\n---\n", j)
}
return
}
func fill_server(server string, port_range string, prefix string) []server_setting {
if len(server) == 0 || len(port_range) == 0 || len(prefix) == 0 {
return nil
}
var isvalid bool
var start, end int
if isvalid, start, end = parse(port_range); !isvalid {
return nil
}
var result []server_setting = make([]server_setting, end-start+1)
for i := 0; i <= end-start; i++ {
result[i] = server_setting{
server,
start + i,
"zhujiceping.com",
"aes-256-cfb",
prefix, /* + "//" + server + ":" + strconv.Itoa(start+i)*/
}
}
return result
}
func parse(port_range string) (isvalid bool, start int, end int) {
if len(port_range) == 0 {
return false, 0, 0
}
isvalid = false
var e error
if strings.Contains(port_range, "-") {
parts := strings.SplitN(port_range, "-", 2)
start, e = strconv.Atoi(parts[0])
if start < 1 || e != nil {
return false, 0, 0
}
end, e = strconv.Atoi(parts[1])
if end < 1 || end < start || e != nil {
return false, 0, 0
}
isvalid = true
} else if start, e = strconv.Atoi(port_range); e == nil && start > 0 {
isvalid = true
end = start
} else {
return false, 0, 0
}
return isvalid, start, end
}
func fill_server_group(servers []string, port_range string, prefix string) [][]server_setting {
var result [][]server_setting
for _, s := range servers {
result = append(result, fill_server(s, port_range, prefix))
}
return result
}
var debug *bool
var usages string = `
usage:
go run add_servers.go -s SERVER_IP -p SERVER_PORT -c COMMENT
-s server or server group. example: 1.2.3.4 or 1.2.3.4-20
-p port or port range. example: 80 or 8000-8080
-c comment for server, i.e. server name
`
func main() {
debug = flag.Bool("d", false, "debug")
server := flag.String("s", "", "1.2.3.4 or 1.2.3.4-20")
ports := flag.String("p", "", "80 or 80-8000")
comment := flag.String("c", "", "comment for this server (group)")
flag.Parse()
if len(*server) == 0 || len(*ports) == 0 || len(*comment) == 0 {
if *debug {
fmt.Printf("s:", *server)
fmt.Printf("p:", *ports)
fmt.Printf("c:", *comment)
}
fmt.Println(usages)
os.Exit(1)
}
data, err := ioutil.ReadFile("gui-config.json")
if err != nil {
fmt.Println("error reading gui-config.json: %v", err)
}
if *debug {
fmt.Printf("read file %v bytes\n", len(data))
}
var guiConfig configStruct
if err := guiConfig.UnmarshalJSON(data); err != nil {
panic(err)
}
if *debug {
fmt.Printf("loaded %d configs\n", len(guiConfig.server_configs))
fmt.Println("--------- this is what i've read ------------")
fmt.Printf("%v\n\n\n\n", guiConfig)
}
if strings.Contains(*server, "-") {
var bundles []string
parts := strings.SplitN(*server, ".", 4)
if *debug {
fmt.Printf("parts are: %v\n", parts)
}
if ok, s, e := parse(parts[3]); ok {
for i := 0; i <= e-s; i++ {
bundles = append(bundles, join_ip(parts[0], parts[1], parts[2], strconv.Itoa(s+i)))
}
}
if *debug {
fmt.Printf("bundles are: %v \n", bundles)
}
server_groups := fill_server_group(bundles, *ports, *comment)
for _, s := range server_groups {
guiConfig.server_configs = append(guiConfig.server_configs, s...)
}
if *debug {
fmt.Printf("now configs are %d \n", len(guiConfig.server_configs))
}
} else {
guiConfig.server_configs = append(guiConfig.server_configs, fill_server(*server, *ports, *comment)...)
}
file, err := os.OpenFile("gui-config.json", os.O_RDWR, 0666)
if err != nil {
panic(err)
}
var output []byte
if *debug {
output, _ = guiConfig.server_configs[0].MarshalJSON()
fmt.Printf("debug marshalling server_configs[0]: the original object is %v (of %q); and marshaled object is %v. \n", guiConfig.server_configs[0], reflect.TypeOf(guiConfig.server_configs[0]), string(output))
output, _ = json.Marshal(guiConfig.server_configs)
fmt.Printf("debug marshalling []server_configs: %v\n", string(output))
}
output, _ = guiConfig.MarshalJSON()
if *debug {
fmt.Printf("ready to write %d bytes \n", len(output))
fmt.Printf("\n\n the intended output is \n\n %v \n", string(output))
}
if len(output) < len(guiConfig.server_configs) {
panic("there is no way that the length of marshalled output is even smalller than number of configs in the struct")
}
// need to clear file content first, to avoid under-patching
n, err := file.Write(output)
if err != nil {
fmt.Printf("error on write: %v", err)
os.Exit(1)
}
if n < len(output) {
fmt.Printf("why only %d written? \n", n)
}
}
func join_ip(a, b, c, d string) string {
sep := "."
return a + sep + b + sep + c + sep + d
}
package main
import (
"testing"
)
type parse_tc_expected struct {
valid bool
start int
end int
}
type parse_tc_struct struct {
tc_input string
tc_expected parse_tc_expected
}
var test_cases []parse_tc_struct = []parse_tc_struct{
{
"0-0",
parse_tc_expected{
valid: false,
start: 0,
end: 0,
},
},
{
"123456",
parse_tc_expected{
true,
123456,
123456,
},
},
{
"abcdedf",
parse_tc_expected{
false,
0,
0,
},
},
{
"ab-cd",
parse_tc_expected{
false,
0,
0,
},
},
{
"12-34",
parse_tc_expected{
true,
12,
34,
},
},
{
"1-1",
parse_tc_expected{
true,
1,
1,
},
},
{
"34-12",
parse_tc_expected{
false,
0,
0,
},
},
}
func TestParse(t *testing.T) {
for _, tc := range test_cases {
v, s, e := parse(tc.tc_input)
if v != tc.tc_expected.valid {
t.Errorf("isValid error, tc \"%v\", got %v\n", tc.tc_input, v)
}
if s != tc.tc_expected.start {
t.Errorf("start error, tc %q, got %v\n", tc.tc_input, s)
}
if e != tc.tc_expected.end {
t.Errorf("end error, tc %q, got %v\n", tc.tc_input, e)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment