1
0
forked from x/icebergs
This commit is contained in:
shaoying 2020-10-08 07:57:42 +08:00
parent a3da6968ca
commit 3a4480bb37
70 changed files with 1064 additions and 1193 deletions

View File

@ -2,6 +2,7 @@ package aaa
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
)
@ -9,27 +10,28 @@ const (
ErrNotAuth = "not auth: "
)
const (
USERZONE = "userzone"
USERNICK = "usernick"
USERNAME = "username"
HOSTNAME = "hostname"
PASSWORD = "password"
IP = "ip"
UA = "ua"
USERROLE = "userrole"
USERNODE = "usernode"
HOSTPORT = "hostport"
USERNAME = "username"
PASSWORD = "password"
USERNICK = "usernick"
USERZONE = "userzone"
SESSID = "sessid"
)
const AAA = "aaa"
var Index = &ice.Context{Name: "aaa", Help: "认证模块", Commands: map[string]*ice.Command{
var Index = &ice.Context{Name: AAA, Help: "认证模块", Commands: map[string]*ice.Command{
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Rich(ROLE, nil, kit.Dict(kit.MDB_NAME, VOID, White, kit.Dict(), Black, kit.Dict()))
m.Rich(ROLE, nil, kit.Dict(kit.MDB_NAME, TECH, Black, kit.Dict(), White, kit.Dict()))
m.Load()
m.Cmd("mdb.search", "create", "user", "user", "aaa")
m.Cmd(mdb.SEARCH, mdb.CREATE, USER, USER, AAA)
}},
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Save(USER, SESS, ROLE)
m.Save()
}},
}}

5
base/aaa/aaa.shy Normal file
View File

@ -0,0 +1,5 @@
chapter "aaa"
field "用户" user
field "会话" sess
field "角色" role

View File

@ -2,6 +2,7 @@ package aaa
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"strings"
@ -16,6 +17,9 @@ const ( // 角色操作
White = "white"
Black = "black"
Right = "right"
WHITE = "white"
BLACK = "black"
)
const ( // 返回结果
OK = "ok"
@ -103,10 +107,10 @@ const ROLE = "role"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
ROLE: {Name: "role", Help: "角色", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME)},
ROLE: {Name: ROLE, Help: "角色", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME)},
},
Commands: map[string]*ice.Command{
ROLE: {Name: "role [role [user...]]", Help: "角色", Action: map[string]*ice.Action{
ROLE: {Name: "role role auto 添加", Help: "角色", Action: map[string]*ice.Action{
White: {Name: "white role chain...", Help: "白名单", Hand: func(m *ice.Message, arg ...string) {
_role_white(m, arg[0], strings.ReplaceAll(kit.Keys(arg[1:]), "/", "."), true)
}},
@ -118,11 +122,27 @@ func init() {
m.Echo(OK)
}
}},
mdb.CREATE: {Name: "create zone=white,black role=void@key key=", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Richs(ROLE, nil, m.Option(ROLE), func(key string, value map[string]interface{}) {
list := value[m.Option(kit.MDB_ZONE)].(map[string]interface{})
m.Log_CREATE(ROLE, m.Option(ROLE), list[m.Option(kit.MDB_KEY)])
list[m.Option(kit.MDB_KEY)] = true
})
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Richs(ROLE, nil, m.Option(ROLE), func(key string, value map[string]interface{}) {
list := value[m.Option(kit.MDB_ZONE)].(map[string]interface{})
m.Log_REMOVE(ROLE, m.Option(ROLE), list[m.Option(kit.MDB_KEY)])
delete(list, m.Option(kit.MDB_KEY))
})
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) > 1 {
_role_user(m, arg[0], arg[1:]...)
}
_role_list(m, kit.Select("", arg, 0))
m.PushAction(mdb.REMOVE)
}},
},
}, nil)

View File

@ -6,14 +6,9 @@ import (
kit "github.com/shylinux/toolkits"
)
func _sess_list(m *ice.Message) {
m.Richs(SESS, nil, kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
m.Push(key, value, []string{kit.MDB_TIME, kit.MDB_KEY, USERNAME, USERROLE})
})
}
func _sess_auth(m *ice.Message, sessid string, username string, userrole string) {
m.Richs(SESS, nil, sessid, func(value map[string]interface{}) {
if m.Option(ice.MSG_USERROLE) == ROOT {
if value = kit.GetMeta(value); m.Option(ice.MSG_USERROLE) == ROOT {
value[USERROLE] = userrole
} else if m.Option(ice.MSG_USERROLE) == TECH && userrole != ROOT {
value[USERROLE] = userrole
@ -26,7 +21,10 @@ func _sess_auth(m *ice.Message, sessid string, username string, userrole string)
}
func _sess_check(m *ice.Message, sessid string) {
m.Richs(SESS, nil, sessid, func(value map[string]interface{}) {
value = kit.GetMeta(value)
m.Richs(USER, nil, value[USERNAME], func(value map[string]interface{}) {
value = kit.GetMeta(value)
if m.Option(ice.MSG_USERNICK, value[USERNICK]) == "" {
if name := kit.Format(value[USERNAME]); len(name) > 10 {
m.Option(ice.MSG_USERNICK, name[:10])
@ -46,13 +44,14 @@ func _sess_create(m *ice.Message, username string) string {
if m.Richs(USER, nil, username, nil) == nil {
_user_create(m, username, "")
}
h := m.Rich(SESS, nil, kit.Dict(
kit.MDB_TIME, m.Time(m.Conf(SESS, "meta.expire")),
m.Cmdy(mdb.INSERT, SESS, "", mdb.HASH,
USERNAME, username, "from", m.Option(ice.MSG_SESSID),
))
m.Log_CREATE(SESSID, h, USERNAME, username)
m.Echo(h)
return h
kit.MDB_TIME, m.Time(m.Conf(SESS, "meta.expire")),
"agent", m.Option(ice.MSG_USERUA),
"ip", m.Option(ice.MSG_USERIP),
)
return m.Result()
}
func SessCheck(m *ice.Message, sessid string) *ice.Message {
@ -69,22 +68,27 @@ const SESS = "sess"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
SESS: {Name: "sess", Help: "会话", Value: kit.Data(
SESS: {Name: SESS, Help: "会话", Value: kit.Data(
kit.MDB_SHORT, "uniq", "expire", "720h",
)},
},
Commands: map[string]*ice.Command{
SESS: {Name: "sess", Help: "会话", Action: map[string]*ice.Action{
mdb.CREATE: {Name: "create [username]", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
_sess_create(m, kit.Select("", arg, 0))
SESS: {Name: "sess hash auto", Help: "会话", Action: map[string]*ice.Action{
"auth": {Name: "auth sessid username [userrole]", Help: "授权", Hand: func(m *ice.Message, arg ...string) {
_sess_auth(m, arg[0], arg[1], kit.Select("", arg, 2))
}},
"check": {Name: "check sessid", Help: "校验", Hand: func(m *ice.Message, arg ...string) {
_sess_check(m, arg[0])
}},
"auth": {Name: "auth sessid username [userrole]", Help: "授权", Hand: func(m *ice.Message, arg ...string) {
_sess_auth(m, arg[0], arg[1], kit.Select("", arg, 2))
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, SESS, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { _sess_list(m) }},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, kit.Select("time,hash,username,userrole", mdb.DETAIL, len(arg) > 0))
m.Cmdy(mdb.SELECT, SESS, "", mdb.HASH, kit.MDB_HASH, arg)
m.PushAction(mdb.REMOVE)
}},
},
}, nil)
}

View File

@ -2,23 +2,12 @@ package aaa
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"strings"
)
const (
USER_CREATE = "user.create"
)
func _user_list(m *ice.Message) {
m.Richs(USER, nil, kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
m.Push(key, value, []string{kit.MDB_TIME, USERZONE, USERNICK, USERNAME})
})
m.Sort(USERNAME)
}
func _user_login(m *ice.Message, name, word string) (ok bool) {
if m.Richs(USER, nil, name, nil) == nil {
_user_create(m, name, "")
@ -33,24 +22,10 @@ func _user_login(m *ice.Message, name, word string) (ok bool) {
})
return ok
}
func _user_modify(m *ice.Message, name string, arg ...string) {
if m.Richs(USER, nil, name, nil) == nil {
_user_create(m, name, "")
}
m.Log_MODIFY(USERNAME, name, arg)
m.Richs(USER, nil, name, func(key string, value map[string]interface{}) {
for i := 0; i < len(arg)-1; i += 2 {
kit.Value(value, arg[i], arg[i+1])
}
})
}
func _user_create(m *ice.Message, name, word string) {
h := m.Rich(USER, nil, kit.Dict(
USERNAME, name, PASSWORD, word,
USERNICK, name, USERNODE, cli.NodeName,
USERZONE, m.Option(ice.MSG_USERZONE),
USERNODE, cli.NodeName,
USERNICK, name, USERZONE, m.Option(ice.MSG_USERZONE),
))
m.Log_CREATE(USERNAME, name, "hash", h)
m.Event(USER_CREATE, name)
@ -72,27 +47,30 @@ func _user_search(m *ice.Message, kind, name, text string, arg ...string) {
}
func UserRoot(m *ice.Message) {
cli.PassWord = kit.Hashs("uniq")
cli.PassWord = cli.UserName
_user_create(m, cli.UserName, cli.PassWord)
ice.Info.PassWord = kit.Hashs("uniq")
ice.Info.PassWord = ice.Info.UserName
_user_create(m, ice.Info.UserName, ice.Info.PassWord)
}
func UserNick(m *ice.Message, username interface{}) (nick string) {
m.Richs(USER, nil, kit.Format(username), func(key string, value map[string]interface{}) {
value = kit.GetMeta(value)
nick = kit.Format(value[USERNICK])
})
return
}
func UserZone(m *ice.Message, username interface{}) (zone string) {
m.Richs(USER, nil, kit.Format(username), func(key string, value map[string]interface{}) {
value = kit.GetMeta(value)
zone = kit.Format(value[USERZONE])
})
return
}
func UserRole(m *ice.Message, username interface{}) (role string) {
if role = VOID; username == cli.UserName {
if role = VOID; username == ice.Info.UserName {
return ROOT
}
m.Richs(ROLE, nil, TECH, func(key string, value map[string]interface{}) {
value = kit.GetMeta(value)
if kit.Value(value, kit.Keys(USER, username)) == true {
role = TECH
}
@ -109,28 +87,33 @@ func UserLogin(m *ice.Message, username, password string) bool {
return false
}
const (
USER_CREATE = "user.create"
)
const USER = "user"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
USER: {Name: "user", Help: "用户", Value: kit.Data(kit.MDB_SHORT, USERNAME)},
USER: {Name: USER, Help: "用户", Value: kit.Data(kit.MDB_SHORT, USERNAME)},
},
Commands: map[string]*ice.Command{
USER: {Name: "user", Help: "用户", Action: map[string]*ice.Action{
mdb.CREATE: {Name: "create username [password]", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
_user_create(m, arg[0], kit.Select("", arg, 1))
USER: {Name: "user username auto", Help: "用户", Action: map[string]*ice.Action{
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.MODIFY, USER, "", mdb.HASH, USERNAME, m.Option(USERNAME), arg)
}},
mdb.MODIFY: {Name: "modify [key value]...", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
_user_modify(m, m.Option(USERNAME), arg...)
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.REMOVE, USER, "", mdb.HASH, USERNAME, m.Option(USERNAME))
}},
mdb.SEARCH: {Name: "search type name text arg...", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
_user_search(m, arg[0], arg[1], kit.Select("", arg, 2))
}},
"login": {Name: "login username password", Help: "登录", Hand: func(m *ice.Message, arg ...string) {
_user_login(m, arg[0], arg[1])
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { _user_list(m) }},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, kit.Select("time,userzone,usernick,username", mdb.DETAIL, len(arg) > 0))
m.Cmdy(mdb.SELECT, USER, "", mdb.HASH, USERNAME, arg)
m.PushAction(mdb.REMOVE)
}},
},
}, nil)
}

View File

@ -2,12 +2,8 @@ package cli
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/ctx"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"bytes"
"io/ioutil"
"os"
"os/user"
"path"
@ -15,27 +11,15 @@ import (
"strings"
)
var UserName = ""
var PassWord = ""
var HostName = ""
var PathName = ""
var NodeName = ""
var NodeType = ""
func NodeInfo(m *ice.Message, kind, name string) {
name = strings.ReplaceAll(name, ".", "_")
m.Conf(RUNTIME, "node.type", kind)
m.Conf(RUNTIME, "node.name", name)
NodeName = name
NodeType = kind
ice.Info.NodeName = name
ice.Info.NodeType = kind
}
const RUNTIME = "runtime"
var Index = &ice.Context{Name: "cli", Help: "命令模块",
Configs: map[string]*ice.Config{
RUNTIME: {Name: "runtime", Help: "运行环境", Value: kit.Dict()},
},
Commands: map[string]*ice.Command{
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Load()
@ -46,7 +30,6 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
m.Conf(RUNTIME, "conf.ctx_shy", os.Getenv("ctx_shy"))
m.Conf(RUNTIME, "conf.ctx_pid", os.Getenv("ctx_pid"))
m.Conf(RUNTIME, "conf.ctx_user", os.Getenv("ctx_user"))
m.Conf(RUNTIME, "conf.ctx_pod", os.Getenv("ctx_pod"))
// 主机信息
m.Conf(RUNTIME, "host.GOARCH", runtime.GOARCH)
@ -54,11 +37,6 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
m.Conf(RUNTIME, "host.pid", os.Getpid())
// 启动信息
if m.Conf(RUNTIME, "boot.username", kit.Select(os.Getenv("USER"), os.Getenv("ctx_user"))) == "" {
if user, e := user.Current(); e == nil && user.Name != "" {
m.Conf(RUNTIME, "boot.username", kit.Select(user.Name, os.Getenv("ctx_user")))
}
}
if name, e := os.Hostname(); e == nil {
m.Conf(RUNTIME, "boot.hostname", kit.Select(name, os.Getenv("HOSTNAME")))
}
@ -70,9 +48,14 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
name = ls[len(ls)-1]
m.Conf(RUNTIME, "boot.pathname", name)
}
UserName = m.Conf(RUNTIME, "boot.username")
HostName = m.Conf(RUNTIME, "boot.hostname")
PathName = m.Conf(RUNTIME, "boot.pathname")
if m.Conf(RUNTIME, "boot.username", kit.Select(os.Getenv("USER"), os.Getenv("ctx_user"))) == "" {
if user, e := user.Current(); e == nil && user.Name != "" {
m.Conf(RUNTIME, "boot.username", kit.Select(user.Name, os.Getenv("ctx_user")))
}
}
ice.Info.HostName = m.Conf(RUNTIME, "boot.hostname")
ice.Info.PathName = m.Conf(RUNTIME, "boot.pathname")
ice.Info.UserName = m.Conf(RUNTIME, "boot.username")
// 启动记录
count := kit.Int(m.Conf(RUNTIME, "boot.count")) + 1
@ -83,84 +66,20 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
NodeInfo(m, "worker", m.Conf(RUNTIME, "boot.pathname"))
m.Info("runtime %v", kit.Formats(m.Confv(RUNTIME)))
n := kit.Int(kit.Select("20", m.Conf(RUNTIME, "host.GOMAXPROCS")))
n := kit.Int(kit.Select("1", m.Conf(RUNTIME, "host.GOMAXPROCS")))
m.Logs("host", "gomaxprocs", n)
runtime.GOMAXPROCS(n)
m.Cmdy(mdb.ENGINE, mdb.CREATE, "shell", m.AddCmd(&ice.Command{Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmdy(SYSTEM, arg[2])
}}))
// 版本信息
m.Conf(RUNTIME, "build.time", ice.Info.Build.Time)
m.Conf(RUNTIME, "build.version", ice.Info.Build.Version)
m.Conf(RUNTIME, "build.hostname", ice.Info.Build.HostName)
m.Conf(RUNTIME, "build.username", ice.Info.Build.UserName)
}},
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Save(RUNTIME, SYSTEM, DAEMON)
}},
"proc": {Name: "proc name=auto PID=auto auto", Help: "进程管理", Action: map[string]*ice.Action{
"kill": {Name: "kill", Help: "结束", Hand: func(m *ice.Message, arg ...string) {
if p, e := os.FindProcess(kit.Int(m.Option("PID"))); m.Assert(e) {
m.Assert(p.Kill())
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
msg := m.Spawn()
msg.Split(m.Cmdx(SYSTEM, "ps", "ux"), "", " ", "\n")
msg.Table(func(index int, value map[string]string, head []string) {
if m.Appendv(ice.MSG_APPEND, "action", head); len(arg) == 2 && value["PID"] == arg[1] {
m.PushRender("action", "button", "结束")
m.Push("", value)
return
}
if len(arg) == 0 || len(arg) == 1 && strings.Contains(value["COMMAND"], arg[0]) {
m.PushRender("action", "button", "结束")
m.Push("", value)
}
})
}},
RUNTIME: {Name: "runtime name auto", Help: "运行环境", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch kit.Select("", arg, 0) {
case "procinfo":
m.Split(m.Cmdx(SYSTEM, "ps", "u"), "", " ", "\n")
case "hostinfo":
if f, e := os.Open("/proc/cpuinfo"); e == nil {
defer f.Close()
if b, e := ioutil.ReadAll(f); e == nil {
m.Push("nCPU", bytes.Count(b, []byte("processor")))
}
}
if f, e := os.Open("/proc/meminfo"); e == nil {
defer f.Close()
if b, e := ioutil.ReadAll(f); e == nil {
for i, ls := range strings.Split(string(b), "\n") {
vs := kit.Split(ls, ": ")
m.Push(strings.TrimSpace(vs[0]), kit.FmtSize(kit.Int64(strings.TrimSpace(vs[1]))*1024))
if i > 1 {
break
}
}
}
}
m.Push("uptime", kit.Split(m.Cmdx(SYSTEM, "uptime"), ",")[0])
case "diskinfo":
m.Spawn().Split(m.Cmdx(SYSTEM, "df", "-h"), "", " ", "\n").Table(func(index int, value map[string]string, head []string) {
if strings.HasPrefix(value["Filesystem"], "/dev") {
m.Push("", value, head)
}
})
case "ifconfig":
m.Cmdy("tcp.host")
case "userinfo":
m.Split(m.Cmdx(SYSTEM, "who"), "user term time", " ", "\n")
case "hostname":
m.Conf(RUNTIME, "boot.hostname", arg[1])
HostName = arg[1]
m.Echo(HostName)
default:
m.Cmdy(ctx.CONFIG, RUNTIME, arg)
}
m.Save()
}},
},
}
func init() { ice.Index.Register(Index, nil, RUNTIME, SYSTEM, DAEMON, PYTHON) }
func init() { ice.Index.Register(Index, nil, RUNTIME, SYSTEM, DAEMON, PYTHON, OUTPUT) }

9
base/cli/cli.shy Normal file
View File

@ -0,0 +1,9 @@
chapter "cli"
field "命令" system
field "输出" output
field "守护" daemon
field "脚本" python
field "环境" runtime
field "进程" cli.proc

View File

@ -2,6 +2,8 @@ package cli
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"fmt"
@ -10,15 +12,6 @@ import (
"strings"
)
const (
ErrStart = "daemon start: "
)
const (
StatusError = "error"
StatusStart = "start"
StatusClose = "close"
)
func _daemon_show(m *ice.Message, cmd *exec.Cmd, out, err string) {
if f, p, e := kit.Create(out); m.Assert(e) {
m.Log_EXPORT(kit.MDB_META, DAEMON, CMD_STDOUT, p)
@ -35,30 +28,40 @@ func _daemon_show(m *ice.Message, cmd *exec.Cmd, out, err string) {
return
}
h := m.Rich(DAEMON, nil, kit.Dict(
kit.MDB_TYPE, "shell", kit.MDB_NAME, strings.Join(cmd.Args, " "),
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.SSH_PID, cmd.Process.Pid)
h := m.Cmdx(mdb.INSERT, DAEMON, "", mdb.HASH,
kit.MDB_STATUS, Status.Start, kit.SSH_CMD, strings.Join(cmd.Args, " "),
kit.SSH_DIR, cmd.Dir, kit.SSH_ENV, cmd.Env, kit.SSH_PID, cmd.Process.Pid,
CMD_STDOUT, out, CMD_STDERR, err,
aaa.USERNAME, m.Option(ice.MSG_USERNAME), aaa.USERROLE, m.Option(ice.MSG_USERROLE),
aaa.IP, m.Option(ice.MSG_USERIP), aaa.UA, m.Option(ice.MSG_USERUA),
)
m.Echo("%d", cmd.Process.Pid)
m.Gos(m, func(m *ice.Message) {
if e := cmd.Wait(); e != nil {
m.Warn(e != nil, ErrStart, cmd.Args, " ", e)
m.Richs(DAEMON, nil, h, func(key string, value map[string]interface{}) {
kit.Value(value, kit.MDB_STATUS, StatusError)
kit.Value(value, kit.Keys(kit.MDB_EXTRA, kit.MDB_ERROR), e)
})
m.Go(func() {
if e := cmd.Wait(); m.Warn(e != nil, ErrStart, cmd.Args, " ", e) {
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, kit.MDB_HASH, h,
kit.MDB_STATUS, Status.Error, kit.MDB_ERROR, e)
} else {
m.Cost("%v exit: %v", cmd.Args, cmd.ProcessState.ExitCode())
m.Richs(DAEMON, nil, h, func(key string, value map[string]interface{}) {
kit.Value(value, kit.MDB_STATUS, StatusClose)
})
m.Cost("args", cmd.Args, "code", cmd.ProcessState.ExitCode())
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, kit.MDB_HASH, h,
kit.MDB_STATUS, Status.Stop)
}
})
}
const ErrStart = "daemon start: "
var Status = struct{ Error, Start, Stop string }{
Error: "error",
Start: "start",
Stop: "stop",
}
const (
START = "start"
STOP = "stop"
)
const DAEMON = "daemon"
func init() {
@ -67,40 +70,45 @@ func init() {
DAEMON: {Name: DAEMON, Help: "守护进程", Value: kit.Data(kit.MDB_PATH, "var/daemon")},
},
Commands: map[string]*ice.Command{
DAEMON: {Name: "daemon hash 查看:button=auto 清理:button", Help: "守护进程", Action: map[string]*ice.Action{
"delete": {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Richs(DAEMON, "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) {
m.Conf(DAEMON, kit.Keys(kit.MDB_HASH, key), "")
m.Log_DELETE(DAEMON, kit.Format(value))
})
DAEMON: {Name: "daemon hash auto 添加 清理", Help: "守护进程", Action: map[string]*ice.Action{
START: {Name: "start cmd env dir", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Option(CMD_TYPE, DAEMON)
m.Cmdy(SYSTEM, kit.Split(m.Option("cmd")))
}},
"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.SSH_PID]), "\n") == 1 {
m.Conf(DAEMON, kit.Keys(kit.MDB_HASH, key), "")
m.Log_DELETE(DAEMON, kit.Format(value))
}
})
}},
"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{}) {
STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(mdb.SELECT, DAEMON, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH)).Table(func(index int, value map[string]string, head []string) {
m.Cmd(mdb.MODIFY, DAEMON, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH), kit.MDB_STATUS, Status.Stop)
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
}
})
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, DAEMON, "", 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, DAEMON, "", mdb.HASH, kit.MDB_STATUS, Status.Error)
m.Cmdy(mdb.PRUNES, DAEMON, "", mdb.HASH, kit.MDB_STATUS, Status.Stop)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
m.Option("fields", "time,hash,status,pid,name,dir")
m.Cmdy("mdb.select", DAEMON, "", kit.MDB_HASH)
m.Sort("time", "time_r")
m.PushAction("停止", "删除")
return
}
m.Option(mdb.FIELDS, "time,hash,status,pid,cmd,dir")
m.Cmdy(mdb.SELECT, DAEMON, "", mdb.HASH)
m.Table(func(index int, value map[string]string, head []string) {
switch value[kit.MDB_STATUS] {
case Status.Start:
m.PushButton(STOP)
default:
m.PushButton(mdb.REMOVE)
}
})
m.Option(CMD_TYPE, DAEMON)
m.Cmdy(SYSTEM, arg)
} else if m.Richs(DAEMON, "", arg[0], nil) != nil {
m.Option(mdb.FIELDS, mdb.DETAIL)
m.Cmdy(mdb.SELECT, DAEMON, "", mdb.HASH, kit.MDB_HASH, arg)
} else {
m.Option(CMD_TYPE, DAEMON)
m.Cmdy(SYSTEM, arg)
}
}},
},
}, nil)

