forked from x/icebergs
add tcp.server
This commit is contained in:
parent
fc6517d83f
commit
76fce2d013
@ -16,8 +16,6 @@ const ( // 角色操作
|
||||
White = "white"
|
||||
Black = "black"
|
||||
Right = "right"
|
||||
Prune = "prune"
|
||||
Clear = "clear"
|
||||
)
|
||||
const ( // 返回结果
|
||||
OK = "ok"
|
||||
|
@ -147,7 +147,7 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
|
||||
}
|
||||
})
|
||||
case "ifconfig":
|
||||
m.Cmdy("tcp.ip")
|
||||
m.Cmdy("tcp.host")
|
||||
case "userinfo":
|
||||
m.Split(m.Cmdx(SYSTEM, "who"), "user term time", " ", "\n")
|
||||
|
||||
|
@ -34,10 +34,10 @@ func _daemon_show(m *ice.Message, cmd *exec.Cmd, out, err string) {
|
||||
|
||||
h := m.Rich(DAEMON, nil, kit.Dict(
|
||||
kit.MDB_TYPE, "shell", kit.MDB_NAME, strings.Join(cmd.Args, " "),
|
||||
kit.MDB_DIR, cmd.Dir, kit.MDB_PID, cmd.Process.Pid, kit.MDB_STATUS, StatusStart,
|
||||
kit.SSH_DIR, cmd.Dir, kit.SSH_PID, cmd.Process.Pid, kit.MDB_STATUS, StatusStart,
|
||||
kit.MDB_EXTRA, kit.Dict(CMD_STDOUT, out, CMD_STDERR, err),
|
||||
))
|
||||
m.Log_EXPORT(kit.MDB_META, DAEMON, kit.MDB_KEY, h, kit.MDB_PID, cmd.Process.Pid)
|
||||
m.Log_EXPORT(kit.MDB_META, DAEMON, kit.MDB_KEY, h, kit.SSH_PID, cmd.Process.Pid)
|
||||
m.Echo("%d", cmd.Process.Pid)
|
||||
|
||||
m.Gos(m, func(m *ice.Message) {
|
||||
@ -73,7 +73,7 @@ func init() {
|
||||
}},
|
||||
"prune": {Name: "prune", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Richs(DAEMON, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
|
||||
if value["status"] == "error" || strings.Count(m.Cmdx(SYSTEM, "ps", value[kit.MDB_PID]), "\n") == 1 {
|
||||
if value["status"] == "error" || strings.Count(m.Cmdx(SYSTEM, "ps", value[kit.SSH_PID]), "\n") == 1 {
|
||||
m.Conf(DAEMON, kit.Keys(kit.MDB_HASH, key), "")
|
||||
m.Log_DELETE(DAEMON, kit.Format(value))
|
||||
}
|
||||
@ -81,8 +81,8 @@ func init() {
|
||||
}},
|
||||
"stop": {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Richs(DAEMON, "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) {
|
||||
m.Cmdy(SYSTEM, "kill", "-9", value[kit.MDB_PID])
|
||||
if strings.Count(m.Cmdx(SYSTEM, "ps", value[kit.MDB_PID]), "\n") == 1 {
|
||||
m.Cmdy(SYSTEM, "kill", "-9", value[kit.SSH_PID])
|
||||
if strings.Count(m.Cmdx(SYSTEM, "ps", value[kit.SSH_PID]), "\n") == 1 {
|
||||
value[kit.MDB_STATUS] = StatusClose
|
||||
}
|
||||
})
|
||||
|
@ -248,17 +248,32 @@ func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
|
||||
}
|
||||
|
||||
func _zone_select(m *ice.Message, prefix, chain, zone string, id string) {
|
||||
cb := m.Optionv("cache.cb")
|
||||
fields := kit.Split(kit.Select("zone,id,time,type,name,text", m.Option(FIELDS)))
|
||||
m.Richs(prefix, chain, kit.Select(kit.MDB_FOREACH, zone), func(key string, val map[string]interface{}) {
|
||||
if val[kit.MDB_META] != nil {
|
||||
val = val[kit.MDB_META].(map[string]interface{})
|
||||
}
|
||||
if zone == "" {
|
||||
m.Push(key, val, fields)
|
||||
return
|
||||
}
|
||||
|
||||
m.Grows(prefix, kit.Keys(chain, kit.MDB_HASH, key), kit.MDB_ID, id, func(index int, value map[string]interface{}) {
|
||||
if value[kit.MDB_META] != nil {
|
||||
value = value[kit.MDB_META].(map[string]interface{})
|
||||
}
|
||||
|
||||
m.Push(zone, value, fields, val)
|
||||
switch cb := cb.(type) {
|
||||
case func(string, map[string]interface{}, map[string]interface{}):
|
||||
cb(key, value, val)
|
||||
default:
|
||||
if len(fields) == 1 && fields[0] == DETAIL {
|
||||
m.Push(DETAIL, value)
|
||||
break
|
||||
}
|
||||
m.Push(key, value, fields, val)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@ -450,7 +465,7 @@ var Index = &ice.Context{Name: "mdb", Help: "数据模块",
|
||||
|
||||
func init() {
|
||||
ice.Index.Register(Index, nil,
|
||||
INSERT, DELETE, SELECT, MODIFY,
|
||||
INSERT, DELETE, MODIFY, SELECT,
|
||||
EXPORT, IMPORT, PRUNES, INPUTS,
|
||||
PLUGIN, RENDER, SEARCH, ENGINE,
|
||||
)
|
||||
|
71
base/ssh/_trash.go
Normal file
71
base/ssh/_trash.go
Normal file
@ -0,0 +1,71 @@
|
||||
package ssh
|
||||
|
||||
func (f *Frame) history(m *ice.Message, line string) string {
|
||||
favor := m.Conf(SOURCE, kit.Keys(kit.MDB_META, web.FAVOR))
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "!!") {
|
||||
if len(line) == 2 {
|
||||
line = m.Cmd(web.FAVOR, favor).Append(kit.MDB_TEXT)
|
||||
}
|
||||
} else if strings.HasPrefix(strings.TrimSpace(line), "!") {
|
||||
if len(line) == 1 {
|
||||
// 历史记录
|
||||
msg := m.Cmd(web.FAVOR, favor)
|
||||
msg.Sort(kit.MDB_ID)
|
||||
msg.Appendv(ice.MSG_APPEND, kit.MDB_TIME, kit.MDB_ID, kit.MDB_TEXT)
|
||||
f.printf(m, msg.Table().Result())
|
||||
return ""
|
||||
}
|
||||
if i, e := strconv.Atoi(line[1:]); e == nil {
|
||||
// 历史命令
|
||||
line = kit.Format(kit.Value(m.Cmd(web.FAVOR, favor, i).Optionv("value"), kit.MDB_TEXT))
|
||||
} else {
|
||||
f.printf(m, m.Cmd("history", "search", line[1:]).Table().Result())
|
||||
return ""
|
||||
}
|
||||
} else if strings.TrimSpace(line) != "" && f.source == STDIO {
|
||||
// 记录历史
|
||||
m.Cmd(web.FAVOR, favor, "cmd", f.source, line)
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
const (
|
||||
REMOTE = "remote"
|
||||
QRCODE = "qrcode"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{
|
||||
Configs: map[string]*ice.Config{
|
||||
REMOTE: {Name: "remote", Help: "远程连接", Value: kit.Data()},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
|
||||
QRCODE: {Name: "qrcode arg...", Help: "命令提示", Action: map[string]*ice.Action{
|
||||
"json": {Name: "json [key val]...", Help: "json", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(cli.PYTHON, QRCODE, kit.Format(kit.Parse(nil, "", arg...)))
|
||||
m.Render(ice.RENDER_RESULT)
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Cmdy(cli.PYTHON, QRCODE, strings.Join(arg, ""))
|
||||
m.Render(ice.RENDER_RESULT)
|
||||
}},
|
||||
REMOTE: {Name: "remote user remote port local", Help: "远程连接", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
key := m.Rich(REMOTE, nil, kit.Dict(
|
||||
"user", arg[0], "remote", arg[1], "port", arg[2], "local", arg[3],
|
||||
))
|
||||
m.Echo(key)
|
||||
m.Info(key)
|
||||
|
||||
m.Gos(m, func(m *ice.Message) {
|
||||
for {
|
||||
m.Cmd(cli.SYSTEM, "ssh", "-CNR", kit.Format("%s:%s:22", arg[2], kit.Select("localhost", arg, 3)),
|
||||
kit.Format("%s@%s", arg[0], arg[1]))
|
||||
m.Info("reconnect after 10s")
|
||||
time.Sleep(time.Second * 10)
|
||||
}
|
||||
})
|
||||
}},
|
||||
},
|
||||
}, nil)
|
||||
}
|
@ -184,17 +184,12 @@ func _ssh_handle(m *ice.Message, meta map[string]string, c net.Conn, channel ssh
|
||||
request.Reply(true, nil)
|
||||
}
|
||||
}
|
||||
func _ssh_listen(m *ice.Message, hostport string) {
|
||||
func _ssh_listen(m *ice.Message, l net.Listener, hostport string) {
|
||||
h := m.Cmdx(mdb.INSERT, m.Prefix(LISTEN), "", mdb.HASH, aaa.HOSTPORT, hostport, kit.MDB_STATUS, "listen")
|
||||
defer m.Cmd(mdb.MODIFY, m.Prefix(LISTEN), "", mdb.HASH, kit.MDB_HASH, h, kit.MDB_STATUS, "close")
|
||||
|
||||
config := _ssh_config(m)
|
||||
|
||||
l, e := net.Listen("tcp", hostport)
|
||||
m.Assert(e)
|
||||
defer l.Close()
|
||||
m.Logs(LISTEN, ADDRESS, l.Addr())
|
||||
|
||||
for {
|
||||
c, e := l.Accept()
|
||||
if m.Warn(e != nil, e) {
|
||||
@ -248,7 +243,7 @@ func _ssh_config(m *ice.Message) *ssh.ServerConfig {
|
||||
},
|
||||
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
|
||||
meta, res := map[string]string{"username": conn.User()}, errors.New(ice.ErrNotAuth)
|
||||
if tcp.IPIsLocal(m, strings.Split(conn.RemoteAddr().String(), ":")[0]) {
|
||||
if tcp.IsLocalHost(m, strings.Split(conn.RemoteAddr().String(), ":")[0]) {
|
||||
m.Log_AUTH(aaa.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
|
||||
res = nil
|
||||
} else {
|
||||
@ -382,8 +377,13 @@ func init() {
|
||||
}},
|
||||
|
||||
LISTEN: {Name: "listen hash=auto auto", Help: "服务", Action: map[string]*ice.Action{
|
||||
mdb.CREATE: {Name: "create port=9030", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Gos(m, func(m *ice.Message) { _ssh_listen(m, ":"+m.Option("port")) })
|
||||
mdb.CREATE: {Name: "create name=tcp port=9030", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(tcp.LISTEN_CB, func(l net.Listener) {
|
||||
_ssh_listen(m, l, ":"+m.Option("port"))
|
||||
})
|
||||
m.Gos(m, func(m *ice.Message) {
|
||||
m.Cmdy(tcp.SERVER, tcp.LISTEN, kit.MDB_NAME, "ssh", tcp.PORT, m.Option(tcp.PORT))
|
||||
})
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
if m.Option(mdb.FIELDS, m.Conf(LISTEN, kit.META_FIELD)); len(arg) > 0 {
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
"github.com/shylinux/icebergs/base/aaa"
|
||||
"github.com/shylinux/icebergs/base/cli"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
"github.com/shylinux/icebergs/base/web"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"bufio"
|
||||
@ -14,48 +13,33 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Frame struct {
|
||||
source string
|
||||
target *ice.Context
|
||||
stdout io.Writer
|
||||
|
||||
count int
|
||||
ps1 []string
|
||||
ps2 []string
|
||||
|
||||
exit bool
|
||||
}
|
||||
|
||||
func Render(msg *ice.Message, cmd string, args ...interface{}) {
|
||||
defer func() { msg.Log_EXPORT(mdb.RENDER, cmd, kit.MDB_TEXT, args) }()
|
||||
|
||||
switch arg := kit.Simple(args...); cmd {
|
||||
case ice.RENDER_OUTPUT:
|
||||
|
||||
case ice.RENDER_DOWNLOAD:
|
||||
os.Link(kit.Select(path.Base(arg[0]), arg, 2), arg[0])
|
||||
|
||||
case ice.RENDER_VOID:
|
||||
case ice.RENDER_RESULT:
|
||||
fmt.Fprintf(msg.O, msg.Result())
|
||||
|
||||
case ice.RENDER_QRCODE:
|
||||
if len(args) > 0 {
|
||||
fmt.Println(msg.Cmdx("cli.python", "qrcode", kit.Format(args[0], args[1:]...)))
|
||||
} else {
|
||||
fmt.Println(msg.Cmdx("cli.python", "qrcode", kit.Format(kit.Dict(
|
||||
kit.MDB_TYPE, "cmd", kit.MDB_NAME, msg.Option("_cmd"), kit.MDB_TEXT, strings.TrimSpace(msg.Result()),
|
||||
))))
|
||||
fmt.Fprintf(msg.O, msg.Cmdx(cli.PYTHON, "qrcode", kit.Format(args[0], args[1:]...)))
|
||||
|
||||
case ice.RENDER_DOWNLOAD:
|
||||
if f, e := os.Open(arg[0]); e == nil {
|
||||
defer f.Close()
|
||||
|
||||
io.Copy(msg.O, f)
|
||||
}
|
||||
|
||||
default:
|
||||
// 转换结果
|
||||
res := msg.Result()
|
||||
if res == "" {
|
||||
res = msg.Table(nil).Result()
|
||||
res = msg.Table().Result()
|
||||
}
|
||||
args = append(args, "length:", len(res))
|
||||
|
||||
@ -64,9 +48,13 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) {
|
||||
fmt.Fprintf(msg.O, "\n")
|
||||
}
|
||||
}
|
||||
msg.Append(ice.MSG_OUTPUT, ice.RENDER_OUTPUT)
|
||||
}
|
||||
func _ssh_script(m *ice.Message, name string) io.Reader {
|
||||
func Script(m *ice.Message, name string) io.Reader {
|
||||
if b, ok := ice.BinPack[name]; ok {
|
||||
m.Debug("binpack %v %v", len(b), name)
|
||||
return bytes.NewReader(b)
|
||||
}
|
||||
|
||||
if strings.Contains(m.Option("_script"), "/") {
|
||||
name = path.Join(path.Dir(m.Option("_script")), name)
|
||||
}
|
||||
@ -95,42 +83,19 @@ func _ssh_script(m *ice.Message, name string) io.Reader {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (f *Frame) history(m *ice.Message, line string) string {
|
||||
favor := m.Conf(SOURCE, kit.Keys(kit.MDB_META, web.FAVOR))
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "!!") {
|
||||
if len(line) == 2 {
|
||||
line = m.Cmd(web.FAVOR, favor).Append(kit.MDB_TEXT)
|
||||
}
|
||||
} else if strings.HasPrefix(strings.TrimSpace(line), "!") {
|
||||
if len(line) == 1 {
|
||||
// 历史记录
|
||||
msg := m.Cmd(web.FAVOR, favor)
|
||||
msg.Sort(kit.MDB_ID)
|
||||
msg.Appendv(ice.MSG_APPEND, kit.MDB_TIME, kit.MDB_ID, kit.MDB_TEXT)
|
||||
f.printf(m, msg.Table().Result())
|
||||
return ""
|
||||
}
|
||||
if i, e := strconv.Atoi(line[1:]); e == nil {
|
||||
// 历史命令
|
||||
line = kit.Format(kit.Value(m.Cmd(web.FAVOR, favor, i).Optionv("value"), kit.MDB_TEXT))
|
||||
} else {
|
||||
f.printf(m, m.Cmd("history", "search", line[1:]).Table().Result())
|
||||
return ""
|
||||
}
|
||||
} else if strings.TrimSpace(line) != "" && f.source == STDIO {
|
||||
// 记录历史
|
||||
m.Cmd(web.FAVOR, favor, "cmd", f.source, line)
|
||||
}
|
||||
return line
|
||||
}
|
||||
func (f *Frame) printf(m *ice.Message, res string, arg ...interface{}) *Frame {
|
||||
if len(arg) > 0 {
|
||||
fmt.Fprintf(f.stdout, res, arg...)
|
||||
} else {
|
||||
fmt.Fprint(f.stdout, res)
|
||||
}
|
||||
return f
|
||||
|
||||
type Frame struct {
|
||||
source string
|
||||
target *ice.Context
|
||||
stdout io.Writer
|
||||
|
||||
count int
|
||||
ps1 []string
|
||||
ps2 []string
|
||||
|
||||
exit bool
|
||||
}
|
||||
|
||||
func (f *Frame) prompt(m *ice.Message, list ...string) *Frame {
|
||||
if f.source != STDIO {
|
||||
return f
|
||||
@ -143,7 +108,7 @@ func (f *Frame) prompt(m *ice.Message, list ...string) *Frame {
|
||||
for _, v := range list {
|
||||
switch v {
|
||||
case "count":
|
||||
fmt.Fprintf(f.stdout, "%d", kit.Int(m.Conf("history", "meta.count"))+1)
|
||||
fmt.Fprintf(f.stdout, "%d", f.count+1)
|
||||
case "time":
|
||||
fmt.Fprintf(f.stdout, time.Now().Format("15:04:05"))
|
||||
case "target":
|
||||
@ -154,21 +119,30 @@ func (f *Frame) prompt(m *ice.Message, list ...string) *Frame {
|
||||
}
|
||||
return f
|
||||
}
|
||||
func (f *Frame) printf(m *ice.Message, res string, arg ...interface{}) *Frame {
|
||||
if len(arg) > 0 {
|
||||
fmt.Fprintf(f.stdout, res, arg...)
|
||||
} else {
|
||||
fmt.Fprint(f.stdout, res)
|
||||
}
|
||||
return f
|
||||
}
|
||||
func (f *Frame) option(m *ice.Message, ls []string) []string {
|
||||
// 解析选项
|
||||
ln := []string{}
|
||||
m.Option("cache.limit", 10)
|
||||
for i := 0; i < len(ls); i++ {
|
||||
if ls[i] == "--" {
|
||||
ln = append(ln, ls[i+1:]...)
|
||||
break
|
||||
} else if strings.HasPrefix(ls[i], "-") {
|
||||
}
|
||||
|
||||
if strings.HasPrefix(ls[i], "-") {
|
||||
for j := i; j < len(ls); j++ {
|
||||
if j == len(ls)-1 || strings.HasPrefix(ls[j+1], "-") {
|
||||
if i == j {
|
||||
m.Option(ls[i][1:], "true")
|
||||
} else {
|
||||
if i < j {
|
||||
m.Option(ls[i][1:], ls[i+1:j+1])
|
||||
} else {
|
||||
m.Option(ls[i][1:], "true")
|
||||
}
|
||||
i = j
|
||||
break
|
||||
@ -201,7 +175,6 @@ func (f *Frame) change(m *ice.Message, ls []string) []string {
|
||||
return ls
|
||||
}
|
||||
func (f *Frame) alias(m *ice.Message, ls []string) []string {
|
||||
// 命令替换
|
||||
if alias, ok := m.Optionv(ice.MSG_ALIAS).(map[string]interface{}); ok {
|
||||
if len(ls) > 0 {
|
||||
if a := kit.Simple(alias[ls[0]]); len(a) > 0 {
|
||||
@ -212,26 +185,23 @@ func (f *Frame) alias(m *ice.Message, ls []string) []string {
|
||||
return ls
|
||||
}
|
||||
func (f *Frame) parse(m *ice.Message, line string) string {
|
||||
if strings.HasPrefix(line, "<") {
|
||||
fmt.Fprintf(m.O, line)
|
||||
return ""
|
||||
}
|
||||
|
||||
for _, one := range kit.Split(line, ";", ";", ";") {
|
||||
m.Log_IMPORT("stdin", one, "length", len(one))
|
||||
|
||||
async, one := false, strings.TrimSpace(one)
|
||||
if strings.TrimSuffix(one, "&") != one {
|
||||
async, one = true, strings.TrimSuffix(one, "&")
|
||||
}
|
||||
|
||||
ls := kit.Split(one)
|
||||
if m.Option("scan_mode") == "scan" {
|
||||
f.printf(m, ls[0])
|
||||
f.printf(m, "`")
|
||||
f.printf(m, strings.Join(ls[1:], "` `"))
|
||||
f.printf(m, "`")
|
||||
f.printf(m, "\n")
|
||||
continue
|
||||
}
|
||||
|
||||
// 解析引擎
|
||||
msg := m.Spawns(f.target)
|
||||
msg.Option("_cmd", one)
|
||||
|
||||
ls := kit.Split(one)
|
||||
ls = f.alias(msg, ls)
|
||||
ls = f.change(msg, ls)
|
||||
ls = f.option(msg, ls)
|
||||
@ -240,15 +210,15 @@ func (f *Frame) parse(m *ice.Message, line string) string {
|
||||
}
|
||||
|
||||
if async {
|
||||
m.Debug("async %v", ls)
|
||||
go msg.Cmd(ls[0], ls[1:])
|
||||
msg.Gos(msg, func(msg *ice.Message) { msg.Cmd(ls[0], ls[1:]) })
|
||||
continue
|
||||
} else {
|
||||
msg.Cmdy(ls[0], ls[1:])
|
||||
}
|
||||
|
||||
if strings.HasPrefix(line, "<") {
|
||||
msg.Resultv(line)
|
||||
} else if msg.Cmdy(ls[0], ls[1:]); strings.HasPrefix(msg.Result(), "warn: ") && m.Option("render") == "raw" {
|
||||
msg.Resultv(line)
|
||||
if strings.HasPrefix(msg.Result(), ice.ErrWarn) && m.Option("render") == "raw" {
|
||||
fmt.Fprintf(msg.O, line)
|
||||
continue
|
||||
}
|
||||
|
||||
// 渲染引擎
|
||||
@ -257,7 +227,7 @@ func (f *Frame) parse(m *ice.Message, line string) string {
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func (f *Frame) scan(m *ice.Message, file, line string, r io.Reader) *Frame {
|
||||
func (f *Frame) scan(m *ice.Message, line string, r io.Reader) *Frame {
|
||||
m.Option("ssh.return", func() { f.exit = true })
|
||||
f.ps1 = kit.Simple(m.Confv("prompt", "meta.PS1"))
|
||||
f.ps2 = kit.Simple(m.Confv("prompt", "meta.PS2"))
|
||||
@ -267,30 +237,26 @@ func (f *Frame) scan(m *ice.Message, file, line string, r io.Reader) *Frame {
|
||||
bio := bufio.NewScanner(r)
|
||||
for f.prompt(m, ps...); bio.Scan() && !f.exit; f.prompt(m, ps...) {
|
||||
if len(bio.Text()) == 0 {
|
||||
// 空行
|
||||
continue
|
||||
continue // 空行
|
||||
}
|
||||
if strings.HasSuffix(bio.Text(), "\\") {
|
||||
// 续行
|
||||
line += bio.Text()[:len(bio.Text())-1]
|
||||
ps = f.ps2
|
||||
continue
|
||||
continue // 续行
|
||||
}
|
||||
if line += bio.Text(); strings.Count(line, "`")%2 == 1 {
|
||||
// 多行
|
||||
line += "\n"
|
||||
ps = f.ps2
|
||||
continue
|
||||
continue // 多行
|
||||
}
|
||||
if strings.HasPrefix(strings.TrimSpace(line), "#") {
|
||||
// 注释
|
||||
line = ""
|
||||
continue
|
||||
}
|
||||
if line = f.history(m, line); line == "" {
|
||||
// 历史命令
|
||||
continue
|
||||
continue // 注释
|
||||
}
|
||||
// if line = f.history(m, line); line == "" {
|
||||
// // 历史命令
|
||||
// continue
|
||||
// }
|
||||
if ps = f.ps1; f.stdout == os.Stdout {
|
||||
// 清空格式
|
||||
f.printf(m, "\033[0m")
|
||||
@ -307,82 +273,62 @@ func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server
|
||||
return &Frame{}
|
||||
}
|
||||
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
f.source, f.target = kit.Select(STDIO, arg, 0), m.Target()
|
||||
|
||||
var r io.Reader
|
||||
switch kit.Select(STDIO, arg, 0) {
|
||||
case STDIO:
|
||||
// 终端交互
|
||||
f.source = STDIO
|
||||
switch m.Cap(ice.CTX_STREAM, f.source) {
|
||||
case STDIO: // 终端交互
|
||||
r, f.stdout = os.Stdin, os.Stdout
|
||||
m.Cap(ice.CTX_STREAM, STDIO)
|
||||
f.target = m.Target()
|
||||
|
||||
m.Option("_option", ice.MSG_USERNAME)
|
||||
m.Option(ice.MSG_USERNAME, cli.UserName)
|
||||
m.Option(ice.MSG_USERROLE, aaa.ROOT)
|
||||
m.Option(ice.MSG_USERZONE, "boot")
|
||||
aaa.UserRoot(m)
|
||||
default:
|
||||
if strings.HasPrefix(arg[0], "/dev") {
|
||||
// 脚本解析
|
||||
f.target = m.Source()
|
||||
|
||||
if strings.HasPrefix(f.source, "/dev") {
|
||||
r, f.stdout = m.I, m.O
|
||||
f.source, f.target = STDIO, m.Source()
|
||||
m.Cap(ice.CTX_STREAM, STDIO)
|
||||
break
|
||||
}
|
||||
if b, ok := ice.BinPack[arg[0]]; ok {
|
||||
m.Debug("binpack %v %v", arg[0], len(b))
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 4096))
|
||||
defer func() { m.Echo(buf.String()) }()
|
||||
|
||||
// 脚本解析
|
||||
f.source = arg[0]
|
||||
r, f.stdout = bytes.NewReader(b), buf
|
||||
m.Cap(ice.CTX_STREAM, arg[0])
|
||||
f.target = m.Source()
|
||||
break
|
||||
}
|
||||
|
||||
s := _ssh_script(m, arg[0])
|
||||
if s == nil {
|
||||
return true
|
||||
}
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 4096))
|
||||
defer func() { m.Echo(buf.String()) }()
|
||||
|
||||
// 脚本解析
|
||||
r, f.stdout = s, buf
|
||||
f.source, f.target = arg[0], m.Source()
|
||||
m.Cap(ice.CTX_STREAM, arg[0])
|
||||
if s := Script(m, f.source); s != nil {
|
||||
r, f.stdout = s, buf
|
||||
break
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
f.scan(m, kit.Select(STDIO, arg, 0), "", r)
|
||||
f.scan(m, "", r)
|
||||
return true
|
||||
}
|
||||
func (f *Frame) Close(m *ice.Message, arg ...string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
const (
|
||||
STDIO = "stdio"
|
||||
)
|
||||
const (
|
||||
SOURCE = "source"
|
||||
TARGET = "target"
|
||||
PROMPT = "prompt"
|
||||
QRCODE = "qrcode"
|
||||
RETURN = "return"
|
||||
REMOTE = "remote"
|
||||
)
|
||||
const (
|
||||
STDIO = "stdio"
|
||||
)
|
||||
const SSH = "ssh"
|
||||
|
||||
var Index = &ice.Context{Name: "ssh", Help: "终端模块",
|
||||
var Index = &ice.Context{Name: SSH, Help: "终端模块",
|
||||
Configs: map[string]*ice.Config{
|
||||
SOURCE: {Name: "prompt", Help: "命令提示", Value: kit.Data(
|
||||
web.FAVOR, "cmd.history",
|
||||
)},
|
||||
PROMPT: {Name: "prompt", Help: "命令提示", Value: kit.Data(
|
||||
SOURCE: {Name: SOURCE, Help: "加载脚本", Value: kit.Data()},
|
||||
PROMPT: {Name: PROMPT, Help: "命令提示", Value: kit.Data(
|
||||
"PS1", []interface{}{"\033[33;44m", "count", "[", "time", "]", "\033[5m", "target", "\033[0m", "\033[44m", ">", "\033[0m ", "\033[?25h", "\033[32m"},
|
||||
"PS2", []interface{}{"count", " ", "target", "> "},
|
||||
)},
|
||||
REMOTE: {Name: "remote", Help: "远程连接", Value: kit.Data()},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Load() }},
|
||||
@ -410,46 +356,13 @@ var Index = &ice.Context{Name: "ssh", Help: "终端模块",
|
||||
f.ps1 = arg
|
||||
f.prompt(m)
|
||||
}},
|
||||
QRCODE: {Name: "qrcode arg...", Help: "命令提示", Action: map[string]*ice.Action{
|
||||
"json": {Name: "json [key val]...", Help: "json", Hand: func(m *ice.Message, arg ...string) {
|
||||
val := map[string]interface{}{}
|
||||
for i := 0; i < len(arg)-1; i += 2 {
|
||||
kit.Value(val, arg[i], arg[i+1])
|
||||
}
|
||||
f := m.Target().Server().(*Frame)
|
||||
f.printf(m, m.Cmdx(cli.PYTHON, "qrcode", kit.Format(val)))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
f := m.Target().Server().(*Frame)
|
||||
f.printf(m, m.Cmdx(cli.PYTHON, "qrcode", strings.Join(arg, "")))
|
||||
}},
|
||||
"what": {Name: "return", Help: "结束脚本", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Echo(kit.MergeURL2(m.Conf(web.SHARE, "meta.domain"), "/chat/lark/sso"))
|
||||
}},
|
||||
RETURN: {Name: "return", Help: "结束脚本", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
switch cb := m.Optionv("ssh.return").(type) {
|
||||
case func():
|
||||
cb()
|
||||
}
|
||||
}},
|
||||
|
||||
REMOTE: {Name: "remote user remote port local", Help: "远程连接", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
key := m.Rich(REMOTE, nil, kit.Dict(
|
||||
"user", arg[0], "remote", arg[1], "port", arg[2], "local", arg[3],
|
||||
))
|
||||
m.Echo(key)
|
||||
m.Info(key)
|
||||
|
||||
m.Gos(m, func(m *ice.Message) {
|
||||
for {
|
||||
m.Cmd(cli.SYSTEM, "ssh", "-CNR", kit.Format("%s:%s:22", arg[2], kit.Select("localhost", arg, 3)),
|
||||
kit.Format("%s@%s", arg[0], arg[1]))
|
||||
m.Info("reconnect after 10s")
|
||||
time.Sleep(time.Second * 10)
|
||||
}
|
||||
})
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, &Frame{}, SOURCE, QRCODE) }
|
||||
func init() { ice.Index.Register(Index, &Frame{}, SOURCE, TARGET, RETURN) }
|
94
base/tcp/_trash.go
Normal file
94
base/tcp/_trash.go
Normal file
@ -0,0 +1,94 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/aaa"
|
||||
"github.com/shylinux/icebergs/base/cli"
|
||||
|
||||
"bufio"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{
|
||||
Commands: map[string]*ice.Command{
|
||||
"server": {Name: "server [tcp4|tcp6|udp4|udp6] addr", Help: "server", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
proto := "tcp4"
|
||||
switch arg[0] {
|
||||
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6":
|
||||
proto, arg = arg[0], arg[1:]
|
||||
}
|
||||
|
||||
if l, e := net.Listen(proto, arg[0]); m.Assert(e) {
|
||||
m.Gos(m, func(m *ice.Message) {
|
||||
// 启动服务
|
||||
m.Logs(ice.LOG_LISTEN, "addr", l.Addr())
|
||||
for {
|
||||
if c, e := l.Accept(); m.Assert(e) {
|
||||
m.Gos(m.Spawns(), func(msg *ice.Message) {
|
||||
// 建立连接
|
||||
msg.Logs(ice.LOG_ACCEPT, "addr", c.RemoteAddr())
|
||||
msg.Option(ice.MSG_USERADDR, c.RemoteAddr())
|
||||
msg.Option(ice.MSG_USERNAME, "")
|
||||
msg.Option(ice.MSG_USERROLE, "")
|
||||
|
||||
switch msg.Cmdx("check", c.RemoteAddr().String()) {
|
||||
case "local":
|
||||
// 本机用户
|
||||
msg.Option(ice.MSG_USERNAME, msg.Conf(cli.RUNTIME, "boot.username"))
|
||||
msg.Option(ice.MSG_USERROLE, msg.Cmdx(aaa.ROLE, "check", msg.Option(ice.MSG_USERNAME)))
|
||||
msg.Logs(ice.LOG_AUTH, "name", msg.Option(ice.MSG_USERNAME), "role", msg.Option(ice.MSG_USERROLE))
|
||||
}
|
||||
|
||||
cmds := []string{}
|
||||
buf := bufio.NewWriter(c)
|
||||
for bio := bufio.NewScanner(c); bio.Scan(); {
|
||||
text := bio.Text()
|
||||
msg.Logs("scan", "len", len(text), "text", text)
|
||||
|
||||
if len(text) == 0 {
|
||||
if len(cmds) > 0 {
|
||||
msg.Cmd(aaa.ROLE, "right")
|
||||
// 执行命令
|
||||
res := msg.Cmd(cmds)
|
||||
|
||||
// 返回结果
|
||||
for _, str := range res.Resultv() {
|
||||
buf.WriteString("result:")
|
||||
buf.WriteString(url.QueryEscape(str))
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
buf.WriteString("\n")
|
||||
buf.Flush()
|
||||
|
||||
cmds = cmds[:0]
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// 解析请求
|
||||
line := strings.SplitN(bio.Text(), ":", 2)
|
||||
line[0], e = url.QueryUnescape(line[0])
|
||||
m.Assert(e)
|
||||
line[1], e = url.QueryUnescape(line[1])
|
||||
m.Assert(e)
|
||||
switch line[0] {
|
||||
case "cmds", ice.MSG_DETAIL:
|
||||
cmds = append(cmds, line[1])
|
||||
default:
|
||||
msg.Option(line[0], line[1])
|
||||
}
|
||||
}
|
||||
msg.Logs(ice.LOG_FINISH, "addr", c.RemoteAddr())
|
||||
})
|
||||
}
|
||||
}
|
||||
m.Logs(ice.LOG_FINISH, "addr", l.Addr())
|
||||
})
|
||||
}
|
||||
}},
|
||||
},
|
||||
}, nil)
|
||||
}
|
66
base/tcp/client.go
Normal file
66
base/tcp/client.go
Normal file
@ -0,0 +1,66 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"net"
|
||||
)
|
||||
|
||||
const (
|
||||
DIAL_CB = "dial.cb"
|
||||
DIAL = "dial"
|
||||
)
|
||||
|
||||
const CLIENT = "client"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{
|
||||
Configs: map[string]*ice.Config{
|
||||
CLIENT: {Name: CLIENT, Help: "客户端", Value: kit.Data()},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
CLIENT: {Name: "client hash auto 连接 清理", Help: "客户端", Action: map[string]*ice.Action{
|
||||
DIAL: {Name: "dial host=localhost port=9010", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
|
||||
c, e := net.Dial(TCP, m.Option(HOST)+":"+m.Option(PORT))
|
||||
h := m.Cmdx(mdb.INSERT, CLIENT, "", mdb.HASH, HOST, m.Option(HOST), PORT, m.Option(PORT), kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
|
||||
|
||||
c = &Conn{h: h, m: m, s: &Stat{}, Conn: c}
|
||||
if e == nil {
|
||||
defer c.Close()
|
||||
}
|
||||
|
||||
switch cb := m.Optionv(DIAL_CB).(type) {
|
||||
case func(net.Conn, error):
|
||||
cb(c, e)
|
||||
case func(net.Conn):
|
||||
m.Assert(e)
|
||||
cb(c)
|
||||
case func(net.Conn, []byte, error):
|
||||
b := make([]byte, 4096)
|
||||
for {
|
||||
n, e := c.Read(b)
|
||||
if cb(c, b[:n], e); e != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
c.Write([]byte("hello world\n"))
|
||||
}
|
||||
}},
|
||||
mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.DELETE, CLIENT, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
|
||||
}},
|
||||
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.PRUNES, CLIENT, "", mdb.HASH, kit.MDB_STATUS, ERROR)
|
||||
m.Cmdy(mdb.PRUNES, CLIENT, "", mdb.HASH, kit.MDB_STATUS, CLOSE)
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Option(mdb.FIELDS, kit.Select(mdb.DETAIL, "time,hash,status,host,port,error,nread,nwrite", len(arg) == 0))
|
||||
m.Cmdy(mdb.SELECT, CLIENT, "", mdb.HASH, kit.MDB_HASH, arg)
|
||||
m.PushAction("删除")
|
||||
}},
|
||||
},
|
||||
}, nil)
|
||||
}
|
86
base/tcp/host.go
Normal file
86
base/tcp/host.go
Normal file
@ -0,0 +1,86 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/aaa"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func _host_list(m *ice.Message, ifname string) {
|
||||
if ifs, e := net.Interfaces(); m.Assert(e) {
|
||||
for _, v := range ifs {
|
||||
if ifname != "" && !strings.Contains(v.Name, ifname) {
|
||||
continue
|
||||
}
|
||||
if len(v.HardwareAddr.String()) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if ips, e := v.Addrs(); m.Assert(e) {
|
||||
for _, x := range ips {
|
||||
ip := strings.Split(x.String(), "/")
|
||||
if strings.Contains(ip[0], ":") || len(ip) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
m.Push("index", v.Index)
|
||||
m.Push("name", v.Name)
|
||||
m.Push("ip", ip[0])
|
||||
m.Push("mask", ip[1])
|
||||
m.Push("hard", v.HardwareAddr.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(m.Appendv("ip")) == 0 {
|
||||
m.Push("index", -1)
|
||||
m.Push("name", "local")
|
||||
m.Push("ip", "127.0.0.1")
|
||||
m.Push("mask", "255.0.0.0")
|
||||
m.Push("hard", "")
|
||||
}
|
||||
}
|
||||
|
||||
func _islocalhost(m *ice.Message, ip string) (ok bool) {
|
||||
if ip == "::1" || strings.HasPrefix(ip, "127.") {
|
||||
return true
|
||||
}
|
||||
if m.Richs(HOST, kit.Keys("meta.black"), ip, nil) != nil {
|
||||
return false
|
||||
}
|
||||
if m.Richs(HOST, kit.Keys("meta.white"), ip, nil) != nil {
|
||||
m.Log_AUTH(aaa.White, ip)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func IsLocalHost(m *ice.Message, ip string) bool { return _islocalhost(m, ip) }
|
||||
|
||||
const HOST = "host"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{
|
||||
Configs: map[string]*ice.Config{
|
||||
HOST: {Name: HOST, Help: "主机", Value: kit.Data(
|
||||
aaa.Black, kit.Dict(kit.MDB_SHORT, kit.MDB_TEXT),
|
||||
aaa.White, kit.Data(kit.MDB_SHORT, kit.MDB_TEXT),
|
||||
)},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
HOST: {Name: "host name auto", Help: "主机", Action: map[string]*ice.Action{
|
||||
aaa.White: {Name: "white", Help: "白名单", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Rich(HOST, kit.Keys("meta.white"), kit.Dict(kit.MDB_NAME, "", kit.MDB_TEXT, arg[0]))
|
||||
}},
|
||||
aaa.Black: {Name: "black", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Rich(HOST, kit.Keys("meta.black"), kit.Dict(kit.MDB_NAME, "", kit.MDB_TEXT, arg[0]))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
_host_list(m, kit.Select("", arg, 0))
|
||||
}},
|
||||
},
|
||||
}, nil)
|
||||
}
|
72
base/tcp/port.go
Normal file
72
base/tcp/port.go
Normal file
@ -0,0 +1,72 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/aaa"
|
||||
"github.com/shylinux/icebergs/base/cli"
|
||||
"github.com/shylinux/icebergs/base/nfs"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
func _port_list(m *ice.Message, port string, dir string) {
|
||||
if m.Cmdy(nfs.DIR, path.Join("var/daemon", port, dir)); port == "" {
|
||||
m.Table(func(index int, value map[string]string, head []string) {
|
||||
m.Push(PORT, path.Base(value["path"]))
|
||||
})
|
||||
}
|
||||
}
|
||||
func _port_right(m *ice.Message, begin string) string {
|
||||
current := kit.Int(kit.Select(m.Conf(PORT, "meta.current"), begin))
|
||||
end := kit.Int(m.Conf(PORT, "meta.end"))
|
||||
if current >= end {
|
||||
current = kit.Int(m.Conf(PORT, "meta.begin"))
|
||||
}
|
||||
|
||||
for i := current; i < end; i++ {
|
||||
if c, e := net.Dial("tcp", kit.Format(":%d", i)); e == nil {
|
||||
m.Info("port exists %v", i)
|
||||
defer c.Close()
|
||||
continue
|
||||
}
|
||||
|
||||
m.Log_SELECT(PORT, i)
|
||||
m.Conf(PORT, "meta.current", i)
|
||||
return kit.Format("%d", i)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
const PORT = "port"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{
|
||||
Configs: map[string]*ice.Config{
|
||||
PORT: {Name: PORT, Help: "端口", Value: kit.Data(
|
||||
"begin", 10000, "current", 10000, "end", 20000,
|
||||
)},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
PORT: {Name: "port port path auto", Help: "端口", Action: map[string]*ice.Action{
|
||||
aaa.Right: {Name: "right [begin]", Help: "分配", Hand: func(m *ice.Message, arg ...string) {
|
||||
port, p := kit.Select("", arg, 0), ""
|
||||
for i := 0; i < 10; i++ {
|
||||
port = _port_right(m, port)
|
||||
p = path.Join(m.Conf(cli.DAEMON, kit.META_PATH), port)
|
||||
if _, e := os.Stat(p); e != nil && os.IsNotExist(e) {
|
||||
os.MkdirAll(p, ice.MOD_DIR)
|
||||
break
|
||||
}
|
||||
port = kit.Format(kit.Int(port) + 1)
|
||||
}
|
||||
m.Echo(port)
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
_port_list(m, kit.Select("", arg, 0), kit.Select("", arg, 1))
|
||||
}},
|
||||
},
|
||||
}, nil)
|
||||
}
|
149
base/tcp/server.go
Normal file
149
base/tcp/server.go
Normal file
@ -0,0 +1,149 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"net"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Stat struct {
|
||||
nc, nr, nw int
|
||||
}
|
||||
|
||||
type Conn struct {
|
||||
h string
|
||||
m *ice.Message
|
||||
s *Stat
|
||||
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (c *Conn) Read(b []byte) (int, error) {
|
||||
n, e := c.Conn.Read(b)
|
||||
c.s.nr += n
|
||||
c.m.Conf(CLIENT, kit.Keys(kit.MDB_HASH, c.h, kit.MDB_META, "nwrite"), c.s.nw)
|
||||
return n, e
|
||||
}
|
||||
func (c *Conn) Write(b []byte) (int, error) {
|
||||
n, e := c.Conn.Write(b)
|
||||
c.s.nw += n
|
||||
c.m.Conf(CLIENT, kit.Keys(kit.MDB_HASH, c.h, kit.MDB_META, "nread"), c.s.nr)
|
||||
return n, e
|
||||
}
|
||||
func (c *Conn) Close() error {
|
||||
c.m.Cmd(mdb.MODIFY, CLIENT, "", mdb.HASH, kit.MDB_HASH, c.h, kit.MDB_STATUS, CLOSE, "nread", c.s.nr, "nwrite", c.s.nw)
|
||||
return c.Conn.Close()
|
||||
}
|
||||
|
||||
type Listener struct {
|
||||
h string
|
||||
m *ice.Message
|
||||
s *Stat
|
||||
|
||||
net.Listener
|
||||
}
|
||||
|
||||
func (l Listener) Accept() (net.Conn, error) {
|
||||
c, e := l.Listener.Accept()
|
||||
l.s.nc += 1
|
||||
l.m.Conf(SERVER, kit.Keys(kit.MDB_HASH, l.h, kit.MDB_META, "nconn"), l.s.nc)
|
||||
|
||||
ls := strings.Split(c.RemoteAddr().String(), ":")
|
||||
if strings.Contains(c.RemoteAddr().String(), "[") {
|
||||
ls = strings.Split(strings.TrimPrefix(c.RemoteAddr().String(), "["), "]:")
|
||||
}
|
||||
h := l.m.Cmdx(mdb.INSERT, CLIENT, "", mdb.HASH, HOST, ls[0], PORT, ls[1], kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
|
||||
|
||||
c = &Conn{h: h, m: l.m, s: &Stat{}, Conn: c}
|
||||
return c, e
|
||||
}
|
||||
func (l Listener) Close() error {
|
||||
l.m.Cmd(mdb.MODIFY, SERVER, "", mdb.HASH, kit.MDB_HASH, l.h, kit.MDB_STATUS, CLOSE)
|
||||
return l.Listener.Close()
|
||||
}
|
||||
|
||||
const (
|
||||
OPEN = "open"
|
||||
CLOSE = "close"
|
||||
ERROR = "error"
|
||||
)
|
||||
const (
|
||||
LISTEN_CB = "listen.cb"
|
||||
LISTEN = "listen"
|
||||
)
|
||||
|
||||
const SERVER = "server"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{
|
||||
Configs: map[string]*ice.Config{
|
||||
SERVER: {Name: SERVER, Help: "服务器", Value: kit.Data()},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
SERVER: {Name: "server hash auto 监听 清理", Help: "服务器", Action: map[string]*ice.Action{
|
||||
LISTEN: {Name: "LISTEN host=localhost port=9010", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
|
||||
l, e := net.Listen(TCP, m.Option(HOST)+":"+m.Option(PORT))
|
||||
h := m.Option(kit.MDB_HASH)
|
||||
if h == "" {
|
||||
h = m.Cmdx(mdb.INSERT, SERVER, "", mdb.HASH, kit.MDB_NAME, m.Option(kit.MDB_NAME), HOST, m.Option(HOST), PORT, m.Option(PORT), kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
|
||||
}
|
||||
|
||||
l = &Listener{h: h, m: m, s: &Stat{}, Listener: l}
|
||||
if e == nil {
|
||||
defer l.Close()
|
||||
}
|
||||
|
||||
switch cb := m.Optionv(LISTEN_CB).(type) {
|
||||
case func(net.Listener, error):
|
||||
cb(l, e)
|
||||
case func(net.Listener):
|
||||
m.Assert(e)
|
||||
cb(l)
|
||||
case func(net.Conn):
|
||||
for {
|
||||
c, e := l.Accept()
|
||||
if cb(c); e != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
case func(net.Conn, error):
|
||||
for {
|
||||
c, e := l.Accept()
|
||||
if cb(c, e); e != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
for {
|
||||
c, e := l.Accept()
|
||||
if e == nil {
|
||||
b := make([]byte, 1024)
|
||||
if n, e := c.Read(b); e == nil {
|
||||
m.Info("nonce", string(b[:n]))
|
||||
c.Write(b[:n])
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
c.Close()
|
||||
}
|
||||
}
|
||||
}},
|
||||
mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.DELETE, SERVER, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
|
||||
}},
|
||||
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.PRUNES, SERVER, "", mdb.HASH, kit.MDB_STATUS, ERROR)
|
||||
m.Cmdy(mdb.PRUNES, SERVER, "", mdb.HASH, kit.MDB_STATUS, CLOSE)
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Option(mdb.FIELDS, kit.Select(mdb.DETAIL, "time,hash,status,name,host,port,error,nconn", len(arg) == 0))
|
||||
m.Cmdy(mdb.SELECT, SERVER, "", mdb.HASH, kit.MDB_HASH, arg)
|
||||
m.PushAction("删除")
|
||||
}},
|
||||
},
|
||||
}, nil)
|
||||
}
|
210
base/tcp/tcp.go
210
base/tcp/tcp.go
@ -1,215 +1,31 @@
|
||||
package tcp
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path"
|
||||
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/aaa"
|
||||
"github.com/shylinux/icebergs/base/cli"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"bufio"
|
||||
"net"
|
||||
"net/url"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func _port_list(m *ice.Message) string {
|
||||
return ""
|
||||
}
|
||||
func _port_get(m *ice.Message, begin string) string {
|
||||
current := kit.Int(kit.Select(m.Conf(PORT, "meta.current"), begin))
|
||||
end := kit.Int(m.Conf(PORT, "meta.end"))
|
||||
if current >= end {
|
||||
current = kit.Int(m.Conf(PORT, "meta.begin"))
|
||||
}
|
||||
for i := current; i < end; i++ {
|
||||
if c, e := net.Dial("tcp", kit.Format(":%d", i)); e == nil {
|
||||
m.Info("port exists %v", i)
|
||||
defer c.Close()
|
||||
continue
|
||||
}
|
||||
m.Conf(PORT, "meta.current", i)
|
||||
m.Log_SELECT(PORT, i)
|
||||
return kit.Format("%d", i)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
const TCP = "tcp"
|
||||
|
||||
func _ip_list(m *ice.Message, ifname string) {
|
||||
if ifs, e := net.Interfaces(); m.Assert(e) {
|
||||
for _, v := range ifs {
|
||||
if ifname != "" && !strings.Contains(v.Name, ifname) {
|
||||
continue
|
||||
}
|
||||
if ips, e := v.Addrs(); m.Assert(e) {
|
||||
for _, x := range ips {
|
||||
ip := strings.Split(x.String(), "/")
|
||||
if strings.Contains(ip[0], ":") || len(ip) == 0 {
|
||||
continue
|
||||
}
|
||||
if len(v.HardwareAddr.String()) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
m.Push("index", v.Index)
|
||||
m.Push("name", v.Name)
|
||||
m.Push("ip", ip[0])
|
||||
m.Push("mask", ip[1])
|
||||
m.Push("hard", v.HardwareAddr.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
func _ip_islocal(m *ice.Message, ip string) (ok bool) {
|
||||
if ip == "::1" || strings.HasPrefix(ip, "127.") {
|
||||
return true
|
||||
}
|
||||
|
||||
if m.Richs(IP, kit.Keys("meta.white"), ip, nil) == nil {
|
||||
return false
|
||||
}
|
||||
m.Log_AUTH(aaa.White, ip)
|
||||
return true
|
||||
}
|
||||
func IPIsLocal(m *ice.Message, ip string) bool {
|
||||
return _ip_islocal(m, ip)
|
||||
}
|
||||
|
||||
const (
|
||||
IP = "ip"
|
||||
PORT = "port"
|
||||
)
|
||||
|
||||
var Index = &ice.Context{Name: "tcp", Help: "通信模块",
|
||||
Configs: map[string]*ice.Config{
|
||||
PORT: {Name: "port", Help: "端口", Value: kit.Data(
|
||||
"begin", 10000, "current", 10000, "end", 20000,
|
||||
)},
|
||||
IP: {Name: "ip", Help: "地址", Value: kit.Data(
|
||||
"black", kit.Dict(),
|
||||
"white", kit.Data(kit.MDB_SHORT, kit.MDB_TEXT),
|
||||
)},
|
||||
},
|
||||
var Index = &ice.Context{Name: TCP, Help: "通信模块",
|
||||
Commands: map[string]*ice.Command{
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Load()
|
||||
m.Cmd(IP).Table(func(index int, value map[string]string, head []string) {
|
||||
m.Cmd(IP, aaa.White, value[IP])
|
||||
m.Cmd(HOST).Table(func(index int, value map[string]string, head []string) {
|
||||
m.Cmd(HOST, aaa.White, value["ip"])
|
||||
})
|
||||
|
||||
}},
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Save(PORT) }},
|
||||
|
||||
IP: {Name: "ip", Help: "地址", Action: map[string]*ice.Action{
|
||||
aaa.White: {Name: "show ip", Help: "白名单", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Rich(IP, kit.Keys("meta.white"), kit.Dict(
|
||||
kit.MDB_NAME, "",
|
||||
kit.MDB_TEXT, arg[0],
|
||||
))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
_ip_list(m, "")
|
||||
}},
|
||||
PORT: {Name: "port", Help: "端口", Action: map[string]*ice.Action{
|
||||
"get": {Name: "get", Help: "分配端口", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Echo(_port_get(m, ""))
|
||||
}},
|
||||
"select": {Name: "select [begin]", Help: "分配端口", Hand: func(m *ice.Message, arg ...string) {
|
||||
port, p := kit.Select("", arg, 0), ""
|
||||
for i := 0; i < 10; i++ {
|
||||
port = _port_get(m, port)
|
||||
p = path.Join(m.Conf(cli.DAEMON, kit.META_PATH), port)
|
||||
if _, e := os.Stat(p); e != nil && os.IsNotExist(e) {
|
||||
break
|
||||
}
|
||||
port = kit.Format(kit.Int(port) + 1)
|
||||
}
|
||||
os.MkdirAll(p, ice.MOD_DIR)
|
||||
m.Echo(port)
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
_port_list(m)
|
||||
}},
|
||||
|
||||
"server": {Name: "server [tcp4|tcp6|udp4|udp6] addr", Help: "server", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
proto := "tcp4"
|
||||
switch arg[0] {
|
||||
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6", "ip", "ip4", "ip6":
|
||||
proto, arg = arg[0], arg[1:]
|
||||
}
|
||||
|
||||
if l, e := net.Listen(proto, arg[0]); m.Assert(e) {
|
||||
m.Gos(m, func(m *ice.Message) {
|
||||
// 启动服务
|
||||
m.Logs(ice.LOG_LISTEN, "addr", l.Addr())
|
||||
for {
|
||||
if c, e := l.Accept(); m.Assert(e) {
|
||||
m.Gos(m.Spawns(), func(msg *ice.Message) {
|
||||
// 建立连接
|
||||
msg.Logs(ice.LOG_ACCEPT, "addr", c.RemoteAddr())
|
||||
msg.Option(ice.MSG_USERADDR, c.RemoteAddr())
|
||||
msg.Option(ice.MSG_USERNAME, "")
|
||||
msg.Option(ice.MSG_USERROLE, "")
|
||||
|
||||
switch msg.Cmdx("check", c.RemoteAddr().String()) {
|
||||
case "local":
|
||||
// 本机用户
|
||||
msg.Option(ice.MSG_USERNAME, msg.Conf(cli.RUNTIME, "boot.username"))
|
||||
msg.Option(ice.MSG_USERROLE, msg.Cmdx(aaa.ROLE, "check", msg.Option(ice.MSG_USERNAME)))
|
||||
msg.Logs(ice.LOG_AUTH, "name", msg.Option(ice.MSG_USERNAME), "role", msg.Option(ice.MSG_USERROLE))
|
||||
}
|
||||
|
||||
cmds := []string{}
|
||||
buf := bufio.NewWriter(c)
|
||||
for bio := bufio.NewScanner(c); bio.Scan(); {
|
||||
text := bio.Text()
|
||||
msg.Logs("scan", "len", len(text), "text", text)
|
||||
|
||||
if len(text) == 0 {
|
||||
if len(cmds) > 0 {
|
||||
msg.Cmd(aaa.ROLE, "right")
|
||||
// 执行命令
|
||||
res := msg.Cmd(cmds)
|
||||
|
||||
// 返回结果
|
||||
for _, str := range res.Resultv() {
|
||||
buf.WriteString("result:")
|
||||
buf.WriteString(url.QueryEscape(str))
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
buf.WriteString("\n")
|
||||
buf.Flush()
|
||||
|
||||
cmds = cmds[:0]
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// 解析请求
|
||||
line := strings.SplitN(bio.Text(), ":", 2)
|
||||
line[0], e = url.QueryUnescape(line[0])
|
||||
m.Assert(e)
|
||||
line[1], e = url.QueryUnescape(line[1])
|
||||
m.Assert(e)
|
||||
switch line[0] {
|
||||
case "cmds", ice.MSG_DETAIL:
|
||||
cmds = append(cmds, line[1])
|
||||
default:
|
||||
msg.Option(line[0], line[1])
|
||||
}
|
||||
}
|
||||
msg.Logs(ice.LOG_FINISH, "addr", c.RemoteAddr())
|
||||
})
|
||||
}
|
||||
}
|
||||
m.Logs(ice.LOG_FINISH, "addr", l.Addr())
|
||||
})
|
||||
}
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Richs(CLIENT, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
|
||||
kit.Value(value, "meta.status", CLOSE)
|
||||
})
|
||||
m.Richs(SERVER, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
|
||||
kit.Value(value, "meta.status", CLOSE)
|
||||
})
|
||||
m.Save()
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
func init() { ice.Index.Register(Index, nil, IP, PORT) }
|
||||
func init() { ice.Index.Register(Index, nil, HOST, PORT, CLIENT, SERVER) }
|
||||
|
6
base/tcp/tcp.shy
Normal file
6
base/tcp/tcp.shy
Normal file
@ -0,0 +1,6 @@
|
||||
chapter "tcp"
|
||||
|
||||
field host tcp.host
|
||||
# field port tcp.port
|
||||
field server tcp.server
|
||||
field client tcp.client
|
@ -359,5 +359,45 @@ func init() {
|
||||
m.Option(kit.MDB_NAME), m.Option(kit.MDB_TEXT), m.Option(kit.MDB_EXTRA))
|
||||
}
|
||||
}},
|
||||
"/share/": {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Richs(SHARE, nil, kit.Select(m.Option(kit.SSH_SHARE), arg, 0), func(key string, value map[string]interface{}) {
|
||||
m.Log_SELECT(kit.MDB_META, SHARE, "arg", arg, "value", kit.Format(value))
|
||||
if m.Warn(m.Option(ice.MSG_USERROLE) != aaa.ROOT && kit.Time(kit.Format(value[kit.MDB_TIME])) < kit.Time(m.Time()), "expired") {
|
||||
m.Echo("expired")
|
||||
return
|
||||
}
|
||||
|
||||
switch value[kit.MDB_TYPE] {
|
||||
case STORY:
|
||||
value = _share_story(m, value, arg...)
|
||||
}
|
||||
|
||||
if _share_show(m, key, value, kit.Select("", arg, 1), kit.Select("", arg, 2)) {
|
||||
return
|
||||
}
|
||||
|
||||
switch value[kit.MDB_TYPE] {
|
||||
case TYPE_RIVER:
|
||||
// 共享群组
|
||||
m.Render("redirect", "/", "share", key, "river", kit.Format(value["text"]))
|
||||
|
||||
case TYPE_STORM:
|
||||
// 共享应用
|
||||
m.Render("redirect", "/", "share", key, "storm", kit.Format(value["text"]), "river", kit.Format(kit.Value(value, "extra.river")))
|
||||
|
||||
case TYPE_ACTION:
|
||||
_share_action(m, value, arg...)
|
||||
|
||||
default:
|
||||
// 查看数据
|
||||
m.Option(kit.MDB_VALUE, value)
|
||||
m.Option(kit.MDB_TYPE, value[kit.MDB_TYPE])
|
||||
m.Option(kit.MDB_NAME, value[kit.MDB_NAME])
|
||||
m.Option(kit.MDB_TEXT, value[kit.MDB_TEXT])
|
||||
m.Render(ice.RENDER_TEMPLATE, m.Conf(SHARE, "meta.template.simple"))
|
||||
m.Option(ice.MSG_OUTPUT, ice.RENDER_RESULT)
|
||||
}
|
||||
})
|
||||
}},
|
||||
}}, nil)
|
||||
}
|
201
base/web/_share.go
Normal file
201
base/web/_share.go
Normal file
@ -0,0 +1,201 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/aaa"
|
||||
"github.com/shylinux/icebergs/base/cli"
|
||||
"github.com/shylinux/icebergs/base/ctx"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func _share_list(m *ice.Message, key string, fields ...string) {
|
||||
if key == "" {
|
||||
m.Grows(SHARE, nil, "", "", func(index int, value map[string]interface{}) {
|
||||
m.Push("", value, []string{kit.MDB_TIME, kit.SSH_SHARE, kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT})
|
||||
m.Push(kit.MDB_LINK, fmt.Sprintf(m.Conf(SHARE, "meta.template.link"), m.Conf(SHARE, "meta.domain"), value[kit.SSH_SHARE], value[kit.SSH_SHARE]))
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
m.Richs(SHARE, nil, key, func(key string, value map[string]interface{}) {
|
||||
m.Push("detail", value)
|
||||
|
||||
m.Push(kit.MDB_KEY, kit.MDB_LINK)
|
||||
m.Push(kit.MDB_VALUE, m.Cmdx(mdb.RENDER, RENDER.A, key, URL(m, kit.Format("/share/%s", key))))
|
||||
m.Push(kit.MDB_KEY, kit.SSH_SHARE)
|
||||
m.Push(kit.MDB_VALUE, m.Cmdx(mdb.RENDER, RENDER.IMG, URL(m, kit.Format("/share/%s/share", key))))
|
||||
m.Push(kit.MDB_KEY, kit.MDB_VALUE)
|
||||
m.Push(kit.MDB_VALUE, m.Cmdx(mdb.RENDER, RENDER.IMG, URL(m, kit.Format("/share/%s/value", key))))
|
||||
})
|
||||
}
|
||||
func _share_show(m *ice.Message, key string, value map[string]interface{}, arg ...string) bool {
|
||||
switch kit.Select("", arg, 0) {
|
||||
case "check", "安全码":
|
||||
m.Render(ice.RENDER_QRCODE, kit.Format(kit.Dict(
|
||||
kit.MDB_TYPE, SHARE, kit.MDB_NAME, value[kit.MDB_TYPE], kit.MDB_TEXT, key,
|
||||
)))
|
||||
case kit.SSH_SHARE, "共享码":
|
||||
m.Render(ice.RENDER_QRCODE, kit.Format("%s/share/%s/?share=%s", m.Conf(SHARE, "meta.domain"), key, key))
|
||||
case kit.MDB_VALUE, "数据值":
|
||||
m.Render(ice.RENDER_QRCODE, kit.Format(value), kit.Select("256", arg, 1))
|
||||
case kit.MDB_TEXT:
|
||||
m.Render(ice.RENDER_QRCODE, kit.Format(value[kit.MDB_TEXT]))
|
||||
case "detail", "详情":
|
||||
m.Render(kit.Formats(value))
|
||||
case "download", "下载":
|
||||
if strings.HasPrefix(kit.Format(value["text"]), m.Conf(CACHE, "meta.path")) {
|
||||
m.Render(ice.RENDER_DOWNLOAD, value["text"], value["type"], value["name"])
|
||||
} else {
|
||||
m.Render("%s", value["text"])
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
func _share_create(m *ice.Message, kind, name, text string, arg ...string) string {
|
||||
h := m.Rich(SHARE, nil, kit.Dict(
|
||||
kit.MDB_TIME, m.Time(m.Conf(SHARE, "meta.expire")),
|
||||
kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, text,
|
||||
kit.MDB_EXTRA, kit.Dict(
|
||||
aaa.USERROLE, m.Option(ice.MSG_USERROLE),
|
||||
aaa.USERNAME, m.Option(ice.MSG_USERNAME),
|
||||
"river", m.Option(ice.MSG_RIVER),
|
||||
"storm", m.Option(ice.MSG_STORM),
|
||||
arg),
|
||||
))
|
||||
|
||||
// 创建列表
|
||||
m.Grow(SHARE, nil, kit.Dict(
|
||||
kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, text,
|
||||
kit.SSH_SHARE, h,
|
||||
))
|
||||
m.Log_CREATE(kit.SSH_SHARE, h, kit.MDB_TYPE, kind, kit.MDB_NAME, name)
|
||||
m.Echo(h)
|
||||
return h
|
||||
}
|
||||
|
||||
func _share_story(m *ice.Message, value map[string]interface{}, arg ...string) map[string]interface{} {
|
||||
msg := m.Cmd(STORY, INDEX, value["text"])
|
||||
if msg.Append("text") == "" && kit.Value(value, "extra.pod") != "" {
|
||||
msg = m.Cmd(SPACE, kit.Value(value, "extra.pod"), STORY, INDEX, value["text"])
|
||||
}
|
||||
value = kit.Dict("type", msg.Append("scene"), "name", msg.Append("story"), "text", msg.Append("text"), "file", msg.Append("file"))
|
||||
m.Log(ice.LOG_EXPORT, "%s: %v", arg, kit.Format(value))
|
||||
return value
|
||||
}
|
||||
func _share_action(m *ice.Message, value map[string]interface{}, arg ...string) bool {
|
||||
if len(arg) == 1 || arg[1] == "" {
|
||||
return _share_action_redirect(m, value, arg[0])
|
||||
}
|
||||
if arg[1] == "" {
|
||||
return _share_action_page(m, value)
|
||||
}
|
||||
if len(arg) == 2 {
|
||||
return _share_action_list(m, value, arg[0], arg[1])
|
||||
}
|
||||
|
||||
// 默认参数
|
||||
meta := kit.Value(value, kit.Format("extra.tool.%s", arg[2])).(map[string]interface{})
|
||||
if meta["single"] == "yes" && kit.Select("", arg, 3) != "action" {
|
||||
arg = append(arg[:3], kit.Simple(kit.UnMarshal(kit.Format(meta["args"])))...)
|
||||
for i := len(arg) - 1; i >= 0; i-- {
|
||||
if arg[i] != "" {
|
||||
return true
|
||||
}
|
||||
arg = arg[:i]
|
||||
}
|
||||
}
|
||||
|
||||
// 执行命令
|
||||
cmds := kit.Simple(m.Space(meta["pod"]), kit.Keys(meta["ctx"], meta["cmd"]), arg[3:])
|
||||
m.Cmdy(cmds).Option("cmds", cmds)
|
||||
m.Option("title", value["name"])
|
||||
if strings.HasPrefix(kit.Format(value["text"]), m.Conf(CACHE, "meta.path")) {
|
||||
m.Render(ice.RENDER_DOWNLOAD, value["text"], value["type"], value["name"])
|
||||
} else {
|
||||
m.Render("%s", value["text"])
|
||||
}
|
||||
return true
|
||||
}
|
||||
func _share_action_redirect(m *ice.Message, value map[string]interface{}, share string) bool {
|
||||
tool := kit.Value(value, "extra.tool.0").(map[string]interface{})
|
||||
m.Render("redirect", "/share", "share", share, "title", kit.Format(value["name"]),
|
||||
"river", kit.Format(kit.Value(value, "extra.river")),
|
||||
"storm", kit.Format(kit.Value(value, "extra.storm")),
|
||||
"pod", kit.Format(tool["pod"]), kit.UnMarshal(kit.Format(tool["val"])),
|
||||
)
|
||||
return true
|
||||
}
|
||||
func _share_action_page(m *ice.Message, value map[string]interface{}) bool {
|
||||
Render(m, ice.RENDER_DOWNLOAD, m.Conf(SERVE, "meta.page.share"))
|
||||
return true
|
||||
}
|
||||
func _share_action_list(m *ice.Message, value map[string]interface{}, river, storm string) bool {
|
||||
value["count"] = kit.Int(value["count"]) + 1
|
||||
kit.Fetch(kit.Value(value, "extra.tool"), func(index int, value map[string]interface{}) {
|
||||
m.Push("river", river)
|
||||
m.Push("storm", storm)
|
||||
m.Push("action", index)
|
||||
|
||||
m.Push("node", value["pod"])
|
||||
m.Push("group", value["ctx"])
|
||||
m.Push("index", value["cmd"])
|
||||
m.Push("args", value["args"])
|
||||
m.Push("value", value["value"])
|
||||
|
||||
msg := m.Cmd(m.Space(value["pod"]), ctx.COMMAND, value["ctx"], value["cmd"])
|
||||
ls := strings.Split(kit.Format(value["cmd"]), ".")
|
||||
m.Push("name", ls[len(ls)-1])
|
||||
m.Push("help", kit.Select(msg.Append("help"), kit.Format(value["help"])))
|
||||
m.Push("inputs", msg.Append("list"))
|
||||
m.Push("feature", msg.Append("meta"))
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
func _share_auth(m *ice.Message, share string, role string) {
|
||||
m.Richs(SHARE, nil, share, func(key string, value map[string]interface{}) {
|
||||
switch value["type"] {
|
||||
case "active":
|
||||
m.Cmdy(SPACE, value["name"], "sessid", m.Cmdx(aaa.SESS, "create", role))
|
||||
case "user":
|
||||
m.Cmdy(aaa.ROLE, role, value["name"])
|
||||
default:
|
||||
m.Cmdy(aaa.SESS, "auth", value["text"], role)
|
||||
}
|
||||
})
|
||||
}
|
||||
func _share_check(m *ice.Message, share string) {
|
||||
m.Richs(SHARE, nil, share, func(key string, value map[string]interface{}) {
|
||||
m.Render(ice.RENDER_QRCODE, kit.Format(kit.Dict(
|
||||
kit.MDB_TYPE, "share", kit.MDB_NAME, value["type"], kit.MDB_TEXT, key,
|
||||
)))
|
||||
})
|
||||
}
|
||||
func _trash(m *ice.Message, arg ...string) {
|
||||
switch arg[0] {
|
||||
case "invite":
|
||||
arg = []string{arg[0], m.Cmdx(SHARE, "invite", kit.Select("tech", arg, 1), kit.Select("miss", arg, 2))}
|
||||
fallthrough
|
||||
case "check":
|
||||
_share_check(m, arg[1])
|
||||
case "auth":
|
||||
_share_auth(m, arg[1], arg[2])
|
||||
case "add":
|
||||
_share_create(m, arg[1], arg[2], arg[3], arg[4:]...)
|
||||
default:
|
||||
if len(arg) == 1 {
|
||||
_share_list(m, arg[0])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
@ -120,10 +120,10 @@ func _cache_download(m *ice.Message, r *http.Response) (file, size string) {
|
||||
value = value[kit.MDB_META].(map[string]interface{})
|
||||
|
||||
s := size * 100 / total
|
||||
if s != kit.Int(value[kit.MDB_STEP]) && s%10 == 0 {
|
||||
m.Log_IMPORT(kit.MDB_FILE, path.Base(cb[2]), kit.MDB_STEP, s, kit.MDB_SIZE, kit.FmtSize(int64(size)), kit.MDB_TOTAL, kit.FmtSize(int64(total)))
|
||||
if s != kit.Int(value[kit.SSH_STEP]) && s%10 == 0 {
|
||||
m.Log_IMPORT(kit.MDB_FILE, path.Base(cb[2]), kit.SSH_STEP, s, kit.MDB_SIZE, kit.FmtSize(int64(size)), kit.MDB_TOTAL, kit.FmtSize(int64(total)))
|
||||
}
|
||||
value[kit.MDB_STEP], value[kit.MDB_SIZE], value[kit.MDB_TOTAL] = kit.Format(s), size, total
|
||||
value[kit.SSH_STEP], value[kit.MDB_SIZE], value[kit.MDB_TOTAL] = kit.Format(s), size, total
|
||||
})
|
||||
case func(int, int):
|
||||
cb(size, total)
|
||||
|
@ -99,7 +99,7 @@ ish_miss_prepare_install
|
||||
Commands: map[string]*ice.Command{
|
||||
DREAM: {Name: "dream [name [cmd...]] auto", Help: "梦想家", Meta: kit.Dict("detail", []interface{}{"启动", "停止"}), Action: map[string]*ice.Action{
|
||||
gdb.START: {Name: "start type name", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Option(kit.MDB_NAME, kit.Select(path.Base(m.Option(kit.MDB_REPOS)), m.Option(kit.MDB_NAME)))
|
||||
m.Option(kit.MDB_NAME, kit.Select(path.Base(m.Option(kit.SSH_REPOS)), m.Option(kit.MDB_NAME)))
|
||||
_dream_show(m, m.Option(kit.MDB_NAME))
|
||||
}},
|
||||
gdb.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
|
||||
|
@ -8,14 +8,14 @@ import (
|
||||
)
|
||||
|
||||
func _label_add(m *ice.Message, cmd string) {
|
||||
if m.Option(cmd) != "" && m.Option(kit.MDB_GROUP) != "" && m.Option(kit.MDB_NAME) != "" {
|
||||
m.Cmdy(cmd, m.Option(cmd), "add", m.Option(kit.MDB_GROUP), m.Option(kit.MDB_NAME))
|
||||
if m.Option(cmd) != "" && m.Option(kit.SSH_GROUP) != "" && m.Option(kit.MDB_NAME) != "" {
|
||||
m.Cmdy(cmd, m.Option(cmd), "add", m.Option(kit.SSH_GROUP), m.Option(kit.MDB_NAME))
|
||||
m.Option(ice.FIELD_RELOAD, "true")
|
||||
}
|
||||
}
|
||||
func _label_del(m *ice.Message, cmd string) {
|
||||
if m.Option(cmd) != "" && m.Option(kit.MDB_GROUP) != "" && m.Option(kit.MDB_NAME) != "" {
|
||||
m.Cmdy(cmd, m.Option(cmd), "del", m.Option(kit.MDB_GROUP), m.Option(kit.MDB_NAME))
|
||||
if m.Option(cmd) != "" && m.Option(kit.SSH_GROUP) != "" && m.Option(kit.MDB_NAME) != "" {
|
||||
m.Cmdy(cmd, m.Option(cmd), "del", m.Option(kit.SSH_GROUP), m.Option(kit.MDB_NAME))
|
||||
m.Option(ice.FIELD_RELOAD, "true")
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,7 @@ func _label_prune(m *ice.Message, cmd string) {
|
||||
m.Richs(cmd, nil, m.Option(cmd), func(key string, value map[string]interface{}) {
|
||||
m.Richs(cmd, kit.Keys(kit.MDB_HASH, key), kit.MDB_FOREACH, func(sub string, value map[string]interface{}) {
|
||||
if value[kit.MDB_STATUS] != "busy" {
|
||||
m.Cmdy(cmd, m.Option(cmd), "del", value[kit.MDB_GROUP], value[kit.MDB_NAME])
|
||||
m.Cmdy(cmd, m.Option(cmd), "del", value[kit.SSH_GROUP], value[kit.MDB_NAME])
|
||||
m.Option(ice.FIELD_RELOAD, "true")
|
||||
}
|
||||
})
|
||||
@ -70,7 +70,7 @@ func _label_select(m *ice.Message, cmd string, arg ...string) {
|
||||
if len(arg) < 2 {
|
||||
// 二级列表
|
||||
m.Option(ice.FIELD_DETAIL, "添加", "退还", "清理", "清空")
|
||||
m.Push(key, value, []string{kit.MDB_TIME, kit.MDB_GROUP, kit.MDB_STATUS, kit.MDB_NAME})
|
||||
m.Push(key, value, []string{kit.MDB_TIME, kit.SSH_GROUP, kit.MDB_STATUS, kit.MDB_NAME})
|
||||
return
|
||||
}
|
||||
// 分组详情
|
||||
@ -94,7 +94,7 @@ func _label_create(m *ice.Message, cmd string, key string, arg ...string) {
|
||||
}) == nil {
|
||||
m.Logs(ice.LOG_INSERT, cmd, arg[0], kit.MDB_NAME, pod)
|
||||
m.Rich(cmd, kit.Keys(kit.MDB_HASH, key), kit.Dict(
|
||||
kit.MDB_NAME, pod, kit.MDB_GROUP, arg[2], kit.MDB_STATUS, "free",
|
||||
kit.MDB_NAME, pod, kit.SSH_GROUP, arg[2], kit.MDB_STATUS, "free",
|
||||
))
|
||||
}
|
||||
m.Echo(arg[0])
|
||||
@ -105,7 +105,7 @@ func _label_remove(m *ice.Message, cmd string, key string, arg ...string) {
|
||||
if value[kit.MDB_STATUS] == "free" {
|
||||
value[kit.MDB_STATUS] = "void"
|
||||
m.Logs(ice.LOG_MODIFY, cmd, arg[0], kit.MDB_NAME, arg[3], kit.MDB_STATUS, "void")
|
||||
m.Cmdx(GROUP, value[kit.MDB_GROUP], "put", arg[3])
|
||||
m.Cmdx(GROUP, value[kit.SSH_GROUP], "put", arg[3])
|
||||
m.Echo(arg[3])
|
||||
}
|
||||
})
|
||||
@ -176,7 +176,7 @@ func init() {
|
||||
if arg[0] == "route" {
|
||||
m.Cmd(ROUTE).Table(func(index int, value map[string]string, field []string) {
|
||||
m.Rich(cmd, kit.Keys(kit.MDB_HASH, key), kit.Dict(
|
||||
kit.MDB_NAME, value["name"], kit.MDB_GROUP, arg[0], kit.MDB_STATUS, "free",
|
||||
kit.MDB_NAME, value["name"], kit.SSH_GROUP, arg[0], kit.MDB_STATUS, "free",
|
||||
))
|
||||
})
|
||||
}
|
||||
|
@ -21,19 +21,19 @@ func _route_travel(m *ice.Message, route string) {
|
||||
// 远程查询
|
||||
m.Cmd(SPACE, val[kit.MDB_NAME], ROUTE).Table(func(index int, value map[string]string, head []string) {
|
||||
m.Push(kit.MDB_TYPE, value[kit.MDB_TYPE])
|
||||
m.Push(kit.MDB_ROUTE, kit.Keys(val[kit.MDB_NAME], value[kit.MDB_ROUTE]))
|
||||
m.Push(kit.SSH_ROUTE, kit.Keys(val[kit.MDB_NAME], value[kit.SSH_ROUTE]))
|
||||
})
|
||||
fallthrough
|
||||
case WORKER:
|
||||
// 本机查询
|
||||
m.Push(kit.MDB_TYPE, val[kit.MDB_TYPE])
|
||||
m.Push(kit.MDB_ROUTE, val[kit.MDB_NAME])
|
||||
m.Push(kit.SSH_ROUTE, val[kit.MDB_NAME])
|
||||
}
|
||||
})
|
||||
} else {
|
||||
m.Cmd(SPACE, route, ROUTE).Table(func(index int, value map[string]string, head []string) {
|
||||
m.Push(kit.MDB_TYPE, value[kit.MDB_TYPE])
|
||||
m.Push(kit.MDB_ROUTE, kit.Keys(route, value[kit.MDB_ROUTE]))
|
||||
m.Push(kit.SSH_ROUTE, kit.Keys(route, value[kit.SSH_ROUTE]))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -43,7 +43,7 @@ const ROUTE = "route"
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{
|
||||
Configs: map[string]*ice.Config{
|
||||
ROUTE: {Name: ROUTE, Help: "路由器", Value: kit.Data(kit.MDB_SHORT, kit.MDB_ROUTE)},
|
||||
ROUTE: {Name: ROUTE, Help: "路由器", Value: kit.Data(kit.MDB_SHORT, kit.SSH_ROUTE)},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
ROUTE: {Name: "route route ctx cmd auto 添加", Help: "路由", Action: map[string]*ice.Action{
|
||||
@ -112,8 +112,8 @@ func init() {
|
||||
m.Push("route", MYSELF)
|
||||
|
||||
m.Table(func(index int, value map[string]string, field []string) {
|
||||
m.PushRender(kit.MDB_LINK, "a", value[kit.MDB_ROUTE],
|
||||
kit.MergeURL(m.Option(ice.MSG_USERWEB), "pod", kit.Keys(m.Option("pod", value[kit.MDB_ROUTE]))))
|
||||
m.PushRender(kit.MDB_LINK, "a", value[kit.SSH_ROUTE],
|
||||
kit.MergeURL(m.Option(ice.MSG_USERWEB), "pod", kit.Keys(m.Option("pod", value[kit.SSH_ROUTE]))))
|
||||
switch value[kit.MDB_TYPE] {
|
||||
case MYSELF, SERVER:
|
||||
m.PushRender("action", "button", "启动")
|
||||
@ -121,7 +121,7 @@ func init() {
|
||||
m.PushRender("action", "button", "结束")
|
||||
}
|
||||
})
|
||||
m.Sort(kit.MDB_ROUTE)
|
||||
m.Sort(kit.SSH_ROUTE)
|
||||
}},
|
||||
"/route/": {Name: "/route/", Help: "路由器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
switch arg[0] {
|
||||
|
@ -27,7 +27,7 @@ func _serve_login(msg *ice.Message, cmds []string, w http.ResponseWriter, r *htt
|
||||
aaa.SessCheck(msg, msg.Option(ice.MSG_SESSID))
|
||||
}
|
||||
|
||||
if !msg.Options(ice.MSG_USERNAME) && tcp.IPIsLocal(msg, msg.Option(ice.MSG_USERIP)) {
|
||||
if !msg.Options(ice.MSG_USERNAME) && tcp.IsLocalHost(msg, msg.Option(ice.MSG_USERIP)) {
|
||||
// 自动认证
|
||||
if aaa.UserLogin(msg, cli.UserName, cli.PassWord) {
|
||||
if strings.HasPrefix(msg.Option(ice.MSG_USERUA), "Mozilla/5.0") {
|
||||
|
@ -4,11 +4,9 @@ import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/aaa"
|
||||
"github.com/shylinux/icebergs/base/cli"
|
||||
"github.com/shylinux/icebergs/base/ctx"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
@ -16,51 +14,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func _share_list(m *ice.Message, key string, fields ...string) {
|
||||
if key == "" {
|
||||
m.Grows(SHARE, nil, "", "", func(index int, value map[string]interface{}) {
|
||||
m.Push("", value, []string{kit.MDB_TIME, kit.MDB_SHARE, kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT})
|
||||
m.Push(kit.MDB_LINK, fmt.Sprintf(m.Conf(SHARE, "meta.template.link"), m.Conf(SHARE, "meta.domain"), value[kit.MDB_SHARE], value[kit.MDB_SHARE]))
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
m.Richs(SHARE, nil, key, func(key string, value map[string]interface{}) {
|
||||
m.Push("detail", value)
|
||||
|
||||
m.Push(kit.MDB_KEY, kit.MDB_LINK)
|
||||
m.Push(kit.MDB_VALUE, m.Cmdx(mdb.RENDER, RENDER.A, key, URL(m, kit.Format("/share/%s", key))))
|
||||
m.Push(kit.MDB_KEY, kit.MDB_SHARE)
|
||||
m.Push(kit.MDB_VALUE, m.Cmdx(mdb.RENDER, RENDER.IMG, URL(m, kit.Format("/share/%s/share", key))))
|
||||
m.Push(kit.MDB_KEY, kit.MDB_VALUE)
|
||||
m.Push(kit.MDB_VALUE, m.Cmdx(mdb.RENDER, RENDER.IMG, URL(m, kit.Format("/share/%s/value", key))))
|
||||
})
|
||||
}
|
||||
func _share_show(m *ice.Message, key string, value map[string]interface{}, arg ...string) bool {
|
||||
switch kit.Select("", arg, 0) {
|
||||
case "check", "安全码":
|
||||
m.Render(ice.RENDER_QRCODE, kit.Format(kit.Dict(
|
||||
kit.MDB_TYPE, SHARE, kit.MDB_NAME, value[kit.MDB_TYPE], kit.MDB_TEXT, key,
|
||||
)))
|
||||
case kit.MDB_SHARE, "共享码":
|
||||
m.Render(ice.RENDER_QRCODE, kit.Format("%s/share/%s/?share=%s", m.Conf(SHARE, "meta.domain"), key, key))
|
||||
case kit.MDB_VALUE, "数据值":
|
||||
m.Render(ice.RENDER_QRCODE, kit.Format(value), kit.Select("256", arg, 1))
|
||||
case kit.MDB_TEXT:
|
||||
m.Render(ice.RENDER_QRCODE, kit.Format(value[kit.MDB_TEXT]))
|
||||
case "detail", "详情":
|
||||
m.Render(kit.Formats(value))
|
||||
case "download", "下载":
|
||||
if strings.HasPrefix(kit.Format(value["text"]), m.Conf(CACHE, "meta.path")) {
|
||||
m.Render(ice.RENDER_DOWNLOAD, value["text"], value["type"], value["name"])
|
||||
} else {
|
||||
m.Render("%s", value["text"])
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
func _share_repos(m *ice.Message, repos string, arg ...string) {
|
||||
prefix := m.Conf(SERVE, "meta.volcanos.require")
|
||||
if _, e := os.Stat(path.Join(prefix, repos)); e != nil {
|
||||
@ -68,6 +21,10 @@ func _share_repos(m *ice.Message, repos string, arg ...string) {
|
||||
}
|
||||
m.Render(ice.RENDER_DOWNLOAD, path.Join(prefix, repos, path.Join(arg...)))
|
||||
}
|
||||
func _share_remote(m *ice.Message, pod string, arg ...string) {
|
||||
m.Cmdy(SPACE, pod, "web./publish/", arg)
|
||||
m.Render(ice.RENDER_RESULT)
|
||||
}
|
||||
func _share_local(m *ice.Message, arg ...string) {
|
||||
p := path.Join(arg...)
|
||||
switch ls := strings.Split(p, "/"); ls[0] {
|
||||
@ -114,148 +71,6 @@ func _share_cache(m *ice.Message, arg ...string) {
|
||||
msg := m.Cmd(CACHE, arg[0])
|
||||
m.Render(ice.RENDER_DOWNLOAD, msg.Append(kit.MDB_FILE), msg.Append(kit.MDB_TYPE), msg.Append(kit.MDB_NAME))
|
||||
}
|
||||
func _share_remote(m *ice.Message, pod string, arg ...string) {
|
||||
m.Cmdy(SPACE, pod, "web./publish/", arg)
|
||||
m.Render(ice.RENDER_RESULT)
|
||||
}
|
||||
func _share_create(m *ice.Message, kind, name, text string, arg ...string) string {
|
||||
h := m.Rich(SHARE, nil, kit.Dict(
|
||||
kit.MDB_TIME, m.Time(m.Conf(SHARE, "meta.expire")),
|
||||
kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, text,
|
||||
kit.MDB_EXTRA, kit.Dict(
|
||||
aaa.USERROLE, m.Option(ice.MSG_USERROLE),
|
||||
aaa.USERNAME, m.Option(ice.MSG_USERNAME),
|
||||
"river", m.Option(ice.MSG_RIVER),
|
||||
"storm", m.Option(ice.MSG_STORM),
|
||||
arg),
|
||||
))
|
||||
|
||||
// 创建列表
|
||||
m.Grow(SHARE, nil, kit.Dict(
|
||||
kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, text,
|
||||
kit.MDB_SHARE, h,
|
||||
))
|
||||
m.Log_CREATE(kit.MDB_SHARE, h, kit.MDB_TYPE, kind, kit.MDB_NAME, name)
|
||||
m.Echo(h)
|
||||
return h
|
||||
}
|
||||
|
||||
func _share_story(m *ice.Message, value map[string]interface{}, arg ...string) map[string]interface{} {
|
||||
msg := m.Cmd(STORY, INDEX, value["text"])
|
||||
if msg.Append("text") == "" && kit.Value(value, "extra.pod") != "" {
|
||||
msg = m.Cmd(SPACE, kit.Value(value, "extra.pod"), STORY, INDEX, value["text"])
|
||||
}
|
||||
value = kit.Dict("type", msg.Append("scene"), "name", msg.Append("story"), "text", msg.Append("text"), "file", msg.Append("file"))
|
||||
m.Log(ice.LOG_EXPORT, "%s: %v", arg, kit.Format(value))
|
||||
return value
|
||||
}
|
||||
func _share_action(m *ice.Message, value map[string]interface{}, arg ...string) bool {
|
||||
if len(arg) == 1 || arg[1] == "" {
|
||||
return _share_action_redirect(m, value, arg[0])
|
||||
}
|
||||
if arg[1] == "" {
|
||||
return _share_action_page(m, value)
|
||||
}
|
||||
if len(arg) == 2 {
|
||||
return _share_action_list(m, value, arg[0], arg[1])
|
||||
}
|
||||
|
||||
// 默认参数
|
||||
meta := kit.Value(value, kit.Format("extra.tool.%s", arg[2])).(map[string]interface{})
|
||||
if meta["single"] == "yes" && kit.Select("", arg, 3) != "action" {
|
||||
arg = append(arg[:3], kit.Simple(kit.UnMarshal(kit.Format(meta["args"])))...)
|
||||
for i := len(arg) - 1; i >= 0; i-- {
|
||||
if arg[i] != "" {
|
||||
return true
|
||||
}
|
||||
arg = arg[:i]
|
||||
}
|
||||
}
|
||||
|
||||
// 执行命令
|
||||
cmds := kit.Simple(m.Space(meta["pod"]), kit.Keys(meta["ctx"], meta["cmd"]), arg[3:])
|
||||
m.Cmdy(cmds).Option("cmds", cmds)
|
||||
m.Option("title", value["name"])
|
||||
if strings.HasPrefix(kit.Format(value["text"]), m.Conf(CACHE, "meta.path")) {
|
||||
m.Render(ice.RENDER_DOWNLOAD, value["text"], value["type"], value["name"])
|
||||
} else {
|
||||
m.Render("%s", value["text"])
|
||||
}
|
||||
return true
|
||||
}
|
||||
func _share_action_redirect(m *ice.Message, value map[string]interface{}, share string) bool {
|
||||
tool := kit.Value(value, "extra.tool.0").(map[string]interface{})
|
||||
m.Render("redirect", "/share", "share", share, "title", kit.Format(value["name"]),
|
||||
"river", kit.Format(kit.Value(value, "extra.river")),
|
||||
"storm", kit.Format(kit.Value(value, "extra.storm")),
|
||||
"pod", kit.Format(tool["pod"]), kit.UnMarshal(kit.Format(tool["val"])),
|
||||
)
|
||||
return true
|
||||
}
|
||||
func _share_action_page(m *ice.Message, value map[string]interface{}) bool {
|
||||
Render(m, ice.RENDER_DOWNLOAD, m.Conf(SERVE, "meta.page.share"))
|
||||
return true
|
||||
}
|
||||
func _share_action_list(m *ice.Message, value map[string]interface{}, river, storm string) bool {
|
||||
value["count"] = kit.Int(value["count"]) + 1
|
||||
kit.Fetch(kit.Value(value, "extra.tool"), func(index int, value map[string]interface{}) {
|
||||
m.Push("river", river)
|
||||
m.Push("storm", storm)
|
||||
m.Push("action", index)
|
||||
|
||||
m.Push("node", value["pod"])
|
||||
m.Push("group", value["ctx"])
|
||||
m.Push("index", value["cmd"])
|
||||
m.Push("args", value["args"])
|
||||
m.Push("value", value["value"])
|
||||
|
||||
msg := m.Cmd(m.Space(value["pod"]), ctx.COMMAND, value["ctx"], value["cmd"])
|
||||
ls := strings.Split(kit.Format(value["cmd"]), ".")
|
||||
m.Push("name", ls[len(ls)-1])
|
||||
m.Push("help", kit.Select(msg.Append("help"), kit.Format(value["help"])))
|
||||
m.Push("inputs", msg.Append("list"))
|
||||
m.Push("feature", msg.Append("meta"))
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
func _share_auth(m *ice.Message, share string, role string) {
|
||||
m.Richs(SHARE, nil, share, func(key string, value map[string]interface{}) {
|
||||
switch value["type"] {
|
||||
case "active":
|
||||
m.Cmdy(SPACE, value["name"], "sessid", m.Cmdx(aaa.SESS, "create", role))
|
||||
case "user":
|
||||
m.Cmdy(aaa.ROLE, role, value["name"])
|
||||
default:
|
||||
m.Cmdy(aaa.SESS, "auth", value["text"], role)
|
||||
}
|
||||
})
|
||||
}
|
||||
func _share_check(m *ice.Message, share string) {
|
||||
m.Richs(SHARE, nil, share, func(key string, value map[string]interface{}) {
|
||||
m.Render(ice.RENDER_QRCODE, kit.Format(kit.Dict(
|
||||
kit.MDB_TYPE, "share", kit.MDB_NAME, value["type"], kit.MDB_TEXT, key,
|
||||
)))
|
||||
})
|
||||
}
|
||||
func _trash(m *ice.Message, arg ...string) {
|
||||
switch arg[0] {
|
||||
case "invite":
|
||||
arg = []string{arg[0], m.Cmdx(SHARE, "invite", kit.Select("tech", arg, 1), kit.Select("miss", arg, 2))}
|
||||
fallthrough
|
||||
case "check":
|
||||
_share_check(m, arg[1])
|
||||
case "auth":
|
||||
_share_auth(m, arg[1], arg[2])
|
||||
case "add":
|
||||
_share_create(m, arg[1], arg[2], arg[3], arg[4:]...)
|
||||
default:
|
||||
if len(arg) == 1 {
|
||||
_share_list(m, arg[0])
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SHARE = "share"
|
||||
|
||||
@ -292,46 +107,6 @@ func init() {
|
||||
"/share/cache/": {Name: "/share/cache/", Help: "缓存池", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
_share_cache(m, arg...)
|
||||
}},
|
||||
"/share/": {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Richs(SHARE, nil, kit.Select(m.Option(kit.MDB_SHARE), arg, 0), func(key string, value map[string]interface{}) {
|
||||
m.Log_SELECT(kit.MDB_META, SHARE, "arg", arg, "value", kit.Format(value))
|
||||
if m.Warn(m.Option(ice.MSG_USERROLE) != aaa.ROOT && kit.Time(kit.Format(value[kit.MDB_TIME])) < kit.Time(m.Time()), "expired") {
|
||||
m.Echo("expired")
|
||||
return
|
||||
}
|
||||
|
||||
switch value[kit.MDB_TYPE] {
|
||||
case STORY:
|
||||
value = _share_story(m, value, arg...)
|
||||
}
|
||||
|
||||
if _share_show(m, key, value, kit.Select("", arg, 1), kit.Select("", arg, 2)) {
|
||||
return
|
||||
}
|
||||
|
||||
switch value[kit.MDB_TYPE] {
|
||||
case TYPE_RIVER:
|
||||
// 共享群组
|
||||
m.Render("redirect", "/", "share", key, "river", kit.Format(value["text"]))
|
||||
|
||||
case TYPE_STORM:
|
||||
// 共享应用
|
||||
m.Render("redirect", "/", "share", key, "storm", kit.Format(value["text"]), "river", kit.Format(kit.Value(value, "extra.river")))
|
||||
|
||||
case TYPE_ACTION:
|
||||
_share_action(m, value, arg...)
|
||||
|
||||
default:
|
||||
// 查看数据
|
||||
m.Option(kit.MDB_VALUE, value)
|
||||
m.Option(kit.MDB_TYPE, value[kit.MDB_TYPE])
|
||||
m.Option(kit.MDB_NAME, value[kit.MDB_NAME])
|
||||
m.Option(kit.MDB_TEXT, value[kit.MDB_TEXT])
|
||||
m.Render(ice.RENDER_TEMPLATE, m.Conf(SHARE, "meta.template.simple"))
|
||||
m.Option(ice.MSG_OUTPUT, ice.RENDER_RESULT)
|
||||
}
|
||||
})
|
||||
}},
|
||||
"/plugin/github.com/": {Name: "/space/", Help: "空间站", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
_share_repos(m, path.Join(strings.Split(cmd, "/")[2:5]...), arg[6:]...)
|
||||
}},
|
||||
|
@ -2,6 +2,7 @@ package web
|
||||
|
||||
import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/aaa"
|
||||
"github.com/shylinux/icebergs/base/cli"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
"github.com/shylinux/icebergs/base/tcp"
|
||||
@ -61,7 +62,7 @@ func _spide_login(m *ice.Message, name string) {
|
||||
func _spide_create(m *ice.Message, name, address string, arg ...string) {
|
||||
if uri, e := url.Parse(address); e == nil && address != "" {
|
||||
if uri.Host == "random" {
|
||||
uri.Host = ":" + m.Cmdx(tcp.PORT, "get")
|
||||
uri.Host = ":" + m.Cmdx(tcp.PORT, aaa.Right)
|
||||
address = strings.Replace(address, "random", uri.Host, -1)
|
||||
}
|
||||
|
||||
|
@ -7,10 +7,13 @@ import (
|
||||
"github.com/shylinux/icebergs/base/ctx"
|
||||
"github.com/shylinux/icebergs/base/gdb"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
"github.com/shylinux/icebergs/base/tcp"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"net"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Frame struct {
|
||||
@ -70,19 +73,18 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool {
|
||||
}
|
||||
})
|
||||
|
||||
// TODO simple
|
||||
m.Richs(SPIDE, nil, arg[0], func(key string, value map[string]interface{}) {
|
||||
client := value["client"].(map[string]interface{})
|
||||
|
||||
// 服务地址
|
||||
port := m.Cap(ice.CTX_STREAM, client["hostname"])
|
||||
m.Log("serve", "listen %s %s %v", arg[0], port, m.Conf(cli.RUNTIME, "node"))
|
||||
web.m, web.Server = m, &http.Server{Handler: web}
|
||||
m.Option(tcp.LISTEN_CB, func(l net.Listener) {
|
||||
m.Event(gdb.SERVE_START, arg[0])
|
||||
m.Warn(true, "listen %s", web.Server.Serve(l))
|
||||
m.Event(gdb.SERVE_CLOSE, arg[0])
|
||||
})
|
||||
|
||||
// 启动服务
|
||||
web.m, web.Server = m, &http.Server{Addr: port, Handler: web}
|
||||
m.Event(gdb.SERVE_START, arg[0])
|
||||
m.Warn(true, "listen %s", web.Server.ListenAndServe())
|
||||
m.Event(gdb.SERVE_CLOSE, arg[0])
|
||||
ls := strings.Split(m.Cap(ice.CTX_STREAM, client["hostname"]), ":")
|
||||
m.Cmd(tcp.SERVER, tcp.LISTEN, kit.MDB_NAME, "web", tcp.HOST, ls[0], tcp.PORT, ls[1])
|
||||
})
|
||||
return true
|
||||
}
|
||||
@ -104,7 +106,6 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
|
||||
m.Cmd(aaa.ROLE, aaa.White, aaa.VOID, "web", "/publish/")
|
||||
m.Cmd(aaa.ROLE, aaa.White, aaa.VOID, ctx.COMMAND)
|
||||
|
||||
m.Cmd(mdb.SEARCH, mdb.CREATE, FAVOR)
|
||||
m.Cmd(mdb.SEARCH, mdb.CREATE, SPIDE)
|
||||
m.Cmd(mdb.RENDER, mdb.CREATE, SPIDE)
|
||||
m.Cmd(mdb.SEARCH, mdb.CREATE, SPACE)
|
||||
@ -116,8 +117,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
|
||||
})
|
||||
}},
|
||||
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Save(SPIDE, SERVE, GROUP, LABEL,
|
||||
FAVOR, CACHE, STORY, SHARE)
|
||||
m.Save(SPIDE, SERVE, CACHE, SHARE, STORY)
|
||||
|
||||
m.Done()
|
||||
m.Richs(SPACE, nil, "*", func(key string, value map[string]interface{}) {
|
||||
@ -131,7 +131,6 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
|
||||
|
||||
func init() {
|
||||
ice.Index.Register(Index, &Frame{},
|
||||
SPIDE, SERVE, SPACE, DREAM,
|
||||
CACHE, FAVOR, STORY, SHARE,
|
||||
SPIDE, SERVE, SPACE, DREAM, CACHE, SHARE, STORY,
|
||||
)
|
||||
}
|
||||
|
2
conf.go
2
conf.go
@ -100,8 +100,8 @@ const ( // RENDER
|
||||
RENDER_OUTPUT = "_output"
|
||||
RENDER_RESULT = "_result"
|
||||
RENDER_QRCODE = "_qrcode"
|
||||
RENDER_TEMPLATE = "_template"
|
||||
RENDER_DOWNLOAD = "_download"
|
||||
RENDER_TEMPLATE = "_template"
|
||||
)
|
||||
|
||||
const ( // TODO
|
||||
|
@ -36,7 +36,7 @@ func _action_show(m *ice.Message, river, storm, index string, arg ...string) {
|
||||
prefix := kit.Keys(kit.MDB_HASH, river, TOOL, kit.MDB_HASH, storm)
|
||||
if m.Grows(RIVER, prefix, kit.MDB_ID, index, func(index int, value map[string]interface{}) {
|
||||
if cmds = kit.Simple(kit.Keys(value[CTX], value[CMD])); kit.Format(value[POD]) != "" {
|
||||
m.Option(kit.GDB_POD, value[POD])
|
||||
m.Option(kit.SSH_POD, value[POD])
|
||||
}
|
||||
}) == nil && m.Warn(!m.Right(cmds), ice.ErrNotAuth) {
|
||||
return
|
||||
|
@ -124,7 +124,7 @@ func init() {
|
||||
m.Cmdy(mdb.SELECT, RIVER, kit.Keys(kit.MDB_HASH, m.Option(ice.MSG_RIVER), NODE), mdb.HASH)
|
||||
m.Table(func(index int, value map[string]string, head []string) {
|
||||
m.PushRender(kit.MDB_LINK, "a", value[kit.MDB_NAME],
|
||||
kit.MergeURL(m.Option(ice.MSG_USERWEB), kit.GDB_POD, kit.Keys(m.Option(kit.GDB_POD), value[kit.MDB_NAME])))
|
||||
kit.MergeURL(m.Option(ice.MSG_USERWEB), kit.SSH_POD, kit.Keys(m.Option(kit.SSH_POD), value[kit.MDB_NAME])))
|
||||
})
|
||||
m.PushAction("删除")
|
||||
return
|
||||
|
59
core/code/_trash.go
Normal file
59
core/code/_trash.go
Normal file
@ -0,0 +1,59 @@
|
||||
package code
|
||||
|
||||
func _pprof_show(m *ice.Message, zone string, id string) {
|
||||
favor := m.Conf(PPROF, kit.Keys(kit.MDB_META, web.FAVOR))
|
||||
|
||||
m.Richs(PPROF, nil, zone, func(key string, val map[string]interface{}) {
|
||||
val = val[kit.MDB_META].(map[string]interface{})
|
||||
|
||||
list := []string{}
|
||||
task.Put(val, func(task *task.Task) error {
|
||||
m.Sleep("1s")
|
||||
m.Grows(PPROF, kit.Keys(kit.MDB_HASH, key), "", "", func(index int, value map[string]interface{}) {
|
||||
// 压测命令
|
||||
m.Log_EXPORT(kit.MDB_META, PPROF, kit.MDB_ZONE, zone, kit.MDB_VALUE, kit.Format(value))
|
||||
cmd := kit.Format(value[kit.MDB_TYPE])
|
||||
arg := kit.Format(value[kit.MDB_TEXT])
|
||||
res := m.Cmd(mdb.ENGINE, value[kit.MDB_TYPE], value[kit.MDB_NAME], value[kit.MDB_TEXT], value[kit.MDB_EXTRA]).Result()
|
||||
m.Cmd(web.FAVOR, favor, cmd, arg, res)
|
||||
list = append(list, cmd+": "+arg, res)
|
||||
})
|
||||
return nil
|
||||
})
|
||||
|
||||
// 收藏程序
|
||||
msg := m.Cmd(web.CACHE, web.CATCH, kit.MIME_FILE, kit.Format(val[BINNARY]))
|
||||
bin := msg.Append(kit.MDB_TEXT)
|
||||
m.Cmd(web.FAVOR, favor, kit.MIME_FILE, bin, val[BINNARY])
|
||||
|
||||
// 性能分析
|
||||
msg = m.Cmd(web.SPIDE, "self", web.CACHE, http.MethodGet, kit.Select("/code/pprof/profile", val[SERVICE]), "seconds", kit.Select("5", kit.Format(val[SECONDS])))
|
||||
m.Cmd(web.FAVOR, favor, PPROF, msg.Append(kit.MDB_TEXT), kit.Keys(zone, "pd.gz"))
|
||||
|
||||
// 结果摘要
|
||||
cmd := kit.Simple(m.Confv(PPROF, "meta.pprof"), "-text", val[BINNARY], msg.Append(kit.MDB_TEXT))
|
||||
res := strings.Split(m.Cmdx(cli.SYSTEM, cmd), "\n")
|
||||
if len(res) > 20 {
|
||||
res = res[:20]
|
||||
}
|
||||
m.Cmd(web.FAVOR, favor, web.TYPE_SHELL, strings.Join(cmd, " "), strings.Join(res, "\n"))
|
||||
list = append(list, web.TYPE_SHELL+": "+strings.Join(cmd, " "), strings.Join(res, "\n"))
|
||||
|
||||
// 结果展示
|
||||
u := kit.ParseURL(m.Option(ice.MSG_USERWEB))
|
||||
p := kit.Format("%s:%s", u.Hostname(), m.Cmdx(tcp.PORT, aaa.Right))
|
||||
m.Option(cli.CMD_STDOUT, "var/daemon/stdout")
|
||||
m.Option(cli.CMD_STDERR, "var/daemon/stderr")
|
||||
m.Cmd(cli.DAEMON, m.Confv(PPROF, "meta.pprof"), "-http="+p, val[BINNARY], msg.Append(kit.MDB_TEXT))
|
||||
|
||||
url := u.Scheme + "://" + p + "/ui/top"
|
||||
m.Cmd(web.FAVOR, favor, web.SPIDE, url, msg.Append(kit.MDB_TEXT))
|
||||
m.Set(ice.MSG_RESULT).Echo(url).Echo(" \n").Echo("\n")
|
||||
m.Echo(strings.Join(list, "\n")).Echo("\n")
|
||||
|
||||
m.Push("url", url)
|
||||
m.Push(PPROF, msg.Append(kit.MDB_TEXT))
|
||||
m.Push(SERVICE, strings.Replace(kit.Format(val[SERVICE]), "profile", "", -1))
|
||||
m.Push("bin", bin)
|
||||
})
|
||||
}
|
@ -2,6 +2,7 @@ package code
|
||||
|
||||
import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/aaa"
|
||||
"github.com/shylinux/icebergs/base/cli"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
"github.com/shylinux/icebergs/base/nfs"
|
||||
@ -49,10 +50,10 @@ func init() {
|
||||
value = value[kit.MDB_META].(map[string]interface{})
|
||||
m.Optionv("progress", func(size int, total int) {
|
||||
s := size * 100 / total
|
||||
if s != kit.Int(value[kit.MDB_STEP]) && s%10 == 0 {
|
||||
m.Log_IMPORT(kit.MDB_FILE, name, kit.MDB_STEP, s, kit.MDB_SIZE, kit.FmtSize(int64(size)), kit.MDB_TOTAL, kit.FmtSize(int64(total)))
|
||||
if s != kit.Int(value[kit.SSH_STEP]) && s%10 == 0 {
|
||||
m.Log_IMPORT(kit.MDB_FILE, name, kit.SSH_STEP, s, kit.MDB_SIZE, kit.FmtSize(int64(size)), kit.MDB_TOTAL, kit.FmtSize(int64(total)))
|
||||
}
|
||||
value[kit.MDB_STEP], value[kit.MDB_SIZE], value[kit.MDB_TOTAL] = s, size, total
|
||||
value[kit.SSH_STEP], value[kit.MDB_SIZE], value[kit.MDB_TOTAL] = s, size, total
|
||||
})
|
||||
})
|
||||
|
||||
@ -85,7 +86,7 @@ func init() {
|
||||
m.Cmdy(cli.SYSTEM, "make", "PREFIX="+kit.Path(path.Join(p, kit.Select("_install", m.Option("install")))), "install")
|
||||
}},
|
||||
"spawn": {Name: "spawn link", Help: "新建", Hand: func(m *ice.Message, arg ...string) {
|
||||
port := m.Cmdx(tcp.PORT, "select")
|
||||
port := m.Cmdx(tcp.PORT, aaa.Right)
|
||||
target := path.Join(m.Conf(cli.DAEMON, kit.META_PATH), port)
|
||||
source := path.Join(m.Conf(INSTALL, kit.META_PATH), kit.TrimExt(arg[0]))
|
||||
|
||||
@ -122,10 +123,10 @@ func init() {
|
||||
// 服务列表
|
||||
if strings.Contains(value[kit.MDB_NAME], key) {
|
||||
m.Push(kit.MDB_TIME, value[kit.MDB_TIME])
|
||||
m.Push(kit.MDB_PORT, path.Base(value[kit.MDB_DIR]))
|
||||
m.Push(kit.SSH_PORT, path.Base(value[kit.SSH_DIR]))
|
||||
m.Push(kit.MDB_STATUS, value[kit.MDB_STATUS])
|
||||
m.Push(kit.MDB_NAME, value[kit.MDB_NAME])
|
||||
m.PushRender(kit.MDB_LINK, "a", kit.Format("http://%s:%s", u.Hostname(), path.Base(value[kit.MDB_DIR])))
|
||||
m.PushRender(kit.MDB_LINK, "a", kit.Format("http://%s:%s", u.Hostname(), path.Base(value[kit.SSH_DIR])))
|
||||
}
|
||||
})
|
||||
return
|
||||
|
@ -2,12 +2,9 @@ package code
|
||||
|
||||
import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/cli"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
"github.com/shylinux/icebergs/base/tcp"
|
||||
"github.com/shylinux/icebergs/base/web"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
"github.com/shylinux/toolkits/task"
|
||||
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
@ -36,63 +33,6 @@ func _pprof_list(m *ice.Message, zone string, id string, field ...interface{}) {
|
||||
}
|
||||
})
|
||||
}
|
||||
func _pprof_show(m *ice.Message, zone string, id string) {
|
||||
favor := m.Conf(PPROF, kit.Keys(kit.MDB_META, web.FAVOR))
|
||||
|
||||
m.Richs(PPROF, nil, zone, func(key string, val map[string]interface{}) {
|
||||
val = val[kit.MDB_META].(map[string]interface{})
|
||||
|
||||
list := []string{}
|
||||
task.Put(val, func(task *task.Task) error {
|
||||
m.Sleep("1s")
|
||||
m.Grows(PPROF, kit.Keys(kit.MDB_HASH, key), "", "", func(index int, value map[string]interface{}) {
|
||||
// 压测命令
|
||||
m.Log_EXPORT(kit.MDB_META, PPROF, kit.MDB_ZONE, zone, kit.MDB_VALUE, kit.Format(value))
|
||||
cmd := kit.Format(value[kit.MDB_TYPE])
|
||||
arg := kit.Format(value[kit.MDB_TEXT])
|
||||
res := m.Cmd(mdb.ENGINE, value[kit.MDB_TYPE], value[kit.MDB_NAME], value[kit.MDB_TEXT], value[kit.MDB_EXTRA]).Result()
|
||||
m.Cmd(web.FAVOR, favor, cmd, arg, res)
|
||||
list = append(list, cmd+": "+arg, res)
|
||||
})
|
||||
return nil
|
||||
})
|
||||
|
||||
// 收藏程序
|
||||
msg := m.Cmd(web.CACHE, web.CATCH, kit.MIME_FILE, kit.Format(val[BINNARY]))
|
||||
bin := msg.Append(kit.MDB_TEXT)
|
||||
m.Cmd(web.FAVOR, favor, kit.MIME_FILE, bin, val[BINNARY])
|
||||
|
||||
// 性能分析
|
||||
msg = m.Cmd(web.SPIDE, "self", web.CACHE, http.MethodGet, kit.Select("/code/pprof/profile", val[SERVICE]), "seconds", kit.Select("5", kit.Format(val[SECONDS])))
|
||||
m.Cmd(web.FAVOR, favor, PPROF, msg.Append(kit.MDB_TEXT), kit.Keys(zone, "pd.gz"))
|
||||
|
||||
// 结果摘要
|
||||
cmd := kit.Simple(m.Confv(PPROF, "meta.pprof"), "-text", val[BINNARY], msg.Append(kit.MDB_TEXT))
|
||||
res := strings.Split(m.Cmdx(cli.SYSTEM, cmd), "\n")
|
||||
if len(res) > 20 {
|
||||
res = res[:20]
|
||||
}
|
||||
m.Cmd(web.FAVOR, favor, web.TYPE_SHELL, strings.Join(cmd, " "), strings.Join(res, "\n"))
|
||||
list = append(list, web.TYPE_SHELL+": "+strings.Join(cmd, " "), strings.Join(res, "\n"))
|
||||
|
||||
// 结果展示
|
||||
u := kit.ParseURL(m.Option(ice.MSG_USERWEB))
|
||||
p := kit.Format("%s:%s", u.Hostname(), m.Cmdx(tcp.PORT, "get"))
|
||||
m.Option(cli.CMD_STDOUT, "var/daemon/stdout")
|
||||
m.Option(cli.CMD_STDERR, "var/daemon/stderr")
|
||||
m.Cmd(cli.DAEMON, m.Confv(PPROF, "meta.pprof"), "-http="+p, val[BINNARY], msg.Append(kit.MDB_TEXT))
|
||||
|
||||
url := u.Scheme + "://" + p + "/ui/top"
|
||||
m.Cmd(web.FAVOR, favor, web.SPIDE, url, msg.Append(kit.MDB_TEXT))
|
||||
m.Set(ice.MSG_RESULT).Echo(url).Echo(" \n").Echo("\n")
|
||||
m.Echo(strings.Join(list, "\n")).Echo("\n")
|
||||
|
||||
m.Push("url", url)
|
||||
m.Push(PPROF, msg.Append(kit.MDB_TEXT))
|
||||
m.Push(SERVICE, strings.Replace(kit.Format(val[SERVICE]), "profile", "", -1))
|
||||
m.Push("bin", bin)
|
||||
})
|
||||
}
|
||||
func _pprof_modify(m *ice.Message, zone, id, k, v, old string) {
|
||||
k = kit.Select(k, m.Option(kit.MDB_KEY))
|
||||
m.Richs(PPROF, nil, kit.Select(kit.MDB_FOREACH, zone), func(key string, val map[string]interface{}) {
|
||||
@ -141,7 +81,7 @@ func init() {
|
||||
Index.Merge(&ice.Context{
|
||||
Configs: map[string]*ice.Config{
|
||||
PPROF: {Name: "pprof", Help: "性能分析", Value: kit.Data(kit.MDB_SHORT, kit.MDB_ZONE,
|
||||
web.FAVOR, "pprof", PPROF, []string{"go", "tool", "pprof"},
|
||||
PPROF, []string{"go", "tool", "pprof"},
|
||||
)},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
@ -163,7 +103,7 @@ func init() {
|
||||
_pprof_modify(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID), arg[0], arg[1], kit.Select("", arg, 2))
|
||||
}},
|
||||
kit.MDB_SHOW: {Name: "show type name text arg...", Help: "运行", Hand: func(m *ice.Message, arg ...string) {
|
||||
_pprof_show(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID))
|
||||
// _pprof_show(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID))
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
_pprof_list(m, kit.Select(kit.MDB_FOREACH, arg, 0), kit.Select("", arg, 1))
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"path"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -20,7 +19,6 @@ func init() {
|
||||
"display", "/plugin/local/team/plan.js", "style", "plan",
|
||||
), Action: map[string]*ice.Action{
|
||||
mdb.INSERT: {Name: "insert zone type=once,step,week name text begin_time@date close_time@date", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_create(m, arg[1])
|
||||
_task_insert(m, arg[1], arg[2:]...)
|
||||
}},
|
||||
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
|
||||
@ -30,20 +28,20 @@ func init() {
|
||||
_task_delete(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID))
|
||||
}},
|
||||
mdb.EXPORT: {Name: "export file", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_export(m, kit.Select(path.Join(EXPORT, m.Option(ice.MSG_DOMAIN), "list.csv")))
|
||||
_task_export(m, m.Option(kit.MDB_FILE))
|
||||
}},
|
||||
mdb.IMPORT: {Name: "import file", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_import(m, kit.Select(path.Join(EXPORT, m.Option(ice.MSG_DOMAIN), "list.csv")))
|
||||
_task_import(m, m.Option(kit.MDB_FILE))
|
||||
}},
|
||||
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_input(m, kit.Select("", arg, 0), kit.Select("", arg, 1))
|
||||
_task_inputs(m, kit.Select("", arg, 0), kit.Select("", arg, 1))
|
||||
}},
|
||||
|
||||
gdb.BEGIN: {Name: "begin", Help: "开始", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_modify(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID), STATUS, StatusProcess)
|
||||
_task_modify(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID), TaskField.STATUS, TaskStatus.PROCESS)
|
||||
}},
|
||||
gdb.END: {Name: "end", Help: "完成", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_modify(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID), STATUS, StatusFinish)
|
||||
_task_modify(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID), TaskField.STATUS, TaskStatus.FINISH)
|
||||
}},
|
||||
|
||||
"command": {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
|
||||
@ -54,21 +52,20 @@ func init() {
|
||||
m.Cmdy(arg[0], arg[1:])
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
begin_time, end_time := _task_scope(m, arg...)
|
||||
|
||||
m.Set(ice.MSG_OPTION, "end_time")
|
||||
begin_time, end_time := _task_scope(m, 8, arg...)
|
||||
m.Set(ice.MSG_OPTION, "begin_time")
|
||||
m.Richs(TASK, kit.Keys(kit.MDB_HASH, m.Optionv(ice.MSG_DOMAIN)), kit.Select(kit.MDB_FOREACH, m.Option(kit.MDB_ZONE)), func(key string, val map[string]interface{}) {
|
||||
zone := kit.Format(kit.Value(val, "meta.zone"))
|
||||
m.Grows(TASK, kit.Keys(kit.MDB_HASH, m.Optionv(ice.MSG_DOMAIN), kit.MDB_HASH, key), "", "", func(index int, value map[string]interface{}) {
|
||||
begin, _ := time.ParseInLocation(ice.MOD_TIME, kit.Format(value[BEGIN_TIME]), time.Local)
|
||||
if begin_time.Before(begin) && begin.Before(end_time) {
|
||||
m.Push(zone, value)
|
||||
m.Push(kit.MDB_ZONE, zone)
|
||||
m.PushAction(_task_action(m, value[STATUS], "插件"))
|
||||
}
|
||||
})
|
||||
m.Set(ice.MSG_OPTION, "end_time")
|
||||
|
||||
m.Option(mdb.FIELDS, "begin_time,close_time,zone,id,level,status,score,type,name,text,extra")
|
||||
m.Option("cache.cb", func(key string, fields []string, value, val map[string]interface{}) {
|
||||
begin, _ := time.ParseInLocation(ice.MOD_TIME, kit.Format(value[TaskField.BEGIN_TIME]), time.Local)
|
||||
if begin_time.After(begin) || begin.After(end_time) {
|
||||
return
|
||||
}
|
||||
m.Push(key, value, fields, val)
|
||||
m.PushRender(kit.MDB_ACTION, kit.MDB_BUTTON, _task_action(m, value[TaskField.STATUS], "插件"))
|
||||
})
|
||||
m.Cmdy(mdb.SELECT, m.Prefix(TASK), kit.Keys(m.Option(ice.MSG_DOMAIN)), mdb.ZONE)
|
||||
}},
|
||||
},
|
||||
}, nil)
|
||||
|
@ -6,60 +6,84 @@ import (
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func _sub_key(m *ice.Message, zone string) string {
|
||||
return kit.Keys(m.Optionv(ice.MSG_DOMAIN), kit.MDB_HASH, kit.Hashs(zone))
|
||||
return kit.Keys(m.Option(ice.MSG_DOMAIN), kit.MDB_HASH, kit.Hashs(zone))
|
||||
}
|
||||
|
||||
func _task_action(m *ice.Message, status interface{}, action ...string) string {
|
||||
switch status {
|
||||
case TaskStatus.PREPARE:
|
||||
action = append(action, "开始")
|
||||
case TaskStatus.PROCESS:
|
||||
action = append(action, "完成")
|
||||
case TaskStatus.CANCEL:
|
||||
case TaskStatus.FINISH:
|
||||
}
|
||||
return strings.Join(action, ",")
|
||||
}
|
||||
func _task_list(m *ice.Message, zone string, id string) {
|
||||
m.Option(mdb.FIELDS, "begin_time,zone,id,status,level,type,name,text")
|
||||
m.Cmdy(mdb.SELECT, m.Prefix(TASK), kit.Keys(m.Optionv(ice.MSG_DOMAIN)), mdb.ZONE, zone, id)
|
||||
if zone == "" {
|
||||
m.Option(mdb.FIELDS, "time,zone,count")
|
||||
} else if id == "" {
|
||||
m.Option(mdb.FIELDS, "begin_time,id,status,level,score,type,name,text")
|
||||
defer m.Table(func(index int, value map[string]string, head []string) {
|
||||
m.PushRender(kit.MDB_ACTION, kit.MDB_BUTTON, _task_action(m, value[TaskField.STATUS]))
|
||||
})
|
||||
} else {
|
||||
m.Option(mdb.FIELDS, mdb.DETAIL)
|
||||
defer m.Table(func(index int, value map[string]string, head []string) {
|
||||
if value[kit.MDB_KEY] == kit.MDB_STATUS {
|
||||
m.Push(kit.MDB_KEY, kit.MDB_ACTION)
|
||||
m.PushRender(kit.MDB_VALUE, kit.MDB_BUTTON, _task_action(m, value[kit.MDB_VALUE]))
|
||||
}
|
||||
})
|
||||
}
|
||||
m.Cmdy(mdb.SELECT, m.Prefix(TASK), m.Option(ice.MSG_DOMAIN), mdb.ZONE, zone, id)
|
||||
}
|
||||
func _task_create(m *ice.Message, zone string) {
|
||||
m.Conf(m.Prefix(TASK), kit.Keys(m.Optionv(ice.MSG_DOMAIN), kit.MDB_META, kit.MDB_SHORT), kit.MDB_ZONE)
|
||||
m.Cmdy(mdb.INSERT, m.Prefix(TASK), kit.Keys(m.Optionv(ice.MSG_DOMAIN)), mdb.HASH, kit.MDB_ZONE, zone)
|
||||
if msg := m.Cmd(mdb.SELECT, m.Prefix(TASK), m.Option(ice.MSG_DOMAIN), mdb.HASH, kit.MDB_ZONE, zone); len(msg.Appendv(kit.MDB_HASH)) == 0 {
|
||||
m.Conf(m.Prefix(TASK), kit.Keys(m.Option(ice.MSG_DOMAIN), kit.MDB_META, kit.MDB_SHORT), kit.MDB_ZONE)
|
||||
m.Cmdy(mdb.INSERT, m.Prefix(TASK), m.Option(ice.MSG_DOMAIN), mdb.HASH, kit.MDB_ZONE, zone)
|
||||
}
|
||||
}
|
||||
func _task_insert(m *ice.Message, zone string, arg ...string) {
|
||||
if msg := m.Cmd(mdb.SELECT, m.Prefix(TASK), kit.Keys(m.Optionv(ice.MSG_DOMAIN)), mdb.HASH, kit.MDB_ZONE, zone); len(msg.Appendv(kit.MDB_HASH)) == 0 {
|
||||
m.Debug("what %v", msg.Formats("meta"))
|
||||
_task_create(m, zone)
|
||||
}
|
||||
|
||||
m.Cmdy(mdb.INSERT, m.Prefix(TASK), _sub_key(m, zone), mdb.LIST,
|
||||
BEGIN_TIME, m.Time(), CLOSE_TIME, m.Time("30m"), STATUS, StatusPrepare, LEVEL, 3, SCORE, 3, arg,
|
||||
TaskField.BEGIN_TIME, m.Time(), TaskField.CLOSE_TIME, m.Time("30m"),
|
||||
TaskField.STATUS, TaskStatus.PREPARE, TaskField.LEVEL, 3, TaskField.SCORE, 3,
|
||||
arg,
|
||||
)
|
||||
}
|
||||
func _task_modify(m *ice.Message, zone, id, field, value string, arg ...string) {
|
||||
if field == STATUS {
|
||||
if field == TaskField.STATUS {
|
||||
switch value {
|
||||
case StatusProcess:
|
||||
arg = append(arg, BEGIN_TIME, m.Time())
|
||||
case StatusCancel, StatusFinish:
|
||||
arg = append(arg, CLOSE_TIME, m.Time())
|
||||
case TaskStatus.PROCESS:
|
||||
arg = append(arg, TaskField.BEGIN_TIME, m.Time())
|
||||
case TaskStatus.CANCEL, TaskStatus.FINISH:
|
||||
arg = append(arg, TaskField.CLOSE_TIME, m.Time())
|
||||
}
|
||||
}
|
||||
m.Cmdy(mdb.MODIFY, m.Prefix(TASK), _sub_key(m, zone), mdb.LIST, kit.MDB_ID, id, field, value, arg)
|
||||
}
|
||||
func _task_delete(m *ice.Message, zone, id string) {
|
||||
m.Cmdy(mdb.MODIFY, m.Prefix(TASK), _sub_key(m, zone), mdb.LIST, kit.MDB_ID, id, STATUS, StatusCancel)
|
||||
m.Cmdy(mdb.MODIFY, m.Prefix(TASK), _sub_key(m, zone), mdb.LIST, kit.MDB_ID, id, TaskField.STATUS, TaskStatus.CANCEL)
|
||||
}
|
||||
func _task_export(m *ice.Message, file string) {
|
||||
m.Option(mdb.FIELDS, "zone,id,time,type,name,text,level,status,score,begin_time,close_time,extra")
|
||||
m.Cmdy(mdb.EXPORT, m.Prefix(TASK), kit.Keys(m.Optionv(ice.MSG_DOMAIN)), mdb.ZONE)
|
||||
m.Cmdy(mdb.EXPORT, m.Prefix(TASK), m.Option(ice.MSG_DOMAIN), mdb.ZONE, file)
|
||||
}
|
||||
func _task_import(m *ice.Message, file string) {
|
||||
m.Option(mdb.FIELDS, kit.MDB_ZONE)
|
||||
m.Cmdy(mdb.IMPORT, m.Prefix(TASK), kit.Keys(m.Optionv(ice.MSG_DOMAIN)), mdb.ZONE, file)
|
||||
m.Option(mdb.FIELDS, "zone")
|
||||
m.Cmdy(mdb.IMPORT, m.Prefix(TASK), m.Option(ice.MSG_DOMAIN), mdb.ZONE, file)
|
||||
}
|
||||
func _task_input(m *ice.Message, field, value string) {
|
||||
func _task_inputs(m *ice.Message, field, value string) {
|
||||
switch field {
|
||||
case kit.MDB_ZONE:
|
||||
m.Cmdy(mdb.INPUTS, m.Prefix(TASK), kit.Keys(m.Optionv(ice.MSG_DOMAIN)), mdb.HASH, field, value)
|
||||
case kit.MDB_NAME, kit.MDB_TEXT:
|
||||
m.Cmdy(mdb.INPUTS, m.Prefix(TASK), m.Option(ice.MSG_DOMAIN), mdb.HASH, field, value)
|
||||
case kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT:
|
||||
m.Cmdy(mdb.INPUTS, m.Prefix(TASK), _sub_key(m, m.Option(kit.MDB_ZONE)), mdb.LIST, field, value)
|
||||
}
|
||||
}
|
||||
@ -89,95 +113,88 @@ func _task_render(m *ice.Message, kind, name, text string, arg ...string) {
|
||||
})
|
||||
})
|
||||
}
|
||||
func _task_action(m *ice.Message, status interface{}, action ...string) []string {
|
||||
switch status {
|
||||
case StatusPrepare:
|
||||
action = append(action, "开始")
|
||||
case StatusProcess:
|
||||
action = append(action, "完成")
|
||||
case StatusCancel, StatusFinish:
|
||||
}
|
||||
return action
|
||||
}
|
||||
func _task_scope(m *ice.Message, arg ...string) (time.Time, time.Time) {
|
||||
func _task_scope(m *ice.Message, tz int, arg ...string) (time.Time, time.Time) {
|
||||
begin_time := time.Now()
|
||||
if len(arg) > 1 {
|
||||
begin_time, _ = time.ParseInLocation(ice.MOD_TIME, arg[1], time.Local)
|
||||
}
|
||||
end_time := begin_time
|
||||
|
||||
switch begin_time = begin_time.Add(-time.Duration(begin_time.UnixNano()) % (24 * time.Hour)); arg[0] {
|
||||
case ScaleDay:
|
||||
end_time := begin_time
|
||||
switch begin_time = begin_time.Add(-time.Duration(begin_time.UnixNano())%(24*time.Hour) - time.Duration(tz)*time.Hour); arg[0] {
|
||||
case TaskScale.DAY:
|
||||
end_time = begin_time.AddDate(0, 0, 1)
|
||||
case ScaleWeek:
|
||||
case TaskScale.WEEK:
|
||||
begin_time = begin_time.AddDate(0, 0, -int(begin_time.Weekday()))
|
||||
end_time = begin_time.AddDate(0, 0, 7)
|
||||
case ScaleMonth:
|
||||
case TaskScale.MONTH:
|
||||
begin_time = begin_time.AddDate(0, 0, -begin_time.Day()+1)
|
||||
end_time = begin_time.AddDate(0, 1, 0)
|
||||
case ScaleYear:
|
||||
case TaskScale.YEAR:
|
||||
begin_time = begin_time.AddDate(0, 0, -begin_time.YearDay()+1)
|
||||
end_time = begin_time.AddDate(1, 0, 0)
|
||||
case ScaleLong:
|
||||
case TaskScale.LONG:
|
||||
begin_time = begin_time.AddDate(0, 0, -begin_time.YearDay()+1)
|
||||
begin_time = begin_time.AddDate(-begin_time.Year()%5, 0, 0)
|
||||
end_time = begin_time.AddDate(5, 0, 0)
|
||||
}
|
||||
|
||||
begin_time = begin_time.Add(-8 * time.Hour)
|
||||
end_time = end_time.Add(-8 * time.Hour)
|
||||
return begin_time, end_time
|
||||
}
|
||||
|
||||
const (
|
||||
LEVEL = "level"
|
||||
STATUS = "status"
|
||||
SCORE = "score"
|
||||
var TaskField = struct{ LEVEL, STATUS, SCORE, BEGIN_TIME, CLOSE_TIME string }{
|
||||
LEVEL: "level",
|
||||
STATUS: "status",
|
||||
SCORE: "score",
|
||||
|
||||
BEGIN_TIME = "begin_time"
|
||||
CLOSE_TIME = "close_time"
|
||||
BEGIN_TIME: "begin_time",
|
||||
CLOSE_TIME: "close_time",
|
||||
}
|
||||
var TaskStatus = struct{ PREPARE, PROCESS, CANCEL, FINISH string }{
|
||||
PREPARE: "prepare",
|
||||
PROCESS: "process",
|
||||
CANCEL: "cancel",
|
||||
FINISH: "finish",
|
||||
}
|
||||
var TaskType = struct{ ONCE, STEP, WEEK string }{
|
||||
ONCE: "once",
|
||||
STEP: "step",
|
||||
WEEK: "week",
|
||||
}
|
||||
var TaskScale = struct{ DAY, WEEK, MONTH, YEAR, LONG string }{
|
||||
DAY: "day",
|
||||
WEEK: "week",
|
||||
MONTH: "month",
|
||||
YEAR: "year",
|
||||
LONG: "long",
|
||||
}
|
||||
|
||||
EXPORT = "usr/export/web.team.task/"
|
||||
)
|
||||
const (
|
||||
ScaleDay = "day"
|
||||
ScaleWeek = "week"
|
||||
ScaleMonth = "month"
|
||||
ScaleYear = "year"
|
||||
ScaleLong = "long"
|
||||
)
|
||||
const (
|
||||
StatusPrepare = "prepare"
|
||||
StatusProcess = "process"
|
||||
StatusCancel = "cancel"
|
||||
StatusFinish = "finish"
|
||||
)
|
||||
const TASK = "task"
|
||||
|
||||
func init() {
|
||||
Index.Merge(&ice.Context{
|
||||
Configs: map[string]*ice.Config{
|
||||
TASK: {Name: "task", Help: "task", Value: kit.Data(kit.MDB_SHORT, kit.MDB_ZONE)},
|
||||
TASK: {Name: TASK, Help: "任务", Value: kit.Data(kit.MDB_SHORT, kit.MDB_ZONE)},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
TASK: {Name: "task zone id auto 添加 导出 导入", Help: "任务", Action: map[string]*ice.Action{
|
||||
mdb.INSERT: {Name: "insert zone@key type=once,step,week name@key text@key begin_time@date close_time@date", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_create(m, arg[1])
|
||||
_task_insert(m, arg[1], arg[2:]...)
|
||||
}},
|
||||
mdb.MODIFY: {Name: "modify key value", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
|
||||
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_modify(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID), arg[0], arg[1])
|
||||
}},
|
||||
mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_delete(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID))
|
||||
}},
|
||||
mdb.EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_export(m, kit.Select(path.Join(EXPORT, m.Option(ice.MSG_DOMAIN), "list.csv"), arg, 0))
|
||||
mdb.EXPORT: {Name: "export file", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_export(m, m.Option(kit.MDB_FILE))
|
||||
}},
|
||||
mdb.IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_import(m, kit.Select(path.Join(EXPORT, m.Option(ice.MSG_DOMAIN), "list.csv"), arg, 0))
|
||||
mdb.IMPORT: {Name: "import file", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_import(m, m.Option(kit.MDB_FILE))
|
||||
}},
|
||||
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_input(m, kit.Select("", arg, 0), kit.Select("", arg, 1))
|
||||
_task_inputs(m, kit.Select("", arg, 0), kit.Select("", arg, 1))
|
||||
}},
|
||||
|
||||
mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
|
||||
@ -188,18 +205,13 @@ func init() {
|
||||
}},
|
||||
|
||||
gdb.BEGIN: {Name: "begin", Help: "开始", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_modify(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID), STATUS, StatusProcess)
|
||||
_task_modify(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID), TaskField.STATUS, TaskStatus.PROCESS)
|
||||
}},
|
||||
gdb.END: {Name: "end", Help: "完成", Hand: func(m *ice.Message, arg ...string) {
|
||||
_task_modify(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID), STATUS, StatusFinish)
|
||||
_task_modify(m, m.Option(kit.MDB_ZONE), m.Option(kit.MDB_ID), TaskField.STATUS, TaskStatus.FINISH)
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Cmdy(mdb.SELECT, m.Prefix(TASK), m.Option(ice.MSG_DOMAIN), mdb.ZONE, arg)
|
||||
if len(arg) > 0 {
|
||||
m.Table(func(index int, value map[string]string, head []string) {
|
||||
m.PushRender("action", "button", "", _task_action(m, value[STATUS])...)
|
||||
})
|
||||
}
|
||||
_task_list(m, kit.Select("", arg, 0), kit.Select("", arg, 1))
|
||||
}},
|
||||
},
|
||||
}, nil)
|
||||
|
@ -387,7 +387,9 @@ func init() {
|
||||
arg = append(arg, kit.Select(ns[len(ns)-1], ""))
|
||||
}
|
||||
|
||||
arg = _name(m, arg)
|
||||
if len(arg) == 1 {
|
||||
arg = append(arg, "")
|
||||
}
|
||||
_title_show(m, arg[0], kit.Select(arg[0], arg[1]), arg[2:]...)
|
||||
}},
|
||||
BRIEF: {Name: "brief [name] text", Help: "摘要", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
|
16
init.go
16
init.go
@ -97,7 +97,7 @@ var Index = &Context{Name: "ice", Help: "冰山模块",
|
||||
m.root.Cmd(CTX_INIT)
|
||||
|
||||
m.target.root.wg = &sync.WaitGroup{}
|
||||
for _, k := range kit.Split(kit.Select("gdb,log,ssh,ctx", os.Getenv("ctx_mod"))) {
|
||||
for _, k := range kit.Split(kit.Select("gdb,log,ssh")) {
|
||||
m.Start(k)
|
||||
}
|
||||
|
||||
@ -186,20 +186,6 @@ func Run(arg ...string) string {
|
||||
|
||||
var names = map[string]interface{}{}
|
||||
|
||||
var ErrNameExists = "name already exists:"
|
||||
|
||||
type Error struct {
|
||||
Arg []interface{}
|
||||
FileLine string
|
||||
}
|
||||
|
||||
func NewError(n int, arg ...interface{}) *Error {
|
||||
return &Error{Arg: arg, FileLine: kit.FileLine(n, 3)}
|
||||
}
|
||||
func (e *Error) Error() string {
|
||||
return e.FileLine + " " + strings.Join(kit.Simple(e.Arg), " ")
|
||||
}
|
||||
|
||||
func Name(name string, value interface{}) string {
|
||||
if s, ok := names[name]; ok {
|
||||
last := ""
|
||||
|
21
misc.go
21
misc.go
@ -89,8 +89,13 @@ func (m *Message) PushRender(key, view, name string, arg ...string) *Message {
|
||||
return m
|
||||
}
|
||||
func (m *Message) PushAction(list ...interface{}) {
|
||||
if len(m.meta[MSG_APPEND]) > 0 && m.meta[MSG_APPEND][0] == kit.MDB_KEY {
|
||||
m.Push(kit.MDB_KEY, kit.MDB_ACTION)
|
||||
m.PushRender(kit.MDB_VALUE, kit.MDB_BUTTON, strings.Join(kit.Simple(list...), ","))
|
||||
return
|
||||
}
|
||||
m.Table(func(index int, value map[string]string, head []string) {
|
||||
m.PushRender("action", "button", strings.Join(kit.Simple(list...), ","))
|
||||
m.PushRender(kit.MDB_ACTION, kit.MDB_BUTTON, strings.Join(kit.Simple(list...), ","))
|
||||
})
|
||||
}
|
||||
func (m *Message) PushDetail(value interface{}, arg ...interface{}) *Message {
|
||||
@ -98,3 +103,17 @@ func (m *Message) PushDetail(value interface{}, arg ...interface{}) *Message {
|
||||
}
|
||||
|
||||
var BinPack = map[string][]byte{}
|
||||
|
||||
var ErrNameExists = "name already exists:"
|
||||
|
||||
type Error struct {
|
||||
Arg []interface{}
|
||||
FileLine string
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return e.FileLine + " " + strings.Join(kit.Simple(e.Arg), " ")
|
||||
}
|
||||
func NewError(n int, arg ...interface{}) *Error {
|
||||
return &Error{Arg: arg, FileLine: kit.FileLine(n, 3)}
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ var Index = &ice.Context{Name: ALPHA, Help: "英汉词典",
|
||||
ALPHA: {Name: ALPHA, Help: "英汉词典", Value: kit.Data(
|
||||
kit.MDB_LIMIT, "50000", kit.MDB_LEAST, "1000",
|
||||
kit.MDB_STORE, "usr/export/alpha", kit.MDB_FSIZE, "2000000",
|
||||
kit.MDB_REPOS, "word-dict", kit.MDB_FIELD, []interface{}{"audio", "bnc", "collins", "definition", "detail", "exchange", "frq", "id", "oxford", "phonetic", "pos", "tag", "time", "translation", "word"},
|
||||
kit.SSH_REPOS, "word-dict", kit.MDB_FIELD, []interface{}{"audio", "bnc", "collins", "definition", "detail", "exchange", "frq", "id", "oxford", "phonetic", "pos", "tag", "time", "translation", "word"},
|
||||
)},
|
||||
},
|
||||
Commands: map[string]*ice.Command{
|
||||
|
@ -65,7 +65,7 @@ func init() {
|
||||
m.Cmdy(mdb.DELETE, m.Prefix(CACHE), "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
|
||||
}},
|
||||
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
|
||||
m.Cmdy(mdb.PRUNES, m.Prefix(CACHE), "", mdb.HASH, kit.MDB_STEP, "100")
|
||||
m.Cmdy(mdb.PRUNES, m.Prefix(CACHE), "", mdb.HASH, kit.SSH_STEP, "100")
|
||||
}},
|
||||
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Option(ice.MSG_ACTION, "删除")
|
||||
|
@ -100,7 +100,7 @@ var Index = &ice.Context{Name: "mp", Help: "小程序",
|
||||
case "upload":
|
||||
msg := m.Cmd(web.CACHE, "upload")
|
||||
m.Cmd(web.STORY, web.WATCH, msg.Append("data"), path.Join("usr/local/mp/", path.Base(msg.Append("name"))))
|
||||
m.Cmd(web.FAVOR, "device", "file", msg.Append("name"), msg.Append("data"))
|
||||
// m.Cmd(web.FAVOR, "device", "file", msg.Append("name"), msg.Append("data"))
|
||||
m.Render(msg.Append("data"))
|
||||
|
||||
case "cmds":
|
||||
|
24
misc/vim/_trash.go
Normal file
24
misc/vim/_trash.go
Normal file
@ -0,0 +1,24 @@
|
||||
package vim
|
||||
|
||||
/*
|
||||
m.Conf(web.FAVOR, "meta.render.vimrc", m.AddCmd(&ice.Command{Name: "render favor id", Help: "渲染引擎", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
value := m.Optionv("value").(map[string]interface{})
|
||||
switch value["name"] {
|
||||
case "read", "write", "exec":
|
||||
p := path.Join(kit.Format(kit.Value(value, "extra.pwd")), kit.Format(kit.Value(value, "extra.buf")))
|
||||
if strings.HasPrefix(kit.Format(kit.Value(value, "extra.buf")), "/") {
|
||||
p = path.Join(kit.Format(kit.Value(value, "extra.buf")))
|
||||
}
|
||||
|
||||
f, e := os.Open(p)
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
b, e := ioutil.ReadAll(f)
|
||||
m.Assert(e)
|
||||
m.Echo(string(b))
|
||||
default:
|
||||
m.Cmdy(cli.SYSTEM, "sed", "-n", fmt.Sprintf("/%s/,/^}$/p", value["text"]), kit.Value(value, "extra.buf"))
|
||||
}
|
||||
}}))
|
||||
|
||||
*/
|
@ -2,15 +2,12 @@ package vim
|
||||
|
||||
import (
|
||||
ice "github.com/shylinux/icebergs"
|
||||
"github.com/shylinux/icebergs/base/cli"
|
||||
"github.com/shylinux/icebergs/base/mdb"
|
||||
"github.com/shylinux/icebergs/base/nfs"
|
||||
"github.com/shylinux/icebergs/base/web"
|
||||
"github.com/shylinux/icebergs/core/code"
|
||||
kit "github.com/shylinux/toolkits"
|
||||
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
@ -66,26 +63,6 @@ var Index = &ice.Context{Name: VIM, Help: "编辑器",
|
||||
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
m.Load()
|
||||
|
||||
m.Conf(web.FAVOR, "meta.render.vimrc", m.AddCmd(&ice.Command{Name: "render favor id", Help: "渲染引擎", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
|
||||
value := m.Optionv("value").(map[string]interface{})
|
||||
switch value["name"] {
|
||||
case "read", "write", "exec":
|
||||
p := path.Join(kit.Format(kit.Value(value, "extra.pwd")), kit.Format(kit.Value(value, "extra.buf")))
|
||||
if strings.HasPrefix(kit.Format(kit.Value(value, "extra.buf")), "/") {
|
||||
p = path.Join(kit.Format(kit.Value(value, "extra.buf")))
|
||||
}
|
||||
|
||||
f, e := os.Open(p)
|
||||
m.Assert(e)
|
||||
defer f.Close()
|
||||
b, e := ioutil.ReadAll(f)
|
||||
m.Assert(e)
|
||||
m.Echo(string(b))
|
||||
default:
|
||||
m.Cmdy(cli.SYSTEM, "sed", "-n", fmt.Sprintf("/%s/,/^}$/p", value["text"]), kit.Value(value, "extra.buf"))
|
||||
}
|
||||
}}))
|
||||
|
||||
m.Cmd(mdb.PLUGIN, mdb.CREATE, VIMRC, VIM, c.Cap(ice.CTX_FOLLOW))
|
||||
m.Cmd(mdb.RENDER, mdb.CREATE, VIMRC, VIM, c.Cap(ice.CTX_FOLLOW))
|
||||
m.Cmd(mdb.PLUGIN, mdb.CREATE, VIM, VIM, c.Cap(ice.CTX_FOLLOW))
|
||||
|
Loading…
x
Reference in New Issue
Block a user