63
base/cli/output.go Normal file
View File

@ -0,0 +1,63 @@
package cli
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"io"
)
const OUTPUT = "output"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
OUTPUT: {Name: OUTPUT, Help: "输出", Value: kit.Data()},
},
Commands: map[string]*ice.Command{
OUTPUT: {Name: "output hash id auto", Help: "输出", Action: map[string]*ice.Action{
mdb.CREATE: {Name: "create cmd", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
h := m.Cmdx(mdb.INSERT, OUTPUT, "", mdb.HASH, kit.MDB_STATUS, Status.Start, arg)
r, w := io.Pipe()
m.Go(func() {
buf := make([]byte, 1024)
for {
if n, e := r.Read(buf); e != nil || n == 0 {
break
} else {
m.Grow(OUTPUT, kit.Keys(kit.MDB_HASH, h), kit.Dict(
kit.SSH_RES, string(buf[:n]),
))
}
}
m.Cmd(mdb.MODIFY, OUTPUT, "", mdb.HASH, kit.MDB_HASH, h, kit.MDB_STATUS, Status.Stop)
})
m.Option(OUTPUT, w)
m.Echo(h)
}},
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.MODIFY, OUTPUT, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH), arg)
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, OUTPUT, "", 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, OUTPUT, "", mdb.HASH, kit.MDB_STATUS, Status.Stop)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
m.Option(mdb.FIELDS, "time,hash,status,name")
m.Cmdy(mdb.SELECT, OUTPUT, "", mdb.HASH)
m.PushAction(mdb.REMOVE)
return
}
m.Option("_control", "_page")
m.Option(mdb.FIELDS, kit.Select("time,id,res", mdb.DETAIL, len(arg) > 1))
m.Cmdy(mdb.SELECT, OUTPUT, kit.Keys(kit.MDB_HASH, arg[0]), mdb.LIST, kit.MDB_ID, arg[1:])
m.Sort(kit.MDB_ID)
}},
},
}, nil)
}

37
base/cli/proc.go Normal file
View File

@ -0,0 +1,37 @@
package cli
import (
ice "github.com/shylinux/icebergs"
kit "github.com/shylinux/toolkits"
"os"
"strings"
)
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
"proc": {Name: "proc name=ice.bin PID auto", Help: "进程管理", Action: map[string]*ice.Action{
"kill": {Name: "kill", Help: "结束", Hand: func(m *ice.Message, arg ...string) {
if p, e := os.FindProcess(kit.Int(m.Option("PID"))); m.Assert(e) {
m.Assert(p.Kill())
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
msg := m.Spawn()
msg.Split(m.Cmdx(SYSTEM, "ps", "ux"), "", " ", "\n")
msg.Table(func(index int, value map[string]string, head []string) {
if m.Appendv(ice.MSG_APPEND, "action", head); len(arg) > 1 && value["PID"] != arg[1] {
return
}
if len(arg) > 0 && !strings.Contains(value["COMMAND"], arg[0]) {
return
}
m.PushButton("结束")
m.Push("", value)
})
}},
},
}, nil)
}

View File

@ -1,12 +1,10 @@
package cli
import (
"path"
"runtime"
"strings"
ice "github.com/shylinux/icebergs"
kit "github.com/shylinux/toolkits"
"path"
)
const PYTHON = "python"
@ -15,38 +13,35 @@ func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
PYTHON: {Name: "python", Help: "脚本命令", Value: kit.Data(
"windows", "http://mirrors.sohu.com/python/3.5.2/Python-3.5.2.tar.xz",
"darwin", "http://mirrors.sohu.com/python/3.5.2/Python-3.5.2.tar.xz",
"linux", "http://mirrors.sohu.com/python/3.5.2/Python-3.5.2.tar.xz",
"source", "http://mirrors.sohu.com/python/3.5.2/Python-3.5.2.tar.xz",
"qrcode", `import pyqrcode; print(pyqrcode.create('%s').terminal(module_color='%s', quiet_zone=1))`,
PYTHON, "python", "pip", "pip",
)},
},
Commands: map[string]*ice.Command{
PYTHON: {Name: "python 编译:button 下载:button", Help: "脚本命令", Action: map[string]*ice.Action{
PYTHON: {Name: "python port path auto 启动:button 构建 下载", Help: "脚本命令", Action: map[string]*ice.Action{
"download": {Name: "download", Help: "下载", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("web.code.install", "download", m.Conf(PYTHON, kit.Keys(kit.MDB_META, runtime.GOOS)))
m.Cmdy("web.code.install", "download", m.Conf(PYTHON, "meta.source"))
}},
"compile": {Name: "compile", Help: "编译", Hand: func(m *ice.Message, arg ...string) {
name := path.Base(strings.TrimSuffix(strings.TrimSuffix(m.Conf(PYTHON, kit.Keys(kit.MDB_META, runtime.GOOS)), ".tar.xz"), "zip"))
m.Option(CMD_DIR, path.Join(m.Conf("web.code.install", kit.META_PATH), name))
m.Cmdy(SYSTEM, "./configure", "--prefix="+kit.Path("usr/local"))
m.Cmdy(SYSTEM, "make", "-j8")
m.Cmdy(SYSTEM, "make", "install")
"build": {Name: "build", Help: "构建", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("web.code.install", "build", m.Conf(PYTHON, "meta.source"))
}},
"start": {Name: "start", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("web.code.install", "start", m.Conf(PYTHON, "meta.source"), "bin/python3")
}},
"install": {Name: "install arg...", Help: "安装", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SYSTEM, m.Conf(PYTHON, "meta.pip"), "install", arg)
}},
"qrcode": {Name: "qrcode text color", Help: "安装", Hand: func(m *ice.Message, arg ...string) {
prefix := []string{SYSTEM, m.Conf(PYTHON, kit.Keys(kit.MDB_META, PYTHON))}
m.Cmdy(prefix, "-c", kit.Format(m.Conf(PYTHON, "meta.qrcode"),
kit.Select("hello world", arg, 0), kit.Select("blue", arg, 1)))
}},
"pip": {Name: "pip", Help: "安装", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SYSTEM, m.Conf(PYTHON, "meta.pip"), "install", arg)
}},
"run": {Name: "run", Help: "运行", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SYSTEM, m.Conf(PYTHON, "meta.python"), arg)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
prefix := []string{SYSTEM, m.Conf(PYTHON, kit.Keys(kit.MDB_META, PYTHON))}
m.Cmdy(prefix, arg)
m.Cmdy("web.code.install", path.Base(m.Conf(PYTHON, kit.META_SOURCE)), arg)
}},
},
}, nil)

73
base/cli/runtime.go Normal file
View File

@ -0,0 +1,73 @@
package cli
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/ctx"
kit "github.com/shylinux/toolkits"
"bytes"
"io/ioutil"
"os"
"strings"
)
const RUNTIME = "runtime"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
RUNTIME: {Name: RUNTIME, Help: "运行环境", Value: kit.Dict()},
},
Commands: map[string]*ice.Command{
RUNTIME: {Name: "runtime info=procinfo,hostinfo,diskinfo,ifconfig,hostname,userinfo,bootinfo auto", Help: "运行环境", Action: map[string]*ice.Action{
"procinfo": {Name: "procinfo", Help: "procinfo", Hand: func(m *ice.Message, arg ...string) {
m.Split(m.Cmdx(SYSTEM, "ps", "u"), "", " ", "\n")
}},
"hostinfo": {Name: "hostinfo", Help: "hostinfo", Hand: func(m *ice.Message, arg ...string) {
if f, e := os.Open("/proc/cpuinfo"); e == nil {
defer f.Close()
if b, e := ioutil.ReadAll(f); e == nil {
m.Push("nCPU", bytes.Count(b, []byte("processor")))
}
}
if f, e := os.Open("/proc/meminfo"); e == nil {
defer f.Close()
if b, e := ioutil.ReadAll(f); e == nil {
for i, ls := range strings.Split(string(b), "\n") {
vs := kit.Split(ls, ": ")
m.Push(strings.TrimSpace(vs[0]), kit.FmtSize(kit.Int64(strings.TrimSpace(vs[1]))*1024))
if i > 1 {
break
}
}
}
}
m.Push("uptime", kit.Split(m.Cmdx(SYSTEM, "uptime"), ",")[0])
}},
"diskinfo": {Name: "diskinfo", Help: "diskinfo", Hand: func(m *ice.Message, arg ...string) {
m.Spawn().Split(m.Cmdx(SYSTEM, "df", "-h"), "", " ", "\n").Table(func(index int, value map[string]string, head []string) {
if strings.HasPrefix(value["Filesystem"], "/dev") {
m.Push("", value, head)
}
})
}},
"ifconfig": {Name: "ifconfig", Help: "ifconfig", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("tcp.host")
}},
"hostname": {Name: "hostname", Help: "hostname", Hand: func(m *ice.Message, arg ...string) {
m.Conf(RUNTIME, "boot.hostname", arg[1])
ice.Info.HostName = arg[1]
m.Echo(ice.Info.HostName)
}},
"userinfo": {Name: "userinfo", Help: "userinfo", Hand: func(m *ice.Message, arg ...string) {
m.Split(m.Cmdx(SYSTEM, "who"), "user term time", " ", "\n")
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) > 0 && arg[0] == "bootinfo" {
arg = arg[1:]
}
m.Cmdy(ctx.CONFIG, RUNTIME, arg)
}},
},
}, nil)
}

View File

@ -2,19 +2,60 @@ package cli
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"bytes"
"fmt"
"io"
"os"
"os/exec"
"strings"
"time"
)
func _system_show(m *ice.Message, cmd *exec.Cmd) {
m.Cmd(mdb.INSERT, SYSTEM, "", mdb.LIST, "cmd", strings.Join(cmd.Args, " "), "dir", cmd.Dir, "env", strings.Join(cmd.Env, ","),
aaa.USERNAME, m.Option(ice.MSG_USERNAME), aaa.USERROLE, m.Option(ice.MSG_USERROLE),
aaa.IP, m.Option(ice.MSG_USERIP), aaa.UA, m.Option(ice.MSG_USERUA),
)
if w, ok := m.Optionv("output").(io.WriteCloser); ok {
cmd.Stderr = w
cmd.Stdout = w
if e := cmd.Run(); e != nil {
m.Warn(e != nil, ErrRun, strings.Join(cmd.Args, " "), "\n", e.Error())
} else {
m.Cost("args", cmd.Args, "code", cmd.ProcessState.ExitCode())
}
} else {
err := bytes.NewBuffer(make([]byte, 0, 1024))
out := bytes.NewBuffer(make([]byte, 0, 1024))
cmd.Stderr = err
cmd.Stdout = out
defer func() {
m.Push(CMD_ERR, err.String())
m.Push(CMD_OUT, out.String())
m.Echo(kit.Select(err.String(), out.String()))
}()
if e := cmd.Run(); e != nil {
m.Warn(e != nil, ErrRun, strings.Join(cmd.Args, " "), "\n", kit.Select(e.Error(), err.String()))
} else {
m.Cost("args", cmd.Args, "code", cmd.ProcessState.ExitCode(), "err", err.Len(), "out", out.Len())
}
}
m.Push(kit.MDB_TIME, m.Time())
m.Push(CMD_CODE, int(cmd.ProcessState.ExitCode()))
}
const ErrRun = "cli run err: "
const (
CMD_STDOUT = "cmd_stdout"
CMD_STDERR = "cmd_stderr"
CMD_STDOUT = "cmd_stdout"
CMD_TYPE = "cmd_type"
CMD_DIR = "cmd_dir"
@ -25,38 +66,25 @@ const (
CMD_CODE = "cmd_code"
)
const ErrRun = "run err "
func _system_show(m *ice.Message, cmd *exec.Cmd) {
out := bytes.NewBuffer(make([]byte, 0, 1024))
err := bytes.NewBuffer(make([]byte, 0, 1024))
cmd.Stdout = out
cmd.Stderr = err
defer func() {
m.Cost("%v exit: %v out: %v err: %v ",
cmd.Args, cmd.ProcessState.ExitCode(), out.Len(), err.Len())
}()
if e := cmd.Run(); e != nil {
m.Warn(e != nil, ErrRun, strings.Join(cmd.Args, " "), "\n", kit.Select(e.Error(), err.String()))
}
m.Push(kit.MDB_TIME, m.Time())
m.Push(CMD_CODE, int(cmd.ProcessState.ExitCode()))
m.Push(CMD_ERR, err.String())
m.Push(CMD_OUT, out.String())
m.Echo(out.String())
}
const SYSTEM = "system"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
SYSTEM: {Name: "system", Help: "系统命令", Value: kit.Data()},
SYSTEM: {Name: SYSTEM, Help: "系统命令", Value: kit.Data()},
},
Commands: map[string]*ice.Command{
SYSTEM: {Name: "system cmd 执行:button 清空:button", Help: "系统命令", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {
SYSTEM: {Name: "system id auto", Help: "系统命令", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {
if len(arg) == 0 || kit.Int(arg[0]) > 0 {
m.Option("_control", "_page")
m.Option(mdb.FIELDS, kit.Select("time,id,cmd,dir,env", mdb.DETAIL, len(arg) > 0))
m.Cmdy(mdb.SELECT, SYSTEM, "", mdb.LIST, kit.MDB_ID, arg)
return
}
if len(arg) == 1 {
arg = kit.Split(arg[0])
}
cmd := exec.Command(arg[0], arg[1:]...)
// 运行目录
@ -83,29 +111,6 @@ func init() {
_system_show(m, cmd)
}
}},
"ssh_user": {Name: "ssh_user", Help: "ssh_user", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {
msg := m.Cmd(SYSTEM, "who")
msg.Split(msg.Result(), "name term begin", " \t", "\n")
msg.Table(func(index int, value map[string]string, head []string) {
m.Push("name", value["name"])
m.Push("term", value["term"])
ls := strings.Split(value["begin"], "(")
ls[0] = strings.Join(kit.Split(ls[0], " \t"), " ")
if len(ls) > 1 {
m.Push("ip", strings.TrimSuffix(ls[1], ")"))
}
t, e := time.ParseInLocation("2006 Jan 2 15:04", "2020 "+ls[0], time.Local)
if e != nil {
t, _ = time.ParseInLocation("2006-01-02 15:04", ls[0], time.Local)
}
m.Push("begin", t.Format("2006-01-02 15:04:05"))
d := time.Since(t)
d = d / time.Millisecond * time.Millisecond
m.Push("duration", d.String())
})
}},
},
}, nil)
}

View File

@ -8,19 +8,15 @@ import (
"strings"
)
func _command_list(m *ice.Message, all bool, name string) {
func _command_list(m *ice.Message, name string) {
p := m.Spawn(m.Source())
if all {
p = ice.Pulse
}
if name != "" {
p.Search(name, func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
m.Push("key", s.Cap(ice.CTX_FOLLOW))
m.Push("name", kit.Format(cmd.Name))
m.Push("help", kit.Simple(cmd.Help)[0])
m.Push("meta", kit.Format(cmd.Meta))
m.Push("list", kit.Format(cmd.List))
m.Push("meta", kit.Formats(cmd.Meta))
m.Push("list", kit.Formats(cmd.List))
})
return
}
@ -28,8 +24,7 @@ func _command_list(m *ice.Message, all bool, name string) {
list := []string{}
for k := range p.Target().Commands {
if k[0] == '/' || k[0] == '_' {
// 内部命令
continue
continue // 内部命令
}
list = append(list, k)
}
@ -48,9 +43,8 @@ const COMMAND = "command"
func init() {
Index.Merge(&ice.Context{
Commands: map[string]*ice.Command{
COMMAND: {Name: "command [all] command", Help: "命令", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
all, arg := _parse_arg_all(m, arg...)
_command_list(m, all, strings.Join(arg, "."))
COMMAND: {Name: "command key auto", Help: "命令", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
_command_list(m, strings.Join(arg, "."))
}},
},
}, nil)

View File

@ -12,17 +12,13 @@ import (
"strings"
)
func _config_list(m *ice.Message, all bool) {
func _config_list(m *ice.Message) {
p := m.Spawn(m.Source())
if all {
p = ice.Pulse
}
list := []string{}
for k := range p.Target().Configs {
if k[0] == '/' || k[0] == '_' {
// 内部命令
continue
continue // 内部配置
}
list = append(list, k)
}
@ -85,19 +81,19 @@ func _config_make(m *ice.Message, chain string, arg ...string) {
}
}
func _config_rich(m *ice.Message, name string, key string, arg ...string) {
m.Rich(name, key, kit.Dict(arg))
m.Rich(name, key, kit.Data(arg))
}
func _config_grow(m *ice.Message, name string, key string, arg ...string) {
m.Grow(name, key, kit.Dict(arg))
}
const CONFIG = "config"
const (
SAVE = "save"
LOAD = "load"
RICH = "rich"
GROW = "grow"
)
const CONFIG = "config"
func init() {
Index.Merge(&ice.Context{
@ -105,7 +101,7 @@ func init() {
CONFIG: {Name: "config", Help: "配置", Value: kit.Data("path", "var/conf")},
},
Commands: map[string]*ice.Command{
CONFIG: {Name: "config [all] [chain [key [arg...]]]", Help: "配置", Action: map[string]*ice.Action{
CONFIG: {Name: "config key auto", Help: "配置", Action: map[string]*ice.Action{
SAVE: {Name: "save", Help: "保存", Hand: func(m *ice.Message, arg ...string) {
_config_save(m, arg[0], arg[1:]...)
}},
@ -119,8 +115,8 @@ func init() {
_config_grow(m, arg[0], arg[1], arg[2:]...)
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if all, arg := _parse_arg_all(m, arg...); len(arg) == 0 {
_config_list(m, all)
if len(arg) == 0 {
_config_list(m)
return
}
_config_make(m, arg[0], arg[1:]...)

39
base/ctx/context.go Normal file
View File

@ -0,0 +1,39 @@
package ctx
import (
ice "github.com/shylinux/icebergs"
kit "github.com/shylinux/toolkits"
)
func _context_list(m *ice.Message, all bool) {
m.Travel(func(p *ice.Context, s *ice.Context) {
m.Push(kit.MDB_NAME, kit.Select("ice", s.Cap(ice.CTX_FOLLOW)))
m.Push(ice.CTX_STATUS, s.Cap(ice.CTX_STATUS))
m.Push(ice.CTX_STREAM, s.Cap(ice.CTX_STREAM))
m.Push(kit.MDB_HELP, s.Help)
})
}
const CONTEXT = "context"
func init() {
Index.Merge(&ice.Context{
Commands: map[string]*ice.Command{
CONTEXT: {Name: "context name=web.chat action=context,command,config key auto", Help: "模块", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Search(kit.Select("ice", arg, 0)+".", func(p *ice.Context, s *ice.Context, key string) {
msg := m.Spawn(s)
defer m.Copy(msg)
switch kit.Select(CONTEXT, arg, 1) {
case CONTEXT:
_context_list(msg, true)
case COMMAND:
msg.Cmdy(COMMAND, arg[2:])
case CONFIG:
msg.Cmdy(CONFIG, arg[2:])
}
})
}},
},
}, nil)
}

View File

@ -1,68 +1,15 @@
package ctx
import (
"strings"
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"strings"
)
func _parse_arg_all(m *ice.Message, arg ...string) (bool, []string) {
if len(arg) > 0 && arg[0] == "all" {
return true, arg[1:]
}
return false, arg
}
func _context_list(m *ice.Message, all bool) {
p := m.Spawn(m.Source())
if all {
p = ice.Pulse
}
p.Travel(func(p *ice.Context, s *ice.Context) {
if p != nil {
m.Push("ups", kit.Select("shy", p.Cap(ice.CTX_FOLLOW)))
} else {
m.Push("ups", "shy")
}
m.Push(kit.MDB_NAME, s.Name)
m.Push(ice.CTX_STATUS, s.Cap(ice.CTX_STATUS))
m.Push(ice.CTX_STREAM, s.Cap(ice.CTX_STREAM))
m.Push("help", s.Help)
})
}
const CONTEXT = "context"
var Index = &ice.Context{Name: "ctx", Help: "配置模块",
Commands: map[string]*ice.Command{
CONTEXT: {Name: "context [all] [name [command|config arg...]]", Help: "模块", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if all, arg := _parse_arg_all(m, arg...); len(arg) == 0 {
_context_list(m, all)
return
}
if len(arg) > 1 && arg[1] == COMMAND {
m.Search(arg[0]+".", func(sup *ice.Context, sub *ice.Context, key string) {
m.Copy(m.Spawn(sub).Cmd(COMMAND, arg[2:]))
})
} else {
m.Search(arg[0]+".", func(p *ice.Context, s *ice.Context, key string) {
msg := m.Spawn(s)
switch kit.Select(CONTEXT, arg, 1) {
case CONTEXT:
_context_list(msg, true)
case COMMAND:
msg.Cmdy(COMMAND, arg[0], arg[2:])
case CONFIG:
msg.Cmdy(CONFIG, arg[2:])
}
m.Copy(msg)
})
}
}},
ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd(mdb.SEARCH, mdb.CREATE, COMMAND, m.AddCmd(&ice.Command{Hand: func(m *ice.Message, c *ice.Context, cc string, arg ...string) {
arg = arg[1:]

6
base/ctx/ctx.shy Normal file
View File

@ -0,0 +1,6 @@
chapter "ctx"
field "模块" context
field "命令" command
field "配置" config

View File

@ -13,7 +13,7 @@ func _event_listen(m *ice.Message, event string, cmd string) {
func _event_action(m *ice.Message, event string, arg ...string) {
m.Option(mdb.FIELDS, "time,id,cmd")
m.Cmd(mdb.SELECT, EVENT, kit.Keys(kit.MDB_HASH, kit.Hashs(event)), mdb.LIST).Table(func(index int, value map[string]string, head []string) {
m.Cmd(kit.Split(value[kit.SSH_CMD]), event, arg).Cost("event %v %v", event, arg)
m.Cmd(kit.Split(value[kit.SSH_CMD]), event, arg).Cost(EVENT, event, "arg", arg)
})
}

View File

@ -7,7 +7,6 @@ import (
const LEX = "lex"
var Index = &ice.Context{Name: LEX, Help: "词法模块",
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Echo("hello %s world", c.Name)

View File

@ -12,13 +12,13 @@ import (
"strings"
)
func _fields(m *ice.Message) []string {
return kit.Split(kit.Select("time,hash,type,name,text", strings.Join(kit.Simple(m.Optionv(FIELDS)), ",")))
}
func _file_name(m *ice.Message, arg ...string) string {
return kit.Select(path.Join("usr/export", path.Join(arg[:2]...)), arg, 3)
}
func _hash_fields(m *ice.Message) []string {
return kit.Split(kit.Select("time,hash,type,name,text", strings.Join(kit.Simple(m.Optionv(FIELDS)), ",")))
}
func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) {
m.Log_INSERT(kit.MDB_KEY, path.Join(prefix, chain), arg[0], arg[1])
m.Echo(m.Rich(prefix, chain, kit.Data(arg)))
@ -33,7 +33,7 @@ func _hash_select(m *ice.Message, prefix, chain, field, value string) {
if field == kit.MDB_HASH && value == RANDOM {
value = kit.MDB_RANDOMS
}
fields := _fields(m)
fields := _hash_fields(m)
m.Richs(prefix, chain, value, func(key string, val map[string]interface{}) {
if val[kit.MDB_META] != nil {
val = val[kit.MDB_META].(map[string]interface{})
@ -86,13 +86,11 @@ func _hash_import(m *ice.Message, prefix, chain, file string) {
count := 0
if m.Conf(prefix, kit.Keys(chain, kit.MDB_META, kit.MDB_SHORT)) == "" {
for k, data := range list {
// 导入数据
m.Conf(prefix, kit.Keys(chain, kit.MDB_HASH, k), data)
count++
}
} else {
for _, data := range list {
// 导入数据
m.Rich(prefix, chain, data)
count++
}
@ -102,7 +100,7 @@ func _hash_import(m *ice.Message, prefix, chain, file string) {
m.Echo("%d", count)
}
func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) {
fields := kit.Split(kit.Select("time,hash,type,name,text", m.Option(FIELDS)))
fields := _hash_fields(m)
m.Richs(prefix, chain, kit.MDB_FOREACH, func(key string, val map[string]interface{}) {
if val[kit.MDB_META] != nil {
val = val[kit.MDB_META].(map[string]interface{})
@ -137,6 +135,9 @@ func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) {
m.Sort(kit.MDB_COUNT, "int_r")
}
func _list_fields(m *ice.Message) []string {
return kit.Split(kit.Select("time,id,type,name,text", strings.Join(kit.Simple(m.Optionv(FIELDS)), ",")))
}
func _list_insert(m *ice.Message, prefix, chain string, arg ...string) {
m.Log_INSERT(kit.MDB_KEY, path.Join(prefix, chain), arg[0], arg[1])
m.Echo("%d", m.Grow(prefix, chain, kit.Dict(arg)))
@ -144,8 +145,11 @@ func _list_insert(m *ice.Message, prefix, chain string, arg ...string) {
func _list_delete(m *ice.Message, prefix, chain, field, value string) {
}
func _list_select(m *ice.Message, prefix, chain, field, value string) {
fields := kit.Split(kit.Select("time,id,type,name,text", m.Option(FIELDS)))
m.Grows(prefix, chain, field, value, func(index int, val map[string]interface{}) {
if value == "" {
field = ""
}
fields := _list_fields(m)
m.Grows(prefix, chain, kit.Select(m.Option("cache.field"), field), kit.Select(m.Option("cache.value"), value), func(index int, val map[string]interface{}) {
if val[kit.MDB_META] != nil {
val = val[kit.MDB_META].(map[string]interface{})
}
@ -257,9 +261,12 @@ func _list_inputs(m *ice.Message, prefix, chain string, field, value string) {
m.Sort(kit.MDB_COUNT, "int_r")
}
func _zone_fields(m *ice.Message) []string {
return kit.Split(kit.Select("zone,id,time,type,name,text", strings.Join(kit.Simple(m.Optionv(FIELDS)), ",")))
}
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)))
fields := _zone_fields(m)
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{})
@ -301,7 +308,7 @@ func _zone_export(m *ice.Message, prefix, chain, file string) {
w := csv.NewWriter(f)
defer w.Flush()
fields := kit.Split(kit.Select("zone,id,time,type,name,text", m.Option(FIELDS)))
fields := _zone_fields(m)
w.Write(fields)
count := 0

View File

@ -1,71 +0,0 @@
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)
}

View File

@ -52,7 +52,7 @@ func _ssh_watch(m *ice.Message, meta map[string]string, h string, input io.Reade
switch buf[i] {
case '\r', '\n':
cmd := strings.TrimSpace(string(buf[:i]))
m.Log_IMPORT(aaa.HOSTNAME, meta[aaa.HOSTNAME], aaa.USERNAME, meta[aaa.USERNAME], CMD, cmd)
m.Log_IMPORT(tcp.HOSTNAME, meta[tcp.HOSTNAME], aaa.USERNAME, meta[aaa.USERNAME], CMD, cmd)
m.Cmdy(mdb.INSERT, CHANNEL, kit.Keys(kit.MDB_HASH, h), mdb.LIST, kit.MDB_TYPE, CMD, kit.MDB_TEXT, cmd)
i = 0
default:

View File

@ -24,7 +24,7 @@ func _ssh_conn(m *ice.Message, conn net.Conn, username, hostport string) (*ssh.C
c, chans, reqs, err := ssh.NewClientConn(conn, hostport, &ssh.ClientConfig{
User: username, Auth: methods, HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
m.Logs(CONNECT, aaa.HOSTNAME, hostname, aaa.HOSTPORT, remote.String())
m.Logs(CONNECT, tcp.HOSTNAME, hostname, tcp.HOSTPORT, remote.String())
return nil
},
})

View File

@ -283,7 +283,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool {
r, f.stdout = os.Stdin, os.Stdout
m.Option("_option", ice.MSG_USERNAME)
m.Option(ice.MSG_USERNAME, cli.UserName)
m.Option(ice.MSG_USERNAME, ice.Info.UserName)
m.Option(ice.MSG_USERROLE, aaa.ROOT)
m.Option(ice.MSG_USERZONE, "boot")
aaa.UserRoot(m)
@ -355,7 +355,7 @@ func init() {
}
if arg[0] == STDIO {
m.Option("_control", "page")
m.Option("_control", "_page")
} else {
m.Option("cache.limit", "-1")
}

View File

@ -23,7 +23,7 @@ import (
)
func _ssh_meta(conn ssh.ConnMetadata) map[string]string {
return map[string]string{aaa.USERNAME: conn.User(), aaa.HOSTPORT: conn.RemoteAddr().String()}
return map[string]string{aaa.USERNAME: conn.User(), tcp.HOSTPORT: conn.RemoteAddr().String()}
}
func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
@ -31,7 +31,7 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotAuth)
if tcp.IsLocalHost(m, strings.Split(conn.RemoteAddr().String(), ":")[0]) {
m.Log_AUTH(aaa.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
m.Log_AUTH(tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
err = nil // 本机用户
} else {
m.Cmd(mdb.SELECT, SERVICE, kit.Keys(kit.MDB_HASH, h), mdb.LIST).Table(func(index int, value map[string]string, head []string) {
@ -42,8 +42,8 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
if pub, e := ssh.ParsePublicKey([]byte(s)); !m.Warn(e != nil, e) {
if bytes.Compare(pub.Marshal(), key.Marshal()) == 0 {
m.Log_AUTH(aaa.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), aaa.HOSTNAME, value[kit.MDB_NAME])
meta[aaa.HOSTNAME] = kit.Select("", kit.Split(value[kit.MDB_NAME], "@"), 1)
m.Log_AUTH(tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), tcp.HOSTNAME, value[kit.MDB_NAME])
meta[tcp.HOSTNAME] = kit.Select("", kit.Split(value[kit.MDB_NAME], "@"), 1)
err = nil // 认证成功
}
}
@ -56,7 +56,7 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotAuth)
m.Richs(aaa.USER, "", conn.User(), func(k string, value map[string]interface{}) {
if string(password) == kit.Format(value[aaa.PASSWORD]) {
m.Log_AUTH(aaa.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), aaa.PASSWORD, strings.Repeat("*", len(kit.Format(value[aaa.PASSWORD]))))
m.Log_AUTH(tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), aaa.PASSWORD, strings.Repeat("*", len(kit.Format(value[aaa.PASSWORD]))))
err = nil // 密码登录
}
})
@ -64,7 +64,7 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
},
BannerCallback: func(conn ssh.ConnMetadata) string {
m.Log_IMPORT(aaa.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
m.Log_IMPORT(tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
return m.Conf(SERVICE, "meta.welcome")
},
}
@ -94,8 +94,8 @@ func _ssh_accept(m *ice.Message, h string, c net.Conn) {
}
}
func _ssh_handle(m *ice.Message, meta map[string]string, c net.Conn, channel ssh.Channel, requests <-chan *ssh.Request) {
m.Logs(CHANNEL, aaa.HOSTPORT, c.RemoteAddr(), "->", c.LocalAddr())
defer m.Logs("dischan", aaa.HOSTPORT, c.RemoteAddr(), "->", c.LocalAddr())
m.Logs(CHANNEL, tcp.HOSTPORT, c.RemoteAddr(), "->", c.LocalAddr())
defer m.Logs("dischan", tcp.HOSTPORT, c.RemoteAddr(), "->", c.LocalAddr())
shell := kit.Select("bash", os.Getenv("SHELL"))
list := []string{"PATH=" + os.Getenv("PATH")}
@ -110,7 +110,7 @@ func _ssh_handle(m *ice.Message, meta map[string]string, c net.Conn, channel ssh
meta[CHANNEL] = h
for request := range requests {
m.Logs("request", aaa.HOSTPORT, c.RemoteAddr(), kit.MDB_TYPE, request.Type)
m.Logs("request", tcp.HOSTPORT, c.RemoteAddr(), kit.MDB_TYPE, request.Type)
switch request.Type {
case "pty-req":

View File

@ -14,7 +14,7 @@ var Index = &ice.Context{Name: SSH, Help: "终端模块", Commands: map[string]*
}},
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if _, ok := m.Target().Server().(*Frame); ok {
m.Done()
m.Done(true)
}
m.Richs(SERVICE, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
kit.Value(value, "meta.status", tcp.CLOSE)

View File

@ -56,10 +56,11 @@ func init() {
},
Commands: map[string]*ice.Command{
CLIENT: {Name: "client hash auto 清理", Help: "客户端", Action: map[string]*ice.Action{
DIAL: {Name: "dial port=9010 host=", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
DIAL: {Name: "dial type name port=9010 host=", 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, PORT, m.Option(PORT), HOST, m.Option(HOST),
kit.MDB_NAME, m.Option(kit.MDB_NAME), kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
kit.MDB_TYPE, m.Option(kit.MDB_TYPE), kit.MDB_NAME, m.Option(kit.MDB_NAME),
kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
c = &Conn{m: m, h: h, s: &Stat{}, Conn: c}
if e == nil {
@ -92,10 +93,10 @@ func init() {
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("time,hash,status,name,host,port,error,nread,nwrite", mdb.DETAIL, len(arg) > 0))
m.Option(mdb.FIELDS, kit.Select("time,hash,status,type,name,host,port,error,nread,nwrite", mdb.DETAIL, len(arg) > 0))
if m.Cmdy(mdb.SELECT, CLIENT, "", mdb.HASH, kit.MDB_HASH, arg); len(arg) == 0 {
m.Table(func(index int, value map[string]string, head []string) {
m.PushButton(kit.Select("", "删除", value[kit.MDB_STATUS] == CLOSE))
m.PushButton(kit.Select("", "删除", value[kit.MDB_STATUS] == OPEN))
})
}
}},

View File

@ -60,6 +60,10 @@ func _islocalhost(m *ice.Message, ip string) (ok bool) {
}
func IsLocalHost(m *ice.Message, ip string) bool { return _islocalhost(m, ip) }
const (
HOSTPORT = "hostport"
HOSTNAME = "hostname"
)
const HOST = "host"
func init() {

View File

@ -27,7 +27,8 @@ func (l Listener) Accept() (net.Conn, error) {
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_NAME, l.m.Option(kit.MDB_NAME), kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
kit.MDB_TYPE, l.m.Option(kit.MDB_TYPE), kit.MDB_NAME, l.m.Option(kit.MDB_NAME),
kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
return &Conn{m: l.m, h: h, s: &Stat{}, Conn: c}, e
}
@ -50,10 +51,10 @@ func init() {
},
Commands: map[string]*ice.Command{
SERVER: {Name: "server hash auto 清理", Help: "服务器", Action: map[string]*ice.Action{
LISTEN: {Name: "LISTEN port=9010 host=", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
LISTEN: {Name: "LISTEN type name port=9010 host=", Help: "监听", Hand: func(m *ice.Message, arg ...string) {
l, e := net.Listen(TCP, m.Option(HOST)+":"+m.Option(PORT))
h := m.Cmdx(mdb.INSERT, SERVER, "", mdb.HASH, PORT, m.Option(PORT), HOST, m.Option(HOST),
kit.MDB_NAME, m.Option(kit.MDB_NAME), kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
h := m.Cmdx(mdb.INSERT, SERVER, "", mdb.HASH, arg,
kit.MDB_STATUS, kit.Select(ERROR, OPEN, e == nil), kit.MDB_ERROR, kit.Format(e))
l = &Listener{m: m, h: h, s: &Stat{}, Listener: l}
if e == nil {
@ -105,7 +106,7 @@ func init() {
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("time,hash,status,name,host,port,error,nconn", mdb.DETAIL, len(arg) > 0))
m.Option(mdb.FIELDS, kit.Select("time,hash,status,type,name,host,port,error,nconn", mdb.DETAIL, len(arg) > 0))
if m.Cmdy(mdb.SELECT, SERVER, "", mdb.HASH, kit.MDB_HASH, arg); len(arg) == 0 {
m.Table(func(index int, value map[string]string, head []string) {
m.PushButton(kit.Select("", "删除", value[kit.MDB_STATUS] == CLOSE))

View File

@ -13,31 +13,13 @@ import (
)
func _cache_name(m *ice.Message, h string) string {
return path.Join(m.Conf(CACHE, "meta.path"), h[:2], h)
}
func _cache_list(m *ice.Message, key string) {
if key == "" {
m.Grows(CACHE, nil, "", "", func(index int, value map[string]interface{}) {
// 缓存列表
m.Push("", value, []string{kit.MDB_TIME, kit.MDB_ID, DATA, kit.MDB_TYPE})
m.Push(kit.MDB_SIZE, kit.FmtSize(kit.Int64(value[kit.MDB_SIZE])))
m.Push("", value, []string{kit.MDB_NAME, kit.MDB_TEXT})
})
m.Sort(kit.MDB_ID, "int_r")
return
}
m.Richs(CACHE, nil, key, func(key string, value map[string]interface{}) {
// 缓存详情
m.Push("detail", value)
})
return path.Join(m.Conf(CACHE, kit.META_PATH), h[:2], h)
}
func _cache_save(m *ice.Message, kind, name, text string, arg ...string) { // file size
if name == "" {
return
}
if len(text) > 512 {
// 存入文件
if len(text) > 512 { // 存入文件
p := m.Cmdx(nfs.SAVE, _cache_name(m, kit.Hashs(text)), text)
text, arg = p, kit.Simple(p, len(text))
}
@ -46,17 +28,9 @@ func _cache_save(m *ice.Message, kind, name, text string, arg ...string) { // fi
size := kit.Int(kit.Select(kit.Format(len(text)), arg, 1))
file := kit.Select("", arg, 0)
text = kit.Select(file, text)
h := m.Rich(CACHE, nil, kit.Dict(
h := m.Cmdx(mdb.INSERT, CACHE, "", mdb.HASH,
kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, text,
kit.MDB_FILE, file, kit.MDB_SIZE, size,
))
m.Log_CREATE(CACHE, h, kit.MDB_TYPE, kind, kit.MDB_NAME, name)
// 添加记录
m.Grow(CACHE, nil, kit.Dict(
kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, text,
kit.MDB_SIZE, size, DATA, h,
))
kit.MDB_FILE, file, kit.MDB_SIZE, size)
// 返回结果
m.Push(kit.MDB_TIME, m.Time())
@ -68,15 +42,15 @@ func _cache_save(m *ice.Message, kind, name, text string, arg ...string) { // fi
m.Push(DATA, h)
}
func _cache_watch(m *ice.Message, key, file string) {
m.Richs(CACHE, nil, key, func(key string, value map[string]interface{}) {
if value[kit.MDB_FILE] == nil {
m.Option(mdb.FIELDS, "time,hash,size,type,name,text,file")
m.Cmd(mdb.SELECT, CACHE, "", mdb.HASH, kit.MDB_HASH, key).Table(func(index int, value map[string]string, head []string) {
if value[kit.MDB_FILE] == "" {
m.Cmdy(nfs.SAVE, file, value[kit.MDB_TEXT])
} else {
m.Cmdy(nfs.LINK, file, value[kit.MDB_FILE])
}
})
}
func _cache_catch(m *ice.Message, name string) (file, size string) {
if f, e := os.Open(name); m.Assert(e) {
defer f.Close()
@ -99,7 +73,7 @@ func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size stri
buf.Seek(0, os.SEEK_SET)
if n, e := io.Copy(f, buf); m.Assert(e) {
m.Log_IMPORT(kit.MDB_FILE, p, kit.MDB_SIZE, kit.FmtSize(int64(n)))
return h.Header.Get("Content-Type"), h.Filename, p, kit.Format(n)
return h.Header.Get(ContentType), h.Filename, p, kit.Format(n)
}
}
}
@ -108,7 +82,7 @@ func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size stri
func _cache_download(m *ice.Message, r *http.Response) (file, size string) {
defer r.Body.Close()
total := kit.Int(kit.Select("1", r.Header.Get("Content-Length")))
total := kit.Int(kit.Select("1", r.Header.Get(ContentLength)))
if f, p, e := kit.Create(path.Join("var/tmp", kit.Hashs("uniq"))); m.Assert(e) {
size, buf := 0, make([]byte, 1024)
for {
@ -160,18 +134,15 @@ const CACHE = "cache"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
CACHE: {Name: "cache", Help: "缓存池", Value: kit.Data(
kit.MDB_SHORT, kit.MDB_TEXT,
kit.MDB_PATH, "var/file",
kit.MDB_STORE, "var/data",
kit.MDB_FSIZE, "200000",
kit.MDB_LIMIT, "50",
kit.MDB_LEAST, "30",
CACHE: {Name: CACHE, Help: "缓存池", Value: kit.Data(
kit.MDB_SHORT, kit.MDB_TEXT, kit.MDB_PATH, "var/file",
kit.MDB_STORE, "var/data", kit.MDB_FSIZE, "200000",
kit.MDB_LIMIT, "50", kit.MDB_LEAST, "30",
)},
},
Commands: map[string]*ice.Command{
CACHE: {Name: "cache data=auto auto", Help: "缓存池", Action: map[string]*ice.Action{
WATCH: {Name: "watch key file", Help: "查看", Hand: func(m *ice.Message, arg ...string) {
CACHE: {Name: "cache hash auto", Help: "缓存池", Action: map[string]*ice.Action{
WATCH: {Name: "watch key file", Help: "释放", Hand: func(m *ice.Message, arg ...string) {
_cache_watch(m, arg[0], arg[1])
}},
WRITE: {Name: "write type name text", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
@ -186,15 +157,16 @@ func init() {
_cache_save(m, kind, name, "", file, size)
}},
DOWNLOAD: {Name: "download type name", Help: "下载", Hand: func(m *ice.Message, arg ...string) {
if r, ok := m.Optionv("response").(*http.Response); ok {
if r, ok := m.Optionv(RESPONSE).(*http.Response); ok {
file, size := _cache_download(m, r)
_cache_save(m, arg[0], arg[1], "", file, size)
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, "time,size,type,name,text,file")
m.Cmdy(mdb.SELECT, m.Prefix(CACHE), "", mdb.HASH, kit.MDB_HASH, arg)
m.Option(mdb.FIELDS, "time,hash,size,type,name,text,file")
m.Cmdy(mdb.SELECT, CACHE, "", mdb.HASH, kit.MDB_HASH, arg)
}},
"/cache/": {Name: "/cache/", Help: "缓存池", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Richs(CACHE, nil, arg[0], func(key string, value map[string]interface{}) {
if value[kit.MDB_FILE] == nil {

View File

@ -4,6 +4,7 @@ import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/gdb"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs"
kit "github.com/shylinux/toolkits"
@ -14,33 +15,35 @@ import (
)
func _dream_list(m *ice.Message) {
// 任务列表
m.Cmdy(nfs.DIR, m.Conf(DREAM, "meta.path"), "time name").Table(func(index int, value map[string]string, head []string) {
m.Cmdy(nfs.DIR, m.Conf(DREAM, kit.META_PATH), "time size name").Table(func(index int, value map[string]string, head []string) {
if m.Richs(SPACE, nil, value[kit.MDB_NAME], func(key string, value map[string]interface{}) {
m.Push(kit.MDB_TYPE, value[kit.MDB_TYPE])
m.Push(kit.MDB_STATUS, gdb.START)
m.PushButton(gdb.STOP)
}) == nil {
m.Push(kit.MDB_TYPE, "none")
m.Push(kit.MDB_TYPE, WORKER)
m.Push(kit.MDB_STATUS, gdb.STOP)
m.PushButton(gdb.START)
}
m.PushRender("action", "button", "start,stop,restart")
})
m.Sort(kit.MDB_NAME)
m.Sort(kit.MDB_NAME, "str_r")
}
func _dream_show(m *ice.Message, name string) {
// 规范命名
if !strings.Contains(name, "-") || !strings.HasPrefix(name, "20") {
name = m.Time("20060102-") + name
name = m.Time("20060102-") + strings.ReplaceAll(name, "-", "_")
}
// 创建目录
p := path.Join(m.Conf(DREAM, "meta.path"), name)
p := path.Join(m.Conf(DREAM, kit.META_PATH), name)
os.MkdirAll(p, ice.MOD_DIR)
if m.Option("repos") != "" {
m.Cmd("web.code.git.repos", "create", "remote", m.Option("repos"), "path", p)
// 下载代码
if m.Option(kit.SSH_REPOS) != "" {
m.Cmd("web.code.git.repos", mdb.CREATE, kit.SSH_REPOS, m.Option(kit.SSH_REPOS), kit.MDB_PATH, p)
}
// 任务脚本
miss := path.Join(p, "etc/miss.sh")
if _, e := os.Stat(miss); e != nil {
m.Cmd(nfs.SAVE, miss, m.Conf(DREAM, "meta.miss"))
@ -49,39 +52,36 @@ func _dream_show(m *ice.Message, name string) {
if b, e := ioutil.ReadFile(path.Join(p, m.Conf(gdb.SIGNAL, "meta.pid"))); e == nil {
if s, e := os.Stat("/proc/" + string(b)); e == nil && s.IsDir() {
m.Info("already exists %v", string(b))
// 已经启动
return
return // 已经启动
}
}
if m.Richs(SPACE, nil, name, nil) == nil {
// 启动任务
m.Option(cli.CMD_DIR, p)
m.Option(cli.CMD_STDERR, path.Join(p, m.Conf(DREAM, "meta.env.ctx_log")))
m.Optionv(cli.CMD_DIR, p)
m.Optionv(cli.CMD_ENV, kit.Simple(
"ctx_dev", m.Conf(cli.RUNTIME, "conf.ctx_dev"),
"PATH", kit.Path(path.Join(p, "bin"))+":"+os.Getenv("PATH"),
"USER", cli.UserName,
m.Confv(DREAM, "meta.env"),
"USER", ice.Info.UserName, m.Confv(DREAM, "meta.env"),
))
// 启动任务
m.Optionv(cli.CMD_STDERR, path.Join(p, m.Conf(DREAM, "meta.env.ctx_log")))
m.Cmd(cli.DAEMON, m.Confv(DREAM, "meta.cmd"), "self", name)
}
m.Cmdy(nfs.DIR, p)
}
const DREAM = "dream"
const (
DREAM_START = "dream.start"
DREAM_STOP = "dream.stop"
)
const DREAM = "dream"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
DREAM: {Name: "dream", Help: "梦想家", Value: kit.Data("path", "usr/local/work",
"cmd", []interface{}{"ice.bin", SPACE, "connect"}, "env", kit.Dict(
"ctx_log", "bin/boot.log", "ctx_mod", "ctx,log,gdb,ssh",
),
DREAM: {Name: DREAM, Help: "梦想家", Value: kit.Data("path", "usr/local/work",
"cmd", []interface{}{"ice.bin", SPACE, "connect"},
"env", kit.Dict("ctx_log", "bin/boot.log"),
"miss", `#!/bin/bash
[ -f ~/.ish/plug.sh ] || [ -f ./.ish/plug.sh ] || git clone ${ISH_CONF_HUB_PROXY:="https://"}github.com/shylinux/intshell ./.ish
[ "$ISH_CONF_PRE" != "" ] || source ./.ish/plug.sh || source ~/.ish/plug.sh
@ -97,29 +97,26 @@ 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.SSH_REPOS)), m.Option(kit.MDB_NAME)))
_dream_show(m, m.Option(kit.MDB_NAME))
DREAM: {Name: "dream name path auto 启动", Help: "梦想家", Action: map[string]*ice.Action{
gdb.START: {Name: "start type=worker,server name repos", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
_dream_show(m, m.Option(kit.MDB_NAME, kit.Select(path.Base(m.Option(kit.SSH_REPOS)), m.Option(kit.MDB_NAME))))
}},
gdb.STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPACE, m.Option(kit.MDB_NAME), "exit", "1")
m.Cmdy(SPACE, m.Option(kit.MDB_NAME), "exit", "0")
}},
gdb.RESTART: {Name: "restart", Help: "重启", Hand: func(m *ice.Message, arg ...string) {
m.Cmd(SPACE, m.Option(kit.MDB_NAME), "exit", "1")
m.Sleep("1s")
_dream_show(m, m.Option(kit.MDB_NAME))
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case kit.MDB_NAME:
m.Cmdy(nfs.DIR, m.Conf(DREAM, kit.META_PATH), "name,time")
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
_dream_list(m)
return
}
if len(arg) > 1 {
m.Cmdy(SPACE, arg[0], arg[1:])
return
}
_dream_show(m, arg[0])
m.Option(nfs.DIR_ROOT, path.Join(m.Conf(DREAM, kit.META_PATH), arg[0]))
m.Cmdy(nfs.DIR, arg[1:])
}},
},
}, nil)

View File

@ -3,7 +3,6 @@ package web
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/mdb"
kit "github.com/shylinux/toolkits"
"github.com/skip2/go-qrcode"
@ -14,26 +13,6 @@ import (
"time"
)
func URL(m *ice.Message, path string, arg ...interface{}) string {
list := kit.Simple(arg)
if m.Option("pod") != "" {
list = append(list, "pod", m.Option("pod"))
}
return kit.MergeURL2(m.R.Header.Get("Origin"), path, list)
}
func Count(m *ice.Message, cmd, key, name string) int {
count := kit.Int(m.Conf(cmd, kit.Keys(key, name)))
m.Conf(cmd, kit.Keys(key, name), count+1)
return count
}
func Format(key string, arg ...interface{}) string {
switch args := kit.Simple(arg); key {
case "a":
return fmt.Sprintf("<a href='%s' target='_blank'>%s</a>", kit.Format(args[0]), kit.Select(kit.Format(args[0]), args, 1))
}
return ""
}
const (
STATUS = "status"
COOKIE = "cookie"
@ -97,69 +76,7 @@ func RenderCookie(msg *ice.Message, value string, arg ...string) { // name path
expire := time.Now().Add(kit.Duration(kit.Select(msg.Conf(aaa.SESS, "meta.expire"), arg, 2)))
http.SetCookie(msg.W, &http.Cookie{Value: value, Name: kit.Select(ice.MSG_SESSID, arg, 0), Path: kit.Select("/", arg, 1), Expires: expire})
}
func RenderStatus(msg *ice.Message, code int, text string) { // name path expire
func RenderStatus(msg *ice.Message, code int, text string) {
msg.W.WriteHeader(code)
msg.W.Write([]byte(text))
}
var RENDER = struct {
A string
IMG string
Video string
Field string
Frame string
Button string
Download string
}{
A: "a",
IMG: "img",
Video: "video",
Field: "field",
Frame: "frame",
Button: "button",
Download: "download",
}
func init() {
Index.Merge(&ice.Context{
Commands: map[string]*ice.Command{
"_render": {Action: map[string]*ice.Action{
RENDER.A: {Hand: func(m *ice.Message, arg ...string) {
// u := kit.Select(m.Conf(SHARE, "meta.domain"), arg, 1)
u := kit.Select(arg[0], arg, 1)
m.Echo(`<a href="%s" target="_blank">%s</a>`, u, arg[0])
}},
RENDER.IMG: {Hand: func(m *ice.Message, arg ...string) {
m.Echo(`<img src="%s" height=%s>`, arg[0], kit.Select("120", arg, 1))
}},
RENDER.Video: {Hand: func(m *ice.Message, arg ...string) {
m.Echo(`<video src="%s" height=%s controls>`, arg[0], kit.Select("120", arg, 1))
}},
RENDER.Field: {Hand: func(m *ice.Message, arg ...string) {
m.Echo(`<fieldset><legend>%s(%s)</legend><form></form></fieldset>`, arg[0], arg[1])
}},
RENDER.Frame: {Hand: func(m *ice.Message, arg ...string) {
m.Echo(`<iframe src=%s class="story" data-type="iframe" width=800 height=400 ></iframe>`, arg[0])
}},
RENDER.Button: {Hand: func(m *ice.Message, arg ...string) {
m.Echo(`<input type="button" value="%s">`, arg[0])
}},
RENDER.Download: {Hand: func(m *ice.Message, arg ...string) {
m.Echo(`<a href="%s" target="_blank" download="%s">%s</a>`, arg[0], kit.Select(path.Base(arg[0]), arg, 1), kit.Select(arg[0], arg, 1))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if arg[0] == mdb.RENDER {
m.Search("_render", func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
if action, ok := cmd.Action[arg[1]]; ok {
action.Hand(m, arg[2:]...)
}
})
return
}
m.Echo(`<input type="%s" value="%s">`, arg[1], arg[2])
}},
},
}, nil)
}

View File

@ -2,9 +2,11 @@ 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/gdb"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs"
"github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
)
@ -13,9 +15,8 @@ func _route_travel(m *ice.Message, route string) {
m.Richs(SPACE, nil, kit.MDB_FOREACH, func(key string, val map[string]interface{}) {
switch val[kit.MDB_TYPE] {
case SERVER:
if val[kit.MDB_NAME] == cli.NodeName {
// 避免循环
return
if val[kit.MDB_NAME] == ice.Info.NodeName {
return // 避免循环
}
// 远程查询
@ -46,100 +47,91 @@ func init() {
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{
"inputs": {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case "cmd":
m.Cmdy(SPACE, m.Option("route"), "command")
case "name":
m.Cmdy(SPACE, m.Option("route"), "dream")
case "template":
m.Option(nfs.DIR_DEEP, true)
m.Cmdy(nfs.DIR, "usr/icebergs")
m.Sort("path")
}
}},
"invite": {Name: "invite", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
ROUTE: {Name: "route route ctx cmd auto invite", Help: "路由", Action: map[string]*ice.Action{
mdb.INVITE: {Name: "invite", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("web.code.publish", "contexts", "tmux")
m.Cmdy("web.code.publish", "contexts", "base")
m.Cmdy("web.code.publish", "contexts", "miss")
}},
"start": {Name: "start type=worker,server name=hi@key repos", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option("route"), "dream", "start", arg)
mdb.INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
switch arg[0] {
case "cmd":
m.Cmdy(SPACE, m.Option(ROUTE), ctx.COMMAND)
case "name":
m.Cmdy(SPACE, m.Option(ROUTE), DREAM)
case "template":
m.Option(nfs.DIR_DEEP, true)
m.Cmdy(nfs.DIR, "usr/icebergs")
m.Sort(kit.MDB_PATH)
}
}},
gdb.START: {Name: "start type=worker,server name=hi@key repos", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(ROUTE), DREAM, gdb.START, arg)
m.Sleep("3s")
}},
gdb.STOP: {Name: "stop", Help: "结束", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option(ROUTE), "exit")
m.Sleep("3s")
}},
"gen": {Name: "gen module=hi@key template=usr/icebergs/misc/zsh/zsh.go@key", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option("route"), "web.code.autogen",
m.Cmdy(SPACE, m.Option(ROUTE), "web.code.autogen",
"create", "name", m.Option("module"), "from", m.Option("template"))
}},
"stop": {Name: "stop", Help: "结束", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(SPACE, m.Option("route"), "exit")
m.Sleep("3s")
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) > 3 && arg[3] == "run" {
m.Cmdy(SPACE, arg[0], kit.Keys(arg[1], arg[2]), arg[4:])
return
if len(arg) == 0 || arg[0] == "" {
if _route_travel(m, kit.Select("", arg, 0)); m.W == nil {
return
}
m.Cmd(tcp.HOST).Table(func(index int, value map[string]string, head []string) {
m.Push(kit.MDB_TYPE, MYSELF)
m.Push(ROUTE, value["ip"])
})
m.Table(func(index int, value map[string]string, field []string) {
switch value[kit.MDB_TYPE] {
case MYSELF:
m.PushRender(kit.MDB_LINK, "a", value[kit.SSH_ROUTE], m.Option(ice.MSG_USERWEB))
default:
m.PushRender(kit.MDB_LINK, "a", value[kit.SSH_ROUTE],
kit.MergeURL(m.Option(ice.MSG_USERWEB), kit.SSH_POD, kit.Keys(m.Option(kit.SSH_POD, value[kit.SSH_ROUTE]))))
}
switch value[kit.MDB_TYPE] {
case MYSELF, SERVER:
m.PushButton(gdb.START)
case WORKER:
m.PushButton(gdb.STOP)
default:
m.PushButton("")
}
})
m.Sort(kit.SSH_ROUTE)
return // 设备列表
}
if len(arg) > 2 && arg[0] != "" {
m.Cmdy(SPACE, arg[0], "context", arg[1], "command", arg[2])
if len(arg) > 3 { // 执行命令
m.Cmdy(SPACE, arg[0], kit.Keys(arg[1], arg[2]), arg[4:])
} else if len(arg) > 2 { // 加载插件
m.Cmdy(SPACE, arg[0], ctx.CONTEXT, arg[1], ctx.COMMAND, arg[2])
m.Option("_prefix", arg[0], arg[1], arg[2], "run")
m.Option("_process", "_field")
return
}
if len(arg) > 1 && arg[0] != "" {
m.Cmd(SPACE, arg[0], "context", arg[1], "command").Table(func(index int, value map[string]string, head []string) {
} else if len(arg) > 1 { // 命令列表
m.Cmd(SPACE, arg[0], ctx.CONTEXT, arg[1], ctx.COMMAND).Table(func(index int, value map[string]string, head []string) {
m.Push("cmd", value["key"])
m.Push("name", value["name"])
m.Push("help", value["help"])
})
return
}
if len(arg) > 0 && arg[0] != "" {
m.Cmd(SPACE, arg[0], "context").Table(func(index int, value map[string]string, head []string) {
} else if len(arg) > 0 { // 模块列表
m.Cmd(SPACE, arg[0], ctx.CONTEXT).Table(func(index int, value map[string]string, head []string) {
m.Push("ctx", kit.Keys(value["ups"], value["name"]))
m.Push("status", value["status"])
m.Push("stream", value["stream"])
m.Push("help", value["help"])
})
return
}
if _route_travel(m, kit.Select("", arg, 0)); m.W == nil {
return
}
m.Push("type", MYSELF)
m.Push("route", cli.NodeName)
m.Table(func(index int, value map[string]string, field []string) {
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", "启动")
case WORKER:
m.PushRender("action", "button", "结束")
}
})
m.Sort(kit.SSH_ROUTE)
}},
"/route/": {Name: "/route/", Help: "路由器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] {
case "login":
if m.Option(ice.MSG_USERNAME) != "" {
m.Push(ice.MSG_USERNAME, m.Option(ice.MSG_USERNAME))
m.Info("username: %v", m.Option(ice.MSG_USERNAME))
break
}
if m.Option(ice.MSG_SESSID) != "" && m.Cmdx(aaa.SESS, "check", m.Option(ice.MSG_SESSID)) != "" {
m.Info("sessid: %v", m.Option(ice.MSG_SESSID))
break
}
sessid := m.Cmdx(aaa.SESS, "create", "")
share := m.Cmdx(SHARE, "login", m.Option(ice.MSG_USERIP), sessid)
Render(m, "cookie", sessid)
m.Render(share)
}
}},
}}, nil)

View File

@ -4,10 +4,10 @@ import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/gdb"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
log "github.com/shylinux/toolkits/logs"
"encoding/json"
"net/http"
@ -16,57 +16,88 @@ import (
"strings"
)
const LOGIN = "_login"
const (
SERVE_START = "serve.start"
SERVE_CLOSE = "serve.close"
)
func _serve_login(msg *ice.Message, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) {
msg.Option(ice.MSG_USERNAME, "")
msg.Option(ice.MSG_USERROLE, "void")
if msg.Options(ice.MSG_SESSID) {
// 会话认证
aaa.SessCheck(msg, msg.Option(ice.MSG_SESSID))
func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
if r.Header.Get("index.module") != "" {
return true
}
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") {
// msg.Option(ice.MSG_SESSID, aaa.SessCreate(msg, msg.Option(ice.MSG_USERNAME), msg.Option(ice.MSG_USERROLE)))
// Render(msg, "cookie", msg.Option(ice.MSG_SESSID))
// 解析地址
if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
r.Header.Set(ice.MSG_USERIP, ip)
} else if ip := r.Header.Get("X-Real-Ip"); ip != "" {
r.Header.Set(ice.MSG_USERIP, ip)
} else if strings.HasPrefix(r.RemoteAddr, "[") {
r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, "]")[0][1:])
} else {
r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, ":")[0])
}
m.Info("").Info("%s %s %s", r.Header.Get(ice.MSG_USERIP), r.Method, r.URL)
// 请求地址
r.Header.Set("index.module", m.Target().Name)
r.Header.Set("index.path", r.URL.Path)
r.Header.Set("index.url", r.URL.String())
// 输出日志
if m.Conf(SERVE, "meta.logheaders") == "true" {
for k, v := range r.Header {
m.Info("%s: %v", k, kit.Format(v))
}
m.Info(" ")
defer func() {
for k, v := range w.Header() {
m.Info("%s: %v", k, kit.Format(v))
}
m.Info(" ")
}()
}
// 单点登录
if r.URL.Path == "/" && m.Conf(SERVE, "meta.sso") != "" {
r.ParseForm()
sessid := r.FormValue(ice.MSG_SESSID)
if sessid == "" {
if c, e := r.Cookie(ice.MSG_SESSID); e == nil {
sessid = c.Value
}
}
ok := false
m.Richs(aaa.SESS, "", sessid, func(key string, value map[string]interface{}) {
ok = true
})
if !ok {
http.Redirect(w, r, m.Conf(SERVE, "meta.sso"), http.StatusTemporaryRedirect)
return false
}
return true
}
if _, ok := msg.Target().Commands[LOGIN]; ok {
// 权限检查
msg.Target().Cmd(msg, LOGIN, msg.Option(ice.MSG_USERURL), cmds...)
cmds = kit.Simple(msg.Optionv(ice.MSG_CMDS))
} else if ls := strings.Split(msg.Option(ice.MSG_USERURL), "/"); msg.Conf(SERVE, kit.Keys("meta.black", ls[1])) == "true" {
return cmds, false // black
} else if msg.Conf(SERVE, kit.Keys("meta.white", ls[1])) == "true" {
return cmds, true // white
} else {
if msg.Warn(!msg.Options(ice.MSG_USERNAME), "not login %s", msg.Option(ice.MSG_USERURL)) {
msg.Render(STATUS, 401, "not login")
return cmds, false
}
if msg.Warn(!msg.Right(msg.Option(ice.MSG_USERURL))) {
msg.Render(STATUS, 403, "not auth")
return cmds, false
}
if strings.HasPrefix(r.URL.Path, "/debug") {
r.URL.Path = strings.Replace(r.URL.Path, "/debug", "/code", -1)
return true
}
return cmds, msg.Option(ice.MSG_USERURL) != ""
if b, ok := ice.BinPack[r.URL.Path]; ok {
if strings.HasSuffix(r.URL.Path, ".css") {
w.Header().Set("Content-Type", "text/css; charset=utf-8")
}
w.Write(b)
return false
}
if r.URL.Path == "/" && strings.Contains(r.Header.Get("User-Agent"), "curl") {
http.ServeFile(w, r, path.Join(m.Conf(SERVE, "meta.intshell.path"), m.Conf(SERVE, "meta.intshell.index")))
return false
}
return true
}
func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.ResponseWriter, r *http.Request) {
defer func() { msg.Cost("%s %v %v", r.URL.Path, msg.Optionv(ice.MSG_CMDS), msg.Format("append")) }()
defer func() {
msg.Cost(kit.Format("%s %v %v", r.URL.Path, msg.Optionv(ice.MSG_CMDS), msg.Format(ice.MSG_APPEND)))
}()
// 请求变量
msg.Option(ice.MSG_SESSID, "")
@ -74,17 +105,16 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
msg.Option(v.Name, v.Value)
}
// 请求
msg.Option(ice.MSG_OUTPUT, "")
// 请求地址
if u, e := url.Parse(r.Header.Get("Referer")); e == nil {
for k, v := range u.Query() {
if msg.Logs("refer", k, v); k != "name" {
msg.Option(k, v)
}
msg.Logs("refer", k, v)
msg.Option(k, v)
}
}
// 用户请求
msg.Option(ice.MSG_OUTPUT, "")
msg.Option("cache.limit", "10")
msg.Option(ice.MSG_METHOD, r.Method)
msg.Option(ice.MSG_USERWEB, kit.Select(msg.Conf(SHARE, "meta.domain"), r.Header.Get("Referer")))
@ -98,12 +128,12 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
}
// 解析引擎
switch r.Header.Get("Content-Type") {
case "application/json":
switch r.Header.Get(ContentType) {
case ContentJSON:
var data interface{}
if e := json.NewDecoder(r.Body).Decode(&data); !msg.Warn(e != nil, "%s", e) {
if e := json.NewDecoder(r.Body).Decode(&data); !msg.Warn(e != nil, e) {
msg.Optionv(ice.MSG_USERDATA, data)
msg.Logs("json", "value", kit.Formats(data))
msg.Logs("json", "value", kit.Format(data))
}
switch d := data.(type) {
@ -113,7 +143,7 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
}
}
default:
r.ParseMultipartForm(kit.Int64(kit.Select(r.Header.Get("Content-Length"), "4096")))
r.ParseMultipartForm(kit.Int64(kit.Select(r.Header.Get(ContentLength), "4096")))
if r.ParseForm(); len(r.PostForm) > 0 {
for k, v := range r.PostForm {
msg.Logs("form", k, v)
@ -138,9 +168,6 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
}
}
if msg.Option("cache.begin") == "" {
msg.Option("cache.begin", -kit.Int(msg.Option("cache.limit")))
}
// 执行命令
if cmds, ok := _serve_login(msg, kit.Simple(msg.Optionv(ice.MSG_CMDS)), w, r); ok {
msg.Option("_option", msg.Optionv(ice.MSG_OPTION))
@ -151,111 +178,64 @@ func _serve_handle(key string, cmd *ice.Command, msg *ice.Message, w http.Respon
_args, _ := msg.Optionv(ice.MSG_ARGS).([]interface{})
Render(msg, msg.Option(ice.MSG_OUTPUT), _args...)
}
func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool {
if r.Header.Get("index.module") == "" {
// 解析地址
if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
r.Header.Set(ice.MSG_USERIP, ip)
} else if ip := r.Header.Get("X-Real-Ip"); ip != "" {
r.Header.Set(ice.MSG_USERIP, ip)
} else if strings.HasPrefix(r.RemoteAddr, "[") {
r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, "]")[0][1:])
} else {
r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, ":")[0])
}
m.Info("").Info("%s %s %s", r.Header.Get(ice.MSG_USERIP), r.Method, r.URL)
func _serve_login(msg *ice.Message, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) {
msg.Option(ice.MSG_USERROLE, aaa.VOID)
msg.Option(ice.MSG_USERNAME, "")
r.Header.Set("index.module", m.Target().Name)
r.Header.Set("index.path", r.URL.Path)
r.Header.Set("index.url", r.URL.String())
if m.Conf(SERVE, "meta.logheaders") == "true" {
// 请求参数
for k, v := range r.Header {
m.Info("%s: %v", k, kit.Format(v))
}
m.Info(" ")
defer func() {
// 响应参数
for k, v := range w.Header() {
m.Info("%s: %v", k, kit.Format(v))
}
m.Info(" ")
}()
}
if r.URL.Path == "/" && strings.Contains(r.Header.Get("User-Agent"), "curl") {
http.ServeFile(w, r, path.Join(m.Conf(SERVE, "meta.intshell.path"), m.Conf(SERVE, "meta.intshell.index")))
return false
}
if msg.Options(ice.MSG_SESSID) {
// 会话认证
aaa.SessCheck(msg, msg.Option(ice.MSG_SESSID))
}
if strings.HasPrefix(r.URL.Path, "/debug") {
r.URL.Path = strings.Replace(r.URL.Path, "/debug", "/code", -1)
if !msg.Options(ice.MSG_USERNAME) && tcp.IsLocalHost(msg, msg.Option(ice.MSG_USERIP)) {
// 自动认证
aaa.UserLogin(msg, ice.Info.UserName, ice.Info.PassWord)
}
if r.URL.Path == "/" && m.Conf(SERVE, "meta.sso") != "" {
if r.ParseForm(); r.FormValue(ice.MSG_SESSID) != "" {
return true
}
if _, ok := msg.Target().Commands[LOGIN]; ok {
// 权限检查
msg.Target().Cmd(msg, LOGIN, msg.Option(ice.MSG_USERURL), cmds...)
cmds = kit.Simple(msg.Optionv(ice.MSG_CMDS))
sessid := ""
if c, e := r.Cookie(ice.MSG_SESSID); e == nil {
m.Richs("aaa.sess", "", c.Value, func(key string, value map[string]interface{}) {
sessid = c.Value
})
}
} else if ls := strings.Split(msg.Option(ice.MSG_USERURL), "/"); msg.Conf(SERVE, kit.Keys("meta.black", ls[1])) == "true" {
return cmds, false // 白名单
} else if msg.Conf(SERVE, kit.Keys("meta.white", ls[1])) == "true" {
return cmds, true // 黑名单
if sessid == "" {
http.Redirect(w, r, m.Conf(SERVE, "meta.sso"), http.StatusTemporaryRedirect)
return false
}
return true
} else if r.URL.Path == "/share" && r.Method == "GET" {
http.ServeFile(w, r, m.Conf(SERVE, "meta.volcanos.share"))
} else {
if b, ok := ice.BinPack[r.URL.Path]; ok {
log.Info("BinPack %v %v", r.URL.Path, len(b))
if strings.HasSuffix(r.URL.Path, ".css") {
w.Header().Set("Content-Type", "text/css; charset=utf-8")
}
w.Write(b)
return false
if msg.Warn(!msg.Options(ice.MSG_USERNAME), ice.ErrNotLogin, msg.Option(ice.MSG_USERURL)) {
msg.Render(STATUS, 401, ice.ErrNotLogin)
return cmds, false // 未登录
}
if msg.Warn(!msg.Right(msg.Option(ice.MSG_USERURL))) {
msg.Render(STATUS, 403, ice.ErrNotAuth)
return cmds, false // 未授权
}
return true
}
return false
return cmds, msg.Option(ice.MSG_USERURL) != ""
}
const (
LOGIN = "_login"
)
const (
SERVE_START = "serve.start"
SERVE_CLOSE = "serve.close"
)
const SERVE = "serve"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
SERVE: {Name: "serve", Help: "服务器", Value: kit.Data(
"logheaders", "false",
"black", kit.Dict(),
"white", kit.Dict(
"header", true,
"river", true,
"action", true,
"footer", true,
"login", true,
"share", true,
"space", true,
"route", true,
"static", true,
"plugin", true,
"publish", true,
SERVE: {Name: SERVE, Help: "服务器", Value: kit.Data(
kit.MDB_SHORT, kit.MDB_NAME,
"logheaders", "false", "black", kit.Dict(), "white", kit.Dict(
"space", true, "share", true, "plugin", true, "publish", true,
),
"intshell", kit.Dict(
"index", "index.sh",
"path", "usr/intshell", "require", ".ish/pluged",
"repos", "https://github.com/shylinux/volcanos", "branch", "master",
),
"static", kit.Dict("/", "usr/volcanos/"),
"volcanos", kit.Dict("refresh", "5",
"share", "usr/volcanos/page/share.html",
@ -263,30 +243,40 @@ func init() {
"repos", "https://github.com/shylinux/volcanos", "branch", "master",
), "publish", "usr/publish/",
"static", kit.Dict("/", "usr/volcanos/"),
"template", kit.Dict("path", "usr/template", "list", []interface{}{
`{{define "raw"}}{{.Result}}{{end}}`,
}),
"intshell", kit.Dict(
"index", "index.sh",
"path", "usr/intshell", "require", ".ish/pluged",
"repos", "https://github.com/shylinux/volcanos", "branch", "master",
),
)},
},
Commands: map[string]*ice.Command{
SERVE: {Name: "serve [random] [ups...]", Help: "服务器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if cli.NodeInfo(m, SERVER, cli.HostName); len(arg) > 0 && arg[0] == "random" {
cli.NodeInfo(m, SERVER, cli.PathName)
// 随机端口
m.Cmd(SPIDE, mdb.CREATE, "self", "http://random")
arg = arg[1:]
}
SERVE: {Name: "serve name auto start", Help: "服务器", Action: map[string]*ice.Action{
gdb.START: {Name: "start name=self proto=http host= port=9020 dev=", Help: "启动", Hand: func(m *ice.Message, arg ...string) {
if cli.NodeInfo(m, SERVER, ice.Info.HostName); m.Option(tcp.PORT) == "random" {
m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.Right))
}
// 启动服务
m.Target().Start(m, "self")
defer m.Cmd(SPACE, "connect", "self")
m.Sleep("1s")
m.Target().Start(m, kit.MDB_NAME, m.Option(kit.MDB_NAME), tcp.HOST, m.Option(tcp.HOST), tcp.PORT, m.Option(tcp.PORT))
m.Sleep("1s")
// 连接服务
for _, k := range arg {
m.Cmd(SPACE, "connect", k)
}
for _, k := range kit.Split(m.Option(SPIDE_DEV)) {
m.Cmd(SPACE, "connect", k)
}
}},
aaa.WHITE: {Name: "white", Help: "白名单", Hand: func(m *ice.Message, arg ...string) {
for _, k := range arg {
m.Conf(SERVE, kit.Keys(kit.MDB_META, aaa.WHITE, k), true)
}
}},
aaa.BLACK: {Name: "black", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) {
for _, k := range arg {
m.Conf(SERVE, kit.Keys(kit.MDB_META, aaa.BLACK, k), true)
}
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, kit.Select("time,status,name,port,dev", mdb.DETAIL, len(arg) > 0))
m.Cmdy(mdb.SELECT, SERVE, "", mdb.HASH, kit.MDB_NAME, arg)
}},
}}, nil)
}

View File

@ -77,8 +77,8 @@ const SHARE = "share"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
SHARE: {Name: "share", Help: "共享链", Value: kit.Data(
"expire", "72h", "template", share_template,
SHARE: {Name: SHARE, Help: "共享链", Value: kit.Data(
"expire", "72h",
)},
},
Commands: map[string]*ice.Command{

View File

@ -3,11 +3,10 @@ package web
import (
"github.com/gorilla/websocket"
ice "github.com/shylinux/icebergs"
aaa "github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
"github.com/shylinux/toolkits/task"
"math/rand"
"net"
@ -18,54 +17,68 @@ import (
)
func _space_list(m *ice.Message, space string) {
m.Option(mdb.FIELDS, "time,type,name,text")
m.Option(mdb.FIELDS, kit.Select("time,type,name,text", mdb.DETAIL, space != ""))
m.Cmdy(mdb.SELECT, SPACE, "", mdb.HASH, kit.MDB_HASH, space)
m.Table(func(index int, value map[string]string, head []string) {
m.PushRender(kit.MDB_LINK, "a", kit.Format(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])))
if p := kit.MergeURL(m.Option(ice.MSG_USERWEB), kit.SSH_POD, kit.Keys(m.Option(kit.SSH_POD), kit.Select(value[kit.MDB_VALUE], value[kit.MDB_NAME]))); space == "" {
m.PushRender(kit.MDB_LINK, "a", value[kit.MDB_NAME], p)
} else if value[kit.MDB_KEY] == kit.MDB_NAME {
m.Push(kit.MDB_KEY, kit.MDB_LINK)
m.PushRender(kit.MDB_VALUE, "a", value[kit.MDB_VALUE], p)
}
})
m.Sort(kit.MDB_NAME)
}
func _space_dial(m *ice.Message, dev, name string, arg ...string) {
m.Debug("what %v %v %v", dev, name, arg)
m.Richs(SPIDE, nil, dev, func(key string, value map[string]interface{}) {
m.Debug("what")
client := kit.Value(value, "client").(map[string]interface{})
redial := m.Confm(SPACE, "meta.redial")
web := m.Target().Server().(*Frame)
host := kit.Format(client["hostname"])
proto := kit.Select("ws", "wss", client["protocol"] == "https")
uri := kit.MergeURL(proto+"://"+host+"/space/", "name", name, "type", cli.NodeType, "share", os.Getenv("ctx_share"), "river", os.Getenv("ctx_river"))
uri := kit.MergeURL(proto+"://"+host+"/space/", "name", name, "type", ice.Info.NodeType, "share", os.Getenv("ctx_share"), "river", os.Getenv("ctx_river"))
if u, e := url.Parse(uri); m.Assert(e) {
m.Debug("what")
task.Put(dev, func(task *task.Task) error {
for i := 0; i < kit.Int(redial["c"]); i++ {
if s, e := net.Dial("tcp", host); !m.Warn(e != nil, "%s", e) {
if s, _, e := websocket.NewClient(s, u, nil, kit.Int(redial["r"]), kit.Int(redial["w"])); !m.Warn(e != nil, "%s", e) {
m.Go(func() {
m.Debug("what")
for i := 0; i >= 0 && i < kit.Int(redial["c"]); i++ {
m.Option(tcp.DIAL_CB, func(s net.Conn, e error) {
if m.Warn(e != nil, e) {
return
}
if s, _, e := websocket.NewClient(s, u, nil, kit.Int(redial["r"]), kit.Int(redial["w"])); !m.Warn(e != nil, e) {
m.Rich(SPACE, nil, kit.Dict("socket", s, kit.MDB_TYPE, MASTER, kit.MDB_NAME, dev, kit.MDB_TEXT, host))
m.Log_CREATE(SPACE, dev, "retry", i, "uri", uri)
// 连接成功
m.Rich(SPACE, nil, kit.Dict("socket", s,
kit.MDB_TYPE, MASTER, kit.MDB_NAME, dev, kit.MDB_TEXT, host,
))
m.Log_CREATE("space", dev, "retry", i, "uri", uri)
m = m.Spawns()
if i = 0; _space_handle(m, true, web.send, s, dev) {
// 连接关闭
break
i = -1 // 连接关闭
}
}
}
})
ls := strings.Split(host, ":")
m.Cmd(tcp.CLIENT, tcp.DIAL, kit.MDB_TYPE, "wss", kit.MDB_NAME, dev, tcp.HOST, ls[0], tcp.PORT, ls[1])
// 断线重连
sleep := time.Duration(rand.Intn(kit.Int(redial["a"])*i+2)+kit.Int(redial["b"])) * time.Millisecond
m.Cost("order: %d sleep: %s reconnect: %s", i, sleep, u)
m.Cost("order", i, "sleep", sleep, "reconnect", u)
time.Sleep(sleep)
}
return nil
})
}
})
}
func _space_send(m *ice.Message, space string, arg ...string) {
if space == "" || space == MYSELF || space == ice.Info.NodeName {
m.Cmdy(arg)
return // 本地命令
}
target := strings.Split(space, ".")
frame := m.Target().Server().(*Frame)
m.Warn(m.Richs(SPACE, nil, target[0], func(key string, value map[string]interface{}) {
@ -93,7 +106,7 @@ func _space_send(m *ice.Message, space string, arg ...string) {
m.Call(m.Option("_async") == "", func(res *ice.Message) *ice.Message {
if delete(frame.send, id); res != nil && m != nil {
// 返回结果
return m.Cost("[%v]->%v %v %v", id, target, arg, m.Copy(res).Format("append"))
return m.Cost(kit.Format("[%v]->%v %v %v", id, target, arg, m.Copy(res).Format(ice.MSG_APPEND)))
}
return nil
})
@ -115,7 +128,7 @@ func _space_exec(msg *ice.Message, source, target []string, c *websocket.Conn, n
}
msg.Set("_option")
_space_echo(msg, []string{}, kit.Revert(source)[1:], c, name)
msg.Cost("%v->%v %v %v", source, target, msg.Detailv(), msg.Format("append"))
msg.Cost(kit.Format("%v->%v %v %v", source, target, msg.Detailv(), msg.Format(ice.MSG_APPEND)))
}
func _space_handle(m *ice.Message, safe bool, send map[string]*ice.Message, c *websocket.Conn, name string) bool {
for running := true; running; {
@ -138,10 +151,7 @@ func _space_handle(m *ice.Message, safe bool, send map[string]*ice.Message, c *w
if msg.Optionv(ice.MSG_HANDLE, "true"); !msg.Warn(!safe, ice.ErrNotAuth) {
// 本地执行
msg.Option("_dev", name)
task.Put(nil, func(task *task.Task) error {
_space_exec(msg, source, target, c, name)
return nil
})
msg.Go(func() { _space_exec(msg, source, target, c, name) })
continue
}
} else if msg.Richs(SPACE, nil, target[0], func(key string, value map[string]interface{}) {
@ -176,20 +186,6 @@ func _space_handle(m *ice.Message, safe bool, send map[string]*ice.Message, c *w
return false
}
func _space_search(m *ice.Message, kind, name, text string, arg ...string) {
m.Richs(SPACE, nil, kit.Select(kit.MDB_FOREACH, name), func(key string, value map[string]interface{}) {
if name != "" && name != value[kit.MDB_NAME] && !strings.Contains(kit.Format(value[kit.MDB_TEXT]), name) {
return
}
m.Push("pod", m.Option("pod"))
m.Push("ctx", "web")
m.Push("cmd", SPACE)
m.Push(key, value, []string{kit.MDB_TIME})
m.Push(kit.MDB_SIZE, kit.FmtSize(int64(len(kit.Format(value[kit.MDB_TEXT])))))
m.Push(key, value, []string{kit.MDB_TYPE, kit.MDB_NAME, kit.MDB_TEXT})
})
}
const (
MASTER = "master"
MYSELF = "myself"
@ -201,7 +197,7 @@ const (
const (
SPACE_START = "space.start"
SPACE_CLOSE = "space.close"
SPACE_STOP = "space.stop"
)
const SPACE = "space"
@ -215,24 +211,14 @@ func init() {
},
Commands: map[string]*ice.Command{
SPACE: {Name: "space name cmd auto", Help: "空间站", Action: map[string]*ice.Action{
"connect": {Name: "connect [dev [name]]", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
_space_dial(m, kit.Select("dev", arg, 0), kit.Select(cli.NodeName, arg, 2))
}},
mdb.SEARCH: {Name: "search type name text", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
_space_search(m, arg[0], arg[1], arg[2], arg[3:]...)
"connect": {Name: "connect dev name", Help: "连接", Hand: func(m *ice.Message, arg ...string) {
_space_dial(m, arg[0], kit.Select(ice.Info.NodeName, arg[1]))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) < 2 {
_space_list(m, kit.Select("", arg, 0))
return
}
if arg[0] == "" || arg[0] == MYSELF || arg[0] == cli.NodeName {
// 本地命令
m.Cmdy(arg[1:])
return
}
_space_send(m, arg[0], arg[1:]...)
}},
@ -247,23 +233,21 @@ func init() {
h := m.Rich(SPACE, nil, kit.Dict("socket", s, "share", share, "river", river,
kit.MDB_TYPE, kind, kit.MDB_NAME, name, kit.MDB_TEXT, s.RemoteAddr().String(),
))
m.Log_CREATE(SPACE, name)
task.Put(name, func(task *task.Task) error {
m.Go(func() {
// 监听消息
switch kind {
case WORKER:
m.Event(DREAM_START, name)
defer m.Event(DREAM_STOP, name)
m.Event(DREAM_START, "type", kind, "name", name, "share", share, "river", river)
defer m.Event(DREAM_STOP, "type", kind, "name", name, "share", share, "river", river)
default:
m.Event(SPACE_START, "type", kind, "name", name, "share", share, "river", river)
defer m.Event(SPACE_CLOSE, "type", kind, "name", name, "share", share, "river", river)
defer m.Event(SPACE_STOP, "type", kind, "name", name, "share", share, "river", river)
}
frame := m.Target().Server().(*Frame)
_space_handle(m, false, frame.send, s, name)
m.Log(ice.LOG_CLOSE, "%s: %s", name, kit.Format(m.Confv(SPACE, kit.Keys(kit.MDB_HASH, h))))
m.Confv(SPACE, kit.Keys(kit.MDB_HASH, h), "")
return nil
})
}
}},

View File

@ -2,15 +2,12 @@ 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"
kit "github.com/shylinux/toolkits"
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
@ -22,96 +19,33 @@ import (
"time"
)
func _spide_list(m *ice.Message, name string) {
if name == "" {
m.Richs(SPIDE, nil, kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
m.Push(key, value["client"], []string{"name", "share", "login", "method", "url"})
})
m.Sort("name")
return
}
m.Richs(SPIDE, nil, name, func(key string, value map[string]interface{}) {
m.Push("detail", value)
if kit.Value(value, "client.share") != nil {
m.Push("key", "share")
m.Push("value", fmt.Sprintf(m.Conf(SHARE, "meta.template.text"), m.Conf(SHARE, "meta.domain"), kit.Value(value, "client.share")))
}
})
}
func _spide_show(m *ice.Message, name string) {
}
func _spide_login(m *ice.Message, name string) {
m.Richs(SPIDE, nil, name, func(key string, value map[string]interface{}) {
msg := m.Cmd(SPIDE, name, "msg", "/route/login", "login")
if msg.Append(ice.MSG_USERNAME) != "" {
m.Echo(msg.Append(ice.MSG_USERNAME))
return
}
if msg.Result() != "" {
kit.Value(value, "client.login", msg.Result())
kit.Value(value, "client.share", m.Cmdx(SHARE, SPIDE, name,
kit.Format("%s?sessid=%s", kit.Value(value, "client.url"), kit.Value(value, "cookie.sessid"))))
}
m.Render(ice.RENDER_QRCODE, kit.Dict(
kit.MDB_TYPE, "login", kit.MDB_NAME, name,
kit.MDB_TEXT, kit.Value(value, "cookie.sessid"),
))
})
}
func _spide_create(m *ice.Message, name, address string, arg ...string) {
func _spide_create(m *ice.Message, name, address string) {
if uri, e := url.Parse(address); e == nil && address != "" {
if uri.Host == "random" {
uri.Host = ":" + m.Cmdx(tcp.PORT, aaa.Right)
address = strings.Replace(address, "random", uri.Host, -1)
}
if m.Richs(SPIDE, nil, name, func(key string, value map[string]interface{}) {
kit.Value(value, "client.hostname", uri.Host)
kit.Value(value, "client.url", address)
}) == nil {
dir, file := path.Split(uri.EscapedPath())
m.Rich(SPIDE, nil, kit.Dict(
m.Echo(m.Rich(SPIDE, nil, kit.Dict(
"cookie", kit.Dict(), "header", kit.Dict(), "client", kit.Dict(
// "share", ShareCreate(m.Spawn(), SPIDE, name, address),
"name", name, "url", address, "method", "POST",
"name", name, "url", address, "method", SPIDE_POST,
"protocol", uri.Scheme, "hostname", uri.Host,
"path", dir, "file", file, "query", uri.RawQuery,
"timeout", "600s", "logheaders", false,
),
))
)))
}
m.Log_CREATE(SPIDE, name, "address", address)
m.Log_CREATE(SPIDE, name, ADDRESS, address)
}
}
func _spide_search(m *ice.Message, kind, name, text string, arg ...string) {
m.Richs(SPIDE, nil, kit.Select(kit.MDB_FOREACH, ""), func(key string, value map[string]interface{}) {
if kit.Format(kit.Value(value, "client.name")) != name && (text == "" || !strings.Contains(kit.Format(kit.Value(value, "client.url")), text)) {
return
}
m.Push("pod", m.Option("pod"))
m.Push("ctx", "web")
m.Push("cmd", SPIDE)
m.Push(key, value, []string{kit.MDB_TIME})
m.Push(kit.MDB_SIZE, 0)
m.Push("type", SPIDE)
// m.Push("type", kit.Format(kit.Value(value, "client.protocol")))
m.Push("name", kit.Format(kit.Value(value, "client.name")))
m.Push("text", kit.Format(kit.Value(value, "client.url")))
})
}
func _spide_render(m *ice.Message, kind, name, text string, arg ...string) {
m.Echo(`<iframe src="%s" width=800 height=400></iframe>`, text)
}
const (
SPIDE_SHY = "shy"
SPIDE_DEV = "dev"
SPIDE_SELF = "self"
SPIDE_MSG = "msg"
SPIDE_RAW = "raw"
SPIDE_MSG = "msg"
SPIDE_SAVE = "save"
SPIDE_CACHE = "cache"
@ -120,11 +54,12 @@ const (
SPIDE_POST = "POST"
SPIDE_DELETE = "DELETE"
SPIDE_FILE = "file"
SPIDE_DATA = "data"
SPIDE_PART = "part"
SPIDE_FORM = "form"
SPIDE_PART = "part"
SPIDE_JSON = "json"
SPIDE_DATA = "data"
SPIDE_FILE = "file"
SPIDE_BODY = "body"
SPIDE_CLIENT = "client"
SPIDE_HEADER = "header"
@ -137,42 +72,39 @@ const (
ContentJSON = "application/json"
ContentHTML = "text/html"
)
const (
ADDRESS = "address"
REQUEST = "request"
RESPONSE = "response"
PROTOCOL = "protocol"
)
const SPIDE = "spide"
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
SPIDE: {Name: "spide", Help: "蜘蛛侠", Value: kit.Data(kit.MDB_SHORT, "client.name")},
"spide_rewrite": {Name: "spide_rewrite", Help: "重定向", Value: kit.Data(kit.MDB_SHORT, "from")},
SPIDE: {Name: SPIDE, Help: "蜘蛛侠", Value: kit.Data(kit.MDB_SHORT, "client.name")},
},
Commands: map[string]*ice.Command{
"spide_rewrite": {Name: "spide name=auto [action:select=msg|raw|cache] [method:select=POST|GET] url [format:select=json|form|part|data|file] arg... auto", Help: "蜘蛛侠", Action: map[string]*ice.Action{
mdb.CREATE: {Name: "create from to", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.INSERT, m.Prefix("spide_rewrite"), "", mdb.HASH, arg)
SPIDE: {Name: "spide client.name action=raw,msg,save,cache method=GET,PUT,POST,DELETE url format=form,part,json,data,file arg auto 创建", Help: "蜘蛛侠", Action: map[string]*ice.Action{
mdb.CREATE: {Name: "create name address", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
if arg[0] != "name" {
m.Option("name", arg[0])
m.Option(ADDRESS, arg[1])
}
_spide_create(m, m.Option(kit.MDB_NAME), m.Option(ADDRESS))
}},
mdb.MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.MODIFY, SPIDE, "", mdb.HASH, "client.name", m.Option("client.name"), arg)
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, SPIDE, "", mdb.HASH, "client.name", m.Option("client.name"))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, "time,hash,from,to")
m.Cmdy(mdb.SELECT, m.Prefix("spide_rewrite"), "", mdb.HASH, "from", arg)
}},
SPIDE: {Name: "spide name=auto [action:select=msg|raw|save|cache] [method:select=POST|GET] url [format:select=json|form|part|data|file] arg... auto", Help: "蜘蛛侠", Action: map[string]*ice.Action{
mdb.CREATE: {Name: "create name address", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
_spide_create(m, arg[0], arg[1])
}},
mdb.SEARCH: {Name: "search type name text arg...", Help: "搜索", Hand: func(m *ice.Message, arg ...string) {
_spide_search(m, arg[0], arg[1], arg[2], arg[3:]...)
}},
mdb.RENDER: {Name: "render type name text arg...", Help: "渲染", Hand: func(m *ice.Message, arg ...string) {
_spide_render(m, arg[0], arg[1], arg[2], arg[3:]...)
}},
"login": {Name: "login name", Help: "", Hand: func(m *ice.Message, arg ...string) {
_spide_login(m, arg[0])
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) < 2 || len(arg) > 3 && arg[3] == "" {
_spide_list(m, kit.Select("", arg, 1))
if len(arg) < 2 || arg[0] == "" || (len(arg) > 3 && arg[3] == "") {
m.Option(mdb.FIELDS, kit.Select("time,client.name,client.method,client.url", mdb.DETAIL, len(arg) > 0 && arg[0] != ""))
m.Cmdy(mdb.SELECT, SPIDE, "", mdb.HASH, "client.name", arg)
m.PushAction(mdb.REMOVE)
return
}
@ -181,10 +113,10 @@ func init() {
// 缓存数据
cache, save := "", ""
switch arg[1] {
case SPIDE_MSG:
cache, arg = arg[1], arg[1:]
case SPIDE_RAW:
cache, arg = arg[1], arg[1:]
case SPIDE_MSG:
cache, arg = arg[1], arg[1:]
case SPIDE_SAVE:
cache, save, arg = arg[1], arg[2], arg[2:]
case SPIDE_CACHE:
@ -207,23 +139,17 @@ func init() {
// 请求地址
uri, arg := arg[0], arg[1:]
if strings.HasPrefix(uri, "ftp") {
m.Cmdy(cli.SYSTEM, "wget", uri)
m.Cmdy(cli.SYSTEM, "wget", uri, arg)
return
}
// if n := m.Cmd("spide_rewrite", uri).Append("to"); n != "" && n != uri {
// m.Logs("rewrite", "from", uri, "to", n)
// uri = n
// }
// 渲染引擎
head := map[string]string{}
body, ok := m.Optionv("body").(io.Reader)
body, ok := m.Optionv(SPIDE_BODY).(io.Reader)
if !ok && len(arg) > 0 && method != SPIDE_GET {
switch arg[0] {
case SPIDE_FILE:
if f, e := os.Open(arg[1]); m.Warn(e != nil, "%s", e) {
return
} else {
if f, e := os.Open(arg[1]); m.Assert(e) {
defer f.Close()
body, arg = f, arg[2:]
}
@ -277,7 +203,7 @@ func init() {
head[ContentType] = ContentJSON
body = bytes.NewBuffer(b)
}
m.Log(ice.LOG_EXPORT, "json: %s", kit.Format(data))
m.Log_EXPORT(SPIDE_JSON, kit.Format(data))
}
arg = arg[:0]
} else {
@ -291,13 +217,13 @@ func init() {
m.Assert(e)
// 请求变量
kit.Fetch(value[SPIDE_HEADER], func(key string, value string) {
req.Header.Set(key, value)
})
kit.Fetch(value[SPIDE_COOKIE], func(key string, value string) {
req.AddCookie(&http.Cookie{Name: key, Value: value})
m.Info("%s: %s", key, value)
})
kit.Fetch(value[SPIDE_HEADER], func(key string, value string) {
req.Header.Set(key, value)
})
list := kit.Simple(m.Optionv(SPIDE_HEADER))
for i := 0; i < len(list)-1; i += 2 {
req.Header.Set(list[i], list[i+1])
@ -323,7 +249,8 @@ func init() {
}
// 检查结果
m.Cost("%s %s: %s", res.Status, res.Header.Get(ContentLength), res.Header.Get(ContentType))
defer res.Body.Close()
m.Cost("status", res.Status, "length", res.Header.Get(ContentLength), "type", res.Header.Get(ContentType))
if m.Warn(res.StatusCode != http.StatusOK, res.Status) {
m.Set(ice.MSG_RESULT)
// return
@ -335,14 +262,13 @@ func init() {
m.Log(ice.LOG_IMPORT, "%s: %s", v.Name, v.Value)
}
defer res.Body.Close()
// 解析引擎
switch cache {
case SPIDE_CACHE:
m.Optionv("response", res)
m.Optionv(RESPONSE, res)
m.Cmdy(CACHE, DOWNLOAD, res.Header.Get(ContentType), uri)
m.Echo(m.Append(DATA))
case SPIDE_SAVE:
if f, p, e := kit.Create(save); m.Assert(e) {
if n, e := io.Copy(f, res.Body); m.Assert(e) {
@ -350,10 +276,12 @@ func init() {
m.Echo(p)
}
}
case SPIDE_RAW:
if b, e := ioutil.ReadAll(res.Body); m.Assert(e) {
m.Echo(string(b))
}
case SPIDE_MSG:
var data map[string][]string
m.Assert(json.NewDecoder(res.Body).Decode(&data))
@ -364,6 +292,7 @@ func init() {
}
}
m.Resultv(data[ice.MSG_RESULT])
default:
if strings.HasPrefix(res.Header.Get(ContentType), ContentHTML) {
b, _ := ioutil.ReadAll(res.Body)

View File

@ -168,14 +168,14 @@ func init() {
)},
},
Commands: map[string]*ice.Command{
STORY: {Name: "story story=auto key=auto auto", Help: "故事会", Action: map[string]*ice.Action{
STORY: {Name: "story story auto", Help: "故事会", Action: map[string]*ice.Action{
WRITE: {Name: "write type name text arg...", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
_story_write(m, arg[0], arg[1], arg[2], arg[3:]...)
}},
CATCH: {Name: "catch type name arg...", Help: "捕捉", Hand: func(m *ice.Message, arg ...string) {
_story_catch(m, arg[0], arg[1], arg[2:]...)
}},
WATCH: {Name: "watch key name", Help: "查看", Hand: func(m *ice.Message, arg ...string) {
WATCH: {Name: "watch key name", Help: "释放", Hand: func(m *ice.Message, arg ...string) {
_story_watch(m, arg[0], arg[1])
}},
INDEX: {Name: "index key", Help: "索引", Hand: func(m *ice.Message, arg ...string) {

View File

@ -2,9 +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/ctx"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
@ -12,7 +10,6 @@ import (
"net"
"net/http"
"path"
"strings"
)
type Frame struct {
@ -72,57 +69,41 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool {
}
})
m.Richs(SPIDE, nil, arg[0], func(key string, value map[string]interface{}) {
client := value["client"].(map[string]interface{})
web.m, web.Server = m, &http.Server{Handler: web}
m.Option(tcp.LISTEN_CB, func(l net.Listener) {
m.Cmdy(mdb.INSERT, SERVE, "", mdb.HASH, arg, kit.MDB_STATUS, "start", "proto", m.Option("proto"), "dev", m.Option("dev"))
m.Event(SERVE_START, arg...)
defer m.Event(SERVE_CLOSE, arg...)
defer m.Cmd(mdb.MODIFY, SERVE, "", mdb.HASH, kit.MDB_NAME, m.Option(kit.MDB_NAME), kit.MDB_STATUS, "stop")
web.m, web.Server = m, &http.Server{Handler: web}
m.Option(tcp.LISTEN_CB, func(l net.Listener) {
m.Event(SERVE_START, arg[0])
m.Warn(true, "listen %s", web.Server.Serve(l))
m.Event(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])
m.Warn(true, SERVE, ": ", web.Server.Serve(l))
})
m.Cmd(tcp.SERVER, tcp.LISTEN, kit.MDB_TYPE, WEB, kit.MDB_NAME, m.Option(kit.MDB_NAME),
tcp.HOST, m.Option(tcp.HOST), tcp.PORT, m.Option(tcp.PORT))
return true
}
func (web *Frame) Close(m *ice.Message, arg ...string) bool {
return true
}
var Index = &ice.Context{Name: "web", Help: "网络模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
const WEB = "web"
var Index = &ice.Context{Name: WEB, 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(SPIDE, mdb.CREATE, "dev", kit.Select("http://:9020", m.Conf(cli.RUNTIME, "conf.ctx_dev")))
m.Cmd(SPIDE, mdb.CREATE, "self", kit.Select("http://:9020", m.Conf(cli.RUNTIME, "conf.ctx_self")))
m.Cmd(SPIDE, mdb.CREATE, "shy", kit.Select("https://shylinux.com:443", m.Conf(cli.RUNTIME, "conf.ctx_shy")))
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, SPIDE)
m.Cmd(mdb.RENDER, mdb.CREATE, SPIDE)
m.Cmd(mdb.SEARCH, mdb.CREATE, SPACE)
m.Search("_render", func(p *ice.Context, s *ice.Context, key string, cmd *ice.Command) {
for k := range cmd.Action {
m.Cmd(mdb.RENDER, mdb.CREATE, k, "_render", "web")
}
})
m.Cmd(SPIDE, mdb.CREATE, SPIDE_DEV, kit.Select("http://:9020", m.Conf(cli.RUNTIME, "conf.ctx_dev")))
m.Cmd(SPIDE, mdb.CREATE, SPIDE_SELF, kit.Select("http://:9020", m.Conf(cli.RUNTIME, "conf.ctx_self")))
m.Cmd(SPIDE, mdb.CREATE, SPIDE_SHY, kit.Select("https://shylinux.com:443", m.Conf(cli.RUNTIME, "conf.ctx_shy")))
}},
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Save(SPIDE, SERVE, CACHE, SHARE, STORY)
m.Save()
m.Done()
m.Richs(SPACE, nil, "*", func(key string, value map[string]interface{}) {
if kit.Format(value["type"]) == "master" {
m.Done()
}
m.Done(true)
m.Cmd(SERVE).Table(func(index int, value map[string]string, head []string) {
m.Done(value[kit.MDB_STATUS] == "start")
})
}},
},
@ -130,6 +111,6 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
func init() {
ice.Index.Register(Index, &Frame{},
SPIDE, SERVE, SPACE, DREAM, CACHE, SHARE, STORY,
SPIDE, SERVE, SPACE, DREAM, ROUTE, SHARE, CACHE, STORY,
)
}

13
base/web/web.shy Normal file
View File

@ -0,0 +1,13 @@
chapter "web"
field "蜘蛛侠" web.spide
field "服务器" web.serve
field "空间站" web.space
field "梦想家" web.dream
field "路由器" web.route
field "缓存池" web.cache
return
field "共享链" web.share
field "故事会" web.story

View File

@ -4,9 +4,9 @@ import (
"github.com/shylinux/icebergs"
)
var Index = &ice.Context{Name: "yac", Help: "语法模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
const YAC = "yac"
var Index = &ice.Context{Name: YAC, Help: "语法模块",
Commands: map[string]*ice.Command{
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Echo("hello %s world", c.Name)

View File

@ -2,6 +2,7 @@ package chat
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/web"
kit "github.com/shylinux/toolkits"
)
@ -12,6 +13,8 @@ var Index = &ice.Context{Name: CHAT, 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(web.SERVE, aaa.WHITE, "header", "river", "action", "footer")
m.Conf(RIVER, "meta.template", kit.Dict(
"base", kit.Dict(
"info", []interface{}{
@ -40,7 +43,7 @@ var Index = &ice.Context{Name: CHAT, Help: "聊天中心",
),
))
m.Watch(web.SPACE_START, m.Prefix(NODE))
m.Watch(web.SPACE_CLOSE, m.Prefix(NODE))
m.Watch(web.SPACE_STOP, m.Prefix(NODE))
}},
ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Save() }},
},

View File

@ -3,7 +3,6 @@ package chat
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/web"
kit "github.com/shylinux/toolkits"
"math"
@ -59,9 +58,9 @@ func init() {
}},
mdb.RENDER: {Name: "render type name text", Help: "渲染", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.RENDER, web.RENDER.Frame, kit.Format(
"https://map.baidu.com/search/%s/@12958750.085,4825785.55,16z?querytype=s&da_src=shareurl&wd=%s",
arg[2], arg[2]))
// m.Cmdy(mdb.RENDER, web.RENDER.Frame, kit.Format(
// "https://map.baidu.com/search/%s/@12958750.085,4825785.55,16z?querytype=s&da_src=shareurl&wd=%s",
// arg[2], arg[2]))
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Option(mdb.FIELDS, "time,type,name,text,longitude,latitude")

View File

@ -3,10 +3,7 @@ package chat
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/web"
kit "github.com/shylinux/toolkits"
"path"
)
const MEET = "meet"
@ -93,7 +90,7 @@ func init() {
m.Push("照片", "")
continue
}
m.Push("照片", m.Cmdx(mdb.RENDER, web.RENDER.IMG, path.Join("/share/local/usr/image/local/", m.Option(ice.MSG_DOMAIN), value["照片"])))
// m.Push("照片", m.Cmdx(mdb.RENDER, web.RENDER.IMG, path.Join("/share/local/usr/image/local/", m.Option(ice.MSG_DOMAIN), value["照片"])))
} else {
m.Push(k, value[k])
}
@ -107,7 +104,7 @@ func init() {
} else {
msg.Table(func(index int, value map[string]string, head []string) {
if value["key"] == "照片" {
value["value"] = m.Cmdx(mdb.RENDER, web.RENDER.IMG, path.Join("/share/local/usr/image/local/", m.Option(ice.MSG_DOMAIN), value["value"]), "640")
// value["value"] = m.Cmdx(mdb.RENDER, web.RENDER.IMG, path.Join("/share/local/usr/image/local/", m.Option(ice.MSG_DOMAIN), value["value"]), "640")
}
m.Push("key", value["key"])
m.Push("value", value["value"])

View File

@ -109,8 +109,6 @@ func init() {
m.Cmdy(mdb.INSERT, RIVER, kit.Keys(kit.MDB_HASH, m.Option(RIVER), NODE), mdb.HASH, arg)
}
}},
web.SPACE_CLOSE: {Name: "close", Help: "关闭", Hand: func(m *ice.Message, arg ...string) {
}},
mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.DELETE, RIVER, kit.Keys(kit.MDB_HASH, m.Option(RIVER), NODE), mdb.HASH,
kit.MDB_NAME, m.Option(kit.MDB_NAME))

View File

@ -3,7 +3,6 @@ package code
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/web"
kit "github.com/shylinux/toolkits"
"github.com/shylinux/toolkits/util/bench"
@ -21,7 +20,7 @@ func _bench_list(m *ice.Message, zone string, id string, field ...interface{}) {
if zone = kit.Format(kit.Value(val, kit.MDB_ZONE)); id == "" {
m.Grows(BENCH, kit.Keys(kit.MDB_HASH, key), "", "", func(index int, value map[string]interface{}) {
// 查看信息
m.Push("操作", m.Cmdx(mdb.RENDER, web.RENDER.Button, "运行"))
// m.Push("操作", m.Cmdx(mdb.RENDER, web.RENDER.Button, "运行"))
m.Push(zone, value, []string{
kit.MDB_ZONE, kit.MDB_ID, kit.MDB_TYPE,
kit.MDB_NAME, NCONN, NREQS, kit.MDB_TEXT,
@ -33,7 +32,7 @@ func _bench_list(m *ice.Message, zone string, id string, field ...interface{}) {
// 查看信息
m.Push("detail", value)
m.Push(kit.MDB_KEY, "操作")
m.Push(kit.MDB_VALUE, m.Cmdx(mdb.RENDER, web.RENDER.Button, "运行"))
// m.Push(kit.MDB_VALUE, m.Cmdx(mdb.RENDER, web.RENDER.Button, "运行"))
})
})
}

View File

@ -68,22 +68,48 @@ func init() {
})
}},
"build": {Name: "build link", Help: "构建", Hand: func(m *ice.Message, arg ...string) {
p := m.Option(cli.CMD_DIR, path.Join(m.Conf(INSTALL, kit.META_PATH), kit.TrimExt(arg[0])))
switch cb := m.Optionv("prepare").(type) {
case func(string):
cb(p)
default:
if m.Cmdy(cli.SYSTEM, "./configure", "--prefix="+kit.Path(path.Join(p, kit.Select("_install", m.Option("install")))), arg[1:]); m.Append(cli.CMD_CODE) != "0" {
m.Option("cache.button", "构建")
m.Option("_process", "_follow")
if m.Option("cache.hash") != "" {
m.Cmdy(cli.OUTPUT, m.Option("cache.hash"))
m.Sort(kit.MDB_ID)
m.Table(func(index int, value map[string]string, head []string) {
m.Option("cache.begin", value[kit.MDB_ID])
m.Echo(value[kit.SSH_RES])
})
if len(m.Resultv()) > 0 {
return
}
}
if m.Cmdy(cli.SYSTEM, "make", "-j8"); m.Append(cli.CMD_CODE) != "0" {
if m.Conf(cli.OUTPUT, kit.Keys(kit.MDB_HASH, m.Option("cache.hash"), kit.MDB_META, kit.MDB_STATUS)) == "stop" {
m.Echo("stop")
}
return
}
m.Cmdy(cli.OUTPUT, mdb.CREATE, kit.MDB_NAME, arg[0])
m.Option("cache.hash", m.Result())
m.Option("cache.begin", 1)
m.Cmdy(cli.SYSTEM, "mv", "INSTALL", "INSTALLS")
m.Cmdy(cli.SYSTEM, "make", "PREFIX="+kit.Path(path.Join(p, kit.Select("_install", m.Option("install")))), "install")
m.Go(func() {
defer m.Cmdy(cli.OUTPUT, mdb.MODIFY, kit.MDB_STATUS, cli.Status.Stop)
defer m.Option(kit.MDB_HASH, m.Option("cache.hash"))
p := m.Option(cli.CMD_DIR, path.Join(m.Conf(INSTALL, kit.META_PATH), kit.TrimExt(arg[0])))
switch cb := m.Optionv("prepare").(type) {
case func(string):
cb(p)
default:
if m.Cmdy(cli.SYSTEM, "./configure", "--prefix="+kit.Path(path.Join(p, kit.Select("_install", m.Option("install")))), arg[1:]); m.Append(cli.CMD_CODE) != "0" {
return
}
}
if m.Cmdy(cli.SYSTEM, "make", "-j8"); m.Append(cli.CMD_CODE) != "0" {
return
}
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, aaa.Right)
@ -116,6 +142,17 @@ func init() {
return
}
if len(arg) == 1 {
// 服务列表
m.Option(mdb.FIELDS, "time,port,status,pid,cmd,dir")
m.Cmdy(mdb.SELECT, cli.DAEMON, "", mdb.HASH)
m.Appendv("port", []string{})
m.Table(func(index int, value map[string]string, head []string) {
m.Push(kit.SSH_PORT, path.Base(value[kit.SSH_DIR]))
})
return
}
arg[0] = path.Base(arg[0])
if key := strings.Split(strings.Split(arg[0], "-")[0], ".")[0]; len(arg) == 1 {
u := kit.ParseURL(m.Option(ice.MSG_USERWEB))

View File

@ -5,7 +5,6 @@ import (
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs"
"github.com/shylinux/icebergs/base/web"
kit "github.com/shylinux/toolkits"
"bufio"
@ -127,7 +126,7 @@ func init() {
if len(arg) == 0 {
m.Cmdy(nfs.DIR, WEBPACK).Table(func(index int, value map[string]string, head []string) {
m.Push(kit.MDB_LINK, m.Cmdx(mdb.RENDER, web.RENDER.Download, "/publish/"+value[kit.MDB_PATH]))
// m.Push(kit.MDB_LINK, m.Cmdx(mdb.RENDER, web.RENDER.Download, "/publish/"+value[kit.MDB_PATH]))
})
return
}
@ -168,7 +167,7 @@ func init() {
m.Option(nfs.DIR_DEEP, true)
m.Cmdy(nfs.DIR, BINPACK).Table(func(index int, value map[string]string, head []string) {
m.Push(kit.MDB_LINK, m.Cmdx(mdb.RENDER, web.RENDER.Download, "/publish/"+value[kit.MDB_PATH]))
// m.Push(kit.MDB_LINK, m.Cmdx(mdb.RENDER, web.RENDER.Download, "/publish/"+value[kit.MDB_PATH]))
})
}},
MODPACK: {Name: "modpack path=auto auto 创建", Help: "打包", Meta: kit.Dict(

View File

@ -3,7 +3,6 @@ package code
import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/web"
kit "github.com/shylinux/toolkits"
"net/http"
@ -17,7 +16,7 @@ func _pprof_list(m *ice.Message, zone string, id string, field ...interface{}) {
if zone = kit.Format(kit.Value(val, kit.MDB_ZONE)); id == "" {
m.Grows(PPROF, kit.Keys(kit.MDB_HASH, key), "", "", func(index int, value map[string]interface{}) {
// 列表信息
m.Push("操作", m.Cmdx(mdb.RENDER, web.RENDER.Button, "运行"))
// m.Push("操作", m.Cmdx(mdb.RENDER, web.RENDER.Button, "运行"))
m.Push(zone, value, []string{
kit.MDB_ZONE, kit.MDB_ID, kit.MDB_TYPE,
kit.MDB_NAME, kit.MDB_TEXT, SECONDS, BINNARY, SERVICE,
@ -28,7 +27,7 @@ func _pprof_list(m *ice.Message, zone string, id string, field ...interface{}) {
// 详细信息
m.Push("detail", value)
m.Push(kit.MDB_KEY, "操作")
m.Push(kit.MDB_VALUE, m.Cmdx(mdb.RENDER, web.RENDER.Button, "运行"))
// m.Push(kit.MDB_VALUE, m.Cmdx(mdb.RENDER, web.RENDER.Button, "运行"))
})
}
})

View File

@ -4,7 +4,6 @@ import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/icebergs/base/ctx"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/nfs"
"github.com/shylinux/icebergs/base/ssh"
"github.com/shylinux/icebergs/base/web"
@ -284,11 +283,12 @@ func _video_show(m *ice.Message, name, text string, arg ...string) {
}
func _baidu_show(m *ice.Message, name, text string, arg ...string) {
_option(m, BAIDU, name, text, arg...)
m.Cmdy(mdb.RENDER, web.RENDER.Frame, kit.Format("https://baidu.com/s?wd=%s", text))
// m.Cmdy(mdb.RENDER, web.RENDER.Frame, kit.Format("https://baidu.com/s?wd=%s", text))
}
func _other_show(m *ice.Message, name, text string, arg ...string) {
_option(m, OTHER, name, text, arg...)
m.Cmdy(mdb.RENDER, web.RENDER.Frame, text)
// m.Cmdy(mdb.RENDER, web.RENDER.Frame, text)
}
func _word_show(m *ice.Message, name string, arg ...string) {
@ -383,7 +383,7 @@ func init() {
Commands: map[string]*ice.Command{
TITLE: {Name: "title [premenu|chapter|section|endmenu] text", Help: "标题", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
ns := strings.Split(cli.NodeName, "-")
ns := strings.Split(ice.Info.NodeName, "-")
arg = append(arg, kit.Select(ns[len(ns)-1], ""))
}

View File

@ -66,7 +66,10 @@ func (m *Message) Hold(n int) *Message {
m.Log(LOG_TRACE, "%s wait %s %v", ctx.Name, m.target.Name, ctx.wg)
return m
}
func (m *Message) Done() bool {
func (m *Message) Done(b bool) bool {
if !b {
return false
}
defer func() { recover() }()
ctx := m.target.root
@ -127,7 +130,7 @@ func (m *Message) Gos(msg *Message, cb interface{}, args ...interface{}) *Messag
msg.Cmdx("gdb.routine", "modify", "status", "stop")
return nil
})
return m
return msg
}
func (m *Message) Go(cb interface{}, args ...interface{}) *Message {
switch cb := cb.(type) {

1
go.sum
View File

@ -4,6 +4,7 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/maruel/rs v0.0.0-20150922171536-2c81c4312fe4/go.mod h1:kcRFpEzolcEklV6rD7W95mG49/sbdX/PlFmd7ni3RvA=
github.com/nareix/joy4 v0.0.0-20200507095837-05a4ffbb5369 h1:Yp0zFEufLz0H7jzffb4UPXijavlyqlYeOg7dcyVUNnQ=
github.com/nareix/joy4 v0.0.0-20200507095837-05a4ffbb5369/go.mod h1:aFJ1ZwLjvHN4yEzE5Bkz8rD8/d8Vlj3UIuvz2yfET7I=
github.com/shylinux/toolkits v0.1.8 h1:Lh5HkR1aRzhOOVu9eHwZ5y7dfW7hcFy29IR5tQ5qUeM=
github.com/shylinux/toolkits v0.1.8/go.mod h1:Y68Ot6xOmo1bun67YvqC3chDGeU2gDxtsUnvVDGJm4g=

16
init.go
View File

@ -9,6 +9,22 @@ import (
"time"
)
var Info = struct {
HostName string
PathName string
UserName string
PassWord string
NodeName string
NodeType string
Build struct {
Time string
Version string
HostName string
UserName string
}
}{}
type Frame struct{ code int }
func (f *Frame) Spawn(m *Message, c *Context, arg ...string) Server {

12
logs.go
View File

@ -81,8 +81,16 @@ func (m *Message) Log(level string, str string, arg ...interface{}) *Message {
func (m *Message) Info(str string, arg ...interface{}) *Message {
return m.log(LOG_INFO, str, arg...)
}
func (m *Message) Cost(str string, arg ...interface{}) *Message {
return m.log(LOG_COST, "%s: %s", m.Format("cost"), kit.Format(str, arg...))
func (m *Message) Cost(arg ...interface{}) *Message {
list := []string{m.Format("cost")}
for i := 0; i < len(arg); i += 2 {
if i == len(arg)-1 {
list = append(list, kit.Format(arg[i]))
} else {
list = append(list, kit.Format(arg[i])+":", kit.Format(arg[i+1]))
}
}
return m.log(LOG_COST, strings.Join(list, " "))
}
func (m *Message) Warn(err bool, arg ...interface{}) bool {
if err {

33
meta.go
View File

@ -63,19 +63,14 @@ func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Messa
for _, k := range head {
m.Push(k, value[k])
}
return m
case map[string]interface{}:
if key == "detail" {
// 格式转换
value = kit.KeyValue(map[string]interface{}{}, "", value)
}
case map[string]interface{}:
// 键值排序
list := []string{}
if len(arg) > 0 {
list = kit.Simple(arg[0])
} else {
for k := range value {
for k := range kit.KeyValue(map[string]interface{}{}, "", value) {
list = append(list, k)
}
sort.Strings(list)
@ -90,13 +85,6 @@ func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Messa
// 查找数据
var v interface{}
switch k {
case "action":
list := []string{}
for _, k := range kit.Simple(m.Optionv(MSG_ACTION)) {
list = append(list, fmt.Sprintf(`<input type="button" value="%s">`, k))
}
v = strings.Join(list, "")
case kit.MDB_KEY, kit.MDB_HASH:
if key != "" {
v = key
@ -104,12 +92,12 @@ func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Messa
}
fallthrough
default:
if v = value[k]; v == nil {
v = value["extra."+k]
if v = kit.Value(value, k); v == nil {
v = kit.Value(value, kit.Keys(kit.MDB_EXTRA, k))
}
if v == nil {
if v = val[k]; v == nil {
v = val["extra."+k]
if v = kit.Value(val, k); v == nil {
v = kit.Value(val, kit.Keys(kit.MDB_EXTRA, k))
}
}
}
@ -123,12 +111,13 @@ func (m *Message) Push(key string, value interface{}, arg ...interface{}) *Messa
m.Add(MSG_APPEND, k, v)
}
}
return m
default:
for _, v := range kit.Simple(value) {
m.Add(MSG_APPEND, key, v)
}
}
for _, v := range kit.Simple(value) {
m.Add(MSG_APPEND, key, v)
}
return m
}
func (m *Message) Echo(str string, arg ...interface{}) *Message {

View File

@ -109,8 +109,5 @@ func (m *Message) PushPlugin(key string, arg ...string) *Message {
m.Cmdy("command", key)
return m
}
func (m *Message) PushDetail(value interface{}, arg ...interface{}) *Message {
return m.Push("detail", value, arg...)
}
var BinPack = map[string][]byte{}

View File

@ -37,21 +37,21 @@ func init() {
},
Commands: map[string]*ice.Command{
REPOS: {Name: "repos name=auto path=auto auto 添加", Help: "代码库", Action: map[string]*ice.Action{
mdb.CREATE: {Name: `create remote branch name path`, Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Option("name", kit.Select(strings.TrimSuffix(path.Base(m.Option("remote")), ".git"), m.Option("name")))
mdb.CREATE: {Name: `create repos branch name path`, Help: "添加", Hand: func(m *ice.Message, arg ...string) {
m.Option("name", kit.Select(strings.TrimSuffix(path.Base(m.Option("repos")), ".git"), m.Option("name")))
m.Option("path", kit.Select(path.Join("usr", m.Option("name")), m.Option("path")))
m.Option("remote", kit.Select(m.Conf(REPOS, "meta.owner")+"/"+m.Option("name"), m.Option("remote")))
m.Option("repos", kit.Select(m.Conf(REPOS, "meta.owner")+"/"+m.Option("name"), m.Option("repos")))
if _, e := os.Stat(path.Join(m.Option("path"), ".git")); e != nil && os.IsNotExist(e) {
// 下载仓库
if _, e := os.Stat(m.Option("path")); e == nil {
m.Option(cli.CMD_DIR, m.Option("path"))
m.Cmd(cli.SYSTEM, GIT, "init")
m.Cmd(cli.SYSTEM, GIT, "remote", "add", "origin", m.Option("remote"))
m.Cmd(cli.SYSTEM, GIT, "remote", "add", "origin", m.Option("repos"))
m.Cmd(cli.SYSTEM, GIT, "pull", "origin", "master")
} else {
m.Cmd(cli.SYSTEM, GIT, "clone", "-b", kit.Select("master", m.Option("branch")),
m.Option("remote"), m.Option("path"))
m.Option("repos"), m.Option("path"))
}
_repos_insert(m, m.Option("name"), m.Option("path"))

View File

@ -150,7 +150,7 @@ var Index = &ice.Context{Name: "lark", Help: "机器人",
kit.Fetch(kit.Value(data, "data.user_list"), func(index int, value map[string]interface{}) {
msg := m.Cmd(m.Prefix(USER), value[OPEN_ID])
m.Push("avatar", m.Cmdx(mdb.RENDER, web.RENDER.IMG, msg.Append("avatar_72")))
// m.Push("avatar", m.Cmdx(mdb.RENDER, web.RENDER.IMG, msg.Append("avatar_72")))
m.Push("gender", kit.Select("男", "女", msg.Append("gender") == "2"))
m.Push(kit.MDB_NAME, msg.Append(kit.MDB_NAME))
m.Push("description", msg.Append("description"))
@ -207,7 +207,7 @@ var Index = &ice.Context{Name: "lark", Help: "机器人",
kit.Fetch(kit.Value(data, "data.members"), func(index int, value map[string]interface{}) {
msg := m.Cmd(m.Prefix(USER), value[OPEN_ID])
m.Push("avatar", m.Cmdx(mdb.RENDER, web.RENDER.IMG, msg.Append("avatar_72")))
// m.Push("avatar", m.Cmdx(mdb.RENDER, web.RENDER.IMG, msg.Append("avatar_72")))
m.Push("gender", kit.Select("男", "女", msg.Append("gender") == "2"))
m.Push(kit.MDB_NAME, msg.Append(kit.MDB_NAME))
m.Push("description", msg.Append("description"))
@ -223,7 +223,7 @@ var Index = &ice.Context{Name: "lark", Help: "机器人",
data := raw(m, "/open-apis/chat/v4/list")
kit.Fetch(kit.Value(data, "data.groups"), func(index int, value map[string]interface{}) {
m.Push(CHAT_ID, value[CHAT_ID])
m.Push("avatar", m.Cmdx(mdb.RENDER, web.RENDER.IMG, value["avatar"]))
// m.Push("avatar", m.Cmdx(mdb.RENDER, web.RENDER.IMG, value["avatar"]))
m.Push(kit.MDB_NAME, value[kit.MDB_NAME])
m.Push("description", value["description"])
m.Push(OPEN_ID, value["owner_open_id"])

View File

@ -4,6 +4,7 @@ import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/tcp"
"github.com/shylinux/icebergs/base/web"
kit "github.com/shylinux/toolkits"
@ -59,7 +60,7 @@ func init() {
m.Option(mdb.FIELDS, m.Conf(m.Prefix(SESS), kit.META_FIELD))
if strings.TrimSpace(m.Option(SID)) == "" {
m.Option(SID, m.Cmdx(mdb.INSERT, m.Prefix(SESS), "", mdb.HASH, kit.MDB_STATUS, "login",
aaa.USERNAME, m.Option(aaa.USERNAME), aaa.HOSTNAME, m.Option(aaa.HOSTNAME), PID, m.Option(PID), PWD, m.Option(PWD)))
aaa.USERNAME, m.Option(aaa.USERNAME), tcp.HOSTNAME, m.Option(tcp.HOSTNAME), PID, m.Option(PID), PWD, m.Option(PWD)))
} else {
m.Cmdy(mdb.MODIFY, m.Prefix(SESS), "", mdb.HASH, kit.MDB_HASH, m.Option(SID), kit.MDB_STATUS, "login")
}
@ -79,7 +80,7 @@ func init() {
msg := m.Cmd(mdb.SELECT, m.Prefix(SESS), "", mdb.HASH, kit.MDB_HASH, strings.TrimSpace(m.Option(SID)))
if m.Option(SID, msg.Append(kit.MDB_HASH)) != "" {
m.Option(aaa.USERNAME, msg.Append(aaa.USERNAME))
m.Option(aaa.HOSTNAME, msg.Append(aaa.HOSTNAME))
m.Option(tcp.HOSTNAME, msg.Append(tcp.HOSTNAME))
}
}
m.Render(ice.RENDER_RESULT)

View File

@ -13,14 +13,14 @@ func init() {
"/download": {Name: "/download", Help: "下载", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 || arg[0] == "" {
// 文件列表
m.Cmdy(web.PROXY, m.Option("you"), web.STORY).Table()
m.Cmdy(web.SPACE, m.Option("you"), web.STORY).Table()
return
}
// 查找文件
if m.Cmdy(web.STORY, "index", arg[0]).Append("text") == "" && m.Option("you") != "" {
// 上发文件
m.Cmd(web.PROXY, m.Option("you"), web.STORY, "push", arg[0], "dev", arg[0])
m.Cmd(web.SPACE, m.Option("you"), web.STORY, "push", arg[0], "dev", arg[0])
m.Cmdy(web.STORY, "index", arg[0])
}

View File

@ -4,6 +4,7 @@ import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/tcp"
"github.com/shylinux/icebergs/base/web"
kit "github.com/shylinux/toolkits"
@ -44,7 +45,7 @@ func init() {
m.Option(mdb.FIELDS, m.Conf(m.Prefix(SESS), kit.META_FIELD))
if strings.TrimSpace(m.Option(SID)) == "" {
m.Option(SID, m.Cmdx(mdb.INSERT, m.Prefix(SESS), "", mdb.HASH, kit.MDB_STATUS, "login",
aaa.USERNAME, m.Option(aaa.USERNAME), aaa.HOSTNAME, m.Option(aaa.HOSTNAME), PID, m.Option(PID), PWD, m.Option(PWD)))
aaa.USERNAME, m.Option(aaa.USERNAME), tcp.HOSTNAME, m.Option(tcp.HOSTNAME), PID, m.Option(PID), PWD, m.Option(PWD)))
} else {
m.Cmdy(mdb.MODIFY, m.Prefix(SESS), "", mdb.HASH, kit.MDB_HASH, m.Option(SID), kit.MDB_STATUS, "login")
}
@ -64,7 +65,7 @@ func init() {
msg := m.Cmd(mdb.SELECT, m.Prefix(SESS), "", mdb.HASH, kit.MDB_HASH, strings.TrimSpace(m.Option(SID)))
if m.Option(SID, msg.Append(kit.MDB_HASH)) != "" {
m.Option(aaa.USERNAME, msg.Append(aaa.USERNAME))
m.Option(aaa.HOSTNAME, msg.Append(aaa.HOSTNAME))
m.Option(tcp.HOSTNAME, msg.Append(tcp.HOSTNAME))
}
}
m.Render(ice.RENDER_RESULT)

View File

@ -4,6 +4,7 @@ import (
ice "github.com/shylinux/icebergs"
"github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/icebergs/base/mdb"
"github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
"strings"
@ -57,7 +58,7 @@ func init() {
ls := strings.SplitN(strings.TrimSpace(m.Option(ARG)), " ", 4)
if text := strings.TrimSpace(strings.Join(ls[3:], " ")); text != "" {
m.Cmd(mdb.INSERT, m.Prefix(SYNC), "", mdb.LIST, kit.MDB_TYPE, SHELL, kit.MDB_NAME, ls[0],
aaa.HOSTNAME, m.Option(aaa.HOSTNAME), aaa.USERNAME, m.Option(aaa.USERNAME),
tcp.HOSTNAME, m.Option(tcp.HOSTNAME), aaa.USERNAME, m.Option(aaa.USERNAME),
kit.MDB_TEXT, text, PWD, m.Option(PWD), kit.MDB_TIME, ls[1]+" "+ls[2])
}

View File

@ -303,7 +303,7 @@ func (c *Context) Start(m *Message, arg ...string) bool {
if wait <- true; c.server != nil {
c.server.Start(m, arg...)
}
if m.Done(); m.wait != nil {
if m.Done(true); m.wait != nil {
m.wait <- true
}
}, p)
@ -565,6 +565,8 @@ func (m *Message) Search(key interface{}, cb interface{}) *Message {
p := m.target.root
if ctx, ok := names[key].(*Context); ok {
p = ctx
} else if key == "ice." {
p, key = m.target.root, ""
} else if key == "." {
p, key = m.target, ""
} else if key == ".." {
@ -625,7 +627,7 @@ func (m *Message) Search(key interface{}, cb interface{}) *Message {
}
}
case func(p *Context, s *Context, key string, conf *Config):
for _, p := range []*Context{p, m.target, m.source} {
for _, p := range []*Context{m.target, p, m.source} {
for s := p; s != nil; s = s.context {
if cmd, ok := s.Configs[key]; ok {
cb(s.context, s, key, cmd)